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:
parent
0e58ee40a2
commit
8a5da09b9e
|
@ -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; \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
38
bfd/linker.c
38
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
|
||||
|
|
|
@ -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 *,
|
||||
|
|
Loading…
Reference in New Issue