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]

[PATCH] libdw: Make dwarf_getfuncs find all (defining) DW_TAG_subprogram DIEs.


dwarf_getfuncs used to return only the DW_TAG_subprogram DIEs that were
direct children of the given CU. This is normally how GCC outputs the
subprogram DIEs. But not always. For nested functions the subprogram DIE
is placed under the subprogram DIE where it is nested. Other compilers
might output the defining subprogram DIE of a C++ class function under
the DW_TAG_namespace DIE where it was defined. Both such constructs seem
allowed by the DWARF specification. So just searching the CU DIE children
was wrong.

To find all (defining) subprogram DIEs in a CU dwarf_getfuncs should
use __libdw_visit_scopes to walk the tree. The only tricky part is
making sure the offset returned and used when the callback returns
DWARF_CB_ABORT is correct and the search continues at the right spot
in the CU DIE tree.

Two new testcases were added that fail without this patch. And the
allfcts test was tweaked so that it always returns DWARF_CB_ABORT
from its callback to make sure the offset handling is correct.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 libdw/ChangeLog                 |    6 +++
 libdw/dwarf_getfuncs.c          |   79 ++++++++++++++++++++++++++-------------
 tests/ChangeLog                 |   10 +++++
 tests/Makefile.am               |    1 +
 tests/allfcts.c                 |   12 ++++-
 tests/run-allfcts.sh            |   56 +++++++++++++++++++++++++++-
 tests/testfile_class_func.bz2   |  Bin 0 -> 2962 bytes
 tests/testfile_nested_funcs.bz2 |  Bin 0 -> 3045 bytes
 8 files changed, 134 insertions(+), 30 deletions(-)
 create mode 100755 tests/testfile_class_func.bz2
 create mode 100755 tests/testfile_nested_funcs.bz2

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index c8398b2..07090ba 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,9 @@
+2013-09-18  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getfuncs.c (visitor_info): New struct.
+	(tree_visitor): New function.
+	(dwarf_getfuncs): Use __libdw_visit_scopes with tree_visitor.
+
 2013-08-24  Mark Wielaard  <mjw@redhat.com>
 
 	* dwarf_getlocation.c (store_implicit_value): Don't take data
diff --git a/libdw/dwarf_getfuncs.c b/libdw/dwarf_getfuncs.c
index afc5b6e..c5a7618 100644
--- a/libdw/dwarf_getfuncs.c
+++ b/libdw/dwarf_getfuncs.c
@@ -1,5 +1,5 @@
 /* Get function information.
-   Copyright (C) 2005 Red Hat, Inc.
+   Copyright (C) 2005, 2013 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2005.
 
@@ -35,6 +35,51 @@
 #include "libdwP.h"
 
 
+struct visitor_info
+{
+  /* The user callback of dwarf_getfuncs.  */
+  int (*callback) (Dwarf_Die *, void *);
+
+  /* The user arg value to dwarf_getfuncs.  */
+  void *arg;
+
+  /* The DIE offset where to (re)start the search.  */
+  Dwarf_Off offset;
+};
+
+static int
+tree_visitor (unsigned int depth __attribute__ ((unused)),
+	      struct Dwarf_Die_Chain *chain, void *arg)
+{
+  struct visitor_info *const v = arg;
+  Dwarf_Die *die = &chain->die;
+  Dwarf_Off offset = v->offset;
+  Dwarf_Off die_offset = INTUSE(dwarf_dieoffset) (die);
+
+  /* Skip any subtrees till we find the first DIE offset we are
+     interested in.  */
+  if (die_offset < offset)
+    {
+      Dwarf_Die sibling;
+      if (INTUSE(dwarf_siblingof) (die, &sibling) == 0
+	  && INTUSE(dwarf_dieoffset) (&sibling) <= offset)
+	{
+	  chain->prune = true;
+	  return DWARF_CB_OK;
+	}
+    }
+
+  /* If we aren't past the requested DIE offset or this isn't a
+     (defining) subprogram entity, skip DIE.  */
+  if (die_offset <= offset
+      || INTUSE(dwarf_tag) (die) != DW_TAG_subprogram
+      || INTUSE(dwarf_hasattr) (die, DW_AT_declaration))
+    return DWARF_CB_OK;
+
+  v->offset = die_offset;
+  return (*v->callback) (die, v->arg);
+}
+
 ptrdiff_t
 dwarf_getfuncs (Dwarf_Die *cudie, int (*callback) (Dwarf_Die *, void *),
 		void *arg, ptrdiff_t offset)
