- /* If there were no dynamic objects in the link, there is nothing to
- do here. */
- if (dynobj == NULL)
- return true;
-
- /* The .dynamic section is always the same size. */
- s = bfd_get_section_by_name (dynobj, ".dynamic");
- 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)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- /* The number of buckets is just the number of symbols divided by
- four. The 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 worse 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_alloc (dynobj, hashalloc);
- if (s->contents == NULL && dynsymcount > 0)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- memset (s->contents, 0, hashalloc);
- 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;
-
- /* 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)
- {
- 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;
- }
- }
-
- /* 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 *) realloc (s->contents, s->_raw_size + add);
- if (contents == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- memset (contents + s->_raw_size, 0, 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)
- {
- bfd_set_error (bfd_error_no_memory);
- 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)
- {
- bfd_set_error (bfd_error_no_memory);
- 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)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- *sdynptr = bfd_get_section_by_name (dynobj, ".dynamic");
- *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 = malloc (rel_size);
- else
- {
- aout_section_data (sec) =
- ((struct aout_section_data_struct *)
- bfd_alloc (abfd, sizeof (struct aout_section_data_struct)));
- if (aout_section_data (sec) == NULL)
- relocs = NULL;
- else
- relocs = aout_section_data (sec)->relocs = malloc (rel_size);
- }
- if (relocs == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
- || bfd_read (relocs, 1, 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;
-}
-
-/* Scan the relocs for an input section using standard relocs. We
- need to figure out what to do for each reloc against a dynamic
- symbol. If the symbol is in the .text section, an entry is made in
- the procedure linkage table. Note that this will do the wrong
- thing if the symbol is actually data; I don't think the Sun 3
- native linker handles this case correctly either. If the symbol is
- not in the .text section, we must preserve the reloc as a dynamic
- reloc. FIXME: We should also handle the PIC relocs here by
- building global offset table entries. */
-
-static boolean
-sunos_scan_std_relocs (info, abfd, sec, relocs, rel_size)
- struct bfd_link_info *info;
- bfd *abfd;
- asection *sec;
- const struct reloc_std_external *relocs;
- bfd_size_type rel_size;
-{
- bfd *dynobj;
- asection *splt;
- asection *srel;
- struct sunos_link_hash_entry **sym_hashes;
- const struct reloc_std_external *rel, *relend;
-
- /* We only know how to handle m68k plt entries. */
- if (bfd_get_arch (abfd) != bfd_arch_m68k)
- {
- bfd_set_error (bfd_error_invalid_target);
- return false;
- }
-
- dynobj = sunos_hash_table (info)->dynobj;
- splt = bfd_get_section_by_name (dynobj, ".plt");
- srel = bfd_get_section_by_name (dynobj, ".dynrel");
- BFD_ASSERT (splt != NULL && srel != NULL);
- sym_hashes = (struct sunos_link_hash_entry **) obj_aout_sym_hashes (abfd);