Currently storing a lot of Dwarf_Dies might be inefficient since it
costs a lot of memory since the sizeof (Dwarf_Die) == 32 bytes on 64bit
arches. You can try storing just the Dwarf_Off from dwarf_dieoffset.
Which is just 8 bytes. But then you have to keep track of whether to
call dwarf_dieoffset, if the Dwarf_Die came from the main .debug_info,
or call dwarf_dieoffset_types, if it came from .debug_types. And you'll
have to keep track of whether it came from the main Dwarf or the alt
Dwarf (dwz multi file). With DWARF5 or GNU DebugFission split-dwarf
you will also need to know which split Dwarf file the original DIE
came from.
A Dwarf_Die consists of an addr pointer where the actual DIE data
comes from, a CU pointer that provides context (and has a pointer
to the Dwarf file the Die is associated with) and a (cached)
Dwarf_Abbrev pointer that is initialized when the Dwarf_Die is
first read and describes how to interpret the DIE data.
libdw already keeps track of the data pointers (sections) of a
Dwarf file and given an offset it can already reconstruct the
other Dwarf_Die fields. So this patch introduces dwarf_die_addr_die.
Given a Dwarf_Die addr dwarf_die_addr_die returns a (reconstructed)
Dwarf_Die, or NULL if the given addr didn't come from a valid
Dwarf_Die. In particular it will make sure that the correct Dwarf_CU
pointer is set for the Dwarf_Die, the Dwarf_Abbrev pointer will not
be set up yet (it will only be once the Dwarf_Die is used to read
attributes, children or siblings).
This functions can be used to keep a reference to a Dwarf_Die which
you want to refer to later. The addr, and the result of this function,
is only valid while the associated Dwarf is valid.
Since libdw already had to lookup the Dwarf_CU given an offset, this
function is as efficient as dwarf_dieoffset (or dwarf_dieoffset_types)
without having to know the original origin of the Dwarf_Die. It will
search both the .debug_info and .debug_types data sections from both
the main Dwarf or the alt Dwarf file. Once split dwarf support is added
it will also look in any split dwarf .dwo (or the .dwp) file.
The only limitation, compared to using a Dwarf_Off and dwarf_dieoffset,
is that it only works during runtime while the main Dwarf object is
valid (till dwarf_end has been called on it).
Signed-off-by: Mark Wielaard
---
libdw/ChangeLog | 9 +++
libdw/Makefile.am | 3 +-
libdw/dwarf_die_addr_die.c | 58 ++
libdw/libdw.h | 12 +++
libdw/libdw.map | 5 ++
libdw/libdwP.h | 4 +
libdw/libdw_findcu.c| 35 +++-
tests/ChangeLog | 9 +++
tests/Makefile.am | 9 ++-
tests/dwarf-die-addr-die.c | 172
tests/run-dwarf-die-addr-die.sh | 38 +
11 files changed, 349 insertions(+), 5 deletions(-)
create mode 100644 libdw/dwarf_die_addr_die.c
create mode 100644 tests/dwarf-die-addr-die.c
create mode 100755 tests/run-dwarf-die-addr-die.sh
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index cb5e61a..37edcd7 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,12 @@
+2018-01-25 Mark Wielaard
+
+ * Makefile.am (libdw_a_SOURCES): Add dwarf_die_addr_die.c.
+ * dwarf_die_addr_die.c: New file.
+ * libdw.h (dwarf_die_addr_die): New function declaration.
+ * libdw.map (ELFUTILS_0.171): New section with dwarf_die_addr_die.
+ * libdwP.h (__libdw_findcu_addr): New internal function declaration.
+ * libdw_findcu.c (__libdw_findcu_addr): New internal function.
+
2018-01-22 Mark Wielaard
* Makefile.am (AM_CPPFLAGS): Add -I libdwelf.
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index 8545b5b..b1da440 100644
--- a/libdw/Makefile.am
+++ b/libdw/Makefile.am
@@ -89,7 +89,8 @@ 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_peel_type.c dwarf_default_lower_bound.c
+ dwarf_cu_die.c dwarf_peel_type.c dwarf_default_lower_bound.c \
+ dwarf_die_addr_die.c
if MAINTAINER_MODE
BUILT_SOURCES = $(srcdir)/known-dwarf.h
diff --git a/libdw/dwarf_die_addr_die.c b/libdw/dwarf_die_addr_die.c
new file mode 100644
index 000..02d63b7
--- /dev/null
+++ b/libdw/dwarf_die_addr_die.c
@@ -0,0 +1,58 @@
+/* Return offset of DIE.
+ Copyright (C) 2018 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
+