summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2014-10-06 22:00:16 +0200
committerMark Wielaard <mjw@redhat.com>2014-11-05 14:31:33 +0100
commit3a36e8a26c32103ec2f8edda8bf212d6883970a2 (patch)
tree0b76055b98d20af626f04022d4987a4de8b812a3
parent564cfbe20beb077c3441400c4b0c406478043d76 (diff)
downloadandroid_external_elfutils-3a36e8a26c32103ec2f8edda8bf212d6883970a2.tar.gz
android_external_elfutils-3a36e8a26c32103ec2f8edda8bf212d6883970a2.tar.bz2
android_external_elfutils-3a36e8a26c32103ec2f8edda8bf212d6883970a2.zip
libdw: Add dwarf_peel_type. Use it in dwarf_aggregate_size.
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>
-rw-r--r--ChangeLog4
-rw-r--r--NEWS5
-rw-r--r--backends/ChangeLog5
-rw-r--r--backends/libebl_CPU.h22
-rw-r--r--libdw/ChangeLog10
-rw-r--r--libdw/Makefile.am2
-rw-r--r--libdw/dwarf_aggregate_size.c14
-rw-r--r--libdw/dwarf_peel_type.c74
-rw-r--r--libdw/libdw.h18
-rw-r--r--libdw/libdw.map12
-rw-r--r--libdw/libdwP.h1
-rw-r--r--tests/ChangeLog6
-rw-r--r--tests/Makefile.am3
-rwxr-xr-xtests/run-aggregate-size.sh40
-rw-r--r--tests/testfile-sizes3.o.bz2bin0 -> 1147 bytes
15 files changed, 192 insertions, 24 deletions
diff --git a/ChangeLog b/ChangeLog
index 82779324..0947608d 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 aceb3e33..130856ea 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 a335b207..82a2bf15 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 fa0d4f2d..ef2b922b 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 89b2735f..82cdd883 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-15 Petr Machata <pmachata@redhat.com>
* libdwP.h (struct Dwarf_Files_s.cu): Drop field.
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index 2e42a376..859af4d4 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 5d23541e..1666e240 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 00000000..a110bc54
--- /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 196d54ae..30364ba1 100644
--- a/libdw/libdw.h
+++ b/libdw/libdw.h
@@ -398,6 +398,24 @@ 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 and qualifier type DIEs follow the DW_AT_type
+ attribute (recursively) and return the underlying type Dwarf_Die.
+ Returns 0 when RESULT contains a Dwarf_Die (possibly equal to the
+ given DIE) that isn't a type alias or qualifier type. Returns 1
+ when RESULT contains a type alias or qualifier Dwarf_Die that
+ couldn't be peeled further (it doesn't have a DW_TAG_type
+ attribute). Returns -1 when an error occured.
+
+ The current DWARF specification defines one type alias tag
+ (DW_TAG_typedef) and three qualifier type tags (DW_TAG_const_type,
+ DW_TAG_volatile_type, DW_TAG_restrict_type). A future version of
+ this function might peel other alias or qualifier type tags if a
+ future DWARF version or GNU extension defines other type aliases or
+ qualifier type tags that don't modify or change the structural
+ layout of the underlying type. */
+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 55bc5371..0c0ea997 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 c0f3741c..f0ed316f 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -689,6 +689,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 6b762488..5c06d236 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 1c4b2b19..09909d28 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 7d812a5f..42b0742b 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 00000000..7fa6a8a5
--- /dev/null
+++ b/tests/testfile-sizes3.o.bz2
Binary files differ