aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2020-06-07 01:02:52 +0200
committerMark Wielaard <mark@klomp.org>2020-06-07 01:02:52 +0200
commit76ff94dce7ee8dd88c502bc0bbfc8dea15efea5b (patch)
treefe02b805e3a9e7b65e4fb66ce4932b0235fb7cdf /src
parent39f22a7687dd190a3e6d26a728ff2ed5129aba5a (diff)
downloadelfutils-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/ChangeLog10
-rw-r--r--src/nm.c59
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.
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