diff options
author | Mark Wielaard <mark@klomp.org> | 2020-06-07 01:02:52 +0200 |
---|---|---|
committer | Mark Wielaard <mark@klomp.org> | 2020-06-07 01:02:52 +0200 |
commit | 76ff94dce7ee8dd88c502bc0bbfc8dea15efea5b (patch) | |
tree | fe02b805e3a9e7b65e4fb66ce4932b0235fb7cdf /src | |
parent | 39f22a7687dd190a3e6d26a728ff2ed5129aba5a (diff) | |
download | elfutils-76ff94dce7ee8dd88c502bc0bbfc8dea15efea5b.tar.gz |
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 <mark@klomp.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 10 | ||||
-rw-r--r-- | src/nm.c | 59 |
2 files changed, 55 insertions, 14 deletions
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 <mark@klomp.org> + + * 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 <mark@klomp.org> * elflint.c (check_program_header): Remove PT_GNU_PROPERTY define. @@ -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 |