diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 55 | ||||
-rw-r--r-- | src/elflint.c | 19 | ||||
-rw-r--r-- | src/nm.c | 92 | ||||
-rw-r--r-- | src/objdump.c | 3 | ||||
-rw-r--r-- | src/readelf.c | 9 | ||||
-rw-r--r-- | src/size.c | 7 |
6 files changed, 152 insertions, 33 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 6af977ed..512d7b54 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,58 @@ +2020-06-07 Mark Wielaard <[email protected]> + + * nm.c (sort_by_name_strtab): Replace by... + (sort_by_name_elf): New static Elf pointer and ... + (sort_by_name_ndx): New static size_t index. + (sort_by_name): Use elf_strptr to get symbol string. + (show_symbols): Set sort_by_name_elf and sort_by_name_ndx. + +2020-06-06 Mark Wielaard <[email protected]> + + * nm.c (show_symbols_sysv): Skip no name and STT_FILE symbols. + When not printing address and size pad strings. Strip "GNU_" + prefix from binding name. + (class_type_char): Use 'V' for weak symbols, 'C' for common + symbols and 'T' for weak functions. + (show_symbols_posix): Skip STT_FILE symbols. Don't print value and + size when undefined. + +2020-06-04 Mark Wielaard <[email protected]> + + * elflint.c (check_program_header): Remove PT_GNU_PROPERTY define. + +2020-05-14 Mark Wielaard <[email protected]> + + * size.c (show_bsd): Set printf format based on radix. + +2020-05-09 Mark Wielaard <[email protected]> + + * elflint.c (process_elf_file): Error out if ebl_openbackend fails. + * objdump.c (handle_elf): Likewise. + * nm.c (handle_elf): Likewise. Move full name string construction + forward, so it can be used in the error message. + +2020-04-17 Mark Wielaard <[email protected]> + + * readelf.c (print_debug): Check .gnu.debuglto_ prefix. + +2020-04-16 Mark Wielaard <[email protected]> + + * elflint.c (check_sections): Mask out SHF_EXCLUDE from processor + specific section flags when --gnu is given. + +2020-02-08 Mark Wielaard <[email protected]> + + * elflint.c (check_program_header): Handle PT_GNU_PROPERTY. + +2020-02-07 Mark Wielaard <[email protected]> + + * elflint.c (check_symtab): Check st_info isn't too big. + +2020-01-16 Mark Wielaard <[email protected]> + + * nm.c (show_symbols_sysv): Iterate over all symbols starting + at index zero. + 2019-11-26 Mark Wielaard <[email protected]> * Makefile.am (BUILD_STATIC): Add libraries needed for libdw. diff --git a/src/elflint.c b/src/elflint.c index 684b794e..72584de0 100644 --- a/src/elflint.c +++ b/src/elflint.c @@ -658,6 +658,10 @@ section [%2d] '%s': symbol table cannot have more than one extended index sectio ERROR (gettext ("\ section [%2u] '%s': entry size is does not match ElfXX_Sym\n"), idx, section_name (ebl, idx)); + else if (shdr->sh_info > shdr->sh_size / sh_entsize) + ERROR (gettext ("\ +section [%2u] '%s': number of local entries in 'st_info' larger than table size\n"), + idx, section_name (ebl, idx)); /* Test the zeroth entry. */ GElf_Sym sym_mem; @@ -3917,6 +3921,11 @@ section [%2zu] '%s': size not multiple of entry size\n"), GElf_Xword sh_flags = shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS; if (sh_flags & SHF_MASKPROC) { + /* Strictly speaking SHF_EXCLUDE is a processor specific + section flag, but it is used generically in the GNU + toolchain. */ + if (gnuld) + sh_flags &= ~(GElf_Xword) SHF_EXCLUDE; if (!ebl_machine_section_flag_check (ebl, sh_flags & SHF_MASKPROC)) ERROR (gettext ("section [%2zu] '%s'" @@ -4485,6 +4494,7 @@ only executables, shared objects, and core files can have program headers\n")); if (phdr->p_type >= PT_NUM && phdr->p_type != PT_GNU_EH_FRAME && phdr->p_type != PT_GNU_STACK && phdr->p_type != PT_GNU_RELRO + && phdr->p_type != PT_GNU_PROPERTY /* Check for a known machine-specific type. */ && ebl_segment_type_name (ebl, phdr->p_type, NULL, 0) == NULL) ERROR (gettext ("\ @@ -4761,7 +4771,14 @@ process_elf_file (Elf *elf, const char *prefix, const char *suffix, ebl = ebl_openbackend (elf); /* If there is no appropriate backend library we cannot test architecture and OS specific features. Any encountered extension - is an error. */ + is an error. Often we'll get a "dummy" ebl, except if something + really bad happen, like a totally corrupted ELF file or out of + memory situation. */ + if (ebl == NULL) + { + ERROR (gettext ("cannot create backend for ELF file\n")); + return; + } /* Go straight by the gABI, check all the parts in turn. */ check_elf_header (ebl, ehdr, size); @@ -1,5 +1,5 @@ /* Print symbol information from ELF file in human-readable form. - Copyright (C) 2000-2008, 2009, 2011, 2012, 2014, 2015 Red Hat, Inc. + Copyright (C) 2000-2008, 2009, 2011, 2012, 2014, 2015, 2020 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper <[email protected]>, 2000. @@ -787,7 +787,7 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx, const char *fullname, #endif /* Iterate over all symbols. */ - for (cnt = 1; cnt < nsyms; ++cnt) + for (cnt = 0; cnt < nsyms; ++cnt) { /* In this format SECTION entries are not printed. */ if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_SECTION) @@ -797,6 +797,16 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx, const char *fullname, const char *symstr = sym_name (ebl->elf, strndx, syms[cnt].sym.st_name, symstrbuf, sizeof symstrbuf); + /* Printing entries with a zero-length name makes the output + not very well parseable. Since these entries don't carry + much information we leave them out. */ + if (symstr[0] == '\0') + continue; + + /* We do not print the entries for files. */ + if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_FILE) + continue; + #ifdef USE_DEMANGLE /* Demangle if necessary. Require GNU v3 ABI by the "_Z" prefix. */ if (demangle && symstr[0] == '_' && symstr[1] == 'Z') @@ -825,7 +835,10 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx, const char *fullname, /* Covert the address. */ if (syms[cnt].sym.st_shndx == SHN_UNDEF) - addressbuf[0] = sizebuf[0] = '\0'; + { + sprintf (addressbuf, "%*c", digits, ' '); + sprintf (sizebuf, "%*c", digits, ' '); + } else { snprintf (addressbuf, sizeof (addressbuf), @@ -841,11 +854,14 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx, const char *fullname, } /* Print the actual string. */ + const char *bind; + bind = ebl_symbol_binding_name (ebl, + GELF_ST_BIND (syms[cnt].sym.st_info), + symbindbuf, sizeof (symbindbuf)); + if (bind != NULL && strncmp (bind, "GNU_", strlen ("GNU_")) == 0) + bind += strlen ("GNU_"); printf ("%-*s|%s|%-6s|%-8s|%s|%*s|%s\n", - longest_name, symstr, addressbuf, - ebl_symbol_binding_name (ebl, - GELF_ST_BIND (syms[cnt].sym.st_info), - symbindbuf, sizeof (symbindbuf)), + longest_name, symstr, addressbuf, bind, ebl_symbol_type_name (ebl, GELF_ST_TYPE (syms[cnt].sym.st_info), symtypebuf, sizeof (symtypebuf)), sizebuf, longest_where, syms[cnt].where, @@ -884,6 +900,10 @@ class_type_char (Elf *elf, const GElf_Ehdr *ehdr, GElf_Sym *sym) if (ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX && GELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE) result = 'u'; + else if (GELF_ST_BIND (sym->st_info) == STB_WEAK) + result = 'V'; + else if (sym->st_shndx == SHN_COMMON) + result = 'C'; else { GElf_Shdr shdr_mem; @@ -898,6 +918,11 @@ class_type_char (Elf *elf, const GElf_Ehdr *ehdr, GElf_Sym *sym) } } } + else if (result == 'T') + { + if (GELF_ST_BIND (sym->st_info) == STB_WEAK) + result = 'W'; + } return local_p ? tolower (result) : result; } @@ -1063,6 +1088,10 @@ show_symbols_posix (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx, if (symstr[0] == '\0') continue; + /* We do not print the entries for files. */ + if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_FILE) + continue; + #ifdef USE_DEMANGLE /* Demangle if necessary. Require GNU v3 ABI by the "_Z" prefix. */ if (demangle && symstr[0] == '_' && symstr[1] == 'Z') @@ -1084,21 +1113,23 @@ show_symbols_posix (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx, putchar_unlocked (' '); } - printf ((radix == radix_hex - ? "%s %c%s %0*" PRIx64 " %0*" PRIx64 "\n" - : (radix == radix_decimal - ? "%s %c%s %*" PRId64 " %*" PRId64 "\n" - : "%s %c%s %0*" PRIo64 " %0*" PRIo64 "\n")), - symstr, + printf ("%s %c%s", symstr, class_type_char (elf, ehdr, &syms[cnt].sym), mark_special ? (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS ? "@" : (GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK ? "*" : " ")) - : "", - digits, syms[cnt].sym.st_value, - digits, syms[cnt].sym.st_size); + : ""); + if (syms[cnt].sym.st_shndx != SHN_UNDEF) + printf ((radix == radix_hex + ? " %0*" PRIx64 " %0*" PRIx64 + : (radix == radix_decimal + ? " %*" PRId64 " %*" PRId64 + : " %0*" PRIo64 " %0*" PRIo64)), + digits, syms[cnt].sym.st_value, + digits, syms[cnt].sym.st_size); + putchar ('\n'); } #ifdef USE_DEMANGLE @@ -1122,7 +1153,8 @@ sort_by_address (const void *p1, const void *p2) return reverse_sort ? -result : result; } -static Elf_Data *sort_by_name_strtab; +static Elf *sort_by_name_elf; +static size_t sort_by_name_ndx; static int sort_by_name (const void *p1, const void *p2) @@ -1130,8 +1162,10 @@ sort_by_name (const void *p1, const void *p2) GElf_SymX *s1 = (GElf_SymX *) p1; GElf_SymX *s2 = (GElf_SymX *) p2; - const char *n1 = sort_by_name_strtab->d_buf + s1->sym.st_name; - const char *n2 = sort_by_name_strtab->d_buf + s2->sym.st_name; + const char *n1 = elf_strptr (sort_by_name_elf, sort_by_name_ndx, + s1->sym.st_name) ?: ""; + const char *n2 = elf_strptr (sort_by_name_elf, sort_by_name_ndx, + s2->sym.st_name) ?: ""; int result = strcmp (n1, n2); @@ -1444,8 +1478,8 @@ show_symbols (int fd, Ebl *ebl, GElf_Ehdr *ehdr, /* Sort the entries according to the users wishes. */ if (sort == sort_name) { - sort_by_name_strtab = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link), - NULL); + sort_by_name_elf = ebl->elf; + sort_by_name_ndx = shdr->sh_link; qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_name); } else if (sort == sort_numeric) @@ -1510,8 +1544,17 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, GElf_Ehdr *ehdr; Ebl *ebl; + /* Create the full name of the file. */ + if (prefix != NULL) + cp = mempcpy (cp, prefix, prefix_len); + cp = mempcpy (cp, fname, fname_len); + if (suffix != NULL) + memcpy (cp - 1, suffix, suffix_len + 1); + /* Get the backend for this object file type. */ ebl = ebl_openbackend (elf); + if (ebl == NULL) + INTERNAL_ERROR (fullname); /* We need the ELF header in a few places. */ ehdr = gelf_getehdr (elf, &ehdr_mem); @@ -1530,13 +1573,6 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, goto out; } - /* Create the full name of the file. */ - if (prefix != NULL) - cp = mempcpy (cp, prefix, prefix_len); - cp = mempcpy (cp, fname, fname_len); - if (suffix != NULL) - memcpy (cp - 1, suffix, suffix_len + 1); - /* Find the symbol table. XXX Can there be more than one? Do we print all? Currently we do. */ diff --git a/src/objdump.c b/src/objdump.c index a619674f..82d7bcf6 100644 --- a/src/objdump.c +++ b/src/objdump.c @@ -755,6 +755,9 @@ handle_elf (Elf *elf, const char *prefix, const char *fname, /* Get the backend for this object file type. */ Ebl *ebl = ebl_openbackend (elf); + if (ebl == NULL) + error (EXIT_FAILURE, 0, + gettext ("cannot create backend for elf file")); printf ("%s: elf%d-%s\n\n", fname, gelf_getclass (elf) == ELFCLASS32 ? 32 : 64, diff --git a/src/readelf.c b/src/readelf.c index cbb519d1..685d0b17 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -11253,7 +11253,8 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr) if (strcmp (name, ".debug_info") == 0 || strcmp (name, ".debug_info.dwo") == 0 || strcmp (name, ".zdebug_info") == 0 - || strcmp (name, ".zdebug_info.dwo") == 0) + || strcmp (name, ".zdebug_info.dwo") == 0 + || strcmp (name, ".gnu.debuglto_.debug_info") == 0) { print_debug_info_section (dwflmod, ebl, ehdr, scn, shdr, dbg); @@ -11339,7 +11340,11 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr) dbglen - 1) == 0 && (scnlen == dbglen + 1 || (scnlen == dbglen + 5 - && strstr (name, ".dwo") == name + dbglen + 1)))) + && strstr (name, ".dwo") == name + dbglen + 1))) + || (scnlen > 14 /* .gnu.debuglto_ prefix. */ + && strncmp (name, ".gnu.debuglto_", 14) == 0 + && strcmp (&name[14], debug_sections[n].name) == 0) +) { if ((print_debug_sections | implicit_debug_sections) & debug_sections[n].bitmask) @@ -545,8 +545,11 @@ show_bsd (Elf *elf, const char *prefix, const char *fname, datasize += shdr->sh_size; } - printf ("%*" PRId64 " %*" PRId64 " %*" PRId64 " %*" PRId64 " %*" - PRIx64 " %s", + printf (radix == radix_decimal + ? "%*" PRId64 " %*" PRId64 " %*" PRId64 " %*" PRId64 " %*" PRIx64 " %s" + : radix == radix_hex + ? "%#*" PRIx64 " %#*" PRIx64 " %#*" PRIx64 " %*" PRId64 " %*" PRIx64 " %s" + : "%#*" PRIo64 " %#*" PRIo64 " %#*" PRIo64 " %*" PRId64 " %*" PRIx64 " %s", ddigits - 2, textsize, ddigits - 2, datasize, ddigits - 2, bsssize, |