Re: [PATCH] libdw: Search skeleton DIE for split compile unit DIE attributes.

2018-05-20 Thread Mark Wielaard
On Thu, May 17, 2018 at 01:28:25PM +0200, Mark Wielaard wrote:
> dwarf_attr_integrate and dwarf_hasattr_integrate should also search
> for attributes from the skeleton DIE in case the given DIE is a split
> compile unit DIE. Split compile unit DIEs inherit various attributes
> from their skeleton unit DIE in DWARF5.

Pushed to master.


[PATCH] libdw: Add new dwarf_cu_info function.

2018-05-20 Thread Mark Wielaard
This allows getting a (split) subdie lazily, only when needed.
All arguments to dwarf_get_units are optional. When not given
then unit DIE and sub DIE are not looked up. This new function
allows them to be looked up when not immediately retrieved with
dwarf_get_units, or for a Dwarf_CU gotten through some other way.

Add a new testcase to make sure the results of calling dwarf_cu_info
and dwarf_get_units are consistent.

Signed-off-by: Mark Wielaard 
---
 libdw/ChangeLog|   7 +
 libdw/Makefile.am  |   2 +-
 libdw/dwarf_cu_info.c  | 103 +
 libdw/libdw.h  |  14 +-
 libdw/libdw.map|   1 +
 tests/ChangeLog|   9 ++
 tests/Makefile.am  |   8 +-
 tests/run-unit-info.sh |  80 ++
 tests/unit-info.c  | 323 +
 9 files changed, 542 insertions(+), 5 deletions(-)
 create mode 100644 libdw/dwarf_cu_info.c
 create mode 100755 tests/run-unit-info.sh
 create mode 100644 tests/unit-info.c

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 4db0f5c1..c575f64a 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,10 @@
+2018-05-20  Mark Wielaard  
+
+   * dwarf_cu_info.c: New file.
+   * Makefile.am (libdw_a_SOURCES): Add dwarf_cu_info.c.
+   * libdw.h (dwarf_cu_info): New function declaration.
+   * libdw.map (ELFUTILS_0.171): Add dwarf_cu_info.
+
 2018-05-18  Mark Wielaard  
 
* dwarf_formudata.c (__libdw_formptr): Handle the special case
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index ba9919c4..41df4f3b 100644
--- a/libdw/Makefile.am
+++ b/libdw/Makefile.am
@@ -91,7 +91,7 @@ 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 dwarf_default_lower_bound.c \
  dwarf_die_addr_die.c dwarf_get_units.c \
- libdw_find_split_unit.c
+ libdw_find_split_unit.c dwarf_cu_info.c
 
 if MAINTAINER_MODE
 BUILT_SOURCES = $(srcdir)/known-dwarf.h
