summaryrefslogtreecommitdiffstats
path: root/libdw
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 /libdw
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>
Diffstat (limited to 'libdw')
-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
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)