This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 2/3] libdwfl: Add minisymtab support.


On Wed, 2013-01-23 at 07:03 +0100, Jan Kratochvil wrote:
> On Tue, 22 Jan 2013 22:03:24 +0100, Mark Wielaard wrote:
> > I do wonder how realistic it is that we will ever encounter such a case though.
> 
> I do not wonder, it is for example /usr/bin/fpc (from fpc-2.6.0-3.fc18.x86_64).

Aha, thanks for that example. I guess it makes sense for static
binaries. So lets support that too. I created a minimal testcase.
How about the attached to support it?

Thanks,

Mark
>From cf875ef688c8f1d081a770e3df43e0668fa80c49 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Wed, 23 Jan 2013 17:39:19 +0100
Subject: [PATCH] libdwfl: Support auxiliary symbol table only for getsym and addrsym.

Static binaries can have only an auxiliary symbol table and no dynsym
or symtab table.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 libdwfl/ChangeLog              |   12 ++++++++++++
 libdwfl/dwfl_module_addrsym.c  |   16 +++++++++++-----
 libdwfl/dwfl_module_getdwarf.c |   22 +++++++++++++++++-----
 libdwfl/dwfl_module_getsym.c   |   11 ++++++-----
 tests/ChangeLog                |    7 +++++++
 tests/Makefile.am              |    2 +-
 tests/run-dwflsyms.sh          |   13 +++++++++++++
 tests/run-readelf-s.sh         |   40 ++++++++++++++++++++++++++++++++++++++++
 tests/testfilebasmin.bz2       |  Bin 0 -> 1082 bytes
 9 files changed, 107 insertions(+), 16 deletions(-)
 create mode 100755 tests/testfilebasmin.bz2

diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 828db08..24d4ae5 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,15 @@
+2013-01-23  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getdwarf.c (find_aux_sym): Don't substract one
+	from aux_syments by default.
+	(find_symtab): Also succeed when only aux_symdata is found.
+	When no symtab is found always try to load auxiliary table.
+	Substract one from aux_syments when both tables have symbols.
+	* dwfl_module_getsym.c (dwfl_module_getsym): Only skip auxiliary
+	zero entry when both tables have symbols.
+	* dwfl_module_addrsym.c (dwfl_module_addrsym): Only substract
+	one from first_global when both tables have symbols.
+
 2013-01-16  Mark Wielaard  <mjw@redhat.com>
 
 	* libdwflP.h (struct Dwfl_Module): Add aux_sym, aux_symdata,
diff --git a/libdwfl/dwfl_module_addrsym.c b/libdwfl/dwfl_module_addrsym.c
index d2059ea..732b698 100644
--- a/libdwfl/dwfl_module_addrsym.c
+++ b/libdwfl/dwfl_module_addrsym.c
@@ -175,11 +175,17 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr,
 
   /* First go through global symbols.  mod->first_global and
      mod->aux_first_global are setup by dwfl_module_getsymtab to the
-     index of the first global symbol in the module's symbol table.  Both
-     are zero when unknown.  All symbols with local binding come first in
-     the symbol table, then all globals.  */
-  int first_global = mod->first_global + mod->aux_first_global - 1;
-  search_table (first_global < 0 ? 1 : first_global, syments);
+     index of the first global symbol in those symbol tables.  Both
+     are non-zero when the table exist, except when there is only a
+     dynsym table loaded through phdrs, then first_global is zero and
+     there will be no auxiliary table.  All symbols with local binding
+     come first in the symbol table, then all globals.  The zeroth,
+     null entry, in the auxiliary table is skipped if there is a main
+     table.  */
+  int first_global = mod->first_global + mod->aux_first_global;
+  if (mod->syments > 0 && mod->aux_syments > 0)
+    first_global--;
+  search_table (first_global == 0 ? 1 : first_global, syments);
 
   /* If we found nothing searching the global symbols, then try the locals.
      Unless we have a global sizeless symbol that matches exactly.  */
diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
index ffbe589..6ec11ff 100644
--- a/libdwfl/dwfl_module_getdwarf.c
+++ b/libdwfl/dwfl_module_getdwarf.c
@@ -909,7 +909,7 @@ find_aux_sym (Dwfl_Module *mod __attribute__ ((unused)),
 			minisymtab = true;
 			*aux_symscn = scn;
 			*aux_strshndx = shdr->sh_link;
-			mod->aux_syments = shdr->sh_size / shdr->sh_entsize - 1;
+			mod->aux_syments = shdr->sh_size / shdr->sh_entsize;
 			mod->aux_first_global = shdr->sh_info;
 			if (*aux_xndxscn != NULL)
 			  return;
@@ -949,7 +949,7 @@ find_aux_sym (Dwfl_Module *mod __attribute__ ((unused)),
 static void
 find_symtab (Dwfl_Module *mod)
 {
-  if (mod->symdata != NULL	/* Already done.  */
+  if (mod->symdata != NULL || mod->aux_symdata != NULL	/* Already done.  */
       || mod->symerr != DWFL_E_NOERROR) /* Cached previous failure.  */
     return;
 
@@ -1001,16 +1001,23 @@ find_symtab (Dwfl_Module *mod)
 	  break;
 
 	case DWFL_E_NO_SYMTAB:
+	  /* There might be an auxiliary table.  */
+	  find_aux_sym (mod, &aux_symscn, &aux_xndxscn, &aux_strshndx);
+
 	  if (symscn != NULL)
 	    {
 	      /* We still have the dynamic symbol table.  */
 	      mod->symerr = DWFL_E_NOERROR;
-
-	      /* The dynsym table might be extended by an auxiliary table.  */
-	      find_aux_sym (mod, &aux_symscn, &aux_xndxscn, &aux_strshndx);
 	      break;
 	    }
 
+	  if (aux_symscn != NULL)
+	    {
+	      /* We still have the auxiliary symbol table.  */
+	      mod->symerr = DWFL_E_NOERROR;
+	      goto aux_cache;
+	    }
+
 	  /* Last ditch, look for dynamic symbols without section headers.  */
 	  find_dynsym (mod);
 	  return;
@@ -1049,6 +1056,7 @@ find_symtab (Dwfl_Module *mod)
   /* Cache any auxiliary symbol info, when it fails, just ignore aux_sym.  */
   if (aux_symscn != NULL)
     {
+  aux_cache:
       /* This does some sanity checks on the string table section.  */
       if (elf_strptr (mod->aux_sym.elf, aux_strshndx, 0) == NULL)
 	{
@@ -1077,6 +1085,10 @@ find_symtab (Dwfl_Module *mod)
       mod->aux_symdata = elf_getdata (aux_symscn, NULL);
       if (mod->aux_symdata == NULL)
 	goto aux_cleanup;
+
+      /* We will skip the auxiliary zero entry if there is another one. */
+      if (mod->syments > 0 && mod->aux_syments > 0)
+	mod->aux_syments--;
     }
 }
 
diff --git a/libdwfl/dwfl_module_getsym.c b/libdwfl/dwfl_module_getsym.c
index 3e4d9f6..07127b7 100644
--- a/libdwfl/dwfl_module_getsym.c
+++ b/libdwfl/dwfl_module_getsym.c
@@ -48,6 +48,7 @@ dwfl_module_getsym (Dwfl_Module *mod, int ndx,
      And skip the auxiliary table zero undefined entry.  */
   GElf_Word shndx;
   int tndx = ndx;
+  int skip_aux_zero = (mod->syments > 0 && mod->aux_syments > 0) ? 1 : 0;
   struct dwfl_file *file;
   Elf_Data *symdata;
   Elf_Data *symxndxdata;
@@ -62,19 +63,19 @@ dwfl_module_getsym (Dwfl_Module *mod, int ndx,
       symxndxdata = mod->symxndxdata;
       symstrdata = mod->symstrdata;
     }
-  else if (ndx < mod->first_global + mod->aux_first_global - 1)
+  else if (ndx < mod->first_global + mod->aux_first_global - skip_aux_zero)
     {
       /* aux symbol table (locals).  */
-      tndx = ndx - mod->first_global + 1;
+      tndx = ndx - mod->first_global + skip_aux_zero;
       file = &mod->aux_sym;
       symdata = mod->aux_symdata;
       symxndxdata = mod->aux_symxndxdata;
       symstrdata = mod->aux_symstrdata;
     }
-  else if ((size_t) ndx < mod->syments + mod->aux_first_global - 1)
+  else if ((size_t) ndx < mod->syments + mod->aux_first_global - skip_aux_zero)
     {
       /* main symbol table (globals).  */
-      tndx = ndx - mod->aux_first_global + 1;
+      tndx = ndx - mod->aux_first_global + skip_aux_zero;
       file = mod->symfile;
       symdata = mod->symdata;
       symxndxdata = mod->symxndxdata;
@@ -83,7 +84,7 @@ dwfl_module_getsym (Dwfl_Module *mod, int ndx,
   else
     {
       /* aux symbol table (globals).  */
-      tndx = ndx - mod->syments + 1;
+      tndx = ndx - mod->syments + skip_aux_zero;
       file = &mod->aux_sym;
       symdata = mod->aux_symdata;
       symxndxdata = mod->aux_symxndxdata;
diff --git a/tests/ChangeLog b/tests/ChangeLog
index feb9f69..bc721c7 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,10 @@
+2013-01-23  Mark Wielaard  <mjw@redhat.com>
+
+	* testfilebasmin.bz2: New testfile.
+	* Makefile.am (EXTRA_DIST): Add testfilebasmin.bz2.
+	* run-readelf-s.sh: Test testfilebasmin.
+	* run-dwflsyms.sh: Likewise.
+
 2013-01-16  Mark Wielaard  <mjw@redhat.com>
 
 	* Makefile.am (check_PROGRAMS): Add dwflsyms.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b46c4c2..f32ea24 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -175,7 +175,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
 	     testfilegdbindex7.bz2 \
 	     run-readelf-s.sh testfilebazdbg.bz2 testfilebazdyn.bz2 \
 	     testfilebazmin.bz2 testfilebazdbg.debug.bz2 testfilebazmdb.bz2 \
-	     testfilebaztab.bz2 \
+	     testfilebaztab.bz2 testfilebasmin.bz2 \
 	     run-dwflsyms.sh \
 	     run-unstrip-n.sh testcore-rtlib.bz2 testcore-rtlib-ppc.bz2 \
 	     run-low_high_pc.sh testfile_low_high_pc.bz2 \
diff --git a/tests/run-dwflsyms.sh b/tests/run-dwflsyms.sh
index 570881a..56a7580 100755
--- a/tests/run-dwflsyms.sh
+++ b/tests/run-dwflsyms.sh
@@ -25,6 +25,7 @@ testfiles testfilebazdbg testfilebazdbg.debug
 testfiles testfilebazdyn
 testfiles testfilebazmdb
 testfiles testfilebazmin
+testfiles testfilebasmin
 
 tempfiles testfile.dynsym.in testfile.symtab.in testfile.minsym.in dwflsyms.out
 
@@ -190,4 +191,16 @@ cat testfile.symtab.in \
 cat testfile.minsym.in \
   | testrun_compare ./dwflsyms -e testfilebazmin
 
+testrun_compare ./dwflsyms -e testfilebasmin <<\EOF
+   0: NOTYPE	LOCAL	 (0) 0
+   1: FUNC	LOCAL	foo (18) 0x400168
+   2: SECTION	LOCAL	 (0) 0x400120
+   3: SECTION	LOCAL	 (0) 0x400144
+   4: SECTION	LOCAL	 (0) 0x4001c0
+   5: SECTION	LOCAL	 (0) 0x600258
+   6: FUNC	GLOBAL	_start (21) 0x4001a8
+   7: FUNC	GLOBAL	main (33) 0x400144
+   8: FUNC	GLOBAL	bar (44) 0x40017a
+EOF
+
 exit 0
diff --git a/tests/run-readelf-s.sh b/tests/run-readelf-s.sh
index f14b305..bad31cf 100755
--- a/tests/run-readelf-s.sh
+++ b/tests/run-readelf-s.sh
@@ -74,12 +74,33 @@
 #
 # - testfilebazmin (dynsym + gnu_debugdata)
 # objcopy --remove-section=.gnu_debuglink baz testfilebazmin
+#
+#
+# Special auxiliary only, can happen with static binaries.
+# - start.c
+#
+# extern int main (int argc, char ** argv);
+# void _start (void) { for (;;) main (1, 0); }
+#
+# gcc -g -c start.c
+# gcc -static -nostdlib -o bas foo.o bar.o start.o
+#
+# eu-strip --remove-comment -f bas.debug bas
+# nm bas.debug --format=posix --defined-only | awk '{ if ($2 == "T" || $2 == "t") print $1 }' | sort > funcsyms
+# objcopy -S --remove-section .gdb_index --remove-section .comment --keep-symbols=funcsyms bas.debug mini_debuginfo
+# rm -f mini_debuginfo.xz
+# xz mini_debuginfo
+# objcopy --add-section .gnu_debugdata=mini_debuginfo.xz bas
+# rm bas.debug
+# mv bas testfilebasmin
+
 
 testfiles testfilebaztab
 testfiles testfilebazdbg testfilebazdbg.debug
 testfiles testfilebazdyn
 testfiles testfilebazmdb
 testfiles testfilebazmin
+testfiles testfilebasmin
 
 tempfiles testfile.dynsym.in testfile.symtab.in testfile.minsym.in
 
@@ -253,4 +274,23 @@ cat testfile.dynsym.in \
 cat testfile.minsym.in \
   | testrun_compare ../src/readelf --elf-section -s testfilebazmin
 
+testrun_compare ../src/readelf -s testfilebasmin <<EOF
+EOF
+
+testrun_compare ../src/readelf --elf-section -s testfilebasmin <<\EOF
+
+Symbol table [ 6] '.symtab' contains 9 entries:
+ 6 local symbols  String table: [ 7] '.strtab'
+  Num:            Value   Size Type    Bind   Vis          Ndx Name
+    0: 0000000000000000      0 NOTYPE  LOCAL  DEFAULT    UNDEF 
+    1: 0000000000400168     18 FUNC    LOCAL  DEFAULT        2 foo
+    2: 0000000000400120      0 SECTION LOCAL  DEFAULT        1 
+    3: 0000000000400144      0 SECTION LOCAL  DEFAULT        2 
+    4: 00000000004001c0      0 SECTION LOCAL  DEFAULT        3 
+    5: 0000000000600258      0 SECTION LOCAL  DEFAULT        4 
+    6: 00000000004001a8     21 FUNC    GLOBAL DEFAULT        2 _start
+    7: 0000000000400144     33 FUNC    GLOBAL DEFAULT        2 main
+    8: 000000000040017a     44 FUNC    GLOBAL DEFAULT        2 bar
+EOF
+
 exit 0
diff --git a/tests/testfilebasmin.bz2 b/tests/testfilebasmin.bz2
new file mode 100755
index 0000000000000000000000000000000000000000..3843972037ca84dc9599f5dc25ad05e0f2278f43
GIT binary patch
literal 1082
zcmV-A1jYM8T4*^jL0KkKS=jQ&IRF9VfB*mg-@X5@_22*Je}4D>|M%bjf9>DZXV?7x
z?YGnI|Np=OyaGAKD2ftjJw_CI4H-iLqfHtO6KOIHsLdKpF&?3fObq~!NuwjuHlS!|
z(@X*~X!SPL8$x;`LkW`&OaV07pQ>zXg-FzGO&Sdv27mzafB*mh0ib9A00000&;S4i
zjQ{`u0000Q211oG8z{uk14pO;000Jn05kwJ0004?000000MGyifCE4P007fb36#Xz
z6wn$pdY-0+Kn6etng9lYp!El+G7UXLKmY-wKmY&%>Hq)+fB+2xMN`W|n6h(h0~K>X
zNiGMW@`8zhT$zR$Q^rgd*$`Z9m`lJJN=B=@R>H_>9>04+P)<)iw#_)u2`;4s1XYxQ
z9}uz#GXx+X1|SKtrWQgv?lFfA-#;|A8=J{3XaGtQh!I5)Bl3a?6Xg&~nIr&_0YN-M
z2ayzjC$F}srzs+e!yXn@>tVwlyr78b$dn2c5^Fk{+Y`YQg%HUSX{A@nB68N^(p5O{
zATe4f8YA~bIz=l1QLZImYyc?26z@xQYCg<>;Xs7H%T~Z`Yys-)sW&t6S0bDA(8051
zAxTc5gaV@;>$5PfN%(W-xY*dt^eR<LNT3s<a4cUOpaMV{r-G!z+w|!8vB0a<YoE#v
z&Uv1FRUYal>|-?hMa&2c&|6INhjMZdSYzW_oGylL|KPlLLCtlmn3I}kT{@N8z&DxV
z8}UGx_G!iDpv9&XK%>W>Mxc+9_~Qgw*R(uQwnt7D416J#3P`L`2oU1Pis9c|I#>hK
z?s4BbkO1?8vo0@ius^RN{Lz2t6qp0av4o-S&4C1!`*&7ss|9DSfooz`AWAX=$)x}c
zNO3X5&J6`os40YoapOF1d?dPonFJ<`x(98R<hU-1HwP9pQ**~)mjMwrh;|VP0rrN4
z_c)H0bO8hAT@1lMaO((*%x^K=sZ_}Qui0`11PiQ+tq&O`3DM+5`mHd^m>>l$%zmIu
zC9nb**KCAjP1duZ%tu-%MIbn=+FJ6WAWAu8(WoAOF?p$sNV6IOOrX*VPKt@Z1=qg`
z18ayPYle(p>bL{IAOK3^IIQ8p0Iy<f`3pq3IWVO`UoxaxsBhdRKWEuNjKGg;MR}P1
z)t}2s)@Y0F3diYb=2LF+i(mAvk?o`M_-?lnU_oK_okv-fLdqp>T}^JKzl&0Hp$Ivc
zJ_ND;r6QxOAtV73?e@Y*`|S~cAX0NxkFy5Y%a1-xXj@&`28P3iVXv&wM5QSP+Knp~
z4BO5CwD9VRY^<XR*i1_BfvcF%7Xx&Vt0xT)L}u2D8-}~{b+c&uXnC{OZLTe6U@eBA
zYEL<a%!<`o*m3T4mMEc<wv$}=;g|qmm<?c1f<znwV27xmq3`&+k}1N3hR2pU$R!8e
AVgLXD

literal 0
HcmV?d00001

-- 
1.7.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]