forked from Imagelibrary/binutils-gdb
* elf-bfd.h (struct elf_backend_data): Add
elf_backend_archive_symbol_lookup. (_bfd_elf_archive_symbol_lookup): Declare. * elflink.c (_bfd_elf_archive_symbol_lookup): New function.. (elf_link_add_archive_symbols): ..extracted from here. Call the backend version. * elfxx-target.h (elf_backend_archive_symbol_lookup): Provide default. (elfNN_bed): Init new field. * elf64-ppc.c (elf_backend_check_directives): Define. (elf_backend_archive_symbol_lookup): Define. (struct ppc_link_hash_table): Add tls_get_add_fd. Make tls_get_add a ppc_link_hash_entry pointer. (get_fdh): Move. (ppc64_elf_archive_symbol_lookup, opd_entry_value): New functions. (add_symbol_adjust, ppc64_elf_check_directives): New functions. (ppc64_elf_check_relocs, ppc64_elf_gc_mark_hook, func_desc_adjust, ppc64_elf_adjust_dynamic_symbol, ppc64_elf_tls_setup, ppc64_elf_tls_optimize, allocate_dynrelocs, ppc_type_of_stub, ppc_build_one_stub, ppc64_elf_size_stubs, ppc64_elf_relocate_section, ppc64_elf_finish_dynamic_symbol): Handle branch relocs to function descriptor symbols.
This commit is contained in:
@@ -4194,6 +4194,55 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Return the linker hash table entry of a symbol that might be
|
||||
satisfied by an archive symbol. Return -1 on error. */
|
||||
|
||||
struct elf_link_hash_entry *
|
||||
_bfd_elf_archive_symbol_lookup (bfd *abfd,
|
||||
struct bfd_link_info *info,
|
||||
const char *name)
|
||||
{
|
||||
struct elf_link_hash_entry *h;
|
||||
char *p, *copy;
|
||||
size_t len, first;
|
||||
|
||||
h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, FALSE);
|
||||
if (h != NULL)
|
||||
return h;
|
||||
|
||||
/* If this is a default version (the name contains @@), look up the
|
||||
symbol again with only one `@' as well as without the version.
|
||||
The effect is that references to the symbol with and without the
|
||||
version will be matched by the default symbol in the archive. */
|
||||
|
||||
p = strchr (name, ELF_VER_CHR);
|
||||
if (p == NULL || p[1] != ELF_VER_CHR)
|
||||
return h;
|
||||
|
||||
/* First check with only one `@'. */
|
||||
len = strlen (name);
|
||||
copy = bfd_alloc (abfd, len);
|
||||
if (copy == NULL)
|
||||
return (struct elf_link_hash_entry *) 0 - 1;
|
||||
|
||||
first = p - name + 1;
|
||||
memcpy (copy, name, first);
|
||||
memcpy (copy + first, name + first + 1, len - first);
|
||||
|
||||
h = elf_link_hash_lookup (elf_hash_table (info), copy, FALSE, FALSE, FALSE);
|
||||
if (h == NULL)
|
||||
{
|
||||
/* We also need to check references to the symbol without the
|
||||
version. */
|
||||
copy[first - 1] = '\0';
|
||||
h = elf_link_hash_lookup (elf_hash_table (info), copy,
|
||||
FALSE, FALSE, FALSE);
|
||||
}
|
||||
|
||||
bfd_release (abfd, copy);
|
||||
return h;
|
||||
}
|
||||
|
||||
/* 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
|
||||
@@ -4228,6 +4277,9 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
carsym *symdefs;
|
||||
bfd_boolean loop;
|
||||
bfd_size_type amt;
|
||||
const struct elf_backend_data *bed;
|
||||
struct elf_link_hash_entry * (*archive_symbol_lookup)
|
||||
(bfd *, struct bfd_link_info *, const char *);
|
||||
|
||||
if (! bfd_has_map (abfd))
|
||||
{
|
||||
@@ -4252,6 +4304,8 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
goto error_return;
|
||||
|
||||
symdefs = bfd_ardata (abfd)->symdefs;
|
||||
bed = get_elf_backend_data (abfd);
|
||||
archive_symbol_lookup = bed->elf_backend_archive_symbol_lookup;
|
||||
|
||||
do
|
||||
{
|
||||
@@ -4280,48 +4334,9 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
continue;
|
||||
}
|
||||
|
||||
h = elf_link_hash_lookup (elf_hash_table (info), symdef->name,
|
||||
FALSE, FALSE, FALSE);
|
||||
|
||||
if (h == NULL)
|
||||
{
|
||||
char *p, *copy;
|
||||
size_t len, first;
|
||||
|
||||
/* If this is a default version (the name contains @@),
|
||||
look up the symbol again with only one `@' as well
|
||||
as without the version. The effect is that references
|
||||
to the symbol with and without the version will be
|
||||
matched by the default symbol in the archive. */
|
||||
|
||||
p = strchr (symdef->name, ELF_VER_CHR);
|
||||
if (p == NULL || p[1] != ELF_VER_CHR)
|
||||
continue;
|
||||
|
||||
/* First check with only one `@'. */
|
||||
len = strlen (symdef->name);
|
||||
copy = bfd_alloc (abfd, len);
|
||||
if (copy == NULL)
|
||||
goto error_return;
|
||||
first = p - symdef->name + 1;
|
||||
memcpy (copy, symdef->name, first);
|
||||
memcpy (copy + first, symdef->name + first + 1, len - first);
|
||||
|
||||
h = elf_link_hash_lookup (elf_hash_table (info), copy,
|
||||
FALSE, FALSE, FALSE);
|
||||
|
||||
if (h == NULL)
|
||||
{
|
||||
/* We also need to check references to the symbol
|
||||
without the version. */
|
||||
|
||||
copy[first - 1] = '\0';
|
||||
h = elf_link_hash_lookup (elf_hash_table (info),
|
||||
copy, FALSE, FALSE, FALSE);
|
||||
}
|
||||
|
||||
bfd_release (abfd, copy);
|
||||
}
|
||||
h = archive_symbol_lookup (abfd, info, symdef->name);
|
||||
if (h == (struct elf_link_hash_entry *) 0 - 1)
|
||||
goto error_return;
|
||||
|
||||
if (h == NULL)
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user