summaryrefslogtreecommitdiffstats
path: root/src/nm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nm.c')
-rw-r--r--src/nm.c92
1 files changed, 64 insertions, 28 deletions
diff --git a/src/nm.c b/src/nm.c
index 7f6cf2a2..a6334743 100644
--- a/src/nm.c
+++ b/src/nm.c
@@ -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. */