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: Add dwarf_peel_type. Use it in dwarf_aggregate_size.


On irc Josh pointed out that dwarf_aggregate_size still doesn't work
correctly for qualified types. Since handling qualified types is a
common issue (we already have support for it in the backends for the
return type and I have had to fix issues with it in other programs
before) I added a new libdw function for it and use that in both the
backends and dwarf_aggregate_size. This will also help when DWARFv5
adds new qualified type tags.

Add new function dwarf_peel_type. Some type annotations in DWARF are
specified by modifier tag type wrappers instead of attributes.
For type aliases (typedef) and qualifiers (const, volatile, restrict)
tags dwarf_peel_type follows the DW_AT_type attributes till it finds
a base, user-defined, reference or pointer type DIE.

Use this new function in the backends for return type DIEs (replacing
the existing dwarf_peel_type there) and in dwarf_aggregate_size so
it can provide the sizes for qualified types too. Add a new version
and testcase for the new dwarf_aggregate_size functionality.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 ChangeLog                    |   4 +++
 NEWS                         |   5 +++
 backends/ChangeLog           |   5 +++
 backends/libebl_CPU.h        |  22 +++----------
 libdw/ChangeLog              |  10 ++++++
 libdw/Makefile.am            |   2 +-
 libdw/dwarf_aggregate_size.c |  14 ++++++--
 libdw/dwarf_peel_type.c      |  74 +++++++++++++++++++++++++++++++++++++++++++
 libdw/libdw.h                |  11 +++++++
 libdw/libdw.map              |  12 ++++++-
 libdw/libdwP.h               |   1 +
 tests/ChangeLog              |   6 ++++
 tests/Makefile.am            |   3 +-
 tests/run-aggregate-size.sh  |  40 ++++++++++++++++++++++-
 tests/testfile-sizes3.o.bz2  | Bin 0 -> 1147 bytes
 15 files changed, 185 insertions(+), 24 deletions(-)
 create mode 100644 libdw/dwarf_peel_type.c
 create mode 100644 tests/testfile-sizes3.o.bz2

diff --git a/ChangeLog b/ChangeLog
index 8277932..0947608 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2014-10-06  Mark Wielaard  <mjw@redhat.com>
+
+	* NEWS: New section 0.161. Add dwarf_peel_type.
+
 2014-08-25  Mark Wielaard  <mjw@redhat.com>
 
 	* configure.ac: Set version to 0.160.
diff --git a/NEWS b/NEWS
index aceb3e3..130856e 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,8 @@
+Version 0.161
+
+libdw: New function dwarf_peel_type. dwarf_aggregate_size now uses
+       dwarf_peel_type to also provide the sizes of qualified types.
+
 Version 0.160
 
 libdw: New functions dwarf_cu_getdwarf, dwarf_cu_die.
diff --git a/backends/ChangeLog b/backends/ChangeLog
index a335b20..82a2bf1 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,8 @@
+2014-10-06  Mark Wielaard  <mjw@redhat.com>
+
+	* libebl_CPU.h (dwarf_peel_type): Removed.
+	(dwarf_peeled_die_type): Use libdw dwarf_peel_type.
+
 2014-07-18  Kyle McMartin  <kyle@redhat.com>
 	    Mark Wielaard  <mjw@redhat.com>
 
diff --git a/backends/libebl_CPU.h b/backends/libebl_CPU.h
index fa0d4f2..ef2b922 100644
--- a/backends/libebl_CPU.h
+++ b/backends/libebl_CPU.h
@@ -53,23 +53,6 @@ extern bool (*generic_debugscn_p) (const char *) attribute_hidden;
      if (_die == NULL) return -1; \
      dwarf_tag (_die); })
 
-/* Follow typedefs and qualifiers to get to the actual type.  */
-static inline int
-dwarf_peel_type (Dwarf_Die *typediep, Dwarf_Attribute *attrp)
-{
-  int tag = DWARF_TAG_OR_RETURN (typediep);
-  while (tag == DW_TAG_typedef
-	 || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
-	 || tag == DW_TAG_restrict_type)
-    {
-      attrp = dwarf_attr_integrate (typediep, DW_AT_type, attrp);
-      typediep = dwarf_formref_die (attrp, typediep);
-      tag = DWARF_TAG_OR_RETURN (typediep);
-    }
-
-  return tag;
-}
-
 /* Get a type die corresponding to DIE.  Peel CV qualifiers off
    it.  */
 static inline int
@@ -84,7 +67,10 @@ dwarf_peeled_die_type (Dwarf_Die *die, Dwarf_Die *result)
   if (dwarf_formref_die (attr, result) == NULL)
     return -1;
 
