aboutsummaryrefslogtreecommitdiff
path: root/bfd/elflink.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elflink.c')
-rw-r--r--bfd/elflink.c626
1 files changed, 332 insertions, 294 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c
index cca0c67..c4f57cf 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -1,5 +1,5 @@
/* ELF linking support for BFD.
- Copyright (C) 1995-2024 Free Software Foundation, Inc.
+ Copyright (C) 1995-2025 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -64,7 +64,7 @@ _bfd_elf_link_keep_memory (struct bfd_link_info *info)
this is opt-in by each backend. */
const struct elf_backend_data *bed
= get_elf_backend_data (info->output_bfd);
- if (bed->use_mmap)
+ if (bed != NULL && bed->use_mmap)
return false;
#endif
bfd *abfd;
@@ -96,22 +96,64 @@ _bfd_elf_link_keep_memory (struct bfd_link_info *info)
return true;
}
-asection *
-_bfd_elf_section_for_symbol (struct elf_reloc_cookie *cookie,
- unsigned long r_symndx,
- bool discard)
+static struct elf_link_hash_entry *
+get_link_hash_entry (struct elf_link_hash_entry ** sym_hashes,
+ unsigned int symndx,
+ unsigned int ext_sym_start)
{
+ if (sym_hashes == NULL
+ /* Guard against corrupt input. See PR 32636 for an example. */
+ || symndx < ext_sym_start)
+ return NULL;
+
+ struct elf_link_hash_entry *h = sym_hashes[symndx - ext_sym_start];
+
+ /* The hash might be empty. See PR 32641 for an example of this. */
+ if (h == NULL)
+ 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;
+
+ return h;
+}
+
+struct elf_link_hash_entry *
+_bfd_elf_get_link_hash_entry (struct elf_link_hash_entry ** sym_hashes,
+ unsigned int symndx,
+ Elf_Internal_Shdr * symtab_hdr)
+{
+ if (symtab_hdr == NULL)
+ return NULL;
+
+ return get_link_hash_entry (sym_hashes, symndx, symtab_hdr->sh_info);
+}
+
+static struct elf_link_hash_entry *
+get_ext_sym_hash_from_cookie (struct elf_reloc_cookie *cookie, unsigned long r_symndx)
+{
+ if (cookie == NULL || cookie->sym_hashes == NULL)
+ return NULL;
+
if (r_symndx >= cookie->locsymcount
|| ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL)
- {
- struct elf_link_hash_entry *h;
+ return get_link_hash_entry (cookie->sym_hashes, r_symndx, cookie->extsymoff);
- h = cookie->sym_hashes[r_symndx - cookie->extsymoff];
+ 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;
+asection *
+_bfd_elf_section_for_symbol (struct elf_reloc_cookie *cookie,
+ unsigned long r_symndx,
+ bool discard)
+{
+ struct elf_link_hash_entry *h;
+ h = get_ext_sym_hash_from_cookie (cookie, r_symndx);
+
+ if (h != NULL)
+ {
if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& discarded_section (h->root.u.def.section))
@@ -119,21 +161,20 @@ _bfd_elf_section_for_symbol (struct elf_reloc_cookie *cookie,
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;
- }
+ /* 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;
}
@@ -198,8 +239,7 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
s = bfd_make_section_anyway_with_flags (abfd,
(bed->rela_plts_and_copies_p
? ".rela.got" : ".rel.got"),
- (bed->dynamic_sec_flags
- | SEC_READONLY));
+ flags | SEC_READONLY);
if (s == NULL
|| !bfd_set_section_alignment (s, bed->s->log_file_align))
return false;
@@ -397,8 +437,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
if (info->enable_dt_relr)
{
s = bfd_make_section_anyway_with_flags (abfd, ".relr.dyn",
- (bed->dynamic_sec_flags
- | SEC_READONLY));
+ flags | SEC_READONLY);
if (s == NULL
|| !bfd_set_section_alignment (s, bed->s->log_file_align))
return false;
@@ -2247,16 +2286,19 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
/* Return the glibc version reference if VERSION_DEP is added to the
list of glibc version dependencies successfully. VERSION_DEP will
- be put into the .gnu.version_r section. */
+ be put into the .gnu.version_r section. GLIBC_MINOR_BASE is the
+ pointer to the glibc minor base version. */
static Elf_Internal_Verneed *
elf_link_add_glibc_verneed (struct elf_find_verdep_info *rinfo,
Elf_Internal_Verneed *glibc_verref,
- const char *version_dep)
+ const char *version_dep,
+ int *glibc_minor_base)
{
Elf_Internal_Verneed *t;
Elf_Internal_Vernaux *a;
size_t amt;
+ int minor_version = -1;
if (glibc_verref != NULL)
{
@@ -2272,8 +2314,6 @@ elf_link_add_glibc_verneed (struct elf_find_verdep_info *rinfo,
}
else
{
- bool is_glibc;
-
for (t = elf_tdata (rinfo->info->output_bfd)->verref;
t != NULL;
t = t->vn_nextref)
@@ -2287,7 +2327,6 @@ elf_link_add_glibc_verneed (struct elf_find_verdep_info *rinfo,
if (t == NULL)
return t;
- is_glibc = false;
for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
{
/* Return if VERSION_DEP dependency has been added. */
@@ -2296,12 +2335,24 @@ elf_link_add_glibc_verneed (struct elf_find_verdep_info *rinfo,
return t;
/* Check if libc.so provides GLIBC_2.XX version. */
- if (!is_glibc && startswith (a->vna_nodename, "GLIBC_2."))
- is_glibc = true;
+ if (startswith (a->vna_nodename, "GLIBC_2."))
+ {
+ minor_version = strtol (a->vna_nodename + 8, NULL, 10);
+ if (minor_version < *glibc_minor_base)
+ *glibc_minor_base = minor_version;
+ }
}
/* Skip if it isn't linked against glibc. */
- if (!is_glibc)
+ if (minor_version < 0)
+ return NULL;
+ }
+
+ /* Skip if 2.GLIBC_MINOR_BASE includes VERSION_DEP. */
+ if (startswith (version_dep, "GLIBC_2."))
+ {
+ minor_version = strtol (version_dep + 8, NULL, 10);
+ if (minor_version <= *glibc_minor_base)
return NULL;
}
@@ -2333,10 +2384,12 @@ _bfd_elf_link_add_glibc_version_dependency
const char *version_dep[])
{
Elf_Internal_Verneed *t = NULL;
+ int glibc_minor_base = INT_MAX;
do
{
- t = elf_link_add_glibc_verneed (rinfo, t, *version_dep);
+ t = elf_link_add_glibc_verneed (rinfo, t, *version_dep,
+ &glibc_minor_base);
/* Return if there is no glibc version reference. */
if (t == NULL)
return;
@@ -2827,14 +2880,9 @@ _bfd_elf_link_info_read_relocs (bfd *abfd,
bfd_size_type size;
size = (bfd_size_type) o->reloc_count * sizeof (Elf_Internal_Rela);
- if (keep_memory)
- {
- internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_alloc (abfd, size);
- if (info)
- info->cache_size += size;
- }
- else
- internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_malloc (size);
+ if (keep_memory && info)
+ info->cache_size += size;
+ internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_malloc (size);
if (internal_relocs == NULL)
return NULL;
}
@@ -2863,7 +2911,7 @@ _bfd_elf_link_info_read_relocs (bfd *abfd,
if (keep_memory)
esdo->relocs = internal_relocs;
- _bfd_munmap_readonly_temporary (alloc1, alloc1_size);
+ _bfd_munmap_temporary (alloc1, alloc1_size);
/* Don't free alloc2, since if it was allocated we are passing it
back (under the name of internal_relocs). */
@@ -2871,14 +2919,8 @@ _bfd_elf_link_info_read_relocs (bfd *abfd,
return internal_relocs;
error_return:
- _bfd_munmap_readonly_temporary (alloc1, alloc1_size);
- if (alloc2 != NULL)
- {
- if (keep_memory)
- bfd_release (abfd, alloc2);
- else
- free (alloc2);
- }
+ _bfd_munmap_temporary (alloc1, alloc1_size);
+ free (alloc2);
return NULL;
}
@@ -3342,12 +3384,9 @@ _bfd_elf_adjust_dynamic_copy (struct bfd_link_info *info,
--power_of_two;
}
- if (power_of_two > bfd_section_alignment (dynbss))
- {
- /* Adjust the section alignment if needed. */
- if (!bfd_set_section_alignment (dynbss, power_of_two))
- return false;
- }
+ /* Adjust the section alignment if needed. */
+ if (!bfd_link_align_section (dynbss, power_of_two))
+ return false;
/* We make sure that the symbol will be aligned properly. */
dynbss->size = BFD_ALIGN (dynbss->size, mask + 1);
@@ -3567,7 +3606,7 @@ _bfd_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
/* Ensure the alignment of the first section (usually .tdata) is the largest
alignment, so that the tls segment starts aligned. */
if (tls != NULL)
- tls->alignment_power = align;
+ (void) bfd_link_align_section (tls, align);
return tls;
}
@@ -3639,6 +3678,7 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
object file is an IR object, give linker LTO plugin a chance to
get the correct symbol table. */
if (abfd->plugin_format == bfd_plugin_yes
+ || abfd->plugin_format == bfd_plugin_yes_unused
#if BFD_SUPPORTS_PLUGINS
|| (abfd->plugin_format == bfd_plugin_unknown
&& bfd_link_plugin_object_p (abfd))
@@ -4319,8 +4359,8 @@ elf_link_add_to_first_hash (bfd *abfd, struct bfd_link_info *info,
= ((struct elf_link_first_hash_entry *)
bfd_hash_lookup (htab->first_hash, name, true, copy));
if (e == NULL)
- info->callbacks->einfo
- (_("%F%P: %pB: failed to add %s to first hash\n"), abfd, name);
+ info->callbacks->fatal
+ (_("%P: %pB: failed to add %s to first hash\n"), abfd, name);
if (e->abfd == NULL)
/* Store ABFD in abfd. */
@@ -4387,8 +4427,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
|| !bfd_hash_table_init
(htab->first_hash, elf_link_first_hash_newfunc,
sizeof (struct elf_link_first_hash_entry)))
- info->callbacks->einfo
- (_("%F%P: first_hash failed to create: %E\n"));
+ info->callbacks->fatal
+ (_("%P: first_hash failed to create: %E\n"));
}
}
else
@@ -4925,6 +4965,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
asection *sec, *new_sec;
flagword flags;
const char *name;
+ const char *defvername;
bool must_copy_name = false;
struct elf_link_hash_entry *h;
struct elf_link_hash_entry *hi;
@@ -5101,6 +5142,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
old_alignment = 0;
old_bfd = NULL;
new_sec = sec;
+ defvername = NULL;
if (is_elf_hash_table (&htab->root))
{
@@ -5219,7 +5261,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
default version of the symbol. */
if ((iver.vs_vers & VERSYM_HIDDEN) == 0
&& isym->st_shndx != SHN_UNDEF)
- *p++ = ELF_VER_CHR;
+ *p++ = ELF_VER_CHR, defvername = name;
memcpy (p, verstr, verlen + 1);
name = newname;
@@ -5664,14 +5706,20 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
/* Create dynamic sections for backends that require
that be done before setup_gnu_properties. */
if (!_bfd_elf_link_create_dynamic_sections (abfd, info))
- return false;
+ goto error_free_vers;
add_needed = true;
}
else if (dynamic
&& h->root.u.def.section->owner == abfd)
- /* Add this symbol to first hash if this shared
- object has the first definition. */
- elf_link_add_to_first_hash (abfd, info, name, must_copy_name);
+ {
+ /* Add this symbol to first hash if this shared
+ object has the first definition. */
+ elf_link_add_to_first_hash (abfd, info, name, must_copy_name);
+ /* And if it was the default symbol version definition,
+ also add the short name. */
+ if (defvername)
+ elf_link_add_to_first_hash (abfd, info, defvername, false);
+ }
}
}
}
@@ -5680,7 +5728,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
&& !bfd_link_relocatable (info)
&& (abfd->flags & BFD_PLUGIN) == 0
&& !just_syms
- && extsymcount)
+ && extsymcount != 0
+ && is_elf_hash_table (&htab->root))
{
int r_sym_shift;
@@ -5703,9 +5752,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
if ((s->flags & SEC_RELOC) == 0
|| s->reloc_count == 0
|| (s->flags & SEC_EXCLUDE) != 0
- || ((info->strip == strip_all
- || info->strip == strip_debugger)
- && (s->flags & SEC_DEBUGGING) != 0))
+ || (s->flags & SEC_DEBUGGING) != 0)
continue;
internal_relocs = _bfd_elf_link_info_read_relocs
@@ -5804,6 +5851,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
return true;
}
+ free (old_strtab);
+ old_strtab = NULL;
if (old_tab != NULL)
{
if (!(*bed->notice_as_needed) (abfd, info, notice_needed))
@@ -5861,9 +5910,9 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
}
free (shortname);
}
- free (nondeflt_vers);
- nondeflt_vers = NULL;
}
+ free (nondeflt_vers);
+ nondeflt_vers = NULL;
/* Now set the alias field correctly for all the weak defined
symbols we found. The only way to do this is to search all the
@@ -6027,7 +6076,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
if (bed->check_directives
&& !(*bed->check_directives) (abfd, info))
- return false;
+ goto error_return;
/* If this is a non-traditional link, try to optimize the handling
of the .stab/.stabstr sections. */
@@ -6232,12 +6281,30 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
if (h->type == bfd_link_hash_undefined)
{
- /* If the archive element has already been loaded then one
- of the symbols defined by that element might have been
- made undefined due to being in a discarded section. */
- if (is_elf_hash_table (info->hash)
- && ((struct elf_link_hash_entry *) h)->indx == -3)
- continue;
+ if (is_elf_hash_table (info->hash))
+ {
+ /* If the archive element has already been loaded then one
+ of the symbols defined by that element might have been
+ made undefined due to being in a discarded section. */
+ if (((struct elf_link_hash_entry *) h)->indx == -3)
+ continue;
+
+ /* In the pre-LTO-plugin pass we must not mistakenly
+ include this archive member if an earlier shared
+ library defined this symbol. */
+ struct elf_link_hash_table *htab = elf_hash_table (info);
+ if (htab->first_hash)
+ {
+ struct elf_link_first_hash_entry *e
+ = ((struct elf_link_first_hash_entry *)
+ bfd_hash_lookup (htab->first_hash, symdef->name,
+ false, false));
+ if (e
+ && (e->abfd->flags & DYNAMIC) != 0
+ && e->abfd != abfd)
+ continue;
+ }
+ }
}
else if (h->type == bfd_link_hash_common)
{
@@ -7030,6 +7097,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
if (s->contents == NULL && s->size != 0)
return false;
+ s->alloced = 1;
/* Fill in the version definition section. */
@@ -7273,6 +7341,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
if (s->contents == NULL)
return false;
+ s->alloced = 1;
p = s->contents;
for (vn = elf_tdata (output_bfd)->verref;
@@ -7810,6 +7879,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
s->contents = (unsigned char *) bfd_zalloc (output_bfd, s->size);
if (s->contents == NULL)
return false;
+ s->alloced = 1;
if (!_bfd_elf_add_dynamic_entry (info, DT_VERSYM, 0))
return false;
@@ -7828,6 +7898,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
if (s->contents == NULL)
return false;
+ s->alloced = 1;
/* The first entry in .dynsym is a dummy symbol. Clear all the
section syms, in case we don't output them all. */
@@ -7883,6 +7954,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
s->contents = (unsigned char *) bfd_zalloc (output_bfd, s->size);
if (s->contents == NULL)
return false;
+ s->alloced = 1;
bfd_put (8 * hash_entry_size, output_bfd, bucketcount, s->contents);
bfd_put (8 * hash_entry_size, output_bfd, dynsymcount,
@@ -7943,6 +8015,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
if (contents == NULL)
return false;
s->contents = contents;
+ s->alloced = 1;
/* 1 empty bucket. */
bfd_put_32 (output_bfd, 1, contents);
/* SYMIDX above the special symbol 0. */
@@ -8026,6 +8099,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
}
s->contents = contents;
+ s->alloced = 1;
bfd_put_32 (output_bfd, bucketcount, contents);
bfd_put_32 (output_bfd, cinfo.symindx, contents + 4);
bfd_put_32 (output_bfd, maskwords, contents + 8);
@@ -8095,8 +8169,8 @@ _bfd_elf_merge_sections (bfd *obfd, struct bfd_link_info *info)
bfd *ibfd;
asection *sec;
- if (!is_elf_hash_table (info->hash))
- return false;
+ if (ENABLE_CHECKING && !is_elf_hash_table (info->hash))
+ abort ();
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
if ((ibfd->flags & DYNAMIC) == 0
@@ -8119,8 +8193,8 @@ _bfd_elf_merge_sections (bfd *obfd, struct bfd_link_info *info)
}
if (elf_hash_table (info)->merge_info != NULL)
- _bfd_merge_sections (obfd, info, elf_hash_table (info)->merge_info,
- merge_sections_remove_hook);
+ return _bfd_merge_sections (obfd, info, elf_hash_table (info)->merge_info,
+ merge_sections_remove_hook);
return true;
}
@@ -8304,11 +8378,11 @@ _bfd_elf_link_hash_table_init
struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
struct bfd_hash_table *,
const char *),
- unsigned int entsize,
- enum elf_target_id target_id)
+ unsigned int entsize)
{
bool ret;
- int can_refcount = get_elf_backend_data (abfd)->can_refcount;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ int can_refcount = bed->can_refcount;
table->init_got_refcount.refcount = can_refcount - 1;
table->init_plt_refcount.refcount = can_refcount - 1;
@@ -8320,8 +8394,9 @@ _bfd_elf_link_hash_table_init
ret = _bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize);
table->root.type = bfd_link_elf_hash_table;
- table->hash_table_id = target_id;
- table->target_os = get_elf_backend_data (abfd)->target_os;
+ table->hash_table_id = bed->target_id;
+ table->target_os = bed->target_os;
+ table->root.hash_table_free = _bfd_elf_link_hash_table_free;
return ret;
}
@@ -8339,13 +8414,11 @@ _bfd_elf_link_hash_table_create (bfd *abfd)
return NULL;
if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc,
- sizeof (struct elf_link_hash_entry),
- GENERIC_ELF_DATA))
+ sizeof (struct elf_link_hash_entry)))
{
free (ret);
return NULL;
}
- ret->root.hash_table_free = _bfd_elf_link_hash_table_free;
return &ret->root;
}
@@ -8363,12 +8436,19 @@ _bfd_elf_link_hash_table_free (bfd *obfd)
_bfd_merge_sections_free (htab->merge_info);
/* NB: htab->dynamic->contents is always allocated by bfd_realloc. */
if (htab->dynamic != NULL)
- free (htab->dynamic->contents);
+ {
+ free (htab->dynamic->contents);
+ htab->dynamic->contents = NULL;
+ }
if (htab->first_hash != NULL)
{
bfd_hash_table_free (htab->first_hash);
free (htab->first_hash);
}
+ if (htab->eh_info.frame_hdr_is_compact)
+ free (htab->eh_info.u.compact.entries);
+ else
+ free (htab->eh_info.u.dwarf.array);
_bfd_generic_link_hash_table_free (obfd);
}
@@ -8805,6 +8885,8 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
symp->name = bfd_elf_string_from_elf_section (bfd1,
hdr1->sh_link,
ssym->st_name);
+ if (symp->name == NULL)
+ goto done;
symp++;
}
@@ -8818,6 +8900,8 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
symp->name = bfd_elf_string_from_elf_section (bfd2,
hdr2->sh_link,
ssym->st_name);
+ if (symp->name == NULL)
+ goto done;
symp++;
}
@@ -8864,14 +8948,22 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
goto done;
for (i = 0; i < count1; i++)
- symtable1[i].name
- = bfd_elf_string_from_elf_section (bfd1, hdr1->sh_link,
- symtable1[i].u.isym->st_name);
+ {
+ symtable1[i].name
+ = bfd_elf_string_from_elf_section (bfd1, hdr1->sh_link,
+ symtable1[i].u.isym->st_name);
+ if (symtable1[i].name == NULL)
+ goto done;
+ }
for (i = 0; i < count2; i++)
- symtable2[i].name
- = bfd_elf_string_from_elf_section (bfd2, hdr2->sh_link,
- symtable2[i].u.isym->st_name);
+ {
+ symtable2[i].name
+ = bfd_elf_string_from_elf_section (bfd2, hdr2->sh_link,
+ symtable2[i].u.isym->st_name);
+ if (symtable2[i].name == NULL)
+ goto done;
+ }
/* Sort symbol by name. */
qsort (symtable1, count1, sizeof (struct elf_symbol),
@@ -9042,7 +9134,6 @@ set_symbol_value (bfd *bfd_with_globals,
size_t symidx,
bfd_vma val)
{
- struct elf_link_hash_entry **sym_hashes;
struct elf_link_hash_entry *h;
size_t extsymoff = locsymcount;
@@ -9065,12 +9156,12 @@ set_symbol_value (bfd *bfd_with_globals,
/* It is a global symbol: set its link type
to "defined" and give it a value. */
-
- sym_hashes = elf_sym_hashes (bfd_with_globals);
- h = sym_hashes [symidx - 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;
+ h = get_link_hash_entry (elf_sym_hashes (bfd_with_globals), symidx, extsymoff);
+ if (h == NULL)
+ {
+ /* FIXMEL What should we do ? */
+ return;
+ }
h->root.type = bfd_link_hash_defined;
h->root.u.def.value = val;
h->root.u.def.section = bfd_abs_section_ptr;
@@ -10427,10 +10518,6 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
ret = false;
free (symbuf);
-
- free (hash_table->strtab);
- hash_table->strtab = NULL;
-
return ret;
}
@@ -11206,7 +11293,7 @@ _bfd_elf_default_action_discarded (asection *sec)
&& strncmp (sec->name, ".eh_frame.", 10) == 0)
return 0;
- if (strcmp (".sframe", sec->name) == 0)
+ if (elf_section_type (sec) == SHT_GNU_SFRAME)
return 0;
if (strcmp (".gcc_except_table", sec->name) == 0)
@@ -11552,10 +11639,19 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
|| (elf_bad_symtab (input_bfd)
&& flinfo->sections[symndx] == NULL))
{
- struct elf_link_hash_entry *h = sym_hashes[symndx - 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;
+ struct elf_link_hash_entry *h;
+
+ h = get_link_hash_entry (sym_hashes, symndx, extsymoff);
+ if (h == NULL)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("error: %pB: unable to create group section symbol"),
+ input_bfd);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
/* Arrange for symbol to be output. */
h->indx = -2;
elf_section_data (osec)->this_hdr.sh_info = -2;
@@ -11690,7 +11786,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
|| (elf_bad_symtab (input_bfd)
&& flinfo->sections[r_symndx] == NULL))
{
- h = sym_hashes[r_symndx - extsymoff];
+ h = get_link_hash_entry (sym_hashes, r_symndx, extsymoff);
/* Badly formatted input files can contain relocs that
reference non-existant symbols. Check here so that
@@ -11699,17 +11795,13 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
{
_bfd_error_handler
/* xgettext:c-format */
- (_("error: %pB contains a reloc (%#" PRIx64 ") for section %pA "
+ (_("error: %pB contains a reloc (%#" PRIx64 ") for section '%pA' "
"that references a non-existent global symbol"),
input_bfd, (uint64_t) rel->r_info, o);
bfd_set_error (bfd_error_bad_value);
return false;
}
- 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;
-
s_type = h->type;
/* If a plugin symbol is referenced from a non-IR file,
@@ -11925,7 +12017,6 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
&& flinfo->sections[r_symndx] == NULL))
{
struct elf_link_hash_entry *rh;
- unsigned long indx;
/* This is a reloc against a global symbol. We
have not yet output all the local symbols, so
@@ -11934,15 +12025,16 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
reloc to point to the global hash table entry
for this symbol. The symbol index is then
set at the end of bfd_elf_final_link. */
- indx = r_symndx - extsymoff;
- rh = elf_sym_hashes (input_bfd)[indx];
- while (rh->root.type == bfd_link_hash_indirect
- || rh->root.type == bfd_link_hash_warning)
- rh = (struct elf_link_hash_entry *) rh->root.u.i.link;
-
- /* Setting the index to -2 tells
- elf_link_output_extsym that this symbol is
- used by a reloc. */
+ rh = get_link_hash_entry (elf_sym_hashes (input_bfd),
+ r_symndx, extsymoff);
+ if (rh == NULL)
+ {
+ /* FIXME: Generate an error ? */
+ continue;
+ }
+
+ /* Setting the index to -2 tells elf_link_output_extsym
+ that this symbol is used by a reloc. */
BFD_ASSERT (rh->indx < 0);
rh->indx = -2;
*rel_hash = rh;
@@ -12140,9 +12232,9 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
break;
case SEC_INFO_TYPE_SFRAME:
{
- /* Merge .sframe sections into the ctf frame encoder
- context of the output_bfd's section. The final .sframe
- output section will be written out later. */
+ /* Merge SFrame section into the SFrame encoder context of the
+ output_bfd's section. The final .sframe output section will
+ be written out later. */
if (!_bfd_elf_merge_section_sframe (output_bfd, flinfo->info,
o, contents))
return false;
@@ -12544,12 +12636,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
size_t relr_entsize;
asection *reldyn = 0;
bfd_size_type amt;
- asection *attr_section = NULL;
- bfd_vma attr_size = 0;
- const char *std_attrs_section;
struct elf_link_hash_table *htab = elf_hash_table (info);
bool sections_removed;
- bool ret;
if (!is_elf_hash_table (&htab->root))
return false;
@@ -12593,12 +12681,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
sections from the link, and set the contents of the output
section. */
sections_removed = false;
- std_attrs_section = get_elf_backend_data (abfd)->obj_attrs_section;
+ const char *obj_attrs_section = get_elf_backend_data (abfd)->obj_attrs_section;
for (o = abfd->sections; o != NULL; o = o->next)
{
bool remove_section = false;
- if ((std_attrs_section && strcmp (o->name, std_attrs_section) == 0)
+ if ((obj_attrs_section && strcmp (o->name, obj_attrs_section) == 0)
|| strcmp (o->name, ".gnu.attributes") == 0)
{
for (p = o->map_head.link_order; p != NULL; p = p->next)
@@ -12613,12 +12701,16 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
input_section->flags &= ~SEC_HAS_CONTENTS;
}
- attr_size = bfd_elf_obj_attr_size (abfd);
- bfd_set_section_size (o, attr_size);
/* Skip this section later on. */
o->map_head.link_order = NULL;
- if (attr_size)
- attr_section = o;
+
+ bfd_vma attr_size = bfd_elf_obj_attr_size (abfd);
+ /* Once ELF headers have been written, the size of a section is
+ frozen. We need to set the size of the attribute section before
+ _bfd_elf_compute_section_file_positions. */
+ bfd_set_section_size (o, attr_size);
+ if (attr_size > 0)
+ elf_obj_build_attributes (abfd) = o;
else
remove_section = true;
}
@@ -12900,7 +12992,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
{
file_ptr off = elf_next_file_pos (abfd);
- _bfd_elf_assign_file_position_for_section (symtab_hdr, off, true);
+ _bfd_elf_assign_file_position_for_section (symtab_hdr, off, true, 0);
/* Note that at this point elf_next_file_pos (abfd) is
incorrect. We do not yet know the size of the .symtab section.
@@ -13054,8 +13146,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
if (info->enable_dt_relr
&& bed->finish_relative_relocs
&& !bed->finish_relative_relocs (info))
- info->callbacks->einfo
- (_("%F%P: %pB: failed to finish relative relocations\n"), abfd);
+ info->callbacks->fatal
+ (_("%P: %pB: failed to finish relative relocations\n"), abfd);
/* Since ELF permits relocations to be against local symbols, we
must have the local symbols available when we do the relocations.
@@ -13153,8 +13245,6 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
}
}
- ret = true;
-
/* 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
@@ -13167,10 +13257,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
eoinfo.file_sym_done = false;
bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo);
if (eoinfo.failed)
- {
- ret = false;
- goto return_local_hash_table;
- }
+ goto error_return;
/* If backend needs to output some local symbols not present in the hash
table, do it now. */
@@ -13178,10 +13265,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
{
if (! ((*bed->elf_backend_output_arch_local_syms)
(abfd, info, &flinfo, elf_link_output_symstrtab)))
- {
- ret = false;
- goto return_local_hash_table;
- }
+ goto error_return;
}
/* That wrote out all the local symbols. Finish up the symbol table
@@ -13228,10 +13312,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
BFD_ASSERT (indx > 0);
sym.st_shndx = indx;
if (! check_dynsym (abfd, &sym))
- {
- ret = false;
- goto return_local_hash_table;
- }
+ goto error_return;
sym.st_value = s->vma;
dest = dynsym + dynindx * bed->s->sizeof_sym;
@@ -13269,10 +13350,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
sym.st_shndx =
elf_section_data (s->output_section)->this_idx;
if (! check_dynsym (abfd, &sym))
- {
- ret = false;
- goto return_local_hash_table;
- }
+ goto error_return;
sym.st_value = (s->output_section->vma
+ s->output_offset
+ e->isym.st_value);
@@ -13295,10 +13373,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
eoinfo.flinfo = &flinfo;
bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo);
if (eoinfo.failed)
- {
- ret = false;
- goto return_local_hash_table;
- }
+ goto error_return;
/* If backend needs to output some symbols not present in the hash
table, do it now. */
@@ -13307,10 +13382,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
{
if (! ((*bed->elf_backend_output_arch_syms)
(abfd, info, &flinfo, elf_link_output_symstrtab)))
- {
- ret = false;
- goto return_local_hash_table;
- }
+ goto error_return;
}
/* Finalize the .strtab section. */
@@ -13318,10 +13390,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
/* Swap out the .strtab section. */
if (!elf_link_swap_symbols_out (&flinfo))
- {
- ret = false;
- goto return_local_hash_table;
- }
+ goto error_return;
+ free (htab->strtab);
+ htab->strtab = NULL;
/* Now we know the size of the symtab section. */
if (bfd_get_symcount (abfd) > 0)
@@ -13344,14 +13415,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
symtab_shndx_hdr->sh_size = amt;
off = _bfd_elf_assign_file_position_for_section (symtab_shndx_hdr,
- off, true);
+ off, true, 0);
if (bfd_seek (abfd, symtab_shndx_hdr->sh_offset, SEEK_SET) != 0
|| (bfd_write (flinfo.symshndxbuf, amt, abfd) != amt))
- {
- ret = false;
- goto return_local_hash_table;
- }
+ goto error_return;
}
}
@@ -13368,23 +13436,19 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
symstrtab_hdr->sh_addralign = 1;
off = _bfd_elf_assign_file_position_for_section (symstrtab_hdr,
- off, true);
+ off, true, 0);
elf_next_file_pos (abfd) = off;
if (bfd_seek (abfd, symstrtab_hdr->sh_offset, SEEK_SET) != 0
|| ! _bfd_elf_strtab_emit (abfd, flinfo.symstrtab))
- {
- ret = false;
- goto return_local_hash_table;
- }
+ goto error_return;
}
if (info->out_implib_bfd && !elf_output_implib (abfd, info))
{
_bfd_error_handler (_("%pB: failed to generate import library"),
info->out_implib_bfd);
- ret = false;
- goto return_local_hash_table;
+ goto error_return;
}
/* Adjust the relocs to have the correct symbol indices. */
@@ -13399,16 +13463,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
sort = bed->sort_relocs_p == NULL || (*bed->sort_relocs_p) (o);
if (esdo->rel.hdr != NULL
&& !elf_link_adjust_relocs (abfd, o, &esdo->rel, sort, info))
- {
- ret = false;
- goto return_local_hash_table;
- }
+ goto error_return;
if (esdo->rela.hdr != NULL
&& !elf_link_adjust_relocs (abfd, o, &esdo->rela, sort, info))
- {
- ret = false;
- goto return_local_hash_table;
- }
+ goto error_return;
/* Set the reloc_count field to 0 to prevent write_relocs from
trying to swap the relocs out itself. */
@@ -13767,34 +13825,26 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
if (! _bfd_elf_write_section_sframe (abfd, info))
goto error_return;
+ if (! _bfd_elf_write_section_build_attributes (abfd, info))
+ goto error_ret2;
+
if (info->callbacks->emit_ctf)
info->callbacks->emit_ctf ();
elf_final_link_free (abfd, &flinfo);
- if (attr_section)
- {
- bfd_byte *contents = (bfd_byte *) bfd_malloc (attr_size);
- if (contents == NULL)
- {
- /* Bail out and fail. */
- ret = false;
- goto return_local_hash_table;
- }
- bfd_elf_set_obj_attr_contents (abfd, contents, attr_size);
- bfd_set_section_contents (abfd, attr_section, contents, 0, attr_size);
- free (contents);
- }
-
- return_local_hash_table:
if (info->unique_symbol)
bfd_hash_table_free (&flinfo.local_hash_table);
- return ret;
+ return true;
error_return:
+ free (htab->strtab);
+ htab->strtab = NULL;
elf_final_link_free (abfd, &flinfo);
- ret = false;
- goto return_local_hash_table;
+ error_ret2:
+ if (info->unique_symbol)
+ bfd_hash_table_free (&flinfo.local_hash_table);
+ return false;
}
/* Initialize COOKIE for input bfd ABFD. */
@@ -13844,7 +13894,7 @@ init_reloc_cookie (struct elf_reloc_cookie *cookie,
{
symtab_hdr->contents = (bfd_byte *) cookie->locsyms;
info->cache_size += (cookie->locsymcount
- * sizeof (Elf_External_Sym_Shndx));
+ * sizeof (Elf_Internal_Sym));
}
}
return true;
@@ -13942,25 +13992,21 @@ _bfd_elf_gc_mark_hook (asection *sec,
struct elf_link_hash_entry *h,
Elf_Internal_Sym *sym)
{
- if (h != NULL)
+ if (h == NULL)
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+
+ switch (h->root.type)
{
- switch (h->root.type)
- {
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- return h->root.u.def.section;
+ case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
+ return h->root.u.def.section;
- case bfd_link_hash_common:
- return h->root.u.c.p->section;
+ case bfd_link_hash_common:
+ return h->root.u.c.p->section;
- default:
- break;
- }
+ default:
+ return NULL;
}
- else
- return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
-
- return NULL;
}
/* Return the debug definition section. */
@@ -14009,56 +14055,49 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
if (r_symndx == STN_UNDEF)
return NULL;
- if (r_symndx >= cookie->locsymcount
- || ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL)
+ h = get_ext_sym_hash_from_cookie (cookie, r_symndx);
+ if (h == NULL)
{
- bool was_marked;
+ /* A corrupt input file can lead to a situation where the index
+ does not reference either a local or an external symbol. */
+ if (r_symndx >= cookie->locsymcount)
+ return NULL;
- h = cookie->sym_hashes[r_symndx - cookie->extsymoff];
- if (h == NULL)
- {
- info->callbacks->einfo (_("%F%P: corrupt input: %pB\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;
+ return (*gc_mark_hook) (sec, info, cookie->rel, NULL,
+ &cookie->locsyms[r_symndx]);
+ }
- was_marked = h->mark;
- h->mark = 1;
- /* Keep all aliases of the symbol too. If an object symbol
- needs to be copied into .dynbss then all of its aliases
- should be present as dynamic symbols, not just the one used
- on the copy relocation. */
- hw = h;
- while (hw->is_weakalias)
- {
- hw = hw->u.alias;
- hw->mark = 1;
- }
+ bool was_marked = h->mark;
- if (!was_marked && h->start_stop && !h->root.ldscript_def)
- {
- if (info->start_stop_gc)
- return NULL;
+ h->mark = 1;
+ /* Keep all aliases of the symbol too. If an object symbol
+ needs to be copied into .dynbss then all of its aliases
+ should be present as dynamic symbols, not just the one used
+ on the copy relocation. */
+ hw = h;
+ while (hw->is_weakalias)
+ {
+ hw = hw->u.alias;
+ hw->mark = 1;
+ }
- /* To work around a glibc bug, mark XXX input sections
- when there is a reference to __start_XXX or __stop_XXX
- symbols. */
- else if (start_stop != NULL)
- {
- asection *s = h->u2.start_stop_section;
- *start_stop = true;
- return s;
- }
- }
+ if (!was_marked && h->start_stop && !h->root.ldscript_def)
+ {
+ if (info->start_stop_gc)
+ return NULL;
- return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL);
+ /* To work around a glibc bug, mark XXX input sections
+ when there is a reference to __start_XXX or __stop_XXX
+ symbols. */
+ else if (start_stop != NULL)
+ {
+ asection *s = h->u2.start_stop_section;
+ *start_stop = true;
+ return s;
+ }
}
- return (*gc_mark_hook) (sec, info, cookie->rel, NULL,
- &cookie->locsyms[r_symndx]);
+ return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL);
}
/* COOKIE->rel describes a relocation against section SEC, which is
@@ -14270,7 +14309,7 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
else if (strcmp (bfd_section_name (isec),
"__patchable_function_entries") == 0
&& elf_linked_to_section (isec) == NULL)
- info->callbacks->einfo (_("%F%P: %pB(%pA): error: "
+ info->callbacks->fatal (_("%P: %pB(%pA): error: "
"need linked-to section "
"for --gc-sections\n"),
isec->owner, isec);
@@ -14371,7 +14410,8 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
if (o->flags & SEC_GROUP)
{
asection *first = elf_next_in_group (o);
- o->gc_mark = first->gc_mark;
+ if (first != NULL)
+ o->gc_mark = first->gc_mark;
}
if (o->gc_mark)
@@ -15079,17 +15119,12 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
if (r_symndx == STN_UNDEF)
return true;
- if (r_symndx >= rcookie->locsymcount
- || ELF_ST_BIND (rcookie->locsyms[r_symndx].st_info) != STB_LOCAL)
- {
- struct elf_link_hash_entry *h;
-
- h = rcookie->sym_hashes[r_symndx - rcookie->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;
+ struct elf_link_hash_entry *h;
+ h = get_ext_sym_hash_from_cookie (rcookie, r_symndx);
+
+ if (h != NULL)
+ {
if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& (h->root.u.def.section->owner != rcookie->abfd
@@ -15099,6 +15134,10 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
}
else
{
+ if (r_symndx >= rcookie->locsymcount)
+ /* This can happen with corrupt input. */
+ return false;
+
/* It's not a relocation against a global symbol,
but it could be a relocation against a local
symbol for a discarded section. */
@@ -15113,6 +15152,7 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
|| discarded_section (isec)))
return true;
}
+
return false;
}
return false;
@@ -15296,9 +15336,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
if (info->eh_frame_hdr_type == COMPACT_EH_HDR)
_bfd_elf_end_eh_frame_parsing (info);
- if (info->eh_frame_hdr_type
- && !bfd_link_relocatable (info)
- && _bfd_elf_discard_section_eh_frame_hdr (info))
+ if (_bfd_elf_discard_section_eh_frame_hdr (info))
changed = 1;
return changed;
@@ -15449,7 +15487,7 @@ _bfd_elf_section_already_linked (bfd *abfd,
/* This is the first section with this name. Record it. */
if (!bfd_section_already_linked_table_insert (already_linked_list, sec))
- info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
+ info->callbacks->fatal (_("%P: already_linked_table: %E\n"));
return sec->output_section == bfd_abs_section_ptr;
}