]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Try harder to find the correct symbol to associate with OPEN GNU BUILD notes.
authorNick Clifton <nickc@redhat.com>
Tue, 14 Mar 2017 12:57:09 +0000 (12:57 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 14 Mar 2017 12:57:09 +0000 (12:57 +0000)
* readelf.c (print_gnu_build_attribute_description): Move symbol
printing code to...
(print_symbol_for_build_attribute): New function.  ...here.
Add to find the best symbol to associate with an OPEN note.
Add code to cache the symbol table and string table, so that they
are not loaded every time a note is displayed.
* testsuite/binutils-all/note-2-32.s: Add a function symbol.
* testsuite/binutils-all/note-2-64.s: Likewise.
* testsuite/binutils-all/note-2-32.d: Update expected note output.
* testsuite/binutils-all/note-2-64.d: Likewise.

binutils/ChangeLog
binutils/readelf.c
binutils/testsuite/binutils-all/note-2-32.d
binutils/testsuite/binutils-all/note-2-32.s
binutils/testsuite/binutils-all/note-2-64.d
binutils/testsuite/binutils-all/note-2-64.s

index 71dd6e2fb25a94b7d13761a03180c4dd235f0be8..f9fb74689f17b6df2f077fb94c60e89612288cc0 100644 (file)
@@ -1,3 +1,16 @@
+2017-03-14  Nick Clifton  <nickc@redhat.com>
+
+       * readelf.c (print_gnu_build_attribute_description): Move symbol
+       printing code to...
+       (print_symbol_for_build_attribute): New function.  ...here.
+       Add to find the best symbol to associate with an OPEN note.
+       Add code to cache the symbol table and string table, so that they
+       are not loaded every time a note is displayed.
+       * testsuite/binutils-all/note-2-32.s: Add a function symbol.
+       * testsuite/binutils-all/note-2-64.s: Likewise.
+       * testsuite/binutils-all/note-2-32.d: Update expected note output.
+       * testsuite/binutils-all/note-2-64.d: Likewise.
+
 2017-03-13  Alan Modra  <amodra@gmail.com>
            Taeung Song <treeze.taeung@gmail.com>
 
index a10ba19b5bb1a622f581417da1ba6fedb1313f1b..34781ae86636c84186847aa4e1163554e4d6c7e6 100644 (file)
@@ -16598,115 +16598,167 @@ print_ia64_vms_note (Elf_Internal_Note * pnote)
   return TRUE;
 }
 
+/* Print the name of the symbol associated with a build attribute
+   that is attached to address OFFSET.  */
+
 static bfd_boolean