-  return dwarf_peel_type (result, attr);
+  if (dwarf_peel_type (result, result) != 0)
+    return -1;
+
+  return DWARF_TAG_OR_RETURN (result);
 }
 
 #endif	/* libebl_CPU.h */
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index f40ad25..2a4f1cd 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,13 @@
+2014-10-06  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_peel_type.c.
+	* dwarf_aggregate_size.c (get_type): Use dwarf_peel_type.
+	(aggregate_size): Likewise. Add old and new version.
+	* dwarf_peel_type.c: New file.
+	* libdw.h (dwarf_peel_type): New function declaration.
+	* libdwP.h (dwarf_peel_type): New internal declaration.
+	* libdw.map (ELFUTILS_0.161): New section.
+
 2014-10-05  Mark Wielaard  <mjw@redhat.com>
 
 	* dwarf.h: Add DW_AT_GNU_deleted.
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index 2e42a37..859af4d 100644
--- a/libdw/Makefile.am
+++ b/libdw/Makefile.am
@@ -87,7 +87,7 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
 		  dwarf_aggregate_size.c dwarf_getlocation_implicit_pointer.c \
 		  dwarf_getlocation_die.c dwarf_getlocation_attr.c \
 		  dwarf_getalt.c dwarf_setalt.c dwarf_cu_getdwarf.c \
-		  dwarf_cu_die.c
+		  dwarf_cu_die.c dwarf_peel_type.c
 
 if MAINTAINER_MODE
 BUILT_SOURCES = $(srcdir)/known-dwarf.h
diff --git a/libdw/dwarf_aggregate_size.c b/libdw/dwarf_aggregate_size.c
index 5d23541..1666e24 100644
--- a/libdw/dwarf_aggregate_size.c
+++ b/libdw/dwarf_aggregate_size.c
@@ -37,8 +37,13 @@
 static Dwarf_Die *
 get_type (Dwarf_Die *die, Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem)
 {
-  return INTUSE(dwarf_formref_die)
+  Dwarf_Die *type = INTUSE(dwarf_formref_die)
     (INTUSE(dwarf_attr_integrate) (die, DW_AT_type, attr_mem), type_mem);
+
+  if (INTUSE(dwarf_peel_type) (type, type) != 0)
+    return NULL;
+
+  return type;
 }
 
 static int
@@ -198,7 +203,6 @@ aggregate_size (Dwarf_Die *die, Dwarf_Word *size, Dwarf_Die *type_mem)
 
   switch (INTUSE(dwarf_tag) (die))
     {
-    case DW_TAG_typedef:
     case DW_TAG_subrange_type:
       return aggregate_size (get_type (die, &attr_mem, type_mem),
 			     size, type_mem); /* Tail call.  */
@@ -225,6 +229,12 @@ dwarf_aggregate_size (die, size)
      Dwarf_Word *size;
 {
   Dwarf_Die type_mem;
+
+  if (INTUSE (dwarf_peel_type) (die, die) != 0)
+    return -1;
+
   return aggregate_size (die, size, &type_mem);
 }
 INTDEF (dwarf_aggregate_size)
+OLD_VERSION (dwarf_aggregate_size, ELFUTILS_0.144)
+NEW_VERSION (dwarf_aggregate_size, ELFUTILS_0.161)
diff --git a/libdw/dwarf_peel_type.c b/libdw/dwarf_peel_type.c
new file mode 100644
index 0000000..a110bc5
--- /dev/null
+++ b/libdw/dwarf_peel_type.c
@@ -0,0 +1,74 @@
+/* Peel type aliases and qualifier tags from a type DIE.
+   Copyright (C) 2014 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 either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <dwarf.h>
+#include <string.h>
+
+
+int
+dwarf_peel_type (die, result)
+     Dwarf_Die *die;
+     Dwarf_Die *result;
+{
+  int tag;
+
+  /* Ignore previous errors.  */
+  if (die == NULL)
+    return -1;
+
+  *result = *die;
+  tag = INTUSE (dwarf_tag) (result);
+  while (tag == DW_TAG_typedef
+	 || tag == DW_TAG_const_type
+	 || tag == DW_TAG_volatile_type
+	 || tag == DW_TAG_restrict_type)
+    {
+      Dwarf_Attribute attr_mem;
+      Dwarf_Attribute *attr = INTUSE (dwarf_attr_integrate) (die, DW_AT_type,
+							     &attr_mem);
+      if (attr == NULL)
+	return 1;
+
+      result = INTUSE (dwarf_formref_die) (attr, result);
+      if (result == NULL)
+	return -1;
+
+      tag = INTUSE (dwarf_tag) (result);
+    }
+
+  if (tag == DW_TAG_invalid)
+    return -1;
+
+  return 0;
+}
+INTDEF(dwarf_peel_type)
diff --git a/libdw/libdw.h b/libdw/libdw.h
index 196d54a..248265e 100644
--- a/libdw/libdw.h
+++ b/libdw/libdw.h
@@ -398,6 +398,17 @@ extern int dwarf_child (Dwarf_Die *die, Dwarf_Die *result)
 extern int dwarf_siblingof (Dwarf_Die *die, Dwarf_Die *result)
      __nonnull_attribute__ (2);
 
