From: Alan Modra Date: Tue, 10 Jun 2014 12:20:21 +0000 (+0930) Subject: Unwrap symbols for debug information X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8a5da09b9;p=binutils-gdb.git 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. --- diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 2c02135b80c..1bbe771cfc5 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 0508aeb3ddd..c9ed6e0260f 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 82152dc56f6..ed7df9ab677 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 0adeb9731cd..9c59c02090c 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 677f0005d6d..3223d461001 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 06ded9a6ef7..c24107771aa 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 d1112778e11..ac9c184eaf1 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 49473e73d0b..b57497d4b53 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 a20a27663d6..d00238cbd4d 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 9f1b50bb8ca..509d626f383 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 *,