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.
This commit is contained in:
Alan Modra 2014-06-10 21:50:21 +09:30
parent 0e58ee40a2
commit 8a5da09b9e
10 changed files with 86 additions and 2 deletions

View file

@ -2431,6 +2431,11 @@ extern asection _bfd_elf_large_com_section;
\ \
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; \ 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 \ while (h->root.type == bfd_link_hash_indirect \
|| h->root.type == bfd_link_hash_warning) \ || h->root.type == bfd_link_hash_warning) \
h = (struct elf_link_hash_entry *) h->root.u.i.link; \ h = (struct elf_link_hash_entry *) h->root.u.i.link; \

View file

@ -1090,6 +1090,12 @@ i370_elf_relocate_section (bfd *output_bfd,
else else
{ {
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 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 while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning) || h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link; h = (struct elf_link_hash_entry *) h->root.u.i.link;

View file

@ -408,6 +408,11 @@ m32c_elf_relocate_section
{ {
h = sym_hashes [r_symndx - symtab_hdr->sh_info]; 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 while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning) || h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link; h = (struct elf_link_hash_entry *) h->root.u.i.link;

View file

@ -2490,6 +2490,12 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
relocation = 0; relocation = 0;
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 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 while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning) || h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link; h = (struct elf_link_hash_entry *) h->root.u.i.link;

View file

@ -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. */ /* For global symbols we look up the symbol in the hash-table. */
h = ((struct score_elf_link_hash_entry *) h = ((struct score_elf_link_hash_entry *)
elf_sym_hashes (input_bfd) [r_symndx - extsymoff]); 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. */ /* Find the real hash-table entry for this symbol. */
while (h->root.root.type == bfd_link_hash_indirect while (h->root.root.type == bfd_link_hash_indirect
|| h->root.root.type == bfd_link_hash_warning) || h->root.root.type == bfd_link_hash_warning)

View file

@ -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. */ /* For global symbols we look up the symbol in the hash-table. */
h = ((struct score_elf_link_hash_entry *) h = ((struct score_elf_link_hash_entry *)
elf_sym_hashes (input_bfd) [r_symndx - extsymoff]); 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. */ /* Find the real hash-table entry for this symbol. */
while (h->root.root.type == bfd_link_hash_indirect while (h->root.root.type == bfd_link_hash_indirect
|| h->root.root.type == bfd_link_hash_warning) || h->root.root.type == bfd_link_hash_warning)

View file

@ -4850,6 +4850,11 @@ spu_elf_relocate_section (bfd *output_bfd,
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 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 while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning) || h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link; h = (struct elf_link_hash_entry *) h->root.u.i.link;

View file

@ -3868,6 +3868,11 @@ elf64_hppa_relocate_section (bfd *output_bfd,
eh = sym_hashes[r_symndx - symtab_hdr->sh_info]; 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 while (eh->root.type == bfd_link_hash_indirect
|| eh->root.type == bfd_link_hash_warning) || eh->root.type == bfd_link_hash_warning)
eh = (struct elf_link_hash_entry *) eh->root.u.i.link; eh = (struct elf_link_hash_entry *) eh->root.u.i.link;

View file

@ -566,8 +566,6 @@ bfd_wrapped_link_hash_lookup (bfd *abfd,
return h; return h;
} }
#undef WRAP
#undef REAL #undef REAL
#define REAL "__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); 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 /* Traverse a generic link hash table. Differs from bfd_hash_traverse
in the treatment of warning symbols. When warning symbols are in the treatment of warning symbols. When warning symbols are
created they replace the real symbol, so you don't get to see the created they replace the real symbol, so you don't get to see the

View file

@ -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 *, struct bfd_link_info *, const char *, bfd_boolean,
bfd_boolean, 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. */ /* Traverse a link hash table. */
extern void bfd_link_hash_traverse extern void bfd_link_hash_traverse
(struct bfd_link_hash_table *, (struct bfd_link_hash_table *,