Try harder to find the correct symbol to associate with OPEN GNU BUILD notes.
* 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.
This commit is contained in:
parent
0efcde634d
commit
c799a79d66
6 changed files with 167 additions and 98 deletions
|
@ -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>
|
2017-03-13 Alan Modra <amodra@gmail.com>
|
||||||
Taeung Song <treeze.taeung@gmail.com>
|
Taeung Song <treeze.taeung@gmail.com>
|
||||||
|
|
||||||
|
|
|
@ -16598,24 +16598,145 @@ print_ia64_vms_note (Elf_Internal_Note * pnote)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Print the name of the symbol associated with a build attribute
|
||||||
|
that is attached to address OFFSET. */
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
print_symbol_for_build_attribute (FILE * file,
|
||||||
|
unsigned long offset,
|
||||||
|
bfd_boolean is_open_attr)
|
||||||
|
{
|
||||||
|
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 (saved_file == NULL || file != saved_file)
|
||||||
|
{
|
||||||
|
Elf_Internal_Shdr * symsec;
|
||||||
|
|
||||||
|
/* Load the symbol and string sections. */
|
||||||
|
for (symsec = section_headers;
|
||||||
|
symsec < section_headers + elf_header.e_shnum;
|
||||||
|
symsec ++)
|
||||||
|
{
|
||||||
|
if (symsec->sh_type == SHT_SYMTAB)
|
||||||
|
{
|
||||||
|
symtab = GET_ELF_SYMBOLS (file, symsec, & nsyms);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (symtab == NULL || strtab == NULL)
|
||||||
|
{
|
||||||
|
printf ("\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 (strtab[sym->st_name] == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
case STT_OBJECT:
|
||||||
|
saved_sym = sym;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case STT_FUNC:
|
||||||
|
/* Ignore function symbols. */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ELF_ST_BIND (sym->st_info))
|
||||||
|
{
|
||||||
|
case STB_GLOBAL:
|
||||||
|
if (saved_sym == NULL
|
||||||
|
|| ELF_ST_TYPE (saved_sym->st_info) != STT_OBJECT)
|
||||||
|
saved_sym = sym;
|
||||||
|
break;
|
||||||
|
|
||||||
|
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
|
static bfd_boolean
|
||||||
print_gnu_build_attribute_description (Elf_Internal_Note * pnote,
|
print_gnu_build_attribute_description (Elf_Internal_Note * pnote,
|
||||||
FILE * file,
|
FILE * file)
|
||||||
Elf_Internal_Shdr * section ATTRIBUTE_UNUSED)
|
|
||||||
{
|
{
|
||||||
static unsigned long global_offset = 0;
|
static unsigned long global_offset = 0;
|
||||||
unsigned long i;
|
unsigned long offset;
|
||||||
unsigned long strtab_size = 0;
|
unsigned int desc_size = is_32bit_elf ? 4 : 8;
|
||||||
char * strtab = NULL;
|
bfd_boolean is_open_attr = pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN;
|
||||||
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)
|
if (pnote->descsz == 0)
|
||||||
{
|
{
|
||||||
printf (_(" Applies from offset %#lx\n"), global_offset);
|
if (is_open_attr)
|
||||||
return TRUE;
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pnote->descsz != desc_size)
|
if (pnote->descsz != desc_size)
|
||||||
|
@ -16625,88 +16746,19 @@ print_gnu_build_attribute_description (Elf_Internal_Note * pnote,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load the symbols. */
|
offset = byte_get ((unsigned char *) pnote->descdata, desc_size);
|
||||||
for (symsec = section_headers;
|
|
||||||
symsec < section_headers + elf_header.e_shnum;
|
if (is_open_attr)
|
||||||
symsec ++)
|
|
||||||
{
|
{
|
||||||
if (symsec->sh_type == SHT_SYMTAB)
|
printf (_(" Applies from offset %#lx"), offset);
|
||||||
{
|
global_offset = offset;
|
||||||
symtab = GET_ELF_SYMBOLS (file, symsec, & nsyms);
|
}
|
||||||
|
else
|
||||||
if (symsec->sh_link < elf_header.e_shnum)
|
{
|
||||||
{
|
printf (_(" Applies to func at %#lx"), offset);
|
||||||
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"));
|
|
||||||
strtab_size = strtab != NULL ? strtab_sec->sh_size : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf (_(" Applies from offset"));
|
return print_symbol_for_build_attribute (file, offset, is_open_attr);
|
||||||
|
|
||||||
for (i = 0; i < pnote->descsz; i += desc_size)
|
|
||||||
{
|
|
||||||
Elf_Internal_Sym * saved_sym = NULL;
|
|
||||||
Elf_Internal_Sym * sym;
|
|
||||||
unsigned long offset;
|
|
||||||
|
|
||||||
offset = byte_get ((unsigned char *) pnote->descdata + i, desc_size);
|
|
||||||
|
|
||||||
if (i + desc_size == pnote->descsz)
|
|
||||||
printf (_(" %#lx"), offset);
|
|
||||||
else
|
|
||||||
printf (_(" %#lx, "), offset);
|
|
||||||
|
|
||||||
if (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN)
|
|
||||||
global_offset = offset;
|
|
||||||
|
|
||||||
if (symtab == NULL || strtab == NULL)
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (strtab[sym->st_name] == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
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);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sym == symtab + nsyms)
|
|
||||||
{
|
|
||||||
if (saved_sym)
|
|
||||||
printf (_(" (file: %s)"), strtab + saved_sym->st_name);
|
|
||||||
else
|
|
||||||
printf (_(" (<symbol name unknown>)"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printf ("\n");
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
|
@ -16893,8 +16945,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
|
||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
process_note (Elf_Internal_Note * pnote,
|
process_note (Elf_Internal_Note * pnote,
|
||||||
FILE * file,
|
FILE * file)
|
||||||
Elf_Internal_Shdr * section)
|
|
||||||
{
|
{
|
||||||
const char * name = pnote->namesz ? pnote->namedata : "(NONE)";
|
const char * name = pnote->namesz ? pnote->namedata : "(NONE)";
|
||||||
const char * nt;
|
const char * nt;
|
||||||
|
@ -16962,7 +17013,7 @@ process_note (Elf_Internal_Note * pnote,
|
||||||
return print_core_note (pnote);
|
return print_core_note (pnote);
|
||||||
else if (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN
|
else if (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN
|
||||||
|| pnote->type == NT_GNU_BUILD_ATTRIBUTE_FUNC)
|
|| 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)
|
if (pnote->descsz)
|
||||||
{
|
{
|
||||||
|
@ -17116,7 +17167,7 @@ process_notes_at (FILE * file,
|
||||||
inote.namedata = temp;
|
inote.namedata = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! process_note (& inote, file, section))
|
if (! process_note (& inote, file))
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
|
|
||||||
if (temp != NULL)
|
if (temp != NULL)
|
||||||
|
|
|
@ -13,5 +13,5 @@
|
||||||
[ ]+\*<ABI>0x0[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x100
|
[ ]+\*<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\)
|
[ ]+\$<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.
|
[ ]+!<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\)
|
||||||
#...
|
#...
|
||||||
|
|
|
@ -39,6 +39,8 @@ note1.s:
|
||||||
|
|
||||||
.global note2.s
|
.global note2.s
|
||||||
note2.s:
|
note2.s:
|
||||||
|
.type func1, STT_FUNC
|
||||||
|
func1:
|
||||||
.word 0x100
|
.word 0x100
|
||||||
|
|
||||||
.pushsection .gnu.build.attributes, "0x100000", %note
|
.pushsection .gnu.build.attributes, "0x100000", %note
|
||||||
|
|
|
@ -13,5 +13,5 @@
|
||||||
[ ]+\*<ABI>0x0[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x100
|
[ ]+\*<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\)
|
[ ]+\$<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.
|
[ ]+!<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\)
|
||||||
#...
|
#...
|
||||||
|
|
|
@ -39,8 +39,11 @@ note1.s:
|
||||||
|
|
||||||
.global note2.s
|
.global note2.s
|
||||||
note2.s:
|
note2.s:
|
||||||
|
.global func1
|
||||||
|
.type func1, STT_FUNC
|
||||||
|
func1:
|
||||||
.word 0x100
|
.word 0x100
|
||||||
|
|
||||||
.pushsection .gnu.build.attributes, "0x100000", %note
|
.pushsection .gnu.build.attributes, "0x100000", %note
|
||||||
.dc.l 4
|
.dc.l 4
|
||||||
.dc.l 8
|
.dc.l 8
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue