X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felflink.h;h=0f5c71252035be930b51c2f8d0d20414ec2c080f;hb=6c426cf36e042f2ef86fdb7d6c7e5e6a7ddb0e1c;hp=5ba86e77e5ad4f9d9b535951b1e0acd691fe8fb2;hpb=7898dedac0f0bd75d7363d13427c4a1e72b66f66;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elflink.h b/bfd/elflink.h index 5ba86e77e5..0f5c712520 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -895,7 +895,6 @@ elf_link_add_object_symbols (abfd, info) Elf_External_Sym *buf = NULL; struct elf_link_hash_entry **sym_hash; boolean dynamic; - bfd_byte *dynver = NULL; Elf_External_Versym *extversym = NULL; Elf_External_Versym *ever; Elf_External_Dyn *dynbuf = NULL; @@ -1023,7 +1022,7 @@ elf_link_add_object_symbols (abfd, info) Elf_Internal_Shdr *versymhdr; versymhdr = &elf_tdata (abfd)->dynversym_hdr; - extversym = (Elf_External_Versym *) bfd_malloc (hdr->sh_size); + extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size); if (extversym == NULL) goto error_return; if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0 @@ -1322,7 +1321,7 @@ elf_link_add_object_symbols (abfd, info) /* Save the SONAME, if there is one, because sometimes the linker emulation code will need to know it. */ if (*name == '\0') - name = bfd_get_filename (abfd); + name = basename (bfd_get_filename (abfd)); elf_dt_name (abfd) = name; } @@ -2167,6 +2166,18 @@ elf_link_add_object_symbols (abfd, info) } } + if (! info->relocateable && ! dynamic) + { + asection *s; + + for (s = abfd->sections; s != NULL; s = s->next) + if ((s->flags & SEC_MERGE) + && ! _bfd_merge_section (abfd, + &elf_hash_table (info)->merge_info, + s, &elf_section_data (s)->merge_info)) + goto error_return; + } + return true; error_return: @@ -2174,8 +2185,6 @@ elf_link_add_object_symbols (abfd, info) free (buf); if (dynbuf != NULL) free (dynbuf); - if (dynver != NULL) - free (dynver); if (extversym != NULL) free (extversym); return false; @@ -2456,7 +2465,7 @@ elf_link_read_relocs_from_section (abfd, shdr, external_relocs, Elf_Internal_Rel *irel; erel = (Elf_External_Rel *) external_relocs; - erelend = erel + shdr->sh_size / shdr->sh_entsize; + erelend = erel + NUM_SHDR_ENTRIES (shdr); irela = internal_relocs; irel = bfd_alloc (abfd, (bed->s->int_rels_per_ext_rel * sizeof (Elf_Internal_Rel))); @@ -2486,7 +2495,7 @@ elf_link_read_relocs_from_section (abfd, shdr, external_relocs, BFD_ASSERT (shdr->sh_entsize == sizeof (Elf_External_Rela)); erela = (Elf_External_Rela *) external_relocs; - erelaend = erela + shdr->sh_size / shdr->sh_entsize; + erelaend = erela + NUM_SHDR_ENTRIES (shdr); irela = internal_relocs; for (; erela < erelaend; erela++, irela += bed->s->int_rels_per_ext_rel) { @@ -2566,7 +2575,7 @@ NAME(_bfd_elf,link_read_relocs) (abfd, o, external_relocs, internal_relocs, (abfd, elf_section_data (o)->rel_hdr2, ((bfd_byte *) external_relocs) + rel_hdr->sh_size, - internal_relocs + (rel_hdr->sh_size / rel_hdr->sh_entsize + internal_relocs + (NUM_SHDR_ENTRIES (rel_hdr) * bed->s->int_rels_per_ext_rel))) goto error_return; @@ -2957,14 +2966,13 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, } } + eif.info = info; + eif.failed = false; + /* If we are supposed to export all symbols into the dynamic symbol table (this is not the normal case), then do so. */ if (export_dynamic) { - struct elf_info_failed eif; - - eif.failed = false; - eif.info = info; elf_link_hash_traverse (elf_hash_table (info), elf_export_symbol, (PTR) &eif); if (eif.failed) @@ -2986,8 +2994,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, /* Find all symbols which were defined in a dynamic object and make the backend pick a reasonable value for them. */ - eif.failed = false; - eif.info = info; elf_link_hash_traverse (elf_hash_table (info), elf_adjust_dynamic_symbol, (PTR) &eif); @@ -3124,7 +3130,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, const char *name; bfd_size_type indx; - name = output_bfd->filename; + name = basename (output_bfd->filename); def.vd_hash = bfd_elf_hash (name); indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, name, true, false); @@ -3308,7 +3314,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, true, false); else indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, - t->vn_bfd->filename, true, false); + basename (t->vn_bfd->filename), + true, false); if (indx == (bfd_size_type) -1) return false; t->vn_file = indx; @@ -3518,16 +3525,24 @@ elf_fix_symbol_flags (h, eif) /* If -Bsymbolic was used (which means to bind references to global symbols to the definition within the shared object), and this symbol was defined in a regular object, then it actually doesn't - need a PLT entry. Likewise, if the symbol has any kind of - visibility (internal, hidden, or protected), it doesn't need a - PLT. */ + need a PLT entry, and we can accomplish that by forcing it local. + Likewise, if the symbol has hidden or internal visibility. + FIXME: It might be that we also do not need a PLT for other + non-hidden visibilities, but we would have to tell that to the + backend specifically; we can't just clear PLT-related data here. */ if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0 && eif->info->shared - && (eif->info->symbolic || ELF_ST_VISIBILITY (h->other)) + && (eif->info->symbolic + || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL + || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN) && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0) { - h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT; - h->plt.offset = (bfd_vma) -1; + struct elf_backend_data *bed; + bed = get_elf_backend_data (elf_hash_table (eif->info)->dynobj); + if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL + || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN) + h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL; + (*bed->elf_backend_hide_symbol) (eif->info, h); } /* If this is a weak defined symbol in a dynamic object, and we know @@ -4067,6 +4082,8 @@ static boolean elf_link_flush_output_syms PARAMS ((struct elf_final_link_info *)); static boolean elf_link_output_extsym PARAMS ((struct elf_link_hash_entry *, PTR)); +static boolean elf_link_sec_merge_syms + PARAMS ((struct elf_link_hash_entry *, PTR)); static boolean elf_link_input_bfd PARAMS ((struct elf_final_link_info *, bfd *)); static boolean elf_reloc_link_order @@ -4216,6 +4233,7 @@ elf_bfd_final_link (abfd, info) Elf_Internal_Shdr *symstrtab_hdr; struct elf_backend_data *bed = get_elf_backend_data (abfd); struct elf_outext_info eoinfo; + boolean merged; if (info->shared) abfd->flags |= DYNAMIC; @@ -4261,6 +4279,7 @@ elf_bfd_final_link (abfd, info) max_external_reloc_size = 0; max_internal_reloc_count = 0; max_sym_count = 0; + merged = false; for (o = abfd->sections; o != (asection *) NULL; o = o->next) { o->reloc_count = 0; @@ -4282,6 +4301,9 @@ elf_bfd_final_link (abfd, info) the linker has decided to not include. */ sec->linker_mark = true; + if (sec->flags & SEC_MERGE) + merged = true; + if (info->relocateable || info->emitrelocations) o->reloc_count += sec->reloc_count; @@ -4339,6 +4361,10 @@ elf_bfd_final_link (abfd, info) o->vma = 0; } + if (! info->relocateable && merged) + elf_link_hash_traverse (elf_hash_table (info), + elf_link_sec_merge_syms, (PTR) abfd); + /* Figure out the file positions for everything but the symbol table and the relocs. We set symcount to force assign_section_numbers to create a symbol table. */ @@ -4387,11 +4413,9 @@ elf_bfd_final_link (abfd, info) rel_count2 = &esdo->rel_count; } - *rel_count += (esdi->rel_hdr.sh_size - / esdi->rel_hdr.sh_entsize); + *rel_count += NUM_SHDR_ENTRIES (& esdi->rel_hdr); if (esdi->rel_hdr2) - *rel_count2 += (esdi->rel_hdr2->sh_size - / esdi->rel_hdr2->sh_entsize); + *rel_count2 += NUM_SHDR_ENTRIES (esdi->rel_hdr2); } } @@ -5058,6 +5082,33 @@ elf_link_flush_output_syms (finfo) return true; } +/* Adjust all external symbols pointing into SEC_MERGE sections + to reflect the object merging within the sections. */ + +static boolean +elf_link_sec_merge_syms (h, data) + struct elf_link_hash_entry *h; + PTR data; +{ + asection *sec; + + if ((h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && ((sec = h->root.u.def.section)->flags & SEC_MERGE) + && elf_section_data (sec)->merge_info) + { + bfd *output_bfd = (bfd *) data; + + h->root.u.def.value = + _bfd_merged_section_offset (output_bfd, + &h->root.u.def.section, + elf_section_data (sec)->merge_info, + h->root.u.def.value, (bfd_vma) 0); + } + + return true; +} + /* Add an external symbol to the symbol table. This is called from the hash table traversal routine. When generating a shared object, we go through the symbol table twice. The first time we output @@ -5389,7 +5440,7 @@ elf_link_output_relocs (output_bfd, input_section, input_rel_hdr, bed = get_elf_backend_data (output_bfd); irela = internal_relocs; - irelaend = irela + input_rel_hdr->sh_size / input_rel_hdr->sh_entsize; + irelaend = irela + NUM_SHDR_ENTRIES (input_rel_hdr); if (input_rel_hdr->sh_entsize == sizeof (Elf_External_Rel)) { Elf_External_Rel *erel; @@ -5424,7 +5475,7 @@ elf_link_output_relocs (output_bfd, input_section, input_rel_hdr, /* Bump the counter, so that we know where to add the next set of relocations. */ - *rel_countp += input_rel_hdr->sh_size / input_rel_hdr->sh_entsize; + *rel_countp += NUM_SHDR_ENTRIES (input_rel_hdr); } /* Link an input file into the linker output file. This function @@ -5523,7 +5574,15 @@ elf_link_input_bfd (finfo, input_bfd) name = isec->name; } else if (isym->st_shndx > 0 && isym->st_shndx < SHN_LORESERVE) - isec = section_from_elf_index (input_bfd, isym->st_shndx); + { + isec = section_from_elf_index (input_bfd, isym->st_shndx); + if (isec && elf_section_data (isec)->merge_info + && ELF_ST_TYPE (isym->st_info) != STT_SECTION) + isym->st_value = + _bfd_merged_section_offset (output_bfd, &isec, + elf_section_data (isec)->merge_info, + isym->st_value, (bfd_vma) 0); + } else if (isym->st_shndx == SHN_ABS) { isec = bfd_abs_section_ptr; @@ -5625,7 +5684,9 @@ elf_link_input_bfd (finfo, input_bfd) if ((finfo->info->strip == strip_some && (bfd_hash_lookup (finfo->info->keep_hash, name, false, false) == NULL)) - || (finfo->info->discard == discard_l + || (((finfo->info->discard == discard_sec_merge + && (isec->flags & SEC_MERGE) && ! finfo->info->relocateable) + || finfo->info->discard == discard_l) && bfd_is_local_label_name (input_bfd, name))) continue; @@ -5876,8 +5937,7 @@ elf_link_input_bfd (finfo, input_bfd) elf_link_output_relocs (output_bfd, o, input_rel_hdr, internal_relocs); - internal_relocs - += input_rel_hdr->sh_size / input_rel_hdr->sh_entsize; + internal_relocs += NUM_SHDR_ENTRIES (input_rel_hdr); input_rel_hdr = elf_section_data (o)->rel_hdr2; if (input_rel_hdr) elf_link_output_relocs (output_bfd, o, @@ -5887,7 +5947,20 @@ elf_link_input_bfd (finfo, input_bfd) } /* Write out the modified section contents. */ - if (elf_section_data (o)->stab_info == NULL) + if (elf_section_data (o)->stab_info) + { + if (! (_bfd_write_section_stabs + (output_bfd, &elf_hash_table (finfo->info)->stab_info, + o, &elf_section_data (o)->stab_info, contents))) + return false; + } + else if (elf_section_data (o)->merge_info) + { + if (! (_bfd_write_merged_section + (output_bfd, o, elf_section_data (o)->merge_info))) + return false; + } + else { if (! (o->flags & SEC_EXCLUDE) && ! bfd_set_section_contents (output_bfd, o->output_section, @@ -5897,13 +5970,6 @@ elf_link_input_bfd (finfo, input_bfd) : o->_raw_size))) return false; } - else - { - if (! (_bfd_write_section_stabs - (output_bfd, &elf_hash_table (finfo->info)->stab_info, - o, &elf_section_data (o)->stab_info, contents))) - return false; - } } return true;