X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bfd%2Felflink.c;h=c8068c0118c1df307cac6e113483e1813b4d6f9e;hb=cbda93a56a0af8d7787ff091caad64af1b2bd085;hp=7cfc37957b5e8cfe813423edd82f7de7a803efe4;hpb=ed54588daf47156f054f0e8c5ef894c3c99e6797;p=platform%2Fupstream%2Fbinutils.git diff --git a/bfd/elflink.c b/bfd/elflink.c index 7cfc379..c8068c0 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -1,5 +1,5 @@ /* ELF linking support for BFD. - Copyright 1995-2013 Free Software Foundation, Inc. + Copyright (C) 1995-2014 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -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); @@ -850,47 +851,26 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd, static void elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h, - Elf_Internal_Sym *isym, bfd_boolean definition, - bfd_boolean dynamic) + const Elf_Internal_Sym *isym, + bfd_boolean definition, bfd_boolean dynamic) { const struct elf_backend_data *bed = get_elf_backend_data (abfd); /* If st_other has a processor-specific meaning, specific - code might be needed here. We never merge the visibility - attribute with the one from a dynamic object. */ + code might be needed here. */ if (bed->elf_backend_merge_symbol_attribute) (*bed->elf_backend_merge_symbol_attribute) (h, isym, definition, dynamic); - /* If this symbol has default visibility and the user has requested - we not re-export it, then mark it as hidden. */ - if (definition - && !dynamic - && (abfd->no_export - || (abfd->my_archive && abfd->my_archive->no_export)) - && ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL) - isym->st_other = (STV_HIDDEN - | (isym->st_other & ~ELF_ST_VISIBILITY (-1))); - - if (!dynamic && ELF_ST_VISIBILITY (isym->st_other) != 0) - { - unsigned char hvis, symvis, other, nvis; - - /* Only merge the visibility. Leave the remainder of the - st_other field to elf_backend_merge_symbol_attribute. */ - other = h->other & ~ELF_ST_VISIBILITY (-1); - - /* Combine visibilities, using the most constraining one. */ - hvis = ELF_ST_VISIBILITY (h->other); - symvis = ELF_ST_VISIBILITY (isym->st_other); - if (! hvis) - nvis = symvis; - else if (! symvis) - nvis = hvis; - else - nvis = hvis < symvis ? hvis : symvis; + if (!dynamic) + { + unsigned symvis = ELF_ST_VISIBILITY (isym->st_other); + unsigned hvis = ELF_ST_VISIBILITY (h->other); - h->other = other | nvis; + /* Keep the most constraining visibility. Leave the remainder + of the st_other field to elf_backend_merge_symbol_attribute. */ + if (symvis - 1 < hvis - 1) + h->other = symvis | (h->other & ~ELF_ST_VISIBILITY (-1)); } } @@ -950,11 +930,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 +937,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 +1024,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,34 +1066,32 @@ _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; } - /* Plugin symbol type isn't currently set. Stop bogus errors. */ - if (oldbfd != NULL && (oldbfd->flags & BFD_PLUGIN) != 0) - *type_change_ok = TRUE; - - /* Check TLS symbol. We don't check undefined symbol introduced by - "ld -u". */ - else if (oldbfd != NULL - && ELF_ST_TYPE (sym->st_info) != h->type - && (ELF_ST_TYPE (sym->st_info) == STT_TLS || h->type == STT_TLS)) + /* Check TLS symbols. We don't check undefined symbols introduced + by "ld -u" which have no type (and oldbfd NULL), and we don't + check symbols from plugins because they also have no type. */ + if (oldbfd != NULL + && (oldbfd->flags & BFD_PLUGIN) == 0 + && (abfd->flags & BFD_PLUGIN) == 0 + && ELF_ST_TYPE (sym->st_info) != h->type + && (ELF_ST_TYPE (sym->st_info) == STT_TLS || h->type == STT_TLS)) { bfd *ntbfd, *tbfd; bfd_boolean ntdef, tdef; @@ -1437,7 +1414,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 +1682,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) @@ -1737,7 +1723,7 @@ nondefault: size_change_ok = FALSE; tmp_sec = sec; if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &tmp_sec, &value, - &hi, NULL, NULL, NULL, &skip, &override, + &hi, poldbfd, NULL, NULL, &skip, &override, &type_change_ok, &size_change_ok)) return FALSE; @@ -1771,6 +1757,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. */ @@ -2943,13 +2931,6 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef) if (! bfd_check_format (abfd, bfd_object)) return FALSE; - /* If we have already included the element containing this symbol in the - link then we do not need to include it again. Just claim that any symbol - it contains is not a definition, so that our caller will not decide to - (re)include this element. */ - if (abfd->archive_pass) - return FALSE; - /* Select the appropriate symbol table. */ if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0) hdr = &elf_tdata (abfd)->symtab_hdr; @@ -3105,7 +3086,8 @@ static bfd_boolean on_needed_list (const char *soname, struct bfd_link_needed_list *needed) { for (; needed != NULL; needed = needed->next) - if (strcmp (soname, needed->name) == 0) + if ((elf_dyn_lib_class (needed->by) & DYN_AS_NEEDED) == 0 + && strcmp (soname, needed->name) == 0) return TRUE; return FALSE; @@ -3309,6 +3291,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, NULL, ibfd, NULL, act, 0); +} + /* Add symbols from an ELF object file to the linker hash table. */ static bfd_boolean @@ -3338,14 +3332,14 @@ 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; + bfd_boolean just_syms; htab = elf_hash_table (info); bed = get_elf_backend_data (abfd); @@ -3387,88 +3381,82 @@ 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; } } } + just_syms = ((s = abfd->sections) != NULL + && s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS); + add_needed = TRUE; if (! dynamic) { /* If we are creating a shared library, create all the dynamic sections immediately. We need to attach them to something, so we attach them to this BFD, provided it is the right - format. FIXME: If there are no input BFD's of the same - format as the output, we can't make a shared library. */ - if (info->shared + format and is not from ld --just-symbols. FIXME: If there + are no input BFD's of the same format as the output, we can't + make a shared library. */ + if (!just_syms + && info->shared && is_elf_hash_table (htab) && info->output_bfd->xvec == abfd->xvec && !htab->dynamic_sections_created) @@ -3481,7 +3469,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; @@ -3489,8 +3476,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) /* ld --just-symbols and dynamic objects don't mix very well. ld shouldn't allow it. */ - if ((s = abfd->sections) != NULL - && s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS) + if (just_syms) abort (); /* If this dynamic lib was specified on the command line with @@ -3700,7 +3686,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 +3694,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 +3753,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 +3765,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 +3828,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); @@ -4089,6 +4073,16 @@ error_free_dyn: name = newname; } + /* If this symbol has default visibility and the user has + requested we not re-export it, then mark it as hidden. */ + if (definition + && !dynamic + && (abfd->no_export + || (abfd->my_archive && abfd->my_archive->no_export)) + && ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL) + isym->st_other = (STV_HIDDEN + | (isym->st_other & ~ELF_ST_VISIBILITY (-1))); + if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec, &value, sym_hash, &old_bfd, &old_weak, &old_alignment, &skip, &override, @@ -4430,6 +4424,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 +4472,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 +4533,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 +4546,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; @@ -4935,20 +4927,8 @@ _bfd_elf_archive_symbol_lookup (bfd *abfd, } /* Add symbols from an ELF archive file to the linker hash table. We - don't use _bfd_generic_link_add_archive_symbols because of a - problem which arises on UnixWare. The UnixWare libc.so is an - archive which includes an entry libc.so.1 which defines a bunch of - symbols. The libc.so archive also includes a number of other - object files, which also define symbols, some of which are the same - as those defined in libc.so.1. Correct linking requires that we - consider each object file in turn, and include it if it defines any - symbols we need. _bfd_generic_link_add_archive_symbols does not do - this; it looks through the list of undefined symbols, and includes - any object file which defines them. When this algorithm is used on - UnixWare, it winds up pulling in libc.so.1 early and defining a - bunch of symbols. This means that some of the other objects in the - archive are not included in the link, which is incorrect since they - precede libc.so.1 in the archive. + don't use _bfd_generic_link_add_archive_symbols because we need to + handle versioned symbols. Fortunately, ELF archive handling is simpler than that done by _bfd_generic_link_add_archive_symbols, which has to allow for a.out @@ -4963,8 +4943,7 @@ static bfd_boolean elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) { symindex c; - bfd_boolean *defined = NULL; - bfd_boolean *included = NULL; + unsigned char *included = NULL; carsym *symdefs; bfd_boolean loop; bfd_size_type amt; @@ -4988,11 +4967,10 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) if (c == 0) return TRUE; amt = c; - amt *= sizeof (bfd_boolean); - defined = (bfd_boolean *) bfd_zmalloc (amt); - included = (bfd_boolean *) bfd_zmalloc (amt); - if (defined == NULL || included == NULL) - goto error_return; + amt *= sizeof (*included); + included = (unsigned char *) bfd_zmalloc (amt); + if (included == NULL) + return FALSE; symdefs = bfd_ardata (abfd)->symdefs; bed = get_elf_backend_data (abfd); @@ -5017,7 +4995,7 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) struct bfd_link_hash_entry *undefs_tail; symindex mark; - if (defined[i] || included[i]) + if (included[i]) continue; if (symdef->file_offset == last) { @@ -5052,7 +5030,8 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) else if (h->root.type != bfd_link_hash_undefined) { if (h->root.type != bfd_link_hash_undefweak) - defined[i] = TRUE; + /* Symbol must be defined. Don't check it again. */ + included[i] = TRUE; continue; } @@ -5064,16 +5043,6 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) if (! bfd_check_format (element, bfd_object)) goto error_return; - /* Doublecheck that we have not included this object - already--it should be impossible, but there may be - something wrong with the archive. */ - if (element->archive_pass != 0) - { - bfd_set_error (bfd_error_bad_value); - goto error_return; - } - element->archive_pass = 1; - undefs_tail = info->hash->undefs_tail; if (!(*info->callbacks @@ -5111,14 +5080,11 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) } while (loop); - free (defined); free (included); return TRUE; error_return: - if (defined != NULL) - free (defined); if (included != NULL) free (included); return FALSE; @@ -5484,7 +5450,7 @@ _bfd_elf_size_group_sections (struct bfd_link_info *info) { bfd *ibfd; - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour && !_bfd_elf_fixup_group_sections (ibfd, bfd_abs_section_ptr)) return FALSE; @@ -5611,7 +5577,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, for (inputobj = info->input_bfds; inputobj; - inputobj = inputobj->link_next) + inputobj = inputobj->link.next) { asection *s; @@ -5877,7 +5843,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, asection *o; for (sub = info->input_bfds; sub != NULL; - sub = sub->link_next) + sub = sub->link.next) if (bfd_get_flavour (sub) == bfd_target_elf_flavour) for (o = sub->sections; o != NULL; o = o->next) if (elf_section_data (o)->this_hdr.sh_type @@ -6707,7 +6673,7 @@ _bfd_elf_merge_sections (bfd *abfd, struct bfd_link_info *info) if (!is_elf_hash_table (info->hash)) return FALSE; - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) if ((ibfd->flags & DYNAMIC) == 0) for (sec = ibfd->sections; sec != NULL; sec = sec->next) if ((sec->flags & SEC_MERGE) != 0 @@ -6897,6 +6863,7 @@ _bfd_elf_link_hash_table_create (bfd *abfd) free (ret); return NULL; } + ret->root.hash_table_free = _bfd_elf_link_hash_table_free; return &ret->root; } @@ -6904,13 +6871,15 @@ _bfd_elf_link_hash_table_create (bfd *abfd) /* Destroy an ELF linker hash table. */ void -_bfd_elf_link_hash_table_free (struct bfd_link_hash_table *hash) +_bfd_elf_link_hash_table_free (bfd *obfd) { - struct elf_link_hash_table *htab = (struct elf_link_hash_table *) hash; + struct elf_link_hash_table *htab; + + htab = (struct elf_link_hash_table *) obfd->link.hash; if (htab->dynstr != NULL) _bfd_elf_strtab_free (htab->dynstr); _bfd_merge_sections_free (htab->merge_info); - _bfd_generic_link_hash_table_free (hash); + _bfd_generic_link_hash_table_free (obfd); } /* This is a hook for the ELF emulation code in the generic linker to @@ -7468,6 +7437,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 +8656,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 { @@ -9527,7 +9513,16 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) file, so the contents field will not have been set by any of the routines which work on output files. */ if (elf_section_data (o)->this_hdr.contents != NULL) - contents = elf_section_data (o)->this_hdr.contents; + { + contents = elf_section_data (o)->this_hdr.contents; + if (bed->caches_rawsize + && o->rawsize != 0 + && o->rawsize < o->size) + { + memcpy (flinfo->contents, contents, o->rawsize); + contents = flinfo->contents; + } + } else { contents = flinfo->contents; @@ -10696,12 +10691,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) esdo->rela.count = 0; } - _bfd_elf_assign_file_positions_for_relocs (abfd); - /* We have now assigned file positions for all the sections except - .symtab and .strtab. We start the .symtab section at the current - file position, and write directly to it. We build the .strtab - section in memory. */ + .symtab, .strtab, and non-loaded reloc sections. We start the + .symtab section at the current file position, and write directly + to it. We build the .strtab section in memory. */ bfd_get_symcount (abfd) = 0; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; /* sh_name is set in prep_headers. */ @@ -10899,7 +10892,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) we could write the relocs out and then read them again; I don't know how bad the memory loss will be. */ - for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) sub->output_has_begun = FALSE; for (o = abfd->sections; o != NULL; o = o->next) { @@ -10961,7 +10954,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* Free symbol buffer if needed. */ if (!info->reduce_memory_overheads) { - for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) if (bfd_get_flavour (sub) == bfd_target_elf_flavour && elf_tdata (sub)->symbuf) { @@ -10970,17 +10963,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 +10974,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; @@ -11662,7 +11640,7 @@ _bfd_elf_gc_mark_hook (asection *sec, { bfd *i; - for (i = info->input_bfds; i; i = i->link_next) + for (i = info->input_bfds; i; i = i->link.next) { sec = bfd_get_section_by_name (i, sec_name); if (sec) @@ -11811,7 +11789,7 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info, { bfd *ibfd; - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) { asection *isec; bfd_boolean some_kept; @@ -11939,7 +11917,7 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info) unsigned long section_sym_count; struct elf_gc_sweep_symbol_info sweep_info; - for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) { asection *o; @@ -11976,7 +11954,9 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info) info we collected before. */ if (gc_sweep_hook && (o->flags & SEC_RELOC) != 0 - && o->reloc_count > 0 + && o->reloc_count != 0 + && !((info->strip == strip_all || info->strip == strip_debugger) + && (o->flags & SEC_DEBUGGING) != 0) && !bfd_is_abs_section (o->output_section)) { Elf_Internal_Rela *internal_relocs; @@ -12124,14 +12104,19 @@ bfd_boolean bfd_elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h, void *inf) { struct bfd_link_info *info = (struct bfd_link_info *) inf; + struct bfd_elf_dynamic_list *d = info->dynamic_list; if ((h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) && (h->ref_dynamic - || ((!info->executable || info->export_dynamic) - && h->def_regular + || (h->def_regular && ELF_ST_VISIBILITY (h->other) != STV_INTERNAL && ELF_ST_VISIBILITY (h->other) != STV_HIDDEN + && (!info->executable + || info->export_dynamic + || (h->dynamic + && d != NULL + && (*d->match) (&d->head, NULL, h->root.root.string))) && (strchr (h->root.root.string, ELF_VER_CHR) != NULL || !bfd_hide_sym_by_version (info->version_info, h->root.root.string))))) @@ -12172,6 +12157,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) bfd *sub; elf_gc_mark_hook_fn gc_mark_hook; const struct elf_backend_data *bed = get_elf_backend_data (abfd); + struct elf_link_hash_table *htab; if (!bed->can_gc_sections || !is_elf_hash_table (info->hash)) @@ -12181,11 +12167,11 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) } bed->gc_keep (info); + htab = elf_hash_table (info); /* Try to parse each bfd's .eh_frame section. Point elf_eh_frame_section at the .eh_frame section if we can mark the FDEs individually. */ - _bfd_elf_begin_eh_frame_parsing (info); - for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) { asection *sec; struct elf_reloc_cookie cookie; @@ -12201,31 +12187,24 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) sec = bfd_get_next_section_by_name (sec); } } - _bfd_elf_end_eh_frame_parsing (info); /* Apply transitive closure to the vtable entry usage info. */ - elf_link_hash_traverse (elf_hash_table (info), - elf_gc_propagate_vtable_entries_used, - &ok); + elf_link_hash_traverse (htab, elf_gc_propagate_vtable_entries_used, &ok); if (!ok) return FALSE; /* Kill the vtable relocations that were not used. */ - elf_link_hash_traverse (elf_hash_table (info), - elf_gc_smash_unused_vtentry_relocs, - &ok); + elf_link_hash_traverse (htab, elf_gc_smash_unused_vtentry_relocs, &ok); if (!ok) return FALSE; /* Mark dynamically referenced symbols. */ - if (elf_hash_table (info)->dynamic_sections_created) - elf_link_hash_traverse (elf_hash_table (info), - bed->gc_mark_dynamic_ref, - info); + if (htab->dynamic_sections_created) + elf_link_hash_traverse (htab, bed->gc_mark_dynamic_ref, info); /* Grovel through relocs to find out who stays ... */ gc_mark_hook = bed->gc_mark_hook; - for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) { asection *o; @@ -12534,7 +12513,7 @@ bfd_elf_gc_common_finalize_got_offsets (bfd *abfd, gotoff = bed->got_header_size; /* Do the local .got entries first. */ - for (i = info->input_bfds; i; i = i->link_next) + for (i = info->input_bfds; i; i = i->link.next) { bfd_signed_vma *local_got; bfd_size_type j, locsymcount; @@ -12623,10 +12602,10 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie) if ((h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) - && discarded_section (h->root.u.def.section)) + && (h->root.u.def.section->owner != rcookie->abfd + || h->root.u.def.section->kept_section != NULL + || discarded_section (h->root.u.def.section))) return TRUE; - else - return FALSE; } else { @@ -12639,7 +12618,9 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie) /* Need to: get the symbol; get the section. */ isym = &rcookie->locsyms[r_symndx]; isec = bfd_section_from_elf_index (rcookie->abfd, isym->st_shndx); - if (isec != NULL && discarded_section (isec)) + if (isec != NULL + && (isec->kept_section != NULL + || discarded_section (isec))) return TRUE; } return FALSE; @@ -12648,94 +12629,105 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie) } /* Discard unneeded references to discarded sections. - Returns TRUE if any section's size was changed. */ -/* This function assumes that the relocations are in sorted order, - which is true for all known assemblers. */ + Returns -1 on error, 1 if any section's size was changed, 0 if + nothing changed. This function assumes that the relocations are in + sorted order, which is true for all known assemblers. */ -bfd_boolean +int bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) { struct elf_reloc_cookie cookie; - asection *stab, *eh; - const struct elf_backend_data *bed; + asection *o; bfd *abfd; - bfd_boolean ret = FALSE; + int changed = 0; if (info->traditional_format || !is_elf_hash_table (info->hash)) - return FALSE; + return 0; - _bfd_elf_begin_eh_frame_parsing (info); - for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next) + o = bfd_get_section_by_name (output_bfd, ".stab"); + if (o != NULL) { - if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) - continue; - - bed = get_elf_backend_data (abfd); + asection *i; - eh = NULL; - if (!info->relocatable) + for (i = o->map_head.s; i != NULL; i = i->map_head.s) { - eh = bfd_get_section_by_name (abfd, ".eh_frame"); - while (eh != NULL - && (eh->size == 0 - || bfd_is_abs_section (eh->output_section))) - eh = bfd_get_next_section_by_name (eh); - } - - stab = bfd_get_section_by_name (abfd, ".stab"); - if (stab != NULL - && (stab->size == 0 - || bfd_is_abs_section (stab->output_section) - || stab->sec_info_type != SEC_INFO_TYPE_STABS)) - stab = NULL; + if (i->size == 0 + || i->reloc_count == 0 + || i->sec_info_type != SEC_INFO_TYPE_STABS) + continue; - if (stab == NULL - && eh == NULL - && bed->elf_backend_discard_info == NULL) - continue; + abfd = i->owner; + if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) + continue; - if (!init_reloc_cookie (&cookie, info, abfd)) - return FALSE; + if (!init_reloc_cookie_for_section (&cookie, info, i)) + return -1; - if (stab != NULL - && stab->reloc_count > 0 - && init_reloc_cookie_rels (&cookie, info, abfd, stab)) - { - if (_bfd_discard_section_stabs (abfd, stab, - elf_section_data (stab)->sec_info, + if (_bfd_discard_section_stabs (abfd, i, + elf_section_data (i)->sec_info, bfd_elf_reloc_symbol_deleted_p, &cookie)) - ret = TRUE; - fini_reloc_cookie_rels (&cookie, stab); + changed = 1; + + fini_reloc_cookie_for_section (&cookie, i); } + } - while (eh != NULL - && init_reloc_cookie_rels (&cookie, info, abfd, eh)) + o = bfd_get_section_by_name (output_bfd, ".eh_frame"); + if (o != NULL) + { + asection *i; + + for (i = o->map_head.s; i != NULL; i = i->map_head.s) { - _bfd_elf_parse_eh_frame (abfd, info, eh, &cookie); - if (_bfd_elf_discard_section_eh_frame (abfd, info, eh, + if (i->size == 0) + continue; + + abfd = i->owner; + if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) + continue; + + if (!init_reloc_cookie_for_section (&cookie, info, i)) + return -1; + + _bfd_elf_parse_eh_frame (abfd, info, i, &cookie); + if (_bfd_elf_discard_section_eh_frame (abfd, info, i, bfd_elf_reloc_symbol_deleted_p, &cookie)) - ret = TRUE; - fini_reloc_cookie_rels (&cookie, eh); - eh = bfd_get_next_section_by_name (eh); + changed = 1; + + fini_reloc_cookie_for_section (&cookie, i); } + } - if (bed->elf_backend_discard_info != NULL - && (*bed->elf_backend_discard_info) (abfd, &cookie, info)) - ret = TRUE; + for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next) + { + const struct elf_backend_data *bed; + + if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) + continue; + + bed = get_elf_backend_data (abfd); - fini_reloc_cookie (&cookie, abfd); + if (bed->elf_backend_discard_info != NULL) + { + if (!init_reloc_cookie (&cookie, info, abfd)) + return -1; + + if ((*bed->elf_backend_discard_info) (abfd, &cookie, info)) + changed = 1; + + fini_reloc_cookie (&cookie, abfd); + } } - _bfd_elf_end_eh_frame_parsing (info); if (info->eh_frame_hdr && !info->relocatable && _bfd_elf_discard_section_eh_frame_hdr (output_bfd, info)) - ret = TRUE; + changed = 1; - return ret; + return changed; } bfd_boolean @@ -13019,17 +13011,24 @@ _bfd_elf_make_dynamic_reloc_section (asection * sec, return reloc_sec; } -/* Copy the ELF symbol type associated with a linker hash entry. */ +/* Copy the ELF symbol type and other attributes for a linker script + assignment from HSRC to HDEST. Generally this should be treated as + if we found a strong non-dynamic definition for HDEST (except that + ld ignores multiple definition errors). */ void -_bfd_elf_copy_link_hash_symbol_type (bfd *abfd ATTRIBUTE_UNUSED, - struct bfd_link_hash_entry * hdest, - struct bfd_link_hash_entry * hsrc) +_bfd_elf_copy_link_hash_symbol_type (bfd *abfd, + struct bfd_link_hash_entry *hdest, + struct bfd_link_hash_entry *hsrc) { - struct elf_link_hash_entry *ehdest = (struct elf_link_hash_entry *)hdest; - struct elf_link_hash_entry *ehsrc = (struct elf_link_hash_entry *)hsrc; + struct elf_link_hash_entry *ehdest = (struct elf_link_hash_entry *) hdest; + struct elf_link_hash_entry *ehsrc = (struct elf_link_hash_entry *) hsrc; + Elf_Internal_Sym isym; ehdest->type = ehsrc->type; ehdest->target_internal = ehsrc->target_internal; + + isym.st_other = ehsrc->other; + elf_merge_st_other (abfd, ehdest, &isym, TRUE, FALSE); } /* Append a RELA relocation REL to section S in BFD. */