+/* For type aliases (typedef) and qualifier (const, volatile,
+   restrict) tags follow the DW_AT_type attribute (recursively) and
+   return the underlying base, user-defined, reference or pointer
+   type.  Returns 0 when RESULT contains a base, user-defined,
+   reference or pointer type (possibly equal to the given DIE).
+   Returns 1 when RESULT contains a type alias or qualifier that
+   couldn't be peeled further (it doesn't have a DW_TAG_type
+   attribute).  Returns -1 when an error occured.  */
+extern int dwarf_peel_type (Dwarf_Die *die, Dwarf_Die *result)
+    __nonnull_attribute__ (2);
+
 /* Check whether the DIE has children.  */
 extern int dwarf_haschildren (Dwarf_Die *die) __nonnull_attribute__ (1);
 
diff --git a/libdw/libdw.map b/libdw/libdw.map
index 55bc537..0c0ea99 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -306,4 +306,14 @@ ELFUTILS_0.160 {
   global:
     dwarf_cu_getdwarf;
     dwarf_cu_die;
-} ELFUTILS_0.159;
\ No newline at end of file
+} ELFUTILS_0.159;
+
+ELFUTILS_0.161 {
+  global:
+    dwarf_peel_type;
+
+    # Replaced ELFUTILS_0.144 version.  Both versions point to the
+    # same implementation, but users of the new symbol version can
+    # presume that it uses dwarf_peel_type.
+    dwarf_aggregate_size;
+} ELFUTILS_0.160;
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index ce8a83d..9a903a3 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -690,6 +690,7 @@ INTDECL (dwarf_lowpc)
 INTDECL (dwarf_nextcu)
 INTDECL (dwarf_next_unit)
 INTDECL (dwarf_offdie)
+INTDECL (dwarf_peel_type)
 INTDECL (dwarf_ranges)
 INTDECL (dwarf_setalt)
 INTDECL (dwarf_siblingof)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 6b76248..5c06d23 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,9 @@
+2014-10-06  Mark Wielaard  <mjw@redhat.com>
+
+	* run-aggregate-size.sh: Add testfile-sizes3.o test case.
+	* testfile-sizes3.o.bz2: New test file.
+	* Makefile.am (EXTRA_DIST): Add testfile-sizes3.o.bz2.
+
 2014-10-02  Mark Wielaard  <mjw@redhat.com>
 
 	* run-deleted.sh: Unset VALGRIND_CMD before running deleted.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 1c4b2b1..09909d2 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -275,7 +275,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
 	     run-readelf-zdebug.sh testfile-debug.bz2 testfile-zdebug.bz2 \
 	     run-deleted.sh run-linkmap-cut.sh linkmap-cut-lib.so.bz2 \
 	     linkmap-cut.bz2 linkmap-cut.core.bz2 \
-	     run-aggregate-size.sh testfile-sizes1.o.bz2 testfile-sizes2.o.bz2
+	     run-aggregate-size.sh testfile-sizes1.o.bz2 testfile-sizes2.o.bz2 \
+	     testfile-sizes3.o.bz2
 
 if USE_VALGRIND
 valgrind_cmd='valgrind -q --error-exitcode=1 --run-libc-freeres=no'
diff --git a/tests/run-aggregate-size.sh b/tests/run-aggregate-size.sh
index 7d812a5..42b0742 100755
--- a/tests/run-aggregate-size.sh
+++ b/tests/run-aggregate-size.sh
@@ -38,7 +38,31 @@
 # gcc -g -c -o testfile-sizes1.o sizes.c
 # clang -g -c -o testfile-sizes2.o sizes.c
 
-testfiles testfile-sizes1.o testfile-sizes2.o
+# const char c;
+# volatile int i;
+# const volatile long l;
+#
+# void * restrict v;
+#
+# struct s
+# {
+#   const char *a;
+#   volatile int i;
+# } s;
+#
+# const char ca[16];
+# volatile int ia[32];
+# const volatile void * const volatile restrict va[64];
+# struct s sa[8];
+#
+# typedef const int foo;
+# typedef volatile foo bar;
+# foo f;
+# bar b;
+#
+# gcc -std=c99 -g -c -o testfile-sizes3.o sizes.c
+
+testfiles testfile-sizes1.o testfile-sizes2.o testfile-sizes3.o
 
 testrun_compare ${abs_builddir}/aggregate_size -e testfile-sizes1.o <<\EOF
 c size 1
