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>
This commit is contained in:
Mark Wielaard
2020-06-07 01:02:52 +02:00
parent 39f22a7687
commit 76ff94dce7
7 changed files with 232 additions and 15 deletions
+10
View File
@@ -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.
+45 -14
View File
@@ -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
+9
View File
@@ -1,3 +1,12 @@
2020-06-06 Mark Wielaard <mark@klomp.org>
* testfilesyms32.bz2: New test file.
* testfilesyms64.bz2: Likewise.
* run-nm-syms.sh: New test.
* Makefile.am (TESTS): Add run-nm-syms.sh.
(EXTRA_DIST): run-nm-syms.sh, testfilesyms32.bz2 and
testfilesyms64.bz2
2020-05-08 Mark Wielaard <mark@klomp.org>
* elfputzdata.c (main): Explicitly check orig_buf is not NULL
+2 -1
View File
@@ -110,7 +110,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \
run-ranlib-test2.sh run-ranlib-test3.sh run-ranlib-test4.sh \
run-addrscopes.sh run-strings-test.sh run-funcscopes.sh \
run-find-prologues.sh run-allregs.sh run-addrcfi.sh \
run-dwarfcfi.sh \
run-dwarfcfi.sh run-nm-syms.sh \
run-nm-self.sh run-readelf-self.sh run-readelf-info-plus.sh \
run-readelf-compressed.sh \
run-readelf-const-values.sh \
@@ -243,6 +243,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
run-elflint-self.sh run-ranlib-test.sh run-ranlib-test2.sh \
run-ranlib-test3.sh run-ranlib-test4.sh \
run-addrscopes.sh run-strings-test.sh run-funcscopes.sh \
run-nm-syms.sh testfilesyms32.bz2 testfilesyms64.bz2 \
run-nm-self.sh run-readelf-self.sh run-readelf-info-plus.sh \
run-readelf-compressed.sh \
run-readelf-const-values.sh testfile-const-values.debug.bz2 \
+166
View File
@@ -0,0 +1,166 @@
#! /bin/sh
# Copyright (C) 2020 Red Hat, Inc.
# This file is part of elfutils.
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# elfutils is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
. $srcdir/test-subr.sh
# void *SYM1;
# void *SYM2 = 0;
# extern void *SYM3;
# static void *SYM4;
#
# void *SYM6 = &SYM3;
# static void *SYM7 = &SYM3;
#
# void *SYM8 __attribute__((__weak__));
#
# void FUN1 (void) { }
# static void FUN2 (void) { }
# extern void FUN3 (void);
#
# void *FREF = FUN3;
#
# void __attribute__((__weak__)) FUN4 (void) { };
#
# int NUM0 = 0; __asm__(".type NUM0,%gnu_unique_object");
# int __thread NUM1 = 1;
#
# gcc -m64 -c syms.c -o testfilesyms64
# gcc -m32 -c syms.c -o testfilesyms32
testfiles testfilesyms32 testfilesyms64
testrun_compare ${abs_top_builddir}/src/nm --format=bsd testfilesyms32 <<\EOF
00000008 D FREF
00000000 T FUN1
00000010 t FUN2
U FUN3
00000020 W FUN4
00000008 u NUM0
00000000 D NUM1
00000004 C SYM1
00000000 B SYM2
U SYM3
0000000c b SYM4
00000000 D SYM6
00000004 d SYM7
00000004 V SYM8
U _GLOBAL_OFFSET_TABLE_
00000000 T __x86.get_pc_thunk.ax
EOF
testrun_compare ${abs_top_builddir}/src/nm --format=posix testfilesyms32 <<\EOF
FREF D 00000008 00000004
FUN1 T 00000000 00000010
FUN2 t 00000010 00000010
FUN3 U
FUN4 W 00000020 00000010
NUM0 u 00000008 00000004
NUM1 D 00000000 00000004
SYM1 C 00000004 00000004
SYM2 B 00000000 00000004
SYM3 U
SYM4 b 0000000c 00000004
SYM6 D 00000000 00000004
SYM7 d 00000004 00000004
SYM8 V 00000004 00000004
_GLOBAL_OFFSET_TABLE_ U
__x86.get_pc_thunk.ax T 00000000 00000000
EOF
testrun_compare ${abs_top_builddir}/src/nm --format=sysv testfilesyms32 <<\EOF
Symbols from testfilesyms32:
Name Value Class Type Size Line Section
FREF |00000008|GLOBAL|OBJECT |00000004| |.data.rel
FUN1 |00000000|GLOBAL|FUNC |00000010| |.text
FUN2 |00000010|LOCAL |FUNC |00000010| |.text
FUN3 | |GLOBAL|NOTYPE | | |UNDEF
FUN4 |00000020|WEAK |FUNC |00000010| |.text
NUM0 |00000008|UNIQUE|OBJECT |00000004| |.bss
NUM1 |00000000|GLOBAL|TLS |00000004| |.tdata
SYM1 |00000004|GLOBAL|OBJECT |00000004| |COMMON
SYM2 |00000000|GLOBAL|OBJECT |00000004| |.bss
SYM3 | |GLOBAL|NOTYPE | | |UNDEF
SYM4 |0000000c|LOCAL |OBJECT |00000004| |.bss
SYM6 |00000000|GLOBAL|OBJECT |00000004| |.data.rel
SYM7 |00000004|LOCAL |OBJECT |00000004| |.data.rel
SYM8 |00000004|WEAK |OBJECT |00000004| |.bss
_GLOBAL_OFFSET_TABLE_| |GLOBAL|NOTYPE | | |UNDEF
__x86.get_pc_thunk.ax|00000000|GLOBAL|FUNC |00000000| |.text.__x86.get_pc_thunk.ax
EOF
testrun_compare ${abs_top_builddir}/src/nm --format=bsd testfilesyms64 <<\EOF
0000000000000010 D FREF
0000000000000000 T FUN1
0000000000000007 t FUN2
U FUN3
000000000000000e W FUN4
0000000000000010 u NUM0
0000000000000000 D NUM1
0000000000000008 C SYM1
0000000000000000 B SYM2
U SYM3
0000000000000018 b SYM4
0000000000000000 D SYM6
0000000000000008 d SYM7
0000000000000008 V SYM8
EOF
testrun_compare ${abs_top_builddir}/src/nm --format=posix testfilesyms64 <<\EOF
FREF D 0000000000000010 0000000000000008
FUN1 T 0000000000000000 0000000000000007
FUN2 t 0000000000000007 0000000000000007
FUN3 U
FUN4 W 000000000000000e 0000000000000007
NUM0 u 0000000000000010 0000000000000004
NUM1 D 0000000000000000 0000000000000004
SYM1 C 0000000000000008 0000000000000008
SYM2 B 0000000000000000 0000000000000008
SYM3 U
SYM4 b 0000000000000018 0000000000000008
SYM6 D 0000000000000000 0000000000000008
SYM7 d 0000000000000008 0000000000000008
SYM8 V 0000000000000008 0000000000000008
EOF
testrun_compare ${abs_top_builddir}/src/nm --format=sysv testfilesyms64 <<\EOF
Symbols from testfilesyms64:
Name Value Class Type Size Line Section
FREF |0000000000000010|GLOBAL|OBJECT |0000000000000008| |.data.rel
FUN1 |0000000000000000|GLOBAL|FUNC |0000000000000007| |.text
FUN2 |0000000000000007|LOCAL |FUNC |0000000000000007| |.text
FUN3 | |GLOBAL|NOTYPE | | |UNDEF
FUN4 |000000000000000e|WEAK |FUNC |0000000000000007| |.text
NUM0 |0000000000000010|UNIQUE|OBJECT |0000000000000004| |.bss
NUM1 |0000000000000000|GLOBAL|TLS |0000000000000004| |.tdata
SYM1 |0000000000000008|GLOBAL|OBJECT |0000000000000008| |COMMON
SYM2 |0000000000000000|GLOBAL|OBJECT |0000000000000008| |.bss
SYM3 | |GLOBAL|NOTYPE | | |UNDEF
SYM4 |0000000000000018|LOCAL |OBJECT |0000000000000008| |.bss
SYM6 |0000000000000000|GLOBAL|OBJECT |0000000000000008| |.data.rel
SYM7 |0000000000000008|LOCAL |OBJECT |0000000000000008| |.data.rel
SYM8 |0000000000000008|WEAK |OBJECT |0000000000000008| |.bss
EOF
exit 0
Binary file not shown.
Binary file not shown.