diff --git a/libdw/dwarf_cu_info.c b/libdw/dwarf_cu_info.c
new file mode 100644
index ..30aee6c7
--- /dev/null
+++ b/libdw/dwarf_cu_info.c
@@ -0,0 +1,103 @@
+/* Provides information and DIEs associated with the Dwarf_CU unit.
+   Copyright (C) 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+   Software Foundation; either version 3 of the License, or (at
+   your option) any later version
+
+   or
+
+ * 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 .  */
+
+
+#ifdef HAVE_CONFIG_H
+# include 
+#endif
+
+#include 
+#include "libdwP.h"
+
+
+int
+dwarf_cu_info (Dwarf_CU *cu,
+  Dwarf_Half *version, uint8_t *unit_type,
+  Dwarf_Die *cudie, Dwarf_Die *subdie,
+  uint64_t *unit_id,
+  uint8_t *address_size, uint8_t *offset_size)
+{
+  if (cu == NULL)
+return -1;
+
+  if (version != NULL)
+*version = cu->version;
+
+  if (unit_type != NULL)
+*unit_type = cu->unit_type;
+
+  if (cudie != NULL)
+{
+  if (cu->version >= 2 && cu->version <= 5
+ && cu->unit_type >= DW_UT_compile
+ && cu->unit_type <= DW_UT_split_type)
+   *cudie = CUDIE (cu);
+  else
+   {
+   invalid:
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+   }
+}
+
+  if (subdie != NULL)
+{
+  if (cu->version >= 2 && cu->version <= 5)
+   {
+ /* For types, return the actual type DIE.  For skeletons,
+find the associated split compile unit and return its
+DIE.  */
+ if (cu->unit_type == DW_UT_type
+ || cu->unit_type == DW_UT_split_type)
+   *subdie = SUBDIE(cu);
+ else if (cu->unit_type == DW_UT_skeleton)
+   {
+ Dwarf_CU *split_cu = __libdw_find_split_unit (cu);
+ if (split_cu != NULL)
+   *subdie = CUDIE(split_cu);
+ else
+   memset (subdie, '\0', sizeof (Dwarf_Die));
+   }
+ else
+   memset (subdie, '\0', sizeof (Dwarf_Die));
+   }
+  else
+   goto invalid;
+}
+
+  if (unit_id != NULL)
+*unit_id = cu->unit_id8;
+
+

[PATCH] readelf: print split CUs when given --debug-dump=info+

2018-05-20 Thread Mark Wielaard
To show the difference between "regular" CUs and split CUs print
offsets and references between { and } instead of [ and ].

When --debug-dump=info+ is given (implied by -w) instead of
--debug-dump=info any skeleton unit will be immediately followed
by the corresponding split compile unit (from the .dwo file).

DWARF section [27] '.debug_info' at offset 0x1075:
 [Offset]
 Compilation unit at offset 0:
 Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
 Unit type: skeleton (4), Unit id: 0xc152129eb4b99599
 [ b]  compile_unit abbrev: 1
   ranges   (sec_offset) range list [ 0]
   low_pc   (addr) +00
   stmt_list(sec_offset) 0
   GNU_dwo_name (strp) "foo.dwo"
   comp_dir (strp) "/tmp"
   GNU_pubnames (flag_present) yes
   GNU_addr_base(sec_offset) 0
   GNU_dwo_id   (data8) 0xc152129eb4b99599
   GNU_ranges_base  (sec_offset) 0
 Split compilation unit at offset 0:
 Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
 Unit type: skeleton (4), Unit id: 0xc152129eb4b99599
 { b}  compile_unit abbrev: 1
   producer (GNU_str_index) "GNU C11 7.3.0 -gsplit-dwarf -g"
   language (data1) C99 (12)
   name (GNU_str_index) "foo.c"
   comp_dir (GNU_str_index) "/tmp"
   GNU_dwo_id   (data8) 0xc152129eb4b99599
 {18}subprogram   abbrev: 2
 external (flag_present) yes
 name (GNU_str_index) "main"
 decl_file(data1) foo.c (1)
 decl_line(data1) 1
 type (ref4) {2b}
 high_pc  (data8) 3
 frame_base   (exprloc)
  [ 0] call_frame_cfa
 GNU_all_call_sites   (flag_present) yes
 {2b}base_typeabbrev: 3
 byte_size(data1) 4
 encoding (data1) signed (5)
 name (string) "int"

Signed-off-by: Mark Wielaard 
---
 src/ChangeLog |  12 ++
 src/readelf.c | 107 +-
 2 files changed, 101 insertions(+), 18 deletions(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index 9a6adab1..e1872775 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,15 @@
+2018-01-19  Mark Wielaard  
+
+   * readelf.c (options): Add info+.
+   (show_split_units): New static boolean defaulting to false.
+   (parse_opt): For all (no arg) --debug-dump set show_split_units
+   to yes. For "info+" enable section_info and show_split_units.
+   (attrcb_args): Add is_split field.
+   (attr_callback): Use is_split to format DIE offsets differently.
+   (print_debug_units): Likewise. Get subdie (type or split) only
+   when needed. When not silent reiterate over split DIEs when
+   found.
+
 2018-05-15  Mark Wielaard  
 
* readelf.c (print_debug_units): Print unit type and id for any
diff --git a/src/readelf.c b/src/readelf.c
index bb03d2c2..466d941e 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -112,7 +112,7 @@ static const struct argp_option options[] =
   { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 },
   { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
 N_("Display DWARF section content.  SECTION can be one of abbrev, "
-   "aranges, decodedaranges, frame, gdb_index, info, loc, line, "
+   "aranges, decodedaranges, frame, gdb_index, info, info+, loc, line, "
"decodedline, ranges, pubnames, str, macinfo, macro or exception"), 0 },
   { "hex-dump", 'x', "SECTION", 0,
 N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 },
@@ -215,6 +215,9 @@ static bool decodedline = false;
 /* True if we want to show more information about compressed sections.  */
 static bool print_decompress = false;
 
+/* True if we want to show split compile units for debug_info skeletons.  */
+static bool show_split_units = false;
+
 /* Select printing of debugging sections.  */
 static enum section_e
 {
@@ -422,6 +425,7 @@ parse_opt (int key, char *arg,
{
  print_debug_sections = section_all;
  implicit_debug_sections = section_info;
+ show_split_units = true;
}
   else if (strcmp (arg, "abbrev") == 0)
print_debug_sections |= section_abbrev;
@@ -441,6 +445,11 @@ parse_opt (int key, char *arg,
print_debug_sections |= section_frame;
   else if (strcmp (arg, "info") == 0)
print_debug_sections |= section_info;
+  else if (strcmp (arg, "info+") == 0)
+   {
+ print_debug_sections |= section_info;
+ show_split_units = true;
+   }
   else if (strcmp (arg, "loc") == 0)
{
  print_debug_sections |= se

Re: [PATCH] libdw: Cache ELF directory early. Explicitly set it in dwfl.

2018-05-20 Thread Mark Wielaard
On Thu, May 17, 2018 at 07:43:42PM +0200, Mark Wielaard wrote:
> The logic that finds alt files and dwo files relies on having an open
> file descriptor. But after all needed ELF data has been read the
> underlying Elf file descriptor can be closed. libdwfl in particular
> closes file descriptor fairly aggressively. So capture the directory
> early on. And make dwfl set it if it has recorded it. Which it will
> do now before closing a file descriptor for the main Dwfl_Module file.

Pushed to master.