aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2014-06-10 21:50:21 +0930
committerAlan Modra <amodra@gmail.com>2014-06-10 23:00:22 +0930
commit8a5da09b9e326a19e78b20a1021a5148ea0484b0 (patch)
treee925755d23c841b430e3e5f083c9edb22871ce7b
parent0e58ee40a2cec3c4bf796980fb05f93540e40ec2 (diff)
downloadfsf-binutils-gdb-8a5da09b9e326a19e78b20a1021a5148ea0484b0.zip
fsf-binutils-gdb-8a5da09b9e326a19e78b20a1021a5148ea0484b0.tar.gz
fsf-binutils-gdb-8a5da09b9e326a19e78b20a1021a5148ea0484b0.tar.bz2
Unwrap symbols for debug information
Fixes issues with dwz multi-file (-m) and ld's -wrap option. Symbols referenced from DWARF debug info in a separate file, eg. to specify low and high pc, must use the real symbol. The DWARF info is specifying attributes of the real function, not one interposed with --wrap. include/ * bfdlink.h (unwrap_hash_lookup): Declare. bfd/ * linker.c (unwrap_hash_lookup): New function. * elf-bfd (RELOC_FOR_GLOBAL_SYMBOL): Call unwrap_hash_lookup. * elf32-i370.c (i370_elf_relocate_section): Likewise. * elf32-m32c.c (m32c_elf_relocate_section): Likewise. * elf32-m32r.c (m32r_elf_relocate_section): Likewise. * elf32-score.c (s3_bfd_score_elf_relocate_section): Likewise. * elf32-score7.c (s7_bfd_score_elf_relocate_section): Likewise. * elf32-spu.c (spu_elf_relocate_section): Likewise. * elf64-hppa.c (elf64_hppa_relocate_section): Likewise.
-rw-r--r--bfd/elf-bfd.h5
-rw-r--r--bfd/elf32-i370.c6
-rw-r--r--bfd/elf32-m32c.c5
-rw-r--r--bfd/elf32-m32r.c6
-rw-r--r--bfd/elf32-score.c6
-rw-r--r--bfd/elf32-score7.c6
-rw-r--r--bfd/elf32-spu.c5
-rw-r--r--bfd/elf64-hppa.c5
-rw-r--r--bfd/linker.c38
-rw-r--r--include/bfdlink.h6
10 files changed, 86 insertions, 2 deletions
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 2c02135..1bbe771 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2431,6 +2431,11 @@ extern asection _bfd_elf_large_com_section;
\
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; \
\
+ if (info->wrap_hash != NULL \
+ && (input_section->flags & SEC_DEBUGGING) != 0) \
+ h = ((struct elf_link_hash_entry *) \
+ unwrap_hash_lookup (info, input_bfd, &h->root)); \
+ \
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; \
diff --git a/bfd/elf32-i370.c b/bfd/elf32-i370.c
index 0508aeb..c9ed6e0 100644
--- a/bfd/elf32-i370.c
+++ b/bfd/elf32-i370.c
@@ -1090,6 +1090,12 @@ i370_elf_relocate_section (bfd *output_bfd,
else
{
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+ if (info->wrap_hash != NULL
+ && (input_section->flags & SEC_DEBUGGING) != 0)
+ h = ((struct elf_link_hash_entry *)
+ unwrap_hash_lookup (info, input_bfd, &h->root));
+
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;
diff --git a/bfd/elf32-m32c.c b/bfd/elf32-m32c.c
index 82152dc..ed7df9a 100644
--- a/bfd/elf32-m32c.c
+++ b/bfd/elf32-m32c.c
@@ -408,6 +408,11 @@ m32c_elf_relocate_section
{
h = sym_hashes [r_symndx - symtab_hdr->sh_info];
+ if (info->wrap_hash != NULL
+ && (input_section->flags & SEC_DEBUGGING) != 0)
+ h = ((struct elf_link_hash_entry *)
+ unwrap_hash_lookup (info, input_bfd, &h->root));
+
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;
diff --git a/bfd/elf32-m32r.c b/bfd/elf32-m32r.c
index 0adeb97..9c59c02 100644
--- a/bfd/elf32-m32r.c
+++ b/bfd/elf32-m32r.c
@@ -2490,6 +2490,12 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
relocation = 0;
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+ if (info->wrap_hash != NULL
+ && (input_section->flags & SEC_DEBUGGING) != 0)
+ h = ((struct elf_link_hash_entry *)
+ unwrap_hash_lookup (info, input_bfd, &h->root));
+
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;
diff --git a/bfd/elf32-score.c b/bfd/elf32-score.c
index 677f000..3223d46 100644
--- a/bfd/elf32-score.c
+++ b/bfd/elf32-score.c
@@ -2604,6 +2604,12 @@ s3_bfd_score_elf_relocate_section (bfd *output_bfd,
/* For global symbols we look up the symbol in the hash-table. */
h = ((struct score_elf_link_hash_entry *)
elf_sym_hashes (input_bfd) [r_symndx - extsymoff]);
+
+ if (info->wrap_hash != NULL
+ && (input_section->flags & SEC_DEBUGGING) != 0)
+ h = ((struct score_elf_link_hash_entry *)
+ unwrap_hash_lookup (info, input_bfd, &h->root.root));
+
/* Find the real hash-table entry for this symbol. */
while (h->root.root.type == bfd_link_hash_indirect
|| h->root.root.type == bfd_link_hash_warning)
diff --git a/bfd/elf32-score7.c b/bfd/elf32-score7.c
index 06ded9a..c241077 100644
--- a/bfd/elf32-score7.c
+++ b/bfd/elf32-score7.c
@@ -2376,6 +2376,12 @@ s7_bfd_score_elf_relocate_section (bfd *output_bfd,
/* For global symbols we look up the symbol in the hash-table. */
h = ((struct score_elf_link_hash_entry *)
elf_sym_hashes (input_bfd) [r_symndx - extsymoff]);
+
+ if (info->wrap_hash != NULL
+ && (input_section->flags & SEC_DEBUGGING) != 0)
+ h = ((struct score_elf_link_hash_entry *)
+ unwrap_hash_lookup (info, input_bfd, &h->root.root));
+
/* Find the real hash-table entry for this symbol. */
while (h->root.root.type == bfd_link_hash_indirect
|| h->root.root.type == bfd_link_hash_warning)
diff --git a/bfd/elf32-spu.c b/bfd/elf32-spu.c
index d111277..ac9c184 100644
--- a/bfd/elf32-spu.c
+++ b/bfd/elf32-spu.c
@@ -4850,6 +4850,11 @@ spu_elf_relocate_section (bfd *output_bfd,
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ if (info->wrap_hash != NULL
+ && (input_section->flags & SEC_DEBUGGING) != 0)
+ h = ((struct elf_link_hash_entry *)
+ unwrap_hash_lookup (info, input_bfd, &h->root));
+
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;
diff --git a/bfd/elf64-hppa.c b/bfd/elf64-hppa.c
index 49473e7..b57497d 100644
--- a/bfd/elf64-hppa.c
+++ b/bfd/elf64-hppa.c
@@ -3868,6 +3868,11 @@ elf64_hppa_relocate_section (bfd *output_bfd,
eh = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ if (info->wrap_hash != NULL
+ && (input_section->flags & SEC_DEBUGGING) != 0)
+ eh = ((struct elf_link_hash_entry *)
+ unwrap_hash_lookup (info, input_bfd, &eh->root));
+
while (eh->root.type == bfd_link_hash_indirect
|| eh->root.type == bfd_link_hash_warning)
eh = (struct elf_link_hash_entry *) eh->root.u.i.link;
diff --git a/bfd/linker.c b/bfd/linker.c
index a20a276..d00238c 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -566,8 +566,6 @@ bfd_wrapped_link_hash_lookup (bfd *abfd,
return h;
}
-#undef WRAP
-
#undef REAL
#define REAL "__real_"
@@ -602,6 +600,42 @@ bfd_wrapped_link_hash_lookup (bfd *abfd,
return bfd_link_hash_lookup (info->hash, string, create, copy, follow);
}
+/* If H is a wrapped symbol, ie. the symbol name starts with "__wrap_"
+ and the remainder is found in wrap_hash, return the real symbol. */
+
+struct bfd_link_hash_entry *
+unwrap_hash_lookup (struct bfd_link_info *info,
+ bfd *input_bfd,
+ struct bfd_link_hash_entry *h)
+{
+ const char *l = h->root.string;
+
+ if (*l == bfd_get_symbol_leading_char (input_bfd)
+ || *l == info->wrap_char)
+ ++l;
+
+ if (CONST_STRNEQ (l, WRAP))
+ {
+ l += sizeof WRAP - 1;
+
+ if (bfd_hash_lookup (info->wrap_hash, l, FALSE, FALSE) != NULL)
+ {
+ char save = 0;
+ if (l - sizeof WRAP - 1 != h->root.string)
+ {
+ --l;
+ save = *l;
+ *(char *) l = *h->root.string;
+ }
+ h = bfd_link_hash_lookup (info->hash, l, FALSE, FALSE, FALSE);
+ if (save)
+ *(char *) l = save;
+ }
+ }
+ return h;
+}
+#undef WRAP
+
/* Traverse a generic link hash table. Differs from bfd_hash_traverse
in the treatment of warning symbols. When warning symbols are
created they replace the real symbol, so you don't get to see the
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 9f1b50b..509d626 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -186,6 +186,12 @@ extern struct bfd_link_hash_entry *bfd_wrapped_link_hash_lookup
(bfd *, struct bfd_link_info *, const char *, bfd_boolean,
bfd_boolean, bfd_boolean);
+/* If H is a wrapped symbol, ie. the symbol name starts with "__wrap_"
+ and the remainder is found in wrap_hash, return the real symbol. */
+
+extern struct bfd_link_hash_entry *unwrap_hash_lookup
+ (struct bfd_link_info *, bfd *, struct bfd_link_hash_entry *);
+
/* Traverse a link hash table. */
extern void bfd_link_hash_traverse
(struct bfd_link_hash_table *,