@@ -43,31 +88,13 @@ dwarf_getfuncs (Dwarf_Die *cudie, int (*callback) (Dwarf_Die *, void *),
 		|| INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit))
     return -1;
 
-  Dwarf_Die die_mem;
-  Dwarf_Die *die;
+  struct visitor_info v = { callback, arg, offset };
+  struct Dwarf_Die_Chain chain = { .die = CUDIE (cudie->cu),
+				   .parent = NULL };
+  int res = __libdw_visit_scopes (0, &chain, &tree_visitor, NULL, &v);
 
-  int res;
-  if (offset == 0)
-    res = INTUSE(dwarf_child) (cudie, &die_mem);
+  if (res == DWARF_CB_ABORT)
+    return v.offset;
   else
-    {
-      die = INTUSE(dwarf_offdie) (cudie->cu->dbg, offset, &die_mem);
-      res = INTUSE(dwarf_siblingof) (die, &die_mem);
-    }
-  die = res != 0 ? NULL : &die_mem;
-
-  while (die != NULL)
-    {
-      if (INTUSE(dwarf_tag) (die) == DW_TAG_subprogram)
-	{
-	  if (callback (die, arg) != DWARF_CB_OK)
-	    return INTUSE(dwarf_dieoffset) (die);
-	}
-
-      if (INTUSE(dwarf_siblingof) (die, &die_mem) != 0)
-	break;
-    }
-
-  /* That's all.  */
-  return 0;
+    return res;
 }
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 9ea285f..810c89a 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,13 @@
+2013-09-18  Mark Wielaard  <mjw@redhat.com>
+
+	* allfcts.c (cb): Return DWARF_CB_ABORT.
+	(main): Iterate over all offsets returned by dwarf_getfuncs.
+	* run-allfcts.sh: Add nested_funcs and class_func testcases.
+	* testfile_nested_funcs.bz2: New test file.
+	* testfile_class_func.bz2: Likewise.
+	* Makefile.am (EXTRA_DIST): Add testfile_class_func.bz2 and
+	testfile_nested_funcs.bz2.
+
 2013-08-30  Mark Wielaard  <mjw@redhat.com>
 
 	* Makefile.am (check_PROGRAMS): Add varlocs.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e06d914..58db6c3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -119,6 +119,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
 	     testfile5.bz2 testfile6.bz2 testfile7.bz2 testfile8.bz2 \
 	     testfile9.bz2 testfile10.bz2 testfile11.bz2 testfile12.bz2 \
 	     testfile13.bz2 run-strip-test3.sh run-allfcts.sh \
+	     testfile_class_func.bz2 testfile_nested_funcs.bz2 \
 	     run-line2addr.sh run-elflint-test.sh testfile14.bz2 \
 	     run-strip-test4.sh run-strip-test5.sh run-strip-test6.sh \
 	     run-strip-test7.sh run-strip-test8.sh run-strip-groups.sh \
diff --git a/tests/allfcts.c b/tests/allfcts.c
index f14b493..7803722 100644
--- a/tests/allfcts.c
+++ b/tests/allfcts.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Red Hat, Inc.
+/* Copyright (C) 2005, 2013 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -34,7 +34,7 @@ cb (Dwarf_Die *func, void *arg __attribute__ ((unused)))
 
   printf ("%s:%d:%s\n", file, line, fct);
 
-  return DWARF_CB_OK;
+  return DWARF_CB_ABORT;
 }
 
 
@@ -57,7 +57,13 @@ main (int argc, char *argv[])
 	      Dwarf_Die die_mem;
 	      Dwarf_Die *die = dwarf_offdie (dbg, off + cuhl, &die_mem);
 
-	      (void) dwarf_getfuncs (die, cb, NULL, 0);
+	      /* Explicitly stop in the callback and then resume each time.  */
+	      ptrdiff_t doff = 0;
+	      do
+		{
+		  doff = dwarf_getfuncs (die, cb, NULL, doff);
+		}
+	      while (doff > 0);
 
 	      off = noff;
 	    }
