X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felflink.c;h=88967c835fa7dc7d164e70ade4093c6c079a7bb1;hb=16e4ecc0dbe114cfc97fe2cd32a035ae4c37f22b;hp=363abed0a260845e65d967bdb06e2907960500b9;hpb=b82970680130d28392656daf79dfa1b94aa553e0;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elflink.c b/bfd/elflink.c index 363abed0a2..88967c835f 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -85,7 +85,8 @@ _bfd_elf_define_linkage_sym (bfd *abfd, h->def_regular = 1; h->non_elf = 0; h->type = STT_OBJECT; - h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN; + if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL) + h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN; bed = get_elf_backend_data (abfd); (*bed->elf_backend_hide_symbol) (info, h, TRUE); @@ -950,11 +951,6 @@ _bfd_elf_merge_symbol (bfd *abfd, bed = get_elf_backend_data (abfd); - /* This code is for coping with dynamic objects, and is only useful - if we are doing an ELF link. */ - if (!(*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec)) - return TRUE; - /* For merging, we only care about real symbols. But we need to make sure that indirect symbol dynamic flags are updated. */ hi = h; @@ -962,6 +958,49 @@ _bfd_elf_merge_symbol (bfd *abfd, || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; + /* OLDBFD and OLDSEC are a BFD and an ASECTION associated with the + existing symbol. */ + + oldbfd = NULL; + oldsec = NULL; + switch (h->root.type) + { + default: + break; + + case bfd_link_hash_undefined: + case bfd_link_hash_undefweak: + oldbfd = h->root.u.undef.abfd; + break; + + case bfd_link_hash_defined: + case bfd_link_hash_defweak: + oldbfd = h->root.u.def.section->owner; + oldsec = h->root.u.def.section; + break; + + case bfd_link_hash_common: + oldbfd = h->root.u.c.p->section->owner; + oldsec = h->root.u.c.p->section; + if (pold_alignment) + *pold_alignment = h->root.u.c.p->alignment_power; + break; + } + if (poldbfd && *poldbfd == NULL) + *poldbfd = oldbfd; + + /* Differentiate strong and weak symbols. */ + newweak = bind == STB_WEAK; + oldweak = (h->root.type == bfd_link_hash_defweak + || h->root.type == bfd_link_hash_undefweak); + if (pold_weak) + *pold_weak = oldweak; + + /* This code is for coping with dynamic objects, and is only useful + if we are doing an ELF link. */ + if (!(*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec)) + return TRUE; + /* We have to check it for every instance since the first few may be references and not all compilers emit symbol type for undefined symbols. */ @@ -1006,45 +1045,6 @@ _bfd_elf_merge_symbol (bfd *abfd, return TRUE; } - /* OLDBFD and OLDSEC are a BFD and an ASECTION associated with the - existing symbol. */ - - switch (h->root.type) - { - default: - oldbfd = NULL; - oldsec = NULL; - break; - - case bfd_link_hash_undefined: - case bfd_link_hash_undefweak: - oldbfd = h->root.u.undef.abfd; - oldsec = NULL; - break; - - case bfd_link_hash_defined: - case bfd_link_hash_defweak: - oldbfd = h->root.u.def.section->owner; - oldsec = h->root.u.def.section; - break; - - case bfd_link_hash_common: - oldbfd = h->root.u.c.p->section->owner; - oldsec = h->root.u.c.p->section; - if (pold_alignment) - *pold_alignment = h->root.u.c.p->alignment_power; - break; - } - if (poldbfd && *poldbfd == NULL) - *poldbfd = oldbfd; - - /* Differentiate strong and weak symbols. */ - newweak = bind == STB_WEAK; - oldweak = (h->root.type == bfd_link_hash_defweak - || h->root.type == bfd_link_hash_undefweak); - if (pold_weak) - *pold_weak = oldweak; - /* In cases involving weak versioned symbols, we may wind up trying to merge a symbol with itself. Catch that here, to avoid the confusion that results if we try to override a symbol with @@ -1087,20 +1087,19 @@ _bfd_elf_merge_symbol (bfd *abfd, /* When we try to create a default indirect symbol from the dynamic definition with the default version, we skip it if its type and - the type of existing regular definition mismatch. We only do it - if the existing regular definition won't be dynamic. */ + the type of existing regular definition mismatch. */ if (pold_alignment == NULL - && !info->shared - && !info->export_dynamic - && !h->ref_dynamic && newdyn && newdef && !olddyn - && (olddef || h->root.type == bfd_link_hash_common) - && ELF_ST_TYPE (sym->st_info) != h->type - && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE - && h->type != STT_NOTYPE - && !(newfunc && oldfunc)) + && (((olddef || h->root.type == bfd_link_hash_common) + && ELF_ST_TYPE (sym->st_info) != h->type + && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE + && h->type != STT_NOTYPE + && !(newfunc && oldfunc)) + || (olddef + && ((h->type == STT_GNU_IFUNC) + != (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC))))) { *skip = TRUE; return TRUE; @@ -1437,7 +1436,10 @@ _bfd_elf_merge_symbol (bfd *abfd, if (!(oldbfd != NULL && (oldbfd->flags & BFD_PLUGIN) != 0 && (abfd->flags & BFD_PLUGIN) == 0)) - *skip = TRUE; + { + newdef = FALSE; + *skip = TRUE; + } /* Merge st_other. If the symbol already has a dynamic index, but visibility says it should not be visible, turn it into a @@ -1702,6 +1704,12 @@ _bfd_elf_add_default_symbol (bfd *abfd, ht = (struct elf_link_hash_entry *) hi->root.u.i.link; (*bed->elf_backend_copy_indirect_symbol) (info, ht, hi); + /* A reference to the SHORTNAME symbol from a dynamic library + will be satisfied by the versioned symbol at runtime. In + effect, we have a reference to the versioned symbol. */ + ht->ref_dynamic_nonweak |= hi->ref_dynamic_nonweak; + hi->dynamic_def |= ht->dynamic_def; + /* See if the new flags lead us to realize that the symbol must be dynamic. */ if (! *dynsym) @@ -1771,6 +1779,8 @@ nondefault: if (hi->root.type == bfd_link_hash_indirect) { (*bed->elf_backend_copy_indirect_symbol) (info, h, hi); + h->ref_dynamic_nonweak |= hi->ref_dynamic_nonweak; + hi->dynamic_def |= h->dynamic_def; /* See if the new flags lead us to realize that the symbol must be dynamic. */ @@ -3309,6 +3319,18 @@ _bfd_elf_relocs_compatible (const bfd_target *input, return ibed->relocs_compatible == obed->relocs_compatible; } +/* Make a special call to the linker "notice" function to tell it that + we are about to handle an as-needed lib, or have finished + processing the lib. */ + +bfd_boolean +_bfd_elf_notice_as_needed (bfd *ibfd, + struct bfd_link_info *info, + enum notice_asneeded_action act) +{ + return (*info->callbacks->notice) (info, NULL, ibfd, NULL, act, 0, NULL); +} + /* Add symbols from an ELF object file to the linker hash table. */ static bfd_boolean @@ -3338,14 +3360,13 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) unsigned int old_size = 0; unsigned int old_count = 0; void *old_tab = NULL; - void *old_hash; void *old_ent; struct bfd_link_hash_entry *old_undefs = NULL; struct bfd_link_hash_entry *old_undefs_tail = NULL; long old_dynsymcount = 0; bfd_size_type old_dynstr_size = 0; size_t tabsize = 0; - size_t hashsize = 0; + asection *s; htab = elf_hash_table (info); bed = get_elf_backend_data (abfd); @@ -3387,75 +3408,64 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) symbol. This differs from .gnu.warning sections, which generate warnings when they are included in an output file. */ /* PR 12761: Also generate this warning when building shared libraries. */ - if (info->executable || info->shared) + for (s = abfd->sections; s != NULL; s = s->next) { - asection *s; + const char *name; - for (s = abfd->sections; s != NULL; s = s->next) + name = bfd_get_section_name (abfd, s); + if (CONST_STRNEQ (name, ".gnu.warning.")) { - const char *name; + char *msg; + bfd_size_type sz; - name = bfd_get_section_name (abfd, s); - if (CONST_STRNEQ (name, ".gnu.warning.")) + name += sizeof ".gnu.warning." - 1; + + /* If this is a shared object, then look up the symbol + in the hash table. If it is there, and it is already + been defined, then we will not be using the entry + from this shared object, so we don't need to warn. + FIXME: If we see the definition in a regular object + later on, we will warn, but we shouldn't. The only + fix is to keep track of what warnings we are supposed + to emit, and then handle them all at the end of the + link. */ + if (dynamic) { - char *msg; - bfd_size_type sz; - - name += sizeof ".gnu.warning." - 1; - - /* If this is a shared object, then look up the symbol - in the hash table. If it is there, and it is already - been defined, then we will not be using the entry - from this shared object, so we don't need to warn. - FIXME: If we see the definition in a regular object - later on, we will warn, but we shouldn't. The only - fix is to keep track of what warnings we are supposed - to emit, and then handle them all at the end of the - link. */ - if (dynamic) - { - struct elf_link_hash_entry *h; + struct elf_link_hash_entry *h; - h = elf_link_hash_lookup (htab, name, FALSE, FALSE, TRUE); + h = elf_link_hash_lookup (htab, name, FALSE, FALSE, TRUE); - /* FIXME: What about bfd_link_hash_common? */ - if (h != NULL - && (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak)) - { - /* We don't want to issue this warning. Clobber - the section size so that the warning does not - get copied into the output file. */ - s->size = 0; - continue; - } - } + /* FIXME: What about bfd_link_hash_common? */ + if (h != NULL + && (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak)) + continue; + } - sz = s->size; - msg = (char *) bfd_alloc (abfd, sz + 1); - if (msg == NULL) - goto error_return; + sz = s->size; + msg = (char *) bfd_alloc (abfd, sz + 1); + if (msg == NULL) + goto error_return; - if (! bfd_get_section_contents (abfd, s, msg, 0, sz)) - goto error_return; + if (! bfd_get_section_contents (abfd, s, msg, 0, sz)) + goto error_return; - msg[sz] = '\0'; + msg[sz] = '\0'; - if (! (_bfd_generic_link_add_one_symbol - (info, abfd, name, BSF_WARNING, s, 0, msg, - FALSE, bed->collect, NULL))) - goto error_return; + if (! (_bfd_generic_link_add_one_symbol + (info, abfd, name, BSF_WARNING, s, 0, msg, + FALSE, bed->collect, NULL))) + goto error_return; - if (! info->relocatable) - { - /* Clobber the section size so that the warning does - not get copied into the output file. */ - s->size = 0; + if (!info->relocatable && info->executable) + { + /* Clobber the section size so that the warning does + not get copied into the output file. */ + s->size = 0; - /* Also set SEC_EXCLUDE, so that symbols defined in - the warning section don't get copied to the output. */ - s->flags |= SEC_EXCLUDE; - } + /* Also set SEC_EXCLUDE, so that symbols defined in + the warning section don't get copied to the output. */ + s->flags |= SEC_EXCLUDE; } } } @@ -3481,7 +3491,6 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) goto error_return; else { - asection *s; const char *soname = NULL; char *audit = NULL; struct bfd_link_needed_list *rpath = NULL, *runpath = NULL; @@ -3700,7 +3709,7 @@ error_free_dyn: extsymoff = hdr->sh_info; } - sym_hash = NULL; + sym_hash = elf_sym_hashes (abfd); if (extsymcount != 0) { isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff, @@ -3708,13 +3717,16 @@ error_free_dyn: if (isymbuf == NULL) goto error_return; - /* We store a pointer to the hash table entry for each external - symbol. */ - amt = extsymcount * sizeof (struct elf_link_hash_entry *); - sym_hash = (struct elf_link_hash_entry **) bfd_alloc (abfd, amt); if (sym_hash == NULL) - goto error_free_sym; - elf_sym_hashes (abfd) = sym_hash; + { + /* We store a pointer to the hash table entry for each + external symbol. */ + amt = extsymcount * sizeof (struct elf_link_hash_entry *); + sym_hash = (struct elf_link_hash_entry **) bfd_zalloc (abfd, amt); + if (sym_hash == NULL) + goto error_free_sym; + elf_sym_hashes (abfd) = sym_hash; + } } if (dynamic) @@ -3764,8 +3776,7 @@ error_free_dyn: } tabsize = htab->root.table.size * sizeof (struct bfd_hash_entry *); - hashsize = extsymcount * sizeof (struct elf_link_hash_entry *); - old_tab = bfd_malloc (tabsize + entsize + hashsize); + old_tab = bfd_malloc (tabsize + entsize); if (old_tab == NULL) goto error_free_vers; @@ -3777,16 +3788,13 @@ error_free_dyn: /* Make a special call to the linker "notice" function to tell it that we are about to handle an as-needed lib. */ - if (!(*info->callbacks->notice) (info, NULL, abfd, NULL, - notice_as_needed, 0, NULL)) + if (!(*bed->notice_as_needed) (abfd, info, notice_as_needed)) goto error_free_vers; - /* Clone the symbol table and sym hashes. Remember some - pointers into the symbol table, and dynamic symbol count. */ - old_hash = (char *) old_tab + tabsize; - old_ent = (char *) old_hash + hashsize; + /* Clone the symbol table. Remember some pointers into the + symbol table, and dynamic symbol count. */ + old_ent = (char *) old_tab + tabsize; memcpy (old_tab, htab->root.table.table, tabsize); - memcpy (old_hash, sym_hash, hashsize); old_undefs = htab->root.undefs; old_undefs_tail = htab->root.undefs_tail; old_table = htab->root.table.table; @@ -3843,7 +3851,6 @@ error_free_dyn: flags = BSF_NO_FLAGS; sec = NULL; value = isym->st_value; - *sym_hash = NULL; common = bed->common_definition (isym); bind = ELF_ST_BIND (isym->st_info); @@ -4430,6 +4437,9 @@ error_free_dyn: int ret; const char *soname = elf_dt_name (abfd); + info->callbacks->minfo ("%!", soname, old_bfd, + h->root.root.string); + /* A symbol from a library loaded via DT_NEEDED of some other library is referenced by a regular object. Add a DT_NEEDED entry for it. Issue an error if @@ -4475,16 +4485,13 @@ error_free_dyn: unsigned int i; /* Restore the symbol table. */ - if (bed->as_needed_cleanup) - (*bed->as_needed_cleanup) (abfd, info); - old_hash = (char *) old_tab + tabsize; - old_ent = (char *) old_hash + hashsize; - sym_hash = elf_sym_hashes (abfd); + old_ent = (char *) old_tab + tabsize; + memset (elf_sym_hashes (abfd), 0, + extsymcount * sizeof (struct elf_link_hash_entry *)); htab->root.table.table = old_table; htab->root.table.size = old_size; htab->root.table.count = old_count; memcpy (htab->root.table.table, old_tab, tabsize); - memcpy (sym_hash, old_hash, hashsize); htab->root.undefs = old_undefs; htab->root.undefs_tail = old_undefs_tail; _bfd_elf_strtab_restore_size (htab->dynstr, old_dynstr_size); @@ -4539,8 +4546,7 @@ error_free_dyn: /* Make a special call to the linker "notice" function to tell it that symbols added for crefs may need to be removed. */ - if (!(*info->callbacks->notice) (info, NULL, abfd, NULL, - notice_not_needed, 0, NULL)) + if (!(*bed->notice_as_needed) (abfd, info, notice_not_needed)) goto error_free_vers; free (old_tab); @@ -4553,8 +4559,7 @@ error_free_dyn: if (old_tab != NULL) { - if (!(*info->callbacks->notice) (info, NULL, abfd, NULL, - notice_needed, 0, NULL)) + if (!(*bed->notice_as_needed) (abfd, info, notice_needed)) goto error_free_vers; free (old_tab); old_tab = NULL; @@ -4665,7 +4670,7 @@ error_free_dyn: struct elf_link_hash_entry *hlook; asection *slook; bfd_vma vlook; - size_t i, j, idx; + size_t i, j, idx = 0; hlook = weaks; weaks = hlook->u.weakdef; @@ -7468,6 +7473,7 @@ struct elf_outext_info bfd_boolean localsyms; bfd_boolean need_second_pass; bfd_boolean second_pass; + bfd_boolean file_sym_done; struct elf_final_link_info *flinfo; }; @@ -8686,6 +8692,22 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) || h->root.type == bfd_link_hash_defweak) && h->root.u.def.section->output_section != NULL)) return TRUE; + + if (!eoinfo->file_sym_done + && (eoinfo->second_pass ? eoinfo->flinfo->filesym_count == 1 + : eoinfo->flinfo->filesym_count > 1)) + { + /* Output a FILE symbol so that following locals are not associated + with the wrong input file. */ + memset (&sym, 0, sizeof (sym)); + sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE); + sym.st_shndx = SHN_ABS; + if (!elf_link_output_sym (eoinfo->flinfo, NULL, &sym, + bfd_und_section_ptr, NULL)) + return FALSE; + + eoinfo->file_sym_done = TRUE; + } } else { @@ -10970,17 +10992,6 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) } } - /* Output a FILE symbol so that following locals are not associated - with the wrong input file. */ - memset (&elfsym, 0, sizeof (elfsym)); - elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE); - elfsym.st_shndx = SHN_ABS; - - if (flinfo.filesym_count > 1 - && !elf_link_output_sym (&flinfo, NULL, &elfsym, - bfd_und_section_ptr, NULL)) - return FALSE; - /* Output any global symbols that got converted to local in a version script or due to symbol visibility. We do this in a separate step since ELF requires all local symbols to appear @@ -10992,15 +11003,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) eoinfo.localsyms = TRUE; eoinfo.need_second_pass = FALSE; eoinfo.second_pass = FALSE; + eoinfo.file_sym_done = FALSE; bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo); if (eoinfo.failed) return FALSE; - if (flinfo.filesym_count == 1 - && !elf_link_output_sym (&flinfo, NULL, &elfsym, - bfd_und_section_ptr, NULL)) - return FALSE; - if (eoinfo.need_second_pass) { eoinfo.second_pass = TRUE;