?? sunos.c
字號:
struct bfd_link_needed_list *bfd_sunos_get_needed_list (abfd, info) bfd *abfd ATTRIBUTE_UNUSED; struct bfd_link_info *info;{ if (info->hash->creator != &MY(vec)) return NULL; return sunos_hash_table (info)->needed;}/* Record an assignment made to a symbol by a linker script. We need this in case some dynamic object refers to this symbol. */booleanbfd_sunos_record_link_assignment (output_bfd, info, name) bfd *output_bfd; struct bfd_link_info *info; const char *name;{ struct sunos_link_hash_entry *h; if (output_bfd->xvec != &MY(vec)) return true; /* This is called after we have examined all the input objects. If the symbol does not exist, it merely means that no object refers to it, and we can just ignore it at this point. */ h = sunos_link_hash_lookup (sunos_hash_table (info), name, false, false, false); if (h == NULL) return true; /* In a shared library, the __DYNAMIC symbol does not appear in the dynamic symbol table. */ if (! info->shared || strcmp (name, "__DYNAMIC") != 0) { h->flags |= SUNOS_DEF_REGULAR; if (h->dynindx == -1) { ++sunos_hash_table (info)->dynsymcount; h->dynindx = -2; } } 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. */booleanbfd_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; size_t dynsymcount; struct sunos_link_hash_entry *h; asection *s; size_t bucketcount; size_t 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_alloc (dynobj, hashalloc); if (s->contents == NULL && dynsymcount > 0) 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; /* 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, (size_t) (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 booleansunos_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 ((size_t) rel_size); else { struct aout_section_data_struct *n; n = ((struct aout_section_data_struct *) bfd_alloc (abfd, sizeof (struct aout_section_data_struct))); if (n == NULL) relocs = NULL; else { set_aout_section_data (sec, n); relocs = bfd_malloc ((size_t) rel_size); aout_section_data (sec)->relocs = relocs; } } if (relocs == NULL) 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 booleansunos_scan_std_relocs (info, abfd, sec, relocs, rel_size) struct bfd_link_info *info; bfd *abfd; asection *sec ATTRIBUTE_UNUSED; const struct reloc_std_external *relocs; bfd_size_type rel_size;{ bfd *dynobj; asection *splt = NULL; asection *srel = NULL; 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 = NULL; sym_hashes = (struct sunos_link_hash_entry **) obj_aout_sym_hashes (abfd); relend = relocs + rel_size / RELOC_STD_SIZE; for (rel = relocs; rel < relend; rel++) { int r_index; struct sunos_link_hash_entry *h; /* We only want relocs against external symbols. */ if (bfd_header_big_endian (abfd)) { if ((rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG) == 0) continue; } else { if ((rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE) == 0) continue; } /* Get the symbol index. */ if (bfd_header_big_endian (abfd)) r_index = ((rel->r_index[0] << 16) | (rel->r_index[1] << 8) | rel->r_index[2]); else r_index = ((rel->r_index[2] << 16) | (rel->r_index[1] << 8) | rel->r_index[0]); /* Get the hash table entry. */ h = sym_hashes[r_index]; if (h == NULL) { /* This should not normally happen, but it will in any case be caught in the relocation phase. */ continue; } /* At this point common symbols have already been allocated, so we don't have to worry about them. We need to consider that we may have already seen this symbol and marked it undefined; if the symbol is really undefined, then SUNOS_DEF_DYNAMIC will be zero. */ if (h->root.root.type != bfd_link_hash_defined && h->root.root.type != bfd_link_hash_defweak && h->root.root.type != bfd_link_hash_undefined) continue;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -