1,5 → 1,5 |
/* ELF linking support for BFD. |
Copyright 1995-2013 Free Software Foundation, Inc. |
Copyright (C) 1995-2015 Free Software Foundation, Inc. |
|
This file is part of BFD, the Binary File Descriptor library. |
|
20,6 → 20,7 |
|
#include "sysdep.h" |
#include "bfd.h" |
#include "bfd_stdint.h" |
#include "bfdlink.h" |
#include "libbfd.h" |
#define ARCH_SIZE 0 |
53,6 → 54,47 |
static bfd_boolean _bfd_elf_fix_symbol_flags |
(struct elf_link_hash_entry *, struct elf_info_failed *); |
|
asection * |
_bfd_elf_section_for_symbol (struct elf_reloc_cookie *cookie, |
unsigned long r_symndx, |
bfd_boolean discard) |
{ |
if (r_symndx >= cookie->locsymcount |
|| ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL) |
{ |
struct elf_link_hash_entry *h; |
|
h = cookie->sym_hashes[r_symndx - cookie->extsymoff]; |
|
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; |
|
if ((h->root.type == bfd_link_hash_defined |
|| h->root.type == bfd_link_hash_defweak) |
&& discarded_section (h->root.u.def.section)) |
return h->root.u.def.section; |
else |
return NULL; |
} |
else |
{ |
/* It's not a relocation against a global symbol, |
but it could be a relocation against a local |
symbol for a discarded section. */ |
asection *isec; |
Elf_Internal_Sym *isym; |
|
/* Need to: get the symbol; get the section. */ |
isym = &cookie->locsyms[r_symndx]; |
isec = bfd_section_from_elf_index (cookie->abfd, isym->st_shndx); |
if (isec != NULL |
&& discard ? discarded_section (isec) : 1) |
return isec; |
} |
return NULL; |
} |
|
/* Define a symbol in a dynamic linkage section. */ |
|
struct elf_link_hash_entry * |
76,19 → 118,19 |
} |
|
bh = &h->root; |
bed = get_elf_backend_data (abfd); |
if (!_bfd_generic_link_add_one_symbol (info, abfd, name, BSF_GLOBAL, |
sec, 0, NULL, FALSE, |
get_elf_backend_data (abfd)->collect, |
sec, 0, NULL, FALSE, bed->collect, |
&bh)) |
return NULL; |
h = (struct elf_link_hash_entry *) bh; |
h->def_regular = 1; |
h->non_elf = 0; |
h->root.linker_def = 1; |
h->type = STT_OBJECT; |
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); |
return h; |
} |
204,7 → 246,7 |
|
/* A dynamically linked executable has a .interp section, but a |
shared library does not. */ |
if (info->executable) |
if (bfd_link_executable (info) && !info->nointerp) |
{ |
s = bfd_make_section_anyway_with_flags (abfd, ".interp", |
flags | SEC_READONLY); |
237,6 → 279,7 |
if (s == NULL |
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) |
return FALSE; |
elf_hash_table (info)->dynsym = s; |
|
s = bfd_make_section_anyway_with_flags (abfd, ".dynstr", |
flags | SEC_READONLY); |
376,7 → 419,7 |
be needed, we can discard it later. We will never need this |
section when generating a shared object, since they do not use |
copy relocs. */ |
if (! info->shared) |
if (! bfd_link_pic (info)) |
{ |
s = bfd_make_section_anyway_with_flags (abfd, |
(bed->rela_plts_and_copies_p |
477,7 → 520,7 |
struct bfd_elf_dynamic_list *d = info->dynamic_list; |
|
/* It may be called more than once on the same H. */ |
if(h->dynamic || info->relocatable) |
if(h->dynamic || bfd_link_relocatable (info)) |
return; |
|
if ((info->dynamic_data |
581,7 → 624,7 |
|
/* STV_HIDDEN and STV_INTERNAL symbols must be STB_LOCAL in shared objects |
and executables. */ |
if (!info->relocatable |
if (!bfd_link_relocatable (info) |
&& h->dynindx != -1 |
&& (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN |
|| ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)) |
589,8 → 632,9 |
|
if ((h->def_dynamic |
|| h->ref_dynamic |
|| info->shared |
|| (info->executable && elf_hash_table (info)->is_relocatable_executable)) |
|| bfd_link_pic (info) |
|| (bfd_link_pde (info) |
&& elf_hash_table (info)->is_relocatable_executable)) |
&& h->dynindx == -1) |
{ |
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
760,6 → 804,7 |
asection *p) |
{ |
struct elf_link_hash_table *htab; |
asection *ip; |
|
switch (elf_section_data (p)->this_hdr.sh_type) |
{ |
775,18 → 820,9 |
if (htab->text_index_section != NULL) |
return p != htab->text_index_section && p != htab->data_index_section; |
|
if (strcmp (p->name, ".got") == 0 |
|| strcmp (p->name, ".got.plt") == 0 |
|| strcmp (p->name, ".plt") == 0) |
{ |
asection *ip; |
|
if (htab->dynobj != NULL |
return (htab->dynobj != NULL |
&& (ip = bfd_get_linker_section (htab->dynobj, p->name)) != NULL |
&& ip->output_section == p) |
return TRUE; |
} |
return FALSE; |
&& ip->output_section == p); |
|
/* There shouldn't be section relative relocations |
against any other section. */ |
808,7 → 844,8 |
{ |
unsigned long dynsymcount = 0; |
|
if (info->shared || elf_hash_table (info)->is_relocatable_executable) |
if (bfd_link_pic (info) |
|| elf_hash_table (info)->is_relocatable_executable) |
{ |
const struct elf_backend_data *bed = get_elf_backend_data (output_bfd); |
asection *p; |
851,48 → 888,31 |
|
static void |
elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h, |
Elf_Internal_Sym *isym, bfd_boolean definition, |
bfd_boolean dynamic) |
const Elf_Internal_Sym *isym, asection *sec, |
bfd_boolean definition, bfd_boolean dynamic) |
{ |
const struct elf_backend_data *bed = get_elf_backend_data (abfd); |
|
/* If st_other has a processor-specific meaning, specific |
code might be needed here. We never merge the visibility |
attribute with the one from a dynamic object. */ |
code might be needed here. */ |
if (bed->elf_backend_merge_symbol_attribute) |
(*bed->elf_backend_merge_symbol_attribute) (h, isym, definition, |
dynamic); |
|
/* If this symbol has default visibility and the user has requested |
we not re-export it, then mark it as hidden. */ |
if (definition |
&& !dynamic |
&& (abfd->no_export |
|| (abfd->my_archive && abfd->my_archive->no_export)) |
&& ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL) |
isym->st_other = (STV_HIDDEN |
| (isym->st_other & ~ELF_ST_VISIBILITY (-1))); |
|
if (!dynamic && ELF_ST_VISIBILITY (isym->st_other) != 0) |
if (!dynamic) |
{ |
unsigned char hvis, symvis, other, nvis; |
unsigned symvis = ELF_ST_VISIBILITY (isym->st_other); |
unsigned hvis = ELF_ST_VISIBILITY (h->other); |
|
/* Only merge the visibility. Leave the remainder of the |
st_other field to elf_backend_merge_symbol_attribute. */ |
other = h->other & ~ELF_ST_VISIBILITY (-1); |
|
/* Combine visibilities, using the most constraining one. */ |
hvis = ELF_ST_VISIBILITY (h->other); |
symvis = ELF_ST_VISIBILITY (isym->st_other); |
if (! hvis) |
nvis = symvis; |
else if (! symvis) |
nvis = hvis; |
else |
nvis = hvis < symvis ? hvis : symvis; |
|
h->other = other | nvis; |
/* Keep the most constraining visibility. Leave the remainder |
of the st_other field to elf_backend_merge_symbol_attribute. */ |
if (symvis - 1 < hvis - 1) |
h->other = symvis | (h->other & ~ELF_ST_VISIBILITY (-1)); |
} |
else if (definition |
&& ELF_ST_VISIBILITY (isym->st_other) != STV_DEFAULT |
&& (sec->flags & SEC_READONLY) == 0) |
h->protected_def = 1; |
} |
|
/* This function is called when we want to merge a new symbol with an |
922,7 → 942,8 |
bfd_boolean *skip, |
bfd_boolean *override, |
bfd_boolean *type_change_ok, |
bfd_boolean *size_change_ok) |
bfd_boolean *size_change_ok, |
bfd_boolean *matched) |
{ |
asection *sec, *oldsec; |
struct elf_link_hash_entry *h; |
933,6 → 954,7 |
bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon; |
bfd_boolean newweak, oldweak, newfunc, oldfunc; |
const struct elf_backend_data *bed; |
char *new_version; |
|
*skip = FALSE; |
*override = FALSE; |
951,6 → 973,30 |
|
bed = get_elf_backend_data (abfd); |
|
/* NEW_VERSION is the symbol version of the new symbol. */ |
if (h->versioned != unversioned) |
{ |
/* Symbol version is unknown or versioned. */ |
new_version = strrchr (name, ELF_VER_CHR); |
if (new_version) |
{ |
if (h->versioned == unknown) |
{ |
if (new_version > name && new_version[-1] != ELF_VER_CHR) |
h->versioned = versioned_hidden; |
else |
h->versioned = versioned; |
} |
new_version += 1; |
if (new_version[0] == '\0') |
new_version = NULL; |
} |
else |
h->versioned = unversioned; |
} |
else |
new_version = NULL; |
|
/* For merging, we only care about real symbols. But we need to make |
sure that indirect symbol dynamic flags are updated. */ |
hi = h; |
958,6 → 1004,44 |
|| h->root.type == bfd_link_hash_warning) |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
|
if (!*matched) |
{ |
if (hi == h || h->root.type == bfd_link_hash_new) |
*matched = TRUE; |
else |
{ |
/* OLD_HIDDEN is true if the existing symbol is only visible |
to the symbol with the same symbol version. NEW_HIDDEN is |
true if the new symbol is only visible to the symbol with |
the same symbol version. */ |
bfd_boolean old_hidden = h->versioned == versioned_hidden; |
bfd_boolean new_hidden = hi->versioned == versioned_hidden; |
if (!old_hidden && !new_hidden) |
/* The new symbol matches the existing symbol if both |
aren't hidden. */ |
*matched = TRUE; |
else |
{ |
/* OLD_VERSION is the symbol version of the existing |
symbol. */ |
char *old_version; |
|
if (h->versioned >= versioned) |
old_version = strrchr (h->root.root.string, |
ELF_VER_CHR) + 1; |
else |
old_version = NULL; |
|
/* The new symbol matches the existing symbol if they |
have the same symbol version. */ |
*matched = (old_version == new_version |
|| (old_version != NULL |
&& new_version != NULL |
&& strcmp (old_version, new_version) == 0)); |
} |
} |
} |
|
/* OLDBFD and OLDSEC are a BFD and an ASECTION associated with the |
existing symbol. */ |
|
1030,6 → 1114,8 |
} |
else |
{ |
/* Update the existing symbol only if they match. */ |
if (*matched) |
h->dynamic_def = 1; |
hi->dynamic_def = 1; |
} |
1087,32 → 1173,30 |
|
/* When we try to create a default indirect symbol from the dynamic |
definition with the default version, we skip it if its type and |
the type of existing regular definition mismatch. We only do it |
if the existing regular definition won't be dynamic. */ |
the type of existing regular definition mismatch. */ |
if (pold_alignment == NULL |
&& !info->shared |
&& !info->export_dynamic |
&& !h->ref_dynamic |
&& newdyn |
&& newdef |
&& !olddyn |
&& (olddef || h->root.type == bfd_link_hash_common) |
&& (((olddef || h->root.type == bfd_link_hash_common) |
&& ELF_ST_TYPE (sym->st_info) != h->type |
&& ELF_ST_TYPE (sym->st_info) != STT_NOTYPE |
&& h->type != STT_NOTYPE |
&& !(newfunc && oldfunc)) |
|| (olddef |
&& ((h->type == STT_GNU_IFUNC) |
!= (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC))))) |
{ |
*skip = TRUE; |
return TRUE; |
} |
|
/* Plugin symbol type isn't currently set. Stop bogus errors. */ |
if (oldbfd != NULL && (oldbfd->flags & BFD_PLUGIN) != 0) |
*type_change_ok = TRUE; |
|
/* Check TLS symbol. We don't check undefined symbol introduced by |
"ld -u". */ |
else if (oldbfd != NULL |
/* Check TLS symbols. We don't check undefined symbols introduced |
by "ld -u" which have no type (and oldbfd NULL), and we don't |
check symbols from plugins because they also have no type. */ |
if (oldbfd != NULL |
&& (oldbfd->flags & BFD_PLUGIN) == 0 |
&& (abfd->flags & BFD_PLUGIN) == 0 |
&& ELF_ST_TYPE (sym->st_info) != h->type |
&& (ELF_ST_TYPE (sym->st_info) == STT_TLS || h->type == STT_TLS)) |
{ |
1437,12 → 1521,15 |
if (!(oldbfd != NULL |
&& (oldbfd->flags & BFD_PLUGIN) != 0 |
&& (abfd->flags & BFD_PLUGIN) == 0)) |
{ |
newdef = FALSE; |
*skip = TRUE; |
} |
|
/* Merge st_other. If the symbol already has a dynamic index, |
but visibility says it should not be visible, turn it into a |
local symbol. */ |
elf_merge_st_other (abfd, h, sym, newdef, newdyn); |
elf_merge_st_other (abfd, h, sym, sec, newdef, newdyn); |
if (h->dynindx != -1) |
switch (ELF_ST_VISIBILITY (h->other)) |
{ |
1600,14 → 1687,41 |
char *p; |
size_t len, shortlen; |
asection *tmp_sec; |
bfd_boolean matched; |
|
if (h->versioned == unversioned || h->versioned == versioned_hidden) |
return TRUE; |
|
/* If this symbol has a version, and it is the default version, we |
create an indirect symbol from the default name to the fully |
decorated name. This will cause external references which do not |
specify a version to be bound to this version of the symbol. */ |
p = strchr (name, ELF_VER_CHR); |
if (p == NULL || p[1] != ELF_VER_CHR) |
if (h->versioned == unknown) |
{ |
if (p == NULL) |
{ |
h->versioned = unversioned; |
return TRUE; |
} |
else |
{ |
if (p[1] != ELF_VER_CHR) |
{ |
h->versioned = versioned_hidden; |
return TRUE; |
} |
else |
h->versioned = versioned; |
} |
} |
else |
{ |
/* PR ld/19073: We may see an unversioned definition after the |
default version. */ |
if (p == NULL) |
return TRUE; |
} |
|
bed = get_elf_backend_data (abfd); |
collect = bed->collect; |
1626,10 → 1740,11 |
actually going to define an indirect symbol. */ |
type_change_ok = FALSE; |
size_change_ok = FALSE; |
matched = TRUE; |
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)) |
&type_change_ok, &size_change_ok, &matched)) |
return FALSE; |
|
if (skip) |
1637,13 → 1752,18 |
|
if (! override) |
{ |
/* Add the default symbol if not performing a relocatable link. */ |
if (! bfd_link_relocatable (info)) |
{ |
bh = &hi->root; |
if (! (_bfd_generic_link_add_one_symbol |
(info, abfd, shortname, BSF_INDIRECT, bfd_ind_section_ptr, |
(info, abfd, shortname, BSF_INDIRECT, |
bfd_ind_section_ptr, |
0, name, FALSE, collect, &bh))) |
return FALSE; |
hi = (struct elf_link_hash_entry *) bh; |
} |
} |
else |
{ |
/* In this case the symbol named SHORTNAME is overriding the |
1702,6 → 1822,12 |
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) |
1708,7 → 1834,7 |
{ |
if (! dynamic) |
{ |
if (! info->executable |
if (! bfd_link_executable (info) |
|| hi->def_dynamic |
|| hi->ref_dynamic) |
*dynsym = TRUE; |
1737,8 → 1863,8 |
size_change_ok = FALSE; |
tmp_sec = sec; |
if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &tmp_sec, &value, |
&hi, NULL, NULL, NULL, &skip, &override, |
&type_change_ok, &size_change_ok)) |
&hi, poldbfd, NULL, NULL, &skip, &override, |
&type_change_ok, &size_change_ok, &matched)) |
return FALSE; |
|
if (skip) |
1771,6 → 1897,8 |
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. */ |
1778,7 → 1906,7 |
{ |
if (! dynamic) |
{ |
if (! info->executable |
if (! bfd_link_executable (info) |
|| hi->ref_dynamic) |
*dynsym = TRUE; |
} |
1844,7 → 1972,9 |
if (!h->def_dynamic |
|| h->def_regular |
|| h->dynindx == -1 |
|| h->verinfo.verdef == NULL) |
|| h->verinfo.verdef == NULL |
|| (elf_dyn_lib_class (h->verinfo.verdef->vd_bfd) |
& (DYN_AS_NEEDED | DYN_DT_NEEDED | DYN_NO_NEEDED))) |
return TRUE; |
|
/* See if we already know about this version. */ |
1944,26 → 2074,14 |
if (p != NULL && h->verinfo.vertree == NULL) |
{ |
struct bfd_elf_version_tree *t; |
bfd_boolean hidden; |
|
hidden = TRUE; |
|
/* There are two consecutive ELF_VER_CHR characters if this is |
not a hidden symbol. */ |
++p; |
if (*p == ELF_VER_CHR) |
{ |
hidden = FALSE; |
++p; |
} |
|
/* If there is no version string, we can just return out. */ |
if (*p == '\0') |
{ |
if (hidden) |
h->hidden = 1; |
return TRUE; |
} |
|
/* Look for the version. If we find it, it is no longer weak. */ |
for (t = sinfo->info->version_info; t != NULL; t = t->next) |
2011,7 → 2129,7 |
|
/* If we are building an application, we need to create a |
version node for this version. */ |
if (t == NULL && info->executable) |
if (t == NULL && bfd_link_executable (info)) |
{ |
struct bfd_elf_version_tree **pp; |
int version_index; |
2059,9 → 2177,6 |
sinfo->failed = TRUE; |
return FALSE; |
} |
|
if (hidden) |
h->hidden = 1; |
} |
|
/* If we don't have a version for this symbol, see if we can find |
2295,8 → 2410,8 |
{ |
struct elf_link_hash_entry **p; |
|
p = (struct elf_link_hash_entry **) |
bfd_zmalloc (reldata->count * sizeof (struct elf_link_hash_entry *)); |
p = ((struct elf_link_hash_entry **) |
bfd_zmalloc (reldata->count * sizeof (*p))); |
if (p == NULL) |
return FALSE; |
|
2376,7 → 2491,7 |
_bfd_elf_link_hash_fixup_symbol (struct bfd_link_info *info, |
struct elf_link_hash_entry *h) |
{ |
if (info->pie |
if (bfd_link_pie (info) |
&& h->dynindx == -1 |
&& h->root.type == bfd_link_hash_undefweak) |
return bfd_elf_link_record_dynamic_symbol (info, h); |
2479,7 → 2594,7 |
visibility. If the symbol has hidden or internal visibility, we |
will force it local. */ |
if (h->needs_plt |
&& eif->info->shared |
&& bfd_link_pic (eif->info) |
&& is_elf_hash_table (eif->info->hash) |
&& (SYMBOLIC_BIND (eif->info, h) |
|| ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) |
2646,7 → 2761,8 |
DYNBSS. */ |
|
bfd_boolean |
_bfd_elf_adjust_dynamic_copy (struct elf_link_hash_entry *h, |
_bfd_elf_adjust_dynamic_copy (struct bfd_link_info *info, |
struct elf_link_hash_entry *h, |
asection *dynbss) |
{ |
unsigned int power_of_two; |
2685,6 → 2801,15 |
/* Increment the size of DYNBSS to make room for the symbol. */ |
dynbss->size += h->size; |
|
/* No error if extern_protected_data is true. */ |
if (h->protected_def |
&& (!info->extern_protected_data |
|| (info->extern_protected_data < 0 |
&& !get_elf_backend_data (dynbss->owner)->extern_protected_data))) |
info->callbacks->einfo |
(_("%P: copy reloc against protected `%T' is dangerous\n"), |
h->root.root.string); |
|
return TRUE; |
} |
|
2741,7 → 2866,8 |
|
/* Identify the cases where name binding rules say that a |
visible symbol resolves locally. */ |
binding_stays_local_p = info->executable || SYMBOLIC_BIND (info, h); |
binding_stays_local_p = (bfd_link_executable (info) |
|| SYMBOLIC_BIND (info, h)); |
|
switch (ELF_ST_VISIBILITY (h->other)) |
{ |
2826,7 → 2952,7 |
/* At this point, we know the symbol is defined and dynamic. In an |
executable it must resolve locally, likewise when building symbolic |
shared libraries. */ |
if (info->executable || SYMBOLIC_BIND (info, h)) |
if (bfd_link_executable (info) || SYMBOLIC_BIND (info, h)) |
return TRUE; |
|
/* Now deal with defined dynamic symbols in shared libraries. Ones |
2840,8 → 2966,12 |
|
bed = get_elf_backend_data (hash_table->dynobj); |
|
/* STV_PROTECTED non-function symbols are local. */ |
if (!bed->is_function_type (h->type)) |
/* If extern_protected_data is false, STV_PROTECTED non-function |
symbols are local. */ |
if ((!info->extern_protected_data |
|| (info->extern_protected_data < 0 |
&& !bed->extern_protected_data)) |
&& !bed->is_function_type (h->type)) |
return TRUE; |
|
/* Function pointer equality tests may require that STV_PROTECTED |
2940,14 → 3070,11 |
if (abfd == NULL) |
return FALSE; |
|
if (! bfd_check_format (abfd, bfd_object)) |
/* Return FALSE if the object has been claimed by plugin. */ |
if (abfd->plugin_format == bfd_plugin_yes) |
return FALSE; |
|
/* If we have already included the element containing this symbol in the |
link then we do not need to include it again. Just claim that any symbol |
it contains is not a definition, so that our caller will not decide to |
(re)include this element. */ |
if (abfd->archive_pass) |
if (! bfd_check_format (abfd, bfd_object)) |
return FALSE; |
|
/* Select the appropriate symbol table. */ |
3105,7 → 3232,8 |
on_needed_list (const char *soname, struct bfd_link_needed_list *needed) |
{ |
for (; needed != NULL; needed = needed->next) |
if (strcmp (soname, needed->name) == 0) |
if ((elf_dyn_lib_class (needed->by) & DYN_AS_NEEDED) == 0 |
&& strcmp (soname, needed->name) == 0) |
return TRUE; |
|
return FALSE; |
3126,7 → 3254,7 |
return vdiff > 0 ? 1 : -1; |
else |
{ |
long sdiff = h1->root.u.def.section->id - h2->root.u.def.section->id; |
int sdiff = h1->root.u.def.section->id - h2->root.u.def.section->id; |
if (sdiff != 0) |
return sdiff > 0 ? 1 : -1; |
} |
3318,7 → 3446,7 |
struct bfd_link_info *info, |
enum notice_asneeded_action act) |
{ |
return (*info->callbacks->notice) (info, NULL, ibfd, NULL, act, 0, NULL); |
return (*info->callbacks->notice) (info, NULL, NULL, ibfd, NULL, act, 0); |
} |
|
/* Add symbols from an ELF object file to the linker hash table. */ |
3357,6 → 3485,7 |
bfd_size_type old_dynstr_size = 0; |
size_t tabsize = 0; |
asection *s; |
bfd_boolean just_syms; |
|
htab = elf_hash_table (info); |
bed = get_elf_backend_data (abfd); |
3370,11 → 3499,11 |
/* You can't use -r against a dynamic object. Also, there's no |
hope of using a dynamic object which does not exactly match |
the format of the output file. */ |
if (info->relocatable |
if (bfd_link_relocatable (info) |
|| !is_elf_hash_table (htab) |
|| info->output_bfd->xvec != abfd->xvec) |
{ |
if (info->relocatable) |
if (bfd_link_relocatable (info)) |
bfd_set_error (bfd_error_invalid_operation); |
else |
bfd_set_error (bfd_error_wrong_format); |
3447,7 → 3576,7 |
FALSE, bed->collect, NULL))) |
goto error_return; |
|
if (!info->relocatable && info->executable) |
if (bfd_link_executable (info)) |
{ |
/* Clobber the section size so that the warning does |
not get copied into the output file. */ |
3460,6 → 3589,9 |
} |
} |
|
just_syms = ((s = abfd->sections) != NULL |
&& s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS); |
|
add_needed = TRUE; |
if (! dynamic) |
{ |
3466,9 → 3598,11 |
/* If we are creating a shared library, create all the dynamic |
sections immediately. We need to attach them to something, |
so we attach them to this BFD, provided it is the right |
format. FIXME: If there are no input BFD's of the same |
format as the output, we can't make a shared library. */ |
if (info->shared |
format and is not from ld --just-symbols. FIXME: If there |
are no input BFD's of the same format as the output, we can't |
make a shared library. */ |
if (!just_syms |
&& bfd_link_pic (info) |
&& is_elf_hash_table (htab) |
&& info->output_bfd->xvec == abfd->xvec |
&& !htab->dynamic_sections_created) |
3488,8 → 3622,7 |
|
/* ld --just-symbols and dynamic objects don't mix very well. |
ld shouldn't allow it. */ |
if ((s = abfd->sections) != NULL |
&& s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS) |
if (just_syms) |
abort (); |
|
/* If this dynamic lib was specified on the command line with |
3835,6 → 3968,7 |
bfd_boolean common; |
unsigned int old_alignment; |
bfd *old_bfd; |
bfd_boolean matched; |
|
override = FALSE; |
|
3920,7 → 4054,7 |
} |
else if (isym->st_shndx == SHN_COMMON |
&& ELF_ST_TYPE (isym->st_info) == STT_TLS |
&& !info->relocatable) |
&& !bfd_link_relocatable (info)) |
{ |
asection *tcomm = bfd_get_section_by_name (abfd, ".tcommon"); |
|
3969,6 → 4103,7 |
size_change_ok = FALSE; |
type_change_ok = bed->type_change_ok; |
old_weak = FALSE; |
matched = FALSE; |
old_alignment = 0; |
old_bfd = NULL; |
new_sec = sec; |
4086,16 → 4221,28 |
name = newname; |
} |
|
/* If this symbol has default visibility and the user has |
requested we not re-export it, then mark it as hidden. */ |
if (!bfd_is_und_section (sec) |
&& !dynamic |
&& abfd->no_export |
&& ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL) |
isym->st_other = (STV_HIDDEN |
| (isym->st_other & ~ELF_ST_VISIBILITY (-1))); |
|
if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec, &value, |
sym_hash, &old_bfd, &old_weak, |
&old_alignment, &skip, &override, |
&type_change_ok, &size_change_ok)) |
&type_change_ok, &size_change_ok, |
&matched)) |
goto error_free_vers; |
|
if (skip) |
continue; |
|
if (override) |
/* Override a definition only if the new symbol matches the |
existing one. */ |
if (override && matched) |
definition = FALSE; |
|
h = *sym_hash; |
4203,7 → 4350,7 |
/* If the indirect symbol has been forced local, don't |
make the real symbol dynamic. */ |
if ((h == hi || !hi->forced_local) |
&& (! info->executable |
&& (bfd_link_dll (info) |
|| h->def_dynamic |
|| h->ref_dynamic)) |
dynsym = TRUE; |
4352,10 → 4499,12 |
} |
|
/* Merge st_other field. */ |
elf_merge_st_other (abfd, h, isym, definition, dynamic); |
elf_merge_st_other (abfd, h, isym, sec, definition, dynamic); |
|
/* We don't want to make debug symbol dynamic. */ |
if (definition && (sec->flags & SEC_DEBUGGING) && !info->relocatable) |
if (definition |
&& (sec->flags & SEC_DEBUGGING) |
&& !bfd_link_relocatable (info)) |
dynsym = FALSE; |
|
/* Nor should we make plugin symbols dynamic. */ |
4379,8 → 4528,8 |
{ |
amt = ((isymend - isym + 1) |
* sizeof (struct elf_link_hash_entry *)); |
nondeflt_vers = |
(struct elf_link_hash_entry **) bfd_malloc (amt); |
nondeflt_vers |
= (struct elf_link_hash_entry **) bfd_malloc (amt); |
if (!nondeflt_vers) |
goto error_free_vers; |
} |
4427,6 → 4576,9 |
int ret; |
const char *soname = elf_dt_name (abfd); |
|
info->callbacks->minfo ("%!", soname, old_bfd, |
h->root.root.string); |
|
/* A symbol from a library loaded via DT_NEEDED of some |
other library is referenced by a regular object. |
Add a DT_NEEDED entry for it. Issue an error if |
4552,9 → 4704,10 |
old_tab = NULL; |
} |
|
/* Now that all the symbols from this input file are created, handle |
.symver foo, foo@BAR such that any relocs against foo become foo@BAR. */ |
if (nondeflt_vers != NULL) |
/* Now that all the symbols from this input file are created, if |
not performing a relocatable link, handle .symver foo, foo@BAR |
such that any relocs against foo become foo@BAR. */ |
if (!bfd_link_relocatable (info) && nondeflt_vers != NULL) |
{ |
bfd_size_type cnt, symidx; |
|
4684,7 → 4837,7 |
i = idx + 1; |
else |
{ |
long sdiff = slook->id - h->root.u.def.section->id; |
int sdiff = slook->id - h->root.u.def.section->id; |
if (sdiff < 0) |
j = idx; |
else if (sdiff > 0) |
4852,8 → 5005,7 |
/* Add this bfd to the loaded list. */ |
struct elf_link_loaded_list *n; |
|
n = (struct elf_link_loaded_list *) |
bfd_alloc (abfd, sizeof (struct elf_link_loaded_list)); |
n = (struct elf_link_loaded_list *) bfd_alloc (abfd, sizeof (*n)); |
if (n == NULL) |
goto error_return; |
n->abfd = abfd; |
4927,20 → 5079,8 |
} |
|
/* Add symbols from an ELF archive file to the linker hash table. We |
don't use _bfd_generic_link_add_archive_symbols because of a |
problem which arises on UnixWare. The UnixWare libc.so is an |
archive which includes an entry libc.so.1 which defines a bunch of |
symbols. The libc.so archive also includes a number of other |
object files, which also define symbols, some of which are the same |
as those defined in libc.so.1. Correct linking requires that we |
consider each object file in turn, and include it if it defines any |
symbols we need. _bfd_generic_link_add_archive_symbols does not do |
this; it looks through the list of undefined symbols, and includes |
any object file which defines them. When this algorithm is used on |
UnixWare, it winds up pulling in libc.so.1 early and defining a |
bunch of symbols. This means that some of the other objects in the |
archive are not included in the link, which is incorrect since they |
precede libc.so.1 in the archive. |
don't use _bfd_generic_link_add_archive_symbols because we need to |
handle versioned symbols. |
|
Fortunately, ELF archive handling is simpler than that done by |
_bfd_generic_link_add_archive_symbols, which has to allow for a.out |
4955,8 → 5095,7 |
elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) |
{ |
symindex c; |
bfd_boolean *defined = NULL; |
bfd_boolean *included = NULL; |
unsigned char *included = NULL; |
carsym *symdefs; |
bfd_boolean loop; |
bfd_size_type amt; |
4980,11 → 5119,10 |
if (c == 0) |
return TRUE; |
amt = c; |
amt *= sizeof (bfd_boolean); |
defined = (bfd_boolean *) bfd_zmalloc (amt); |
included = (bfd_boolean *) bfd_zmalloc (amt); |
if (defined == NULL || included == NULL) |
goto error_return; |
amt *= sizeof (*included); |
included = (unsigned char *) bfd_zmalloc (amt); |
if (included == NULL) |
return FALSE; |
|
symdefs = bfd_ardata (abfd)->symdefs; |
bed = get_elf_backend_data (abfd); |
5009,7 → 5147,7 |
struct bfd_link_hash_entry *undefs_tail; |
symindex mark; |
|
if (defined[i] || included[i]) |
if (included[i]) |
continue; |
if (symdef->file_offset == last) |
{ |
5044,7 → 5182,8 |
else if (h->root.type != bfd_link_hash_undefined) |
{ |
if (h->root.type != bfd_link_hash_undefweak) |
defined[i] = TRUE; |
/* Symbol must be defined. Don't check it again. */ |
included[i] = TRUE; |
continue; |
} |
|
5056,16 → 5195,6 |
if (! bfd_check_format (element, bfd_object)) |
goto error_return; |
|
/* Doublecheck that we have not included this object |
already--it should be impossible, but there may be |
something wrong with the archive. */ |
if (element->archive_pass != 0) |
{ |
bfd_set_error (bfd_error_bad_value); |
goto error_return; |
} |
element->archive_pass = 1; |
|
undefs_tail = info->hash->undefs_tail; |
|
if (!(*info->callbacks |
5103,14 → 5232,11 |
} |
while (loop); |
|
free (defined); |
free (included); |
|
return TRUE; |
|
error_return: |
if (defined != NULL) |
free (defined); |
if (included != NULL) |
free (included); |
return FALSE; |
5148,7 → 5274,6 |
{ |
struct hash_codes_info *inf = (struct hash_codes_info *) data; |
const char *name; |
char *p; |
unsigned long ha; |
char *alc = NULL; |
|
5157,7 → 5282,9 |
return TRUE; |
|
name = h->root.root.string; |
p = strchr (name, ELF_VER_CHR); |
if (h->versioned >= versioned) |
{ |
char *p = strchr (name, ELF_VER_CHR); |
if (p != NULL) |
{ |
alc = (char *) bfd_malloc (p - name + 1); |
5170,6 → 5297,7 |
alc[p - name] = '\0'; |
name = alc; |
} |
} |
|
/* Compute the hash value. */ |
ha = bfd_elf_hash (name); |
5216,7 → 5344,6 |
{ |
struct collect_gnu_hash_codes *s = (struct collect_gnu_hash_codes *) data; |
const char *name; |
char *p; |
unsigned long ha; |
char *alc = NULL; |
|
5229,7 → 5356,9 |
return TRUE; |
|
name = h->root.root.string; |
p = strchr (name, ELF_VER_CHR); |
if (h->versioned >= versioned) |
{ |
char *p = strchr (name, ELF_VER_CHR); |
if (p != NULL) |
{ |
alc = (char *) bfd_malloc (p - name + 1); |
5242,6 → 5371,7 |
alc[p - name] = '\0'; |
name = alc; |
} |
} |
|
/* Compute the hash value. */ |
ha = bfd_elf_gnu_hash (name); |
5476,7 → 5606,7 |
{ |
bfd *ibfd; |
|
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) |
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) |
if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour |
&& !_bfd_elf_fixup_group_sections (ibfd, bfd_abs_section_ptr)) |
return FALSE; |
5579,7 → 5709,7 |
elf_hash_table (info)->init_plt_refcount |
= elf_hash_table (info)->init_plt_offset; |
|
if (info->relocatable |
if (bfd_link_relocatable (info) |
&& !_bfd_elf_size_group_sections (info)) |
return FALSE; |
|
5603,7 → 5733,7 |
|
for (inputobj = info->input_bfds; |
inputobj; |
inputobj = inputobj->link_next) |
inputobj = inputobj->link.next) |
{ |
asection *s; |
|
5622,7 → 5752,7 |
} |
if (notesec || info->stacksize > 0) |
elf_stack_flags (output_bfd) = PF_R | PF_W | exec; |
if (notesec && exec && info->relocatable |
if (notesec && exec && bfd_link_relocatable (info) |
&& notesec->output_section != bfd_abs_section_ptr) |
notesec->output_section->flags |= SEC_CODE; |
} |
5640,7 → 5770,7 |
bfd_boolean all_defined; |
|
*sinterpptr = bfd_get_linker_section (dynobj, ".interp"); |
BFD_ASSERT (*sinterpptr != NULL || !info->executable); |
BFD_ASSERT (*sinterpptr != NULL || !bfd_link_executable (info) || info->nointerp); |
|
if (soname != NULL) |
{ |
5728,7 → 5858,7 |
/* If we are supposed to export all symbols into the dynamic symbol |
table (this is not the normal case), then do so. */ |
if (info->export_dynamic |
|| (info->executable && info->dynamic)) |
|| (bfd_link_executable (info) && info->dynamic)) |
{ |
elf_link_hash_traverse (elf_hash_table (info), |
_bfd_elf_export_symbol, |
5863,13 → 5993,13 |
if (s != NULL && s->linker_has_input) |
{ |
/* DT_PREINIT_ARRAY is not allowed in shared library. */ |
if (! info->executable) |
if (! bfd_link_executable (info)) |
{ |
bfd *sub; |
asection *o; |
|
for (sub = info->input_bfds; sub != NULL; |
sub = sub->link_next) |
sub = sub->link.next) |
if (bfd_get_flavour (sub) == bfd_target_elf_flavour) |
for (o = sub->sections; o != NULL; o = o->next) |
if (elf_section_data (o)->this_hdr.sh_type |
5927,6 → 6057,9 |
} |
} |
|
if (! _bfd_elf_maybe_strip_eh_frame_hdr (info)) |
return FALSE; |
|
/* The backend must work out the sizes of all the other dynamic |
sections. */ |
if (dynobj != NULL |
5934,9 → 6067,6 |
&& ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info)) |
return FALSE; |
|
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; |
6197,7 → 6327,7 |
|
if (info->flags_1) |
{ |
if (info->executable) |
if (bfd_link_executable (info)) |
info->flags_1 &= ~ (DF_1_INITFIRST |
| DF_1_NODELETE |
| DF_1_NOOPEN); |
6423,7 → 6553,7 |
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_linker_section (dynobj, ".dynsym"); |
s = elf_hash_table (info)->dynsym; |
BFD_ASSERT (s != NULL); |
s->size = dynsymcount * bed->s->sizeof_sym; |
|
6691,7 → 6821,7 |
/* Finish SHF_MERGE section merging. */ |
|
bfd_boolean |
_bfd_elf_merge_sections (bfd *abfd, struct bfd_link_info *info) |
_bfd_elf_merge_sections (bfd *obfd, struct bfd_link_info *info) |
{ |
bfd *ibfd; |
asection *sec; |
6699,8 → 6829,11 |
if (!is_elf_hash_table (info->hash)) |
return FALSE; |
|
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) |
if ((ibfd->flags & DYNAMIC) == 0) |
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) |
if ((ibfd->flags & DYNAMIC) == 0 |
&& bfd_get_flavour (ibfd) == bfd_target_elf_flavour |
&& (elf_elfheader (ibfd)->e_ident[EI_CLASS] |
== get_elf_backend_data (obfd)->s->elfclass)) |
for (sec = ibfd->sections; sec != NULL; sec = sec->next) |
if ((sec->flags & SEC_MERGE) != 0 |
&& !bfd_is_abs_section (sec->output_section)) |
6708,7 → 6841,7 |
struct bfd_elf_section_data *secdata; |
|
secdata = elf_section_data (sec); |
if (! _bfd_add_merge_section (abfd, |
if (! _bfd_add_merge_section (obfd, |
&elf_hash_table (info)->merge_info, |
sec, &secdata->sec_info)) |
return FALSE; |
6717,7 → 6850,7 |
} |
|
if (elf_hash_table (info)->merge_info != NULL) |
_bfd_merge_sections (abfd, info, elf_hash_table (info)->merge_info, |
_bfd_merge_sections (obfd, info, elf_hash_table (info)->merge_info, |
merge_sections_remove_hook); |
return TRUE; |
} |
6774,8 → 6907,11 |
struct elf_link_hash_table *htab; |
|
/* Copy down any references that we may have already seen to the |
symbol which just became indirect. */ |
symbol which just became indirect if DIR isn't a hidden versioned |
symbol. */ |
|
if (dir->versioned != versioned_hidden) |
{ |
dir->ref_dynamic |= ind->ref_dynamic; |
dir->ref_regular |= ind->ref_regular; |
dir->ref_regular_nonweak |= ind->ref_regular_nonweak; |
6782,6 → 6918,7 |
dir->non_got_ref |= ind->non_got_ref; |
dir->needs_plt |= ind->needs_plt; |
dir->pointer_equality_needed |= ind->pointer_equality_needed; |
} |
|
if (ind->root.type != bfd_link_hash_indirect) |
return; |
6889,6 → 7026,7 |
free (ret); |
return NULL; |
} |
ret->root.hash_table_free = _bfd_elf_link_hash_table_free; |
|
return &ret->root; |
} |
6896,13 → 7034,15 |
/* Destroy an ELF linker hash table. */ |
|
void |
_bfd_elf_link_hash_table_free (struct bfd_link_hash_table *hash) |
_bfd_elf_link_hash_table_free (bfd *obfd) |
{ |
struct elf_link_hash_table *htab = (struct elf_link_hash_table *) hash; |
struct elf_link_hash_table *htab; |
|
htab = (struct elf_link_hash_table *) obfd->link.hash; |
if (htab->dynstr != NULL) |
_bfd_elf_strtab_free (htab->dynstr); |
_bfd_merge_sections_free (htab->merge_info); |
_bfd_generic_link_hash_table_free (hash); |
_bfd_generic_link_hash_table_free (obfd); |
} |
|
/* This is a hook for the ELF emulation code in the generic linker to |
7282,10 → 7422,10 |
if (count1 == 0 || count2 == 0 || count1 != count2) |
goto done; |
|
symtable1 = (struct elf_symbol *) |
bfd_malloc (count1 * sizeof (struct elf_symbol)); |
symtable2 = (struct elf_symbol *) |
bfd_malloc (count2 * sizeof (struct elf_symbol)); |
symtable1 |
= (struct elf_symbol *) bfd_malloc (count1 * sizeof (*symtable1)); |
symtable2 |
= (struct elf_symbol *) bfd_malloc (count2 * sizeof (*symtable2)); |
if (symtable1 == NULL || symtable2 == NULL) |
goto done; |
|
7411,9 → 7551,7 |
/* Output BFD. */ |
bfd *output_bfd; |
/* Symbol string table. */ |
struct bfd_strtab_hash *symstrtab; |
/* .dynsym section. */ |
asection *dynsym_sec; |
struct elf_strtab_hash *symstrtab; |
/* .hash section. */ |
asection *hash_sec; |
/* symbol version section (.gnu.version). */ |
7438,16 → 7576,8 |
/* Array large enough to hold a section pointer for each local |
symbol of any input BFD. */ |
asection **sections; |
/* Buffer to hold swapped out symbols. */ |
bfd_byte *symbuf; |
/* And one for symbol section indices. */ |
/* Buffer for SHT_SYMTAB_SHNDX section. */ |
Elf_External_Sym_Shndx *symshndxbuf; |
/* Number of swapped out symbols in buffer. */ |
size_t symbuf_count; |
/* Number of symbols which fit in symbuf. */ |
size_t symbuf_size; |
/* And same for symshndxbuf. */ |
size_t shndxbuf_size; |
/* Number of STT_FILE syms seen. */ |
size_t filesym_count; |
}; |
7458,8 → 7588,7 |
{ |
bfd_boolean failed; |
bfd_boolean localsyms; |
bfd_boolean need_second_pass; |
bfd_boolean second_pass; |
bfd_boolean file_sym_done; |
struct elf_final_link_info *flinfo; |
}; |
|
7809,28 → 7938,34 |
{ |
location += (size - chunksz); |
|
for (; size; size -= chunksz, location -= chunksz, x >>= (chunksz * 8)) |
for (; size; size -= chunksz, location -= chunksz) |
{ |
switch (chunksz) |
{ |
default: |
case 0: |
abort (); |
case 1: |
bfd_put_8 (input_bfd, x, location); |
x >>= 8; |
break; |
case 2: |
bfd_put_16 (input_bfd, x, location); |
x >>= 16; |
break; |
case 4: |
bfd_put_32 (input_bfd, x, location); |
/* Computed this way because x >>= 32 is undefined if x is a 32-bit value. */ |
x >>= 16; |
x >>= 16; |
break; |
#ifdef BFD64 |
case 8: |
#ifdef BFD64 |
bfd_put_64 (input_bfd, x, location); |
#else |
/* Computed this way because x >>= 64 is undefined if x is a 64-bit value. */ |
x >>= 32; |
x >>= 32; |
break; |
#endif |
default: |
abort (); |
#endif |
break; |
} |
} |
7977,14 → 8112,101 |
return r; |
} |
|
/* Functions to read r_offset from external (target order) reloc |
entry. Faster than bfd_getl32 et al, because we let the compiler |
know the value is aligned. */ |
|
static bfd_vma |
ext32l_r_offset (const void *p) |
{ |
union aligned32 |
{ |
uint32_t v; |
unsigned char c[4]; |
}; |
const union aligned32 *a |
= (const union aligned32 *) &((const Elf32_External_Rel *) p)->r_offset; |
|
uint32_t aval = ( (uint32_t) a->c[0] |
| (uint32_t) a->c[1] << 8 |
| (uint32_t) a->c[2] << 16 |
| (uint32_t) a->c[3] << 24); |
return aval; |
} |
|
static bfd_vma |
ext32b_r_offset (const void *p) |
{ |
union aligned32 |
{ |
uint32_t v; |
unsigned char c[4]; |
}; |
const union aligned32 *a |
= (const union aligned32 *) &((const Elf32_External_Rel *) p)->r_offset; |
|
uint32_t aval = ( (uint32_t) a->c[0] << 24 |
| (uint32_t) a->c[1] << 16 |
| (uint32_t) a->c[2] << 8 |
| (uint32_t) a->c[3]); |
return aval; |
} |
|
#ifdef BFD_HOST_64_BIT |
static bfd_vma |
ext64l_r_offset (const void *p) |
{ |
union aligned64 |
{ |
uint64_t v; |
unsigned char c[8]; |
}; |
const union aligned64 *a |
= (const union aligned64 *) &((const Elf64_External_Rel *) p)->r_offset; |
|
uint64_t aval = ( (uint64_t) a->c[0] |
| (uint64_t) a->c[1] << 8 |
| (uint64_t) a->c[2] << 16 |
| (uint64_t) a->c[3] << 24 |
| (uint64_t) a->c[4] << 32 |
| (uint64_t) a->c[5] << 40 |
| (uint64_t) a->c[6] << 48 |
| (uint64_t) a->c[7] << 56); |
return aval; |
} |
|
static bfd_vma |
ext64b_r_offset (const void *p) |
{ |
union aligned64 |
{ |
uint64_t v; |
unsigned char c[8]; |
}; |
const union aligned64 *a |
= (const union aligned64 *) &((const Elf64_External_Rel *) p)->r_offset; |
|
uint64_t aval = ( (uint64_t) a->c[0] << 56 |
| (uint64_t) a->c[1] << 48 |
| (uint64_t) a->c[2] << 40 |
| (uint64_t) a->c[3] << 32 |
| (uint64_t) a->c[4] << 24 |
| (uint64_t) a->c[5] << 16 |
| (uint64_t) a->c[6] << 8 |
| (uint64_t) a->c[7]); |
return aval; |
} |
#endif |
|
/* When performing a relocatable link, the input relocations are |
preserved. But, if they reference global symbols, the indices |
referenced must be updated. Update all the relocations found in |
RELDATA. */ |
|
static void |
static bfd_boolean |
elf_link_adjust_relocs (bfd *abfd, |
struct bfd_elf_section_reloc_data *reldata) |
struct bfd_elf_section_reloc_data *reldata, |
bfd_boolean sort) |
{ |
unsigned int i; |
const struct elf_backend_data *bed = get_elf_backend_data (abfd); |
8040,8 → 8262,120 |
| (irela[j].r_info & r_type_mask)); |
(*swap_out) (abfd, irela, erela); |
} |
|
if (sort && count != 0) |
{ |
bfd_vma (*ext_r_off) (const void *); |
bfd_vma r_off; |
size_t elt_size; |
bfd_byte *base, *end, *p, *loc; |
bfd_byte *buf = NULL; |
|
if (bed->s->arch_size == 32) |
{ |
if (abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE) |
ext_r_off = ext32l_r_offset; |
else if (abfd->xvec->header_byteorder == BFD_ENDIAN_BIG) |
ext_r_off = ext32b_r_offset; |
else |
abort (); |
} |
else |
{ |
#ifdef BFD_HOST_64_BIT |
if (abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE) |
ext_r_off = ext64l_r_offset; |
else if (abfd->xvec->header_byteorder == BFD_ENDIAN_BIG) |
ext_r_off = ext64b_r_offset; |
else |
#endif |
abort (); |
} |
|
/* Must use a stable sort here. A modified insertion sort, |
since the relocs are mostly sorted already. */ |
elt_size = reldata->hdr->sh_entsize; |
base = reldata->hdr->contents; |
end = base + count * elt_size; |
if (elt_size > sizeof (Elf64_External_Rela)) |
abort (); |
|
/* Ensure the first element is lowest. This acts as a sentinel, |
speeding the main loop below. */ |
r_off = (*ext_r_off) (base); |
for (p = loc = base; (p += elt_size) < end; ) |
{ |
bfd_vma r_off2 = (*ext_r_off) (p); |
if (r_off > r_off2) |
{ |
r_off = r_off2; |
loc = p; |
} |
} |
if (loc != base) |
{ |
/* Don't just swap *base and *loc as that changes the order |
of the original base[0] and base[1] if they happen to |
have the same r_offset. */ |
bfd_byte onebuf[sizeof (Elf64_External_Rela)]; |
memcpy (onebuf, loc, elt_size); |
memmove (base + elt_size, base, loc - base); |
memcpy (base, onebuf, elt_size); |
} |
|
for (p = base + elt_size; (p += elt_size) < end; ) |
{ |
/* base to p is sorted, *p is next to insert. */ |
r_off = (*ext_r_off) (p); |
/* Search the sorted region for location to insert. */ |
loc = p - elt_size; |
while (r_off < (*ext_r_off) (loc)) |
loc -= elt_size; |
loc += elt_size; |
if (loc != p) |
{ |
/* Chances are there is a run of relocs to insert here, |
from one of more input files. Files are not always |
linked in order due to the way elf_link_input_bfd is |
called. See pr17666. */ |
size_t sortlen = p - loc; |
bfd_vma r_off2 = (*ext_r_off) (loc); |
size_t runlen = elt_size; |
size_t buf_size = 96 * 1024; |
while (p + runlen < end |
&& (sortlen <= buf_size |
|| runlen + elt_size <= buf_size) |
&& r_off2 > (*ext_r_off) (p + runlen)) |
runlen += elt_size; |
if (buf == NULL) |
{ |
buf = bfd_malloc (buf_size); |
if (buf == NULL) |
return FALSE; |
} |
if (runlen < sortlen) |
{ |
memcpy (buf, p, runlen); |
memmove (loc + runlen, loc, sortlen); |
memcpy (loc, buf, runlen); |
} |
else |
{ |
memcpy (buf, loc, sortlen); |
memmove (loc, p, runlen); |
memcpy (loc + runlen, buf, sortlen); |
} |
p += runlen - elt_size; |
} |
} |
/* Hashes are no longer valid. */ |
free (reldata->hashes); |
reldata->hashes = NULL; |
free (buf); |
} |
return TRUE; |
} |
|
struct elf_link_sort_rela |
{ |
union { |
8370,48 → 8704,24 |
return ret; |
} |
|
/* Flush the output symbols to the file. */ |
/* Add a symbol to the output symbol string table. */ |
|
static bfd_boolean |
elf_link_flush_output_syms (struct elf_final_link_info *flinfo, |
const struct elf_backend_data *bed) |
{ |
if (flinfo->symbuf_count > 0) |
{ |
Elf_Internal_Shdr *hdr; |
file_ptr pos; |
bfd_size_type amt; |
|
hdr = &elf_tdata (flinfo->output_bfd)->symtab_hdr; |
pos = hdr->sh_offset + hdr->sh_size; |
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; |
flinfo->symbuf_count = 0; |
} |
|
return TRUE; |
} |
|
/* Add a symbol to the output symbol table. */ |
|
static int |
elf_link_output_sym (struct elf_final_link_info *flinfo, |
elf_link_output_symstrtab (struct elf_final_link_info *flinfo, |
const char *name, |
Elf_Internal_Sym *elfsym, |
asection *input_sec, |
struct elf_link_hash_entry *h) |
{ |
bfd_byte *dest; |
Elf_External_Sym_Shndx *destshndx; |
int (*output_symbol_hook) |
(struct bfd_link_info *, const char *, Elf_Internal_Sym *, asection *, |
struct elf_link_hash_entry *); |
struct elf_link_hash_table *hash_table; |
const struct elf_backend_data *bed; |
bfd_size_type strtabsize; |
|
BFD_ASSERT (elf_onesymtab (flinfo->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) |
8421,49 → 8731,119 |
return ret; |
} |
|
if (name == NULL || *name == '\0') |
elfsym->st_name = 0; |
else if (input_sec->flags & SEC_EXCLUDE) |
elfsym->st_name = 0; |
if (name == NULL |
|| *name == '\0' |
|| (input_sec->flags & SEC_EXCLUDE)) |
elfsym->st_name = (unsigned long) -1; |
else |
{ |
elfsym->st_name = (unsigned long) _bfd_stringtab_add (flinfo->symstrtab, |
name, TRUE, FALSE); |
/* Call _bfd_elf_strtab_offset after _bfd_elf_strtab_finalize |
to get the final offset for st_name. */ |
elfsym->st_name |
= (unsigned long) _bfd_elf_strtab_add (flinfo->symstrtab, |
name, FALSE); |
if (elfsym->st_name == (unsigned long) -1) |
return 0; |
} |
|
if (flinfo->symbuf_count >= flinfo->symbuf_size) |
hash_table = elf_hash_table (flinfo->info); |
strtabsize = hash_table->strtabsize; |
if (strtabsize <= hash_table->strtabcount) |
{ |
if (! elf_link_flush_output_syms (flinfo, bed)) |
strtabsize += strtabsize; |
hash_table->strtabsize = strtabsize; |
strtabsize *= sizeof (*hash_table->strtab); |
hash_table->strtab |
= (struct elf_sym_strtab *) bfd_realloc (hash_table->strtab, |
strtabsize); |
if (hash_table->strtab == NULL) |
return 0; |
} |
hash_table->strtab[hash_table->strtabcount].sym = *elfsym; |
hash_table->strtab[hash_table->strtabcount].dest_index |
= hash_table->strtabcount; |
hash_table->strtab[hash_table->strtabcount].destshndx_index |
= flinfo->symshndxbuf ? bfd_get_symcount (flinfo->output_bfd) : 0; |
|
dest = flinfo->symbuf + flinfo->symbuf_count * bed->s->sizeof_sym; |
destshndx = flinfo->symshndxbuf; |
if (destshndx != NULL) |
bfd_get_symcount (flinfo->output_bfd) += 1; |
hash_table->strtabcount += 1; |
|
return 1; |
} |
|
/* Swap symbols out to the symbol table and flush the output symbols to |
the file. */ |
|
static bfd_boolean |
elf_link_swap_symbols_out (struct elf_final_link_info *flinfo) |
{ |
if (bfd_get_symcount (flinfo->output_bfd) >= flinfo->shndxbuf_size) |
struct elf_link_hash_table *hash_table = elf_hash_table (flinfo->info); |
bfd_size_type amt, i; |
const struct elf_backend_data *bed; |
bfd_byte *symbuf; |
Elf_Internal_Shdr *hdr; |
file_ptr pos; |
bfd_boolean ret; |
|
if (!hash_table->strtabcount) |
return TRUE; |
|
BFD_ASSERT (elf_onesymtab (flinfo->output_bfd)); |
|
bed = get_elf_backend_data (flinfo->output_bfd); |
|
amt = bed->s->sizeof_sym * hash_table->strtabcount; |
symbuf = (bfd_byte *) bfd_malloc (amt); |
if (symbuf == NULL) |
return FALSE; |
|
if (flinfo->symshndxbuf) |
{ |
bfd_size_type amt; |
amt = (sizeof (Elf_External_Sym_Shndx) |
* (bfd_get_symcount (flinfo->output_bfd))); |
flinfo->symshndxbuf = (Elf_External_Sym_Shndx *) bfd_zmalloc (amt); |
if (flinfo->symshndxbuf == NULL) |
{ |
free (symbuf); |
return FALSE; |
} |
} |
|
amt = flinfo->shndxbuf_size * sizeof (Elf_External_Sym_Shndx); |
destshndx = (Elf_External_Sym_Shndx *) bfd_realloc (destshndx, |
amt * 2); |
if (destshndx == NULL) |
return 0; |
flinfo->symshndxbuf = destshndx; |
memset ((char *) destshndx + amt, 0, amt); |
flinfo->shndxbuf_size *= 2; |
for (i = 0; i < hash_table->strtabcount; i++) |
{ |
struct elf_sym_strtab *elfsym = &hash_table->strtab[i]; |
if (elfsym->sym.st_name == (unsigned long) -1) |
elfsym->sym.st_name = 0; |
else |
elfsym->sym.st_name |
= (unsigned long) _bfd_elf_strtab_offset (flinfo->symstrtab, |
elfsym->sym.st_name); |
bed->s->swap_symbol_out (flinfo->output_bfd, &elfsym->sym, |
((bfd_byte *) symbuf |
+ (elfsym->dest_index |
* bed->s->sizeof_sym)), |
(flinfo->symshndxbuf |
+ elfsym->destshndx_index)); |
} |
destshndx += bfd_get_symcount (flinfo->output_bfd); |
|
hdr = &elf_tdata (flinfo->output_bfd)->symtab_hdr; |
pos = hdr->sh_offset + hdr->sh_size; |
amt = hash_table->strtabcount * bed->s->sizeof_sym; |
if (bfd_seek (flinfo->output_bfd, pos, SEEK_SET) == 0 |
&& bfd_bwrite (symbuf, amt, flinfo->output_bfd) == amt) |
{ |
hdr->sh_size += amt; |
ret = TRUE; |
} |
else |
ret = FALSE; |
|
bed->s->swap_symbol_out (flinfo->output_bfd, elfsym, dest, destshndx); |
flinfo->symbuf_count += 1; |
bfd_get_symcount (flinfo->output_bfd) += 1; |
free (symbuf); |
|
return 1; |
free (hash_table->strtab); |
hash_table->strtab = NULL; |
|
return ret; |
} |
|
/* Return TRUE if the dynamic symbol SYM in ABFD is supported. */ |
8660,6 → 9040,16 |
const struct elf_backend_data *bed; |
long indx; |
int ret; |
/* A symbol is bound locally if it is forced local or it is locally |
defined, hidden versioned, not referenced by shared library and |
not exported when linking executable. */ |
bfd_boolean local_bind = (h->forced_local |
|| (bfd_link_executable (flinfo->info) |
&& !flinfo->info->export_dynamic |
&& !h->dynamic |
&& !h->ref_dynamic |
&& h->def_regular |
&& h->versioned == versioned_hidden)); |
|
if (h->root.type == bfd_link_hash_warning) |
{ |
8671,17 → 9061,12 |
/* Decide whether to output this symbol in this pass. */ |
if (eoinfo->localsyms) |
{ |
if (!h->forced_local) |
if (!local_bind) |
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 |
{ |
if (h->forced_local) |
if (local_bind) |
return TRUE; |
} |
|
8724,8 → 9109,7 |
|
/* We should also warn if a forced local symbol is referenced from |
shared libraries. */ |
if (!flinfo->info->relocatable |
&& flinfo->info->executable |
if (bfd_link_executable (flinfo->info) |
&& h->forced_local |
&& h->ref_dynamic |
&& h->def_regular |
8779,7 → 9163,8 |
|| h->root.type == bfd_link_hash_defweak) |
&& ((flinfo->info->strip_discarded |
&& discarded_section (h->root.u.def.section)) |
|| (h->root.u.def.section->owner != NULL |
|| ((h->root.u.def.section->flags & SEC_LINKER_CREATED) == 0 |
&& h->root.u.def.section->owner != NULL |
&& (h->root.u.def.section->owner->flags & BFD_PLUGIN) != 0))) |
strip = TRUE; |
else if ((h->root.type == bfd_link_hash_undefined |
8802,7 → 9187,7 |
sym.st_value = 0; |
sym.st_size = h->size; |
sym.st_other = h->other; |
if (h->forced_local) |
if (local_bind) |
{ |
sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type); |
/* Turn off visibility on local symbol. */ |
8838,19 → 9223,6 |
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 (flinfo->output_bfd, |
input_sec->output_section); |
8868,7 → 9240,7 |
but in nonrelocatable files they are virtual |
addresses. */ |
sym.st_value = h->root.u.def.value + input_sec->output_offset; |
if (!flinfo->info->relocatable) |
if (!bfd_link_relocatable (flinfo->info)) |
{ |
sym.st_value += input_sec->output_section->vma; |
if (h->type == STT_TLS) |
8876,15 → 9248,9 |
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 (flinfo->info->gc_sections |
&& !input_sec->gc_mark); |
} |
} |
} |
} |
else |
{ |
BFD_ASSERT (input_sec->owner == NULL |
8918,10 → 9284,10 |
STT_GNU_IFUNC symbol must go through PLT. */ |
if ((h->type == STT_GNU_IFUNC |
&& h->def_regular |
&& !flinfo->info->relocatable) |
&& !bfd_link_relocatable (flinfo->info)) |
|| ((h->dynindx != -1 |
|| h->forced_local) |
&& ((flinfo->info->shared |
&& ((bfd_link_pic (flinfo->info) |
&& (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
|| h->root.type != bfd_link_hash_undefweak)) |
|| !h->forced_local) |
8971,7 → 9337,7 |
|
/* If a non-weak symbol with non-default visibility is not defined |
locally, it is a fatal error. */ |
if (!flinfo->info->relocatable |
if (!bfd_link_relocatable (flinfo->info) |
&& ELF_ST_VISIBILITY (sym.st_other) != STV_DEFAULT |
&& ELF_ST_BIND (sym.st_info) != STB_WEAK |
&& h->root.type == bfd_link_hash_undefined |
8994,7 → 9360,7 |
/* 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 (flinfo->dynsym_sec != NULL |
if (elf_hash_table (flinfo->info)->dynsym != NULL |
&& h->dynindx != -1 |
&& elf_hash_table (flinfo->info)->dynamic_sections_created) |
{ |
9002,8 → 9368,14 |
|
/* 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) |
have a run-time problem if not linking executable, referenced |
by shared library, not locally defined, or not bound locally. |
*/ |
if (h->verinfo.verdef == NULL |
&& !local_bind |
&& (!bfd_link_executable (flinfo->info) |
|| h->ref_dynamic |
|| !h->def_regular)) |
{ |
char *p = strrchr (h->root.root.string, ELF_VER_CHR); |
|
9018,7 → 9390,8 |
} |
|
sym.st_name = h->dynstr_index; |
esym = flinfo->dynsym_sec->contents + h->dynindx * bed->s->sizeof_sym; |
esym = (elf_hash_table (flinfo->info)->dynsym->contents |
+ h->dynindx * bed->s->sizeof_sym); |
if (!check_dynsym (flinfo->output_bfd, &sym)) |
{ |
eoinfo->failed = TRUE; |
9056,7 → 9429,9 |
|
if (!h->def_regular) |
{ |
if (h->verinfo.verdef == NULL) |
if (h->verinfo.verdef == NULL |
|| (elf_dyn_lib_class (h->verinfo.verdef->vd_bfd) |
& (DYN_AS_NEEDED | DYN_DT_NEEDED | DYN_NO_NEEDED))) |
iversym.vs_vers = 0; |
else |
iversym.vs_vers = h->verinfo.verdef->vd_exp_refno + 1; |
9071,7 → 9446,9 |
iversym.vs_vers++; |
} |
|
if (h->hidden) |
/* Turn on VERSYM_HIDDEN only if the hidden versioned symbol is |
defined locally. */ |
if (h->versioned == versioned_hidden && h->def_regular) |
iversym.vs_vers |= VERSYM_HIDDEN; |
|
eversym = (Elf_External_Versym *) flinfo->symver_sec->contents; |
9085,8 → 9462,32 |
if (strip || (input_sec->flags & SEC_EXCLUDE) != 0) |
return TRUE; |
|
/* Output a FILE symbol so that following locals are not associated |
with the wrong input file. We need one for forced local symbols |
if we've seen more than one FILE symbol or when we have exactly |
one FILE symbol but global symbols are present in a file other |
than the one with the FILE symbol. We also need one if linker |
defined symbols are present. In practice these conditions are |
always met, so just emit the FILE symbol unconditionally. */ |
if (eoinfo->localsyms |
&& !eoinfo->file_sym_done |
&& eoinfo->flinfo->filesym_count != 0) |
{ |
Elf_Internal_Sym fsym; |
|
memset (&fsym, 0, sizeof (fsym)); |
fsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE); |
fsym.st_shndx = SHN_ABS; |
if (!elf_link_output_symstrtab (eoinfo->flinfo, NULL, &fsym, |
bfd_und_section_ptr, NULL)) |
return FALSE; |
|
eoinfo->file_sym_done = TRUE; |
} |
|
indx = bfd_get_symcount (flinfo->output_bfd); |
ret = elf_link_output_sym (flinfo, h->root.root.string, &sym, input_sec, h); |
ret = elf_link_output_symstrtab (flinfo, h->root.root.string, &sym, |
input_sec, h); |
if (ret == 0) |
{ |
eoinfo->failed = TRUE; |
9112,6 → 9513,7 |
{ |
case SEC_INFO_TYPE_STABS: |
case SEC_INFO_TYPE_EH_FRAME: |
case SEC_INFO_TYPE_EH_FRAME_ENTRY: |
return TRUE; |
default: |
break; |
9351,7 → 9753,8 |
&& (bfd_hash_lookup (flinfo->info->keep_hash, name, FALSE, FALSE) |
== NULL)) |
|| (((flinfo->info->discard == discard_sec_merge |
&& (isec->flags & SEC_MERGE) && !flinfo->info->relocatable) |
&& (isec->flags & SEC_MERGE) |
&& !bfd_link_relocatable (flinfo->info)) |
|| flinfo->info->discard == discard_l) |
&& bfd_is_local_label_name (input_bfd, name))) |
continue; |
9358,6 → 9761,10 |
|
if (ELF_ST_TYPE (isym->st_info) == STT_FILE) |
{ |
if (input_bfd->lto_output) |
/* -flto puts a temp file name here. This means builds |
are not reproducible. Discard the symbol. */ |
continue; |
have_file_sym = TRUE; |
flinfo->filesym_count += 1; |
} |
9374,8 → 9781,11 |
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)) |
if (!elf_link_output_symstrtab (flinfo, |
(input_bfd->lto_output ? NULL |
: input_bfd->filename), |
&osym, bfd_abs_section_ptr, |
NULL)) |
return FALSE; |
} |
|
9395,7 → 9805,7 |
output_section. Any special sections must be set up to meet |
these requirements. */ |
osym.st_value += isec->output_offset; |
if (!flinfo->info->relocatable) |
if (!bfd_link_relocatable (flinfo->info)) |
{ |
osym.st_value += isec->output_section->vma; |
if (ELF_ST_TYPE (osym.st_info) == STT_TLS) |
9407,7 → 9817,7 |
} |
|
indx = bfd_get_symcount (output_bfd); |
ret = elf_link_output_sym (flinfo, name, &osym, isec, NULL); |
ret = elf_link_output_symstrtab (flinfo, name, &osym, isec, NULL); |
if (ret == 0) |
return FALSE; |
else if (ret == 1) |
9439,7 → 9849,7 |
continue; |
} |
|
if (flinfo->info->relocatable |
if (bfd_link_relocatable (flinfo->info) |
&& (o->flags & (SEC_LINKER_CREATED | SEC_GROUP)) == SEC_GROUP) |
{ |
/* Deal with the group signature symbol. */ |
9490,7 → 9900,8 |
sym.st_value += o->output_offset; |
|
indx = bfd_get_symcount (output_bfd); |
ret = elf_link_output_sym (flinfo, name, &sym, o, NULL); |
ret = elf_link_output_symstrtab (flinfo, name, &sym, o, |
NULL); |
if (ret == 0) |
return FALSE; |
else if (ret == 1) |
9519,7 → 9930,16 |
file, so the contents field will not have been set by any of |
the routines which work on output files. */ |
if (elf_section_data (o)->this_hdr.contents != NULL) |
{ |
contents = elf_section_data (o)->this_hdr.contents; |
if (bed->caches_rawsize |
&& o->rawsize != 0 |
&& o->rawsize < o->size) |
{ |
memcpy (flinfo->contents, contents, o->rawsize); |
contents = flinfo->contents; |
} |
} |
else |
{ |
contents = flinfo->contents; |
9616,6 → 10036,24 |
|
s_type = h->type; |
|
/* If a plugin symbol is referenced from a non-IR file, |
mark the symbol as undefined. Note that the |
linker may attach linker created dynamic sections |
to the plugin bfd. Symbols defined in linker |
created sections are not plugin symbols. */ |
if (h->root.non_ir_ref |
&& (h->root.type == bfd_link_hash_defined |
|| h->root.type == bfd_link_hash_defweak) |
&& (h->root.u.def.section->flags |
& SEC_LINKER_CREATED) == 0 |
&& h->root.u.def.section->owner != NULL |
&& (h->root.u.def.section->owner->flags |
& BFD_PLUGIN) != 0) |
{ |
h->root.type = bfd_link_hash_undefined; |
h->root.u.undef.abfd = h->root.u.def.section->owner; |
} |
|
ps = NULL; |
if (h->root.type == bfd_link_hash_defined |
|| h->root.type == bfd_link_hash_defweak) |
9634,7 → 10072,7 |
} |
|
if ((s_type == STT_RELC || s_type == STT_SRELC) |
&& !flinfo->info->relocatable) |
&& !bfd_link_relocatable (flinfo->info)) |
{ |
bfd_vma val; |
bfd_vma dot = (rel->r_offset |
9724,7 → 10162,7 |
return FALSE; |
|
if (ret == 2 |
|| flinfo->info->relocatable |
|| bfd_link_relocatable (flinfo->info) |
|| flinfo->info->emitrelocations) |
{ |
Elf_Internal_Rela *irela; |
9755,7 → 10193,7 |
rel_hash_list = rel_hash; |
rela_hash_list = NULL; |
last_offset = o->output_offset; |
if (!flinfo->info->relocatable) |
if (!bfd_link_relocatable (flinfo->info)) |
last_offset += o->output_section->vma; |
for (next_erel = 0; irela < irelaend; irela++, next_erel++) |
{ |
9795,7 → 10233,7 |
irela->r_offset += o->output_offset; |
|
/* Relocs in an executable have to be virtual addresses. */ |
if (!flinfo->info->relocatable) |
if (!bfd_link_relocatable (flinfo->info)) |
irela->r_offset += o->output_section->vma; |
|
last_offset = irela->r_offset; |
9923,7 → 10361,7 |
return FALSE; |
|
sym.st_value += sec->output_offset; |
if (!flinfo->info->relocatable) |
if (!bfd_link_relocatable (flinfo->info)) |
{ |
sym.st_value += osec->vma; |
if (ELF_ST_TYPE (sym.st_info) == STT_TLS) |
9938,7 → 10376,8 |
} |
|
indx = bfd_get_symcount (output_bfd); |
ret = elf_link_output_sym (flinfo, name, &sym, sec, |
ret = elf_link_output_symstrtab (flinfo, name, |
&sym, sec, |
NULL); |
if (ret == 0) |
return FALSE; |
10009,6 → 10448,14 |
return FALSE; |
} |
break; |
case SEC_INFO_TYPE_EH_FRAME_ENTRY: |
{ |
if (! _bfd_elf_write_section_eh_frame_entry (output_bfd, |
flinfo->info, |
o, contents)) |
return FALSE; |
} |
break; |
default: |
{ |
/* FIXME: octets_per_byte. */ |
10152,7 → 10599,7 |
|
size = (bfd_size_type) bfd_get_reloc_size (howto); |
buf = (bfd_byte *) bfd_zmalloc (size); |
if (buf == NULL) |
if (buf == NULL && size != 0) |
return FALSE; |
rstat = _bfd_relocate_contents (howto, output_bfd, addend, buf); |
switch (rstat) |
10190,7 → 10637,7 |
relocatable file, and is a virtual address in an executable |
file. */ |
offset = link_order->offset; |
if (! info->relocatable) |
if (! bfd_link_relocatable (info)) |
offset += output_section->vma; |
|
for (i = 0; i < bed->s->int_rels_per_ext_rel; i++) |
10378,7 → 10825,7 |
asection *o; |
|
if (flinfo->symstrtab != NULL) |
_bfd_stringtab_free (flinfo->symstrtab); |
_bfd_elf_strtab_free (flinfo->symstrtab); |
if (flinfo->contents != NULL) |
free (flinfo->contents); |
if (flinfo->external_relocs != NULL) |
10395,8 → 10842,6 |
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) |
10426,12 → 10871,10 |
bfd_size_type max_internal_reloc_count; |
bfd_size_type max_sym_count; |
bfd_size_type max_sym_shndx_count; |
file_ptr off; |
Elf_Internal_Sym elfsym; |
unsigned int i; |
Elf_Internal_Shdr *symtab_hdr; |
Elf_Internal_Shdr *symtab_shndx_hdr; |
Elf_Internal_Shdr *symstrtab_hdr; |
const struct elf_backend_data *bed = get_elf_backend_data (abfd); |
struct elf_outext_info eoinfo; |
bfd_boolean merged; |
10445,30 → 10888,28 |
if (! is_elf_hash_table (info->hash)) |
return FALSE; |
|
if (info->shared) |
if (bfd_link_pic (info)) |
abfd->flags |= DYNAMIC; |
|
dynamic = elf_hash_table (info)->dynamic_sections_created; |
dynobj = elf_hash_table (info)->dynobj; |
|
emit_relocs = (info->relocatable |
emit_relocs = (bfd_link_relocatable (info) |
|| info->emitrelocations); |
|
flinfo.info = info; |
flinfo.output_bfd = abfd; |
flinfo.symstrtab = _bfd_elf_stringtab_init (); |
flinfo.symstrtab = _bfd_elf_strtab_init (); |
if (flinfo.symstrtab == NULL) |
return FALSE; |
|
if (! dynamic) |
{ |
flinfo.dynsym_sec = NULL; |
flinfo.hash_sec = NULL; |
flinfo.symver_sec = NULL; |
} |
else |
{ |
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"); |
10483,10 → 10924,7 |
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 |
10567,7 → 11005,7 |
to count particular types of relocs. Of course, |
reloc sections themselves can't have relocations. */ |
reloc_count = 0; |
else if (info->relocatable || info->emitrelocations) |
else if (emit_relocs) |
reloc_count = sec->reloc_count; |
else if (bed->elf_backend_count_relocs) |
reloc_count = (*bed->elf_backend_count_relocs) (info, sec); |
10594,7 → 11032,7 |
max_sym_count = sym_count; |
|
if (sym_count > max_sym_shndx_count |
&& elf_symtab_shndx (sec->owner) != 0) |
&& elf_symtab_shndx_list (sec->owner) != NULL) |
max_sym_shndx_count = sym_count; |
|
if ((sec->flags & SEC_RELOC) != 0) |
10619,8 → 11057,7 |
|
o->reloc_count += reloc_count; |
|
if (p->type == bfd_indirect_link_order |
&& (info->relocatable || info->emitrelocations)) |
if (p->type == bfd_indirect_link_order && emit_relocs) |
{ |
if (esdi->rel.hdr) |
esdo->rel.count += NUM_SHDR_ENTRIES (esdi->rel.hdr); |
10655,7 → 11092,7 |
o->vma = 0; |
} |
|
if (! info->relocatable && merged) |
if (! bfd_link_relocatable (info) && merged) |
elf_link_hash_traverse (elf_hash_table (info), |
_bfd_elf_link_sec_merge_syms, abfd); |
|
10662,7 → 11099,7 |
/* Figure out the file positions for everything but the symbol table |
and the relocs. We set symcount to force assign_section_numbers |
to create a symbol table. */ |
bfd_get_symcount (abfd) = info->strip == strip_all ? 0 : 1; |
bfd_get_symcount (abfd) = info->strip != strip_all || emit_relocs; |
BFD_ASSERT (! abfd->output_has_begun); |
if (! _bfd_elf_compute_section_file_positions (abfd, info)) |
goto error_return; |
10686,14 → 11123,27 |
to count upwards while actually outputting the relocations. */ |
esdo->rel.count = 0; |
esdo->rela.count = 0; |
|
if (esdo->this_hdr.sh_offset == (file_ptr) -1) |
{ |
/* Cache the section contents so that they can be compressed |
later. Use bfd_malloc since it will be freed by |
bfd_compress_section_contents. */ |
unsigned char *contents = esdo->this_hdr.contents; |
if ((o->flags & SEC_ELF_COMPRESS) == 0 || contents != NULL) |
abort (); |
contents |
= (unsigned char *) bfd_malloc (esdo->this_hdr.sh_size); |
if (contents == NULL) |
goto error_return; |
esdo->this_hdr.contents = contents; |
} |
} |
|
_bfd_elf_assign_file_positions_for_relocs (abfd); |
|
/* We have now assigned file positions for all the sections except |
.symtab and .strtab. We start the .symtab section at the current |
file position, and write directly to it. We build the .strtab |
section in memory. */ |
.symtab, .strtab, and non-loaded reloc sections. We start the |
.symtab section at the current file position, and write directly |
to it. We build the .strtab section in memory. */ |
bfd_get_symcount (abfd) = 0; |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
/* sh_name is set in prep_headers. */ |
10705,40 → 11155,31 |
/* sh_offset is set just below. */ |
symtab_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align; |
|
off = elf_next_file_pos (abfd); |
off = _bfd_elf_assign_file_position_for_section (symtab_hdr, off, TRUE); |
if (max_sym_count < 20) |
max_sym_count = 20; |
elf_hash_table (info)->strtabsize = max_sym_count; |
amt = max_sym_count * sizeof (struct elf_sym_strtab); |
elf_hash_table (info)->strtab |
= (struct elf_sym_strtab *) bfd_malloc (amt); |
if (elf_hash_table (info)->strtab == NULL) |
goto error_return; |
/* The real buffer will be allocated in elf_link_swap_symbols_out. */ |
flinfo.symshndxbuf |
= (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF) |
? (Elf_External_Sym_Shndx *) -1 : NULL); |
|
if (info->strip != strip_all || emit_relocs) |
{ |
file_ptr off = elf_next_file_pos (abfd); |
|
_bfd_elf_assign_file_position_for_section (symtab_hdr, off, TRUE); |
|
/* 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. */ |
|
/* 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) |
flinfo.symbuf_size = 20; |
else |
flinfo.symbuf_size = max_sym_count; |
amt = flinfo.symbuf_size; |
amt *= bed->s->sizeof_sym; |
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; |
flinfo.shndxbuf_size = amt; |
amt *= sizeof (Elf_External_Sym_Shndx); |
flinfo.symshndxbuf = (Elf_External_Sym_Shndx *) bfd_zmalloc (amt); |
if (flinfo.symshndxbuf == NULL) |
goto error_return; |
} |
|
/* Start writing out the symbol table. The first symbol is always a |
dummy symbol. */ |
if (info->strip != strip_all |
|| emit_relocs) |
{ |
elfsym.st_value = 0; |
elfsym.st_size = 0; |
elfsym.st_info = 0; |
10745,10 → 11186,9 |
elfsym.st_other = 0; |
elfsym.st_shndx = SHN_UNDEF; |
elfsym.st_target_internal = 0; |
if (elf_link_output_sym (&flinfo, NULL, &elfsym, bfd_und_section_ptr, |
NULL) != 1) |
if (elf_link_output_symstrtab (&flinfo, NULL, &elfsym, |
bfd_und_section_ptr, NULL) != 1) |
goto error_return; |
} |
|
/* Output a symbol for each section. We output these even if we are |
discarding local symbols, since they are used for relocs. These |
10755,9 → 11195,7 |
symbols have no names. We store the index of each one in the |
index field of the section, so that we can find it again when |
outputting relocs. */ |
if (info->strip != strip_all |
|| emit_relocs) |
{ |
|
elfsym.st_size = 0; |
elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); |
elfsym.st_other = 0; |
10770,9 → 11208,10 |
{ |
o->target_index = bfd_get_symcount (abfd); |
elfsym.st_shndx = i; |
if (!info->relocatable) |
if (!bfd_link_relocatable (info)) |
elfsym.st_value = o->vma; |
if (elf_link_output_sym (&flinfo, NULL, &elfsym, o, NULL) != 1) |
if (elf_link_output_symstrtab (&flinfo, NULL, &elfsym, o, |
NULL) != 1) |
goto error_return; |
} |
} |
10871,6 → 11310,9 |
return FALSE; |
} |
|
if (!_bfd_elf_fixup_eh_frame_hdr (info)) |
return FALSE; |
|
/* Since ELF permits relocations to be against local symbols, we |
must have the local symbols available when we do the relocations. |
Since we would rather only read the local symbols once, and we |
10891,7 → 11333,7 |
we could write the relocs out and then read them again; I don't |
know how bad the memory loss will be. */ |
|
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) |
for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) |
sub->output_has_begun = FALSE; |
for (o = abfd->sections; o != NULL; o = o->next) |
{ |
10953,7 → 11395,7 |
/* Free symbol buffer if needed. */ |
if (!info->reduce_memory_overheads) |
{ |
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) |
for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) |
if (bfd_get_flavour (sub) == bfd_target_elf_flavour |
&& elf_tdata (sub)->symbuf) |
{ |
10962,17 → 11404,6 |
} |
} |
|
/* 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 |
10982,28 → 11413,15 |
eoinfo.failed = FALSE; |
eoinfo.flinfo = &flinfo; |
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; |
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) |
if (bed->elf_backend_output_arch_local_syms |
&& (info->strip != strip_all || emit_relocs)) |
{ |
typedef int (*out_sym_func) |
(void *, const char *, Elf_Internal_Sym *, asection *, |
11010,7 → 11428,8 |
struct elf_link_hash_entry *); |
|
if (! ((*bed->elf_backend_output_arch_local_syms) |
(abfd, info, &flinfo, (out_sym_func) elf_link_output_sym))) |
(abfd, info, &flinfo, |
(out_sym_func) elf_link_output_symstrtab))) |
return FALSE; |
} |
|
11023,15 → 11442,17 |
symtab_hdr->sh_info = bfd_get_symcount (abfd); |
|
if (dynamic |
&& flinfo.dynsym_sec != NULL |
&& flinfo.dynsym_sec->output_section != bfd_abs_section_ptr) |
&& elf_hash_table (info)->dynsym != NULL |
&& (elf_hash_table (info)->dynsym->output_section |
!= bfd_abs_section_ptr)) |
{ |
Elf_Internal_Sym sym; |
bfd_byte *dynsym = flinfo.dynsym_sec->contents; |
bfd_byte *dynsym = elf_hash_table (info)->dynsym->contents; |
long last_local = 0; |
|
/* Write out the section symbols for the output sections. */ |
if (info->shared || elf_hash_table (info)->is_relocatable_executable) |
if (bfd_link_pic (info) |
|| elf_hash_table (info)->is_relocatable_executable) |
{ |
asection *s; |
|
11099,7 → 11520,7 |
} |
} |
|
elf_section_data (flinfo.dynsym_sec->output_section)->this_hdr.sh_info = |
elf_section_data (elf_hash_table (info)->dynsym->output_section)->this_hdr.sh_info = |
last_local + 1; |
} |
|
11113,7 → 11534,8 |
|
/* If backend needs to output some symbols not present in the hash |
table, do it now. */ |
if (bed->elf_backend_output_arch_syms) |
if (bed->elf_backend_output_arch_syms |
&& (info->strip != strip_all || emit_relocs)) |
{ |
typedef int (*out_sym_func) |
(void *, const char *, Elf_Internal_Sym *, asection *, |
11120,19 → 11542,28 |
struct elf_link_hash_entry *); |
|
if (! ((*bed->elf_backend_output_arch_syms) |
(abfd, info, &flinfo, (out_sym_func) elf_link_output_sym))) |
(abfd, info, &flinfo, |
(out_sym_func) elf_link_output_symstrtab))) |
return FALSE; |
} |
|
/* Flush all symbols to the file. */ |
if (! elf_link_flush_output_syms (&flinfo, bed)) |
/* Finalize the .strtab section. */ |
_bfd_elf_strtab_finalize (flinfo.symstrtab); |
|
/* Swap out the .strtab section. */ |
if (!elf_link_swap_symbols_out (&flinfo)) |
return FALSE; |
|
/* Now we know the size of the symtab section. */ |
off += symtab_hdr->sh_size; |
if (bfd_get_symcount (abfd) > 0) |
{ |
/* Finish up and write out the symbol string table (.strtab) |
section. */ |
Elf_Internal_Shdr *symstrtab_hdr; |
file_ptr off = symtab_hdr->sh_offset + symtab_hdr->sh_size; |
|
symtab_shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; |
if (symtab_shndx_hdr->sh_name != 0) |
symtab_shndx_hdr = & elf_symtab_shndx_list (abfd)->hdr; |
if (symtab_shndx_hdr != NULL && symtab_shndx_hdr->sh_name != 0) |
{ |
symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX; |
symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx); |
11148,15 → 11579,12 |
return FALSE; |
} |
|
|
/* Finish up and write out the symbol string table (.strtab) |
section. */ |
symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr; |
/* sh_name was set in prep_headers. */ |
symstrtab_hdr->sh_type = SHT_STRTAB; |
symstrtab_hdr->sh_flags = 0; |
symstrtab_hdr->sh_addr = 0; |
symstrtab_hdr->sh_size = _bfd_stringtab_size (flinfo.symstrtab); |
symstrtab_hdr->sh_size = _bfd_elf_strtab_size (flinfo.symstrtab); |
symstrtab_hdr->sh_entsize = 0; |
symstrtab_hdr->sh_link = 0; |
symstrtab_hdr->sh_info = 0; |
11163,13 → 11591,12 |
/* sh_offset is set just below. */ |
symstrtab_hdr->sh_addralign = 1; |
|
off = _bfd_elf_assign_file_position_for_section (symstrtab_hdr, off, TRUE); |
off = _bfd_elf_assign_file_position_for_section (symstrtab_hdr, |
off, TRUE); |
elf_next_file_pos (abfd) = off; |
|
if (bfd_get_symcount (abfd) > 0) |
{ |
if (bfd_seek (abfd, symstrtab_hdr->sh_offset, SEEK_SET) != 0 |
|| ! _bfd_stringtab_emit (abfd, flinfo.symstrtab)) |
|| ! _bfd_elf_strtab_emit (abfd, flinfo.symstrtab)) |
return FALSE; |
} |
|
11177,13 → 11604,17 |
for (o = abfd->sections; o != NULL; o = o->next) |
{ |
struct bfd_elf_section_data *esdo = elf_section_data (o); |
bfd_boolean sort; |
if ((o->flags & SEC_RELOC) == 0) |
continue; |
|
if (esdo->rel.hdr != NULL) |
elf_link_adjust_relocs (abfd, &esdo->rel); |
if (esdo->rela.hdr != NULL) |
elf_link_adjust_relocs (abfd, &esdo->rela); |
sort = bed->sort_relocs_p == NULL || (*bed->sort_relocs_p) (o); |
if (esdo->rel.hdr != NULL |
&& !elf_link_adjust_relocs (abfd, &esdo->rel, sort)) |
return FALSE; |
if (esdo->rela.hdr != NULL |
&& !elf_link_adjust_relocs (abfd, &esdo->rela, sort)) |
return FALSE; |
|
/* Set the reloc_count field to 0 to prevent write_relocs from |
trying to swap the relocs out itself. */ |
11374,7 → 11805,7 |
goto error_return; |
|
/* Check for DT_TEXTREL (late, in case the backend removes it). */ |
if (((info->warn_shared_textrel && info->shared) |
if (((info->warn_shared_textrel && bfd_link_pic (info)) |
|| info->error_textrel) |
&& (o = bfd_get_linker_section (dynobj, ".dynamic")) != NULL) |
{ |
11430,6 → 11861,8 |
{ |
/* The contents of the .dynstr section are actually in a |
stringtab. */ |
file_ptr off; |
|
off = elf_section_data (o->output_section)->this_hdr.sh_offset; |
if (bfd_seek (abfd, off, SEEK_SET) != 0 |
|| ! _bfd_elf_strtab_emit (abfd, |
11439,7 → 11872,7 |
} |
} |
|
if (info->relocatable) |
if (bfd_link_relocatable (info)) |
{ |
bfd_boolean failed = FALSE; |
|
11623,8 → 12056,6 |
struct elf_link_hash_entry *h, |
Elf_Internal_Sym *sym) |
{ |
const char *sec_name; |
|
if (h != NULL) |
{ |
switch (h->root.type) |
11636,33 → 12067,6 |
case bfd_link_hash_common: |
return h->root.u.c.p->section; |
|
case bfd_link_hash_undefined: |
case bfd_link_hash_undefweak: |
/* To work around a glibc bug, keep all XXX input sections |
when there is an as yet undefined reference to __start_XXX |
or __stop_XXX symbols. The linker will later define such |
symbols for orphan input sections that have a name |
representable as a C identifier. */ |
if (strncmp (h->root.root.string, "__start_", 8) == 0) |
sec_name = h->root.root.string + 8; |
else if (strncmp (h->root.root.string, "__stop_", 7) == 0) |
sec_name = h->root.root.string + 7; |
else |
sec_name = NULL; |
|
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); |
if (sec) |
sec->flags |= SEC_KEEP; |
} |
} |
break; |
|
default: |
break; |
} |
11680,7 → 12084,8 |
asection * |
_bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec, |
elf_gc_mark_hook_fn gc_mark_hook, |
struct elf_reloc_cookie *cookie) |
struct elf_reloc_cookie *cookie, |
bfd_boolean *start_stop) |
{ |
unsigned long r_symndx; |
struct elf_link_hash_entry *h; |
11693,6 → 12098,12 |
|| ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL) |
{ |
h = cookie->sym_hashes[r_symndx - cookie->extsymoff]; |
if (h == NULL) |
{ |
info->callbacks->einfo (_("%F%P: corrupt input: %B\n"), |
sec->owner); |
return NULL; |
} |
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; |
11703,6 → 12114,38 |
handling copy relocs. */ |
if (h->u.weakdef != NULL) |
h->u.weakdef->mark = 1; |
|
if (start_stop != NULL |
&& (h->root.type == bfd_link_hash_undefined |
|| h->root.type == bfd_link_hash_undefweak)) |
{ |
/* To work around a glibc bug, mark all XXX input sections |
when there is an as yet undefined reference to __start_XXX |
or __stop_XXX symbols. The linker will later define such |
symbols for orphan input sections that have a name |
representable as a C identifier. */ |
const char *sec_name = NULL; |
if (strncmp (h->root.root.string, "__start_", 8) == 0) |
sec_name = h->root.root.string + 8; |
else if (strncmp (h->root.root.string, "__stop_", 7) == 0) |
sec_name = h->root.root.string + 7; |
|
if (sec_name != NULL && *sec_name != '\0') |
{ |
bfd *i; |
|
for (i = info->input_bfds; i != NULL; i = i->link.next) |
{ |
asection *s = bfd_get_section_by_name (i, sec_name); |
if (s != NULL && !s->gc_mark) |
{ |
*start_stop = TRUE; |
return s; |
} |
} |
} |
} |
|
return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL); |
} |
|
11721,10 → 12164,13 |
struct elf_reloc_cookie *cookie) |
{ |
asection *rsec; |
bfd_boolean start_stop = FALSE; |
|
rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie); |
if (rsec && !rsec->gc_mark) |
rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie, &start_stop); |
while (rsec != NULL) |
{ |
if (!rsec->gc_mark) |
{ |
if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour |
|| (rsec->owner->flags & DYNAMIC) != 0) |
rsec->gc_mark = 1; |
11731,6 → 12177,10 |
else if (!_bfd_elf_gc_mark (info, rsec, gc_mark_hook)) |
return FALSE; |
} |
if (!start_stop) |
break; |
rsec = bfd_get_next_section_by_name (rsec->owner, rsec); |
} |
return TRUE; |
} |
|
11792,9 → 12242,55 |
} |
} |
|
eh_frame = elf_section_eh_frame_entry (sec); |
if (ret && eh_frame && !eh_frame->gc_mark) |
if (!_bfd_elf_gc_mark (info, eh_frame, gc_mark_hook)) |
ret = FALSE; |
|
return ret; |
} |
|
/* Scan and mark sections in a special or debug section group. */ |
|
static void |
_bfd_elf_gc_mark_debug_special_section_group (asection *grp) |
{ |
/* Point to first section of section group. */ |
asection *ssec; |
/* Used to iterate the section group. */ |
asection *msec; |
|
bfd_boolean is_special_grp = TRUE; |
bfd_boolean is_debug_grp = TRUE; |
|
/* First scan to see if group contains any section other than debug |
and special section. */ |
ssec = msec = elf_next_in_group (grp); |
do |
{ |
if ((msec->flags & SEC_DEBUGGING) == 0) |
is_debug_grp = FALSE; |
|
if ((msec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) != 0) |
is_special_grp = FALSE; |
|
msec = elf_next_in_group (msec); |
} |
while (msec != ssec); |
|
/* If this is a pure debug section group or pure special section group, |
keep all sections in this group. */ |
if (is_debug_grp || is_special_grp) |
{ |
do |
{ |
msec->gc_mark = 1; |
msec = elf_next_in_group (msec); |
} |
while (msec != ssec); |
} |
} |
|
/* Keep debug and special sections. */ |
|
bfd_boolean |
11803,7 → 12299,7 |
{ |
bfd *ibfd; |
|
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) |
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) |
{ |
asection *isec; |
bfd_boolean some_kept; |
11835,13 → 12331,17 |
continue; |
|
/* Keep debug and special sections like .comment when they are |
not part of a group, or when we have single-member groups. */ |
not part of a group. Also keep section groups that contain |
just debug sections or special sections. */ |
for (isec = ibfd->sections; isec != NULL; isec = isec->next) |
if ((elf_next_in_group (isec) == NULL |
|| elf_next_in_group (isec) == isec) |
&& ((isec->flags & SEC_DEBUGGING) != 0 |
|| (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)) |
{ |
if ((isec->flags & SEC_GROUP) != 0) |
_bfd_elf_gc_mark_debug_special_section_group (isec); |
else if (((isec->flags & SEC_DEBUGGING) != 0 |
|| (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0) |
&& elf_next_in_group (isec) == NULL) |
isec->gc_mark = 1; |
} |
|
if (! debug_frag_seen) |
continue; |
11877,7 → 12377,6 |
isec->name, ilen) == 0) |
{ |
dsec->gc_mark = 0; |
break; |
} |
} |
} |
11900,7 → 12399,7 |
if (!h->mark |
&& (((h->root.type == bfd_link_hash_defined |
|| h->root.type == bfd_link_hash_defweak) |
&& !(h->def_regular |
&& !((h->def_regular || ELF_COMMON_DEF_P (h)) |
&& h->root.u.def.section->gc_mark)) |
|| h->root.type == bfd_link_hash_undefined |
|| h->root.type == bfd_link_hash_undefweak)) |
11931,11 → 12430,12 |
unsigned long section_sym_count; |
struct elf_gc_sweep_symbol_info sweep_info; |
|
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) |
for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) |
{ |
asection *o; |
|
if (bfd_get_flavour (sub) != bfd_target_elf_flavour) |
if (bfd_get_flavour (sub) != bfd_target_elf_flavour |
|| !(*bed->relocs_compatible) (sub->xvec, abfd->xvec)) |
continue; |
|
for (o = sub->sections; o != NULL; o = o->next) |
11968,7 → 12468,9 |
info we collected before. */ |
if (gc_sweep_hook |
&& (o->flags & SEC_RELOC) != 0 |
&& o->reloc_count > 0 |
&& o->reloc_count != 0 |
&& !((info->strip == strip_all || info->strip == strip_debugger) |
&& (o->flags & SEC_DEBUGGING) != 0) |
&& !bfd_is_abs_section (o->output_section)) |
{ |
Elf_Internal_Rela *internal_relocs; |
12116,15 → 12618,20 |
bfd_elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h, void *inf) |
{ |
struct bfd_link_info *info = (struct bfd_link_info *) inf; |
struct bfd_elf_dynamic_list *d = info->dynamic_list; |
|
if ((h->root.type == bfd_link_hash_defined |
|| h->root.type == bfd_link_hash_defweak) |
&& (h->ref_dynamic |
|| ((!info->executable || info->export_dynamic) |
&& h->def_regular |
|| ((h->def_regular || ELF_COMMON_DEF_P (h)) |
&& ELF_ST_VISIBILITY (h->other) != STV_INTERNAL |
&& ELF_ST_VISIBILITY (h->other) != STV_HIDDEN |
&& (strchr (h->root.root.string, ELF_VER_CHR) != NULL |
&& (!bfd_link_executable (info) |
|| info->export_dynamic |
|| (h->dynamic |
&& d != NULL |
&& (*d->match) (&d->head, NULL, h->root.root.string))) |
&& (h->versioned >= versioned |
|| !bfd_hide_sym_by_version (info->version_info, |
h->root.root.string))))) |
h->root.u.def.section->flags |= SEC_KEEP; |
12155,6 → 12662,36 |
} |
} |
|
bfd_boolean |
bfd_elf_parse_eh_frame_entries (bfd *abfd ATTRIBUTE_UNUSED, |
struct bfd_link_info *info) |
{ |
bfd *ibfd = info->input_bfds; |
|
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) |
{ |
asection *sec; |
struct elf_reloc_cookie cookie; |
|
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) |
continue; |
|
if (!init_reloc_cookie (&cookie, info, ibfd)) |
return FALSE; |
|
for (sec = ibfd->sections; sec; sec = sec->next) |
{ |
if (CONST_STRNEQ (bfd_section_name (ibfd, sec), ".eh_frame_entry") |
&& init_reloc_cookie_rels (&cookie, info, ibfd, sec)) |
{ |
_bfd_elf_parse_eh_frame_entry (info, sec, &cookie); |
fini_reloc_cookie_rels (&cookie, sec); |
} |
} |
} |
return TRUE; |
} |
|
/* Do mark and sweep of unused sections. */ |
|
bfd_boolean |
12164,6 → 12701,7 |
bfd *sub; |
elf_gc_mark_hook_fn gc_mark_hook; |
const struct elf_backend_data *bed = get_elf_backend_data (abfd); |
struct elf_link_hash_table *htab; |
|
if (!bed->can_gc_sections |
|| !is_elf_hash_table (info->hash)) |
12173,11 → 12711,13 |
} |
|
bed->gc_keep (info); |
htab = elf_hash_table (info); |
|
/* Try to parse each bfd's .eh_frame section. Point elf_eh_frame_section |
at the .eh_frame section if we can mark the FDEs individually. */ |
_bfd_elf_begin_eh_frame_parsing (info); |
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) |
for (sub = info->input_bfds; |
info->eh_frame_hdr_type != COMPACT_EH_HDR && sub != NULL; |
sub = sub->link.next) |
{ |
asection *sec; |
struct elf_reloc_cookie cookie; |
12190,38 → 12730,32 |
&& (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); |
sec = bfd_get_next_section_by_name (NULL, sec); |
} |
} |
_bfd_elf_end_eh_frame_parsing (info); |
|
/* Apply transitive closure to the vtable entry usage info. */ |
elf_link_hash_traverse (elf_hash_table (info), |
elf_gc_propagate_vtable_entries_used, |
&ok); |
elf_link_hash_traverse (htab, elf_gc_propagate_vtable_entries_used, &ok); |
if (!ok) |
return FALSE; |
|
/* Kill the vtable relocations that were not used. */ |
elf_link_hash_traverse (elf_hash_table (info), |
elf_gc_smash_unused_vtentry_relocs, |
&ok); |
elf_link_hash_traverse (htab, elf_gc_smash_unused_vtentry_relocs, &ok); |
if (!ok) |
return FALSE; |
|
/* Mark dynamically referenced symbols. */ |
if (elf_hash_table (info)->dynamic_sections_created) |
elf_link_hash_traverse (elf_hash_table (info), |
bed->gc_mark_dynamic_ref, |
info); |
if (htab->dynamic_sections_created) |
elf_link_hash_traverse (htab, bed->gc_mark_dynamic_ref, info); |
|
/* Grovel through relocs to find out who stays ... */ |
gc_mark_hook = bed->gc_mark_hook; |
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) |
for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) |
{ |
asection *o; |
|
if (bfd_get_flavour (sub) != bfd_target_elf_flavour) |
if (bfd_get_flavour (sub) != bfd_target_elf_flavour |
|| !(*bed->relocs_compatible) (sub->xvec, abfd->xvec)) |
continue; |
|
/* Start at sections marked with SEC_KEEP (ref _bfd_elf_gc_keep). |
12289,8 → 12823,8 |
win: |
if (!child->vtable) |
{ |
child->vtable = (struct elf_link_virtual_table_entry *) |
bfd_zalloc (abfd, sizeof (*child->vtable)); |
child->vtable = ((struct elf_link_virtual_table_entry *) |
bfd_zalloc (abfd, sizeof (*child->vtable))); |
if (!child->vtable) |
return FALSE; |
} |
12322,8 → 12856,8 |
|
if (!h->vtable) |
{ |
h->vtable = (struct elf_link_virtual_table_entry *) |
bfd_zalloc (abfd, sizeof (*h->vtable)); |
h->vtable = ((struct elf_link_virtual_table_entry *) |
bfd_zalloc (abfd, sizeof (*h->vtable))); |
if (!h->vtable) |
return FALSE; |
} |
12526,7 → 13060,7 |
gotoff = bed->got_header_size; |
|
/* Do the local .got entries first. */ |
for (i = info->input_bfds; i; i = i->link_next) |
for (i = info->input_bfds; i; i = i->link.next) |
{ |
bfd_signed_vma *local_got; |
bfd_size_type j, locsymcount; |
12615,10 → 13149,10 |
|
if ((h->root.type == bfd_link_hash_defined |
|| h->root.type == bfd_link_hash_defweak) |
&& discarded_section (h->root.u.def.section)) |
&& (h->root.u.def.section->owner != rcookie->abfd |
|| h->root.u.def.section->kept_section != NULL |
|| discarded_section (h->root.u.def.section))) |
return TRUE; |
else |
return FALSE; |
} |
else |
{ |
12631,7 → 13165,9 |
/* Need to: get the symbol; get the section. */ |
isym = &rcookie->locsyms[r_symndx]; |
isec = bfd_section_from_elf_index (rcookie->abfd, isym->st_shndx); |
if (isec != NULL && discarded_section (isec)) |
if (isec != NULL |
&& (isec->kept_section != NULL |
|| discarded_section (isec))) |
return TRUE; |
} |
return FALSE; |
12640,94 → 13176,110 |
} |
|
/* Discard unneeded references to discarded sections. |
Returns TRUE if any section's size was changed. */ |
/* This function assumes that the relocations are in sorted order, |
which is true for all known assemblers. */ |
Returns -1 on error, 1 if any section's size was changed, 0 if |
nothing changed. This function assumes that the relocations are in |
sorted order, which is true for all known assemblers. */ |
|
bfd_boolean |
int |
bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) |
{ |
struct elf_reloc_cookie cookie; |
asection *stab, *eh; |
const struct elf_backend_data *bed; |
asection *o; |
bfd *abfd; |
bfd_boolean ret = FALSE; |
int changed = 0; |
|
if (info->traditional_format |
|| !is_elf_hash_table (info->hash)) |
return FALSE; |
return 0; |
|
_bfd_elf_begin_eh_frame_parsing (info); |
for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next) |
o = bfd_get_section_by_name (output_bfd, ".stab"); |
if (o != NULL) |
{ |
asection *i; |
|
for (i = o->map_head.s; i != NULL; i = i->map_head.s) |
{ |
if (i->size == 0 |
|| i->reloc_count == 0 |
|| i->sec_info_type != SEC_INFO_TYPE_STABS) |
continue; |
|
abfd = i->owner; |
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) |
continue; |
|
bed = get_elf_backend_data (abfd); |
if (!init_reloc_cookie_for_section (&cookie, info, i)) |
return -1; |
|
eh = NULL; |
if (!info->relocatable) |
{ |
eh = bfd_get_section_by_name (abfd, ".eh_frame"); |
while (eh != NULL |
&& (eh->size == 0 |
|| bfd_is_abs_section (eh->output_section))) |
eh = bfd_get_next_section_by_name (eh); |
if (_bfd_discard_section_stabs (abfd, i, |
elf_section_data (i)->sec_info, |
bfd_elf_reloc_symbol_deleted_p, |
&cookie)) |
changed = 1; |
|
fini_reloc_cookie_for_section (&cookie, i); |
} |
} |
|
stab = bfd_get_section_by_name (abfd, ".stab"); |
if (stab != NULL |
&& (stab->size == 0 |
|| bfd_is_abs_section (stab->output_section) |
|| stab->sec_info_type != SEC_INFO_TYPE_STABS)) |
stab = NULL; |
o = NULL; |
if (info->eh_frame_hdr_type != COMPACT_EH_HDR) |
o = bfd_get_section_by_name (output_bfd, ".eh_frame"); |
if (o != NULL) |
{ |
asection *i; |
|
if (stab == NULL |
&& eh == NULL |
&& bed->elf_backend_discard_info == NULL) |
for (i = o->map_head.s; i != NULL; i = i->map_head.s) |
{ |
if (i->size == 0) |
continue; |
|
if (!init_reloc_cookie (&cookie, info, abfd)) |
return FALSE; |
abfd = i->owner; |
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) |
continue; |
|
if (stab != NULL |
&& stab->reloc_count > 0 |
&& init_reloc_cookie_rels (&cookie, info, abfd, stab)) |
{ |
if (_bfd_discard_section_stabs (abfd, stab, |
elf_section_data (stab)->sec_info, |
if (!init_reloc_cookie_for_section (&cookie, info, i)) |
return -1; |
|
_bfd_elf_parse_eh_frame (abfd, info, i, &cookie); |
if (_bfd_elf_discard_section_eh_frame (abfd, info, i, |
bfd_elf_reloc_symbol_deleted_p, |
&cookie)) |
ret = TRUE; |
fini_reloc_cookie_rels (&cookie, stab); |
changed = 1; |
|
fini_reloc_cookie_for_section (&cookie, i); |
} |
} |
|
while (eh != NULL |
&& init_reloc_cookie_rels (&cookie, info, abfd, eh)) |
for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next) |
{ |
_bfd_elf_parse_eh_frame (abfd, info, eh, &cookie); |
if (_bfd_elf_discard_section_eh_frame (abfd, info, eh, |
bfd_elf_reloc_symbol_deleted_p, |
&cookie)) |
ret = TRUE; |
fini_reloc_cookie_rels (&cookie, eh); |
eh = bfd_get_next_section_by_name (eh); |
} |
const struct elf_backend_data *bed; |
|
if (bed->elf_backend_discard_info != NULL |
&& (*bed->elf_backend_discard_info) (abfd, &cookie, info)) |
ret = TRUE; |
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) |
continue; |
|
bed = get_elf_backend_data (abfd); |
|
if (bed->elf_backend_discard_info != NULL) |
{ |
if (!init_reloc_cookie (&cookie, info, abfd)) |
return -1; |
|
if ((*bed->elf_backend_discard_info) (abfd, &cookie, info)) |
changed = 1; |
|
fini_reloc_cookie (&cookie, abfd); |
} |
} |
|
if (info->eh_frame_hdr_type == COMPACT_EH_HDR) |
_bfd_elf_end_eh_frame_parsing (info); |
|
if (info->eh_frame_hdr |
&& !info->relocatable |
if (info->eh_frame_hdr_type |
&& !bfd_link_relocatable (info) |
&& _bfd_elf_discard_section_eh_frame_hdr (output_bfd, info)) |
ret = TRUE; |
changed = 1; |
|
return ret; |
return changed; |
} |
|
bfd_boolean |
13011,17 → 13563,24 |
return reloc_sec; |
} |
|
/* Copy the ELF symbol type associated with a linker hash entry. */ |
/* Copy the ELF symbol type and other attributes for a linker script |
assignment from HSRC to HDEST. Generally this should be treated as |
if we found a strong non-dynamic definition for HDEST (except that |
ld ignores multiple definition errors). */ |
void |
_bfd_elf_copy_link_hash_symbol_type (bfd *abfd ATTRIBUTE_UNUSED, |
_bfd_elf_copy_link_hash_symbol_type (bfd *abfd, |
struct bfd_link_hash_entry * hdest, |
struct bfd_link_hash_entry * hsrc) |
{ |
struct elf_link_hash_entry *ehdest = (struct elf_link_hash_entry *)hdest; |
struct elf_link_hash_entry *ehsrc = (struct elf_link_hash_entry *)hsrc; |
Elf_Internal_Sym isym; |
|
ehdest->type = ehsrc->type; |
ehdest->target_internal = ehsrc->target_internal; |
|
isym.st_other = ehsrc->other; |
elf_merge_st_other (abfd, ehdest, &isym, NULL, TRUE, FALSE); |
} |
|
/* Append a RELA relocation REL to section S in BFD. */ |