| Index: bfd/elflink.c
|
| diff --git a/bfd/elflink.c b/bfd/elflink.c
|
| index 574b6e29497f7ea3314012df3cd51c496661b4e0..6fa62f9b0bec20106c3f7fa50c4d33b42c9607ce 100644
|
| --- a/bfd/elflink.c
|
| +++ b/bfd/elflink.c
|
| @@ -1,7 +1,5 @@
|
| /* ELF linking support for BFD.
|
| - Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
| - 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
|
| - Free Software Foundation, Inc.
|
| + Copyright 1995-2013 Free Software Foundation, Inc.
|
|
|
| This file is part of BFD, the Binary File Descriptor library.
|
|
|
| @@ -87,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);
|
| @@ -187,6 +186,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
|
| flagword flags;
|
| asection *s;
|
| const struct elf_backend_data *bed;
|
| + struct elf_link_hash_entry *h;
|
|
|
| if (! is_elf_hash_table (info->hash))
|
| return FALSE;
|
| @@ -254,7 +254,9 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
|
| section. We don't want to define it if there is no .dynamic
|
| section, since on some ELF platforms the start up code examines it
|
| to decide how to initialize the process. */
|
| - if (!_bfd_elf_define_linkage_sym (abfd, info, s, "_DYNAMIC"))
|
| + h = _bfd_elf_define_linkage_sym (abfd, info, s, "_DYNAMIC");
|
| + elf_hash_table (info)->hdynamic = h;
|
| + if (h == NULL)
|
| return FALSE;
|
|
|
| if (info->emit_hash)
|
| @@ -569,10 +571,11 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
|
|
|
| h->def_regular = 1;
|
|
|
| - if (provide && hidden)
|
| + if (hidden)
|
| {
|
| bed = get_elf_backend_data (output_bfd);
|
| - 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->elf_backend_hide_symbol) (info, h, TRUE);
|
| }
|
|
|
| @@ -892,54 +895,30 @@ elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h,
|
| }
|
| }
|
|
|
| -/* Mark if a symbol has a definition in a dynamic object or is
|
| - weak in all dynamic objects. */
|
| -
|
| -static void
|
| -_bfd_elf_mark_dynamic_def_weak (struct elf_link_hash_entry *h,
|
| - asection *sec, int bind)
|
| -{
|
| - if (!h->dynamic_def)
|
| - {
|
| - if (!bfd_is_und_section (sec))
|
| - h->dynamic_def = 1;
|
| - else
|
| - {
|
| - /* Check if this symbol is weak in all dynamic objects. If it
|
| - is the first time we see it in a dynamic object, we mark
|
| - if it is weak. Otherwise, we clear it. */
|
| - if (!h->ref_dynamic)
|
| - {
|
| - if (bind == STB_WEAK)
|
| - h->dynamic_weak = 1;
|
| - }
|
| - else if (bind != STB_WEAK)
|
| - h->dynamic_weak = 0;
|
| - }
|
| - }
|
| -}
|
| -
|
| -/* This function is called when we want to define a new symbol. It
|
| - handles the various cases which arise when we find a definition in
|
| - a dynamic object, or when there is already a definition in a
|
| - dynamic object. The new symbol is described by NAME, SYM, PSEC,
|
| - and PVALUE. We set SYM_HASH to the hash table entry. We set
|
| - OVERRIDE if the old symbol is overriding a new definition. We set
|
| - TYPE_CHANGE_OK if it is OK for the type to change. We set
|
| - SIZE_CHANGE_OK if it is OK for the size to change. By OK to
|
| - change, we mean that we shouldn't warn if the type or size does
|
| - change. We set POLD_ALIGNMENT if an old common symbol in a dynamic
|
| - object is overridden by a regular object. */
|
| +/* This function is called when we want to merge a new symbol with an
|
| + existing symbol. It handles the various cases which arise when we
|
| + find a definition in a dynamic object, or when there is already a
|
| + definition in a dynamic object. The new symbol is described by
|
| + NAME, SYM, PSEC, and PVALUE. We set SYM_HASH to the hash table
|
| + entry. We set POLDBFD to the old symbol's BFD. We set POLD_WEAK
|
| + if the old symbol was weak. We set POLD_ALIGNMENT to the alignment
|
| + of an old common symbol. We set OVERRIDE if the old symbol is
|
| + overriding a new definition. We set TYPE_CHANGE_OK if it is OK for
|
| + the type to change. We set SIZE_CHANGE_OK if it is OK for the size
|
| + to change. By OK to change, we mean that we shouldn't warn if the
|
| + type or size does change. */
|
|
|
| -bfd_boolean
|
| +static bfd_boolean
|
| _bfd_elf_merge_symbol (bfd *abfd,
|
| struct bfd_link_info *info,
|
| const char *name,
|
| Elf_Internal_Sym *sym,
|
| asection **psec,
|
| bfd_vma *pvalue,
|
| - unsigned int *pold_alignment,
|
| struct elf_link_hash_entry **sym_hash,
|
| + bfd **poldbfd,
|
| + bfd_boolean *pold_weak,
|
| + unsigned int *pold_alignment,
|
| bfd_boolean *skip,
|
| bfd_boolean *override,
|
| bfd_boolean *type_change_ok,
|
| @@ -961,15 +940,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
| sec = *psec;
|
| bind = ELF_ST_BIND (sym->st_info);
|
|
|
| - /* Silently discard TLS symbols from --just-syms. There's no way to
|
| - combine a static TLS block with a new TLS block for this executable. */
|
| - if (ELF_ST_TYPE (sym->st_info) == STT_TLS
|
| - && sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
|
| - {
|
| - *skip = TRUE;
|
| - return TRUE;
|
| - }
|
| -
|
| if (! bfd_is_und_section (sec))
|
| h = elf_link_hash_lookup (elf_hash_table (info), name, TRUE, FALSE, FALSE);
|
| else
|
| @@ -981,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;
|
| @@ -993,35 +958,19 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
| || h->root.type == bfd_link_hash_warning)
|
| h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
|
|
| - /* We have to check it for every instance since the first few may be
|
| - refereences and not all compilers emit symbol type for undefined
|
| - symbols. */
|
| - bfd_elf_link_mark_dynamic_symbol (info, h, sym);
|
| -
|
| - /* If we just created the symbol, mark it as being an ELF symbol.
|
| - Other than that, there is nothing to do--there is no merge issue
|
| - with a newly defined symbol--so we just return. */
|
| -
|
| - if (h->root.type == bfd_link_hash_new)
|
| - {
|
| - h->non_elf = 0;
|
| - return TRUE;
|
| - }
|
| -
|
| /* OLDBFD and OLDSEC are a BFD and an ASECTION associated with the
|
| existing symbol. */
|
|
|
| + oldbfd = NULL;
|
| + oldsec = NULL;
|
| 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:
|
| @@ -1033,13 +982,68 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
| 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. */
|
| + bfd_elf_link_mark_dynamic_symbol (info, h, sym);
|
| +
|
| + /* NEWDYN and OLDDYN indicate whether the new or old symbol,
|
| + respectively, is from a dynamic object. */
|
| +
|
| + newdyn = (abfd->flags & DYNAMIC) != 0;
|
| +
|
| + /* ref_dynamic_nonweak and dynamic_def flags track actual undefined
|
| + syms and defined syms in dynamic libraries respectively.
|
| + ref_dynamic on the other hand can be set for a symbol defined in
|
| + a dynamic library, and def_dynamic may not be set; When the
|
| + definition in a dynamic lib is overridden by a definition in the
|
| + executable use of the symbol in the dynamic lib becomes a
|
| + reference to the executable symbol. */
|
| + if (newdyn)
|
| + {
|
| + if (bfd_is_und_section (sec))
|
| + {
|
| + if (bind != STB_WEAK)
|
| + {
|
| + h->ref_dynamic_nonweak = 1;
|
| + hi->ref_dynamic_nonweak = 1;
|
| + }
|
| + }
|
| + else
|
| + {
|
| + h->dynamic_def = 1;
|
| + hi->dynamic_def = 1;
|
| + }
|
| + }
|
| +
|
| + /* If we just created the symbol, mark it as being an ELF symbol.
|
| + Other than that, there is nothing to do--there is no merge issue
|
| + with a newly defined symbol--so we just return. */
|
| +
|
| + if (h->root.type == bfd_link_hash_new)
|
| + {
|
| + h->non_elf = 0;
|
| + return TRUE;
|
| + }
|
|
|
| /* In cases involving weak versioned symbols, we may wind up trying
|
| to merge a symbol with itself. Catch that here, to avoid the
|
| @@ -1053,11 +1057,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
| || !h->def_regular))
|
| return TRUE;
|
|
|
| - /* NEWDYN and OLDDYN indicate whether the new or old symbol,
|
| - respectively, is from a dynamic object. */
|
| -
|
| - newdyn = (abfd->flags & DYNAMIC) != 0;
|
| -
|
| olddyn = FALSE;
|
| if (oldbfd != NULL)
|
| olddyn = (oldbfd->flags & DYNAMIC) != 0;
|
| @@ -1142,35 +1141,29 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
|
|
| if (tdef && ntdef)
|
| (*_bfd_error_handler)
|
| - (_("%s: TLS definition in %B section %A mismatches non-TLS definition in %B section %A"),
|
| + (_("%s: TLS definition in %B section %A "
|
| + "mismatches non-TLS definition in %B section %A"),
|
| tbfd, tsec, ntbfd, ntsec, h->root.root.string);
|
| else if (!tdef && !ntdef)
|
| (*_bfd_error_handler)
|
| - (_("%s: TLS reference in %B mismatches non-TLS reference in %B"),
|
| + (_("%s: TLS reference in %B "
|
| + "mismatches non-TLS reference in %B"),
|
| tbfd, ntbfd, h->root.root.string);
|
| else if (tdef)
|
| (*_bfd_error_handler)
|
| - (_("%s: TLS definition in %B section %A mismatches non-TLS reference in %B"),
|
| + (_("%s: TLS definition in %B section %A "
|
| + "mismatches non-TLS reference in %B"),
|
| tbfd, tsec, ntbfd, h->root.root.string);
|
| else
|
| (*_bfd_error_handler)
|
| - (_("%s: TLS reference in %B mismatches non-TLS definition in %B section %A"),
|
| + (_("%s: TLS reference in %B "
|
| + "mismatches non-TLS definition in %B section %A"),
|
| tbfd, ntbfd, ntsec, h->root.root.string);
|
|
|
| bfd_set_error (bfd_error_bad_value);
|
| return FALSE;
|
| }
|
|
|
| - /* We need to remember if a symbol has a definition in a dynamic
|
| - object or is weak in all dynamic objects. Internal and hidden
|
| - visibility will make it unavailable to dynamic objects. */
|
| - if (newdyn)
|
| - {
|
| - _bfd_elf_mark_dynamic_def_weak (h, sec, bind);
|
| - if (h != hi)
|
| - _bfd_elf_mark_dynamic_def_weak (hi, sec, bind);
|
| - }
|
| -
|
| /* If the old symbol has non-default visibility, we ignore the new
|
| definition from a dynamic object. */
|
| if (newdyn
|
| @@ -1197,7 +1190,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
| /* If the new symbol with non-default visibility comes from a
|
| relocatable file and the old definition comes from a dynamic
|
| object, we remove the old definition. */
|
| - if ((*sym_hash)->root.type == bfd_link_hash_indirect)
|
| + if (hi->root.type == bfd_link_hash_indirect)
|
| {
|
| /* Handle the case where the old dynamic definition is
|
| default versioned. We need to copy the symbol info from
|
| @@ -1205,32 +1198,31 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
| was referenced before. */
|
| if (h->ref_regular)
|
| {
|
| - struct elf_link_hash_entry *vh = *sym_hash;
|
| -
|
| - vh->root.type = h->root.type;
|
| + hi->root.type = h->root.type;
|
| h->root.type = bfd_link_hash_indirect;
|
| - (*bed->elf_backend_copy_indirect_symbol) (info, vh, h);
|
| - /* Protected symbols will override the dynamic definition
|
| - with default version. */
|
| - if (ELF_ST_VISIBILITY (sym->st_other) == STV_PROTECTED)
|
| + (*bed->elf_backend_copy_indirect_symbol) (info, hi, h);
|
| +
|
| + h->root.u.i.link = (struct bfd_link_hash_entry *) hi;
|
| + if (ELF_ST_VISIBILITY (sym->st_other) != STV_PROTECTED)
|
| {
|
| - h->root.u.i.link = (struct bfd_link_hash_entry *) vh;
|
| - vh->dynamic_def = 1;
|
| - vh->ref_dynamic = 1;
|
| + /* If the new symbol is hidden or internal, completely undo
|
| + any dynamic link state. */
|
| + (*bed->elf_backend_hide_symbol) (info, h, TRUE);
|
| + h->forced_local = 0;
|
| + h->ref_dynamic = 0;
|
| }
|
| else
|
| - {
|
| - h->root.type = vh->root.type;
|
| - vh->ref_dynamic = 0;
|
| - /* We have to hide it here since it was made dynamic
|
| - global with extra bits when the symbol info was
|
| - copied from the old dynamic definition. */
|
| - (*bed->elf_backend_hide_symbol) (info, vh, TRUE);
|
| - }
|
| - h = vh;
|
| + h->ref_dynamic = 1;
|
| +
|
| + h->def_dynamic = 0;
|
| + /* FIXME: Should we check type and size for protected symbol? */
|
| + h->size = 0;
|
| + h->type = 0;
|
| +
|
| + h = hi;
|
| }
|
| else
|
| - h = *sym_hash;
|
| + h = hi;
|
| }
|
|
|
| /* If the old symbol was undefined before, then it will still be
|
| @@ -1262,16 +1254,12 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
| else
|
| h->ref_dynamic = 1;
|
| h->def_dynamic = 0;
|
| - h->dynamic_def = 0;
|
| /* FIXME: Should we check type and size for protected symbol? */
|
| h->size = 0;
|
| h->type = 0;
|
| return TRUE;
|
| }
|
|
|
| - if (bind == STB_GNU_UNIQUE)
|
| - h->unique_global = 1;
|
| -
|
| /* If a new weak symbol definition comes from a regular file and the
|
| old symbol comes from a dynamic library, we treat the new one as
|
| strong. Similarly, an old weak symbol definition from a regular
|
| @@ -1357,15 +1345,12 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
|
|
| /* We now know everything about the old and new symbols. We ask the
|
| backend to check if we can merge them. */
|
| - if (bed->merge_symbol
|
| - && !bed->merge_symbol (info, sym_hash, h, sym, psec, pvalue,
|
| - pold_alignment, skip, override,
|
| - type_change_ok, size_change_ok,
|
| - &newdyn, &newdef, &newdyncommon, &newweak,
|
| - abfd, &sec,
|
| - &olddyn, &olddef, &olddyncommon, &oldweak,
|
| - oldbfd, &oldsec))
|
| - return FALSE;
|
| + if (bed->merge_symbol != NULL)
|
| + {
|
| + if (!bed->merge_symbol (h, sym, psec, newdef, olddef, oldbfd, oldsec))
|
| + return FALSE;
|
| + sec = *psec;
|
| + }
|
|
|
| /* If both the old and the new symbols look like common symbols in a
|
| dynamic object, set the size of the symbol to the larger of the
|
| @@ -1514,8 +1499,8 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
| *type_change_ok = TRUE;
|
| }
|
|
|
| - if ((*sym_hash)->root.type == bfd_link_hash_indirect)
|
| - flip = *sym_hash;
|
| + if (hi->root.type == bfd_link_hash_indirect)
|
| + flip = hi;
|
| else
|
| /* This union may have been set to be non-NULL when this symbol
|
| was seen in a dynamic object. We must force the union to be
|
| @@ -1560,8 +1545,8 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
| *size_change_ok = TRUE;
|
| *type_change_ok = TRUE;
|
|
|
| - if ((*sym_hash)->root.type == bfd_link_hash_indirect)
|
| - flip = *sym_hash;
|
| + if (hi->root.type == bfd_link_hash_indirect)
|
| + flip = hi;
|
| else
|
| h->verinfo.vertree = NULL;
|
| }
|
| @@ -1588,7 +1573,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
|
|
| /* This function is called to create an indirect symbol from the
|
| default for the symbol with the default version if needed. The
|
| - symbol is described by H, NAME, SYM, PSEC, VALUE, and OVERRIDE. We
|
| + symbol is described by H, NAME, SYM, SEC, and VALUE. We
|
| set DYNSYM if the new indirect symbol is dynamic. */
|
|
|
| static bfd_boolean
|
| @@ -1597,10 +1582,10 @@ _bfd_elf_add_default_symbol (bfd *abfd,
|
| struct elf_link_hash_entry *h,
|
| const char *name,
|
| Elf_Internal_Sym *sym,
|
| - asection **psec,
|
| - bfd_vma *value,
|
| - bfd_boolean *dynsym,
|
| - bfd_boolean override)
|
| + asection *sec,
|
| + bfd_vma value,
|
| + bfd **poldbfd,
|
| + bfd_boolean *dynsym)
|
| {
|
| bfd_boolean type_change_ok;
|
| bfd_boolean size_change_ok;
|
| @@ -1611,9 +1596,10 @@ _bfd_elf_add_default_symbol (bfd *abfd,
|
| const struct elf_backend_data *bed;
|
| bfd_boolean collect;
|
| bfd_boolean dynamic;
|
| + bfd_boolean override;
|
| char *p;
|
| size_t len, shortlen;
|
| - asection *sec;
|
| + asection *tmp_sec;
|
|
|
| /* If this symbol has a version, and it is the default version, we
|
| create an indirect symbol from the default name to the fully
|
| @@ -1623,24 +1609,6 @@ _bfd_elf_add_default_symbol (bfd *abfd,
|
| if (p == NULL || p[1] != ELF_VER_CHR)
|
| return TRUE;
|
|
|
| - if (override)
|
| - {
|
| - /* We are overridden by an old definition. We need to check if we
|
| - need to create the indirect symbol from the default name. */
|
| - hi = elf_link_hash_lookup (elf_hash_table (info), name, TRUE,
|
| - FALSE, FALSE);
|
| - BFD_ASSERT (hi != NULL);
|
| - if (hi == h)
|
| - return TRUE;
|
| - while (hi->root.type == bfd_link_hash_indirect
|
| - || hi->root.type == bfd_link_hash_warning)
|
| - {
|
| - hi = (struct elf_link_hash_entry *) hi->root.u.i.link;
|
| - if (hi == h)
|
| - return TRUE;
|
| - }
|
| - }
|
| -
|
| bed = get_elf_backend_data (abfd);
|
| collect = bed->collect;
|
| dynamic = (abfd->flags & DYNAMIC) != 0;
|
| @@ -1658,9 +1626,9 @@ _bfd_elf_add_default_symbol (bfd *abfd,
|
| actually going to define an indirect symbol. */
|
| type_change_ok = FALSE;
|
| size_change_ok = FALSE;
|
| - sec = *psec;
|
| - if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
|
| - NULL, &hi, &skip, &override,
|
| + tmp_sec = sec;
|
| + if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &tmp_sec, &value,
|
| + &hi, poldbfd, NULL, NULL, &skip, &override,
|
| &type_change_ok, &size_change_ok))
|
| return FALSE;
|
|
|
| @@ -1734,6 +1702,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)
|
| @@ -1767,9 +1741,9 @@ nondefault:
|
| /* Once again, merge with any existing symbol. */
|
| type_change_ok = FALSE;
|
| size_change_ok = FALSE;
|
| - sec = *psec;
|
| - if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
|
| - NULL, &hi, &skip, &override,
|
| + tmp_sec = sec;
|
| + if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &tmp_sec, &value,
|
| + &hi, NULL, NULL, NULL, &skip, &override,
|
| &type_change_ok, &size_change_ok))
|
| return FALSE;
|
|
|
| @@ -1803,6 +1777,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. */
|
| @@ -2501,7 +2477,7 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
|
| && !h->def_regular
|
| && h->ref_regular
|
| && !h->def_dynamic
|
| - && (h->root.u.def.section->owner->flags & DYNAMIC) == 0)
|
| + && (h->root.u.def.section->owner->flags & (DYNAMIC | BFD_PLUGIN)) == 0)
|
| h->def_regular = 1;
|
|
|
| /* If -Bsymbolic was used (which means to bind references to global
|
| @@ -3083,19 +3059,17 @@ elf_add_dt_needed_tag (bfd *abfd,
|
| bfd_boolean do_it)
|
| {
|
| struct elf_link_hash_table *hash_table;
|
| - bfd_size_type oldsize;
|
| bfd_size_type strindex;
|
|
|
| if (!_bfd_elf_link_create_dynstrtab (abfd, info))
|
| return -1;
|
|
|
| hash_table = elf_hash_table (info);
|
| - oldsize = _bfd_elf_strtab_size (hash_table->dynstr);
|
| strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, FALSE);
|
| if (strindex == (bfd_size_type) -1)
|
| return -1;
|
|
|
| - if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr))
|
| + if (_bfd_elf_strtab_refcount (hash_table->dynstr, strindex) != 1)
|
| {
|
| asection *sdyn;
|
| const struct elf_backend_data *bed;
|
| @@ -3343,6 +3317,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
|
| @@ -3372,13 +3358,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);
|
| @@ -3420,75 +3406,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 += sizeof ".gnu.warning." - 1;
|
|
|
| - name = bfd_get_section_name (abfd, s);
|
| - if (CONST_STRNEQ (name, ".gnu.warning."))
|
| + /* 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;
|
| }
|
| }
|
| }
|
| @@ -3514,7 +3489,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;
|
| @@ -3704,7 +3678,7 @@ error_free_dyn:
|
| return TRUE;
|
|
|
| /* Save the DT_AUDIT entry for the linker emulation code. */
|
| - elf_dt_audit (abfd) = audit;
|
| + elf_dt_audit (abfd) = audit;
|
| }
|
|
|
| /* If this is a dynamic object, we always link against the .dynsym
|
| @@ -3733,7 +3707,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,
|
| @@ -3741,13 +3715,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)
|
| @@ -3797,8 +3774,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;
|
|
|
| @@ -3810,22 +3786,20 @@ 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;
|
| old_size = htab->root.table.size;
|
| old_count = htab->root.table.count;
|
| old_dynsymcount = htab->dynsymcount;
|
| + old_dynstr_size = _bfd_elf_strtab_size (htab->dynstr);
|
|
|
| for (i = 0; i < htab->root.table.size; i++)
|
| {
|
| @@ -3863,18 +3837,18 @@ error_free_dyn:
|
| bfd_boolean size_change_ok;
|
| bfd_boolean type_change_ok;
|
| bfd_boolean new_weakdef;
|
| + bfd_boolean new_weak;
|
| + bfd_boolean old_weak;
|
| bfd_boolean override;
|
| bfd_boolean common;
|
| unsigned int old_alignment;
|
| bfd *old_bfd;
|
| - bfd * undef_bfd = NULL;
|
|
|
| override = FALSE;
|
|
|
| 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);
|
| @@ -3987,6 +3961,13 @@ error_free_dyn:
|
| goto error_free_vers;
|
| }
|
|
|
| + /* Silently discard TLS symbols from --just-syms. There's
|
| + no way to combine a static TLS block with a new TLS block
|
| + for this executable. */
|
| + if (ELF_ST_TYPE (isym->st_info) == STT_TLS
|
| + && sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
|
| + continue;
|
| +
|
| if (bfd_is_und_section (sec)
|
| || bfd_is_com_section (sec))
|
| definition = FALSE;
|
| @@ -3995,6 +3976,7 @@ error_free_dyn:
|
|
|
| size_change_ok = FALSE;
|
| type_change_ok = bed->type_change_ok;
|
| + old_weak = FALSE;
|
| old_alignment = 0;
|
| old_bfd = NULL;
|
| new_sec = sec;
|
| @@ -4005,20 +3987,6 @@ error_free_dyn:
|
| unsigned int vernum = 0;
|
| bfd_boolean skip;
|
|
|
| - /* If this is a definition of a symbol which was previously
|
| - referenced in a non-weak manner then make a note of the bfd
|
| - that contained the reference. This is used if we need to
|
| - refer to the source of the reference later on. */
|
| - if (! bfd_is_und_section (sec))
|
| - {
|
| - h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, FALSE);
|
| -
|
| - if (h != NULL
|
| - && h->root.type == bfd_link_hash_undefined
|
| - && h->root.u.undef.abfd)
|
| - undef_bfd = h->root.u.undef.abfd;
|
| - }
|
| -
|
| if (ever == NULL)
|
| {
|
| if (info->default_imported_symver)
|
| @@ -4126,22 +4094,9 @@ error_free_dyn:
|
| name = newname;
|
| }
|
|
|
| - /* If necessary, make a second attempt to locate the bfd
|
| - containing an unresolved, non-weak reference to the
|
| - current symbol. */
|
| - if (! bfd_is_und_section (sec) && undef_bfd == NULL)
|
| - {
|
| - h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, FALSE);
|
| -
|
| - if (h != NULL
|
| - && h->root.type == bfd_link_hash_undefined
|
| - && h->root.u.undef.abfd)
|
| - undef_bfd = h->root.u.undef.abfd;
|
| - }
|
| -
|
| - if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec,
|
| - &value, &old_alignment,
|
| - sym_hash, &skip, &override,
|
| + if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec, &value,
|
| + sym_hash, &old_bfd, &old_weak,
|
| + &old_alignment, &skip, &override,
|
| &type_change_ok, &size_change_ok))
|
| goto error_free_vers;
|
|
|
| @@ -4156,30 +4111,7 @@ error_free_dyn:
|
| || h->root.type == bfd_link_hash_warning)
|
| h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
|
|
| - /* Remember the old alignment if this is a common symbol, so
|
| - that we don't reduce the alignment later on. We can't
|
| - check later, because _bfd_generic_link_add_one_symbol
|
| - will set a default for the alignment which we want to
|
| - override. We also remember the old bfd where the existing
|
| - definition comes from. */
|
| - switch (h->root.type)
|
| - {
|
| - default:
|
| - break;
|
| -
|
| - case bfd_link_hash_defined:
|
| - case bfd_link_hash_defweak:
|
| - old_bfd = h->root.u.def.section->owner;
|
| - break;
|
| -
|
| - case bfd_link_hash_common:
|
| - old_bfd = h->root.u.c.p->section->owner;
|
| - old_alignment = h->root.u.c.p->alignment_power;
|
| - break;
|
| - }
|
| -
|
| if (elf_tdata (abfd)->verdef != NULL
|
| - && ! override
|
| && vernum > 1
|
| && definition)
|
| h->verinfo.verdef = &elf_tdata (abfd)->verdef[vernum - 1];
|
| @@ -4199,13 +4131,12 @@ error_free_dyn:
|
| h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
|
|
| *sym_hash = h;
|
| - if (is_elf_hash_table (htab))
|
| - h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
|
|
|
| + new_weak = (flags & BSF_WEAK) != 0;
|
| new_weakdef = FALSE;
|
| if (dynamic
|
| && definition
|
| - && (flags & BSF_WEAK) != 0
|
| + && new_weak
|
| && !bed->is_function_type (ELF_ST_TYPE (isym->st_info))
|
| && is_elf_hash_table (htab)
|
| && h->u.weakdef == NULL)
|
| @@ -4249,7 +4180,73 @@ error_free_dyn:
|
|
|
| if (is_elf_hash_table (htab))
|
| {
|
| - bfd_boolean dynsym;
|
| + /* Set a flag in the hash table entry indicating the type of
|
| + reference or definition we just found. A dynamic symbol
|
| + is one which is referenced or defined by both a regular
|
| + object and a shared object. */
|
| + bfd_boolean dynsym = FALSE;
|
| +
|
| + /* Plugin symbols aren't normal. Don't set def_regular or
|
| + ref_regular for them, or make them dynamic. */
|
| + if ((abfd->flags & BFD_PLUGIN) != 0)
|
| + ;
|
| + else if (! dynamic)
|
| + {
|
| + if (! definition)
|
| + {
|
| + h->ref_regular = 1;
|
| + if (bind != STB_WEAK)
|
| + h->ref_regular_nonweak = 1;
|
| + }
|
| + else
|
| + {
|
| + h->def_regular = 1;
|
| + if (h->def_dynamic)
|
| + {
|
| + h->def_dynamic = 0;
|
| + h->ref_dynamic = 1;
|
| + }
|
| + }
|
| +
|
| + /* If the indirect symbol has been forced local, don't
|
| + make the real symbol dynamic. */
|
| + if ((h == hi || !hi->forced_local)
|
| + && (! info->executable
|
| + || h->def_dynamic
|
| + || h->ref_dynamic))
|
| + dynsym = TRUE;
|
| + }
|
| + else
|
| + {
|
| + if (! definition)
|
| + {
|
| + h->ref_dynamic = 1;
|
| + hi->ref_dynamic = 1;
|
| + }
|
| + else
|
| + {
|
| + h->def_dynamic = 1;
|
| + hi->def_dynamic = 1;
|
| + }
|
| +
|
| + /* If the indirect symbol has been forced local, don't
|
| + make the real symbol dynamic. */
|
| + if ((h == hi || !hi->forced_local)
|
| + && (h->def_regular
|
| + || h->ref_regular
|
| + || (h->u.weakdef != NULL
|
| + && ! new_weakdef
|
| + && h->u.weakdef->dynindx != -1)))
|
| + dynsym = TRUE;
|
| + }
|
| +
|
| + /* Check to see if we need to add an indirect symbol for
|
| + the default name. */
|
| + if (definition
|
| + || (!override && h->root.type == bfd_link_hash_common))
|
| + if (!_bfd_elf_add_default_symbol (abfd, info, h, name, isym,
|
| + sec, value, &old_bfd, &dynsym))
|
| + goto error_free_vers;
|
|
|
| /* Check the alignment when a common symbol is involved. This
|
| can change when a common symbol is overridden by a normal
|
| @@ -4265,6 +4262,9 @@ error_free_dyn:
|
| bfd *normal_bfd;
|
| bfd *common_bfd;
|
|
|
| + BFD_ASSERT (h->root.type == bfd_link_hash_defined
|
| + || h->root.type == bfd_link_hash_defweak);
|
| +
|
| symbol_align = ffs (h->root.u.def.value) - 1;
|
| if (h->root.u.def.section->owner != NULL
|
| && (h->root.u.def.section->owner->flags & DYNAMIC) == 0)
|
| @@ -4294,8 +4294,8 @@ error_free_dyn:
|
| /* PR binutils/2735 */
|
| if (normal_bfd == NULL)
|
| (*_bfd_error_handler)
|
| - (_("Warning: alignment %u of common symbol `%s' in %B"
|
| - " is greater than the alignment (%u) of its section %A"),
|
| + (_("Warning: alignment %u of common symbol `%s' in %B is"
|
| + " greater than the alignment (%u) of its section %A"),
|
| common_bfd, h->root.u.def.section,
|
| 1 << common_align, name, 1 << normal_align);
|
| else
|
| @@ -4308,7 +4308,8 @@ error_free_dyn:
|
| }
|
|
|
| /* Remember the symbol size if it isn't undefined. */
|
| - if ((isym->st_size != 0 && isym->st_shndx != SHN_UNDEF)
|
| + if (isym->st_size != 0
|
| + && isym->st_shndx != SHN_UNDEF
|
| && (definition || h->size == 0))
|
| {
|
| if (h->size != 0
|
| @@ -4328,13 +4329,15 @@ error_free_dyn:
|
| to be the size of the common symbol. The code just above
|
| won't fix the size if a common symbol becomes larger. We
|
| don't warn about a size change here, because that is
|
| - covered by --warn-common. Allow changed between different
|
| + covered by --warn-common. Allow changes between different
|
| function types. */
|
| if (h->root.type == bfd_link_hash_common)
|
| h->size = h->root.u.c.size;
|
|
|
| if (ELF_ST_TYPE (isym->st_info) != STT_NOTYPE
|
| - && (definition || h->type == STT_NOTYPE))
|
| + && ((definition && !new_weak)
|
| + || (old_weak && h->root.type == bfd_link_hash_common)
|
| + || h->type == STT_NOTYPE))
|
| {
|
| unsigned int type = ELF_ST_TYPE (isym->st_info);
|
|
|
| @@ -4359,64 +4362,6 @@ error_free_dyn:
|
| /* Merge st_other field. */
|
| elf_merge_st_other (abfd, h, isym, definition, dynamic);
|
|
|
| - /* Set a flag in the hash table entry indicating the type of
|
| - reference or definition we just found. Keep a count of
|
| - the number of dynamic symbols we find. A dynamic symbol
|
| - is one which is referenced or defined by both a regular
|
| - object and a shared object. */
|
| - dynsym = FALSE;
|
| - if (! dynamic)
|
| - {
|
| - if (! definition)
|
| - {
|
| - h->ref_regular = 1;
|
| - if (bind != STB_WEAK)
|
| - h->ref_regular_nonweak = 1;
|
| - }
|
| - else
|
| - {
|
| - h->def_regular = 1;
|
| - if (h->def_dynamic)
|
| - {
|
| - h->def_dynamic = 0;
|
| - h->ref_dynamic = 1;
|
| - }
|
| - }
|
| -
|
| - /* If the indirect symbol has been forced local, don't
|
| - make the real symbol dynamic. */
|
| - if ((h == hi || !hi->forced_local)
|
| - && (! info->executable
|
| - || h->def_dynamic
|
| - || h->ref_dynamic))
|
| - dynsym = TRUE;
|
| - }
|
| - else
|
| - {
|
| - if (! definition)
|
| - {
|
| - h->ref_dynamic = 1;
|
| - hi->ref_dynamic = 1;
|
| - }
|
| - else
|
| - {
|
| - h->def_dynamic = 1;
|
| - h->dynamic_def = 1;
|
| - hi->def_dynamic = 1;
|
| - hi->dynamic_def = 1;
|
| - }
|
| -
|
| - /* If the indirect symbol has been forced local, don't
|
| - make the real symbol dynamic. */
|
| - if ((h == hi || !hi->forced_local)
|
| - && (h->def_regular
|
| - || h->ref_regular
|
| - || (h->u.weakdef != NULL
|
| - && ! new_weakdef
|
| - && h->u.weakdef->dynindx != -1)))
|
| - dynsym = TRUE;
|
| - }
|
| -
|
| /* We don't want to make debug symbol dynamic. */
|
| if (definition && (sec->flags & SEC_DEBUGGING) && !info->relocatable)
|
| dynsym = FALSE;
|
| @@ -4426,15 +4371,10 @@ error_free_dyn:
|
| dynsym = FALSE;
|
|
|
| if (definition)
|
| - h->target_internal = isym->st_target_internal;
|
| -
|
| - /* Check to see if we need to add an indirect symbol for
|
| - the default name. */
|
| - if (definition || h->root.type == bfd_link_hash_common)
|
| - if (!_bfd_elf_add_default_symbol (abfd, info, h, name, isym,
|
| - &sec, &value, &dynsym,
|
| - override))
|
| - goto error_free_vers;
|
| + {
|
| + h->target_internal = isym->st_target_internal;
|
| + h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
|
| + }
|
|
|
| if (definition && !dynamic)
|
| {
|
| @@ -4481,11 +4421,14 @@ error_free_dyn:
|
| break;
|
| }
|
|
|
| + /* Don't add DT_NEEDED for references from the dummy bfd. */
|
| if (!add_needed
|
| && definition
|
| && ((dynsym
|
| - && h->ref_regular)
|
| - || (h->ref_dynamic
|
| + && h->ref_regular_nonweak
|
| + && (old_bfd == NULL
|
| + || (old_bfd->flags & BFD_PLUGIN) == 0))
|
| + || (h->ref_dynamic_nonweak
|
| && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0
|
| && !on_needed_list (elf_dt_name (abfd), htab->needed))))
|
| {
|
| @@ -4497,16 +4440,13 @@ error_free_dyn:
|
| Add a DT_NEEDED entry for it. Issue an error if
|
| --no-add-needed is used and the reference was not
|
| a weak one. */
|
| - if (undef_bfd != NULL
|
| + if (old_bfd != NULL
|
| && (elf_dyn_lib_class (abfd) & DYN_NO_NEEDED) != 0)
|
| {
|
| (*_bfd_error_handler)
|
| (_("%B: undefined reference to symbol '%s'"),
|
| - undef_bfd, name);
|
| - (*_bfd_error_handler)
|
| - (_("note: '%s' is defined in DSO %B so try adding it to the linker command line"),
|
| - abfd, name);
|
| - bfd_set_error (bfd_error_invalid_operation);
|
| + old_bfd, name);
|
| + bfd_set_error (bfd_error_missing_dso);
|
| goto error_free_vers;
|
| }
|
|
|
| @@ -4540,18 +4480,16 @@ 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);
|
| for (i = 0; i < htab->root.table.size; i++)
|
| {
|
| struct bfd_hash_entry *p;
|
| @@ -4564,12 +4502,13 @@ error_free_dyn:
|
| h = (struct elf_link_hash_entry *) p;
|
| if (h->root.type == bfd_link_hash_warning)
|
| h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
| - if (h->dynindx >= old_dynsymcount)
|
| + if (h->dynindx >= old_dynsymcount
|
| + && h->dynstr_index < old_dynstr_size)
|
| _bfd_elf_strtab_delref (htab->dynstr, h->dynstr_index);
|
|
|
| /* Preserve the maximum alignment and size for common
|
| symbols even if this dynamic lib isn't on DT_NEEDED
|
| - since it can still be loaded at the run-time by another
|
| + since it can still be loaded at run time by another
|
| dynamic lib. */
|
| if (h->root.type == bfd_link_hash_common)
|
| {
|
| @@ -4588,8 +4527,9 @@ error_free_dyn:
|
| {
|
| memcpy (h->root.u.i.link, old_ent, htab->root.table.entsize);
|
| old_ent = (char *) old_ent + htab->root.table.entsize;
|
| + h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
| }
|
| - else if (h->root.type == bfd_link_hash_common)
|
| + if (h->root.type == bfd_link_hash_common)
|
| {
|
| if (size > h->root.u.c.size)
|
| h->root.u.c.size = size;
|
| @@ -4601,8 +4541,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);
|
| @@ -4615,8 +4554,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;
|
| @@ -4727,7 +4665,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;
|
| @@ -5553,6 +5491,65 @@ _bfd_elf_size_group_sections (struct bfd_link_info *info)
|
| return TRUE;
|
| }
|
|
|
| +/* Set a default stack segment size. The value in INFO wins. If it
|
| + is unset, LEGACY_SYMBOL's value is used, and if that symbol is
|
| + undefined it is initialized. */
|
| +
|
| +bfd_boolean
|
| +bfd_elf_stack_segment_size (bfd *output_bfd,
|
| + struct bfd_link_info *info,
|
| + const char *legacy_symbol,
|
| + bfd_vma default_size)
|
| +{
|
| + struct elf_link_hash_entry *h = NULL;
|
| +
|
| + /* Look for legacy symbol. */
|
| + if (legacy_symbol)
|
| + h = elf_link_hash_lookup (elf_hash_table (info), legacy_symbol,
|
| + FALSE, FALSE, FALSE);
|
| + if (h && (h->root.type == bfd_link_hash_defined
|
| + || h->root.type == bfd_link_hash_defweak)
|
| + && h->def_regular
|
| + && (h->type == STT_NOTYPE || h->type == STT_OBJECT))
|
| + {
|
| + /* The symbol has no type if specified on the command line. */
|
| + h->type = STT_OBJECT;
|
| + if (info->stacksize)
|
| + (*_bfd_error_handler) (_("%B: stack size specified and %s set"),
|
| + output_bfd, legacy_symbol);
|
| + else if (h->root.u.def.section != bfd_abs_section_ptr)
|
| + (*_bfd_error_handler) (_("%B: %s not absolute"),
|
| + output_bfd, legacy_symbol);
|
| + else
|
| + info->stacksize = h->root.u.def.value;
|
| + }
|
| +
|
| + if (!info->stacksize)
|
| + /* If the user didn't set a size, or explicitly inhibit the
|
| + size, set it now. */
|
| + info->stacksize = default_size;
|
| +
|
| + /* Provide the legacy symbol, if it is referenced. */
|
| + if (h && (h->root.type == bfd_link_hash_undefined
|
| + || h->root.type == bfd_link_hash_undefweak))
|
| + {
|
| + struct bfd_link_hash_entry *bh = NULL;
|
| +
|
| + if (!(_bfd_generic_link_add_one_symbol
|
| + (info, output_bfd, legacy_symbol,
|
| + BSF_GLOBAL, bfd_abs_section_ptr,
|
| + info->stacksize >= 0 ? info->stacksize : 0,
|
| + NULL, FALSE, get_elf_backend_data (output_bfd)->collect, &bh)))
|
| + return FALSE;
|
| +
|
| + h = (struct elf_link_hash_entry *) bh;
|
| + h->def_regular = 1;
|
| + h->type = STT_OBJECT;
|
| + }
|
| +
|
| + return TRUE;
|
| +}
|
| +
|
| /* Set up the sizes and contents of the ELF dynamic sections. This is
|
| called by the ELF linker emulation before_allocation routine. We
|
| must set the sizes of the sections before the linker sets the
|
| @@ -5582,10 +5579,30 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
|
| return TRUE;
|
|
|
| bed = get_elf_backend_data (output_bfd);
|
| +
|
| + /* Any syms created from now on start with -1 in
|
| + got.refcount/offset and plt.refcount/offset. */
|
| + elf_hash_table (info)->init_got_refcount
|
| + = elf_hash_table (info)->init_got_offset;
|
| + elf_hash_table (info)->init_plt_refcount
|
| + = elf_hash_table (info)->init_plt_offset;
|
| +
|
| + if (info->relocatable
|
| + && !_bfd_elf_size_group_sections (info))
|
| + return FALSE;
|
| +
|
| + /* The backend may have to create some sections regardless of whether
|
| + we're dynamic or not. */
|
| + if (bed->elf_backend_always_size_sections
|
| + && ! (*bed->elf_backend_always_size_sections) (output_bfd, info))
|
| + return FALSE;
|
| +
|
| + /* Determine any GNU_STACK segment requirements, after the backend
|
| + has had a chance to set a default segment size. */
|
| if (info->execstack)
|
| - elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X;
|
| + elf_stack_flags (output_bfd) = PF_R | PF_W | PF_X;
|
| else if (info->noexecstack)
|
| - elf_tdata (output_bfd)->stack_flags = PF_R | PF_W;
|
| + elf_stack_flags (output_bfd) = PF_R | PF_W;
|
| else
|
| {
|
| bfd *inputobj;
|
| @@ -5611,32 +5628,13 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
|
| else if (bed->default_execstack)
|
| exec = PF_X;
|
| }
|
| - if (notesec)
|
| - {
|
| - elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | exec;
|
| - if (exec && info->relocatable
|
| - && notesec->output_section != bfd_abs_section_ptr)
|
| - notesec->output_section->flags |= SEC_CODE;
|
| - }
|
| + if (notesec || info->stacksize > 0)
|
| + elf_stack_flags (output_bfd) = PF_R | PF_W | exec;
|
| + if (notesec && exec && info->relocatable
|
| + && notesec->output_section != bfd_abs_section_ptr)
|
| + notesec->output_section->flags |= SEC_CODE;
|
| }
|
|
|
| - /* Any syms created from now on start with -1 in
|
| - got.refcount/offset and plt.refcount/offset. */
|
| - elf_hash_table (info)->init_got_refcount
|
| - = elf_hash_table (info)->init_got_offset;
|
| - elf_hash_table (info)->init_plt_refcount
|
| - = elf_hash_table (info)->init_plt_offset;
|
| -
|
| - if (info->relocatable
|
| - && !_bfd_elf_size_group_sections (info))
|
| - return FALSE;
|
| -
|
| - /* The backend may have to create some sections regardless of whether
|
| - we're dynamic or not. */
|
| - if (bed->elf_backend_always_size_sections
|
| - && ! (*bed->elf_backend_always_size_sections) (output_bfd, info))
|
| - return FALSE;
|
| -
|
| dynobj = elf_hash_table (info)->dynobj;
|
|
|
| if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
|
| @@ -5671,19 +5669,16 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
|
| if (rpath != NULL)
|
| {
|
| bfd_size_type indx;
|
| + bfd_vma tag;
|
|
|
| indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, rpath,
|
| TRUE);
|
| - if (indx == (bfd_size_type) -1
|
| - || !_bfd_elf_add_dynamic_entry (info, DT_RPATH, indx))
|
| + if (indx == (bfd_size_type) -1)
|
| return FALSE;
|
|
|
| - if (info->new_dtags)
|
| - {
|
| - _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr, indx);
|
| - if (!_bfd_elf_add_dynamic_entry (info, DT_RUNPATH, indx))
|
| - return FALSE;
|
| - }
|
| + tag = info->new_dtags ? DT_RUNPATH : DT_RPATH;
|
| + if (!_bfd_elf_add_dynamic_entry (info, tag, indx))
|
| + return FALSE;
|
| }
|
|
|
| if (filter_shlib != NULL)
|
| @@ -6852,7 +6847,8 @@ _bfd_elf_link_hash_hide_symbol (struct bfd_link_info *info,
|
| }
|
| }
|
|
|
| -/* Initialize an ELF linker hash table. */
|
| +/* Initialize an ELF linker hash table. *TABLE has been zeroed by our
|
| + caller. */
|
|
|
| bfd_boolean
|
| _bfd_elf_link_hash_table_init
|
| @@ -6867,7 +6863,6 @@ _bfd_elf_link_hash_table_init
|
| bfd_boolean ret;
|
| int can_refcount = get_elf_backend_data (abfd)->can_refcount;
|
|
|
| - memset (table, 0, sizeof * table);
|
| table->init_got_refcount.refcount = can_refcount - 1;
|
| table->init_plt_refcount.refcount = can_refcount - 1;
|
| table->init_got_offset.offset = -(bfd_vma) 1;
|
| @@ -6891,7 +6886,7 @@ _bfd_elf_link_hash_table_create (bfd *abfd)
|
| struct elf_link_hash_table *ret;
|
| bfd_size_type amt = sizeof (struct elf_link_hash_table);
|
|
|
| - ret = (struct elf_link_hash_table *) bfd_malloc (amt);
|
| + ret = (struct elf_link_hash_table *) bfd_zmalloc (amt);
|
| if (ret == NULL)
|
| return NULL;
|
|
|
| @@ -6906,6 +6901,18 @@ _bfd_elf_link_hash_table_create (bfd *abfd)
|
| return &ret->root;
|
| }
|
|
|
| +/* Destroy an ELF linker hash table. */
|
| +
|
| +void
|
| +_bfd_elf_link_hash_table_free (struct bfd_link_hash_table *hash)
|
| +{
|
| + struct elf_link_hash_table *htab = (struct elf_link_hash_table *) 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);
|
| +}
|
| +
|
| /* This is a hook for the ELF emulation code in the generic linker to
|
| tell the backend linker what file name to use for the DT_NEEDED
|
| entry for a dynamic object. */
|
| @@ -7461,6 +7468,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;
|
| };
|
|
|
| @@ -7843,31 +7851,49 @@ get_value (bfd_vma size,
|
| bfd *input_bfd,
|
| bfd_byte *location)
|
| {
|
| + int shift;
|
| bfd_vma x = 0;
|
|
|
| + /* Sanity checks. */
|
| + BFD_ASSERT (chunksz <= sizeof (x)
|
| + && size >= chunksz
|
| + && chunksz != 0
|
| + && (size % chunksz) == 0
|
| + && input_bfd != NULL
|
| + && location != NULL);
|
| +
|
| + if (chunksz == sizeof (x))
|
| + {
|
| + BFD_ASSERT (size == chunksz);
|
| +
|
| + /* Make sure that we do not perform an undefined shift operation.
|
| + We know that size == chunksz so there will only be one iteration
|
| + of the loop below. */
|
| + shift = 0;
|
| + }
|
| + else
|
| + shift = 8 * chunksz;
|
| +
|
| for (; size; size -= chunksz, location += chunksz)
|
| {
|
| switch (chunksz)
|
| {
|
| - default:
|
| - case 0:
|
| - abort ();
|
| case 1:
|
| - x = (x << (8 * chunksz)) | bfd_get_8 (input_bfd, location);
|
| + x = (x << shift) | bfd_get_8 (input_bfd, location);
|
| break;
|
| case 2:
|
| - x = (x << (8 * chunksz)) | bfd_get_16 (input_bfd, location);
|
| + x = (x << shift) | bfd_get_16 (input_bfd, location);
|
| break;
|
| case 4:
|
| - x = (x << (8 * chunksz)) | bfd_get_32 (input_bfd, location);
|
| + x = (x << shift) | bfd_get_32 (input_bfd, location);
|
| break;
|
| - case 8:
|
| #ifdef BFD64
|
| - x = (x << (8 * chunksz)) | bfd_get_64 (input_bfd, location);
|
| -#else
|
| - abort ();
|
| -#endif
|
| + case 8:
|
| + x = (x << shift) | bfd_get_64 (input_bfd, location);
|
| break;
|
| +#endif
|
| + default:
|
| + abort ();
|
| }
|
| }
|
| return x;
|
| @@ -8066,17 +8092,14 @@ elf_link_sort_cmp2 (const void *A, const void *B)
|
| {
|
| const struct elf_link_sort_rela *a = (const struct elf_link_sort_rela *) A;
|
| const struct elf_link_sort_rela *b = (const struct elf_link_sort_rela *) B;
|
| - int copya, copyb;
|
|
|
| - if (a->u.offset < b->u.offset)
|
| + if (a->type < b->type)
|
| return -1;
|
| - if (a->u.offset > b->u.offset)
|
| + if (a->type > b->type)
|
| return 1;
|
| - copya = (a->type == reloc_class_copy) * 2 + (a->type == reloc_class_plt);
|
| - copyb = (b->type == reloc_class_copy) * 2 + (b->type == reloc_class_plt);
|
| - if (copya < copyb)
|
| + if (a->u.offset < b->u.offset)
|
| return -1;
|
| - if (copya > copyb)
|
| + if (a->u.offset > b->u.offset)
|
| return 1;
|
| if (a->rela->r_offset < b->rela->r_offset)
|
| return -1;
|
| @@ -8303,7 +8326,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
|
| struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p;
|
|
|
| (*swap_in) (abfd, erel, s->rela);
|
| - s->type = (*bed->elf_backend_reloc_type_class) (s->rela);
|
| + s->type = (*bed->elf_backend_reloc_type_class) (info, o, s->rela);
|
| s->u.sym_mask = r_sym_mask;
|
| p += sort_elt;
|
| erel += ext_size;
|
| @@ -8664,6 +8687,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
|
| {
|
| @@ -8716,7 +8755,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
|
| && h->ref_dynamic
|
| && h->def_regular
|
| && !h->dynamic_def
|
| - && !h->dynamic_weak
|
| + && h->ref_dynamic_nonweak
|
| && !elf_link_check_versioned_symbol (flinfo->info, bed, h))
|
| {
|
| bfd *def_bfd;
|
| @@ -8794,7 +8833,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
|
| /* Turn off visibility on local symbol. */
|
| sym.st_other &= ~ELF_ST_VISIBILITY (-1);
|
| }
|
| - else if (h->unique_global)
|
| + /* Set STB_GNU_UNIQUE only if symbol is defined in regular object. */
|
| + else if (h->unique_global && h->def_regular)
|
| sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, h->type);
|
| else if (h->root.type == bfd_link_hash_undefweak
|
| || h->root.type == bfd_link_hash_defweak)
|
| @@ -10357,6 +10397,42 @@ elf_fixup_link_order (bfd *abfd, asection *o)
|
| return TRUE;
|
| }
|
|
|
| +static void
|
| +elf_final_link_free (bfd *obfd, struct elf_final_link_info *flinfo)
|
| +{
|
| + asection *o;
|
| +
|
| + if (flinfo->symstrtab != NULL)
|
| + _bfd_stringtab_free (flinfo->symstrtab);
|
| + if (flinfo->contents != NULL)
|
| + free (flinfo->contents);
|
| + if (flinfo->external_relocs != NULL)
|
| + free (flinfo->external_relocs);
|
| + if (flinfo->internal_relocs != NULL)
|
| + free (flinfo->internal_relocs);
|
| + if (flinfo->external_syms != NULL)
|
| + free (flinfo->external_syms);
|
| + if (flinfo->locsym_shndx != NULL)
|
| + free (flinfo->locsym_shndx);
|
| + if (flinfo->internal_syms != NULL)
|
| + free (flinfo->internal_syms);
|
| + if (flinfo->indices != NULL)
|
| + free (flinfo->indices);
|
| + if (flinfo->sections != NULL)
|
| + free (flinfo->sections);
|
| + if (flinfo->symbuf != NULL)
|
| + free (flinfo->symbuf);
|
| + if (flinfo->symshndxbuf != NULL)
|
| + free (flinfo->symshndxbuf);
|
| + for (o = obfd->sections; o != NULL; o = o->next)
|
| + {
|
| + struct bfd_elf_section_data *esdo = elf_section_data (o);
|
| + if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL)
|
| + free (esdo->rel.hashes);
|
| + if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL)
|
| + free (esdo->rela.hashes);
|
| + }
|
| +}
|
|
|
| /* Do the final step of an ELF link. */
|
|
|
| @@ -10654,10 +10730,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
|
| /* sh_offset is set just below. */
|
| symtab_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align;
|
|
|
| - off = elf_tdata (abfd)->next_file_pos;
|
| + off = elf_next_file_pos (abfd);
|
| off = _bfd_elf_assign_file_position_for_section (symtab_hdr, off, TRUE);
|
|
|
| - /* Note that at this point elf_tdata (abfd)->next_file_pos is
|
| + /* Note that at this point elf_next_file_pos (abfd) is
|
| incorrect. We do not yet know the size of the .symtab section.
|
| We correct next_file_pos below, after we do know the size. */
|
|
|
| @@ -10911,17 +10987,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
|
| @@ -10933,15 +10998,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;
|
| @@ -11113,7 +11174,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
|
| symstrtab_hdr->sh_addralign = 1;
|
|
|
| off = _bfd_elf_assign_file_position_for_section (symstrtab_hdr, off, TRUE);
|
| - elf_tdata (abfd)->next_file_pos = off;
|
| + elf_next_file_pos (abfd) = off;
|
|
|
| if (bfd_get_symcount (abfd) > 0)
|
| {
|
| @@ -11404,44 +11465,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
|
| goto error_return;
|
| }
|
|
|
| - if (info->eh_frame_hdr)
|
| - {
|
| - if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info))
|
| - goto error_return;
|
| - }
|
| + if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info))
|
| + goto error_return;
|
|
|
| - if (flinfo.symstrtab != NULL)
|
| - _bfd_stringtab_free (flinfo.symstrtab);
|
| - if (flinfo.contents != NULL)
|
| - free (flinfo.contents);
|
| - if (flinfo.external_relocs != NULL)
|
| - free (flinfo.external_relocs);
|
| - if (flinfo.internal_relocs != NULL)
|
| - free (flinfo.internal_relocs);
|
| - if (flinfo.external_syms != NULL)
|
| - free (flinfo.external_syms);
|
| - if (flinfo.locsym_shndx != NULL)
|
| - free (flinfo.locsym_shndx);
|
| - if (flinfo.internal_syms != NULL)
|
| - free (flinfo.internal_syms);
|
| - if (flinfo.indices != NULL)
|
| - free (flinfo.indices);
|
| - if (flinfo.sections != NULL)
|
| - free (flinfo.sections);
|
| - if (flinfo.symbuf != NULL)
|
| - free (flinfo.symbuf);
|
| - if (flinfo.symshndxbuf != NULL)
|
| - free (flinfo.symshndxbuf);
|
| - for (o = abfd->sections; o != NULL; o = o->next)
|
| - {
|
| - struct bfd_elf_section_data *esdo = elf_section_data (o);
|
| - if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL)
|
| - free (esdo->rel.hashes);
|
| - if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL)
|
| - free (esdo->rela.hashes);
|
| - }
|
| + elf_final_link_free (abfd, &flinfo);
|
|
|
| - elf_tdata (abfd)->linker = TRUE;
|
| + elf_linker (abfd) = TRUE;
|
|
|
| if (attr_section)
|
| {
|
| @@ -11456,37 +11485,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
|
| return TRUE;
|
|
|
| error_return:
|
| - if (flinfo.symstrtab != NULL)
|
| - _bfd_stringtab_free (flinfo.symstrtab);
|
| - if (flinfo.contents != NULL)
|
| - free (flinfo.contents);
|
| - if (flinfo.external_relocs != NULL)
|
| - free (flinfo.external_relocs);
|
| - if (flinfo.internal_relocs != NULL)
|
| - free (flinfo.internal_relocs);
|
| - if (flinfo.external_syms != NULL)
|
| - free (flinfo.external_syms);
|
| - if (flinfo.locsym_shndx != NULL)
|
| - free (flinfo.locsym_shndx);
|
| - if (flinfo.internal_syms != NULL)
|
| - free (flinfo.internal_syms);
|
| - if (flinfo.indices != NULL)
|
| - free (flinfo.indices);
|
| - if (flinfo.sections != NULL)
|
| - free (flinfo.sections);
|
| - if (flinfo.symbuf != NULL)
|
| - free (flinfo.symbuf);
|
| - if (flinfo.symshndxbuf != NULL)
|
| - free (flinfo.symshndxbuf);
|
| - for (o = abfd->sections; o != NULL; o = o->next)
|
| - {
|
| - struct bfd_elf_section_data *esdo = elf_section_data (o);
|
| - if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL)
|
| - free (esdo->rel.hashes);
|
| - if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL)
|
| - free (esdo->rela.hashes);
|
| - }
|
| -
|
| + elf_final_link_free (abfd, &flinfo);
|
| return FALSE;
|
| }
|
|
|
| @@ -11664,7 +11663,7 @@ _bfd_elf_gc_mark_hook (asection *sec,
|
| if (sec_name && *sec_name != '\0')
|
| {
|
| bfd *i;
|
| -
|
| +
|
| for (i = info->input_bfds; i; i = i->link_next)
|
| {
|
| sec = bfd_get_section_by_name (i, sec_name);
|
| @@ -11818,23 +11817,30 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
|
| {
|
| asection *isec;
|
| bfd_boolean some_kept;
|
| + bfd_boolean debug_frag_seen;
|
|
|
| if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
|
| continue;
|
|
|
| - /* Ensure all linker created sections are kept, and see whether
|
| - any other section is already marked. */
|
| - some_kept = FALSE;
|
| + /* Ensure all linker created sections are kept,
|
| + see if any other section is already marked,
|
| + and note if we have any fragmented debug sections. */
|
| + debug_frag_seen = some_kept = FALSE;
|
| for (isec = ibfd->sections; isec != NULL; isec = isec->next)
|
| {
|
| if ((isec->flags & SEC_LINKER_CREATED) != 0)
|
| isec->gc_mark = 1;
|
| else if (isec->gc_mark)
|
| some_kept = TRUE;
|
| +
|
| + if (debug_frag_seen == FALSE
|
| + && (isec->flags & SEC_DEBUGGING)
|
| + && CONST_STRNEQ (isec->name, ".debug_line."))
|
| + debug_frag_seen = TRUE;
|
| }
|
|
|
| /* If no section in this file will be kept, then we can
|
| - toss out debug sections. */
|
| + toss out the debug and special sections. */
|
| if (!some_kept)
|
| continue;
|
|
|
| @@ -11846,6 +11852,45 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
|
| && ((isec->flags & SEC_DEBUGGING) != 0
|
| || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0))
|
| isec->gc_mark = 1;
|
| +
|
| + if (! debug_frag_seen)
|
| + continue;
|
| +
|
| + /* Look for CODE sections which are going to be discarded,
|
| + and find and discard any fragmented debug sections which
|
| + are associated with that code section. */
|
| + for (isec = ibfd->sections; isec != NULL; isec = isec->next)
|
| + if ((isec->flags & SEC_CODE) != 0
|
| + && isec->gc_mark == 0)
|
| + {
|
| + unsigned int ilen;
|
| + asection *dsec;
|
| +
|
| + ilen = strlen (isec->name);
|
| +
|
| + /* Association is determined by the name of the debug section
|
| + containing the name of the code section as a suffix. For
|
| + example .debug_line.text.foo is a debug section associated
|
| + with .text.foo. */
|
| + for (dsec = ibfd->sections; dsec != NULL; dsec = dsec->next)
|
| + {
|
| + unsigned int dlen;
|
| +
|
| + if (dsec->gc_mark == 0
|
| + || (dsec->flags & SEC_DEBUGGING) == 0)
|
| + continue;
|
| +
|
| + dlen = strlen (dsec->name);
|
| +
|
| + if (dlen > ilen
|
| + && strncmp (dsec->name + (dlen - ilen),
|
| + isec->name, ilen) == 0)
|
| + {
|
| + dsec->gc_mark = 0;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| }
|
| return TRUE;
|
| }
|
| @@ -12421,7 +12466,7 @@ bfd_elf_lookup_section_flags (struct bfd_link_info *info,
|
| }
|
| if (!tf->valid)
|
| {
|
| - info->callbacks->einfo
|
| + info->callbacks->einfo
|
| (_("Unrecognized INPUT_SECTION_FLAG %s\n"), tf->name);
|
| return FALSE;
|
| }
|
| @@ -12889,7 +12934,7 @@ get_dynamic_reloc_section_name (bfd * abfd,
|
| return NULL;
|
|
|
| name = bfd_alloc (abfd, strlen (prefix) + strlen (old_name) + 1);
|
| - sprintf (name, "%s%s", prefix, old_name);
|
| + sprintf (name, "%s%s", prefix, old_name);
|
|
|
| return name;
|
| }
|
| @@ -12960,6 +13005,11 @@ _bfd_elf_make_dynamic_reloc_section (asection * sec,
|
| reloc_sec = bfd_make_section_anyway_with_flags (dynobj, name, flags);
|
| if (reloc_sec != NULL)
|
| {
|
| + /* _bfd_elf_get_sec_type_attr chooses a section type by
|
| + name. Override as it may be wrong, eg. for a user
|
| + section named "auto" we'll get ".relauto" which is
|
| + seen to be a .rela section. */
|
| + elf_section_type (reloc_sec) = is_rela ? SHT_RELA : SHT_REL;
|
| if (! bfd_set_section_alignment (dynobj, reloc_sec, alignment))
|
| reloc_sec = NULL;
|
| }
|
| @@ -13003,5 +13053,5 @@ elf_append_rel (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
|
| const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
| bfd_byte *loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rel);
|
| BFD_ASSERT (loc + bed->s->sizeof_rel <= s->contents + s->size);
|
| - bed->s->swap_reloca_out (abfd, rel, loc);
|
| + bed->s->swap_reloc_out (abfd, rel, loc);
|
| }
|
|
|