diff options
author | Mark Wielaard <mjw@redhat.com> | 2014-10-06 22:00:16 +0200 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2014-11-05 14:31:33 +0100 |
commit | 3a36e8a26c32103ec2f8edda8bf212d6883970a2 (patch) | |
tree | 0b76055b98d20af626f04022d4987a4de8b812a3 | |
parent | 564cfbe20beb077c3441400c4b0c406478043d76 (diff) | |
download | android_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-- | ChangeLog | 4 | ||||
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | backends/ChangeLog | 5 | ||||
-rw-r--r-- | backends/libebl_CPU.h | 22 | ||||
-rw-r--r-- | libdw/ChangeLog | 10 | ||||
-rw-r--r-- | libdw/Makefile.am | 2 | ||||
-rw-r--r-- | libdw/dwarf_aggregate_size.c | 14 | ||||
-rw-r--r-- | libdw/dwarf_peel_type.c | 74 | ||||
-rw-r--r-- | libdw/libdw.h | 18 | ||||
-rw-r--r-- | libdw/libdw.map | 12 | ||||
-rw-r--r-- | libdw/libdwP.h | 1 | ||||
-rw-r--r-- | tests/ChangeLog | 6 | ||||
-rw-r--r-- | tests/Makefile.am | 3 | ||||
-rwxr-xr-x | tests/run-aggregate-size.sh | 40 | ||||
-rw-r--r-- | tests/testfile-sizes3.o.bz2 | bin | 0 -> 1147 bytes |
15 files changed, 192 insertions, 24 deletions
@@ -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. @@ -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 Binary files differnew file mode 100644 index 00000000..7fa6a8a5 --- /dev/null +++ b/tests/testfile-sizes3.o.bz2 |