diff --git a/tests/run-allfcts.sh b/tests/run-allfcts.sh
index 30f7dd4..6eaf13c 100755
--- a/tests/run-allfcts.sh
+++ b/tests/run-allfcts.sh
@@ -1,5 +1,5 @@
 #! /bin/sh
-# Copyright (C) 2005 Red Hat, Inc.
+# Copyright (C) 2005, 2013 Red Hat, Inc.
 # This file is part of elfutils.
 # Written by Ulrich Drepper <drepper@redhat.com>, 2005.
 #
@@ -37,4 +37,58 @@ testrun_compare ${abs_builddir}/allfcts testfile testfile2 testfile8 <<\EOF
 /home/drepper/gnu/elfutils/build/src/../../src/strip.c:313:handle_elf
 EOF
 
+# = nested_funcs.c =
+#
+# static int
+# foo (int x)
+# {
+#   int bar (int y)
+#   {
+#     return x - y;
+#   }
+# 
+#   return bar (x * 2);
+# }
+#
+# int
+# main (int argc, char ** argv)
+# {
+#   return foo (argc);
+# }
+#
+# gcc -g -o nested_funcs nested_funcs.c
+
+# = class_func.cxx =
+#
+# namespace foobar
+# {
+#   class Foo
+#   {
+#   public:
+#     int bar(int x);
+#   };
+#
+#   int Foo::bar(int x) { return x - 42; }
+# };
+#
+# int
+# main (int argc, char **argv)
+# {
+#   foobar::Foo foo;
+#
+#   return foo.bar (42);
+# }
+#
+# clang++ -g -o class_func class_func.cxx
+
+testfiles testfile_nested_funcs testfile_class_func
+
+testrun_compare ${abs_builddir}/allfcts testfile_nested_funcs testfile_class_func <<\EOF
+/home/mark/src/tests/nested/nested_funcs.c:2:foo
+/home/mark/src/tests/nested/nested_funcs.c:4:bar
+/home/mark/src/tests/nested/nested_funcs.c:13:main
+/home/mark/src/tests/nested/class_func.cxx:6:bar
+/home/mark/src/tests/nested/class_func.cxx:13:main
+EOF
+
 exit 0
diff --git a/tests/testfile_class_func.bz2 b/tests/testfile_class_func.bz2
new file mode 100755
index 0000000000000000000000000000000000000000..e40dcf2623637a709110115e013273e3e8277eaa
GIT binary patch
literal 2962
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
I0;uKJAjNljEdT%j

literal 0
HcmV?d00001

