summaryrefslogtreecommitdiff
path: root/bfd/elflink.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2004-08-09 06:02:03 +0000
committerAlan Modra <amodra@gmail.com>2004-08-09 06:02:03 +0000
commit8387904def5e1510b39abce755c964c1b3f52307 (patch)
tree40e1ef05b173ac7b158f2ec5a48752ae948901f1 /bfd/elflink.c
parentfed7ba43e0cf5e3f58d8fb93615cb11a342906cf (diff)
downloadbinutils-gdb-8387904def5e1510b39abce755c964c1b3f52307.tar.gz
* 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.
Diffstat (limited to 'bfd/elflink.c')
-rw-r--r--bfd/elflink.c99
1 files changed, 57 insertions, 42 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 7c7414a7ec2..82220ecf573 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -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;