From 76ff94dce7ee8dd88c502bc0bbfc8dea15efea5b Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sun, 7 Jun 2020 01:02:52 +0200 Subject: nm: Explicitly print weak 'V' or 'T' and common 'C' symbols. Mimic binutils nm for bsd and posix formats which uses 'V' for weak symbols, 'C' for common symbols and 'T' for weak functions. Also fix some formatting issues. Don't print undefined addresses as zeros, but make sure there is enough padding instead. Just print UNIQUE for GNU_UNIQUE to make it fit 6 chars, like other binding names in sysv format. https://sourceware.org/bugzilla/show_bug.cgi?id=25227 Signed-off-by: Mark Wielaard --- src/ChangeLog | 10 ++++++++++ src/nm.c | 59 +++++++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 55 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index c8e6b4e8..4684d332 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,13 @@ +2020-06-06 Mark Wielaard + + * 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 * elflint.c (check_program_header): Remove PT_GNU_PROPERTY define. diff --git a/src/nm.c b/src/nm.c index f6ca3b0a..8302a98c 100644 --- a/src/nm.c +++ b/src/nm.c @@ -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 -- cgit v1.2.3