[PATCH 1/2] Enable C++
by Petr Machata
Hi there,
I think this was mostly agreed on. The change since last time is that
we pass -std=gnu++98 when testing C++ compiler existence, for
correctness' sake.
Thanks,
Petr
--- 8< -----------------------------------------------------------
- Detect C++ compiler in configure, add supporting infrastructure to
eu.am.
Signed-off-by: Petr Machata <pmachata(a)redhat.com>
---
ChangeLog | 4 ++++
config/ChangeLog | 6 ++++++
config/eu.am | 21 ++++++++++++++++++++-
configure.ac | 28 ++++++++++++++++++++++++++++
4 files changed, 58 insertions(+), 1 deletion(-)
diff --git a/ChangeLog b/ChangeLog
index 5c8e1c2..65c3ef5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2015-04-14 Petr Machata <pmachata(a)redhat.com>
+
+ * configure.ac (HAVE_CXX): New conditional.
+
2015-03-13 Mark Wielaard <mjw(a)redhat.com>
* configure.ac (ac_cv_c99): Add explicit return.
diff --git a/config/ChangeLog b/config/ChangeLog
index 586ebb0..936f62d 100644
--- a/config/ChangeLog
+++ b/config/ChangeLog
@@ -1,3 +1,9 @@
+2015-04-14 Petr Machata <pmachata(a)redhat.com>
+
+ * eu.am (AM_CXXFLAGS, CXXCOMPILE.os): New variables.
+ (%.os: %.c %.o): Create dep-file subdirectory if necessary.
+ (%.os: %.cc %.o): New rule.
+
2015-03-18 Petr Machata <pmachata(a)redhat.com>
* known-dwarf.awk (comment): Drop all uses of this variable.
diff --git a/config/eu.am b/config/eu.am
index faf8add..f1d290b 100644
--- a/config/eu.am
+++ b/config/eu.am
@@ -1,6 +1,6 @@
## Common automake fragments for elfutils subdirectory makefiles.
##
-## Copyright (C) 2010, 2014 Red Hat, Inc.
+## Copyright (C) 2010, 2014, 2015 Red Hat, Inc.
##
## This file is part of elfutils.
##
@@ -35,11 +35,17 @@ AM_CFLAGS = -std=gnu99 -Wall -Wshadow -Wformat=2 \
$(if $($(*F)_no_Werror),,-Werror) \
$(if $($(*F)_no_Wunused),,-Wunused -Wextra) \
$($(*F)_CFLAGS)
+AM_CXXFLAGS = -std=gnu++98 -Wall -Wshadow -Wformat=2 \
+ $(if $($(*F)_no_Werror),,-Werror) \
+ $(if $($(*F)_no_Wunused),,-Wunused -Wextra) \
+ $($(*F)_CXXFLAGS)
COMPILE.os = $(filter-out -fprofile-arcs -ftest-coverage, $(COMPILE))
+CXXCOMPILE.os = $(filter-out -fprofile-arcs -ftest-coverage, $(CXXCOMPILE))
%.os: %.c %.o
if AMDEP
+ test -d $(DEPDIR)/$(*D) || mkdir $(DEPDIR)/$(*D)
if $(COMPILE.os) -c -o $@ -fpic -DPIC -DSHARED -MT $@ -MD -MP \
-MF "$(DEPDIR)/$*.Tpo" `test -f '$<' || echo '$(srcdir)/'`$<; \
then cat "$(DEPDIR)/$*.Tpo" >> "$(DEPDIR)/$*.Po"; \
@@ -50,6 +56,19 @@ else
$(COMPILE.os) -c -o $@ -fpic -DPIC -DSHARED $<
endif
+%.os: %.cc %.o
+if AMDEP
+ test -d $(DEPDIR)/$(*D) || mkdir $(DEPDIR)/$(*D)
+ if $(CXXCOMPILE.os) -c -o $@ -fpic -DPIC -DSHARED -MT $@ -MD -MP \
+ -MF "$(DEPDIR)/$*.Tpo" `test -f '$<' || echo '$(srcdir)/'`$<; \
+ then cat "$(DEPDIR)/$*.Tpo" >> "$(DEPDIR)/$*.Po"; \
+ rm -f "$(DEPDIR)/$*.Tpo"; \
+ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+ fi
+else
+ $(CXXCOMPILE.os) -c -o $@ -fpic -DPIC -DSHARED $<
+endif
+
CLEANFILES = *.gcno *.gcda
textrel_msg = echo "WARNING: TEXTREL found in '$@'"
diff --git a/configure.ac b/configure.ac
index c4b818d..6d1df60 100644
--- a/configure.ac
+++ b/configure.ac
@@ -71,6 +71,7 @@ AS_IF([test "$use_locks" = yes],
AH_TEMPLATE([USE_LOCKS], [Defined if libraries should be thread-safe.])
AC_PROG_CC
+AC_PROG_CXX
AC_PROG_RANLIB
AC_PROG_YACC
AM_PROG_LEX
@@ -89,6 +90,33 @@ CFLAGS="$old_CFLAGS"])
AS_IF([test "x$ac_cv_c99" != xyes],
AC_MSG_ERROR([gcc with C99 support required]))
+AC_LANG_PUSH([C++])
+
+# Above, we check for C++ compiler. However even if none is available,
+# CXX is set to a non-empty value. So we need to figure out whether a
+# C++ compiler is actually available.
+
+# We in fact use -std=gnu++98. Check that the compiler supports this.
+SAVE_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS -std=gnu++98"
+
+AC_CACHE_CHECK([for C++ compiler that supports -std=gnu++98],
+ ac_cv_cxx_works,
+[AC_COMPILE_IFELSE([AC_LANG_SOURCE([dnl
+struct foo {
+ int i;
+ explicit foo () : i (0) {}
+ virtual ~foo () {}
+};
+
+struct A { int i; int j; } a = {.i = 1, .j = 2};
+])], ac_cv_cxx_works=yes, ac_cv_cxx_works=no)])
+
+CXXFLAGS="$SAVE_CXXFLAGS"
+AC_LANG_POP()
+
+AM_CONDITIONAL(HAVE_CXX, test "$ac_cv_cxx_works" = yes)
+
AC_CACHE_CHECK([for __thread support], ac_cv_tls, [dnl
# Use the same flags that we use for our DSOs, so the test is representative.
# Some old compiler/linker/libc combinations fail some ways and not others.
--
2.1.0
9 years
[PATCH] src: Remove __DATE__ from internal error messages.
by Mark Wielaard
The date didn't really add much information (it is the day on which the
code happened to be compiled) and it prevents creating reproducible builds.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 7 +++++++
src/nm.c | 6 +++---
src/objdump.c | 6 +++---
src/size.c | 6 +++---
src/strip.c | 6 +++---
5 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index 858d0f7..c8ddff6 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
+2015-03-14 Mark Wielaard <mjw(a)redhat.com>
+
+ * nm.c (INTERNAL_ERROR): Remove __DATE__.
+ * objdump.c (INTERNAL_ERROR): Likewise.
+ * size.c (INTERNAL_ERROR): Likewise.
+ * strip.c (INTERNAL_ERROR): Likewise.
+
2015-03-18 Petr Machata <pmachata(a)redhat.com>
* readelf.c (dwarf_tag_string, dwarf_attr_string)
diff --git a/src/nm.c b/src/nm.c
index 915153f..67fb4c2 100644
--- a/src/nm.c
+++ b/src/nm.c
@@ -1,5 +1,5 @@
/* Print symbol information from ELF file in human-readable form.
- Copyright (C) 2000-2008, 2009, 2011, 2012, 2014 Red Hat, Inc.
+ Copyright (C) 2000-2008, 2009, 2011, 2012, 2014, 2015 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper(a)redhat.com>, 2000.
@@ -137,8 +137,8 @@ static int handle_elf (Elf *elf, const char *prefix, const char *fname,
#define INTERNAL_ERROR(fname) \
- error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"), \
- fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1))
+ error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s): %s"), \
+ fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1))
/* Internal representation of symbols. */
diff --git a/src/objdump.c b/src/objdump.c
index 87290cc..b689024 100644
--- a/src/objdump.c
+++ b/src/objdump.c
@@ -1,5 +1,5 @@
/* Print information from ELF file in human-readable form.
- Copyright (C) 2005, 2006, 2007, 2009, 2011, 2012, 2014 Red Hat, Inc.
+ Copyright (C) 2005, 2006, 2007, 2009, 2011, 2012, 2014, 2015 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper(a)redhat.com>, 2005.
@@ -101,8 +101,8 @@ static int handle_elf (Elf *elf, const char *prefix, const char *fname,
#define INTERNAL_ERROR(fname) \
- error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"), \
- fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1))
+ error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s): %s"), \
+ fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1))
/* List of sections which should be used. */
diff --git a/src/size.c b/src/size.c
index 0e7e41e..0ec1139 100644
--- a/src/size.c
+++ b/src/size.c
@@ -1,5 +1,5 @@
/* Print size information from ELF file.
- Copyright (C) 2000-2007,2009,2012,2014 Red Hat, Inc.
+ Copyright (C) 2000-2007,2009,2012,2014,2015 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper(a)redhat.com>, 2000.
@@ -106,8 +106,8 @@ static void handle_elf (Elf *elf, const char *fullname, const char *fname);
static void show_bsd_totals (void);
#define INTERNAL_ERROR(fname) \
- error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"), \
- fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1))
+ error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s): %s"), \
+ fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1))
/* User-selectable options. */
diff --git a/src/strip.c b/src/strip.c
index 2b21799..c003647 100644
--- a/src/strip.c
+++ b/src/strip.c
@@ -1,5 +1,5 @@
/* Discard section not used at runtime from object files.
- Copyright (C) 2000-2012, 2014 Red Hat, Inc.
+ Copyright (C) 2000-2012, 2014, 2015 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper(a)redhat.com>, 2000.
@@ -117,8 +117,8 @@ static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
struct timeval tvp[2]);
#define INTERNAL_ERROR(fname) \
- error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"), \
- fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1))
+ error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s): %s"), \
+ fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1))
/* Name of the output file. */
--
1.8.3.1
9 years
[PATCH] configure: Add explicit checks for all GNU99 extensions used.
by Mark Wielaard
Some compilers (clang) claim to support -std=gnu99 but don't actually
implement all extensions we use in the code. Producing really hard to
parse errors. Add explicit checks for some of the other language
extensions we use, Nested Functions and Arrays of Variable Length,
to the configure check to catch such issues early.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
ChangeLog | 5 +++++
configure.ac | 29 ++++++++++++++++++++++++++---
2 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 5c8e1c2..9a0a82d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2015-04-14 Mark Wielaard <mjw(a)redhat.com>
+
+ * configure.ac (ac_cv_c99): Add explicit checks for all GNU99
+ extensions used.
+
2015-03-13 Mark Wielaard <mjw(a)redhat.com>
* configure.ac (ac_cv_c99): Add explicit return.
diff --git a/configure.ac b/configure.ac
index c4b818d..ed2c964 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,15 +79,38 @@ m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
AC_CHECK_TOOL([READELF], [readelf])
AC_CHECK_TOOL([NM], [nm])
-AC_CACHE_CHECK([for gcc with C99 support], ac_cv_c99, [dnl
+# We use -std=gnu99 but have explicit checks for some language constructs
+# and GNU extensions since some compilers claim GNU99 support, but don't
+# really support all language extensions. In particular we need
+# Mixed Declarations and Code
+# https://gcc.gnu.org/onlinedocs/gcc/Mixed-Declarations.html
+# Nested Functions
+# https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html
+# Arrays of Variable Length
+# https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html
+AC_CACHE_CHECK([for gcc with GNU99 support], ac_cv_c99, [dnl
old_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -std=gnu99"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([dnl
-int foo (int a) { for (int i = 0; i < a; ++i) if (i % 4) break; int s = a; return s;}])],
+int foo (int a)
+{
+ for (int i = 0; i < a; ++i) if (i % 4) break; int s = a; return s;
+}
+
+double bar (double a, double b)
+{
+ double square (double z) { return z * z; }
+ return square (a) + square (b);
+}
+
+void baz (int n)
+{
+ struct S { int x[[n]]; };
+}])],
ac_cv_c99=yes, ac_cv_c99=no)
CFLAGS="$old_CFLAGS"])
AS_IF([test "x$ac_cv_c99" != xyes],
- AC_MSG_ERROR([gcc with C99 support required]))
+ AC_MSG_ERROR([gcc with GNU99 support required]))
AC_CACHE_CHECK([for __thread support], ac_cv_tls, [dnl
# Use the same flags that we use for our DSOs, so the test is representative.
--
1.8.3.1
9 years
[PATCH] libdwfl: Correct off-by-one check in segment.c insert.
by Mark Wielaard
Caught by running run-backtrace-core-x32.sh under valgrind.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdwfl/ChangeLog | 4 ++++
libdwfl/segment.c | 5 +++--
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index d40dbae..7664edc 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,7 @@
+2015-04-02 Mark Wielaard <mjw(a)redhat.com>
+
+ * segment.c (insert): Check correct number of lookup_elts.
+
2015-01-26 Mark Wielaard <mjw(a)redhat.com>
* dwfl_module_getdwarf.c (find_symtab): Explicitly clear symdata,
diff --git a/libdwfl/segment.c b/libdwfl/segment.c
index 9276917..2983cf2 100644
--- a/libdwfl/segment.c
+++ b/libdwfl/segment.c
@@ -1,5 +1,5 @@
/* Manage address space lookup table for libdwfl.
- Copyright (C) 2008, 2009, 2010, 2013 Red Hat, Inc.
+ Copyright (C) 2008, 2009, 2010, 2013, 2015 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -50,7 +50,8 @@ static bool
insert (Dwfl *dwfl, size_t i, GElf_Addr start, GElf_Addr end, int segndx)
{
bool need_start = (i == 0 || dwfl->lookup_addr[i - 1] != start);
- bool need_end = (i >= dwfl->lookup_elts || dwfl->lookup_addr[i + 1] != end);
+ bool need_end = (i + 1 >= dwfl->lookup_elts
+ || dwfl->lookup_addr[i + 1] != end);
size_t need = need_start + need_end;
if (need == 0)
return false;
--
2.1.0
9 years
[PATCH 2/2] Add C++ iterators
by Petr Machata
Hello,
as requested by Mark, I made the iterator interfaces ABI stable, so that
they can be safely used on API boundaries of third-party libraries.
This patch should also include all the other points that we talked about
(from the top of my head: returning reference from operator++, dropping
of offset member function, change from cu_iterator to unit_iterator),
except for exceptions, which are still std::runtime_error.
This adds a new library, libdwpp, which implements these interfaces.
The interfaces themselves are fully pimpl'd. Actual class layout
etc. is fully internal detail--on the outside we publish one pointer
field. Due to this, the iterators are more heavyweight, involving a
dynamic allocation for each instance, and PLT call for each operation,
but on the other hand, virtually no ABI breakage is possible.
Symbols are versioned. This ties us closely to the GCC ABI, but I think
everybody uses Itanium ABI these days anyway. This also means that if
there should be a change in behavior that would constitute an ABI
breakage, it can be mitigated the same way as with C symbols.
I hid many symbols as well. Namely the private constructors are not
exported at all, and I have also hidden the not-in-charge constructor
and destructor variants, because those should only come into play when
the iterators are inherited from, which they are not designed for.
The test case was extended to at least use each of the iterators, albeit
in somewhat limited manner. dwgrep, when adapted, builds and passes
test suite fine as well.
Thanks,
Petr
--- 8< ---------------------------------------------------------------
- Add unit_iterator, child_iterator, die_tree_iterator and
attr_iterator for libdw, and dwfl_module_iterator for libdwfl.
- The code is shipped in a new library called libdwpp with versioned
symbols.
Signed-off-by: Petr Machata <pmachata(a)redhat.com>
---
ChangeLog | 4 +
NEWS | 5 +-
libdw/ChangeLog | 21 ++++
libdw/Makefile.am | 62 ++++++++-
libdw/c++/attr_iterator.cc | 172 +++++++++++++++++++++++++
libdw/c++/child_iterator.cc | 143 +++++++++++++++++++++
libdw/c++/die_tree_iterator.cc | 213 +++++++++++++++++++++++++++++++
libdw/c++/libdw | 245 ++++++++++++++++++++++++++++++++++++
libdw/c++/libdwP.hh | 88 +++++++++++++
libdw/c++/unit_iterator.cc | 204 ++++++++++++++++++++++++++++++
libdw/libdwpp.map | 199 +++++++++++++++++++++++++++++
libdwfl/ChangeLog | 13 ++
libdwfl/Makefile.am | 33 ++++-
libdwfl/c++/dwfl_module_iterator.cc | 154 +++++++++++++++++++++++
libdwfl/c++/libdwfl | 70 +++++++++++
libdwfl/c++/libdwflP.hh | 44 +++++++
tests/ChangeLog | 7 ++
tests/Makefile.am | 12 +-
tests/run-test-iterators.sh | 52 ++++++++
tests/test-iterators.cc | 87 +++++++++++++
20 files changed, 1820 insertions(+), 8 deletions(-)
create mode 100644 libdw/c++/attr_iterator.cc
create mode 100644 libdw/c++/child_iterator.cc
create mode 100644 libdw/c++/die_tree_iterator.cc
create mode 100644 libdw/c++/libdw
create mode 100644 libdw/c++/libdwP.hh
create mode 100644 libdw/c++/unit_iterator.cc
create mode 100644 libdw/libdwpp.map
create mode 100644 libdwfl/c++/dwfl_module_iterator.cc
create mode 100644 libdwfl/c++/libdwfl
create mode 100644 libdwfl/c++/libdwflP.hh
create mode 100755 tests/run-test-iterators.sh
create mode 100644 tests/test-iterators.cc
diff --git a/ChangeLog b/ChangeLog
index 6c6f216..99c2450 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2015-04-03 Petr Machata <pmachata(a)redhat.com>
+
+ * NEWS: Mention <elfutils/libdw>, <elfutils/libdwfl>, and libdwpp.
+
2015-03-18 Petr Machata <pmachata(a)redhat.com>
* configure.ac (HAVE_CXX): New conditional.
diff --git a/NEWS b/NEWS
index 60aa995..02f8691 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,9 @@
Version 0.162
-libdw: Install new header elfutils/known-dwarf.h.
+libdw: Install new headers elfutils/known-dwarf.h, elfutils/libdw.
+libdwfl: Install new header elfutils/libdwfl.
+libdwpp: New library, contains the code for <elfutils/libdw> and
+ <elfutils/libdwfl> C++ interfaces.
Version 0.161
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 4fb4763..30bb80c 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -7,6 +7,27 @@
of white-listing valid tags.
* dwarf_getsrclines.c (dwarf_getsrclines.c): Likewise.
+2015-03-17 Petr Machata <pmachata(a)redhat.com>
+
+ * c++: New directory.
+ * c++/libdw, c++/libdwP.hh: New header files.
+ * libdwpp.map: New version script file.
+ * c++/attr_iterator.cc, c++/child_iterator.cc: New files.
+ * c++/die_tree_iterator.cc, c++/unit_iterator.cc: Likewise.
+ * Makefile.am (AUTOMAKE_OPTIONS): New variable.
+ [HAVE_CXX] (lib_LIBRARIES): Add libdwpp.a.
+ [HAVE_CXX] (noinst_LIBRARIES): Add libdwpp_pic.a.
+ [HAVE_CXX] (pkginclude_HEADERS): Add c++/libdw.
+ [HAVE_CXX] (libdwpp_a_SOURCES, libdwpp_so_SOURCES): New variables.
+ [HAVE_CXX] (libdwpp_pic_a_SOURCES, am_libdwpp_pic_a_OBJECTS): Likewise.
+ [HAVE_CXX] (libdwpp.so$(EXEEXT)): New rule.
+ (INSTALL_DEPS): New variable, contains libdwpp.so if HAVE_CXX.
+ (install): Depend on $(INSTALL_DEPS).
+ [HAVE_CXX] (install): Install libdwpp.so et.al.
+ [HAVE_CXX] (uninstall): Uninstall them.
+ (EXTRA_DIST): Add libdwpp.map.
+ (MOSTLYCLEANFILES): Add libdwpp-related files.
+
2015-03-18 Petr Machata <pmachata(a)redhat.com>
* Makefile.am (pkginclude_HEADERS): Add known-dwarf.h.
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index 272289c..8f43e76 100644
--- a/libdw/Makefile.am
+++ b/libdw/Makefile.am
@@ -1,6 +1,6 @@
## Process this file with automake to create Makefile.in
##
-## Copyright (C) 2002-2010, 2012, 2014 Red Hat, Inc.
+## Copyright (C) 2002-2010, 2012, 2014, 2015 Red Hat, Inc.
## This file is part of elfutils.
##
## This file is free software; you can redistribute it and/or modify
@@ -34,12 +34,26 @@ endif
AM_CPPFLAGS += -I$(srcdir)/../libelf
VERSION = 1
+# For c++/ subdir.
+AUTOMAKE_OPTIONS = subdir-objects
+
lib_LIBRARIES = libdw.a
+if HAVE_CXX
+lib_LIBRARIES += libdwpp.a
+endif
+
noinst_LIBRARIES = libdw_pic.a
+if HAVE_CXX
+noinst_LIBRARIES += libdwpp_pic.a
+endif
+
noinst_PROGRAMS = $(noinst_LIBRARIES:_pic.a=.so)
include_HEADERS = dwarf.h
pkginclude_HEADERS = libdw.h known-dwarf.h
+if HAVE_CXX
+pkginclude_HEADERS += c++/libdw
+endif
libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
dwarf_getpubnames.c dwarf_getabbrev.c dwarf_tag.c \
@@ -91,6 +105,11 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
dwarf_getalt.c dwarf_setalt.c dwarf_cu_getdwarf.c \
dwarf_cu_die.c dwarf_peel_type.c
+if HAVE_CXX
+libdwpp_a_SOURCES = c++/unit_iterator.cc c++/die_tree_iterator.cc \
+ c++/child_iterator.cc c++/attr_iterator.cc
+endif
+
if MAINTAINER_MODE
BUILT_SOURCES = $(srcdir)/known-dwarf.h
MAINTAINERCLEANFILES = $(srcdir)/known-dwarf.h
@@ -102,6 +121,11 @@ endif
libdw_pic_a_SOURCES =
am_libdw_pic_a_OBJECTS = $(libdw_a_SOURCES:.c=.os)
+if HAVE_CXX
+libdwpp_pic_a_SOURCES =
+am_libdwpp_pic_a_OBJECTS = $(libdwpp_a_SOURCES:.cc=.os)
+endif
+
libdw_so_SOURCES =
libdw.so$(EXEEXT): $(srcdir)/libdw.map libdw_pic.a ../libdwelf/libdwelf_pic.a \
../libdwfl/libdwfl_pic.a ../libebl/libebl.a \
@@ -116,16 +140,45 @@ libdw.so$(EXEEXT): $(srcdir)/libdw.map libdw_pic.a ../libdwelf/libdwelf_pic.a \
@$(textrel_check)
ln -fs $@ $@.$(VERSION)
-install: install-am libdw.so
+if HAVE_CXX
+libdwpp_so_SOURCES =
+libdwpp.so$(EXEEXT): $(srcdir)/libdwpp.map libdwpp_pic.a ../libdwfl/libdwflpp_pic.a \
+ libdw.so$(EXEEXT)
+ $(CXXLINK) -shared -o $@ -Wl,--soname,$@.$(VERSION),-z,defs \
+ -Wl,--enable-new-dtags \
+ -Wl,--version-script,$<,--no-undefined \
+ -Wl,--whole-archive $(filter-out $<,$^) -Wl,--no-whole-archive\
+ libdw.so$(EXEEXT)
+ @$(textrel_check)
+ ln -fs $@ $@.$(VERSION)
+endif
+
+if HAVE_CXX
+INSTALL_DEPS = libdwpp.so
+else
+INSTALL_DEPS =
+endif
+
+install: install-am libdw.so $(INSTALL_DEPS)
$(mkinstalldirs) $(DESTDIR)$(libdir)
$(INSTALL_PROGRAM) libdw.so $(DESTDIR)$(libdir)/libdw-$(PACKAGE_VERSION).so
ln -fs libdw-$(PACKAGE_VERSION).so $(DESTDIR)$(libdir)/libdw.so.$(VERSION)
ln -fs libdw.so.$(VERSION) $(DESTDIR)$(libdir)/libdw.so
+if HAVE_CXX
+ $(INSTALL_PROGRAM) libdwpp.so $(DESTDIR)$(libdir)/libdwpp-$(PACKAGE_VERSION).so
+ ln -fs libdwpp-$(PACKAGE_VERSION).so $(DESTDIR)$(libdir)/libdwpp.so.$(VERSION)
+ ln -fs libdwpp.so.$(VERSION) $(DESTDIR)$(libdir)/libdwpp.so
+endif
uninstall: uninstall-am
rm -f $(DESTDIR)$(libdir)/libdw-$(PACKAGE_VERSION).so
rm -f $(DESTDIR)$(libdir)/libdw.so.$(VERSION)
rm -f $(DESTDIR)$(libdir)/libdw.so
+if HAVE_CXX
+ rm -f $(DESTDIR)$(libdir)/libdwpp-$(PACKAGE_VERSION).so
+ rm -f $(DESTDIR)$(libdir)/libdwpp.so.$(VERSION)
+ rm -f $(DESTDIR)$(libdir)/libdwpp.so
+endif
rmdir --ignore-fail-on-non-empty $(DESTDIR)$(includedir)/elfutils
libdwfl_objects = $(shell $(AR) t ../libdwfl/libdwfl.a)
@@ -137,6 +190,7 @@ libdw_a_LIBADD += $(addprefix ../libdwelf/,$(libdwelf_objects))
noinst_HEADERS = libdwP.h memory-access.h dwarf_abbrev_hash.h \
dwarf_sig8_hash.h cfi.h encoded-value.h
-EXTRA_DIST = libdw.map
+EXTRA_DIST = libdw.map libdwpp.map
-MOSTLYCLEANFILES = $(am_libdw_pic_a_OBJECTS) libdw.so.$(VERSION)
+MOSTLYCLEANFILES = $(am_libdw_pic_a_OBJECTS) libdw.so.$(VERSION) \
+ $(am_libdwpp_pic_a_OBJECTS) libdwpp.so.$(VERSION)
diff --git a/libdw/c++/attr_iterator.cc b/libdw/c++/attr_iterator.cc
new file mode 100644
index 0000000..ade1b53
--- /dev/null
+++ b/libdw/c++/attr_iterator.cc
@@ -0,0 +1,172 @@
+/* -*-c++-*-
+ Copyright (C) 2009, 2010, 2011, 2012, 2014, 2015 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/>. */
+
+#include "libdw"
+#include "libdwP.hh"
+
+struct elfutils::attr_iterator::pimpl
+{
+ Dwarf_Die *m_die;
+ Dwarf_Attribute m_at;
+ ptrdiff_t m_offset;
+
+ struct cb_data
+ {
+ // The visited attribute.
+ Dwarf_Attribute *at;
+
+ // Whether this is second pass through the callback.
+ bool been;
+ };
+
+ static int
+ callback (Dwarf_Attribute *at, void *data)
+ {
+ cb_data *d = static_cast <cb_data *> (data);
+ if (d->been)
+ return DWARF_CB_ABORT;
+
+ *d->at = *at;
+ d->been = true;
+
+ // Do a second iteration to find the next offset.
+ return DWARF_CB_OK;
+ }
+
+ void
+ move ()
+ {
+ // If m_offset is already 1, we are done iterating.
+ if (m_offset == 1)
+ {
+ *this = pimpl ((ptrdiff_t) 1);
+ return;
+ }
+
+ cb_data data = {&m_at, false};
+ m_offset = dwarf_getattrs (m_die, &callback, &data, m_offset);
+ if (m_offset == -1)
+ throw_libdw ();
+ }
+
+ pimpl (ptrdiff_t offset)
+ : m_die (NULL)
+ , m_at ((Dwarf_Attribute) {0, 0, NULL, NULL})
+ , m_offset (offset)
+ {}
+
+ pimpl (Dwarf_Die *die)
+ : m_die (die)
+ , m_at ((Dwarf_Attribute) {0, 0, NULL, NULL})
+ , m_offset (0)
+ {
+ move ();
+ }
+
+ bool
+ operator== (pimpl const &other) const
+ {
+ return m_offset == other.m_offset
+ && m_at.code == other.m_at.code;
+ }
+};
+
+elfutils::attr_iterator::attr_iterator (ptrdiff_t offset)
+ : m_pimpl (new pimpl (offset))
+{}
+
+elfutils::attr_iterator::attr_iterator (Dwarf_Die *die)
+ : m_pimpl (new pimpl (die))
+{}
+
+elfutils::attr_iterator::attr_iterator (attr_iterator const &that)
+ : m_pimpl (new pimpl (*that.m_pimpl))
+{}
+
+elfutils::attr_iterator::~attr_iterator ()
+{
+ delete m_pimpl;
+}
+
+elfutils::attr_iterator &
+elfutils::attr_iterator::operator= (attr_iterator const &that)
+{
+ if (this != &that)
+ {
+ pimpl *npimpl = new pimpl (*that.m_pimpl);
+ delete m_pimpl;
+ m_pimpl = npimpl;
+ }
+
+ return *this;
+}
+
+elfutils::attr_iterator
+elfutils::attr_iterator::end ()
+{
+ return attr_iterator ((ptrdiff_t) 1);
+}
+
+bool
+elfutils::attr_iterator::operator== (attr_iterator const &that) const
+{
+ return *m_pimpl == *that.m_pimpl;
+}
+
+bool
+elfutils::attr_iterator::operator!= (attr_iterator const &that) const
+{
+ return ! (*this == that);
+}
+
+elfutils::attr_iterator &
+elfutils::attr_iterator::operator++ ()
+{
+ m_pimpl->move ();
+ return *this;
+}
+
+elfutils::attr_iterator
+elfutils::attr_iterator::operator++ (int)
+{
+ attr_iterator tmp = *this;
+ ++*this;
+ return tmp;
+}
+
+Dwarf_Attribute &
+elfutils::attr_iterator::operator* ()
+{
+ return m_pimpl->m_at;
+}
+
+Dwarf_Attribute *
+elfutils::attr_iterator::operator-> ()
+{
+ return &**this;
+}
diff --git a/libdw/c++/child_iterator.cc b/libdw/c++/child_iterator.cc
new file mode 100644
index 0000000..e4dbff8
--- /dev/null
+++ b/libdw/c++/child_iterator.cc
@@ -0,0 +1,143 @@
+/* -*-c++-*-
+ Copyright (C) 2009, 2010, 2011, 2012, 2014, 2015 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/>. */
+
+#include "libdw"
+#include "libdwP.hh"
+
+#include <cstring>
+
+struct elfutils::child_iterator::pimpl
+{
+ Dwarf_Die m_die;
+
+ // Create pimpl for end-iterator.
+ pimpl ()
+ {
+ std::memset (&m_die, 0, sizeof m_die);
+ m_die.addr = (void *) -1;
+ }
+
+ explicit pimpl (Dwarf_Die parent)
+ {
+ if (! dwpp_child (parent, m_die))
+ *this = pimpl ();
+ }
+
+ pimpl (pimpl const &that)
+ : m_die (that.m_die)
+ {}
+
+ bool
+ operator== (pimpl const &that) const
+ {
+ return m_die.addr == that.m_die.addr;
+ }
+
+ void
+ move ()
+ {
+ assert (! (*this == pimpl ()));
+ if (! dwpp_siblingof (m_die, m_die))
+ *this = pimpl ();
+ }
+};
+
+elfutils::child_iterator::child_iterator ()
+ : m_pimpl (new pimpl ())
+{}
+
+elfutils::child_iterator::child_iterator (Dwarf_Die parent)
+ : m_pimpl (new pimpl (parent))
+{}
+
+elfutils::child_iterator::child_iterator (child_iterator const &that)
+ : m_pimpl (new pimpl (*that.m_pimpl))
+{}
+
+elfutils::child_iterator::~child_iterator ()
+{
+ delete m_pimpl;
+}
+
+elfutils::child_iterator &
+elfutils::child_iterator::operator= (child_iterator const &that)
+{
+ if (this != &that)
+ {
+ pimpl *npimpl = new pimpl (*that.m_pimpl);
+ delete m_pimpl;
+ m_pimpl = npimpl;
+ }
+
+ return *this;
+}
+
+elfutils::child_iterator
+elfutils::child_iterator::end ()
+{
+ return child_iterator ();
+}
+
+bool
+elfutils::child_iterator::operator== (child_iterator const &that) const
+{
+ return *m_pimpl == *that.m_pimpl;
+}
+
+bool
+elfutils::child_iterator::operator!= (child_iterator const &that) const
+{
+ return ! (*this == that);
+}
+
+elfutils::child_iterator &
+elfutils::child_iterator::operator++ ()
+{
+ m_pimpl->move ();
+ return *this;
+}
+
+elfutils::child_iterator
+elfutils::child_iterator::operator++ (int)
+{
+ child_iterator ret = *this;
+ ++*this;
+ return ret;
+}
+
+Dwarf_Die &
+elfutils::child_iterator::operator* ()
+{
+ return m_pimpl->m_die;
+}
+
+Dwarf_Die *
+elfutils::child_iterator::operator-> ()
+{
+ return &**this;
+}
diff --git a/libdw/c++/die_tree_iterator.cc b/libdw/c++/die_tree_iterator.cc
new file mode 100644
index 0000000..11b1bf6
--- /dev/null
+++ b/libdw/c++/die_tree_iterator.cc
@@ -0,0 +1,213 @@
+/* -*-c++-*-
+ Copyright (C) 2009, 2010, 2011, 2012, 2014, 2015 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/>. */
+
+#include <dwarf.h>
+#include <algorithm>
+
+#include "libdw"
+#include "libdwP.hh"
+
+namespace
+{
+ Dwarf *
+ getdw (elfutils::unit_iterator &cuit)
+ {
+ return dwarf_cu_getdwarf (cuit->cudie.cu);
+ }
+}
+
+struct elfutils::die_tree_iterator::pimpl
+{
+ unit_iterator m_cuit;
+ // Internally, only offsets are kept on the stack.
+ std::vector <Dwarf_Off> m_stack;
+ Dwarf_Die m_die;
+
+ pimpl (Dwarf_Off)
+ : m_cuit (unit_iterator::end ())
+ {}
+
+ explicit pimpl (Dwarf *dw)
+ : m_cuit (unit_iterator (dw))
+ , m_die (m_cuit->cudie)
+ {}
+
+ explicit pimpl (unit_iterator const &cuit)
+ : m_cuit (cuit)
+ , m_die (m_cuit->cudie)
+ {}
+
+ pimpl (pimpl const &that)
+ : m_cuit (that.m_cuit)
+ , m_stack (that.m_stack)
+ , m_die (that.m_die)
+ {}
+
+ bool
+ operator== (pimpl const &that) const
+ {
+ return m_cuit == that.m_cuit
+ && m_stack == that.m_stack
+ // xxx fishy. What if other is end()?
+ && (m_cuit == unit_iterator::end ()
+ || m_die.addr == that.m_die.addr);
+ }
+
+ void
+ move ()
+ {
+ Dwarf_Die child;
+ if (dwpp_child (m_die, child))
+ {
+ m_stack.push_back (dwarf_dieoffset (&m_die));
+ m_die = child;
+ return;
+ }
+
+ do
+ if (dwpp_siblingof (m_die, m_die))
+ return;
+ else
+ // No sibling found. Go a level up and retry, unless this
+ // was a sole, childless CU DIE.
+ if (! m_stack.empty ())
+ {
+ m_die = (dwarf_tag (&m_cuit->cudie) == DW_TAG_type_unit
+ ? dwpp_offdie_types : dwpp_offdie)
+ (getdw (m_cuit), m_stack.back ());
+ m_stack.pop_back ();
+ }
+ while (! m_stack.empty ());
+
+ m_die = (++m_cuit)->cudie;
+ }
+};
+
+elfutils::die_tree_iterator::die_tree_iterator (Dwarf_Off off)
+ : m_pimpl (new pimpl (off))
+{}
+
+elfutils::die_tree_iterator::die_tree_iterator (Dwarf *dw)
+ : m_pimpl (new pimpl (dw))
+{}
+
+elfutils::die_tree_iterator::die_tree_iterator (unit_iterator const &cuit)
+ : m_pimpl (new pimpl (cuit))
+{}
+
+elfutils::die_tree_iterator::die_tree_iterator (die_tree_iterator const &that)
+ : m_pimpl (new pimpl (*that.m_pimpl))
+{}
+
+elfutils::die_tree_iterator::~die_tree_iterator ()
+{
+ delete m_pimpl;
+}
+
+elfutils::die_tree_iterator &
+elfutils::die_tree_iterator::operator= (die_tree_iterator const &that)
+{
+ if (this != &that)
+ {
+ pimpl *npimpl = new pimpl (*that.m_pimpl);
+ delete m_pimpl;
+ m_pimpl = npimpl;
+ }
+ return *this;
+}
+
+elfutils::die_tree_iterator
+elfutils::die_tree_iterator::end ()
+{
+ return die_tree_iterator ((Dwarf_Off) -1);
+}
+
+bool
+elfutils::die_tree_iterator::operator== (die_tree_iterator const &that) const
+{
+ return *m_pimpl == *that.m_pimpl;
+}
+
+bool
+elfutils::die_tree_iterator::operator!= (die_tree_iterator const &that) const
+{
+ return ! (*this == that);
+}
+
+elfutils::die_tree_iterator &
+elfutils::die_tree_iterator::operator++ ()
+{
+ m_pimpl->move ();
+ return *this;
+}
+
+elfutils::die_tree_iterator
+elfutils::die_tree_iterator::operator++ (int)
+{
+ die_tree_iterator ret = *this;
+ ++*this;
+ return ret;
+}
+
+Dwarf_Die &
+elfutils::die_tree_iterator::operator* ()
+{
+ return m_pimpl->m_die;
+}
+
+Dwarf_Die *
+elfutils::die_tree_iterator::operator-> ()
+{
+ return &**this;
+}
+
+elfutils::die_tree_iterator::stack_type
+elfutils::die_tree_iterator::stack () const
+{
+ stack_type ret;
+ for (die_tree_iterator it = *this; it != end (); it = it.parent ())
+ ret.push_back (*it);
+ std::reverse (ret.begin (), ret.end ());
+ return ret;
+}
+
+elfutils::die_tree_iterator
+elfutils::die_tree_iterator::parent ()
+{
+ assert (*this != end ());
+ if (m_pimpl->m_stack.empty ())
+ return end ();
+
+ die_tree_iterator ret = *this;
+ ret.m_pimpl->m_die = (dwarf_tag (&m_pimpl->m_cuit->cudie) == DW_TAG_type_unit
+ ? dwpp_offdie_types : dwpp_offdie)
+ (getdw (m_pimpl->m_cuit), m_pimpl->m_stack.back ());
+ ret.m_pimpl->m_stack.pop_back ();
+
+ return ret;
+}
diff --git a/libdw/c++/libdw b/libdw/c++/libdw
new file mode 100644
index 0000000..0b01b2d
--- /dev/null
+++ b/libdw/c++/libdw
@@ -0,0 +1,245 @@
+/* -*-c++-*-
+ Copyright (C) 2009, 2010, 2011, 2012, 2014, 2015 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/>. */
+
+#ifndef _LIBDW_CPP
+#define _LIBDW_CPP 1
+
+#include <vector>
+#include <iterator>
+
+#include <elfutils/libdw.h>
+
+namespace elfutils
+{
+ // The iterators presented here have operators * and -> as non-const
+ // member functions. The reason is that the libdw interfaces do not
+ // take, say, Dwarf_Die const *, but Dwarf_Die *, and therefore
+ // returning a const reference of some sort would not be useful. We
+ // don't want to give out copies either, as that adds unnecessary
+ // overhead. And we simply don't care much if anyone does end up
+ // changing the internal copy of the current CU, DIE, or whatever.
+
+
+ // An iterator that goes over compile units (full or partial) in a
+ // given DWARF file. The type that it points to (yields on
+ // dereference) is CU_INFO (see below).
+ //
+ // Example usage:
+ // {
+ // std::vector <Dwarf_Off> v
+ // for (elfutils::cu_iterator jt (dw);
+ // jt != elfutils::cu_iterator::end (); ++jt)
+ // v.push_back (dwarf_dieoffset (&jt->cudie));
+ // }
+ class unit_iterator;
+
+ // Helper structure with data about each compile unit.
+ struct unit_info
+ {
+ Dwarf_Die cudie;
+ Dwarf_Off abbrev_offset;
+ uint64_t type_signature; // Valid for DW_TAG_type_unit
+ Dwarf_Half version;
+ uint8_t address_size;
+ uint8_t offset_size;
+ };
+
+ class unit_iterator
+ : public std::iterator <std::input_iterator_tag, unit_info>
+ {
+ struct pimpl;
+ pimpl *m_pimpl;
+
+ explicit unit_iterator (Dwarf_Off off, bool types);
+
+ public:
+ // Construct a unit iterator that will iterate through all units
+ // in DW.
+ explicit unit_iterator (Dwarf *dw);
+
+ // Construct a unit iterator for DW such that it points to a
+ // compile (or other type of) unit represented by CUDIE.
+ unit_iterator (Dwarf *dw, Dwarf_Die cudie);
+
+ unit_iterator (unit_iterator const &that);
+ ~unit_iterator ();
+ unit_iterator &operator= (unit_iterator const &that);
+
+ // Return a unit_iterator pointing one after the last actual CU.
+ static unit_iterator end ();
+
+ bool operator== (unit_iterator const &that) const;
+ bool operator!= (unit_iterator const &that) const;
+
+ unit_iterator &operator++ ();
+ unit_iterator operator++ (int);
+
+ // N.B. see top of the file for explanation of non-constness of
+ // operators * and ->.
+
+ unit_info &operator* ();
+ unit_info *operator-> ();
+ };
+
+
+ // An iterator that goes through children of a given DIE.
+ // Example usage:
+ // {
+ // size_t nchildren = std::distance (elfutils::child_iterator (type_die),
+ // elfutils::child_iterator::end ());
+ // }
+
+ class child_iterator
+ : public std::iterator <std::input_iterator_tag, Dwarf_Die>
+ {
+ struct pimpl;
+ pimpl *m_pimpl;
+
+ child_iterator ();
+
+ public:
+ explicit child_iterator (Dwarf_Die parent);
+ child_iterator (child_iterator const &that);
+ ~child_iterator ();
+ child_iterator &operator= (child_iterator const &that);
+
+ // Return a child_iterator pointing one after the last actual
+ // child.
+ static child_iterator end ();
+
+ bool operator== (child_iterator const &that) const;
+ bool operator!= (child_iterator const &that) const;
+
+ child_iterator &operator++ ();
+ child_iterator operator++ (int);
+
+ // N.B. see top of the file for explanation of non-constness of
+ // operators * and ->.
+ Dwarf_Die &operator* ();
+ Dwarf_Die *operator-> ();
+ };
+
+
+ // Tree flattening iterator. It pre-order iterates all DIEs in
+ // given DWARF file, optionally starting from a given CU iterator.
+ // It keeps track of path from CU root to the current DIE, and that
+ // can be requested through stack() member function.
+ //
+ // Example usage:
+ // {
+ // for (elfutils::die_tree_iterator it (dw);
+ // it != elfutils::die_tree_iterator::end (); ++it)
+ // {
+ // typedef elfutils::die_tree_iterator::stack_type stack_type;
+ // stack_type const &stack = it.stack ();
+ // for (stack_type::const_iterator jt = stack.begin ();
+ // jt != stack.end (); ++jt)
+ // ...;
+ // }
+ // }
+ class die_tree_iterator
+ : public std::iterator <std::input_iterator_tag, Dwarf_Die>
+ {
+ struct pimpl;
+ pimpl *m_pimpl;
+
+ die_tree_iterator (Dwarf_Off);
+
+ public:
+ typedef std::vector <Dwarf_Die> stack_type;
+
+ explicit die_tree_iterator (Dwarf *dw);
+ explicit die_tree_iterator (unit_iterator const &cuit);
+
+ die_tree_iterator (die_tree_iterator const &that);
+ ~die_tree_iterator ();
+ die_tree_iterator &operator= (die_tree_iterator const &that);
+
+ // Return a die_tree_iterator pointing one after the last actual
+ // DIE.
+ static die_tree_iterator end ();
+
+ bool operator== (die_tree_iterator const &that) const;
+ bool operator!= (die_tree_iterator const &that) const;
+
+ die_tree_iterator &operator++ ();
+ die_tree_iterator operator++ (int);
+
+ // N.B. see top of the file for explanation of non-constness of
+ // operators * and ->.
+
+ Dwarf_Die &operator* ();
+ Dwarf_Die *operator-> ();
+
+ // Return a stack of DIE's representing the path from CU DIE to
+ // the current DIE (both ends inclusive). The first element of
+ // the returned stack is the CU DIE, the last one the current DIE.
+ stack_type stack () const;
+
+ // Return a die_tree_iterator referencing a parent of a DIE that
+ // this iterator points at. Returns an end iterator if there is
+ // no parent. Technically a const, but can't be one due to
+ // dwarf_tag call inside.
+ die_tree_iterator parent ();
+ };
+
+
+ // An attribute iterator goes through attributes of a given DIE.
+ class attr_iterator
+ : public std::iterator <std::input_iterator_tag, Dwarf_Attribute>
+ {
+ struct pimpl;
+ pimpl *m_pimpl;
+
+ attr_iterator (ptrdiff_t offset);
+
+ public:
+ attr_iterator (Dwarf_Die *die);
+ attr_iterator (attr_iterator const &that);
+ ~attr_iterator ();
+ attr_iterator &operator= (attr_iterator const &that);
+
+ // Return an attr_iterator pointing one after the last actual
+ // attribute.
+ static attr_iterator end ();
+
+ bool operator== (attr_iterator const &that) const;
+ bool operator!= (attr_iterator const &that) const;
+
+ attr_iterator &operator++ ();
+ attr_iterator operator++ (int);
+
+ // N.B. see top of the file for explanation of non-constness of
+ // operators * and ->.
+
+ Dwarf_Attribute &operator* ();
+ Dwarf_Attribute *operator-> ();
+ };
+}
+
+#endif
diff --git a/libdw/c++/libdwP.hh b/libdw/c++/libdwP.hh
new file mode 100644
index 0000000..cb6a145
--- /dev/null
+++ b/libdw/c++/libdwP.hh
@@ -0,0 +1,88 @@
+/* -*-c++-*-
+ Copyright (C) 2009, 2010, 2011, 2012, 2014, 2015 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/>. */
+
+#ifndef _CPP_LIBDWP_H
+#define _CPP_LIBDWP_H 1
+
+#include <stdexcept>
+#include <cassert>
+#include <cstdlib>
+
+inline void
+throw_libdw (int dwerr = 0)
+{
+ if (dwerr == 0)
+ dwerr = dwarf_errno ();
+ assert (dwerr != 0);
+ throw std::runtime_error (dwarf_errmsg (dwerr));
+}
+
+inline bool
+dwpp_child (Dwarf_Die &die, Dwarf_Die &result)
+{
+ int ret = dwarf_child (&die, &result);
+ if (ret < 0)
+ throw_libdw ();
+ return ret == 0;
+}
+
+inline bool
+dwpp_siblingof (Dwarf_Die &die, Dwarf_Die &result)
+{
+ switch (dwarf_siblingof (&die, &result))
+ {
+ case -1:
+ throw_libdw ();
+ case 0:
+ return true;
+ case 1:
+ return false;
+ default:
+ std::abort ();
+ }
+}
+
+inline Dwarf_Die
+dwpp_offdie (Dwarf *dbg, Dwarf_Off offset)
+{
+ Dwarf_Die result;
+ if (dwarf_offdie (dbg, offset, &result) == NULL)
+ throw_libdw ();
+ return result;
+}
+
+inline Dwarf_Die
+dwpp_offdie_types (Dwarf *dbg, Dwarf_Off offset)
+{
+ Dwarf_Die result;
+ if (dwarf_offdie_types (dbg, offset, &result) == NULL)
+ throw_libdw ();
+ return result;
+}
+
+#endif
diff --git a/libdw/c++/unit_iterator.cc b/libdw/c++/unit_iterator.cc
new file mode 100644
index 0000000..f49b363
--- /dev/null
+++ b/libdw/c++/unit_iterator.cc
@@ -0,0 +1,204 @@
+/* -*-c++-*-
+ Copyright (C) 2009, 2010, 2011, 2012, 2014, 2015 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/>. */
+
+#include <dwarf.h>
+
+#include "libdw"
+#include "libdwP.hh"
+
+struct elfutils::unit_iterator::pimpl
+{
+ Dwarf *m_dw;
+ Dwarf_Off m_offset;
+ Dwarf_Off m_old_offset;
+ unit_info m_info;
+ bool m_types;
+
+ bool
+ is_end ()
+ {
+ return m_offset == (Dwarf_Off) -1 && m_types;
+ }
+
+ void
+ move ()
+ {
+ assert (! is_end ());
+ m_old_offset = m_offset;
+ size_t hsize;
+ int rc = dwarf_next_unit (m_dw, m_offset, &m_offset, &hsize,
+ &m_info.version, &m_info.abbrev_offset,
+ &m_info.address_size, &m_info.offset_size,
+ m_types ? &m_info.type_signature : NULL, NULL);
+ if (rc < 0)
+ throw_libdw ();
+
+ if (rc != 0 && m_types)
+ done ();
+ else if (rc != 0)
+ {
+ m_types = true;
+ m_offset = 0;
+ m_old_offset = 0;
+ move ();
+ }
+ else
+ m_info.cudie = (m_types ? dwpp_offdie_types : dwpp_offdie)
+ (m_dw, m_old_offset + hsize);
+ }
+
+ void
+ done ()
+ {
+ *this = *end ().m_pimpl;
+ assert (is_end ());
+ }
+
+ pimpl (Dwarf_Off off, bool types)
+ : m_dw (NULL)
+ , m_offset (off)
+ , m_old_offset (0)
+ , m_types (types)
+ {}
+
+ explicit pimpl (Dwarf *dw)
+ : m_dw (dw)
+ , m_offset (0)
+ , m_old_offset (0)
+ , m_types (false)
+ {
+ move ();
+ }
+
+ // Construct a CU iterator for DW such that it points to a compile
+ // unit represented by CUDIE.
+ pimpl (Dwarf *dw, Dwarf_Die cudie)
+ : m_dw (dw)
+ , m_offset (dwarf_dieoffset (&cudie) - dwarf_cuoffset (&cudie))
+ , m_old_offset (0)
+ , m_types (dwarf_tag (&cudie) == DW_TAG_type_unit)
+ {
+ move ();
+ }
+
+ bool
+ operator== (pimpl const &that) const
+ {
+ return m_types == that.m_types && m_offset == that.m_offset;
+ }
+
+ unit_info &
+ deref ()
+ {
+ return m_info;
+ }
+};
+
+elfutils::unit_iterator::unit_iterator (Dwarf_Off off, bool types)
+ : m_pimpl (new pimpl (off, types))
+{
+}
+
+elfutils::unit_iterator::unit_iterator (Dwarf *dw)
+ : m_pimpl (new pimpl (dw))
+{
+}
+
+elfutils::unit_iterator::unit_iterator (Dwarf *dw, Dwarf_Die cudie)
+ : m_pimpl (new pimpl (dw, cudie))
+{
+}
+
+elfutils::unit_iterator::unit_iterator (unit_iterator const &that)
+ : m_pimpl (new pimpl (*that.m_pimpl))
+{
+}
+
+elfutils::unit_iterator::~unit_iterator ()
+{
+ delete m_pimpl;
+}
+
+elfutils::unit_iterator &
+elfutils::unit_iterator::operator= (unit_iterator const &that)
+{
+ if (this != &that)
+ {
+ pimpl *npimpl = new pimpl (*that.m_pimpl);
+ delete m_pimpl;
+ m_pimpl = npimpl;
+ }
+ return *this;
+}
+
+elfutils::unit_iterator
+elfutils::unit_iterator::end ()
+{
+ unit_iterator ret ((Dwarf_Off) -1, true);
+ assert (ret.m_pimpl->is_end ());
+ return ret;
+}
+
+bool
+elfutils::unit_iterator::operator== (unit_iterator const &that) const
+{
+ return *m_pimpl == *that.m_pimpl;
+}
+
+bool
+elfutils::unit_iterator::operator!= (unit_iterator const &that) const
+{
+ return ! (*this == that);
+}
+
+elfutils::unit_iterator &
+elfutils::unit_iterator::operator++ ()
+{
+ m_pimpl->move ();
+ return *this;
+}
+
+elfutils::unit_iterator
+elfutils::unit_iterator::operator++ (int)
+{
+ unit_iterator tmp = *this;
+ ++*this;
+ return tmp;
+}
+
+elfutils::unit_info &
+elfutils::unit_iterator::operator* ()
+{
+ return m_pimpl->deref ();
+}
+
+elfutils::unit_info *
+elfutils::unit_iterator::operator-> ()
+{
+ return &**this;
+}
diff --git a/libdw/libdwpp.map b/libdw/libdwpp.map
new file mode 100644
index 0000000..7d85575
--- /dev/null
+++ b/libdw/libdwpp.map
@@ -0,0 +1,199 @@
+ELFUTILS_0 { };
+
+ELFUTILS_0.162 {
+ global:
+
+ # ### elfutils::die_tree_iterator ###
+
+ # die_tree_iterator(Dwarf*)
+ _ZN8elfutils17die_tree_iteratorC1EP5Dwarf;
+
+ # die_tree_iterator(elfutils::die_tree_iterator const&)
+ _ZN8elfutils17die_tree_iteratorC1ERKS0_;
+
+ # die_tree_iterator(elfutils::unit_iterator const&)
+ _ZN8elfutils17die_tree_iteratorC1ERKNS_13unit_iteratorE;
+
+ # ~die_tree_iterator()
+ _ZN8elfutils17die_tree_iteratorD1Ev;
+
+ # operator=(elfutils::die_tree_iterator const&)
+ _ZN8elfutils17die_tree_iteratoraSERKS0_;
+
+ # parent()
+ _ZN8elfutils17die_tree_iterator6parentEv;
+
+ # stack() const
+ _ZNK8elfutils17die_tree_iterator5stackEv;
+
+ # end()
+ _ZN8elfutils17die_tree_iterator3endEv;
+
+ # operator->()
+ _ZN8elfutils17die_tree_iteratorptEv;
+
+ # operator*()
+ _ZN8elfutils17die_tree_iteratordeEv;
+
+ # operator++()
+ _ZN8elfutils17die_tree_iteratorppEv;
+
+ # operator++(int)
+ _ZN8elfutils17die_tree_iteratorppEi;
+
+ # operator==(elfutils::die_tree_iterator const&) const
+ _ZNK8elfutils17die_tree_iteratoreqERKS0_;
+
+ # operator!=(elfutils::die_tree_iterator const&) const
+ _ZNK8elfutils17die_tree_iteratorneERKS0_;
+
+
+ # ### elfutils::unit_iterator ###
+
+ # unit_iterator(Dwarf*)
+ _ZN8elfutils13unit_iteratorC1EP5Dwarf;
+
+ # unit_iterator(Dwarf*, Dwarf_Die)
+ _ZN8elfutils13unit_iteratorC1EP5Dwarf9Dwarf_Die;
+
+ # unit_iterator(elfutils::unit_iterator const&)
+ _ZN8elfutils13unit_iteratorC1ERKS0_;
+
+ # ~unit_iterator()
+ _ZN8elfutils13unit_iteratorD1Ev;
+
+ # operator=(elfutils::unit_iterator const&)
+ _ZN8elfutils13unit_iteratoraSERKS0_;
+
+ # end()
+ _ZN8elfutils13unit_iterator3endEv;
+
+ # operator->()
+ _ZN8elfutils13unit_iteratorptEv;
+
+ # operator*()
+ _ZN8elfutils13unit_iteratordeEv;
+
+ # operator++()
+ _ZN8elfutils13unit_iteratorppEv;
+
+ # operator++(int)
+ _ZN8elfutils13unit_iteratorppEi;
+
+ # operator==(elfutils::unit_iterator const&) const
+ _ZNK8elfutils13unit_iteratoreqERKS0_;
+
+ # operator!=(elfutils::unit_iterator const&) const
+ _ZNK8elfutils13unit_iteratorneERKS0_;
+
+
+ # ### elfutils::child_iterator ###
+
+ # child_iterator(elfutils::child_iterator const&)
+ _ZN8elfutils14child_iteratorC1ERKS0_;
+
+ # child_iterator(Dwarf_Die)
+ _ZN8elfutils14child_iteratorC1E9Dwarf_Die;
+
+ # ~child_iterator()
+ _ZN8elfutils14child_iteratorD1Ev;
+
+ # operator=(elfutils::child_iterator const&)
+ _ZN8elfutils14child_iteratoraSERKS0_;
+
+ # end()
+ _ZN8elfutils14child_iterator3endEv;
+
+ # operator==(elfutils::child_iterator const&) const
+ _ZNK8elfutils14child_iteratoreqERKS0_;
+
+ # operator!=(elfutils::child_iterator const&) const
+ _ZNK8elfutils14child_iteratorneERKS0_;
+
+ # operator*()
+ _ZN8elfutils14child_iteratordeEv;
+
+ # operator->()
+ _ZN8elfutils14child_iteratorptEv;
+
+ # operator++()
+ _ZN8elfutils14child_iteratorppEv;
+
+ # operator++(int)
+ _ZN8elfutils14child_iteratorppEi;
+
+
+ # ### elfutils::attr_iterator ###
+
+ # attr_iterator(Dwarf_Die*)
+ _ZN8elfutils13attr_iteratorC1EP9Dwarf_Die;
+
+ # attr_iterator(elfutils::attr_iterator const&)
+ _ZN8elfutils13attr_iteratorC1ERKS0_;
+
+ # ~attr_iterator()
+ _ZN8elfutils13attr_iteratorD1Ev;
+
+ # operator=(elfutils::attr_iterator const&)
+ _ZN8elfutils13attr_iteratoraSERKS0_;
+
+ # end()
+ _ZN8elfutils13attr_iterator3endEv;
+
+ # operator++()
+ _ZN8elfutils13attr_iteratorppEv;
+
+ # operator++(int)
+ _ZN8elfutils13attr_iteratorppEi;
+
+ # operator*()
+ _ZN8elfutils13attr_iteratordeEv;
+
+ # operator->()
+ _ZN8elfutils13attr_iteratorptEv;
+
+ # operator==(elfutils::attr_iterator const&) const
+ _ZNK8elfutils13attr_iteratoreqERKS0_;
+
+ # operator!=(elfutils::attr_iterator const&) const
+ _ZNK8elfutils13attr_iteratorneERKS0_;
+
+
+ # ### elfutils::dwfl_module_iterator ###
+
+ # dwfl_module_iterator(Dwfl*)
+ _ZN8elfutils20dwfl_module_iteratorC1EP4Dwfl;
+
+ # dwfl_module_iterator(elfutils::dwfl_module_iterator const&)
+ _ZN8elfutils20dwfl_module_iteratorC1ERKS0_;
+
+ # ~dwfl_module_iterator()
+ _ZN8elfutils20dwfl_module_iteratorD1Ev;
+
+ # operator=(elfutils::dwfl_module_iterator const&)
+ _ZN8elfutils20dwfl_module_iteratoraSERKS0_;
+
+ # end()
+ _ZN8elfutils20dwfl_module_iterator3endEv;
+
+ # operator++()
+ _ZN8elfutils20dwfl_module_iteratorppEv;
+
+ # operator++(int)
+ _ZN8elfutils20dwfl_module_iteratorppEi;
+
+ # operator*() const
+ _ZNK8elfutils20dwfl_module_iteratordeEv;
+
+ # operator->() const
+ _ZNK8elfutils20dwfl_module_iteratorptEv;
+
+ # operator==(elfutils::dwfl_module_iterator const&) const
+ _ZNK8elfutils20dwfl_module_iteratoreqERKS0_;
+
+ # operator!=(elfutils::dwfl_module_iterator const&) const
+ _ZNK8elfutils20dwfl_module_iteratorneERKS0_;
+
+ local:
+ *;
+} ELFUTILS_0;
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index d40dbae..b5cfdb9 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,16 @@
+2015-03-17 Petr Machata <pmachata(a)redhat.com>
+
+ * c++: New directory.
+ * c++/libdwfl, c++/libdwflP.hh: New header files.
+ * Makefile.am (AUTOMAKE_OPTIONS): New variable.
+ [HAVE_CXX] (pkginclude_HEADERS): Add c++/libdwfl.
+ [HAVE_CXX] (noinst_LIBRARIES): Add libdwflpp.a, libdwflpp_pic.a.
+ [HAVE_CXX] (libdwflpp_a_SOURCES, libdwflpp, libdwpp): New variables.
+ [HAVE_CXX] (libdwflpp_pic_a_SOURCES): Likewise.
+ [HAVE_CXX] (am_libdwflpp_pic_a_OBJECTS): Likewise.
+ (noinst_HEADERS): Add c++/libdwflP.hh.
+ [HAVE_CXX] (CLEANFILES): Add $(am_libdwflpp_pic_a_OBJECTS).
+
2015-01-26 Mark Wielaard <mjw(a)redhat.com>
* dwfl_module_getdwarf.c (find_symtab): Explicitly clear symdata,
diff --git a/libdwfl/Makefile.am b/libdwfl/Makefile.am
index 72c980b..21e1844 100644
--- a/libdwfl/Makefile.am
+++ b/libdwfl/Makefile.am
@@ -2,7 +2,7 @@
##
## Process this file with automake to create Makefile.in
##
-## Copyright (C) 2005-2010, 2013 Red Hat, Inc.
+## Copyright (C) 2005-2010, 2013, 2015 Red Hat, Inc.
## This file is part of elfutils.
##
## This file is free software; you can redistribute it and/or modify
@@ -34,10 +34,23 @@ AM_CPPFLAGS += -I$(srcdir) -I$(srcdir)/../libelf -I$(srcdir)/../libebl \
-I$(srcdir)/../libdw -I$(srcdir)/../libdwelf
VERSION = 1
+# For c++/ subdir.
+AUTOMAKE_OPTIONS = subdir-objects
+
noinst_LIBRARIES = libdwfl.a
+if HAVE_CXX
+noinst_LIBRARIES += libdwflpp.a
+endif
+
noinst_LIBRARIES += libdwfl_pic.a
+if HAVE_CXX
+noinst_LIBRARIES += libdwflpp_pic.a
+endif
pkginclude_HEADERS = libdwfl.h
+if HAVE_CXX
+pkginclude_HEADERS += c++/libdwfl
+endif
libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c dwfl_version.c \
dwfl_module.c dwfl_report_elf.c relocate.c \
@@ -70,6 +83,10 @@ libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c dwfl_version.c \
dwfl_frame.c frame_unwind.c dwfl_frame_pc.c \
linux-pid-attach.c linux-core-attach.c dwfl_frame_regs.c
+if HAVE_CXX
+libdwflpp_a_SOURCES = c++/dwfl_module_iterator.cc
+endif
+
if ZLIB
libdwfl_a_SOURCES += gzip.c
endif
@@ -82,6 +99,10 @@ endif
libdwfl = $(libdw)
libdw = ../libdw/libdw.so
+if HAVE_CXX
+libdwflpp = $(libdwpp)
+libdwpp = ../libdw/libdwpp.so
+endif
libelf = ../libelf/libelf.so
libebl = ../libebl/libebl.a
libeu = ../lib/libeu.a
@@ -89,6 +110,14 @@ libeu = ../lib/libeu.a
libdwfl_pic_a_SOURCES =
am_libdwfl_pic_a_OBJECTS = $(libdwfl_a_SOURCES:.c=.os)
-noinst_HEADERS = libdwflP.h
+if HAVE_CXX
+libdwflpp_pic_a_SOURCES =
+am_libdwflpp_pic_a_OBJECTS = $(libdwflpp_a_SOURCES:.cc=.os)
+endif
+
+noinst_HEADERS = libdwflP.h c++/libdwflP.hh
CLEANFILES += $(am_libdwfl_pic_a_OBJECTS)
+if HAVE_CXX
+CLEANFILES += $(am_libdwflpp_pic_a_OBJECTS)
+endif
diff --git a/libdwfl/c++/dwfl_module_iterator.cc b/libdwfl/c++/dwfl_module_iterator.cc
new file mode 100644
index 0000000..26f96fe
--- /dev/null
+++ b/libdwfl/c++/dwfl_module_iterator.cc
@@ -0,0 +1,154 @@
+/* -*-c++-*-
+ Copyright (C) 2009, 2010, 2011, 2012, 2014, 2015 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/>. */
+
+#include "libdwfl"
+#include "libdwflP.hh"
+
+struct elfutils::dwfl_module_iterator::pimpl
+{
+ Dwfl *m_dwfl;
+ ptrdiff_t m_offset;
+ Dwfl_Module *m_module;
+
+ static int
+ module_cb (Dwfl_Module *mod, void **, const char *,
+ Dwarf_Addr, void *arg)
+ {
+ pimpl *self = static_cast <pimpl *> (arg);
+ self->m_module = mod;
+ return DWARF_CB_ABORT;
+ }
+
+ void
+ move ()
+ {
+ m_offset = dwfl_getmodules (m_dwfl, module_cb, this, m_offset);
+ if (m_offset == -1)
+ throw_libdwfl ();
+ }
+
+ explicit pimpl (ptrdiff_t off)
+ : m_dwfl (NULL)
+ , m_offset (off)
+ {}
+
+ explicit pimpl (Dwfl *dwfl)
+ : m_dwfl (dwfl)
+ , m_offset (0)
+ {
+ move ();
+ }
+
+ pimpl (pimpl const &that)
+ : m_dwfl (that.m_dwfl)
+ , m_offset (that.m_offset)
+ , m_module (that.m_module)
+ {}
+
+ bool
+ operator== (pimpl const &that) const
+ {
+ assert (m_dwfl == NULL || that.m_dwfl == NULL || m_dwfl == that.m_dwfl);
+ return m_offset == that.m_offset;
+ }
+};
+
+elfutils::dwfl_module_iterator::dwfl_module_iterator (ptrdiff_t off)
+ : m_pimpl (new pimpl (off))
+{}
+
+elfutils::dwfl_module_iterator::dwfl_module_iterator (Dwfl *dwfl)
+ : m_pimpl (new pimpl (dwfl))
+{}
+
+elfutils::dwfl_module_iterator::dwfl_module_iterator (dwfl_module_iterator const &that)
+ : m_pimpl (new pimpl (*that.m_pimpl))
+{}
+
+elfutils::dwfl_module_iterator::~dwfl_module_iterator ()
+{
+ delete m_pimpl;
+}
+
+elfutils::dwfl_module_iterator &
+elfutils::dwfl_module_iterator::operator= (dwfl_module_iterator const &that)
+{
+ if (this != &that)
+ {
+ pimpl *npimpl = new pimpl (*that.m_pimpl);
+ delete m_pimpl;
+ m_pimpl = npimpl;
+ }
+
+ return *this;
+}
+
+elfutils::dwfl_module_iterator
+elfutils::dwfl_module_iterator::end ()
+{
+ return dwfl_module_iterator ((ptrdiff_t) 0);
+}
+
+elfutils::dwfl_module_iterator &
+elfutils::dwfl_module_iterator::operator++ ()
+{
+ m_pimpl->move ();
+ return *this;
+}
+
+elfutils::dwfl_module_iterator
+elfutils::dwfl_module_iterator::operator++ (int)
+{
+ dwfl_module_iterator ret = *this;
+ ++*this;
+ return ret;
+}
+
+Dwfl_Module &
+elfutils::dwfl_module_iterator::operator* () const
+{
+ return *m_pimpl->m_module;
+}
+
+Dwfl_Module *
+elfutils::dwfl_module_iterator::operator-> () const
+{
+ return &**this;
+}
+
+bool
+elfutils::dwfl_module_iterator::operator== (dwfl_module_iterator const &that) const
+{
+ return *m_pimpl == *that.m_pimpl;
+}
+
+bool
+elfutils::dwfl_module_iterator::operator!= (dwfl_module_iterator const &that) const
+{
+ return ! (*this == that);
+}
diff --git a/libdwfl/c++/libdwfl b/libdwfl/c++/libdwfl
new file mode 100644
index 0000000..42eb584
--- /dev/null
+++ b/libdwfl/c++/libdwfl
@@ -0,0 +1,70 @@
+/* -*-c++-*-
+ Copyright (C) 2009, 2010, 2011, 2012, 2014, 2015 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/>. */
+
+#ifndef _LIBDWFL_CPP
+#define _LIBDWFL_CPP 1
+
+#include <iterator>
+#include <elfutils/libdwfl.h>
+
+namespace elfutils
+{
+ // Given a Dwfl, iterates through its Dwfl_Module's.
+ //
+ // Example usage:
+ // std::vector <Dwfl_Module *> mods (elfutils::dwfl_module_iterator (dwfl),
+ // elfutils::dwfl_module_iterator::end ());
+
+ class dwfl_module_iterator
+ : public std::iterator <std::input_iterator_tag, Dwfl_Module *>
+ {
+ struct pimpl;
+ pimpl *m_pimpl;
+
+ explicit dwfl_module_iterator (ptrdiff_t off);
+
+ public:
+ explicit dwfl_module_iterator (Dwfl *dwfl);
+ dwfl_module_iterator (dwfl_module_iterator const &that);
+ ~dwfl_module_iterator ();
+ dwfl_module_iterator &operator= (dwfl_module_iterator const &that);
+
+ static dwfl_module_iterator end ();
+
+ dwfl_module_iterator &operator++ ();
+ dwfl_module_iterator operator++ (int);
+
+ Dwfl_Module &operator* () const;
+ Dwfl_Module *operator-> () const;
+
+ bool operator== (dwfl_module_iterator const &that) const;
+ bool operator!= (dwfl_module_iterator const &that) const;
+ };
+}
+
+#endif
diff --git a/libdwfl/c++/libdwflP.hh b/libdwfl/c++/libdwflP.hh
new file mode 100644
index 0000000..c3f2792
--- /dev/null
+++ b/libdwfl/c++/libdwflP.hh
@@ -0,0 +1,44 @@
+/* -*-c++-*-
+ Copyright (C) 2009, 2010, 2011, 2012, 2014, 2015 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/>. */
+
+#ifndef _CPP_LIBDWFLP_H
+#define _CPP_LIBDWFLP_H 1
+
+#include <stdexcept>
+#include <cassert>
+
+static inline void
+throw_libdwfl (int dwflerr = 0)
+{
+ if (dwflerr == 0)
+ dwflerr = dwfl_errno ();
+ assert (dwflerr != 0);
+ throw std::runtime_error (dwfl_errmsg (dwflerr));
+}
+
+#endif
diff --git a/tests/ChangeLog b/tests/ChangeLog
index a029645..f50da48 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,5 +1,12 @@
2015-03-18 Petr Machata <pmachata(a)redhat.com>
+ * test-iterators.cc, run-test-iterators.sh: New files.
+ * Makefile.am (check_PROGRAMS) [HAVE_CXX]: Add test-iterators.
+ (TESTS) [HAVE_CXX]: Add run-test-iterators.sh.
+ (libdwpp): New variable.
+
+2015-03-18 Petr Machata <pmachata(a)redhat.com>
+
* addrcfi.c (op_name): Adjust uses of know-dwarf.h macros to match
the API changes.
* allregs.c (dwarf_encoding_string): Likewise.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 9e8bc02..abe6da7 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -141,6 +141,11 @@ check_PROGRAMS += $(asm_TESTS)
TESTS += $(asm_TESTS)
endif
+if HAVE_CXX
+check_PROGRAMS += test-iterators
+TESTS += run-test-iterators.sh
+endif
+
EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
run-show-die-info.sh run-get-files.sh run-get-lines.sh \
run-get-pubnames.sh run-get-aranges.sh \
@@ -286,7 +291,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
testfile-sizes3.o.bz2 \
run-readelf-A.sh testfileppc32attrs.o.bz2 \
testfile-debug-types.bz2 \
- run-getsrc-die.sh run-strptr.sh
+ run-getsrc-die.sh run-strptr.sh run-test-iterators.sh
if USE_VALGRIND
valgrind_cmd='valgrind -q --error-exitcode=1 --run-libc-freeres=no'
@@ -330,16 +335,19 @@ endif !STANDALONE
if STANDALONE
libdw = -ldw
+libdwpp = -ldwpp
libelf = -lelf
libasm = -lasm
libebl = -lebl
else !STANDALONE
if BUILD_STATIC
libdw = ../libdw/libdw.a $(zip_LIBS) $(libelf) $(libebl) -ldl
+libdwpp = ../libdw/libdwpp.a $(libdw)
libelf = ../libelf/libelf.a
libasm = ../libasm/libasm.a
else
libdw = ../libdw/libdw.so
+libdwpp = ../libdw/libdwpp.so
libelf = ../libelf/libelf.so
libasm = ../libasm/libasm.so
endif
@@ -431,6 +439,8 @@ getsrc_die_LDADD = $(libdw) $(libelf)
strptr_LDADD = $(libelf)
newdata_LDADD = $(libelf)
elfstrtab_LDADD = $(libelf)
+test_iterators_SOURCES = test-iterators.cc
+test_iterators_LDADD = $(libdw) $(libdwpp)
if GCOV
check: check-am coverage
diff --git a/tests/run-test-iterators.sh b/tests/run-test-iterators.sh
new file mode 100755
index 0000000..6942570
--- /dev/null
+++ b/tests/run-test-iterators.sh
@@ -0,0 +1,52 @@
+#! /bin/sh
+# Copyright (C) 2015 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 the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# 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 a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile39 testfile-debug-types
+
+testrun_compare ${abs_top_builddir}/tests/test-iterators testfile39 <<\EOF
+0xb
+0x9e
+0x135
+0x1c8
+0 7
+0 7
+0 7
+0 7
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/test-iterators testfile-debug-types <<\EOF
+0xb
+0x17
+0x5a
+4 6
+0 9
+0 3
+0 6
+0 6
+2 3
+1 4
+0 2
+0 5
+1 3
+2 4
+0 3
+0 5
+EOF
+
+exit 0
diff --git a/tests/test-iterators.cc b/tests/test-iterators.cc
new file mode 100644
index 0000000..987bc6a
--- /dev/null
+++ b/tests/test-iterators.cc
@@ -0,0 +1,87 @@
+/* Copyright (C) 2015 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 the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ 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 a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <iostream>
+#include <cassert>
+#include <stdexcept>
+
+#include "../libdw/c++/libdw"
+#include "../libdwfl/c++/libdwfl"
+#include "../libdw/c++/libdwP.hh"
+#include "../libdwfl/c++/libdwflP.hh"
+
+int
+main (int, char *argv[])
+{
+ int fd = open (argv[1], O_RDONLY);
+ if (fd < 0)
+ throw std::runtime_error (strerror (errno));
+
+ const static Dwfl_Callbacks callbacks =
+ {
+ .find_elf = dwfl_build_id_find_elf,
+ .find_debuginfo = dwfl_standard_find_debuginfo,
+ .section_address = dwfl_offline_section_address,
+ .debuginfo_path = NULL,
+ };
+
+ Dwfl *dwfl = dwfl_begin (&callbacks);
+ if (dwfl == NULL)
+ throw_libdwfl ();
+
+ dwfl_report_begin (dwfl);
+ if (dwfl_report_offline (dwfl, argv[1], argv[1], fd) == NULL)
+ throw_libdwfl ();
+ dwfl_report_end (dwfl, NULL, NULL);
+
+ for (elfutils::dwfl_module_iterator modit (dwfl);
+ modit != elfutils::dwfl_module_iterator::end (); ++modit)
+ {
+ Dwarf_Off bias;
+ Dwarf *dw = dwfl_module_getdwarf (&*modit, &bias);
+ std::vector <std::pair <elfutils::unit_iterator, Dwarf_Die> > cudies;
+ for (elfutils::unit_iterator it (dw); it != elfutils::unit_iterator::end (); ++it)
+ cudies.push_back (std::make_pair (it, it->cudie));
+
+ for (size_t i = 0; i < cudies.size (); ++i)
+ {
+ elfutils::unit_iterator jt (dw, cudies[i].second);
+ std::cerr << std::hex << std::showbase
+ << dwarf_dieoffset (&jt->cudie) << std::endl;
+ for (size_t j = i; jt != elfutils::unit_iterator::end (); ++jt, ++j)
+ assert (jt == cudies[j].first);
+ }
+
+ assert (elfutils::die_tree_iterator (elfutils::unit_iterator::end ())
+ == elfutils::die_tree_iterator::end ());
+
+ for (elfutils::die_tree_iterator it (dw);
+ it != elfutils::die_tree_iterator::end (); ++it)
+ std::cerr << std::dec
+ << std::distance (elfutils::child_iterator (*it),
+ elfutils::child_iterator::end ()) << ' '
+ << std::distance (elfutils::attr_iterator (&*it),
+ elfutils::attr_iterator::end ())
+ << std::endl;
+ }
+
+ dwfl_end (dwfl);
+}
--
2.1.0
9 years
[PATCH 1/2] Enable C++
by Petr Machata
- Detect C++ compiler in configure, add supporting infrastructure to
eu.am.
Signed-off-by: Petr Machata <pmachata(a)redhat.com>
---
ChangeLog | 4 ++++
config/ChangeLog | 6 ++++++
config/eu.am | 21 ++++++++++++++++++++-
configure.ac | 15 +++++++++++++++
4 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/ChangeLog b/ChangeLog
index 5c8e1c2..6c6f216 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2015-03-18 Petr Machata <pmachata(a)redhat.com>
+
+ * configure.ac (HAVE_CXX): New conditional.
+
2015-03-13 Mark Wielaard <mjw(a)redhat.com>
* configure.ac (ac_cv_c99): Add explicit return.
diff --git a/config/ChangeLog b/config/ChangeLog
index 586ebb0..32f3c93 100644
--- a/config/ChangeLog
+++ b/config/ChangeLog
@@ -1,3 +1,9 @@
+2015-04-02 Petr Machata <pmachata(a)redhat.com>
+
+ * eu.am (AM_CXXFLAGS, CXXCOMPILE.os): New variables.
+ (%.os: %.c %.o): Create dep-file subdirectory if necessary.
+ (%.os: %.cc %.o): New rule.
+
2015-03-18 Petr Machata <pmachata(a)redhat.com>
* known-dwarf.awk (comment): Drop all uses of this variable.
diff --git a/config/eu.am b/config/eu.am
index faf8add..f1d290b 100644
--- a/config/eu.am
+++ b/config/eu.am
@@ -1,6 +1,6 @@
## Common automake fragments for elfutils subdirectory makefiles.
##
-## Copyright (C) 2010, 2014 Red Hat, Inc.
+## Copyright (C) 2010, 2014, 2015 Red Hat, Inc.
##
## This file is part of elfutils.
##
@@ -35,11 +35,17 @@ AM_CFLAGS = -std=gnu99 -Wall -Wshadow -Wformat=2 \
$(if $($(*F)_no_Werror),,-Werror) \
$(if $($(*F)_no_Wunused),,-Wunused -Wextra) \
$($(*F)_CFLAGS)
+AM_CXXFLAGS = -std=gnu++98 -Wall -Wshadow -Wformat=2 \
+ $(if $($(*F)_no_Werror),,-Werror) \
+ $(if $($(*F)_no_Wunused),,-Wunused -Wextra) \
+ $($(*F)_CXXFLAGS)
COMPILE.os = $(filter-out -fprofile-arcs -ftest-coverage, $(COMPILE))
+CXXCOMPILE.os = $(filter-out -fprofile-arcs -ftest-coverage, $(CXXCOMPILE))
%.os: %.c %.o
if AMDEP
+ test -d $(DEPDIR)/$(*D) || mkdir $(DEPDIR)/$(*D)
if $(COMPILE.os) -c -o $@ -fpic -DPIC -DSHARED -MT $@ -MD -MP \
-MF "$(DEPDIR)/$*.Tpo" `test -f '$<' || echo '$(srcdir)/'`$<; \
then cat "$(DEPDIR)/$*.Tpo" >> "$(DEPDIR)/$*.Po"; \
@@ -50,6 +56,19 @@ else
$(COMPILE.os) -c -o $@ -fpic -DPIC -DSHARED $<
endif
+%.os: %.cc %.o
+if AMDEP
+ test -d $(DEPDIR)/$(*D) || mkdir $(DEPDIR)/$(*D)
+ if $(CXXCOMPILE.os) -c -o $@ -fpic -DPIC -DSHARED -MT $@ -MD -MP \
+ -MF "$(DEPDIR)/$*.Tpo" `test -f '$<' || echo '$(srcdir)/'`$<; \
+ then cat "$(DEPDIR)/$*.Tpo" >> "$(DEPDIR)/$*.Po"; \
+ rm -f "$(DEPDIR)/$*.Tpo"; \
+ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+ fi
+else
+ $(CXXCOMPILE.os) -c -o $@ -fpic -DPIC -DSHARED $<
+endif
+
CLEANFILES = *.gcno *.gcda
textrel_msg = echo "WARNING: TEXTREL found in '$@'"
diff --git a/configure.ac b/configure.ac
index c4b818d..bc40bff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -71,6 +71,7 @@ AS_IF([test "$use_locks" = yes],
AH_TEMPLATE([USE_LOCKS], [Defined if libraries should be thread-safe.])
AC_PROG_CC
+AC_PROG_CXX
AC_PROG_RANLIB
AC_PROG_YACC
AM_PROG_LEX
@@ -89,6 +90,20 @@ CFLAGS="$old_CFLAGS"])
AS_IF([test "x$ac_cv_c99" != xyes],
AC_MSG_ERROR([gcc with C99 support required]))
+# Above, we check for C++ compiler. However even if none is available,
+# CXX is set to a non-empty value. So we need to figure out whether a
+# C++ compiler is actually available.
+AC_CACHE_CHECK([for working C++ compiler], ac_cv_cxx_works,
+[AC_LANG_PUSH([C++])
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([dnl
+struct foo {
+ int i;
+ explicit foo () : i (0) {}
+ virtual ~foo () {}
+};])], ac_cv_cxx_works=yes, ac_cv_cxx_works=no)
+ AC_LANG_POP()])
+AM_CONDITIONAL(HAVE_CXX, test "$ac_cv_cxx_works" = yes)
+
AC_CACHE_CHECK([for __thread support], ac_cv_tls, [dnl
# Use the same flags that we use for our DSOs, so the test is representative.
# Some old compiler/linker/libc combinations fail some ways and not others.
--
2.1.0
9 years
[PATCH] libdwfl: Special case linux-gate/vdso.so in core_file_read_eagerly.
by Mark Wielaard
linux-gate or linux-vdso might be available in the core file, but not
on disk, even if we have a build-id. Try to read them in to make sure
symbols and unwind information are always available for them. We would
already map them in if the core file was opened with ELF_C_READ_MMAP.
https://bugzilla.redhat.com/show_bug.cgi?id=1129756
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdwfl/ChangeLog | 5 +++++
libdwfl/core-file.c | 13 +++++++++----
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index d40dbae..68cf9f0 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,8 @@
+2015-03-16 Mark Wielaard <mjw(a)redhat.com>
+
+ * core-file.c (core_file_read_eagerly): Special case linux-gate
+ and linux-vdso.
+
2015-01-26 Mark Wielaard <mjw(a)redhat.com>
* dwfl_module_getdwarf.c (find_symtab): Explicitly clear symdata,
diff --git a/libdwfl/core-file.c b/libdwfl/core-file.c
index 50031ae..a3ac8a8 100644
--- a/libdwfl/core-file.c
+++ b/libdwfl/core-file.c
@@ -1,5 +1,5 @@
/* Core file handling.
- Copyright (C) 2008-2010, 2013 Red Hat, Inc.
+ Copyright (C) 2008-2010, 2013, 2015 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -164,7 +164,7 @@ dwfl_report_core_segments (Dwfl *dwfl, Elf *elf, size_t phnum, GElf_Phdr *notes)
static bool
core_file_read_eagerly (Dwfl_Module *mod,
void **userdata __attribute__ ((unused)),
- const char *name __attribute__ ((unused)),
+ const char *name,
Dwarf_Addr start __attribute__ ((unused)),
void **buffer, size_t *buffer_available,
GElf_Off cost, GElf_Off worthwhile,
@@ -212,10 +212,15 @@ core_file_read_eagerly (Dwfl_Module *mod,
requires find_elf hook re-doing the magic to fall back if no file found
*/
- if (mod->build_id_len > 0)
+ if (mod->build_id_len > 0
+ && strcmp ("linux-gate.so.1", name) != 0
+ && strcmp ("linux-vdso.so.1", name) != 0
+ && strcmp ("linux-vdso32.so.1", name) != 0
+ && strcmp ("linux-vdso64.so.1", name) != 0)
/* There is a build ID that could help us find the whole file,
which might be more useful than what we have.
- We'll just rely on that. */
+ We'll just rely on that. Special hack for linux-gate and
+ linux-vdso since those might not actually be found on disk. */
return false;
if (core->map_address != NULL)
--
1.8.3.1
9 years
[PATCH 1/1] Add a --{enable,disable}-backends option
by Jan Heylen
Add a --{enable,disable}-backends configuration option to elfutils. This
allows to selectively disable the compilation of the libebl backends
shared libraries. This is usefull when some application require linking
against the elfutils libelf, but don't require the backends to be available
at runtime on target, e.g. in a cross compilation setting.
Signed-off-by: Jan Heylen <heyleke(a)gmail.com>
---
Makefile.am | 9 +++++++--
configure.ac | 5 +++++
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index d044a7c..7245fe3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -23,8 +23,13 @@ ACLOCAL_AMFLAGS = -I m4
pkginclude_HEADERS = version.h
# Add doc back when we have some real content.
-SUBDIRS = config m4 lib libelf libebl libdwelf libdwfl libdw libcpu libasm \
- backends src po tests
+SUBDIRS = config m4 lib libelf libebl libdwelf libdwfl libdw libcpu libasm
+
+if ENABLE_BACKENDS
+SUBDIRS += backends
+endif
+
+SUBDIRS += src po tests
EXTRA_DIST = elfutils.spec GPG-KEY NOTES CONTRIBUTING \
COPYING COPYING-GPLV2 COPYING-LGPLV3
diff --git a/configure.ac b/configure.ac
index c4b818d..70445a2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -189,6 +189,11 @@ AS_HELP_STRING([--enable-tests-rpath],[build $ORIGIN-using rpath into tests]),
[tests_use_rpath=$enableval], [tests_use_rpath=no])
AM_CONDITIONAL(TESTS_RPATH, test "$tests_use_rpath" = yes)
+AC_ARG_ENABLE([backends],
+AS_HELP_STRING([--enable-backends], [enable ebl backends]),
+ enable_backends=$enableval, enable_backends=yes)
+AM_CONDITIONAL(ENABLE_BACKENDS, test "$enable_backends" = yes)
+
LIBEBL_SUBDIR="$PACKAGE"
AC_ARG_ENABLE([libebl-subdir],
AS_HELP_STRING([--enable-libebl-subdir=DIR],
--
1.7.1
9 years
[PATCH] Do not reject type units in dwarf_getsrcfiles and dwarf_getsrclines
by Petr Machata
Signed-off-by: Petr Machata <pmachata(a)redhat.com>
---
libdw/ChangeLog | 9 +++++++++
libdw/dwarf_error.c | 3 ++-
libdw/dwarf_getsrcfiles.c | 9 +++++----
libdw/dwarf_getsrclines.c | 11 ++++++-----
libdw/libdwP.h | 7 +++++++
5 files changed, 29 insertions(+), 10 deletions(-)
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 3ca85cb..4fb4763 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,12 @@
+2015-04-01 Petr Machata <pmachata(a)redhat.com>
+
+ * libdwP.h (DWARF_E_NOT_CUDIE): New enumerator.
+ (is_cudie): New function.
+ * dwarf_error.c (errmsgs): Add message for DWARF_E_NOT_CUDIE.
+ * dwarf_getsrcfiles.c (dwarf_getsrcfiles): Call is_cudie instead
+ of white-listing valid tags.
+ * dwarf_getsrclines.c (dwarf_getsrclines.c): Likewise.
+
2015-03-18 Petr Machata <pmachata(a)redhat.com>
* Makefile.am (pkginclude_HEADERS): Add known-dwarf.h.
diff --git a/libdw/dwarf_error.c b/libdw/dwarf_error.c
index 08b691a..aa97a68 100644
--- a/libdw/dwarf_error.c
+++ b/libdw/dwarf_error.c
@@ -1,5 +1,5 @@
/* Retrieve ELF descriptor used for DWARF access.
- Copyright (C) 2002, 2003, 2004, 2005, 2009, 2014 Red Hat, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2009, 2014, 2015 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper(a)redhat.com>, 2002.
@@ -93,6 +93,7 @@ static const char *errmsgs[] =
[DWARF_E_INVALID_CFI] = N_("invalid CFI section"),
[DWARF_E_NO_ALT_DEBUGLINK] = N_("no alternative debug link found"),
[DWARF_E_INVALID_OPCODE] = N_("invalid opcode"),
+ [DWARF_E_NOT_CUDIE] = N_("not a CU (unit) DIE"),
};
#define nerrmsgs (sizeof (errmsgs) / sizeof (errmsgs[0]))
diff --git a/libdw/dwarf_getsrcfiles.c b/libdw/dwarf_getsrcfiles.c
index 4bfc34b..30bf8f5 100644
--- a/libdw/dwarf_getsrcfiles.c
+++ b/libdw/dwarf_getsrcfiles.c
@@ -39,10 +39,11 @@
int
dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, size_t *nfiles)
{
- if (unlikely (cudie == NULL
- || (INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit
- && INTUSE(dwarf_tag) (cudie) != DW_TAG_partial_unit)))
- return -1;
+ if (cudie == NULL || ! is_cudie (cudie))
+ {
+ __libdw_seterrno (DWARF_E_NOT_CUDIE);
+ return -1;
+ }
int res = -1;
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index 053b30f..1b31721 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -1,5 +1,5 @@
/* Return line number information of CU.
- Copyright (C) 2004-2010, 2013, 2014 Red Hat, Inc.
+ Copyright (C) 2004-2010, 2013, 2014, 2015 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper(a)redhat.com>, 2004.
@@ -838,10 +838,11 @@ __libdw_getcompdir (Dwarf_Die *cudie)
int
dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
{
- if (unlikely (cudie == NULL
- || (INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit
- && INTUSE(dwarf_tag) (cudie) != DW_TAG_partial_unit)))
- return -1;
+ if (cudie == NULL || ! is_cudie (cudie))
+ {
+ __libdw_seterrno (DWARF_E_NOT_CUDIE);
+ return -1;
+ }
/* Get the information if it is not already known. */
struct Dwarf_CU *const cu = cudie->cu;
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index e38e0c9..fc77960 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -128,6 +128,7 @@ enum
DWARF_E_INVALID_CFI,
DWARF_E_NO_ALT_DEBUGLINK,
DWARF_E_INVALID_OPCODE,
+ DWARF_E_NOT_CUDIE,
};
@@ -725,6 +726,12 @@ cu_sec_idx (struct Dwarf_CU *cu)
return cu->type_offset == 0 ? IDX_debug_info : IDX_debug_types;
}
+static inline bool
+is_cudie (Dwarf_Die *cudie)
+{
+ return CUDIE (cudie->cu).addr == cudie->addr;
+}
+
/* Read up begin/end pair and increment read pointer.
- If it's normal range record, set up *BEGINP and *ENDP and return 0.
- If it's base address selection record, set up *BASEP and return 1.
--
2.1.0
9 years
PATCH: Add x32_corenote.c
by H.J. Lu
This patch adds x32_corenote.c to support x32 coredump. X32 coredump is
a hybrid between ia32 coredump and x86-64 coredump. The exact formats
are described in bfd/hosts/x86-64linux.h in GNU binutils source tree.
--
H.J.
9 years