diff options
-rw-r--r-- | binutils/ChangeLog | 13 | ||||
-rw-r--r-- | binutils/readelf.c | 221 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/note-2-32.d | 2 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/note-2-32.s | 2 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/note-2-64.d | 2 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/note-2-64.s | 5 |
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 |