@@ -64,4 +88,18 @@ va size 512
 sa size 128
 EOF
 
+testrun_compare ${abs_builddir}/aggregate_size -e testfile-sizes3.o <<\EOF
+c size 1
+i size 4
+l size 8
+v size 8
+s size 16
+ca size 16
+ia size 128
+va size 512
+sa size 128
+f size 4
+b size 4
+EOF
+
 exit 0
diff --git a/tests/testfile-sizes3.o.bz2 b/tests/testfile-sizes3.o.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..7fa6a8a529676bc8324d383c8d11f86c66ef453c
GIT binary patch
literal 1147
zcmV->1cduST4*^jL0KkKSxZ~zf&c_3|NsC0|L^bT_ka8SS{VQT-|)ggfXE^V2tr{{
zfPe%fFbvQGsyqn-n<EVnnrMl=Dm_mW@=w%{DWSbd>NI+XsA;u5Kn*nY9-4z>Lror_
z1JrFJL-eE6^hSh2YGI~{l5I58Q%_UUX{Jp8000000000000068OeO$Km;eOC3;+NC
zm=geu002w?00IU~CIC#B00hJg0001(699|=089V?0Fe<0o{}3)Q#55BQ+lVUX_HKW
z>S>{%4X83S7?_Me4K&f|84pt<^+tzP)-#f|y7q30foPkXqYxWfgEY8a>(~ESWfS6-
z(a)Ni+=gF-x(6*8ds7=!_fcc2kOBPJBU<GRQ?0tC?^CN&|5C!&5Nxl<*@ihk@!8vP6N
zb~9?QZ$X^t;U!#h5Gk76G$6+a)RjA#4E{7O(J7KWD9`F?U-H)H-g)ZA26UR~0D>Tw
z#ZeF;oL~!mc$lCHaf(a)Drt4cMyxPV_n1%SYA{*@Uz8m{Xo77Mc1ipRx|I%Gs-^K(S#
zz~LeuggzfHUyp-V(Bybt)#5L0rk*Fcl4m_=YRW}g1D3!>b4XIsTc#4pVGLTXT1b{C
zY;B`mlF~hPlCrSbNQO5skS=2lszO~R9%C1M(a)JC<r;>p&g7!T8HvC6bBViRaun7(O9
zMH*Q?m_SQ4nGFCoAne2jUmhiaU4g<%SiRPgJxp*QJ!Z6V-=k*4?&l$Mq#Nd}>3J!t
zfx`XPsYr$eHCW5YOOW$;<Uu(Mp?6|G-W*-ru}Ghjw5>|$B(a)q}qM(GTYNG+|LJ({_8
zb?fQ(KL3N(l{N!Fuwt=`l~6!h_jQGp+&2DQfA3p2e_{{Wqh*T+0t305Wg<};8-x;t
zy1Eb$FcdZ6tgC~fs4Li$X=7Hm$kLz{Vyi0BR^Tv8VMh)byfdjST0soqw3Uq0%@siW
zhg)D{cfrYaV$Ry29j-}_4KTE4FuSx2gziv|o=8Q_V$X13V#y?Tx__-HW3poW6C$fd
z(a)R9=!CQBj`C4z1vY#q@>WGYL(A=#;?K`$6H79)_yACnT8a*1<2g3nIX(a)5n|ABB$^!
z2F#TNRAR^FJ!$x(a)vp$$~3RP9v;)X!xUCK>tjRyltEBDzZBH@|);M+R^*Ec4{I0-W4
zgB{bwG2sl~4o$|I-(a)tg-b+`N9^GeVf(a)32um(kr174#XSZnKXtArwj{}267M#JLjb?
zBEnP>Sz`~{TP{nXOoJaxH!a1OYD%q#3i;{k(pI3vICDllLdrL&<q$UwX54S9jwIN(
zLr(a)Cl+-iX>A+{t8{qoj}gu_}I)ytfkiqQ~5BcQzLqo_fwvE6!VfF5U-qN=(h5<Hk}
z?>IlgqS=W8etiOryOLoxgk~01!GmL1C>KHinx!gA5J!N5gTbgIL$nc6oK%e13>g$>
z2FNzDZWI9%SIuBR+mE)BL>%;jojDHxDS-I|yTEbKl*(HQYg(19(a)laZxtTkWzypjKl
Nxgwk>NF}ZF!2m-C{KEhM

literal 0
HcmV?d00001

-- 
1.8.3.1


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