Index: bfd/elflink.c |
diff --git a/bfd/elflink.c b/bfd/elflink.c |
index 1d1ca0bce44987d3383ea7e0188cc85719a4a1ef..574b6e29497f7ea3314012df3cd51c496661b4e0 100644 |
--- a/bfd/elflink.c |
+++ b/bfd/elflink.c |
@@ -1,6 +1,6 @@ |
/* ELF linking support for BFD. |
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, |
- 2005, 2006, 2007, 2008, 2009, 2010, 2011 |
+ 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 |
Free Software Foundation, Inc. |
This file is part of BFD, the Binary File Descriptor library. |
@@ -104,8 +104,8 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) |
struct elf_link_hash_table *htab = elf_hash_table (info); |
/* This function may be called more than once. */ |
- s = bfd_get_section_by_name (abfd, ".got"); |
- if (s != NULL && (s->flags & SEC_LINKER_CREATED) != 0) |
+ s = bfd_get_linker_section (abfd, ".got"); |
+ if (s != NULL) |
return TRUE; |
flags = bed->dynamic_sec_flags; |
@@ -779,8 +779,7 @@ _bfd_elf_link_omit_section_dynsym (bfd *output_bfd ATTRIBUTE_UNUSED, |
asection *ip; |
if (htab->dynobj != NULL |
- && (ip = bfd_get_section_by_name (htab->dynobj, p->name)) != NULL |
- && (ip->flags & SEC_LINKER_CREATED) |
+ && (ip = bfd_get_linker_section (htab->dynobj, p->name)) != NULL |
&& ip->output_section == p) |
return TRUE; |
} |
@@ -893,6 +892,33 @@ 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 |
@@ -921,6 +947,7 @@ _bfd_elf_merge_symbol (bfd *abfd, |
{ |
asection *sec, *oldsec; |
struct elf_link_hash_entry *h; |
+ struct elf_link_hash_entry *hi; |
struct elf_link_hash_entry *flip; |
int bind; |
bfd *oldbfd; |
@@ -937,7 +964,7 @@ _bfd_elf_merge_symbol (bfd *abfd, |
/* 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 == ELF_INFO_TYPE_JUST_SYMS) |
+ && sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS) |
{ |
*skip = TRUE; |
return TRUE; |
@@ -959,8 +986,9 @@ _bfd_elf_merge_symbol (bfd *abfd, |
if (!(*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec)) |
return TRUE; |
- /* For merging, we only care about real symbols. */ |
- |
+ /* For merging, we only care about real symbols. But we need to make |
+ sure that indirect symbol dynamic flags are updated. */ |
+ hi = h; |
while (h->root.type == bfd_link_hash_indirect |
|| h->root.type == bfd_link_hash_warning) |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
@@ -1136,23 +1164,11 @@ _bfd_elf_merge_symbol (bfd *abfd, |
/* 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 && !h->dynamic_def) |
+ if (newdyn) |
{ |
- 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; |
- } |
+ _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 |
@@ -1164,6 +1180,7 @@ _bfd_elf_merge_symbol (bfd *abfd, |
*skip = TRUE; |
/* Make sure this symbol is dynamic. */ |
h->ref_dynamic = 1; |
+ hi->ref_dynamic = 1; |
/* A protected symbol has external availability. Make sure it is |
recorded as dynamic. |
@@ -1216,15 +1233,15 @@ _bfd_elf_merge_symbol (bfd *abfd, |
h = *sym_hash; |
} |
- if ((h->root.u.undef.next || info->hash->undefs_tail == &h->root) |
- && bfd_is_und_section (sec)) |
+ /* If the old symbol was undefined before, then it will still be |
+ on the undefs list. If the new symbol is undefined or |
+ common, we can't make it bfd_link_hash_new here, because new |
+ undefined or common symbols will be added to the undefs list |
+ by _bfd_generic_link_add_one_symbol. Symbols may not be |
+ added twice to the undefs list. Also, if the new symbol is |
+ undefweak then we don't want to lose the strong undef. */ |
+ if (h->root.u.undef.next || info->hash->undefs_tail == &h->root) |
{ |
- /* If the new symbol is undefined and the old symbol was |
- also undefined before, we need to make sure |
- _bfd_generic_link_add_one_symbol doesn't mess |
- up the linker hash table undefs list. Since the old |
- definition came from a dynamic object, it is still on the |
- undefs list. */ |
h->root.type = bfd_link_hash_undefined; |
h->root.u.undef.abfd = abfd; |
} |
@@ -1234,11 +1251,18 @@ _bfd_elf_merge_symbol (bfd *abfd, |
h->root.u.undef.abfd = NULL; |
} |
- if (h->def_dynamic) |
+ if (ELF_ST_VISIBILITY (sym->st_other) != STV_PROTECTED) |
{ |
- h->def_dynamic = 0; |
- h->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->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; |
@@ -1717,6 +1741,7 @@ _bfd_elf_add_default_symbol (bfd *abfd, |
if (! dynamic) |
{ |
if (! info->executable |
+ || hi->def_dynamic |
|| hi->ref_dynamic) |
*dynsym = TRUE; |
} |
@@ -2510,23 +2535,21 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h, |
over to the real definition. */ |
if (h->u.weakdef != NULL) |
{ |
- struct elf_link_hash_entry *weakdef; |
- |
- weakdef = h->u.weakdef; |
- while (h->root.type == bfd_link_hash_indirect) |
- h = (struct elf_link_hash_entry *) h->root.u.i.link; |
- |
- BFD_ASSERT (h->root.type == bfd_link_hash_defined |
- || h->root.type == bfd_link_hash_defweak); |
- BFD_ASSERT (weakdef->def_dynamic); |
- |
/* If the real definition is defined by a regular object file, |
don't do anything special. See the longer description in |
_bfd_elf_adjust_dynamic_symbol, below. */ |
- if (weakdef->def_regular) |
+ if (h->u.weakdef->def_regular) |
h->u.weakdef = NULL; |
else |
{ |
+ struct elf_link_hash_entry *weakdef = h->u.weakdef; |
+ |
+ while (h->root.type == bfd_link_hash_indirect) |
+ h = (struct elf_link_hash_entry *) h->root.u.i.link; |
+ |
+ BFD_ASSERT (h->root.type == bfd_link_hash_defined |
+ || h->root.type == bfd_link_hash_defweak); |
+ BFD_ASSERT (weakdef->def_dynamic); |
BFD_ASSERT (weakdef->root.type == bfd_link_hash_defined |
|| weakdef->root.type == bfd_link_hash_defweak); |
(*bed->elf_backend_copy_indirect_symbol) (eif->info, weakdef, h); |
@@ -2708,7 +2731,7 @@ _bfd_elf_link_sec_merge_syms (struct elf_link_hash_entry *h, void *data) |
if ((h->root.type == bfd_link_hash_defined |
|| h->root.type == bfd_link_hash_defweak) |
&& ((sec = h->root.u.def.section)->flags & SEC_MERGE) |
- && sec->sec_info_type == ELF_INFO_TYPE_MERGE) |
+ && sec->sec_info_type == SEC_INFO_TYPE_MERGE) |
{ |
bfd *output_bfd = (bfd *) data; |
@@ -3031,7 +3054,7 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info, |
return FALSE; |
bed = get_elf_backend_data (hash_table->dynobj); |
- s = bfd_get_section_by_name (hash_table->dynobj, ".dynamic"); |
+ s = bfd_get_linker_section (hash_table->dynobj, ".dynamic"); |
BFD_ASSERT (s != NULL); |
newsize = s->size + bed->s->sizeof_dyn; |
@@ -3079,7 +3102,7 @@ elf_add_dt_needed_tag (bfd *abfd, |
bfd_byte *extdyn; |
bed = get_elf_backend_data (hash_table->dynobj); |
- sdyn = bfd_get_section_by_name (hash_table->dynobj, ".dynamic"); |
+ sdyn = bfd_get_linker_section (hash_table->dynobj, ".dynamic"); |
if (sdyn != NULL) |
for (extdyn = sdyn->contents; |
extdyn < sdyn->contents + sdyn->size; |
@@ -3122,7 +3145,7 @@ on_needed_list (const char *soname, struct bfd_link_needed_list *needed) |
return FALSE; |
} |
-/* Sort symbol by value and section. */ |
+/* Sort symbol by value, section, and size. */ |
static int |
elf_sort_symbol (const void *arg1, const void *arg2) |
{ |
@@ -3141,7 +3164,8 @@ elf_sort_symbol (const void *arg1, const void *arg2) |
if (sdiff != 0) |
return sdiff > 0 ? 1 : -1; |
} |
- return 0; |
+ vdiff = h1->size - h2->size; |
+ return vdiff == 0 ? 0 : vdiff > 0 ? 1 : -1; |
} |
/* This function is used to adjust offsets into .dynstr for |
@@ -3176,7 +3200,7 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info) |
size = _bfd_elf_strtab_size (dynstr); |
bed = get_elf_backend_data (dynobj); |
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); |
+ sdyn = bfd_get_linker_section (dynobj, ".dynamic"); |
BFD_ASSERT (sdyn != NULL); |
/* Update all .dynamic entries referencing .dynstr strings. */ |
@@ -3225,7 +3249,7 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info) |
Elf_Internal_Verdef def; |
Elf_Internal_Verdaux defaux; |
- s = bfd_get_section_by_name (dynobj, ".gnu.version_d"); |
+ s = bfd_get_linker_section (dynobj, ".gnu.version_d"); |
p = s->contents; |
do |
{ |
@@ -3257,7 +3281,7 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info) |
Elf_Internal_Verneed need; |
Elf_Internal_Vernaux needaux; |
- s = bfd_get_section_by_name (dynobj, ".gnu.version_r"); |
+ s = bfd_get_linker_section (dynobj, ".gnu.version_r"); |
p = s->contents; |
do |
{ |
@@ -3499,7 +3523,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 == ELF_INFO_TYPE_JUST_SYMS) |
+ && s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS) |
abort (); |
/* If this dynamic lib was specified on the command line with |
@@ -3834,6 +3858,7 @@ error_free_dyn: |
flagword flags; |
const char *name; |
struct elf_link_hash_entry *h; |
+ struct elf_link_hash_entry *hi; |
bfd_boolean definition; |
bfd_boolean size_change_ok; |
bfd_boolean type_change_ok; |
@@ -3896,7 +3921,7 @@ error_free_dyn: |
sec = bfd_section_from_elf_index (abfd, isym->st_shndx); |
if (sec == NULL) |
sec = bfd_abs_section_ptr; |
- else if (elf_discarded_section (sec)) |
+ else if (discarded_section (sec)) |
{ |
/* Symbols from discarded section are undefined. We keep |
its visibility. */ |
@@ -4166,6 +4191,9 @@ error_free_dyn: |
goto error_free_vers; |
h = *sym_hash; |
+ /* We need to make sure that indirect symbol dynamic flags are |
+ updated. */ |
+ hi = h; |
while (h->root.type == bfd_link_hash_indirect |
|| h->root.type == bfd_link_hash_warning) |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
@@ -4354,25 +4382,38 @@ error_free_dyn: |
h->ref_dynamic = 1; |
} |
} |
- if (! info->executable |
- || h->def_dynamic |
- || h->ref_dynamic) |
+ |
+ /* 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; |
+ { |
+ 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 (h->def_regular |
- || h->ref_regular |
- || (h->u.weakdef != NULL |
- && ! new_weakdef |
- && h->u.weakdef->dynindx != -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; |
} |
@@ -4686,7 +4727,6 @@ error_free_dyn: |
struct elf_link_hash_entry *hlook; |
asection *slook; |
bfd_vma vlook; |
- long ilook; |
size_t i, j, idx; |
hlook = weaks; |
@@ -4700,14 +4740,13 @@ error_free_dyn: |
slook = hlook->root.u.def.section; |
vlook = hlook->root.u.def.value; |
- ilook = -1; |
i = 0; |
j = sym_count; |
- while (i < j) |
+ while (i != j) |
{ |
bfd_signed_vma vdiff; |
idx = (i + j) / 2; |
- h = sorted_sym_hash [idx]; |
+ h = sorted_sym_hash[idx]; |
vdiff = vlook - h->root.u.def.value; |
if (vdiff < 0) |
j = idx; |
@@ -4721,24 +4760,36 @@ error_free_dyn: |
else if (sdiff > 0) |
i = idx + 1; |
else |
- { |
- ilook = idx; |
- break; |
- } |
+ break; |
} |
} |
/* We didn't find a value/section match. */ |
- if (ilook == -1) |
+ if (i == j) |
continue; |
- for (i = ilook; i < sym_count; i++) |
+ /* With multiple aliases, or when the weak symbol is already |
+ strongly defined, we have multiple matching symbols and |
+ the binary search above may land on any of them. Step |
+ one past the matching symbol(s). */ |
+ while (++idx != j) |
{ |
- h = sorted_sym_hash [i]; |
+ h = sorted_sym_hash[idx]; |
+ if (h->root.u.def.section != slook |
+ || h->root.u.def.value != vlook) |
+ break; |
+ } |
+ |
+ /* Now look back over the aliases. Since we sorted by size |
+ as well as value and section, we'll choose the one with |
+ the largest size. */ |
+ while (idx-- != i) |
+ { |
+ h = sorted_sym_hash[idx]; |
/* Stop if value or section doesn't match. */ |
- if (h->root.u.def.value != vlook |
- || h->root.u.def.section != slook) |
+ if (h->root.u.def.section != slook |
+ || h->root.u.def.value != vlook) |
break; |
else if (h != hlook) |
{ |
@@ -4861,7 +4912,7 @@ error_free_dyn: |
&string_offset)) |
goto error_return; |
if (secdata->sec_info) |
- stab->sec_info_type = ELF_INFO_TYPE_STABS; |
+ stab->sec_info_type = SEC_INFO_TYPE_STABS; |
} |
} |
} |
@@ -5586,17 +5637,9 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, |
&& ! (*bed->elf_backend_always_size_sections) (output_bfd, info)) |
return FALSE; |
- if (! _bfd_elf_maybe_strip_eh_frame_hdr (info)) |
- return FALSE; |
- |
dynobj = elf_hash_table (info)->dynobj; |
- /* If there were no dynamic objects in the link, there is nothing to |
- do here. */ |
- if (dynobj == NULL) |
- return TRUE; |
- |
- if (elf_hash_table (info)->dynamic_sections_created) |
+ if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created) |
{ |
struct elf_info_failed eif; |
struct elf_link_hash_entry *h; |
@@ -5606,7 +5649,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, |
asection *s; |
bfd_boolean all_defined; |
- *sinterpptr = bfd_get_section_by_name (dynobj, ".interp"); |
+ *sinterpptr = bfd_get_linker_section (dynobj, ".interp"); |
BFD_ASSERT (*sinterpptr != NULL || !info->executable); |
if (soname != NULL) |
@@ -5874,7 +5917,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, |
return FALSE; |
} |
- dynstr = bfd_get_section_by_name (dynobj, ".dynstr"); |
+ dynstr = bfd_get_linker_section (dynobj, ".dynstr"); |
/* If .dynstr is excluded from the link, we don't want any of |
these tags. Strictly, we should be checking each section |
individually; This quick check covers for the case where |
@@ -5899,18 +5942,22 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, |
/* The backend must work out the sizes of all the other dynamic |
sections. */ |
- if (bed->elf_backend_size_dynamic_sections |
+ if (dynobj != NULL |
+ && bed->elf_backend_size_dynamic_sections != NULL |
&& ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info)) |
return FALSE; |
- if (elf_hash_table (info)->dynamic_sections_created) |
+ if (! _bfd_elf_maybe_strip_eh_frame_hdr (info)) |
+ return FALSE; |
+ |
+ if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created) |
{ |
unsigned long section_sym_count; |
struct bfd_elf_version_tree *verdefs; |
asection *s; |
/* Set up the version definition section. */ |
- s = bfd_get_section_by_name (dynobj, ".gnu.version_d"); |
+ s = bfd_get_linker_section (dynobj, ".gnu.version_d"); |
BFD_ASSERT (s != NULL); |
/* We may have created additional version definitions if we are |
@@ -6173,7 +6220,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, |
/* Work out the size of the version reference section. */ |
- s = bfd_get_section_by_name (dynobj, ".gnu.version_r"); |
+ s = bfd_get_linker_section (dynobj, ".gnu.version_r"); |
BFD_ASSERT (s != NULL); |
{ |
struct elf_find_verdep_info sinfo; |
@@ -6285,7 +6332,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, |
|| _bfd_elf_link_renumber_dynsyms (output_bfd, info, |
§ion_sym_count) == 0) |
{ |
- s = bfd_get_section_by_name (dynobj, ".gnu.version"); |
+ s = bfd_get_linker_section (dynobj, ".gnu.version"); |
s->flags |= SEC_EXCLUDE; |
} |
} |
@@ -6369,7 +6416,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) |
§ion_sym_count); |
/* Work out the size of the symbol version section. */ |
- s = bfd_get_section_by_name (dynobj, ".gnu.version"); |
+ s = bfd_get_linker_section (dynobj, ".gnu.version"); |
BFD_ASSERT (s != NULL); |
if (dynsymcount != 0 |
&& (s->flags & SEC_EXCLUDE) == 0) |
@@ -6389,7 +6436,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) |
the final symbol table, because until then we do not know the |
correct value to give the symbols. We built the .dynstr |
section as we went along in elf_link_add_object_symbols. */ |
- s = bfd_get_section_by_name (dynobj, ".dynsym"); |
+ s = bfd_get_linker_section (dynobj, ".dynsym"); |
BFD_ASSERT (s != NULL); |
s->size = dynsymcount * bed->s->sizeof_sym; |
@@ -6447,7 +6494,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) |
elf_hash_table (info)->bucketcount = bucketcount; |
- s = bfd_get_section_by_name (dynobj, ".hash"); |
+ s = bfd_get_linker_section (dynobj, ".hash"); |
BFD_ASSERT (s != NULL); |
hash_entry_size = elf_section_data (s)->this_hdr.sh_entsize; |
s->size = ((2 + bucketcount + dynsymcount) * hash_entry_size); |
@@ -6501,7 +6548,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) |
return FALSE; |
} |
- s = bfd_get_section_by_name (dynobj, ".gnu.hash"); |
+ s = bfd_get_linker_section (dynobj, ".gnu.hash"); |
BFD_ASSERT (s != NULL); |
if (cinfo.nsyms == 0) |
@@ -6629,7 +6676,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) |
} |
} |
- s = bfd_get_section_by_name (dynobj, ".dynstr"); |
+ s = bfd_get_linker_section (dynobj, ".dynstr"); |
BFD_ASSERT (s != NULL); |
elf_finalize_dynstr (output_bfd, info); |
@@ -6644,25 +6691,14 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) |
return TRUE; |
} |
-/* Indicate that we are only retrieving symbol values from this |
- section. */ |
- |
-void |
-_bfd_elf_link_just_syms (asection *sec, struct bfd_link_info *info) |
-{ |
- if (is_elf_hash_table (info->hash)) |
- sec->sec_info_type = ELF_INFO_TYPE_JUST_SYMS; |
- _bfd_generic_link_just_syms (sec, info); |
-} |
- |
/* Make sure sec_info_type is cleared if sec_info is cleared too. */ |
static void |
merge_sections_remove_hook (bfd *abfd ATTRIBUTE_UNUSED, |
asection *sec) |
{ |
- BFD_ASSERT (sec->sec_info_type == ELF_INFO_TYPE_MERGE); |
- sec->sec_info_type = ELF_INFO_TYPE_NONE; |
+ BFD_ASSERT (sec->sec_info_type == SEC_INFO_TYPE_MERGE); |
+ sec->sec_info_type = SEC_INFO_TYPE_NONE; |
} |
/* Finish SHF_MERGE section merging. */ |
@@ -6690,7 +6726,7 @@ _bfd_elf_merge_sections (bfd *abfd, struct bfd_link_info *info) |
sec, &secdata->sec_info)) |
return FALSE; |
else if (secdata->sec_info) |
- sec->sec_info_type = ELF_INFO_TYPE_MERGE; |
+ sec->sec_info_type = SEC_INFO_TYPE_MERGE; |
} |
if (elf_hash_table (info)->merge_info != NULL) |
@@ -7413,6 +7449,8 @@ struct elf_final_link_info |
size_t symbuf_size; |
/* And same for symshndxbuf. */ |
size_t shndxbuf_size; |
+ /* Number of STT_FILE syms seen. */ |
+ size_t filesym_count; |
}; |
/* This struct is used to pass information to elf_link_output_extsym. */ |
@@ -7421,7 +7459,9 @@ struct elf_outext_info |
{ |
bfd_boolean failed; |
bfd_boolean localsyms; |
- struct elf_final_link_info *finfo; |
+ bfd_boolean need_second_pass; |
+ bfd_boolean second_pass; |
+ struct elf_final_link_info *flinfo; |
}; |
@@ -7498,7 +7538,7 @@ set_symbol_value (bfd *bfd_with_globals, |
static bfd_boolean |
resolve_symbol (const char *name, |
bfd *input_bfd, |
- struct elf_final_link_info *finfo, |
+ struct elf_final_link_info *flinfo, |
bfd_vma *result, |
Elf_Internal_Sym *isymbuf, |
size_t locsymcount) |
@@ -7527,7 +7567,7 @@ resolve_symbol (const char *name, |
#endif |
if (candidate && strcmp (candidate, name) == 0) |
{ |
- asection *sec = finfo->sections [i]; |
+ asection *sec = flinfo->sections [i]; |
*result = _bfd_elf_rel_local_sym (input_bfd, sym, &sec, 0); |
*result += sec->output_offset + sec->output_section->vma; |
@@ -7540,7 +7580,7 @@ resolve_symbol (const char *name, |
} |
/* Hmm, haven't found it yet. perhaps it is a global. */ |
- global_entry = bfd_link_hash_lookup (finfo->info->hash, name, |
+ global_entry = bfd_link_hash_lookup (flinfo->info->hash, name, |
FALSE, FALSE, TRUE); |
if (!global_entry) |
return FALSE; |
@@ -7609,7 +7649,7 @@ static bfd_boolean |
eval_symbol (bfd_vma *result, |
const char **symp, |
bfd *input_bfd, |
- struct elf_final_link_info *finfo, |
+ struct elf_final_link_info *flinfo, |
bfd_vma dot, |
Elf_Internal_Sym *isymbuf, |
size_t locsymcount, |
@@ -7669,8 +7709,8 @@ eval_symbol (bfd_vma *result, |
if (symbol_is_section) |
{ |
- if (!resolve_section (symbuf, finfo->output_bfd->sections, result) |
- && !resolve_symbol (symbuf, input_bfd, finfo, result, |
+ if (!resolve_section (symbuf, flinfo->output_bfd->sections, result) |
+ && !resolve_symbol (symbuf, input_bfd, flinfo, result, |
isymbuf, locsymcount)) |
{ |
undefined_reference ("section", symbuf); |
@@ -7679,9 +7719,9 @@ eval_symbol (bfd_vma *result, |
} |
else |
{ |
- if (!resolve_symbol (symbuf, input_bfd, finfo, result, |
+ if (!resolve_symbol (symbuf, input_bfd, flinfo, result, |
isymbuf, locsymcount) |
- && !resolve_section (symbuf, finfo->output_bfd->sections, |
+ && !resolve_section (symbuf, flinfo->output_bfd->sections, |
result)) |
{ |
undefined_reference ("symbol", symbuf); |
@@ -7700,7 +7740,7 @@ eval_symbol (bfd_vma *result, |
if (*sym == ':') \ |
++sym; \ |
*symp = sym; \ |
- if (!eval_symbol (&a, symp, input_bfd, finfo, dot, \ |
+ if (!eval_symbol (&a, symp, input_bfd, flinfo, dot, \ |
isymbuf, locsymcount, signed_p)) \ |
return FALSE; \ |
if (signed_p) \ |
@@ -7717,11 +7757,11 @@ eval_symbol (bfd_vma *result, |
if (*sym == ':') \ |
++sym; \ |
*symp = sym; \ |
- if (!eval_symbol (&a, symp, input_bfd, finfo, dot, \ |
+ if (!eval_symbol (&a, symp, input_bfd, flinfo, dot, \ |
isymbuf, locsymcount, signed_p)) \ |
return FALSE; \ |
++*symp; \ |
- if (!eval_symbol (&b, symp, input_bfd, finfo, dot, \ |
+ if (!eval_symbol (&b, symp, input_bfd, flinfo, dot, \ |
isymbuf, locsymcount, signed_p)) \ |
return FALSE; \ |
if (signed_p) \ |
@@ -8319,24 +8359,24 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) |
/* Flush the output symbols to the file. */ |
static bfd_boolean |
-elf_link_flush_output_syms (struct elf_final_link_info *finfo, |
+elf_link_flush_output_syms (struct elf_final_link_info *flinfo, |
const struct elf_backend_data *bed) |
{ |
- if (finfo->symbuf_count > 0) |
+ if (flinfo->symbuf_count > 0) |
{ |
Elf_Internal_Shdr *hdr; |
file_ptr pos; |
bfd_size_type amt; |
- hdr = &elf_tdata (finfo->output_bfd)->symtab_hdr; |
+ hdr = &elf_tdata (flinfo->output_bfd)->symtab_hdr; |
pos = hdr->sh_offset + hdr->sh_size; |
- amt = finfo->symbuf_count * bed->s->sizeof_sym; |
- if (bfd_seek (finfo->output_bfd, pos, SEEK_SET) != 0 |
- || bfd_bwrite (finfo->symbuf, amt, finfo->output_bfd) != amt) |
+ amt = flinfo->symbuf_count * bed->s->sizeof_sym; |
+ if (bfd_seek (flinfo->output_bfd, pos, SEEK_SET) != 0 |
+ || bfd_bwrite (flinfo->symbuf, amt, flinfo->output_bfd) != amt) |
return FALSE; |
hdr->sh_size += amt; |
- finfo->symbuf_count = 0; |
+ flinfo->symbuf_count = 0; |
} |
return TRUE; |
@@ -8345,7 +8385,7 @@ elf_link_flush_output_syms (struct elf_final_link_info *finfo, |
/* Add a symbol to the output symbol table. */ |
static int |
-elf_link_output_sym (struct elf_final_link_info *finfo, |
+elf_link_output_sym (struct elf_final_link_info *flinfo, |
const char *name, |
Elf_Internal_Sym *elfsym, |
asection *input_sec, |
@@ -8358,11 +8398,11 @@ elf_link_output_sym (struct elf_final_link_info *finfo, |
struct elf_link_hash_entry *); |
const struct elf_backend_data *bed; |
- bed = get_elf_backend_data (finfo->output_bfd); |
+ bed = get_elf_backend_data (flinfo->output_bfd); |
output_symbol_hook = bed->elf_backend_link_output_symbol_hook; |
if (output_symbol_hook != NULL) |
{ |
- int ret = (*output_symbol_hook) (finfo->info, name, elfsym, input_sec, h); |
+ int ret = (*output_symbol_hook) (flinfo->info, name, elfsym, input_sec, h); |
if (ret != 1) |
return ret; |
} |
@@ -8373,41 +8413,41 @@ elf_link_output_sym (struct elf_final_link_info *finfo, |
elfsym->st_name = 0; |
else |
{ |
- elfsym->st_name = (unsigned long) _bfd_stringtab_add (finfo->symstrtab, |
+ elfsym->st_name = (unsigned long) _bfd_stringtab_add (flinfo->symstrtab, |
name, TRUE, FALSE); |
if (elfsym->st_name == (unsigned long) -1) |
return 0; |
} |
- if (finfo->symbuf_count >= finfo->symbuf_size) |
+ if (flinfo->symbuf_count >= flinfo->symbuf_size) |
{ |
- if (! elf_link_flush_output_syms (finfo, bed)) |
+ if (! elf_link_flush_output_syms (flinfo, bed)) |
return 0; |
} |
- dest = finfo->symbuf + finfo->symbuf_count * bed->s->sizeof_sym; |
- destshndx = finfo->symshndxbuf; |
+ dest = flinfo->symbuf + flinfo->symbuf_count * bed->s->sizeof_sym; |
+ destshndx = flinfo->symshndxbuf; |
if (destshndx != NULL) |
{ |
- if (bfd_get_symcount (finfo->output_bfd) >= finfo->shndxbuf_size) |
+ if (bfd_get_symcount (flinfo->output_bfd) >= flinfo->shndxbuf_size) |
{ |
bfd_size_type amt; |
- amt = finfo->shndxbuf_size * sizeof (Elf_External_Sym_Shndx); |
+ amt = flinfo->shndxbuf_size * sizeof (Elf_External_Sym_Shndx); |
destshndx = (Elf_External_Sym_Shndx *) bfd_realloc (destshndx, |
amt * 2); |
if (destshndx == NULL) |
return 0; |
- finfo->symshndxbuf = destshndx; |
+ flinfo->symshndxbuf = destshndx; |
memset ((char *) destshndx + amt, 0, amt); |
- finfo->shndxbuf_size *= 2; |
+ flinfo->shndxbuf_size *= 2; |
} |
- destshndx += bfd_get_symcount (finfo->output_bfd); |
+ destshndx += bfd_get_symcount (flinfo->output_bfd); |
} |
- bed->s->swap_symbol_out (finfo->output_bfd, elfsym, dest, destshndx); |
- finfo->symbuf_count += 1; |
- bfd_get_symcount (finfo->output_bfd) += 1; |
+ bed->s->swap_symbol_out (flinfo->output_bfd, elfsym, dest, destshndx); |
+ flinfo->symbuf_count += 1; |
+ bfd_get_symcount (flinfo->output_bfd) += 1; |
return 1; |
} |
@@ -8448,6 +8488,10 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info, |
if (!is_elf_hash_table (info->hash)) |
return FALSE; |
+ /* Check indirect symbol. */ |
+ while (h->root.type == bfd_link_hash_indirect) |
+ h = (struct elf_link_hash_entry *) h->root.u.i.link; |
+ |
switch (h->root.type) |
{ |
default: |
@@ -8595,7 +8639,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) |
{ |
struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) bh; |
struct elf_outext_info *eoinfo = (struct elf_outext_info *) data; |
- struct elf_final_link_info *finfo = eoinfo->finfo; |
+ struct elf_final_link_info *flinfo = eoinfo->flinfo; |
bfd_boolean strip; |
Elf_Internal_Sym sym; |
asection *input_sec; |
@@ -8615,6 +8659,11 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) |
{ |
if (!h->forced_local) |
return TRUE; |
+ if (eoinfo->second_pass |
+ && !((h->root.type == bfd_link_hash_defined |
+ || h->root.type == bfd_link_hash_defweak) |
+ && h->root.u.def.section->output_section != NULL)) |
+ return TRUE; |
} |
else |
{ |
@@ -8622,7 +8671,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) |
return TRUE; |
} |
- bed = get_elf_backend_data (finfo->output_bfd); |
+ bed = get_elf_backend_data (flinfo->output_bfd); |
if (h->root.type == bfd_link_hash_undefined) |
{ |
@@ -8641,14 +8690,16 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) |
/* If we are reporting errors for this situation then do so now. */ |
if (!ignore_undef |
&& h->ref_dynamic |
- && (!h->ref_regular || finfo->info->gc_sections) |
- && ! elf_link_check_versioned_symbol (finfo->info, bed, h) |
- && finfo->info->unresolved_syms_in_shared_libs != RM_IGNORE) |
- { |
- if (! (finfo->info->callbacks->undefined_symbol |
- (finfo->info, h->root.root.string, |
- h->ref_regular ? NULL : h->root.u.undef.abfd, |
- NULL, 0, finfo->info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR))) |
+ && (!h->ref_regular || flinfo->info->gc_sections) |
+ && !elf_link_check_versioned_symbol (flinfo->info, bed, h) |
+ && flinfo->info->unresolved_syms_in_shared_libs != RM_IGNORE) |
+ { |
+ if (!(flinfo->info->callbacks->undefined_symbol |
+ (flinfo->info, h->root.root.string, |
+ h->ref_regular ? NULL : h->root.u.undef.abfd, |
+ NULL, 0, |
+ (flinfo->info->unresolved_syms_in_shared_libs |
+ == RM_GENERATE_ERROR)))) |
{ |
bfd_set_error (bfd_error_bad_value); |
eoinfo->failed = TRUE; |
@@ -8659,17 +8710,22 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) |
/* We should also warn if a forced local symbol is referenced from |
shared libraries. */ |
- if (!finfo->info->relocatable |
- && finfo->info->executable |
+ if (!flinfo->info->relocatable |
+ && flinfo->info->executable |
&& h->forced_local |
&& h->ref_dynamic |
&& h->def_regular |
&& !h->dynamic_def |
&& !h->dynamic_weak |
- && ! elf_link_check_versioned_symbol (finfo->info, bed, h)) |
+ && !elf_link_check_versioned_symbol (flinfo->info, bed, h)) |
{ |
bfd *def_bfd; |
const char *msg; |
+ struct elf_link_hash_entry *hi = h; |
+ |
+ /* Check indirect symbol. */ |
+ while (hi->root.type == bfd_link_hash_indirect) |
+ hi = (struct elf_link_hash_entry *) hi->root.u.i.link; |
if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL) |
msg = _("%B: internal symbol `%s' in %B is referenced by DSO"); |
@@ -8677,10 +8733,10 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) |
msg = _("%B: hidden symbol `%s' in %B is referenced by DSO"); |
else |
msg = _("%B: local symbol `%s' in %B is referenced by DSO"); |
- def_bfd = finfo->output_bfd; |
- if (h->root.u.def.section != bfd_abs_section_ptr) |
- def_bfd = h->root.u.def.section->owner; |
- (*_bfd_error_handler) (msg, finfo->output_bfd, def_bfd, |
+ def_bfd = flinfo->output_bfd; |
+ if (hi->root.u.def.section != bfd_abs_section_ptr) |
+ def_bfd = hi->root.u.def.section->owner; |
+ (*_bfd_error_handler) (msg, flinfo->output_bfd, def_bfd, |
h->root.root.string); |
bfd_set_error (bfd_error_bad_value); |
eoinfo->failed = TRUE; |
@@ -8699,16 +8755,16 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) |
&& !h->def_regular |
&& !h->ref_regular) |
strip = TRUE; |
- else if (finfo->info->strip == strip_all) |
+ else if (flinfo->info->strip == strip_all) |
strip = TRUE; |
- else if (finfo->info->strip == strip_some |
- && bfd_hash_lookup (finfo->info->keep_hash, |
+ else if (flinfo->info->strip == strip_some |
+ && bfd_hash_lookup (flinfo->info->keep_hash, |
h->root.root.string, FALSE, FALSE) == NULL) |
strip = TRUE; |
else if ((h->root.type == bfd_link_hash_defined |
|| h->root.type == bfd_link_hash_defweak) |
- && ((finfo->info->strip_discarded |
- && elf_discarded_section (h->root.u.def.section)) |
+ && ((flinfo->info->strip_discarded |
+ && discarded_section (h->root.u.def.section)) |
|| (h->root.u.def.section->owner != NULL |
&& (h->root.u.def.section->owner->flags & BFD_PLUGIN) != 0))) |
strip = TRUE; |
@@ -8767,14 +8823,27 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) |
input_sec = h->root.u.def.section; |
if (input_sec->output_section != NULL) |
{ |
+ if (eoinfo->localsyms && flinfo->filesym_count == 1) |
+ { |
+ bfd_boolean second_pass_sym |
+ = (input_sec->owner == flinfo->output_bfd |
+ || input_sec->owner == NULL |
+ || (input_sec->flags & SEC_LINKER_CREATED) != 0 |
+ || (input_sec->owner->flags & BFD_LINKER_CREATED) != 0); |
+ |
+ eoinfo->need_second_pass |= second_pass_sym; |
+ if (eoinfo->second_pass != second_pass_sym) |
+ return TRUE; |
+ } |
+ |
sym.st_shndx = |
- _bfd_elf_section_from_bfd_section (finfo->output_bfd, |
+ _bfd_elf_section_from_bfd_section (flinfo->output_bfd, |
input_sec->output_section); |
if (sym.st_shndx == SHN_BAD) |
{ |
(*_bfd_error_handler) |
(_("%B: could not find output section %A for input section %A"), |
- finfo->output_bfd, input_sec->output_section, input_sec); |
+ flinfo->output_bfd, input_sec->output_section, input_sec); |
bfd_set_error (bfd_error_nonrepresentable_section); |
eoinfo->failed = TRUE; |
return FALSE; |
@@ -8784,18 +8853,18 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) |
but in nonrelocatable files they are virtual |
addresses. */ |
sym.st_value = h->root.u.def.value + input_sec->output_offset; |
- if (! finfo->info->relocatable) |
+ if (!flinfo->info->relocatable) |
{ |
sym.st_value += input_sec->output_section->vma; |
if (h->type == STT_TLS) |
{ |
- asection *tls_sec = elf_hash_table (finfo->info)->tls_sec; |
+ asection *tls_sec = elf_hash_table (flinfo->info)->tls_sec; |
if (tls_sec != NULL) |
sym.st_value -= tls_sec->vma; |
else |
{ |
/* The TLS section may have been garbage collected. */ |
- BFD_ASSERT (finfo->info->gc_sections |
+ BFD_ASSERT (flinfo->info->gc_sections |
&& !input_sec->gc_mark); |
} |
} |
@@ -8834,17 +8903,17 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) |
STT_GNU_IFUNC symbol must go through PLT. */ |
if ((h->type == STT_GNU_IFUNC |
&& h->def_regular |
- && !finfo->info->relocatable) |
+ && !flinfo->info->relocatable) |
|| ((h->dynindx != -1 |
|| h->forced_local) |
- && ((finfo->info->shared |
+ && ((flinfo->info->shared |
&& (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
|| h->root.type != bfd_link_hash_undefweak)) |
|| !h->forced_local) |
- && elf_hash_table (finfo->info)->dynamic_sections_created)) |
+ && elf_hash_table (flinfo->info)->dynamic_sections_created)) |
{ |
if (! ((*bed->elf_backend_finish_dynamic_symbol) |
- (finfo->output_bfd, finfo->info, h, &sym))) |
+ (flinfo->output_bfd, flinfo->info, h, &sym))) |
{ |
eoinfo->failed = TRUE; |
return FALSE; |
@@ -8887,7 +8956,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) |
/* If a non-weak symbol with non-default visibility is not defined |
locally, it is a fatal error. */ |
- if (! finfo->info->relocatable |
+ if (!flinfo->info->relocatable |
&& ELF_ST_VISIBILITY (sym.st_other) != STV_DEFAULT |
&& ELF_ST_BIND (sym.st_info) != STB_WEAK |
&& h->root.type == bfd_link_hash_undefined |
@@ -8901,7 +8970,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) |
msg = _("%B: internal symbol `%s' isn't defined"); |
else |
msg = _("%B: hidden symbol `%s' isn't defined"); |
- (*_bfd_error_handler) (msg, finfo->output_bfd, h->root.root.string); |
+ (*_bfd_error_handler) (msg, flinfo->output_bfd, h->root.root.string); |
bfd_set_error (bfd_error_bad_value); |
eoinfo->failed = TRUE; |
return FALSE; |
@@ -8910,21 +8979,39 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) |
/* If this symbol should be put in the .dynsym section, then put it |
there now. We already know the symbol index. We also fill in |
the entry in the .hash section. */ |
- if (h->dynindx != -1 |
- && elf_hash_table (finfo->info)->dynamic_sections_created) |
+ if (flinfo->dynsym_sec != NULL |
+ && h->dynindx != -1 |
+ && elf_hash_table (flinfo->info)->dynamic_sections_created) |
{ |
bfd_byte *esym; |
+ /* Since there is no version information in the dynamic string, |
+ if there is no version info in symbol version section, we will |
+ have a run-time problem. */ |
+ if (h->verinfo.verdef == NULL) |
+ { |
+ char *p = strrchr (h->root.root.string, ELF_VER_CHR); |
+ |
+ if (p && p [1] != '\0') |
+ { |
+ (*_bfd_error_handler) |
+ (_("%B: No symbol version section for versioned symbol `%s'"), |
+ flinfo->output_bfd, h->root.root.string); |
+ eoinfo->failed = TRUE; |
+ return FALSE; |
+ } |
+ } |
+ |
sym.st_name = h->dynstr_index; |
- esym = finfo->dynsym_sec->contents + h->dynindx * bed->s->sizeof_sym; |
- if (! check_dynsym (finfo->output_bfd, &sym)) |
+ esym = flinfo->dynsym_sec->contents + h->dynindx * bed->s->sizeof_sym; |
+ if (!check_dynsym (flinfo->output_bfd, &sym)) |
{ |
eoinfo->failed = TRUE; |
return FALSE; |
} |
- bed->s->swap_symbol_out (finfo->output_bfd, &sym, esym, 0); |
+ bed->s->swap_symbol_out (flinfo->output_bfd, &sym, esym, 0); |
- if (finfo->hash_sec != NULL) |
+ if (flinfo->hash_sec != NULL) |
{ |
size_t hash_entry_size; |
bfd_byte *bucketpos; |
@@ -8932,21 +9019,22 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) |
size_t bucketcount; |
size_t bucket; |
- bucketcount = elf_hash_table (finfo->info)->bucketcount; |
+ bucketcount = elf_hash_table (flinfo->info)->bucketcount; |
bucket = h->u.elf_hash_value % bucketcount; |
hash_entry_size |
- = elf_section_data (finfo->hash_sec)->this_hdr.sh_entsize; |
- bucketpos = ((bfd_byte *) finfo->hash_sec->contents |
+ = elf_section_data (flinfo->hash_sec)->this_hdr.sh_entsize; |
+ bucketpos = ((bfd_byte *) flinfo->hash_sec->contents |
+ (bucket + 2) * hash_entry_size); |
- chain = bfd_get (8 * hash_entry_size, finfo->output_bfd, bucketpos); |
- bfd_put (8 * hash_entry_size, finfo->output_bfd, h->dynindx, bucketpos); |
- bfd_put (8 * hash_entry_size, finfo->output_bfd, chain, |
- ((bfd_byte *) finfo->hash_sec->contents |
+ chain = bfd_get (8 * hash_entry_size, flinfo->output_bfd, bucketpos); |
+ bfd_put (8 * hash_entry_size, flinfo->output_bfd, h->dynindx, |
+ bucketpos); |
+ bfd_put (8 * hash_entry_size, flinfo->output_bfd, chain, |
+ ((bfd_byte *) flinfo->hash_sec->contents |
+ (bucketcount + 2 + h->dynindx) * hash_entry_size)); |
} |
- if (finfo->symver_sec != NULL && finfo->symver_sec->contents != NULL) |
+ if (flinfo->symver_sec != NULL && flinfo->symver_sec->contents != NULL) |
{ |
Elf_Internal_Versym iversym; |
Elf_External_Versym *eversym; |
@@ -8964,16 +9052,16 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) |
iversym.vs_vers = 1; |
else |
iversym.vs_vers = h->verinfo.vertree->vernum + 1; |
- if (finfo->info->create_default_symver) |
+ if (flinfo->info->create_default_symver) |
iversym.vs_vers++; |
} |
if (h->hidden) |
iversym.vs_vers |= VERSYM_HIDDEN; |
- eversym = (Elf_External_Versym *) finfo->symver_sec->contents; |
+ eversym = (Elf_External_Versym *) flinfo->symver_sec->contents; |
eversym += h->dynindx; |
- _bfd_elf_swap_versym_out (finfo->output_bfd, &iversym, eversym); |
+ _bfd_elf_swap_versym_out (flinfo->output_bfd, &iversym, eversym); |
} |
} |
@@ -8982,8 +9070,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) |
if (strip || (input_sec->flags & SEC_EXCLUDE) != 0) |
return TRUE; |
- indx = bfd_get_symcount (finfo->output_bfd); |
- ret = elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec, h); |
+ indx = bfd_get_symcount (flinfo->output_bfd); |
+ ret = elf_link_output_sym (flinfo, h->root.root.string, &sym, input_sec, h); |
if (ret == 0) |
{ |
eoinfo->failed = TRUE; |
@@ -9007,8 +9095,8 @@ elf_section_ignore_discarded_relocs (asection *sec) |
switch (sec->sec_info_type) |
{ |
- case ELF_INFO_TYPE_STABS: |
- case ELF_INFO_TYPE_EH_FRAME: |
+ case SEC_INFO_TYPE_STABS: |
+ case SEC_INFO_TYPE_EH_FRAME: |
return TRUE; |
default: |
break; |
@@ -9097,7 +9185,7 @@ _bfd_elf_check_kept_section (asection *sec, struct bfd_link_info *info) |
don't have to keep them in memory. */ |
static bfd_boolean |
-elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
+elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) |
{ |
int (*relocate_section) |
(bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
@@ -9117,8 +9205,9 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
bfd_size_type address_size; |
bfd_vma r_type_mask; |
int r_sym_shift; |
+ bfd_boolean have_file_sym = FALSE; |
- output_bfd = finfo->output_bfd; |
+ output_bfd = flinfo->output_bfd; |
bed = get_elf_backend_data (output_bfd); |
relocate_section = bed->elf_backend_relocate_section; |
@@ -9145,9 +9234,9 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
if (isymbuf == NULL && locsymcount != 0) |
{ |
isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0, |
- finfo->internal_syms, |
- finfo->external_syms, |
- finfo->locsym_shndx); |
+ flinfo->internal_syms, |
+ flinfo->external_syms, |
+ flinfo->locsym_shndx); |
if (isymbuf == NULL) |
return FALSE; |
} |
@@ -9156,7 +9245,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
SEC_MERGE sections. Write out those local symbols we know are |
going into the output file. */ |
isymend = isymbuf + locsymcount; |
- for (isym = isymbuf, pindex = finfo->indices, ppsection = finfo->sections; |
+ for (isym = isymbuf, pindex = flinfo->indices, ppsection = flinfo->sections; |
isym < isymend; |
isym++, pindex++, ppsection++) |
{ |
@@ -9193,7 +9282,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
*ppsection = NULL; |
continue; |
} |
- else if (isec->sec_info_type == ELF_INFO_TYPE_MERGE |
+ else if (isec->sec_info_type == SEC_INFO_TYPE_MERGE |
&& ELF_ST_TYPE (isym->st_info) != STT_SECTION) |
isym->st_value = |
_bfd_merged_section_offset (output_bfd, &isec, |
@@ -9204,7 +9293,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
*ppsection = isec; |
/* Don't output the first, undefined, symbol. */ |
- if (ppsection == finfo->sections) |
+ if (ppsection == flinfo->sections) |
continue; |
if (ELF_ST_TYPE (isym->st_info) == STT_SECTION) |
@@ -9217,7 +9306,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
/* If we are stripping all symbols, we don't want to output this |
one. */ |
- if (finfo->info->strip == strip_all) |
+ if (flinfo->info->strip == strip_all) |
continue; |
/* If we are discarding all local symbols, we don't want to |
@@ -9225,7 +9314,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
file, then some of the local symbols may be required by |
relocs; we output them below as we discover that they are |
needed. */ |
- if (finfo->info->discard == discard_all) |
+ if (flinfo->info->discard == discard_all) |
continue; |
/* If this symbol is defined in a section which we are |
@@ -9243,15 +9332,38 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
return FALSE; |
/* See if we are discarding symbols with this name. */ |
- if ((finfo->info->strip == strip_some |
- && (bfd_hash_lookup (finfo->info->keep_hash, name, FALSE, FALSE) |
+ if ((flinfo->info->strip == strip_some |
+ && (bfd_hash_lookup (flinfo->info->keep_hash, name, FALSE, FALSE) |
== NULL)) |
- || (((finfo->info->discard == discard_sec_merge |
- && (isec->flags & SEC_MERGE) && ! finfo->info->relocatable) |
- || finfo->info->discard == discard_l) |
+ || (((flinfo->info->discard == discard_sec_merge |
+ && (isec->flags & SEC_MERGE) && !flinfo->info->relocatable) |
+ || flinfo->info->discard == discard_l) |
&& bfd_is_local_label_name (input_bfd, name))) |
continue; |
+ if (ELF_ST_TYPE (isym->st_info) == STT_FILE) |
+ { |
+ have_file_sym = TRUE; |
+ flinfo->filesym_count += 1; |
+ } |
+ if (!have_file_sym) |
+ { |
+ /* In the absence of debug info, bfd_find_nearest_line uses |
+ FILE symbols to determine the source file for local |
+ function symbols. Provide a FILE symbol here if input |
+ files lack such, so that their symbols won't be |
+ associated with a previous input file. It's not the |
+ source file, but the best we can do. */ |
+ have_file_sym = TRUE; |
+ flinfo->filesym_count += 1; |
+ memset (&osym, 0, sizeof (osym)); |
+ osym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE); |
+ osym.st_shndx = SHN_ABS; |
+ if (!elf_link_output_sym (flinfo, input_bfd->filename, &osym, |
+ bfd_abs_section_ptr, NULL)) |
+ return FALSE; |
+ } |
+ |
osym = *isym; |
/* Adjust the section index for the output file. */ |
@@ -9268,19 +9380,19 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
output_section. Any special sections must be set up to meet |
these requirements. */ |
osym.st_value += isec->output_offset; |
- if (! finfo->info->relocatable) |
+ if (!flinfo->info->relocatable) |
{ |
osym.st_value += isec->output_section->vma; |
if (ELF_ST_TYPE (osym.st_info) == STT_TLS) |
{ |
/* STT_TLS symbols are relative to PT_TLS segment base. */ |
- BFD_ASSERT (elf_hash_table (finfo->info)->tls_sec != NULL); |
- osym.st_value -= elf_hash_table (finfo->info)->tls_sec->vma; |
+ BFD_ASSERT (elf_hash_table (flinfo->info)->tls_sec != NULL); |
+ osym.st_value -= elf_hash_table (flinfo->info)->tls_sec->vma; |
} |
} |
indx = bfd_get_symcount (output_bfd); |
- ret = elf_link_output_sym (finfo, name, &osym, isec, NULL); |
+ ret = elf_link_output_sym (flinfo, name, &osym, isec, NULL); |
if (ret == 0) |
return FALSE; |
else if (ret == 1) |
@@ -9312,7 +9424,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
continue; |
} |
- if (finfo->info->relocatable |
+ if (flinfo->info->relocatable |
&& (o->flags & (SEC_LINKER_CREATED | SEC_GROUP)) == SEC_GROUP) |
{ |
/* Deal with the group signature symbol. */ |
@@ -9322,7 +9434,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
if (symndx >= locsymcount |
|| (elf_bad_symtab (input_bfd) |
- && finfo->sections[symndx] == NULL)) |
+ && flinfo->sections[symndx] == NULL)) |
{ |
struct elf_link_hash_entry *h = sym_hashes[symndx - extsymoff]; |
while (h->root.type == bfd_link_hash_indirect |
@@ -9335,16 +9447,16 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
else if (ELF_ST_TYPE (isymbuf[symndx].st_info) == STT_SECTION) |
{ |
/* We'll use the output section target_index. */ |
- asection *sec = finfo->sections[symndx]->output_section; |
+ asection *sec = flinfo->sections[symndx]->output_section; |
elf_section_data (osec)->this_hdr.sh_info = sec->target_index; |
} |
else |
{ |
- if (finfo->indices[symndx] == -1) |
+ if (flinfo->indices[symndx] == -1) |
{ |
/* Otherwise output the local symbol now. */ |
Elf_Internal_Sym sym = isymbuf[symndx]; |
- asection *sec = finfo->sections[symndx]->output_section; |
+ asection *sec = flinfo->sections[symndx]->output_section; |
const char *name; |
long indx; |
int ret; |
@@ -9363,16 +9475,16 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
sym.st_value += o->output_offset; |
indx = bfd_get_symcount (output_bfd); |
- ret = elf_link_output_sym (finfo, name, &sym, o, NULL); |
+ ret = elf_link_output_sym (flinfo, name, &sym, o, NULL); |
if (ret == 0) |
return FALSE; |
else if (ret == 1) |
- finfo->indices[symndx] = indx; |
+ flinfo->indices[symndx] = indx; |
else |
abort (); |
} |
elf_section_data (osec)->this_hdr.sh_info |
- = finfo->indices[symndx]; |
+ = flinfo->indices[symndx]; |
} |
} |
@@ -9395,7 +9507,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
contents = elf_section_data (o)->this_hdr.contents; |
else |
{ |
- contents = finfo->contents; |
+ contents = flinfo->contents; |
if (! bfd_get_full_section_contents (input_bfd, o, &contents)) |
return FALSE; |
} |
@@ -9409,8 +9521,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
/* Get the swapped relocs. */ |
internal_relocs |
- = _bfd_elf_link_read_relocs (input_bfd, o, finfo->external_relocs, |
- finfo->internal_relocs, FALSE); |
+ = _bfd_elf_link_read_relocs (input_bfd, o, flinfo->external_relocs, |
+ flinfo->internal_relocs, FALSE); |
if (internal_relocs == NULL |
&& o->reloc_count > 0) |
return FALSE; |
@@ -9463,7 +9575,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
if (r_symndx >= locsymcount |
|| (elf_bad_symtab (input_bfd) |
- && finfo->sections[r_symndx] == NULL)) |
+ && flinfo->sections[r_symndx] == NULL)) |
{ |
h = sym_hashes[r_symndx - extsymoff]; |
@@ -9501,13 +9613,13 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
Elf_Internal_Sym *sym = isymbuf + r_symndx; |
s_type = ELF_ST_TYPE (sym->st_info); |
- ps = &finfo->sections[r_symndx]; |
+ ps = &flinfo->sections[r_symndx]; |
sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, |
sym, *ps); |
} |
if ((s_type == STT_RELC || s_type == STT_SRELC) |
- && !finfo->info->relocatable) |
+ && !flinfo->info->relocatable) |
{ |
bfd_vma val; |
bfd_vma dot = (rel->r_offset |
@@ -9523,7 +9635,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
(unsigned long) rel->r_info, |
(unsigned long) rel->r_offset); |
#endif |
- if (!eval_symbol (&val, &sym_name, input_bfd, finfo, dot, |
+ if (!eval_symbol (&val, &sym_name, input_bfd, flinfo, dot, |
isymbuf, locsymcount, s_type == STT_SRELC)) |
return FALSE; |
@@ -9537,11 +9649,11 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
{ |
/* Complain if the definition comes from a |
discarded section. */ |
- if ((sec = *ps) != NULL && elf_discarded_section (sec)) |
+ if ((sec = *ps) != NULL && discarded_section (sec)) |
{ |
BFD_ASSERT (r_symndx != STN_UNDEF); |
if (action_discarded & COMPLAIN) |
- (*finfo->info->callbacks->einfo) |
+ (*flinfo->info->callbacks->einfo) |
(_("%X`%s' referenced in section `%A' of %B: " |
"defined in discarded section `%A' of %B\n"), |
sym_name, o, input_bfd, sec, sec->owner); |
@@ -9557,7 +9669,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
asection *kept; |
kept = _bfd_elf_check_kept_section (sec, |
- finfo->info); |
+ flinfo->info); |
if (kept != NULL) |
{ |
*ps = kept; |
@@ -9588,17 +9700,17 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
corresponding to the output section, which will require |
the addend to be adjusted. */ |
- ret = (*relocate_section) (output_bfd, finfo->info, |
+ ret = (*relocate_section) (output_bfd, flinfo->info, |
input_bfd, o, contents, |
internal_relocs, |
isymbuf, |
- finfo->sections); |
+ flinfo->sections); |
if (!ret) |
return FALSE; |
if (ret == 2 |
- || finfo->info->relocatable |
- || finfo->info->emitrelocations) |
+ || flinfo->info->relocatable |
+ || flinfo->info->emitrelocations) |
{ |
Elf_Internal_Rela *irela; |
Elf_Internal_Rela *irelaend, *irelamid; |
@@ -9628,7 +9740,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
rel_hash_list = rel_hash; |
rela_hash_list = NULL; |
last_offset = o->output_offset; |
- if (!finfo->info->relocatable) |
+ if (!flinfo->info->relocatable) |
last_offset += o->output_section->vma; |
for (next_erel = 0; irela < irelaend; irela++, next_erel++) |
{ |
@@ -9650,7 +9762,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
} |
irela->r_offset = _bfd_elf_section_offset (output_bfd, |
- finfo->info, o, |
+ flinfo->info, o, |
irela->r_offset); |
if (irela->r_offset >= (bfd_vma) -2) |
{ |
@@ -9668,7 +9780,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
irela->r_offset += o->output_offset; |
/* Relocs in an executable have to be virtual addresses. */ |
- if (!finfo->info->relocatable) |
+ if (!flinfo->info->relocatable) |
irela->r_offset += o->output_section->vma; |
last_offset = irela->r_offset; |
@@ -9679,7 +9791,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
if (r_symndx >= locsymcount |
|| (elf_bad_symtab (input_bfd) |
- && finfo->sections[r_symndx] == NULL)) |
+ && flinfo->sections[r_symndx] == NULL)) |
{ |
struct elf_link_hash_entry *rh; |
unsigned long indx; |
@@ -9712,7 +9824,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
*rel_hash = NULL; |
sym = isymbuf[r_symndx]; |
- sec = finfo->sections[r_symndx]; |
+ sec = flinfo->sections[r_symndx]; |
if (ELF_ST_TYPE (sym.st_info) == STT_SECTION) |
{ |
/* I suppose the backend ought to fill in the |
@@ -9749,23 +9861,12 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
r_symndx = osec->target_index; |
if (r_symndx == STN_UNDEF) |
{ |
- struct elf_link_hash_table *htab; |
- asection *oi; |
- |
- htab = elf_hash_table (finfo->info); |
- oi = htab->text_index_section; |
- if ((osec->flags & SEC_READONLY) == 0 |
- && htab->data_index_section != NULL) |
- oi = htab->data_index_section; |
- |
- if (oi != NULL) |
- { |
- irela->r_addend += osec->vma - oi->vma; |
- r_symndx = oi->target_index; |
- } |
+ irela->r_addend += osec->vma; |
+ osec = _bfd_nearby_section (output_bfd, osec, |
+ osec->vma); |
+ irela->r_addend -= osec->vma; |
+ r_symndx = osec->target_index; |
} |
- |
- BFD_ASSERT (r_symndx != STN_UNDEF); |
} |
} |
@@ -9776,14 +9877,14 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
} |
else |
{ |
- if (finfo->indices[r_symndx] == -1) |
+ if (flinfo->indices[r_symndx] == -1) |
{ |
unsigned long shlink; |
const char *name; |
asection *osec; |
long indx; |
- if (finfo->info->strip == strip_all) |
+ if (flinfo->info->strip == strip_all) |
{ |
/* You can't do ld -r -s. */ |
bfd_set_error (bfd_error_invalid_operation); |
@@ -9807,32 +9908,32 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
return FALSE; |
sym.st_value += sec->output_offset; |
- if (! finfo->info->relocatable) |
+ if (!flinfo->info->relocatable) |
{ |
sym.st_value += osec->vma; |
if (ELF_ST_TYPE (sym.st_info) == STT_TLS) |
{ |
/* STT_TLS symbols are relative to PT_TLS |
segment base. */ |
- BFD_ASSERT (elf_hash_table (finfo->info) |
+ BFD_ASSERT (elf_hash_table (flinfo->info) |
->tls_sec != NULL); |
- sym.st_value -= (elf_hash_table (finfo->info) |
+ sym.st_value -= (elf_hash_table (flinfo->info) |
->tls_sec->vma); |
} |
} |
indx = bfd_get_symcount (output_bfd); |
- ret = elf_link_output_sym (finfo, name, &sym, sec, |
+ ret = elf_link_output_sym (flinfo, name, &sym, sec, |
NULL); |
if (ret == 0) |
return FALSE; |
else if (ret == 1) |
- finfo->indices[r_symndx] = indx; |
+ flinfo->indices[r_symndx] = indx; |
else |
abort (); |
} |
- r_symndx = finfo->indices[r_symndx]; |
+ r_symndx = flinfo->indices[r_symndx]; |
} |
irela->r_info = ((bfd_vma) r_symndx << r_sym_shift |
@@ -9867,28 +9968,28 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) |
/* Write out the modified section contents. */ |
if (bed->elf_backend_write_section |
- && (*bed->elf_backend_write_section) (output_bfd, finfo->info, o, |
+ && (*bed->elf_backend_write_section) (output_bfd, flinfo->info, o, |
contents)) |
{ |
/* Section written out. */ |
} |
else switch (o->sec_info_type) |
{ |
- case ELF_INFO_TYPE_STABS: |
+ case SEC_INFO_TYPE_STABS: |
if (! (_bfd_write_section_stabs |
(output_bfd, |
- &elf_hash_table (finfo->info)->stab_info, |
+ &elf_hash_table (flinfo->info)->stab_info, |
o, &elf_section_data (o)->sec_info, contents))) |
return FALSE; |
break; |
- case ELF_INFO_TYPE_MERGE: |
+ case SEC_INFO_TYPE_MERGE: |
if (! _bfd_write_merged_section (output_bfd, o, |
elf_section_data (o)->sec_info)) |
return FALSE; |
break; |
- case ELF_INFO_TYPE_EH_FRAME: |
+ case SEC_INFO_TYPE_EH_FRAME: |
{ |
- if (! _bfd_elf_write_section_eh_frame (output_bfd, finfo->info, |
+ if (! _bfd_elf_write_section_eh_frame (output_bfd, flinfo->info, |
o, contents)) |
return FALSE; |
} |
@@ -10265,7 +10366,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
bfd_boolean dynamic; |
bfd_boolean emit_relocs; |
bfd *dynobj; |
- struct elf_final_link_info finfo; |
+ struct elf_final_link_info flinfo; |
asection *o; |
struct bfd_link_order *p; |
bfd *sub; |
@@ -10302,39 +10403,40 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
emit_relocs = (info->relocatable |
|| info->emitrelocations); |
- finfo.info = info; |
- finfo.output_bfd = abfd; |
- finfo.symstrtab = _bfd_elf_stringtab_init (); |
- if (finfo.symstrtab == NULL) |
+ flinfo.info = info; |
+ flinfo.output_bfd = abfd; |
+ flinfo.symstrtab = _bfd_elf_stringtab_init (); |
+ if (flinfo.symstrtab == NULL) |
return FALSE; |
if (! dynamic) |
{ |
- finfo.dynsym_sec = NULL; |
- finfo.hash_sec = NULL; |
- finfo.symver_sec = NULL; |
+ flinfo.dynsym_sec = NULL; |
+ flinfo.hash_sec = NULL; |
+ flinfo.symver_sec = NULL; |
} |
else |
{ |
- finfo.dynsym_sec = bfd_get_section_by_name (dynobj, ".dynsym"); |
- finfo.hash_sec = bfd_get_section_by_name (dynobj, ".hash"); |
- BFD_ASSERT (finfo.dynsym_sec != NULL); |
- finfo.symver_sec = bfd_get_section_by_name (dynobj, ".gnu.version"); |
+ flinfo.dynsym_sec = bfd_get_linker_section (dynobj, ".dynsym"); |
+ flinfo.hash_sec = bfd_get_linker_section (dynobj, ".hash"); |
+ /* Note that dynsym_sec can be NULL (on VMS). */ |
+ flinfo.symver_sec = bfd_get_linker_section (dynobj, ".gnu.version"); |
/* Note that it is OK if symver_sec is NULL. */ |
} |
- finfo.contents = NULL; |
- finfo.external_relocs = NULL; |
- finfo.internal_relocs = NULL; |
- finfo.external_syms = NULL; |
- finfo.locsym_shndx = NULL; |
- finfo.internal_syms = NULL; |
- finfo.indices = NULL; |
- finfo.sections = NULL; |
- finfo.symbuf = NULL; |
- finfo.symshndxbuf = NULL; |
- finfo.symbuf_count = 0; |
- finfo.shndxbuf_size = 0; |
+ flinfo.contents = NULL; |
+ flinfo.external_relocs = NULL; |
+ flinfo.internal_relocs = NULL; |
+ flinfo.external_syms = NULL; |
+ flinfo.locsym_shndx = NULL; |
+ flinfo.internal_syms = NULL; |
+ flinfo.indices = NULL; |
+ flinfo.sections = NULL; |
+ flinfo.symbuf = NULL; |
+ flinfo.symshndxbuf = NULL; |
+ flinfo.symbuf_count = 0; |
+ flinfo.shndxbuf_size = 0; |
+ flinfo.filesym_count = 0; |
/* The object attributes have been merged. Remove the input |
sections from the link, and set the contents of the output |
@@ -10408,7 +10510,13 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
if (sec->flags & SEC_MERGE) |
merged = TRUE; |
- if (info->relocatable || info->emitrelocations) |
+ if (esdo->this_hdr.sh_type == SHT_REL |
+ || esdo->this_hdr.sh_type == SHT_RELA) |
+ /* Some backends use reloc_count in relocation sections |
+ to count particular types of relocs. Of course, |
+ reloc sections themselves can't have relocations. */ |
+ reloc_count = 0; |
+ else if (info->relocatable || info->emitrelocations) |
reloc_count = sec->reloc_count; |
else if (bed->elf_backend_count_relocs) |
reloc_count = (*bed->elf_backend_count_relocs) (info, sec); |
@@ -10556,22 +10664,22 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
/* Allocate a buffer to hold swapped out symbols. This is to avoid |
continuously seeking to the right position in the file. */ |
if (! info->keep_memory || max_sym_count < 20) |
- finfo.symbuf_size = 20; |
+ flinfo.symbuf_size = 20; |
else |
- finfo.symbuf_size = max_sym_count; |
- amt = finfo.symbuf_size; |
+ flinfo.symbuf_size = max_sym_count; |
+ amt = flinfo.symbuf_size; |
amt *= bed->s->sizeof_sym; |
- finfo.symbuf = (bfd_byte *) bfd_malloc (amt); |
- if (finfo.symbuf == NULL) |
+ flinfo.symbuf = (bfd_byte *) bfd_malloc (amt); |
+ if (flinfo.symbuf == NULL) |
goto error_return; |
if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF)) |
{ |
/* Wild guess at number of output symbols. realloc'd as needed. */ |
amt = 2 * max_sym_count + elf_numsections (abfd) + 1000; |
- finfo.shndxbuf_size = amt; |
+ flinfo.shndxbuf_size = amt; |
amt *= sizeof (Elf_External_Sym_Shndx); |
- finfo.symshndxbuf = (Elf_External_Sym_Shndx *) bfd_zmalloc (amt); |
- if (finfo.symshndxbuf == NULL) |
+ flinfo.symshndxbuf = (Elf_External_Sym_Shndx *) bfd_zmalloc (amt); |
+ if (flinfo.symshndxbuf == NULL) |
goto error_return; |
} |
@@ -10586,7 +10694,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
elfsym.st_other = 0; |
elfsym.st_shndx = SHN_UNDEF; |
elfsym.st_target_internal = 0; |
- if (elf_link_output_sym (&finfo, NULL, &elfsym, bfd_und_section_ptr, |
+ if (elf_link_output_sym (&flinfo, NULL, &elfsym, bfd_und_section_ptr, |
NULL) != 1) |
goto error_return; |
} |
@@ -10613,7 +10721,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
elfsym.st_shndx = i; |
if (!info->relocatable) |
elfsym.st_value = o->vma; |
- if (elf_link_output_sym (&finfo, NULL, &elfsym, o, NULL) != 1) |
+ if (elf_link_output_sym (&flinfo, NULL, &elfsym, o, NULL) != 1) |
goto error_return; |
} |
} |
@@ -10623,15 +10731,15 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
files. */ |
if (max_contents_size != 0) |
{ |
- finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size); |
- if (finfo.contents == NULL) |
+ flinfo.contents = (bfd_byte *) bfd_malloc (max_contents_size); |
+ if (flinfo.contents == NULL) |
goto error_return; |
} |
if (max_external_reloc_size != 0) |
{ |
- finfo.external_relocs = bfd_malloc (max_external_reloc_size); |
- if (finfo.external_relocs == NULL) |
+ flinfo.external_relocs = bfd_malloc (max_external_reloc_size); |
+ if (flinfo.external_relocs == NULL) |
goto error_return; |
} |
@@ -10639,39 +10747,39 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
{ |
amt = max_internal_reloc_count * bed->s->int_rels_per_ext_rel; |
amt *= sizeof (Elf_Internal_Rela); |
- finfo.internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt); |
- if (finfo.internal_relocs == NULL) |
+ flinfo.internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt); |
+ if (flinfo.internal_relocs == NULL) |
goto error_return; |
} |
if (max_sym_count != 0) |
{ |
amt = max_sym_count * bed->s->sizeof_sym; |
- finfo.external_syms = (bfd_byte *) bfd_malloc (amt); |
- if (finfo.external_syms == NULL) |
+ flinfo.external_syms = (bfd_byte *) bfd_malloc (amt); |
+ if (flinfo.external_syms == NULL) |
goto error_return; |
amt = max_sym_count * sizeof (Elf_Internal_Sym); |
- finfo.internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt); |
- if (finfo.internal_syms == NULL) |
+ flinfo.internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt); |
+ if (flinfo.internal_syms == NULL) |
goto error_return; |
amt = max_sym_count * sizeof (long); |
- finfo.indices = (long int *) bfd_malloc (amt); |
- if (finfo.indices == NULL) |
+ flinfo.indices = (long int *) bfd_malloc (amt); |
+ if (flinfo.indices == NULL) |
goto error_return; |
amt = max_sym_count * sizeof (asection *); |
- finfo.sections = (asection **) bfd_malloc (amt); |
- if (finfo.sections == NULL) |
+ flinfo.sections = (asection **) bfd_malloc (amt); |
+ if (flinfo.sections == NULL) |
goto error_return; |
} |
if (max_sym_shndx_count != 0) |
{ |
amt = max_sym_shndx_count * sizeof (Elf_External_Sym_Shndx); |
- finfo.locsym_shndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt); |
- if (finfo.locsym_shndx == NULL) |
+ flinfo.locsym_shndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt); |
+ if (flinfo.locsym_shndx == NULL) |
goto error_return; |
} |
@@ -10745,7 +10853,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
{ |
if (! sub->output_has_begun) |
{ |
- if (! elf_link_input_bfd (&finfo, sub)) |
+ if (! elf_link_input_bfd (&flinfo, sub)) |
goto error_return; |
sub->output_has_begun = TRUE; |
} |
@@ -10803,6 +10911,17 @@ 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 |
@@ -10810,12 +10929,27 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
some global symbols were, in fact, converted to become local. |
FIXME: Will this work correctly with the Irix 5 linker? */ |
eoinfo.failed = FALSE; |
- eoinfo.finfo = &finfo; |
+ eoinfo.flinfo = &flinfo; |
eoinfo.localsyms = TRUE; |
+ eoinfo.need_second_pass = FALSE; |
+ eoinfo.second_pass = 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; |
+ bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo); |
+ if (eoinfo.failed) |
+ return FALSE; |
+ } |
+ |
/* If backend needs to output some local symbols not present in the hash |
table, do it now. */ |
if (bed->elf_backend_output_arch_local_syms) |
@@ -10825,7 +10959,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
struct elf_link_hash_entry *); |
if (! ((*bed->elf_backend_output_arch_local_syms) |
- (abfd, info, &finfo, (out_sym_func) elf_link_output_sym))) |
+ (abfd, info, &flinfo, (out_sym_func) elf_link_output_sym))) |
return FALSE; |
} |
@@ -10838,10 +10972,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
symtab_hdr->sh_info = bfd_get_symcount (abfd); |
if (dynamic |
- && finfo.dynsym_sec->output_section != bfd_abs_section_ptr) |
+ && flinfo.dynsym_sec != NULL |
+ && flinfo.dynsym_sec->output_section != bfd_abs_section_ptr) |
{ |
Elf_Internal_Sym sym; |
- bfd_byte *dynsym = finfo.dynsym_sec->contents; |
+ bfd_byte *dynsym = flinfo.dynsym_sec->contents; |
long last_local = 0; |
/* Write out the section symbols for the output sections. */ |
@@ -10913,14 +11048,14 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
} |
} |
- elf_section_data (finfo.dynsym_sec->output_section)->this_hdr.sh_info = |
+ elf_section_data (flinfo.dynsym_sec->output_section)->this_hdr.sh_info = |
last_local + 1; |
} |
/* We get the global symbols from the hash table. */ |
eoinfo.failed = FALSE; |
eoinfo.localsyms = FALSE; |
- eoinfo.finfo = &finfo; |
+ eoinfo.flinfo = &flinfo; |
bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo); |
if (eoinfo.failed) |
return FALSE; |
@@ -10934,12 +11069,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
struct elf_link_hash_entry *); |
if (! ((*bed->elf_backend_output_arch_syms) |
- (abfd, info, &finfo, (out_sym_func) elf_link_output_sym))) |
+ (abfd, info, &flinfo, (out_sym_func) elf_link_output_sym))) |
return FALSE; |
} |
/* Flush all symbols to the file. */ |
- if (! elf_link_flush_output_syms (&finfo, bed)) |
+ if (! elf_link_flush_output_syms (&flinfo, bed)) |
return FALSE; |
/* Now we know the size of the symtab section. */ |
@@ -10958,7 +11093,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
off, TRUE); |
if (bfd_seek (abfd, symtab_shndx_hdr->sh_offset, SEEK_SET) != 0 |
- || (bfd_bwrite (finfo.symshndxbuf, amt, abfd) != amt)) |
+ || (bfd_bwrite (flinfo.symshndxbuf, amt, abfd) != amt)) |
return FALSE; |
} |
@@ -10970,7 +11105,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
symstrtab_hdr->sh_type = SHT_STRTAB; |
symstrtab_hdr->sh_flags = 0; |
symstrtab_hdr->sh_addr = 0; |
- symstrtab_hdr->sh_size = _bfd_stringtab_size (finfo.symstrtab); |
+ symstrtab_hdr->sh_size = _bfd_stringtab_size (flinfo.symstrtab); |
symstrtab_hdr->sh_entsize = 0; |
symstrtab_hdr->sh_link = 0; |
symstrtab_hdr->sh_info = 0; |
@@ -10983,7 +11118,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
if (bfd_get_symcount (abfd) > 0) |
{ |
if (bfd_seek (abfd, symstrtab_hdr->sh_offset, SEEK_SET) != 0 |
- || ! _bfd_stringtab_emit (abfd, finfo.symstrtab)) |
+ || ! _bfd_stringtab_emit (abfd, flinfo.symstrtab)) |
return FALSE; |
} |
@@ -11014,7 +11149,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
bfd_byte *dyncon, *dynconend; |
/* Fix up .dynamic entries. */ |
- o = bfd_get_section_by_name (dynobj, ".dynamic"); |
+ o = bfd_get_linker_section (dynobj, ".dynamic"); |
BFD_ASSERT (o != NULL); |
dyncon = o->contents; |
@@ -11190,7 +11325,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
/* Check for DT_TEXTREL (late, in case the backend removes it). */ |
if (((info->warn_shared_textrel && info->shared) |
|| info->error_textrel) |
- && (o = bfd_get_section_by_name (dynobj, ".dynamic")) != NULL) |
+ && (o = bfd_get_linker_section (dynobj, ".dynamic")) != NULL) |
{ |
bfd_byte *dyncon, *dynconend; |
@@ -11231,9 +11366,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
continue; |
if (elf_hash_table (info)->eh_info.hdr_sec == o) |
continue; |
- if ((elf_section_data (o->output_section)->this_hdr.sh_type |
- != SHT_STRTAB) |
- && (strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0)) |
+ if (strcmp (o->name, ".dynstr") != 0) |
{ |
/* FIXME: octets_per_byte. */ |
if (! bfd_set_section_contents (abfd, o->output_section, |
@@ -11277,28 +11410,28 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
goto error_return; |
} |
- if (finfo.symstrtab != NULL) |
- _bfd_stringtab_free (finfo.symstrtab); |
- if (finfo.contents != NULL) |
- free (finfo.contents); |
- if (finfo.external_relocs != NULL) |
- free (finfo.external_relocs); |
- if (finfo.internal_relocs != NULL) |
- free (finfo.internal_relocs); |
- if (finfo.external_syms != NULL) |
- free (finfo.external_syms); |
- if (finfo.locsym_shndx != NULL) |
- free (finfo.locsym_shndx); |
- if (finfo.internal_syms != NULL) |
- free (finfo.internal_syms); |
- if (finfo.indices != NULL) |
- free (finfo.indices); |
- if (finfo.sections != NULL) |
- free (finfo.sections); |
- if (finfo.symbuf != NULL) |
- free (finfo.symbuf); |
- if (finfo.symshndxbuf != NULL) |
- free (finfo.symshndxbuf); |
+ 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); |
@@ -11323,28 +11456,28 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
return TRUE; |
error_return: |
- if (finfo.symstrtab != NULL) |
- _bfd_stringtab_free (finfo.symstrtab); |
- if (finfo.contents != NULL) |
- free (finfo.contents); |
- if (finfo.external_relocs != NULL) |
- free (finfo.external_relocs); |
- if (finfo.internal_relocs != NULL) |
- free (finfo.internal_relocs); |
- if (finfo.external_syms != NULL) |
- free (finfo.external_syms); |
- if (finfo.locsym_shndx != NULL) |
- free (finfo.locsym_shndx); |
- if (finfo.internal_syms != NULL) |
- free (finfo.internal_syms); |
- if (finfo.indices != NULL) |
- free (finfo.indices); |
- if (finfo.sections != NULL) |
- free (finfo.sections); |
- if (finfo.symbuf != NULL) |
- free (finfo.symbuf); |
- if (finfo.symshndxbuf != NULL) |
- free (finfo.symshndxbuf); |
+ 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); |
@@ -11575,6 +11708,12 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec, |
|| h->root.type == bfd_link_hash_warning) |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
h->mark = 1; |
+ /* If this symbol is weak and there is a non-weak definition, we |
+ keep the non-weak definition because many backends put |
+ dynamic reloc info on the non-weak definition for code |
+ handling copy relocs. */ |
+ if (h->u.weakdef != NULL) |
+ h->u.weakdef->mark = 1; |
return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL); |
} |
@@ -11597,7 +11736,8 @@ _bfd_elf_gc_mark_reloc (struct bfd_link_info *info, |
rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie); |
if (rsec && !rsec->gc_mark) |
{ |
- if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour) |
+ if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour |
+ || (rsec->owner->flags & DYNAMIC) != 0) |
rsec->gc_mark = 1; |
else if (!_bfd_elf_gc_mark (info, rsec, gc_mark_hook)) |
return FALSE; |
@@ -12008,12 +12148,14 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) |
struct elf_reloc_cookie cookie; |
sec = bfd_get_section_by_name (sub, ".eh_frame"); |
- if (sec && init_reloc_cookie_for_section (&cookie, info, sec)) |
+ while (sec && init_reloc_cookie_for_section (&cookie, info, sec)) |
{ |
_bfd_elf_parse_eh_frame (sub, info, sec, &cookie); |
- if (elf_section_data (sec)->sec_info) |
+ if (elf_section_data (sec)->sec_info |
+ && (sec->flags & SEC_LINKER_CREATED) == 0) |
elf_eh_frame_section (sub) = sec; |
fini_reloc_cookie_for_section (&cookie, sec); |
+ sec = bfd_get_next_section_by_name (sec); |
} |
} |
_bfd_elf_end_eh_frame_parsing (info); |
@@ -12229,58 +12371,73 @@ static elf_flags_to_name_table elf_flags_to_names [] = |
{ "SHF_EXCLUDE", SHF_EXCLUDE }, |
}; |
-void |
+/* Returns TRUE if the section is to be included, otherwise FALSE. */ |
+bfd_boolean |
bfd_elf_lookup_section_flags (struct bfd_link_info *info, |
- struct flag_info *finfo) |
+ struct flag_info *flaginfo, |
+ asection *section) |
{ |
- bfd *output_bfd = info->output_bfd; |
- const struct elf_backend_data *bed = get_elf_backend_data (output_bfd); |
- struct flag_info_list *tf = finfo->flag_list; |
- int with_hex = 0; |
- int without_hex = 0; |
+ const bfd_vma sh_flags = elf_section_flags (section); |
- for (tf = finfo->flag_list; tf != NULL; tf = tf->next) |
+ if (!flaginfo->flags_initialized) |
{ |
- int i; |
- if (bed->elf_backend_lookup_section_flags_hook) |
+ bfd *obfd = info->output_bfd; |
+ const struct elf_backend_data *bed = get_elf_backend_data (obfd); |
+ struct flag_info_list *tf = flaginfo->flag_list; |
+ int with_hex = 0; |
+ int without_hex = 0; |
+ |
+ for (tf = flaginfo->flag_list; tf != NULL; tf = tf->next) |
{ |
- flagword hexval = |
- (*bed->elf_backend_lookup_section_flags_hook) ((char *) tf->name); |
+ unsigned i; |
+ flagword (*lookup) (char *); |
- if (hexval != 0) |
+ lookup = bed->elf_backend_lookup_section_flags_hook; |
+ if (lookup != NULL) |
{ |
- if (tf->with == with_flags) |
- with_hex |= hexval; |
- else if (tf->with == without_flags) |
- without_hex |= hexval; |
- tf->valid = TRUE; |
- continue; |
+ flagword hexval = (*lookup) ((char *) tf->name); |
+ |
+ if (hexval != 0) |
+ { |
+ if (tf->with == with_flags) |
+ with_hex |= hexval; |
+ else if (tf->with == without_flags) |
+ without_hex |= hexval; |
+ tf->valid = TRUE; |
+ continue; |
+ } |
} |
- } |
- for (i = 0; i < 12; i++) |
- { |
- if (!strcmp (tf->name, elf_flags_to_names[i].flag_name)) |
+ for (i = 0; i < ARRAY_SIZE (elf_flags_to_names); ++i) |
{ |
- if (tf->with == with_flags) |
- with_hex |= elf_flags_to_names[i].flag_value; |
- else if (tf->with == without_flags) |
- without_hex |= elf_flags_to_names[i].flag_value; |
- tf->valid = TRUE; |
- continue; |
+ if (strcmp (tf->name, elf_flags_to_names[i].flag_name) == 0) |
+ { |
+ if (tf->with == with_flags) |
+ with_hex |= elf_flags_to_names[i].flag_value; |
+ else if (tf->with == without_flags) |
+ without_hex |= elf_flags_to_names[i].flag_value; |
+ tf->valid = TRUE; |
+ break; |
+ } |
} |
- } |
- if (tf->valid == FALSE) |
- { |
- info->callbacks->einfo |
+ if (!tf->valid) |
+ { |
+ info->callbacks->einfo |
(_("Unrecognized INPUT_SECTION_FLAG %s\n"), tf->name); |
- return; |
+ return FALSE; |
+ } |
} |
+ flaginfo->flags_initialized = TRUE; |
+ flaginfo->only_with_flags |= with_hex; |
+ flaginfo->not_with_flags |= without_hex; |
} |
- finfo->flags_initialized = TRUE; |
- finfo->only_with_flags |= with_hex; |
- finfo->not_with_flags |= without_hex; |
- return; |
+ if ((flaginfo->only_with_flags & sh_flags) != flaginfo->only_with_flags) |
+ return FALSE; |
+ |
+ if ((flaginfo->not_with_flags & sh_flags) != 0) |
+ return FALSE; |
+ |
+ return TRUE; |
} |
struct alloc_got_off_arg { |
@@ -12423,7 +12580,7 @@ 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) |
- && elf_discarded_section (h->root.u.def.section)) |
+ && discarded_section (h->root.u.def.section)) |
return TRUE; |
else |
return FALSE; |
@@ -12439,7 +12596,7 @@ 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 && elf_discarded_section (isec)) |
+ if (isec != NULL && discarded_section (isec)) |
return TRUE; |
} |
return FALSE; |
@@ -12473,24 +12630,21 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) |
bed = get_elf_backend_data (abfd); |
- if ((abfd->flags & DYNAMIC) != 0) |
- continue; |
- |
eh = NULL; |
if (!info->relocatable) |
{ |
eh = bfd_get_section_by_name (abfd, ".eh_frame"); |
- if (eh != NULL |
- && (eh->size == 0 |
- || bfd_is_abs_section (eh->output_section))) |
- eh = NULL; |
+ 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 != ELF_INFO_TYPE_STABS)) |
+ || stab->sec_info_type != SEC_INFO_TYPE_STABS)) |
stab = NULL; |
if (stab == NULL |
@@ -12513,8 +12667,8 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) |
fini_reloc_cookie_rels (&cookie, stab); |
} |
- if (eh != NULL |
- && init_reloc_cookie_rels (&cookie, info, abfd, eh)) |
+ while (eh != NULL |
+ && init_reloc_cookie_rels (&cookie, info, abfd, eh)) |
{ |
_bfd_elf_parse_eh_frame (abfd, info, eh, &cookie); |
if (_bfd_elf_discard_section_eh_frame (abfd, info, eh, |
@@ -12522,6 +12676,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) |
&cookie)) |
ret = TRUE; |
fini_reloc_cookie_rels (&cookie, eh); |
+ eh = bfd_get_next_section_by_name (eh); |
} |
if (bed->elf_backend_discard_info != NULL |
@@ -12757,7 +12912,7 @@ _bfd_elf_get_dynamic_reloc_section (bfd * abfd, |
if (name != NULL) |
{ |
- reloc_sec = bfd_get_section_by_name (abfd, name); |
+ reloc_sec = bfd_get_linker_section (abfd, name); |
if (reloc_sec != NULL) |
elf_section_data (sec)->sreloc = reloc_sec; |
@@ -12793,17 +12948,16 @@ _bfd_elf_make_dynamic_reloc_section (asection * sec, |
if (name == NULL) |
return NULL; |
- reloc_sec = bfd_get_section_by_name (dynobj, name); |
+ reloc_sec = bfd_get_linker_section (dynobj, name); |
if (reloc_sec == NULL) |
{ |
- flagword flags; |
- |
- flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_IN_MEMORY | SEC_LINKER_CREATED); |
+ flagword flags = (SEC_HAS_CONTENTS | SEC_READONLY |
+ | SEC_IN_MEMORY | SEC_LINKER_CREATED); |
if ((sec->flags & SEC_ALLOC) != 0) |
flags |= SEC_ALLOC | SEC_LOAD; |
- reloc_sec = bfd_make_section_with_flags (dynobj, name, flags); |
+ reloc_sec = bfd_make_section_anyway_with_flags (dynobj, name, flags); |
if (reloc_sec != NULL) |
{ |
if (! bfd_set_section_alignment (dynobj, reloc_sec, alignment)) |