[PATCH] libelf: Make sure version xlate dest buffer is fully defined.
by Mark Wielaard
https://bugzilla.redhat.com/show_bug.cgi?id=1170810#c16
contains an example of usage of undefined memory when version section
data needs to be translated, but the version xlate functions detect they
cannot fully transform the section data. To make sure the dest buffer
data is completely defined this patch makes sure all data is moved
from src to dest first. This is somewhat inefficient since normally
all data will be fully converted. But the translation functions have
no way to indicate only partial data was converted.
Reported-by: Alexander Cherepanov <cherepan(a)mccme.ru>
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libelf/ChangeLog | 5 +++++
libelf/version_xlate.h | 12 +++++++++++-
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 2ca9509..adfccf1 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,8 @@
+2015-01-03 Mark Wielaard <mjw(a)redhat.com>
+
+ * version_xlate.h (elf_cvt_Verdef): Use memmove to copy src to dest.
+ (elf_cvt_Verneed): Likewise.
+
2014-12-30 Mark Wielaard <mjw(a)redhat.com>
* elf_getphdrnum.c (__elf_getphdrnum_chk_rdlock): New function.
diff --git a/libelf/version_xlate.h b/libelf/version_xlate.h
index 16eaa19..9fe01c6 100644
--- a/libelf/version_xlate.h
+++ b/libelf/version_xlate.h
@@ -1,5 +1,5 @@
/* Conversion functions for versioning information.
- Copyright (C) 1998, 1999, 2000, 2002, 2003 Red Hat, Inc.
+ Copyright (C) 1998, 1999, 2000, 2002, 2003, 2015 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper(a)redhat.com>, 1998.
@@ -55,6 +55,11 @@ elf_cvt_Verdef (void *dest, const void *src, size_t len, int encode)
if (len == 0)
return;
+ /* Below we rely on the next field offsets to be correct, start by
+ copying over all data as is in case some data isn't translated.
+ We don't want to leave (undefined) garbage in the dest buffer. */
+ memmove (dest, src, len);
+
do
{
size_t aux_offset;
@@ -149,6 +154,11 @@ elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
if (len == 0)
return;
+ /* Below we rely on the next field offsets to be correct, start by
+ copying over all data as is in case some data isn't translated.
+ We don't want to leave (undefined) garbage in the dest buffer. */
+ memmove (dest, src, len);
+
do
{
size_t aux_offset;
--
2.1.0
8 years, 10 months
[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
8 years, 11 months
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.
8 years, 11 months
known-elf.awk/known-elf.h
by Petr Machata
Hi there,
dwgrep needs to programmatically work with ELF constants, so I put
together the attached script.
The basic idea is the same as with known-dwarf, but elf.h has some extra
challenges to address:
- It's not entirely predictable which constants are bona fide values,
and which are metavalues that e.g. count numbers of other constants,
or e.g. flags. The script handles this by having a whitelist of
constant types to admit, and then some heuristics to remove the
non-values.
- Arch- and OS-specific values are rather the norm in ELF. I didn't
find any collisions in per-OS ranges, but plenty of them in per-PROC
ranges, so the latter is actually addressed in the generated headers.
The following example illustrates how the facility is used.
/* Per-constant executor. */
#define ELF_ONE_KNOWN_STB(SHORT, LONG) /* ... */
/* Visit generic constants. */
ELF_ALL_KNOWN_STB
/* STB_ per-arch executor. */
#define ELF_ONE_KNOWN_STB_ARCH(ARCH) \
/* ... */ \
/* Visit STB_ARCH_* constants. */ \
ELF_ALL_KNOWN_STB_##ARCH \
/* ... */
/* Visit arches known for STB_ constants. */
ELF_ALL_KNOWN_STB_ARCHES
#undef ELF_ONE_KNOWN_STB_ARCH
#undef ELF_ONE_KNOWN_STB
I'm attaching the script as well as the generated .h for preliminary
assesment. Let me know if you think this would be a good addition to
elfutils, and any comments that you might have. If this seems
acceptable, I'll send a full-fledged patch.
Thanks,
Petr
8 years, 11 months
[PATCH] Add C++ wrappers for iterating through various libdw and libdwfl objects
by Petr Machata
Hello,
these iterators originated a couple years back on the dwarflint branch.
Back then Roland added some C++ wrappers and we started writing stuff in
C++. I've been lugging them around ever since, first to dwlocstat,
which was peeled off dwarflint (and should be coming for review after
this bunch), and then to dwgrep. They are header-only library.
They are not completely zero-overhead, as every "++" involves a call to
the underlying C-level interface. But they are tremendously handy and
allow one to express algorithms in a native C++ way, which is why I've
been using them.
Error conditions are communicated through exceptions. For better or
worse, that's how things are done in C++, and there's simply no way to
communicate failures out of constructors or the likes of operator++.
Currently I'm simply throwing an std::runtime_error, but maybe it would
make sense to have a custom family of libelf, libdw, libdwfl exceptions,
all rooted in a general elfutils exception type.
One non-iterator-like concept that I included as well is a wrapper
around dwfl_report. It's an RAII class that ends the reporting when it
goes out of scope. As soon as one calls dwfl_report_begin, they assume
responsibility to call dwfl_report_end eventually. But in C++ many
error conditions are communicated through exceptions, and making sure
these cleanups are not skipped is messy. RAII as a way to express these
responsibilities in C++.
It's all C++98. We have had "the new C++" out there on the streets
since 2009 or so, and the iterators presented here were all written with
varying degrees of C++11 in them. But that is still sufficiently new
that I felt adhering to the C++98 subset is the prudent way forward, and
backported the code.
The headers are installed unconditionally, but a test for availability
of a C++ compiler is made anyway, and build of the corresponding test is
skipped if there is none. The testing is rather light, including only a
couple cases that I wanted to make sure about as I reviewed the code.
Dwgrep has a fairly comprehensive test suite that covers proper function
of these iterators, if that's any consolation.
Let me know what you think.
Thanks,
Petr
--8<-----------------------------------------------------------------
Signed-off-by: Petr Machata <pmachata(a)redhat.com>
---
configure.ac | 17 +-
libdw/ChangeLog | 6 +
libdw/Makefile.am | 5 +-
libdw/c++/libdw | 600 ++++++++++++++++++++++++++++++++++++++++++++
libdwfl/ChangeLog | 6 +
libdwfl/Makefile.am | 5 +-
libdwfl/c++/libdwfl | 227 +++++++++++++++++
tests/Makefile.am | 7 +
tests/run-test-iterators.sh | 29 +++
tests/test-iterators.cc | 50 ++++
10 files changed, 949 insertions(+), 3 deletions(-)
create mode 100644 libdw/c++/libdw
create mode 100644 libdwfl/c++/libdwfl
create mode 100755 tests/run-test-iterators.sh
create mode 100644 tests/test-iterators.cc
diff --git a/configure.ac b/configure.ac
index 0e67a79..296584c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
dnl Process this file with autoconf to produce a configure script.
dnl Configure input file for elfutils. -*-autoconf-*-
dnl
-dnl Copyright (C) 1996-2014 Red Hat, Inc.
+dnl Copyright (C) 1996-2015 Red Hat, Inc.
dnl
dnl This file is part of elfutils.
dnl
@@ -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.
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 59fda1a..9c996f0 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,9 @@
+2015-03-17 Petr Machata <pmachata(a)redhat.com>
+
+ * c++: New directory.
+ * c++/libdw: New header file.
+ * Makefile.am: Install it.
+
2015-02-09 Mark Wielaard <mjw(a)redhat.com>
* dwarf.h: Add DW_LANG_Fortran03 and DW_LANG_Fortran08.
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index 887da6b..771db9e 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
@@ -41,6 +41,9 @@ noinst_PROGRAMS = $(noinst_LIBRARIES:_pic.a=.so)
include_HEADERS = dwarf.h
pkginclude_HEADERS = libdw.h
+cppdir = $(pkgincludedir)/c++
+cpp_HEADERS = c++/libdw
+
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 \
dwarf_error.c dwarf_nextcu.c dwarf_diename.c dwarf_offdie.c \
diff --git a/libdw/c++/libdw b/libdw/c++/libdw
new file mode 100644
index 0000000..f884d2e
--- /dev/null
+++ b/libdw/c++/libdw
@@ -0,0 +1,600 @@
+/* -*-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 <cassert>
+#include <algorithm>
+#include <stdexcept>
+
+#include <elfutils/libdw.h>
+#include <dwarf.h>
+
+namespace elfutils
+{
+ // Helper functions. Not for client consumption.
+ namespace libdw_impl
+ {
+ inline void throw_libdw (int dwerr = 0);
+ inline bool dwpp_child (Dwarf_Die &die, Dwarf_Die &result);
+ inline bool dwpp_siblingof (Dwarf_Die &die, Dwarf_Die &result);
+ inline Dwarf_Die dwpp_offdie (Dwarf *dbg, Dwarf_Off offset);
+ }
+
+ // 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 cu_iterator;
+
+ // Helper structure with data about each compile unit.
+ struct cu_info
+ {
+ Dwarf_Die cudie;
+ Dwarf_Off abbrev_offset;
+ uint8_t address_size;
+ uint8_t offset_size;
+ };
+
+ class cu_iterator
+ : public std::iterator <std::input_iterator_tag, cu_info>
+ {
+ friend class die_tree_iterator;
+ Dwarf *m_dw;
+ Dwarf_Off m_offset;
+ Dwarf_Off m_old_offset;
+ cu_info m_info;
+
+ explicit cu_iterator (Dwarf_Off off)
+ : m_dw (NULL)
+ , m_offset (off)
+ , m_old_offset (0)
+ {}
+
+ void
+ move ()
+ {
+ assert (*this != end ());
+ m_old_offset = m_offset;
+ size_t hsize;
+ if (dwarf_nextcu (m_dw, m_offset, &m_offset, &hsize,
+ &m_info.abbrev_offset,
+ &m_info.address_size, &m_info.offset_size) != 0)
+ done ();
+ else
+ m_info.cudie
+ = elfutils::libdw_impl::dwpp_offdie (m_dw, m_old_offset + hsize);
+ }
+
+ void
+ done ()
+ {
+ *this = end ();
+ }
+
+ public:
+ explicit cu_iterator (Dwarf *dw)
+ : m_dw (dw)
+ , m_offset (0)
+ , m_old_offset (0)
+ {
+ move ();
+ }
+
+ // Construct a CU iterator for DW such that it points to a compile
+ // unit represented by CUDIE.
+ cu_iterator (Dwarf *dw, Dwarf_Die cudie)
+ : m_dw (dw)
+ , m_offset (dwarf_dieoffset (&cudie) - dwarf_cuoffset (&cudie))
+ , m_old_offset (0)
+ {
+ move ();
+ }
+
+ cu_iterator (cu_iterator const &that)
+ : m_dw (that.m_dw)
+ , m_offset (that.m_offset)
+ , m_old_offset (that.m_old_offset)
+ , m_info (that.m_info)
+ {}
+
+ // Return a cu_iterator pointing one after the last actual CU.
+ static cu_iterator
+ end ()
+ {
+ return cu_iterator ((Dwarf_Off) -1);
+ }
+
+ bool
+ operator== (cu_iterator const &that) const
+ {
+ return m_offset == that.m_offset;
+ }
+
+ bool
+ operator!= (cu_iterator const &that) const
+ {
+ return ! (*this == that);
+ }
+
+ cu_iterator
+ operator++ ()
+ {
+ move ();
+ return *this;
+ }
+
+ cu_iterator
+ operator++ (int)
+ {
+ cu_iterator tmp = *this;
+ ++*this;
+ return tmp;
+ }
+
+ Dwarf_Off
+ offset () const
+ {
+ return m_old_offset;
+ }
+
+ // N.B. see top of the file for explanation of non-constness of
+ // operators * and ->.
+
+ cu_info &
+ operator* ()
+ {
+ return m_info;
+ }
+
+ cu_info *
+ operator-> ()
+ {
+ return &**this;
+ }
+ };
+
+ // 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>
+ {
+ Dwarf_Die m_die;
+
+ child_iterator ()
+ : m_die ({.addr = (void *) -1})
+ {}
+
+ public:
+ explicit child_iterator (Dwarf_Die parent)
+ {
+ if (! elfutils::libdw_impl::dwpp_child (parent, m_die))
+ *this = end ();
+ }
+
+ child_iterator (child_iterator const &that)
+ : m_die (that.m_die)
+ {}
+
+ // Return a child_iterator pointing one after the last actual
+ // child.
+ static child_iterator
+ end ()
+ {
+ return child_iterator ();
+ }
+
+ bool
+ operator== (child_iterator const &that) const
+ {
+ return m_die.addr == that.m_die.addr;
+ }
+
+ bool
+ operator!= (child_iterator const &that) const
+ {
+ return ! (*this == that);
+ }
+
+ child_iterator
+ operator++ ()
+ {
+ assert (*this != end ());
+ if (! elfutils::libdw_impl::dwpp_siblingof (m_die, m_die))
+ *this = end ();
+ return *this;
+ }
+
+ child_iterator
+ operator++ (int)
+ {
+ child_iterator ret = *this;
+ ++*this;
+ return ret;
+ }
+
+ // N.B. see top of the file for explanation of non-constness of
+ // operators * and ->.
+
+ Dwarf_Die &
+ operator* ()
+ {
+ assert (*this != end ());
+ return m_die;
+ }
+
+ Dwarf_Die *
+ operator-> ()
+ {
+ return &**this;
+ }
+ };
+
+ // 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>
+ {
+ public:
+ typedef std::vector <Dwarf_Die> stack_type;
+
+ private:
+ cu_iterator m_cuit;
+ // Internally, only offsets are kept on the stack.
+ std::vector <Dwarf_Off> m_stack;
+ Dwarf_Die m_die;
+
+ die_tree_iterator (Dwarf_Off offset)
+ : m_cuit (cu_iterator::end ())
+ {}
+
+ public:
+ explicit die_tree_iterator (Dwarf *dw)
+ : die_tree_iterator (cu_iterator (dw))
+ {}
+
+ explicit die_tree_iterator (cu_iterator const &cuit)
+ : m_cuit (cuit)
+ , m_die (m_cuit->cudie)
+ {}
+
+ die_tree_iterator (die_tree_iterator const &that)
+ : m_cuit (that.m_cuit)
+ , m_stack (that.m_stack)
+ , m_die (that.m_die)
+ {}
+
+ // Return a die_tree_iterator pointing one after the last actual
+ // DIE.
+ static die_tree_iterator
+ end ()
+ {
+ return die_tree_iterator ((Dwarf_Off) -1);
+ }
+
+ bool
+ operator== (die_tree_iterator const &that) const
+ {
+ return m_cuit == that.m_cuit
+ && m_stack == that.m_stack
+ && (m_cuit == cu_iterator::end ()
+ || m_die.addr == that.m_die.addr);
+ }
+
+ bool
+ operator!= (die_tree_iterator const &that) const
+ {
+ return ! (*this == that);
+ }
+
+ die_tree_iterator
+ operator++ ()
+ {
+ Dwarf_Die child;
+ if (elfutils::libdw_impl::dwpp_child (m_die, child))
+ {
+ m_stack.push_back (dwarf_dieoffset (&m_die));
+ m_die = child;
+ return *this;
+ }
+
+ do
+ if (elfutils::libdw_impl::dwpp_siblingof (m_die, m_die))
+ return *this;
+ else
+ // No sibling found. Go a level up and retry, unless this
+ // was a sole, childless CU DIE.
+ if (! m_stack.empty ())
+ {
+ m_die = elfutils::libdw_impl::dwpp_offdie (m_cuit.m_dw,
+ m_stack.back ());
+ m_stack.pop_back ();
+ }
+ while (! m_stack.empty ());
+
+ m_die = (++m_cuit)->cudie;
+ return *this;
+ }
+
+ die_tree_iterator
+ operator++ (int)
+ {
+ die_tree_iterator prev = *this;
+ ++*this;
+ return prev;
+ }
+
+ // N.B. see top of the file for explanation of non-constness of
+ // operators * and ->.
+
+ Dwarf_Die &
+ operator* ()
+ {
+ return m_die;
+ }
+
+ Dwarf_Die *
+ operator-> ()
+ {
+ return &**this;
+ }
+
+ // 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
+ {
+ 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;
+ }
+
+ // Return a die_tree_iterator pointing at a parent of a DIE that
+ // this iterator points at. Returns an end iterator if there is
+ // no parent.
+ die_tree_iterator
+ parent () const
+ {
+ assert (*this != end ());
+ if (m_stack.empty ())
+ return end ();
+
+ die_tree_iterator ret = *this;
+ ret.m_die = elfutils::libdw_impl::dwpp_offdie (m_cuit.m_dw,
+ m_stack.back ());
+ ret.m_stack.pop_back ();
+ return ret;
+ }
+
+ // Return a CU iterator representing a CU that the current DIE
+ // comes from.
+ cu_iterator
+ cu () const
+ {
+ return m_cuit;
+ }
+ };
+
+ // An attribute iterator goes through attributes of a given DIE.
+ class attr_iterator
+ : public std::iterator <std::input_iterator_tag, Dwarf_Attribute>
+ {
+ Dwarf_Die *m_die;
+ Dwarf_Attribute m_at;
+ ptrdiff_t m_offset;
+
+ struct cb_data
+ {
+ Dwarf_Attribute *at;
+ 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 = end ();
+ return;
+ }
+
+ cb_data data = {&m_at, false};
+ m_offset = dwarf_getattrs (m_die, &callback, &data, m_offset);
+ if (m_offset == -1)
+ elfutils::libdw_impl::throw_libdw ();
+ }
+
+ attr_iterator (ptrdiff_t offset)
+ : m_die (NULL)
+ , m_at ({0})
+ , m_offset (offset)
+ {}
+
+ public:
+ attr_iterator (Dwarf_Die *die)
+ : m_die (die)
+ , m_at ({0})
+ , m_offset (0)
+ {
+ move ();
+ }
+
+ bool
+ operator== (attr_iterator const &other) const
+ {
+ return m_offset == other.m_offset
+ && m_at.code == other.m_at.code;
+ }
+
+ bool
+ operator!= (attr_iterator const &other) const
+ {
+ return ! (*this == other);
+ }
+
+ attr_iterator &
+ operator++ ()
+ {
+ assert (*this != end ());
+ move ();
+ return *this;
+ }
+
+ attr_iterator
+ operator++ (int)
+ {
+ attr_iterator tmp = *this;
+ ++*this;
+ return tmp;
+ }
+
+ // N.B. see top of the file for explanation of non-constness of
+ // operators * and ->.
+
+ Dwarf_Attribute &
+ operator* ()
+ {
+ return m_at;
+ }
+
+ Dwarf_Attribute *
+ operator-> ()
+ {
+ return &**this;
+ }
+
+ // Return an attr_iterator pointing one after the last actual
+ // attribute.
+ static attr_iterator
+ end ()
+ {
+ return attr_iterator ((ptrdiff_t) 1);
+ }
+ };
+}
+
+inline void
+elfutils::libdw_impl::throw_libdw (int dwerr)
+{
+ if (dwerr == 0)
+ dwerr = dwarf_errno ();
+ assert (dwerr != 0);
+ throw std::runtime_error (dwarf_errmsg (dwerr));
+}
+
+inline bool
+elfutils::libdw_impl::dwpp_child (Dwarf_Die &die, Dwarf_Die &result)
+{
+ int ret = dwarf_child (&die, &result);
+ if (ret < 0)
+ elfutils::libdw_impl::throw_libdw ();
+ return ret == 0;
+}
+
+inline bool
+elfutils::libdw_impl::dwpp_siblingof (Dwarf_Die &die, Dwarf_Die &result)
+{
+ switch (dwarf_siblingof (&die, &result))
+ {
+ case -1:
+ elfutils::libdw_impl::throw_libdw ();
+ case 0:
+ return true;
+ case 1:
+ return false;
+ default:
+ abort ();
+ }
+}
+
+inline Dwarf_Die
+elfutils::libdw_impl::dwpp_offdie (Dwarf *dbg, Dwarf_Off offset)
+{
+ Dwarf_Die result;
+ if (dwarf_offdie (dbg, offset, &result) == NULL)
+ throw_libdw ();
+ return result;
+}
+
+#endif
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index d40dbae..45772b1 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,9 @@
+2015-03-17 Petr Machata <pmachata(a)redhat.com>
+
+ * c++: New directory.
+ * c++/libdwfl: New header file.
+ * Makefile.am: Install it.
+
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..8d4a0f1 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
@@ -39,6 +39,9 @@ noinst_LIBRARIES += libdwfl_pic.a
pkginclude_HEADERS = libdwfl.h
+cppdir = $(pkgincludedir)/c++
+cpp_HEADERS = c++/libdwfl
+
libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c dwfl_version.c \
dwfl_module.c dwfl_report_elf.c relocate.c \
dwfl_module_build_id.c dwfl_module_report_build_id.c \
diff --git a/libdwfl/c++/libdwfl b/libdwfl/c++/libdwfl
new file mode 100644
index 0000000..9243f14
--- /dev/null
+++ b/libdwfl/c++/libdwfl
@@ -0,0 +1,227 @@
+/* -*-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 <stdexcept>
+#include <cassert>
+#include <string>
+#include <elfutils/libdwfl.h>
+
+namespace elfutils
+{
+ // Helper functions. Not for client consumption.
+ namespace libdwfl_impl
+ {
+ inline void throw_libdwfl (int dwerr = 0);
+ }
+
+ // 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 *>
+ {
+ Dwfl *m_dwfl;
+ ptrdiff_t m_offset;
+ Dwfl_Module *m_module;
+
+ static int
+ module_cb (Dwfl_Module *mod, void **data, const char *name,
+ Dwarf_Addr addr, void *arg)
+ {
+ elfutils::dwfl_module_iterator *self
+ = static_cast <elfutils::dwfl_module_iterator *> (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)
+ elfutils::libdwfl_impl::throw_libdwfl ();
+ }
+
+ explicit dwfl_module_iterator (ptrdiff_t off)
+ : m_dwfl (NULL)
+ , m_offset (off)
+ {}
+
+ public:
+ dwfl_module_iterator (Dwfl *dwfl)
+ : m_dwfl (dwfl)
+ , m_offset (0)
+ {
+ move ();
+ }
+
+ dwfl_module_iterator (const dwfl_module_iterator &that)
+ : m_dwfl (that.m_dwfl)
+ , m_offset (that.m_offset)
+ , m_module (that.m_module)
+ {}
+
+ static dwfl_module_iterator
+ end ()
+ {
+ return dwfl_module_iterator ((ptrdiff_t) 0);
+ }
+
+ dwfl_module_iterator &
+ operator++ ()
+ {
+ assert (*this != end ());
+ move ();
+ return *this;
+ }
+
+ dwfl_module_iterator
+ operator++ (int)
+ {
+ dwfl_module_iterator ret = *this;
+ ++*this;
+ return ret;
+ }
+
+ Dwfl_Module &
+ operator* () const
+ {
+ return *m_module;
+ }
+
+ Dwfl_Module *
+ operator-> () const
+ {
+ return &**this;
+ }
+
+ bool
+ operator== (const dwfl_module_iterator &that) const
+ {
+ assert (m_dwfl == NULL || that.m_dwfl == NULL || m_dwfl == that.m_dwfl);
+ return m_offset == that.m_offset;
+ }
+
+ bool
+ operator!= (const dwfl_module_iterator &that) const
+ {
+ return !(*this == that);
+ }
+ };
+
+
+ // RAII-style wrapper around dwfl_report_* calls.
+ //
+ // Example usage:
+ // {
+ // elfutils::dwfl_report r (dwfl);
+ // r.report_offline (fn, fn, fd);
+ // }
+
+ class dwfl_report
+ {
+ Dwfl *m_dwfl;
+
+ Dwfl_Module *
+ reported (Dwfl_Module *mod)
+ {
+ if (mod == NULL)
+ elfutils::libdwfl_impl::throw_libdwfl ();
+ return mod;
+ }
+
+ public:
+ explicit dwfl_report (Dwfl *dwfl)
+ : m_dwfl ((assert (dwfl != NULL), dwfl))
+ {
+ dwfl_report_begin_add (m_dwfl);
+ }
+
+ ~dwfl_report ()
+ {
+ dwfl_report_end (m_dwfl, NULL, NULL);
+ }
+
+ Dwfl_Module *
+ report_module (const char *name, Dwarf_Addr start, Dwarf_Addr end)
+ {
+ return reported (dwfl_report_module (m_dwfl, name, start, end));
+ }
+
+ Dwfl_Module *
+ report_module (const std::string &name, Dwarf_Addr start, Dwarf_Addr end)
+ {
+ return report_module (name.c_str (), start, end);
+ }
+
+ Dwfl_Module *
+ report_elf (const char *name, const char *file_name, int fd,
+ GElf_Addr base, bool add_p_vaddr)
+ {
+ return reported (dwfl_report_elf (m_dwfl, name, file_name, fd,
+ base, add_p_vaddr));
+ }
+
+ Dwfl_Module *
+ report_elf (const std::string &name, const std::string &file_name, int fd,
+ GElf_Addr base, bool add_p_vaddr)
+ {
+ return report_elf (name.c_str (), file_name.c_str (), fd,
+ base, add_p_vaddr);
+ }
+
+ Dwfl_Module *
+ report_offline (const char *name, const char *file_name, int fd)
+ {
+ return reported (dwfl_report_offline (m_dwfl, name, file_name, fd));
+ }
+
+ Dwfl_Module *
+ report_offline (const std::string &name, const std::string &file_name, int fd)
+ {
+ return report_offline (name.c_str (), file_name.c_str (), fd);
+ }
+ };
+}
+
+inline void
+elfutils::libdwfl_impl::throw_libdwfl (int dwerr)
+{
+ if (dwerr == 0)
+ dwerr = dwfl_errno ();
+ assert (dwerr != 0);
+ throw std::runtime_error (dwfl_errmsg (dwerr));
+}
+
+#endif
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b03f62e..514b8a2 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 \
@@ -429,6 +434,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) $(libelf)
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..983fbd9
--- /dev/null
+++ b/tests/run-test-iterators.sh
@@ -0,0 +1,29 @@
+#! /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
+
+testrun_compare ${abs_top_builddir}/tests/test-iterators testfile39 <<\EOF
+0
+0x93
+0x12a
+0x1bd
+EOF
+
+exit 0
diff --git a/tests/test-iterators.cc b/tests/test-iterators.cc
new file mode 100644
index 0000000..732ea78
--- /dev/null
+++ b/tests/test-iterators.cc
@@ -0,0 +1,50 @@
+/* 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 <elfutils/c++/libdw>
+
+int
+main (int argc, char *argv[])
+{
+ int fd = open (argv[1], O_RDONLY);
+ if (fd < 0)
+ throw std::runtime_error (strerror (errno));
+
+ Dwarf *dw = dwarf_begin (fd, DWARF_C_READ);
+ std::vector <std::pair <elfutils::cu_iterator, Dwarf_Die> > cudies;
+ for (elfutils::cu_iterator it (dw); it != elfutils::cu_iterator::end (); ++it)
+ cudies.push_back (std::make_pair (it, it->cudie));
+
+ for (size_t i = 0; i < cudies.size (); ++i)
+ {
+ elfutils::cu_iterator jt (dw, cudies[i].second);
+ std::cerr << std::hex << std::showbase << jt.offset () << std::endl;
+ size_t j = i;
+ for (; jt != elfutils::cu_iterator::end (); ++jt, ++j)
+ assert (jt == cudies[j].first);
+ }
+
+ assert (elfutils::die_tree_iterator (elfutils::cu_iterator::end ())
+ == elfutils::die_tree_iterator::end ());
+}
--
2.1.0
8 years, 11 months
[PATCH] Publish known-dwarf.h
by Petr Machata
- Make the macro names properly scoped (DWARF_ALL_KNOWN_* and
DWARF_ONE_KNOWN_*).
- Simplify the calling convention: don't keep track of the comment
associated with the enumerator, always use the non-_DESC
DWARF_ONE_KNOWN_* callback.
- Install known-dwarf.h alongside libdw.h and others.
Signed-off-by: Petr Machata <pmachata(a)redhat.com>
---
config/ChangeLog | 7 ++++
config/known-dwarf.awk | 13 ++------
libdw/ChangeLog | 5 +++
libdw/Makefile.am | 4 +--
src/ChangeLog | 11 ++++++
src/readelf.c | 90 ++++++++++++++++++++++++--------------------------
tests/ChangeLog | 8 +++++
tests/addrcfi.c | 10 +++---
tests/allregs.c | 8 ++---
tests/show-die-info.c | 14 ++++----
tests/varlocs.c | 16 ++++-----
11 files changed, 100 insertions(+), 86 deletions(-)
diff --git a/config/ChangeLog b/config/ChangeLog
index 409e2b1..586ebb0 100644
--- a/config/ChangeLog
+++ b/config/ChangeLog
@@ -1,3 +1,10 @@
+2015-03-18 Petr Machata <pmachata(a)redhat.com>
+
+ * known-dwarf.awk (comment): Drop all uses of this variable.
+ (END): Always emit the non-_DESC variant. Emit
+ DWARF_ALL_KNOWN_DW_ instead of ALL_KNOWN_DW_*, and
+ DWARF_ONE_KNOWN_DW_ instead of ONE_KNOWN_DW_*.
+
2015-02-20 Petr Machata <pmachata(a)redhat.com>
* known-dwarf.awk (END): Drop useless variables lo, hi. Merge two
diff --git a/config/known-dwarf.awk b/config/known-dwarf.awk
index 4d89f0f..bc9b02d 100755
--- a/config/known-dwarf.awk
+++ b/config/known-dwarf.awk
@@ -33,11 +33,6 @@ $1 ~ /DW([_A-Z]+)_([^ ]+)/ {
DW[set] = DW[set] "," elt;
else
DW[set] = elt;
- if ($NF == "*/" && $4 == "/*") {
- c = $5;
- for (i = 6; i < NF; ++i) c = c " " $i;
- comment[set, elt] = c;
- }
}
END {
@@ -49,16 +44,12 @@ END {
split(DW[set], elts, ",");
m = asort(elts);
if (m == 0) continue;
- print "\n#define ALL_KNOWN_DW_" set " \\";
+ print "\n#define DWARF_ALL_KNOWN_DW_" set " \\";
for (j = 1; j <= m; ++j) {
elt = elts[j];
if (elt ~ /(low?|hi|high)_user$/)
continue;
- if (comment[set, elt])
- print " ONE_KNOWN_DW_" set "_DESC (" elt ", DW_" set "_" elt \
- ", \"" comment[set, elt] "\") \\";
- else
- print " ONE_KNOWN_DW_" set " (" elt ", DW_" set "_" elt ") \\";
+ print " DWARF_ONE_KNOWN_DW_" set " (" elt ", DW_" set "_" elt ") \\";
}
print " /* End of DW_" set "_*. */";
}
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 9c996f0..aa9fbd2 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2015-03-18 Petr Machata <pmachata(a)redhat.com>
+
+ * Makefile.am (pkginclude_HEADERS): Add known-dwarf.h.
+ (EXTRA_DIST): Remove known-dwarf.h.
+
2015-03-17 Petr Machata <pmachata(a)redhat.com>
* c++: New directory.
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index 771db9e..0bd8115 100644
--- a/libdw/Makefile.am
+++ b/libdw/Makefile.am
@@ -39,7 +39,7 @@ noinst_LIBRARIES = libdw_pic.a
noinst_PROGRAMS = $(noinst_LIBRARIES:_pic.a=.so)
include_HEADERS = dwarf.h
-pkginclude_HEADERS = libdw.h
+pkginclude_HEADERS = libdw.h known-dwarf.h
cppdir = $(pkgincludedir)/c++
cpp_HEADERS = c++/libdw
@@ -140,6 +140,6 @@ 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 known-dwarf.h
+EXTRA_DIST = libdw.map
MOSTLYCLEANFILES = $(am_libdw_pic_a_OBJECTS) libdw.so.$(VERSION)
diff --git a/src/ChangeLog b/src/ChangeLog
index dad984e..b6224cb 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,14 @@
+2015-03-18 Petr Machata <pmachata(a)redhat.com>
+
+ * readelf.c (dwarf_tag_string, dwarf_attr_string)
+ (dwarf_form_string, dwarf_lang_string, dwarf_inline_string)
+ (dwarf_encoding_string, dwarf_access_string)
+ (dwarf_visibility_string, dwarf_virtuality_string)
+ (dwarf_identifier_case_string, dwarf_calling_convention_string)
+ (dwarf_ordering_string, dwarf_discr_list_string)
+ (dwarf_locexpr_opcode_string): Adjust uses of know-dwarf.h macros
+ to match the API changes.
+
2015-01-03 Mark Wielaard <mjw(a)redhat.com>
* elfcmp (main): Check section name is not NULL. Check sh_entsize
diff --git a/src/readelf.c b/src/readelf.c
index 237975f..23bd73f 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -1,5 +1,5 @@
/* Print information from ELF file in human-readable form.
- Copyright (C) 1999-2014 Red Hat, Inc.
+ Copyright (C) 1999-2015 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper(a)redhat.com>, 1999.
@@ -3566,9 +3566,9 @@ dwarf_tag_string (unsigned int tag)
{
switch (tag)
{
-#define ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
- ALL_KNOWN_DW_TAG
-#undef ONE_KNOWN_DW_TAG
+#define DWARF_ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
+ DWARF_ALL_KNOWN_DW_TAG
+#undef DWARF_ONE_KNOWN_DW_TAG
default:
return NULL;
}
@@ -3580,9 +3580,9 @@ dwarf_attr_string (unsigned int attrnum)
{
switch (attrnum)
{
-#define ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
- ALL_KNOWN_DW_AT
-#undef ONE_KNOWN_DW_AT
+#define DWARF_ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
+ DWARF_ALL_KNOWN_DW_AT
+#undef DWARF_ONE_KNOWN_DW_AT
default:
return NULL;
}
@@ -3594,11 +3594,9 @@ dwarf_form_string (unsigned int form)
{
switch (form)
{
-#define ONE_KNOWN_DW_FORM_DESC(NAME, CODE, DESC) ONE_KNOWN_DW_FORM (NAME, CODE)
-#define ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME;
- ALL_KNOWN_DW_FORM
-#undef ONE_KNOWN_DW_FORM
-#undef ONE_KNOWN_DW_FORM_DESC
+#define DWARF_ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME;
+ DWARF_ALL_KNOWN_DW_FORM
+#undef DWARF_ONE_KNOWN_DW_FORM
default:
return NULL;
}
@@ -3610,9 +3608,9 @@ dwarf_lang_string (unsigned int lang)
{
switch (lang)
{
-#define ONE_KNOWN_DW_LANG_DESC(NAME, CODE, DESC) case CODE: return #NAME;
- ALL_KNOWN_DW_LANG
-#undef ONE_KNOWN_DW_LANG_DESC
+#define DWARF_ONE_KNOWN_DW_LANG(NAME, CODE) case CODE: return #NAME;
+ DWARF_ALL_KNOWN_DW_LANG
+#undef DWARF_ONE_KNOWN_DW_LANG
default:
return NULL;
}
@@ -3624,9 +3622,9 @@ dwarf_inline_string (unsigned int code)
{
static const char *const known[] =
{
-#define ONE_KNOWN_DW_INL(NAME, CODE) [CODE] = #NAME,
- ALL_KNOWN_DW_INL
-#undef ONE_KNOWN_DW_INL
+#define DWARF_ONE_KNOWN_DW_INL(NAME, CODE) [CODE] = #NAME,
+ DWARF_ALL_KNOWN_DW_INL
+#undef DWARF_ONE_KNOWN_DW_INL
};
if (likely (code < sizeof (known) / sizeof (known[0])))
@@ -3641,9 +3639,9 @@ dwarf_encoding_string (unsigned int code)
{
static const char *const known[] =
{
-#define ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
- ALL_KNOWN_DW_ATE
-#undef ONE_KNOWN_DW_ATE
+#define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
+ DWARF_ALL_KNOWN_DW_ATE
+#undef DWARF_ONE_KNOWN_DW_ATE
};
if (likely (code < sizeof (known) / sizeof (known[0])))
@@ -3658,9 +3656,9 @@ dwarf_access_string (unsigned int code)
{
static const char *const known[] =
{
-#define ONE_KNOWN_DW_ACCESS(NAME, CODE) [CODE] = #NAME,
- ALL_KNOWN_DW_ACCESS
-#undef ONE_KNOWN_DW_ACCESS
+#define DWARF_ONE_KNOWN_DW_ACCESS(NAME, CODE) [CODE] = #NAME,
+ DWARF_ALL_KNOWN_DW_ACCESS
+#undef DWARF_ONE_KNOWN_DW_ACCESS
};
if (likely (code < sizeof (known) / sizeof (known[0])))
@@ -3675,9 +3673,9 @@ dwarf_visibility_string (unsigned int code)
{
static const char *const known[] =
{
-#define ONE_KNOWN_DW_VIS(NAME, CODE) [CODE] = #NAME,
- ALL_KNOWN_DW_VIS
-#undef ONE_KNOWN_DW_VIS
+#define DWARF_ONE_KNOWN_DW_VIS(NAME, CODE) [CODE] = #NAME,
+ DWARF_ALL_KNOWN_DW_VIS
+#undef DWARF_ONE_KNOWN_DW_VIS
};
if (likely (code < sizeof (known) / sizeof (known[0])))
@@ -3692,9 +3690,9 @@ dwarf_virtuality_string (unsigned int code)
{
static const char *const known[] =
{
-#define ONE_KNOWN_DW_VIRTUALITY(NAME, CODE) [CODE] = #NAME,
- ALL_KNOWN_DW_VIRTUALITY
-#undef ONE_KNOWN_DW_VIRTUALITY
+#define DWARF_ONE_KNOWN_DW_VIRTUALITY(NAME, CODE) [CODE] = #NAME,
+ DWARF_ALL_KNOWN_DW_VIRTUALITY
+#undef DWARF_ONE_KNOWN_DW_VIRTUALITY
};
if (likely (code < sizeof (known) / sizeof (known[0])))
@@ -3709,9 +3707,9 @@ dwarf_identifier_case_string (unsigned int code)
{
static const char *const known[] =
{
-#define ONE_KNOWN_DW_ID(NAME, CODE) [CODE] = #NAME,
- ALL_KNOWN_DW_ID
-#undef ONE_KNOWN_DW_ID
+#define DWARF_ONE_KNOWN_DW_ID(NAME, CODE) [CODE] = #NAME,
+ DWARF_ALL_KNOWN_DW_ID
+#undef DWARF_ONE_KNOWN_DW_ID
};
if (likely (code < sizeof (known) / sizeof (known[0])))
@@ -3726,9 +3724,9 @@ dwarf_calling_convention_string (unsigned int code)
{
static const char *const known[] =
{
-#define ONE_KNOWN_DW_CC(NAME, CODE) [CODE] = #NAME,
- ALL_KNOWN_DW_CC
-#undef ONE_KNOWN_DW_CC
+#define DWARF_ONE_KNOWN_DW_CC(NAME, CODE) [CODE] = #NAME,
+ DWARF_ALL_KNOWN_DW_CC
+#undef DWARF_ONE_KNOWN_DW_CC
};
if (likely (code < sizeof (known) / sizeof (known[0])))
@@ -3743,9 +3741,9 @@ dwarf_ordering_string (unsigned int code)
{
static const char *const known[] =
{
-#define ONE_KNOWN_DW_ORD(NAME, CODE) [CODE] = #NAME,
- ALL_KNOWN_DW_ORD
-#undef ONE_KNOWN_DW_ORD
+#define DWARF_ONE_KNOWN_DW_ORD(NAME, CODE) [CODE] = #NAME,
+ DWARF_ALL_KNOWN_DW_ORD
+#undef DWARF_ONE_KNOWN_DW_ORD
};
if (likely (code < sizeof (known) / sizeof (known[0])))
@@ -3760,9 +3758,9 @@ dwarf_discr_list_string (unsigned int code)
{
static const char *const known[] =
{
-#define ONE_KNOWN_DW_DSC(NAME, CODE) [CODE] = #NAME,
- ALL_KNOWN_DW_DSC
-#undef ONE_KNOWN_DW_DSC
+#define DWARF_ONE_KNOWN_DW_DSC(NAME, CODE) [CODE] = #NAME,
+ DWARF_ALL_KNOWN_DW_DSC
+#undef DWARF_ONE_KNOWN_DW_DSC
};
if (likely (code < sizeof (known) / sizeof (known[0])))
@@ -3780,11 +3778,9 @@ dwarf_locexpr_opcode_string (unsigned int code)
/* Normally we can't affort building huge table of 64K entries,
most of them zero, just because there are a couple defined
values at the far end. In case of opcodes, it's OK. */
-#define ONE_KNOWN_DW_OP_DESC(NAME, CODE, DESC) ONE_KNOWN_DW_OP (NAME, CODE)
-#define ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
- ALL_KNOWN_DW_OP
-#undef ONE_KNOWN_DW_OP
-#undef ONE_KNOWN_DW_OP_DESC
+#define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
+ DWARF_ALL_KNOWN_DW_OP
+#undef DWARF_ONE_KNOWN_DW_OP
};
if (likely (code < sizeof (known) / sizeof (known[0])))
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 223fab4..a14315a 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,5 +1,13 @@
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.
+ * show-die-info.c (dwarf_tag_string, dwarf_attr_string): Likewise.
+ * varlocs.c (dwarf_encoding_string, dwarf_opcode_string): Likewise.
+
+2015-03-18 Petr Machata <pmachata(a)redhat.com>
+
* Makefile.am (EXTRA_DIST): Add run-dwarf-ranges.sh,
debug-ranges-no-lowpc.o.bz2.
diff --git a/tests/addrcfi.c b/tests/addrcfi.c
index 8a2d126..eb950c0 100644
--- a/tests/addrcfi.c
+++ b/tests/addrcfi.c
@@ -1,5 +1,5 @@
/* Test program for CFI handling.
- Copyright (C) 2009-2010, 2013 Red Hat, Inc.
+ Copyright (C) 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
@@ -34,11 +34,9 @@ op_name (unsigned int code)
{
static const char *const known[] =
{
-#define ONE_KNOWN_DW_OP_DESC(NAME, CODE, DESC) ONE_KNOWN_DW_OP (NAME, CODE)
-#define ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
- ALL_KNOWN_DW_OP
-#undef ONE_KNOWN_DW_OP
-#undef ONE_KNOWN_DW_OP_DESC
+#define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
+ DWARF_ALL_KNOWN_DW_OP
+#undef DWARF_ONE_KNOWN_DW_OP
};
if (likely (code < sizeof (known) / sizeof (known[0])))
diff --git a/tests/allregs.c b/tests/allregs.c
index b103ce1..901d4e8 100644
--- a/tests/allregs.c
+++ b/tests/allregs.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005, 2006 Red Hat, Inc.
+/* Copyright (C) 2005, 2006, 2015 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -35,9 +35,9 @@ dwarf_encoding_string (unsigned int code)
{
static const char *const known[] =
{
-#define ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
- ALL_KNOWN_DW_ATE
-#undef ONE_KNOWN_DW_ATE
+#define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
+ DWARF_ALL_KNOWN_DW_ATE
+#undef DWARF_ONE_KNOWN_DW_ATE
};
if (likely (code < sizeof (known) / sizeof (known[0])))
diff --git a/tests/show-die-info.c b/tests/show-die-info.c
index 0c298ac..34e27a3 100644
--- a/tests/show-die-info.c
+++ b/tests/show-die-info.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998-2002, 2004, 2006, 2012 Red Hat, Inc.
+/* Copyright (C) 1998-2002, 2004, 2006, 2012, 2015 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper(a)redhat.com>, 1998.
@@ -33,9 +33,9 @@ dwarf_tag_string (unsigned int tag)
{
switch (tag)
{
-#define ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
- ALL_KNOWN_DW_TAG
-#undef ONE_KNOWN_DW_TAG
+#define DWARF_ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
+ DWARF_ALL_KNOWN_DW_TAG
+#undef DWARF_ONE_KNOWN_DW_TAG
default:
return NULL;
}
@@ -46,9 +46,9 @@ dwarf_attr_string (unsigned int attrnum)
{
switch (attrnum)
{
-#define ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
- ALL_KNOWN_DW_AT
-#undef ONE_KNOWN_DW_AT
+#define DWARF_ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
+ DWARF_ALL_KNOWN_DW_AT
+#undef DWARF_ONE_KNOWN_DW_AT
default:
return NULL;
}
diff --git a/tests/varlocs.c b/tests/varlocs.c
index 04f17ff..b5733e7 100644
--- a/tests/varlocs.c
+++ b/tests/varlocs.c
@@ -1,5 +1,5 @@
/* Test program for dwarf location functions.
- Copyright (C) 2013 Red Hat, Inc.
+ Copyright (C) 2013, 2015 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -64,9 +64,9 @@ dwarf_encoding_string (unsigned int code)
{
static const char *const known[] =
{
-#define ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
- ALL_KNOWN_DW_ATE
-#undef ONE_KNOWN_DW_ATE
+#define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
+ DWARF_ALL_KNOWN_DW_ATE
+#undef DWARF_ONE_KNOWN_DW_ATE
};
if (likely (code < sizeof (known) / sizeof (known[0])))
@@ -108,11 +108,9 @@ dwarf_opcode_string (unsigned int code)
{
static const char *const known[] =
{
-#define ONE_KNOWN_DW_OP_DESC(NAME, CODE, DESC) ONE_KNOWN_DW_OP (NAME, CODE)
-#define ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
- ALL_KNOWN_DW_OP
-#undef ONE_KNOWN_DW_OP
-#undef ONE_KNOWN_DW_OP_DESC
+#define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
+ DWARF_ALL_KNOWN_DW_OP
+#undef DWARF_ONE_KNOWN_DW_OP
};
if (likely (code < sizeof (known) / sizeof (known[0])))
--
2.1.0
8 years, 11 months
[PATCH] libelf: Don't extend ELF file size with SHT_NOBITS sh_offset.
by Mark Wielaard
Don't explicitly extend the file size for SHT_NOBITS sections. Since
that could cause a size beyond any actual file content it will cause
issues when the underlying ELF file has been mmapped or will extend
the file size to increase (writing fill bytes) when not mmapped. The
sh_offset value is essentially meaningless for SHT_NOBITS. gabi says
that a NOBITS section sh_offset member locates the "conceptual
placement" in the file. But it doesn't say this cannot be beyond the
enf of the file. When ELF_F_LAYOUT is set we should trust sh_offset
as given is what is wanted for an SHT_NOBITS section without extending
the file size.
https://bugzilla.redhat.com/show_bug.cgi?id=1020842
Buggy binutils ld could generate files where SHT_NOBITS sections have
sh_offset outside the file.
https://sourceware.org/bugzilla/show_bug.cgi?id=12921
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libelf/ChangeLog | 5 +++++
libelf/elf32_updatenull.c | 7 +++----
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 5739c77..dc9892f 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,8 @@
+2015-03-23 Mark Wielaard <mjw(a)redhat.com>
+
+ * elf32_updatenull.c (updatenull_wrlock): Don't extend size with
+ SHT_NOBITS sh_offset.
+
2015-02-18 Mark Wielaard <mjw(a)redhat.com>
* libelfP.h (__libelf_set_data_list_rdlock): Make internal_function.
diff --git a/libelf/elf32_updatenull.c b/libelf/elf32_updatenull.c
index 5e809b7..d873a30 100644
--- a/libelf/elf32_updatenull.c
+++ b/libelf/elf32_updatenull.c
@@ -1,5 +1,5 @@
/* Update data structures for changes.
- Copyright (C) 2000-2010 Red Hat, Inc.
+ Copyright (C) 2000-2010, 2015 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper(a)redhat.com>, 2000.
@@ -318,9 +318,8 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
if (elf->flags & ELF_F_LAYOUT)
{
size = MAX ((GElf_Word) size,
- shdr->sh_offset
- + (shdr->sh_type != SHT_NOBITS
- ? shdr->sh_size : 0));
+ (shdr->sh_type != SHT_NOBITS
+ ? shdr->sh_offset + shdr->sh_size : 0));
/* The alignment must be a power of two. This is a
requirement from the ELF specification. Additionally
--
2.1.0
8 years, 11 months
[PATCH] backends: aarch64 can have _GLOBAL_OFFSET_TABLE_ point anywhere in .got.
by Mark Wielaard
When building with relro aarch64 splits .got in a writable and read-only
part. _GLOBAL_OFFSET_TABLE_ points to the first writable symbol, not the
start of .got.
https://bugzilla.redhat.com/show_bug.cgi?id=1201778
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
backends/ChangeLog | 5 +++++
backends/aarch64_symbol.c | 15 ++++++++++-----
2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/backends/ChangeLog b/backends/ChangeLog
index 818e8d5..0a47b75 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,8 @@
+2015-03-23 Mark Wielaard <mjw(a)redhat.com>
+
+ * aarch64_symbol.c (aarch64_check_special_symbol): Accept
+ _GLOBAL_OFFSET_TABLE_ pointing anywhere in .got.
+
2015-03-09 Mark Wielaard <mjw(a)redhat.com>
* aarch64_reloc.def (COPY): Add DYN.
diff --git a/backends/aarch64_symbol.c b/backends/aarch64_symbol.c
index 3fdc9cf..76999e4 100644
--- a/backends/aarch64_symbol.c
+++ b/backends/aarch64_symbol.c
@@ -1,5 +1,5 @@
/* AArch64 specific symbolic name handling.
- Copyright (C) 2013 Red Hat, Inc.
+ Copyright (C) 2013, 2015 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -56,8 +56,11 @@ aarch64_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
}
}
-/* If this is the _GLOBAL_OFFSET_TABLE_ symbol, then it should point to
- .got[0] even if there is a .got.plt section. */
+/* If this is the _GLOBAL_OFFSET_TABLE_ symbol, then it should point in
+ the .got even if there is a .got.plt section.
+ https://sourceware.org/ml/libc-ports/2013-06/msg00057.html
+ https://bugzilla.redhat.com/show_bug.cgi?id=1201778
+ */
bool
aarch64_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr, const GElf_Sym *sym,
const char *name, const GElf_Shdr *destshdr)
@@ -66,7 +69,8 @@ aarch64_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr, const GElf_Sym *sym,
&& strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
{
const char *sname = elf_strptr (elf, ehdr->e_shstrndx, destshdr->sh_name);
- if (sname != NULL && strcmp (sname, ".got.plt") == 0)
+ if (sname != NULL
+ && (strcmp (sname, ".got") == 0 || strcmp (sname, ".got.plt") == 0))
{
Elf_Scn *scn = NULL;
while ((scn = elf_nextscn (elf, scn)) != NULL)
@@ -77,7 +81,8 @@ aarch64_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr, const GElf_Sym *sym,
{
sname = elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name);
if (sname != NULL && strcmp (sname, ".got") == 0)
- return sym->st_value == shdr->sh_addr;
+ return (sym->st_value >= shdr->sh_addr
+ && sym->st_value < shdr->sh_addr + shdr->sh_size);
}
}
}
--
1.8.3.1
8 years, 11 months
[PATCH] Skip dynamic relocations
by H.J. Lu
Since r_offset in dynamic relocation isn't section relative, we can't
check it like relocations in relocatable objets. This fixes:
https://bugzilla.redhat.com/show_bug.cgi?id=1205789
* elflint.c (check_one_reloc): Skip dynamic relocations.
---
src/elflint.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/src/elflint.c b/src/elflint.c
index a6f9b68..d881419 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -1392,12 +1392,20 @@ section [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can be u
else if (!known_broken)
{
if (destshdr != NULL
- && GELF_R_TYPE (r_info) != 0
- && (r_offset - (ehdr->e_type == ET_REL ? 0
- : destshdr->sh_addr)) >= destshdr->sh_size)
- ERROR (gettext ("\
-section [%2d] '%s': relocation %zu: offset out of bounds\n"),
- idx, section_name (ebl, idx), cnt);
+ && GELF_R_TYPE (r_info) != 0)
+ {
+ if (ehdr->e_type == ET_REL)
+ {
+ if (r_offset >= destshdr->sh_size)
+ ERROR (gettext ("\
+ section [%2d] '%s': relocation %zu: offset out of bounds\n"),
+ idx, section_name (ebl, idx), cnt);
+ }
+ else
+ {
+ // XXX TODO Check .rel.xxx section addresses.
+ }
+ }
}
GElf_Sym sym_mem;
--
2.1.0
8 years, 12 months