aboutsummaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
Diffstat (limited to 'binutils')
-rw-r--r--binutils/ChangeLog13
-rw-r--r--binutils/readelf.c221
-rw-r--r--binutils/testsuite/binutils-all/note-2-32.d2
-rw-r--r--binutils/testsuite/binutils-all/note-2-32.s2
-rw-r--r--binutils/testsuite/binutils-all/note-2-64.d2
-rw-r--r--binutils/testsuite/binutils-all/note-2-64.s5
6 files changed, 157 insertions, 88 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 71dd6e2..f9fb746 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -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>
diff --git a/binutils/readelf.c b/binutils/readelf.c
index a10ba19..34781ae 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -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)
diff --git a/binutils/testsuite/binutils-all/note-2-32.d b/binutils/testsuite/binutils-all/note-2-32.d
index 0c0974c..8deb7f6 100644
--- a/binutils/testsuite/binutils-all/note-2-32.d
+++ b/binutils/testsuite/binutils-all/note-2-32.d
@@ -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\)
#...
diff --git a/binutils/testsuite/binutils-all/note-2-32.s b/binutils/testsuite/binutils-all/note-2-32.s
index 8d9f53a..da3b085 100644
--- a/binutils/testsuite/binutils-all/note-2-32.s
+++ b/binutils/testsuite/binutils-all/note-2-32.s
@@ -39,6 +39,8 @@ note1.s:
.global note2.s
note2.s:
+ .type func1, STT_FUNC
+func1:
.word 0x100
.pushsection .gnu.build.attributes, "0x100000", %note
diff --git a/binutils/testsuite/binutils-all/note-2-64.d b/binutils/testsuite/binutils-all/note-2-64.d
index 3dd4582..8535821 100644
--- a/binutils/testsuite/binutils-all/note-2-64.d
+++ b/binutils/testsuite/binutils-all/note-2-64.d
@@ -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\)
#...
diff --git a/binutils/testsuite/binutils-all/note-2-64.s b/binutils/testsuite/binutils-all/note-2-64.s
index 51317c8..fcd61d0 100644
--- a/binutils/testsuite/binutils-all/note-2-64.s
+++ b/binutils/testsuite/binutils-all/note-2-64.s
@@ -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