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 /libdw | |
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>
Diffstat (limited to 'libdw')
-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 |
7 files changed, 127 insertions, 4 deletions
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) |