Unwrap symbols for debug information
authorAlan Modra <amodra@gmail.com>
Tue, 10 Jun 2014 12:20:21 +0000 (21:50 +0930)
committerAlan Modra <amodra@gmail.com>
Tue, 10 Jun 2014 13:30:22 +0000 (23:00 +0930)
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.

bfd/elf-bfd.h
bfd/elf32-i370.c
bfd/elf32-m32c.c
bfd/elf32-m32r.c
bfd/elf32-score.c
bfd/elf32-score7.c
bfd/elf32-spu.c
bfd/elf64-hppa.c
bfd/linker.c
include/bfdlink.h

index 2c02135..1bbe771 100644 (file)
@@ -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;            \
index 0508aeb..c9ed6e0 100644 (file)
@@ -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;
index 82152dc..ed7df9a 100644 (file)
@@ -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;
index 0adeb97..9c59c02 100644 (file)
@@ -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;
index 677f000..3223d46 100644 (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.  */
           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)
index 06ded9a..c241077 100644 (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.  */
           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)
index d111277..ac9c184 100644 (file)
@@ -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;
index 49473e7..b57497d 100644 (file)
@@ -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;
index a20a276..d00238c 100644 (file)
@@ -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
index 9f1b50b..509d626 100644 (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_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 *,