- return true;
-}
-
-/* Set up the sizes and contents of the dynamic sections created in
- sunos_add_dynamic_symbols. This is called by the SunOS linker
- emulation before_allocation routine. We must set the sizes of the
- sections before the linker sets the addresses of the various
- sections. This unfortunately requires reading all the relocs so
- that we can work out which ones need to become dynamic relocs. If
- info->keep_memory is true, we keep the relocs in memory; otherwise,
- we discard them, and will read them again later. */
-
-boolean
-bfd_sunos_size_dynamic_sections (output_bfd, info, sdynptr, sneedptr,
- srulesptr)
- bfd *output_bfd;
- struct bfd_link_info *info;
- asection **sdynptr;
- asection **sneedptr;
- asection **srulesptr;
-{
- bfd *dynobj;
- bfd_size_type dynsymcount;
- struct sunos_link_hash_entry *h;
- asection *s;
- size_t bucketcount;
- bfd_size_type hashalloc;
- size_t i;
- bfd *sub;
-
- *sdynptr = NULL;
- *sneedptr = NULL;
- *srulesptr = NULL;
-
- if (info->relocateable)
- return true;
-
- if (output_bfd->xvec != &MY(vec))
- return true;
-
- /* Look through all the input BFD's and read their relocs. It would
- be better if we didn't have to do this, but there is no other way
- to determine the number of dynamic relocs we need, and, more
- importantly, there is no other way to know which symbols should
- get an entry in the procedure linkage table. */
- for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
- {
- if ((sub->flags & DYNAMIC) == 0
- && sub->xvec == output_bfd->xvec)
- {
- if (! sunos_scan_relocs (info, sub, obj_textsec (sub),
- exec_hdr (sub)->a_trsize)
- || ! sunos_scan_relocs (info, sub, obj_datasec (sub),
- exec_hdr (sub)->a_drsize))
- return false;
- }
- }
-
- dynobj = sunos_hash_table (info)->dynobj;
- dynsymcount = sunos_hash_table (info)->dynsymcount;
-
- /* If there were no dynamic objects in the link, and we don't need
- to build a global offset table, there is nothing to do here. */
- if (! sunos_hash_table (info)->dynamic_sections_needed
- && ! sunos_hash_table (info)->got_needed)
- return true;
-
- /* If __GLOBAL_OFFSET_TABLE_ was mentioned, define it. */
- h = sunos_link_hash_lookup (sunos_hash_table (info),
- "__GLOBAL_OFFSET_TABLE_", false, false, false);
- if (h != NULL && (h->flags & SUNOS_REF_REGULAR) != 0)
- {
- h->flags |= SUNOS_DEF_REGULAR;
- if (h->dynindx == -1)
- {
- ++sunos_hash_table (info)->dynsymcount;
- h->dynindx = -2;
- }
- h->root.root.type = bfd_link_hash_defined;
- h->root.root.u.def.section = bfd_get_section_by_name (dynobj, ".got");
-
- /* If the .got section is more than 0x1000 bytes, we set
- __GLOBAL_OFFSET_TABLE_ to be 0x1000 bytes into the section,
- so that 13 bit relocations have a greater chance of working. */
- s = bfd_get_section_by_name (dynobj, ".got");
- BFD_ASSERT (s != NULL);
- if (s->_raw_size >= 0x1000)
- h->root.root.u.def.value = 0x1000;
- else
- h->root.root.u.def.value = 0;
-
- sunos_hash_table (info)->got_base = h->root.root.u.def.value;
- }
-
- /* If there are any shared objects in the link, then we need to set
- up the dynamic linking information. */
- if (sunos_hash_table (info)->dynamic_sections_needed)
- {
- *sdynptr = bfd_get_section_by_name (dynobj, ".dynamic");
-
- /* The .dynamic section is always the same size. */
- s = *sdynptr;
- BFD_ASSERT (s != NULL);
- s->_raw_size = (sizeof (struct external_sun4_dynamic)
- + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE
- + sizeof (struct external_sun4_dynamic_link));
-
- /* Set the size of the .dynsym and .hash sections. We counted
- the number of dynamic symbols as we read the input files. We
- will build the dynamic symbol table (.dynsym) and the hash
- table (.hash) when we build the final symbol table, because
- until then we do not know the correct value to give the
- symbols. We build the dynamic symbol string table (.dynstr)
- in a traversal of the symbol table using
- sunos_scan_dynamic_symbol. */
- s = bfd_get_section_by_name (dynobj, ".dynsym");
- BFD_ASSERT (s != NULL);
- s->_raw_size = dynsymcount * sizeof (struct external_nlist);
- s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
- if (s->contents == NULL && s->_raw_size != 0)
- return false;
-
- /* The number of buckets is just the number of symbols divided
- by four. To compute the final size of the hash table, we
- must actually compute the hash table. Normally we need
- exactly as many entries in the hash table as there are
- dynamic symbols, but if some of the buckets are not used we
- will need additional entries. In the worst case, every
- symbol will hash to the same bucket, and we will need
- BUCKETCOUNT - 1 extra entries. */
- if (dynsymcount >= 4)
- bucketcount = dynsymcount / 4;
- else if (dynsymcount > 0)
- bucketcount = dynsymcount;
- else
- bucketcount = 1;
- s = bfd_get_section_by_name (dynobj, ".hash");
- BFD_ASSERT (s != NULL);
- hashalloc = (dynsymcount + bucketcount - 1) * HASH_ENTRY_SIZE;
- s->contents = (bfd_byte *) bfd_zalloc (dynobj, hashalloc);
- if (s->contents == NULL && dynsymcount > 0)
- return false;
- for (i = 0; i < bucketcount; i++)
- PUT_WORD (output_bfd, (bfd_vma) -1, s->contents + i * HASH_ENTRY_SIZE);
- s->_raw_size = bucketcount * HASH_ENTRY_SIZE;
-
- sunos_hash_table (info)->bucketcount = bucketcount;
-
- /* Scan all the symbols, place them in the dynamic symbol table,
- and build the dynamic hash table. We reuse dynsymcount as a
- counter for the number of symbols we have added so far. */
- sunos_hash_table (info)->dynsymcount = 0;
- sunos_link_hash_traverse (sunos_hash_table (info),
- sunos_scan_dynamic_symbol,
- (PTR) info);
- BFD_ASSERT (sunos_hash_table (info)->dynsymcount == dynsymcount);
-
- /* The SunOS native linker seems to align the total size of the
- symbol strings to a multiple of 8. I don't know if this is
- important, but it can't hurt much. */
- s = bfd_get_section_by_name (dynobj, ".dynstr");
- BFD_ASSERT (s != NULL);
- if ((s->_raw_size & 7) != 0)
- {
- bfd_size_type add;
- bfd_byte *contents;
-
- add = 8 - (s->_raw_size & 7);
- contents = (bfd_byte *) bfd_realloc (s->contents,
- s->_raw_size + add);
- if (contents == NULL)
- return false;
- memset (contents + s->_raw_size, 0, (size_t) add);
- s->contents = contents;
- s->_raw_size += add;
- }
- }
-
- /* Now that we have worked out the sizes of the procedure linkage
- table and the dynamic relocs, allocate storage for them. */
- s = bfd_get_section_by_name (dynobj, ".plt");
- BFD_ASSERT (s != NULL);
- if (s->_raw_size != 0)
- {
- s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
- if (s->contents == NULL)
- return false;
-
- /* Fill in the first entry in the table. */
- switch (bfd_get_arch (dynobj))
- {
- case bfd_arch_sparc:
- memcpy (s->contents, sparc_plt_first_entry, SPARC_PLT_ENTRY_SIZE);
- break;
-
- case bfd_arch_m68k:
- memcpy (s->contents, m68k_plt_first_entry, M68K_PLT_ENTRY_SIZE);
- break;
-
- default:
- abort ();
- }
- }
-
- s = bfd_get_section_by_name (dynobj, ".dynrel");
- if (s->_raw_size != 0)
- {
- s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
- if (s->contents == NULL)
- return false;
- }
- /* We use the reloc_count field to keep track of how many of the
- relocs we have output so far. */
- s->reloc_count = 0;
-
- /* Make space for the global offset table. */
- s = bfd_get_section_by_name (dynobj, ".got");
- s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
- if (s->contents == NULL)
- return false;
-
- *sneedptr = bfd_get_section_by_name (dynobj, ".need");
- *srulesptr = bfd_get_section_by_name (dynobj, ".rules");
-
- return true;
-}
-
-/* Scan the relocs for an input section. */
-
-static boolean
-sunos_scan_relocs (info, abfd, sec, rel_size)
- struct bfd_link_info *info;
- bfd *abfd;
- asection *sec;
- bfd_size_type rel_size;
-{
- PTR relocs;
- PTR free_relocs = NULL;
-
- if (rel_size == 0)
- return true;
-
- if (! info->keep_memory)
- relocs = free_relocs = bfd_malloc (rel_size);
- else
- {
- struct aout_section_data_struct *n;
- bfd_size_type amt = sizeof (struct aout_section_data_struct);
-
- n = (struct aout_section_data_struct *) bfd_alloc (abfd, amt);
- if (n == NULL)
- relocs = NULL;
- else
- {
- set_aout_section_data (sec, n);
- relocs = bfd_malloc (rel_size);
- aout_section_data (sec)->relocs = relocs;
- }
- }
- if (relocs == NULL)
- return false;
-
- if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
- || bfd_bread (relocs, rel_size, abfd) != rel_size)
- goto error_return;
-
- if (obj_reloc_entry_size (abfd) == RELOC_STD_SIZE)
- {
- if (! sunos_scan_std_relocs (info, abfd, sec,
- (struct reloc_std_external *) relocs,
- rel_size))
- goto error_return;
- }
- else
- {
- if (! sunos_scan_ext_relocs (info, abfd, sec,
- (struct reloc_ext_external *) relocs,
- rel_size))
- goto error_return;
- }
-
- if (free_relocs != NULL)
- free (free_relocs);
-
- return true;
-
- error_return:
- if (free_relocs != NULL)
- free (free_relocs);
- return false;