-print_gnu_build_attribute_description (Elf_Internal_Note * pnote,
-                                      FILE *              file,
-                                      Elf_Internal_Shdr * section ATTRIBUTE_UNUSED)
+print_symbol_for_build_attribute (FILE *         file,
+                                 unsigned long  offset,
+                                 bfd_boolean    is_open_attr)
 {
-  static unsigned long global_offset = 0;
-  unsigned long       i;
-  unsigned long       strtab_size = 0;
-  char *              strtab = NULL;
-  Elf_Internal_Sym *  symtab = NULL;
-  unsigned long       nsyms = 0;
-  Elf_Internal_Shdr * symsec = NULL;
-  unsigned int        desc_size = is_32bit_elf ? 4 : 8;
-
-  if (pnote->descsz  == 0)
-    {
-      printf (_("    Applies from offset %#lx\n"), global_offset);
-      return TRUE;
-    }
+  static FILE *             saved_file = NULL;
+  static char *             strtab;
+  static unsigned long      strtablen;
+  static Elf_Internal_Sym * symtab;
+  static unsigned long      nsyms;
+  Elf_Internal_Sym *  saved_sym = NULL;
+  Elf_Internal_Sym *  sym;
 
-  if (pnote->descsz != desc_size)
+  if (saved_file == NULL || file != saved_file)
     {
-      error (_("    <invalid description size: %lx>\n"), pnote->descsz);
-      printf (_("    <invalid descsz>"));
-      return FALSE;
-    }
+      Elf_Internal_Shdr * symsec;
 
-  /* Load the symbols.  */
-  for (symsec = section_headers;
-       symsec < section_headers + elf_header.e_shnum;
-       symsec ++)
-    {
-      if (symsec->sh_type == SHT_SYMTAB)
+      /* Load the symbol and string sections.  */
+      for (symsec = section_headers;
+          symsec < section_headers + elf_header.e_shnum;
+          symsec ++)
        {
-         symtab = GET_ELF_SYMBOLS (file, symsec, & nsyms);
-
-         if (symsec->sh_link < elf_header.e_shnum)
+         if (symsec->sh_type == SHT_SYMTAB)
            {
-             Elf_Internal_Shdr * strtab_sec = section_headers + symsec->sh_link;
+             symtab = GET_ELF_SYMBOLS (file, symsec, & nsyms);
 
-             strtab = (char *) get_data (NULL, file, strtab_sec->sh_offset,
-                                         1, strtab_sec->sh_size,
-                                         _("string table"));
-             strtab_size = strtab != NULL ? strtab_sec->sh_size : 0;
+             if (symsec->sh_link < elf_header.e_shnum)
+               {
+                 Elf_Internal_Shdr * strtab_sec = section_headers + symsec->sh_link;
+
+                 strtab = (char *) get_data (NULL, file, strtab_sec->sh_offset,
+                                             1, strtab_sec->sh_size,
+                                             _("string table"));
+                 strtablen = strtab != NULL ? strtab_sec->sh_size : 0;
+               }
            }
        }
+      saved_file = file;
     }
 
-  printf (_("    Applies from offset"));
-
-  for (i = 0; i < pnote->descsz; i += desc_size)
+  if (symtab == NULL || strtab == NULL)
     {
-      Elf_Internal_Sym * saved_sym = NULL;
-      Elf_Internal_Sym * sym;
-      unsigned long offset;
+      printf ("\n");
+      return FALSE;
+    }
 
-      offset = byte_get ((unsigned char *) pnote->descdata + i, desc_size);
+  /* Find a symbol whose value matches offset.  */
+  for (sym = symtab; sym < symtab + nsyms; sym ++)
+    if (sym->st_value == offset)
+      {
+       if (sym->st_name >= strtablen)
+         /* Huh ?  This should not happen.  */
+         continue;
 
-      if (i + desc_size == pnote->descsz)
-       printf (_(" %#lx"), offset);
-      else
-       printf (_(" %#lx, "), offset);
+       if (strtab[sym->st_name] == 0)
+         continue;
 
-      if (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN)
-       global_offset = offset;
+       if (is_open_attr)
+         {
+           /* For OPEN attributes we prefer GLOBAL over LOCAL symbols
+              and FILE or OBJECT symbols over NOTYPE symbols.  We skip
+              FUNC symbols entirely.  */
+           switch (ELF_ST_TYPE (sym->st_info))
+             {
+             case STT_FILE:
+               saved_sym = sym;
+               /* We can stop searching now.  */
+               sym = symtab + nsyms;
+               continue;
 
-      if (symtab == NULL || strtab == NULL)
-       continue;
+             case STT_OBJECT:
+               saved_sym = sym;
+               continue;
 
-      /* Find a symbol whose value matches offset.  */
-      for (sym = symtab; sym < symtab + nsyms; sym ++)
-       if (sym->st_value == offset)
-         {
-           if (sym->st_name < strtab_size)
+             case STT_FUNC:
+               /* Ignore function symbols.  */
+               continue;
+
+             default:
+               break;
+             }
+
+           switch (ELF_ST_BIND (sym->st_info))
              {
-               if (strtab[sym->st_name] == 0)
-                 continue;
+             case STB_GLOBAL:
+               if (saved_sym == NULL
+                   || ELF_ST_TYPE (saved_sym->st_info) != STT_OBJECT)
+                 saved_sym = sym;
+               break;
 
-               if (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN)
-                 {
-                   /* For OPEN attributes we prefer GLOBAL symbols, if there
-                      is one that matches.  But keep a record of a matching
-                      LOCAL symbol, just in case that is all that we can find.  */
-                   if (ELF_ST_BIND (sym->st_info) == STB_LOCAL)
-                     {
-                       saved_sym = sym;
-                       continue;
-                     }
-                   printf (_(" (file: %s)"), strtab + sym->st_name);
-                 }
-               else if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
-                 continue;
-               else
-                 printf (_(" (function: %s)"), strtab + sym->st_name);
+             case STB_LOCAL:
+               if (saved_sym == NULL)
+                 saved_sym = sym;
+               break;
+
+             default:
                break;
              }
          }
+       else
+         {
+           if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
+             continue;
+
+           saved_sym = sym;
+           break;
+         }
+      }
+
+  printf (" (%s: %s)\n",
+         is_open_attr ? _("file") : _("func"),
+         saved_sym ? strtab + saved_sym->st_name : _("<no symbol found>)"));
+  return TRUE;
+}
+
+static bfd_boolean
+print_gnu_build_attribute_description (Elf_Internal_Note * pnote,
+                                      FILE *              file)
+{
+  static unsigned long global_offset = 0;
+  unsigned long        offset;
+  unsigned int         desc_size = is_32bit_elf ? 4 : 8;
+  bfd_boolean          is_open_attr = pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN;
 
-      if (sym == symtab + nsyms)
+  if (pnote->descsz == 0)
+    {
+      if (is_open_attr)
        {
-         if (saved_sym)
-           printf (_(" (file: %s)"), strtab + saved_sym->st_name);
-         else
-           printf (_(" (<symbol name unknown>)"));
+         printf (_("    Applies from offset %#lx\n"), global_offset);
+         return TRUE;
+       }
+      else
+       {
+         printf (_("    Applies to func at %#lx"), global_offset);
+         return print_symbol_for_build_attribute (file, global_offset, is_open_attr);
        }
     }
 
-  printf ("\n");
-  return TRUE;
+  if (pnote->descsz != desc_size)
+    {
+      error (_("    <invalid description size: %lx>\n"), pnote->descsz);
+      printf (_("    <invalid descsz>"));
+      return FALSE;
+    }
+
+  offset = byte_get ((unsigned char *) pnote->descdata, desc_size);
+
+  if (is_open_attr)
+    {
+      printf (_("    Applies from offset %#lx"), offset);
+      global_offset = offset;
+    }
+  else
+    {
+      printf (_("    Applies to func at %#lx"), offset);
+    }
+
+  return print_symbol_for_build_attribute (file, offset, is_open_attr);
 }
 
 static bfd_boolean
@@ -16893,8 +16945,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
 
 static bfd_boolean
 process_note (Elf_Internal_Note *  pnote,
-             FILE *               file,
-             Elf_Internal_Shdr *  section)
+             FILE *               file)
 {
   const char * name = pnote->namesz ? pnote->namedata : "(NONE)";
   const char * nt;
@@ -16962,7 +17013,7 @@ process_note (Elf_Internal_Note *  pnote,
     return print_core_note (pnote);
   else if (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN
           || pnote->type == NT_GNU_BUILD_ATTRIBUTE_FUNC)
-    return print_gnu_build_attribute_description (pnote, file, section);
+    return print_gnu_build_attribute_description (pnote, file);
 
   if (pnote->descsz)
     {
@@ -17116,7 +17167,7 @@ process_notes_at (FILE *              file,
          inote.namedata = temp;
        }
 
-      if (! process_note (& inote, file, section))
+      if (! process_note (& inote, file))
        res = FALSE;
 
       if (temp != NULL)
index 0c0974c0bc94961c6d9709296f42c1ce546ffda5..8deb7f6c93da3e7d6cfdae40bb0b3870be6d6bdc 100644 (file)
@@ -13,5 +13,5 @@
 [      ]+\*<ABI>0x0[   ]+0x00000000[   ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[  ]+Applies from offset 0x100
 [      ]+\$<version>1[         ]+0x00000004[   ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[  ]+Applies from offset 0x10. \(file: note2.s\)
 [      ]+!<stack prot>false[   ]+0x00000000[   ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[  ]+Applies from offset 0x10.
-[      ]+\*<PIC>pic[   ]+0x00000000[   ]+NT_GNU_BUILD_ATTRIBUTE_FUNC[  ]+Applies from offset 0x10.
+[      ]+\*<PIC>pic[   ]+0x00000000[   ]+NT_GNU_BUILD_ATTRIBUTE_FUNC[  ]+Applies to func at 0x10. \(func: func1\)
 #...
index 8d9f53a3a0feaea04f65668f2a4d335001b4ef39..da3b08536ad3fd7e673ab09293567bde2543b099 100644 (file)
@@ -39,6 +39,8 @@ note1.s:
 
        .global note2.s
 note2.s:
+       .type func1, STT_FUNC
+func1: 
        .word 0x100
        
        .pushsection .gnu.build.attributes, "0x100000", %note
index 3dd4582011d23a73c128d684c18b0add4ac989d6..85358213a2c7721fcce357e9e684fe8d5b6a51c6 100644 (file)
@@ -13,5 +13,5 @@
 [      ]+\*<ABI>0x0[   ]+0x00000000[   ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[  ]+Applies from offset 0x100
 [      ]+\$<version>1[         ]+0x00000008[   ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[  ]+Applies from offset 0x10. \(file: note2.s\)
 [      ]+!<stack prot>false[   ]+0x00000000[   ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[  ]+Applies from offset 0x10.
-[      ]+\*<PIC>pic[   ]+0x00000000[   ]+NT_GNU_BUILD_ATTRIBUTE_FUNC[  ]+Applies from offset 0x10.
+[      ]+\*<PIC>pic[   ]+0x00000000[   ]+NT_GNU_BUILD_ATTRIBUTE_FUNC[  ]+Applies to func at 0x10. \(func: func1\)
 #...
index 51317c84fc498eb2d3ef4a264aaa77ebd5c373a4..fcd61d033706d2de686b8185cbeb334cb6d6233e 100644 (file)
@@ -39,8 +39,11 @@ note1.s:
 
        .global note2.s
 note2.s:
+       .global func1
+       .type func1, STT_FUNC
+func1: 
        .word 0x100
-       
+
        .pushsection .gnu.build.attributes, "0x100000", %note
        .dc.l 4         
        .dc.l 8