[PATCH] nm: Explicitly print weak 'V' or 'T' and common 'C' symbols.

Mark Wielaard mark@klomp.org
Sat Jun 6 23:12:04 GMT 2020


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>
---
 src/ChangeLog            |  10 +++
 src/nm.c                 |  59 ++++++++++----
 tests/ChangeLog          |   9 +++
 tests/Makefile.am        |   3 +-
 tests/run-nm-syms.sh     | 166 +++++++++++++++++++++++++++++++++++++++
 tests/testfilesyms32.bz2 | Bin 0 -> 771 bytes
 tests/testfilesyms64.bz2 | Bin 0 -> 652 bytes
 7 files changed, 232 insertions(+), 15 deletions(-)
 create mode 100755 tests/run-nm-syms.sh
 create mode 100644 tests/testfilesyms32.bz2
 create mode 100644 tests/testfilesyms64.bz2

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
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 05aab3ef..99f9da9d 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -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
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a7ad07d0..7db7db16 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -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 \
diff --git a/tests/run-nm-syms.sh b/tests/run-nm-syms.sh
new file mode 100755
index 00000000..ddf09222
--- /dev/null
+++ b/tests/run-nm-syms.sh
@@ -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
diff --git a/tests/testfilesyms32.bz2 b/tests/testfilesyms32.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..b3b7812cc2a7e43a744619cdef389e5c783b7307
GIT binary patch
literal 771
zcmV+e1N{6#T4*^jL0KkKSu4X)asUFsfB*mg|L*s1f7O4Fo+khQ-gUxkz(QaEKmbYr
zKmY<nFa*E?l(=XqpwdDxnHqq^H1cWyJws1WdYUxQXfy!z13{q3G{gV^A_5H*{3>WY
zKo3(u4FDP*pa1{>0B8e1(9kp-00000000000000000000NRnu#CPt$W27qYL&}eA%
zgH1HkAO?T|paVe3lR#OpQXp^}qm@$+F%bBi1q_%95lRO$!#txkE<GgqrM+pBxqhfx
z5QnexFV&253$q@7l1)%Cb5c_l=3|p*LsXK0cx{96t|wDXxhRr?12IrQ!~tMZv{O09
zU6%c+80)A;S`0%R0R$6^9@PN&S><84gNOqb2#OXfTd_iD#7kpVd`Iyx0pAD9gB+Y4
zByBDd>V+t3`Ba>$rH@6b)QAH0q=B>>W+70(p@ERhX~gD1fjA0TO9?b>+8b748zjQ&
zAPWp3uLB}*SjvD3ni883L}BFVOrmongh`{6)uu_Ln@y(7CX$;Bw<ao>Dws*Drs`2O
zNYn`%bd)@+%s^0i>Cb3eNNwkLXrB2cgfvbO3>P(Fi5Ocx(U{xq%!VU-Qq#rmSEXyW
z1(_9|>E1L@e%vL7(f3UkOw-iR)uRT>0umN&tMHPB35;!9QjDO~qDanJiV{JZ@)Jt=
zh-^lx=|*~Co|?48-K5kpU=B<!mP&;~oLP{J{M{J^wyDgFM_TWNp}{dse0zm#c3dvV
zE;OY5O<I2WGvGGh*iPK%OZHv^g>ZCrzf8aij4D*wN4jEjed^VoWgy8h4LFA`iqNH#
zL%fNF6&H2<H)RP*zR6G-r0-ICs+g^>w=0{ordcT4>>_Duel(SHc(CB}5`w3v8d9tj
zX_G8krCG7Tq|T_f#wt|;Uz_p;niI`B>dx|m)xZWU7^5=g0-$mdHG>4OL(Rq*EF@R3
zPZF_7T&Sx58Y+nrd234M`Ak#6aNp<R&B~st{V1gUujfI3TK_NjyOJrwgn?cfi;&p-
BR5Jho

literal 0
HcmV?d00001

diff --git a/tests/testfilesyms64.bz2 b/tests/testfilesyms64.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..cdec3817a4a636deb05392f20cf727d2f796c4d5
GIT binary patch
literal 652
zcmV;70(1RBT4*^jL0KkKSsyk6vH${ffA#<W|ITsmf8GD@T5kV;+;D*)U_f912mk^=
zFaW>;65@c^X(lQ>nwm0t1T@i*^)$gfKo3yRG5~K;7)*d<22BDJK&iHxr<zdmBR~d#
zG&IQ20000001Y$)fB*)8p`oFsKn8#SGy_9G01SWt5+p>#f_XHaQ$P(g0B8*~XlNQ}
zGz|uZKpHbp7A25^NT{Yg6n1jAQQ5g`MqDfvz8U~_7<P@`L@P3h&M%7T?Nqg-;fnOA
z0yz~sV(+C6vhjdg5ULS6A~RzIsmO8+We4$*mdiB0uO2~JH&$+xUM)UGCb0SVFmT|G
z65~i95MV$F&g#x!H(N@ZH+j|2A#>Wa(x}ewOP!P3>dhH!t5OSBj>m$T+$ltOph+N`
zNnm<;kOkh%dK#NSylNSdhRFg&6hf4t28)}UhL$u!ZLmwG)Za0rgseb<#sy$HJ-qD?
zLtqDn1u07Hq?Jcf^!yH-8H<P!8{3(Jm^B9hCa8K6BW;CzJ<XFT-oQd@C7VfxALhMt
zO1p+I<i;e8)xSKfk#<Q1<s}qEHjaojTkbiu=o+-8MW}@4#xx4<dh1g&SutxSl}ui(
zDCDe2L5S8<hhrhNW=y2hvFH0XY@H*I4rV;CY2}=QO3rIDM%Z3wx#MhN&M|z@+j1f(
ze)e1?eb!g0e%#C(_)?)sO09bS9eg_<8ikQzl&dL&=9J(q+Ad+ul2<S4l7e9~=#!sG
zY~#;F?F}1$ugc*pyW}#LwH`TCrjM1**0Iz;va{-_9rUVwN~s#qYYyBZlMJM!`~zO`
mn7E8VGX<lCncpvxt$dqEG=IXrNI3oe{}*yaI8cxuHUhFH_#yNF

literal 0
HcmV?d00001

-- 
2.20.1



More information about the Elfutils-devel mailing list