From c799a79d66d09c442d85467986c2e8873f09297c Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 14 Mar 2017 12:57:09 +0000 Subject: 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. --- binutils/ChangeLog | 13 ++ binutils/readelf.c | 221 +++++++++++++++++----------- binutils/testsuite/binutils-all/note-2-32.d | 2 +- binutils/testsuite/binutils-all/note-2-32.s | 2 + binutils/testsuite/binutils-all/note-2-64.d | 2 +- binutils/testsuite/binutils-all/note-2-64.s | 5 +- 6 files changed, 157 insertions(+), 88 deletions(-) (limited to 'binutils') 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 + + * 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 Taeung Song 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 (_(" \n"), pnote->descsz); - printf (_(" ")); - 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 : _(")")); + 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 (_(" ()")); + 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 (_(" \n"), pnote->descsz); + printf (_(" ")); + 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 @@ [ ]+\*0x0[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x100 [ ]+\$1[ ]+0x00000004[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x10. \(file: note2.s\) [ ]+!false[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x10. -[ ]+\*pic[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_FUNC[ ]+Applies from offset 0x10. +[ ]+\*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 @@ [ ]+\*0x0[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x100 [ ]+\$1[ ]+0x00000008[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x10. \(file: note2.s\) [ ]+!false[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x10. -[ ]+\*pic[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_FUNC[ ]+Applies from offset 0x10. +[ ]+\*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 -- cgit v1.1