diff --git a/tests/testfile_nested_funcs.bz2 b/tests/testfile_nested_funcs.bz2
new file mode 100755
index 0000000000000000000000000000000000000000..d36b603ebd25ddd53367909dc7512b05930fdd6b
GIT binary patch
literal 3045
zcmV<B3mWu7T4*^jL0KkKSuURr_W%mkfB*mg|Nq|q|NH;<|L_0*-~aD#<^S~1Rn!0E
z_Fs2(a)Z-3wlFSlLZ%V-VnFFe#O=MC#yF}Cp4$~5k?cMUY5GH4N|nrW(d(@E-jC#rbG
zPf%(4lhpK?rlw43HlxaTrk|=Fq3U{=nWTD|9;Sz+^&X~;3(a)4}thm`d_LqG%5P|!U<
z(@#;Mk?IXhg*^<Kni!g=fJx}5>Y6>Ep{9>0^#EvS00E!?&;vj;&;S|$27mwqKmY&$
zX!QWoLMBKin1Xsnr>W>@G$zzzQ1vt#0B8e4AOHXlP&68782|==00E!|jQ|XQ27^G;
zN)V&cY@<M885%V8G-;qRF#)ESni^@NAoT`AKs0HQra&41$Oepzk5FhdXfXiOK+p!7
zGzc0R00Ton8W{|LG-NUXqd|}uAQ=Nq00EJqpc()JKn8#s003wJ4FQ5gku(xEqct{z
zK}^)h(TMd1k5fPZ14Gm_0C=W=(Deq7L;wH=fMfsw15Z!@000_o_l!;=QzD*27#Tw^
ze%Zo(a)0rmvSMb}?4sKFtXh(icNf3k)c+iYV7gRWvw)4P<3I;_Gh$zfqD-g2Bso{)GV
z7RnWph?GjpVc-&(;<+nb1B_xMTr464-eafV!Ly&Km*TS3qfJSPHF`$=wj+I^dh}mJ
zXG&)+PZ{g56vGsZAVlEo2^9C71QnQT2|Stc5J-m7Q<BP!A)Qjhb|HykMB#QFRpzPV
zMWZYQFO(=GkVynG$qaHKW5}xJW!}nnQ!l8MhoHhQ_pBII>nA)8Q7Dwo8wPCydCwp$
zptN1r(%UH{D#8PGz~3<$7cOB-m|~$e<sB5bB?GmPFzv@>)n8lDZSno`eQr0W5J;}2
zoA!GC6%WzOM-u3SyCDRQADqG<M598mNV6v0fn^n(a)Iae3>UZ#HP5(Gg^PJs%5Z7!d|
zGzjW;IK5-gh=DY6Z!M!hxq4gxJ4)$*`G7s<G&3ckonZ#KwjA6+w2>td2h(a)QeQ4%ql
zNoGHxiBz$0<d%()@O3W#hNFer=p^c%jjm$adhAP>8i%rXZxiI<%h*4zejDdZRtqIs
zSLULg&9*{hpERRj6aY4Xw$LGIni9upAXXT!7$miiAYlwfJMmgj#U_Yi6f_`J0hGrE
zk`jn$fE+Rg#=~OJ1|ZN$q_yoNLk7(a)VVOoesN3tWy;G&ZOF63aVG=i%^RiHrF0ifKV
zA&Dbo&<0ymv;$};Y8aaqjiMQ=h*D`H8Vq=Zk)<#p0+R`%;u~XRfhd$M?jclQ5XqAW
z&B6i0a9>JHV{^<YZvx=9Wuj5S0)!-ShC{WSThV`)RMv=8TGpvEO%YL92bU|E$;<hg
zwUro{@8;^@C*;wf@}(~>BKCBs%3HR{aN%lKDXf5P5yKIHHY6v)#O-=xL4<<|BsD`?
zrd6>sXS{RXW~}p9atcZAiQSu)FTHeEn)9j+I-rkjl3=j>YpYb)jBCk+jS7dV2dNu_
z?k|pw#+(a)M$!%!k=0QSTI3t524nzyXxI3p6xX9(VboN>~478%jp2+#^eSpk9sM?!$~
zgtWhhYj5TE?cuq9w$J4IJj_}&lsWsH?9SHS9AbzGl0uM!b_fDNM}-kJfNPOaH2P8n
zGgu5Mv};&<%quY3hSNsc!)$3x*Sp90oWAcYnX1uE-jM{ECK!!u9yKFLlV<ji8isVc
zI1Nh?fI(a)O8ssdC(iF<0=TT91xcX#iSKKVi6=hPx$ns=Rc_ov(a)3s7p}81?(*#S>#9n
zo#%!qFQFu{cl&F5diCg<5V5a}zsO2(oZ&b{2E6U~6#yW-ycSehL~!R&P>?SQK!Ff*
z$VlpKcU}dhc#Ub{TF|bQAg4Q{RMSx|5J*nr!Gi4zH4vkmp32VAv)DV;_;Fy1mcue6
z0mZ;a_Z)h3I+g^DLIvp<4JxAiCF=|^HgKeX;1zxNqT{3LTN$L<t<cDvHK*50PjhTc
zRw+?#@@fQ{Ub_%x+6mu;!F2;xp#aXJqcI9*1T_Gb5mG4u9jZ}Rb;7m`;CpykMU;p{
zAqXynAWQl(Ck)HUbrpfU0Ts1nUZUN(>oEY~g=|bq!qDz!AJN$*+q6=u!6d5$mR$#g
zLzl!&2fAh{{_m#Q0-_L=ylSUIv&Gd>dMMqPCmb-;LIAL2-9~6t-)>y6(a)5Ra7va>4>
zT%*Z1aBwcG3h_u|qp~L?b{ZZ5kpuu9%7T(8w(lxpK4gJAs4`NpVRBB0QGhXvx~Np0
zO*sTqjwC?EMcCk_HDdOwO&@ccC27rph(+TUL~R171_+2?k7<I?CBRXquC$sI_PxNN
zzw$Rg#HJBEouF78DAb}GH<474u~C*PsbN4k^AI71y6H5HQK=}8DFrC0y}Nb2so6QG
zc^xx?QIxLhfv^yVjv>bcSkBhQuyzigF9ZvmJ(va#pbU7kcmdMFCb*(Npn(aUbpnj~
zqy{p*iBH0oV+JHi2Eb~!L1<u$5zvO^3afzVBG?{mCfI#r<#0nHylZ|OdGH3Z$Wy_|
zT9``w0wWb1cte5FFxXkAY4T=~B`HcwLIzN_DQ07YkSzS$;Tsx@%;xp|{nQ18+jRoP
zC{B?uog9K4;;ic7g0iV)W-38)A2`x?0tD$5s6bH_(oI6G9qa)mS_!q9aW+w4HriIn
z{ObH$pGzx88fR&^`cEH_)$JH|lz#8L@@z%OIu+>k?A-mpsT-ZC5=DS^?eLp#AuBAK
zdpGcHIajc8zI;`L)ooMUNKYrSsV0<Qu=A#-l|)Ca4f?bfSKdva`sh4CW&bfgd?4Pb
zLyy-Zmd`Yf48S<4XUmi(a)-!dQHc>cdb1@<EPak5{p(}ot~b{r1IBrFh6pIH(i0#@fs
zEGz<cLqU)<0&#fEi4ynCAFj&e2(a)4neILHEHS`Uh8_PSV78PU01+zvm*J*HgzSj`pj
z#-(a)C?pUqkhfY%Cw#?_WUAgsTRV_233<v(a)ejChFT}QAf085vOarG$mhUvs)UxiXK|m
z5*<49>CaK3YjYnpJuI_1Ib7o^ViQ{9O$#_d3}i$NwA*7uLW4h;N=*{e>5FxpSA#{(
zqA!D3R|@yhD0ELya4HZ_Q=u&)a-giN3-gn<nq)IIkxvB>PSWDSk^z+hE49|zNC%ZJ
zO_Wh~2ot(lNzf|Bh89{U3#+N(a)R#eE6YUL8Z(2x~lIu(XUxu*prQz|YXjV=-DO>TBW
zBNDw}Oyg;ZL5)Db$(jnd^xvSE6+$ht7NZLT4Tsb*kfWkA5`<9dbmRhxPMHDb2$9Dc
zo+v<#2vvCSja*`3wqs9I9Bh-Otbsj22(TD3uM02{K@~iLMWS4&tQMLg8Lq%oD-^OM
z?EvIXreMZ`0$+)Rks-hyI1yYc$wje1D}vTV0wE|^4Hd*<=+s2YqE=_k9Ez~59Vyp9
zkOPb&Q)1jvi^~ZlnS(a)Xb8US#42vh=4n1ZbpC=>`&w9vT113<2Tb5RQ8cv`eiNLzJO
zwm>%T(a)a$@_UNo)>wF-dAA(pfEXgNga9fk&S?&isO76QREo3p8dzN<7KKrGt`aJq!P
zW*6DaWKFD?Z(2)cFkP%AF`lg3rtUGAYKxaapvuUw1dkaUO>xz`rWqz$-2f1wU30R6
zcSxJq^pf5+R-<DxU)Q4`1yb_kVX}FAFK2g8S`_`8>saHWOX$E+ee+E)@~}5q><{WG
z+56dToMAct3*EvMLyH<~w$iJJ#6VG-(a)-}cPTyQxPAwzBPcKCU)ah!f%mG%>eG|6eE
z86WNp9eS|9Wg{zod%2AY4<E&WTB}OXtPO(a)lX-a89oKZ?|CN-Kp#+PV+IL(|8zUZ>3
z=<y94o?q^f;1H+K#NG7r>D>i*hQokseh(s*WD7SgUl;lY1}%&J!o6?GfG7=nsu(Qx
zL|&`fyIKTtWY~H*1diBP6#N|C-xp`D!`SL{S<7>t4DH>NaZOG&m2^NGMwW(a)rH6}L9
nz^X|ntyMf?sGDwf^6#JUNq>2zr8`Qo&-`7<6yZWZx_mp_!b(a)pV

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]