public inbox for elfutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] libdw: Handle GNU DebugFission split ranges.
@ 2018-05-19 14:04 Mark Wielaard
  2018-05-22 22:42 ` Mark Wielaard
  2018-05-24 13:26 ` Mark Wielaard
  0 siblings, 2 replies; 3+ messages in thread
From: Mark Wielaard @ 2018-05-19 14:04 UTC (permalink / raw)
  To: elfutils-devel; +Cc: Mark Wielaard

GNU DebugFission split dwarf handles DW_FORM_sec_offset specially for
attributes that point to ranges. The .debug_ranges section is not in
the .dwo file, but in the main/skeleton object file. The sec_offset is
not relocated (in the ELF file), but is an offset against the skeleton
DIE DW_AT_GNU_ranges_base attribute. dwarf_formudata is changed so it
still looks like a normal offset ptr into the .debug_ranges section.
dwarf_ranges is adapted to look for the .debug_ranges in the main object
file. dwarf_highpc and dwarf_lowpc now handle the highpc and lowpc
attributes being inherited for the split unit DIE from the skeleton.

A new testcase is added to iterate over all ranges in a split GNU
DebugFission file.

Signed-off-by: Mark Wielaard <mark@klomp.org>
---
 libdw/ChangeLog                      |  12 ++++
 libdw/dwarf_formudata.c              |  50 +++++++++++++--
 libdw/dwarf_highpc.c                 |  18 +++---
 libdw/dwarf_lowpc.c                  |  15 ++---
 libdw/dwarf_ranges.c                 |  22 +++++--
 libdw/libdwP.h                       |  26 ++++++++
 tests/ChangeLog                      |  14 +++++
 tests/Makefile.am                    |  11 +++-
 tests/all-dwarf-ranges.c             |  90 +++++++++++++++++++++++++++
 tests/run-all-dwarf-ranges.sh        |  49 +++++++++++++++
 tests/testfile-ranges-hello.dwo.bz2  | Bin 0 -> 948 bytes
 tests/testfile-ranges-world.dwo.bz2  | Bin 0 -> 1176 bytes
 tests/testfilesplitranges4.debug.bz2 | Bin 0 -> 2154 bytes
 13 files changed, 281 insertions(+), 26 deletions(-)
 create mode 100644 tests/all-dwarf-ranges.c
 create mode 100755 tests/run-all-dwarf-ranges.sh
 create mode 100644 tests/testfile-ranges-hello.dwo.bz2
 create mode 100644 tests/testfile-ranges-world.dwo.bz2
 create mode 100755 tests/testfilesplitranges4.debug.bz2

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index e067827b..caa2d124 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,15 @@
+2018-05-18  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_formudata.c (__libdw_formptr): Handle the special case
+	of IDX_debug_ranges for DW_UT_split_compile with version < 5.
+	* dwarf_highpc.c (dwarf_highpc): Use dwarf_lowpc, check for
+	split compile cudie.
+	* dwarf_lowpc.c (dwarf_lowpc): Check for split compile cudie.
+	* dwarf_ranges.c (dwarf_ranges): Switch cu and sectiondata for
+	split compile units.
+	* libdwP.h (struct Dwarf_CU): Add ranges_base field.
+	(__libdw_cu_ranges_base): New static inline function.
+
 2018-05-18  Mark Wielaard  <mark@klomp.org>
 
 	* libdw_findcu.c (__libdw_intern_next_unit): Init files to NULL.
diff --git a/libdw/dwarf_formudata.c b/libdw/dwarf_formudata.c
index 19d34f8e..316ad865 100644
--- a/libdw/dwarf_formudata.c
+++ b/libdw/dwarf_formudata.c
@@ -43,6 +43,17 @@ __libdw_formptr (Dwarf_Attribute *attr, int sec_index,
     return NULL;
 
   const Elf_Data *d = attr->cu->dbg->sectiondata[sec_index];
+  Dwarf_CU *skel = NULL; /* See below, needed for GNU DebugFission.  */
+  if (unlikely (d == NULL
+		&& sec_index == IDX_debug_ranges
+		&& attr->cu->version < 5
+		&& attr->cu->unit_type == DW_UT_split_compile))
+    {
+      skel = __libdw_find_split_unit (attr->cu);
+      if (skel != NULL)
+	d = skel->dbg->sectiondata[IDX_debug_ranges];
+    }
+
   if (unlikely (d == NULL))
     {
       __libdw_seterrno (err_nodata);
@@ -52,10 +63,41 @@ __libdw_formptr (Dwarf_Attribute *attr, int sec_index,
   Dwarf_Word offset;
   if (attr->form == DW_FORM_sec_offset)
     {
-      if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
-			       cu_sec_idx (attr->cu), attr->valp,
-			       attr->cu->offset_size, &offset, sec_index, 0))
-	return NULL;
+      /* GNU DebugFission is slightly odd.  It uses DW_FORM_sec_offset
+	 in split units, but they are really (unrelocated) offsets
+	 from the skeleton DW_AT_GNU_ranges_base (which is only used
+	 for the split unit, not the skeleton ranges itself, see also
+	 DW_AT_rnglists_base, which is used in DWARF5 for both, but
+	 points to the offsets index).  So it isn't really a formptr,
+	 but an offset + base calculation.  */
+      if (unlikely (skel != NULL))
+	{
+	  Elf_Data *data = attr->cu->dbg->sectiondata[cu_sec_idx (attr->cu)];
+	  const unsigned char *datap = attr->valp;
+	  size_t size = attr->cu->offset_size;
+	  if (unlikely (data == NULL
+			|| datap < (const unsigned char *) data->d_buf
+			|| data->d_size < size
+			|| ((size_t) (datap
+				      - (const unsigned char *) data->d_buf)
+			    > data->d_size - size)))
+	    goto invalid;
+
+	  if (size == 4)
+	    offset = read_4ubyte_unaligned (attr->cu->dbg, datap);
+	  else
+	    offset = read_8ubyte_unaligned (attr->cu->dbg, datap);
+
+	  offset += __libdw_cu_ranges_base (skel);
+	}
+      else
+	{
+	  if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
+				   cu_sec_idx (attr->cu), attr->valp,
+				   attr->cu->offset_size, &offset,
+				   sec_index, 0))
+	    return NULL;
+	}
     }
   else if (attr->cu->version > 3)
     goto invalid;
diff --git a/libdw/dwarf_highpc.c b/libdw/dwarf_highpc.c
index 20702545..1baffa7e 100644
--- a/libdw/dwarf_highpc.c
+++ b/libdw/dwarf_highpc.c
@@ -1,7 +1,6 @@
 /* Return high PC attribute of DIE.
-   Copyright (C) 2003, 2005, 2012 Red Hat, Inc.
+   Copyright (C) 2003, 2005, 2012, 2018 Red Hat, Inc.
    This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
 
    This file is free software; you can redistribute it and/or modify
    it under the terms of either
@@ -39,8 +38,14 @@ int
 dwarf_highpc (Dwarf_Die *die, Dwarf_Addr *return_addr)
 {
   Dwarf_Attribute attr_high_mem;
-  Dwarf_Attribute *attr_high = INTUSE(dwarf_attr) (die, DW_AT_high_pc,
-						   &attr_high_mem);
+  Dwarf_Attribute *attr_high;
+  /* Split compile DIEs inherit high_pc from their skeleton DIE.  */
+  if (is_cudie (die) && die->cu->unit_type == DW_UT_split_compile)
+    attr_high = INTUSE(dwarf_attr_integrate) (die, DW_AT_high_pc,
+					      &attr_high_mem);
+  else
+    attr_high = INTUSE(dwarf_attr) (die, DW_AT_high_pc, &attr_high_mem);
+
   if (attr_high == NULL)
     return -1;
 
@@ -48,10 +53,7 @@ dwarf_highpc (Dwarf_Die *die, Dwarf_Addr *return_addr)
     return INTUSE(dwarf_formaddr) (attr_high, return_addr);
 
   /* DWARF 4 allows high_pc to be a constant offset from low_pc. */
-  Dwarf_Attribute attr_low_mem;
-  if (INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (die, DW_AT_low_pc,
-						  &attr_low_mem),
-			      return_addr) == 0)
+  if (INTUSE(dwarf_lowpc) (die, return_addr) == 0)
     {
       Dwarf_Word uval;
       if (INTUSE(dwarf_formudata) (attr_high, &uval) == 0)
diff --git a/libdw/dwarf_lowpc.c b/libdw/dwarf_lowpc.c
index b3be2b0e..4d743a72 100644
--- a/libdw/dwarf_lowpc.c
+++ b/libdw/dwarf_lowpc.c
@@ -1,7 +1,6 @@
 /* Return low PC attribute of DIE.
-   Copyright (C) 2003, 2005 Red Hat, Inc.
+   Copyright (C) 2003, 2005, 2018 Red Hat, Inc.
    This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
 
    This file is free software; you can redistribute it and/or modify
    it under the terms of either
@@ -38,10 +37,12 @@
 int
 dwarf_lowpc (Dwarf_Die *die, Dwarf_Addr *return_addr)
 {
-  Dwarf_Attribute attr_mem;
-
-  return INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (die, DW_AT_low_pc,
-						     &attr_mem),
-				 return_addr);
+  Dwarf_Attribute attr_mem, *attr;
+  /* Split compile DIEs inherit low_pc from their skeleton DIE.  */
+  if (is_cudie (die) && die->cu->unit_type == DW_UT_split_compile)
+    attr = INTUSE(dwarf_attr_integrate) (die, DW_AT_low_pc, &attr_mem);
+  else
+    attr = INTUSE(dwarf_attr) (die, DW_AT_low_pc, &attr_mem);
+  return INTUSE(dwarf_formaddr) (attr, return_addr);
 }
 INTDEF(dwarf_lowpc)
diff --git a/libdw/dwarf_ranges.c b/libdw/dwarf_ranges.c
index dbcfa2d4..b0450cf3 100644
--- a/libdw/dwarf_ranges.c
+++ b/libdw/dwarf_ranges.c
@@ -122,7 +122,17 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
 
   /* We have to look for a noncontiguous range.  */
   size_t secidx = IDX_debug_ranges;
-  const Elf_Data *d = die->cu->dbg->sectiondata[secidx];
+  Dwarf_CU *cu = die->cu;
+  const Elf_Data *d = cu->dbg->sectiondata[secidx];
+  if (d == NULL && cu->unit_type == DW_UT_split_compile)
+    {
+      Dwarf_CU *skel = __libdw_find_split_unit (cu);
+      if (skel != NULL)
+	{
+	  cu = skel;
+	  d = cu->dbg->sectiondata[secidx];
+	}
+    }
 
   const unsigned char *readp;
   const unsigned char *readendp;
@@ -131,6 +141,10 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
       Dwarf_Attribute attr_mem;
       Dwarf_Attribute *attr = INTUSE(dwarf_attr) (die, DW_AT_ranges,
 						  &attr_mem);
+      if (attr == NULL
+	  && is_cudie (die)
+	  && die->cu->unit_type == DW_UT_split_compile)
+	attr = INTUSE(dwarf_attr_integrate) (die, DW_AT_ranges, &attr_mem);
       if (attr == NULL)
 	/* No PC attributes in this DIE at all, so an empty range list.  */
 	return 0;
@@ -144,7 +158,7 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
     }
   else
     {
-      if (__libdw_offset_in_section (die->cu->dbg,
+      if (__libdw_offset_in_section (cu->dbg,
 				     secidx, offset, 1))
 	return -1;
     }
@@ -156,9 +170,9 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
   Dwarf_Addr end;
 
  next:
-  switch (__libdw_read_begin_end_pair_inc (die->cu->dbg, secidx,
+  switch (__libdw_read_begin_end_pair_inc (cu->dbg, secidx,
 					   &readp, readendp,
-					   die->cu->address_size,
+					   cu->address_size,
 					   &begin, &end, basep))
     {
     case 0:
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 7cc68fc8..01511855 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -352,6 +352,11 @@ struct Dwarf_CU
      Don't access directly, call __libdw_cu_str_off_base.  */
   Dwarf_Off str_off_base;
 
+  /* The offset into the .debug_ranges section to use for GNU
+     DebugFission split units.  Don't access directly, call
+     __libdw_cu_ranges_base.  */
+  Dwarf_Off ranges_base;
+
   /* Memory boundaries of this CU.  */
   void *startp;
   void *endp;
@@ -1054,6 +1059,27 @@ static inline Dwarf_Off __libdw_cu_str_off_base (Dwarf_CU *cu)
 }
 
 
+static inline Dwarf_Off
+__libdw_cu_ranges_base (Dwarf_CU *cu)
+{
+  if (cu->ranges_base == (Dwarf_Off) -1)
+    {
+      Dwarf_Off offset = 0;
+      Dwarf_Die cu_die = CUDIE(cu);
+      Dwarf_Attribute attr;
+      if (dwarf_attr (&cu_die, DW_AT_GNU_ranges_base, &attr) != NULL)
+	{
+	  Dwarf_Word off;
+	  if (dwarf_formudata (&attr, &off) == 0)
+	    offset = off;
+	}
+      cu->ranges_base = offset;
+    }
+
+  return cu->ranges_base;
+}
+
+
 /* Helper function to set debugdir field in Dwarf, used from dwarf_begin_elf
    and libdwfl process_file.  */
 char * __libdw_debugdir (int fd);
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 0370fbc6..a021a019 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,17 @@
+2018-05-18  Mark Wielaard  <mark@klomp.org>
+
+	* tests/Makefiles.am (check_PROGRAMS): Add all-dwarf-ranges.
+	(TESTS): Add run-all-dwarf-ranges.sh.
+	(EXTRA_DIST): Add run-all-dwarf-ranges.sh,
+	testfilesplitranges4.debug.bz2, testfile-ranges-hello.dwo.bz2
+	and testfile-ranges-world.dwo.bz2.
+	(all_dwarf_ranges_LDADD): New variable.
+	* all-dwarf-ranges.c: New test program.
+	* run-all-dwarf-ranges: New test runner.
+	* testfile-ranges-hello.dwo.bz2: New test file.
+	* testfile-ranges-world.dwo.bz2: Likewise.
+	* testfilesplitranges4.debug.bz2: Likewise.
+
 2018-05-18  Mark Wielaard  <mark@klomp.org>
 
 	* run-get-files.sh: Add testcases for testfile-splitdwarf-4,
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 05a5441b..08d84649 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -56,7 +56,8 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
 		  elfshphehdr elfstrmerge dwelfgnucompressed elfgetchdr \
 		  elfgetzdata elfputzdata zstrptr emptyfile vendorelf \
 		  fillfile dwarf_default_lower_bound dwarf-die-addr-die \
-		  get-units-invalid get-units-split attr-integrate-skel
+		  get-units-invalid get-units-split attr-integrate-skel \
+		  all-dwarf-ranges
 
 asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
 	    asm-tst6 asm-tst7 asm-tst8 asm-tst9
@@ -141,7 +142,8 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \
 	emptyfile vendorelf fillfile dwarf_default_lower_bound \
 	run-dwarf-die-addr-die.sh \
 	run-get-units-invalid.sh run-get-units-split.sh \
-	run-attr-integrate-skel.sh
+	run-attr-integrate-skel.sh \
+	run-all-dwarf-ranges.sh
 
 if !BIARCH
 export ELFUTILS_DISABLE_BIARCH = 1
@@ -366,7 +368,9 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 	     testfile-hello4.dwo.bz2 testfile-hello5.dwo.bz2 \
 	     testfile-splitdwarf-4.bz2 testfile-splitdwarf-5.bz2 \
 	     testfile-world5.dwo.bz2 testfile-world4.dwo.bz2 \
-	     run-attr-integrate-skel.sh
+	     run-attr-integrate-skel.sh \
+	     run-all-dwarf-ranges.sh testfilesplitranges4.debug.bz2 \
+	     testfile-ranges-hello.dwo.bz2 testfile-ranges-world.dwo.bz2
 
 if USE_VALGRIND
 valgrind_cmd='valgrind -q --leak-check=full --error-exitcode=1'
@@ -528,6 +532,7 @@ dwarf_die_addr_die_LDADD = $(libdw)
 get_units_invalid_LDADD = $(libdw)
 get_units_split_LDADD = $(libdw)
 attr_integrate_skel_LDADD = $(libdw)
+all_dwarf_ranges_LDADD = $(libdw)
 
 # We want to test the libelf header against the system elf.h header.
 # Don't include any -I CPPFLAGS.
diff --git a/tests/all-dwarf-ranges.c b/tests/all-dwarf-ranges.c
new file mode 100644
index 00000000..4331a05b
--- /dev/null
+++ b/tests/all-dwarf-ranges.c
@@ -0,0 +1,90 @@
+/* Test program for dwarf_ranges
+   Copyright (C) 2015, 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 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 <config.h>
+#include ELFUTILS_HEADER(dw)
+#include <dwarf.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <inttypes.h>
+
+static void
+ranges_die (Dwarf_Die *die)
+{
+  Dwarf_Addr base, start, end;
+  int ranges = dwarf_ranges (die, 0, &base, &start, &end);
+  if (ranges < 0)
+    puts (dwarf_errmsg (-1));
+  else if (ranges > 0)
+    {
+      printf ("die: %s (%x)\n", dwarf_diename (die) ?: "<unknown>",
+	      dwarf_tag (die));
+      for (ptrdiff_t off = 0;
+	   (off = dwarf_ranges (die, off, &base, &start, &end)); )
+	if (off == -1)
+	  {
+	    puts (dwarf_errmsg (-1));
+	    break;
+	  }
+	else
+	  printf (" %"PRIx64"..%"PRIx64"\n", start, end);
+      printf ("\n");
+    }
+}
+
+static void
+walk_tree (Dwarf_Die *dwarf_die)
+{
+  Dwarf_Die die = *dwarf_die;
+  do
+    {
+      Dwarf_Die child;
+      ranges_die (&die);
+      if (dwarf_child (&die, &child) == 0)
+	walk_tree (&child);
+    }
+  while (dwarf_siblingof (&die, &die) == 0);
+}
+
+int
+main (int argc, char *argv[])
+{
+  assert (argc >= 2);
+  const char *name = argv[1];
+
+  int fd = open (name, O_RDONLY);
+  Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+
+  Dwarf_CU *cu = NULL;
+  Dwarf_Die cudie, subdie;
+  uint8_t unit_type;
+  while (dwarf_get_units (dbg, cu, &cu, NULL,
+			  &unit_type, &cudie, &subdie) == 0)
+    {
+      Dwarf_Die die = (unit_type == DW_UT_skeleton
+		       ? subdie : cudie);
+      walk_tree (&die);
+    }
+  dwarf_end (dbg);
+
+  return 0;
+}
diff --git a/tests/run-all-dwarf-ranges.sh b/tests/run-all-dwarf-ranges.sh
new file mode 100755
index 00000000..0bd641b0
--- /dev/null
+++ b/tests/run-all-dwarf-ranges.sh
@@ -0,0 +1,49 @@
+#! /bin/sh
+# 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 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
+
+# See run-dwarf-ranges.sh
+# Compiled with:
+# gcc -c -O2 -o testfile-ranges-hello.o -gsplit-dwarf -gdwarf-4 hello.c
+# gcc -c -O2 -o testfile-ranges-world.o -gsplit-dwarf -gdwarf-4 world.c
+# gcc -o testfilesplitranges4 -O2 \
+#        testfile-ranges-hello.o testfile-ranges-world.o
+# eu-strip -f testfilesplitranges4.debug testfilesplitranges4
+
+testfiles testfilesplitranges4.debug
+testfiles testfile-ranges-hello.dwo testfile-ranges-world.dwo
+
+testrun_compare ${abs_builddir}/all-dwarf-ranges testfilesplitranges4.debug <<\EOF
+die: hello.c (11)
+ 4004e0..4004ff
+ 4003e0..4003f7
+
+die: world.c (11)
+ 400500..400567
+
+die: happy (1d)
+ 8009e0..8009ff
+ 8008e0..8008f7
+
+die: sad (1d)
+ 400530..400534
+ 400535..40053f
+
+EOF
+
+exit 0
diff --git a/tests/testfile-ranges-hello.dwo.bz2 b/tests/testfile-ranges-hello.dwo.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..fac246728de7fd92be344a89f85f65e41e1cbf18
GIT binary patch
literal 948
zcmV;l155luT4*^jL0KkKSxud!5C8(C|NsC0`RmW`|Nq<d_w2v_-{9~t0+oP3Ap=OD
z0R;epSqQ)a^y2L+bVi1nlT*~to|DoVP3j(@qG{@WpifZr14z>&AYw5vj39cAGeAs6
zOf;J)2B4ZFDe0yu`VwT1K$sH%0$>dWlLJV^zyY8D5DYW{rjlraWFu-Y(UN*i7-SOz
zK++mu6Vx+87!jjJ1jNBGj3=N-q?!nsFia*Unq<(#7()OfCQO)`X^0sy84MwjfSL_7
zG{C?*w?$Nk1Tx1vPP+uIxa>I%sgXEA6#bTVSI*m&00rYb9#9ojJ+nSuKYq(cVm+O~
zg5L5F>Z4&LdL;rucLP9No?<FUzIZ4=V^LJN>s{ufkiru<q9$KGU+y$UA_nhOBL@z%
z!;6vVek1vvHtPjU#80#$@rov{SVYFcp@bSz+!_YNNN{6qgl^%2QTCvh*7gOYs3JBX
zZ3chd0~)rjAsgjt14Cl^G%mw0m@Ff|1Peu?a>@WsKJt^kgaS9+3r6zPF!GeN2V*<V
zrSZvQ;f-+ZLaIj86CG`1;0UDypr~I;yNwZ{81ktRmbqvZ$6}vbj<w@qHW=_KGFc@4
zwoFi&`Tgp0#&}+%mp^Kv669+pcr6@KS|TqL9vF%Qk{BWd1Al^h5M0iI70OgBEm$6h
z0|+8Aqpy?)*)3uU#4iX6`q4v$D#0WvkVF+w{qDvp7e49+*RJsBNC{4CltbPpL`2yQ
zrit1jRG9?0v*Hzn1O%!oT?OS-5RkCLM+WEEg#?uhRRygOW6}jP1wfz)o+wgWM<%E{
znUltGC)N)IcZw_Zs(QiT)Tg$Vu<Mi|#~^TNFJh6#C5hlnGe0(7BBIF#KjjkG<+)f;
z2~U@so2mtlfLE>cEK7y48`T!p;RK+P4Q?wkip3OZ5Sbxz;<bDiPMD_Dj=lDxEx^$Z
zj>a_GlE!{NHS1<gKdhKUq2(e}i_={lMjt>ECMZo#eydYRHWj7aN+44CKoVnzKBdu6
z7_PN2Bkias_dU~$5|rjAJQrF7sz%yI6KMoh&k~yc{5&GEq9R6OM8iamux(#61wrIQ
ziq!nmqP(eG(298=j0T@GF_0g9bi58`-ATZTRTUIP48vxwEfk0l98s7?bU4yu2`oPG
z0}2@+j-|&Ik^pQo@Mw^Hb)hssKl$B6CZvh;H-!z7N&0)lC#K7m{!_P*32(WvB`U*f
WA$u-FL+B$u;_gVN3K9vkw1NPM1DdG-

literal 0
HcmV?d00001

diff --git a/tests/testfile-ranges-world.dwo.bz2 b/tests/testfile-ranges-world.dwo.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..27ad06d569224f99761f170b5aa8da1e2da65d68
GIT binary patch
literal 1176
zcmV;J1ZVp~T4*^jL0KkKS^4H-!vF(TfB*mg|LgDn|KH#J-ekZ3-{kf5B87oKpa1|6
z5P)JJ8CcK*y7dJ#Fs=}2f;AZ?YMJO$(+XrVJtl{#>NN5Y(-YJTk5f$4JW-$nL)86A
zqe1ANPy^I78iW+Wc%G@~$Z8ri4^SEa0002c00000GyniJ0jVdDQTnEVriM)o02%<(
zMu0Rl05WLE3_+ttm_eX47@0H#7)(r<34t**X^6l9FbLBlMgnP*0GSv700_Y}U?50|
zO$kqE(V$b&l=Tl&%6gus=|-774H}PAY5?^Ir~}j(H8V(Ip)}b*dXG@aqtv3m<?BUA
z>Es;fq(T%Fw5YJBJc`AM9pbf-0SqLe?Rk~hU;>IRP5?9`0rstHS)WtWPfe3C1|*}!
z80(&z44P$ycH%H)ED>X4r6g8&&2lm1w?j{>1<O8VstW5bT2Xcq%&iwY5RJx*HTI#o
zvecucmn(&zFQcN$x^@1&-G+#Oc<Gq}j$}Y2^9&LU4K_=b63J(^l?h8NFi_Cg*y^f9
zGXl$S<(6VcBW@-{LlaFZv|vi>KFv7$-FNsfE4g41vjS}!*JEl*O%IX^p94fOHkNZi
z>@z)r_m5@-s$vUFLDXwi+H0BCV9YCJ0>*4DPl6~W#f`CIJG+%*yiF*HvmT8W4ii<R
zTk-pTdfA3Rz-%6l-g=JZPM?zHR57tnA?kw;Ap%R!p&@T2IATHslN@twvg*{ZHl0+(
zt$T}ktnqDZCakSr@wjQ!o#S70>*zw#3aUwH|J!oDEA&BI77@jKnn!KAL5|FO*ebpt
zziA<im`ubE<EjK>la_M{lWfaA|8YA8=@|fI8>>(hNI?))Kv>X>*Om`vx#L)%Nb+Gq
z&rF7AFu!IUzn`&#fxBD>wAqqdqVSn+${^bi@|1*brdD`(1S@s%FwX^yH(aE{Y-S@$
zyHABwp{rovs;I2+0hNut!W$vO95*zQNrgy}#{?D`pJpYOm#RFGx<*X|LL_xbDlL*T
zfQGVF8g;EF33tV2wZp5cAZS0<amf?&Q#bc5=4UK~`Hc5Exaxm(>xF(`FCv6m92l`M
zN4!Z8!D?5T1$(Us>q36Zu<l<sfWbHo31@EI*^Q-O>081z#6w{@kGrcBZ_F8)iGYOL
z^hwQgu4bWN1OqZ7Balkv<2yx5;*wE&Uh!UTLD;N>#)cOW7N`B*{qibHBYVyy-MB+-
zk05*PYvViMoB!x2ag6}!mZb~Z;BW}RABB&|8$(`rDmq6O^%>z1Haku#@{BnIgy_JW
zhb@>Sak}a|gy23%hgB=Zm;_DdxlLPc!B$ZvUptg+%CsZ^I(=nmuM~S32#JTzOt}h#
zNpMA<km|!o23<12mop&~E{g~Na-u}U(L$Hks~#Mz6hi2zfzT_}!Co@ZhVBC-5-8ut
zViZ`YxD5h9Y5VmXoB%Qd*`@>~6>RI;5Q~sD3T7wE8|-%HY#;$^74bG6clVtZ7lo!)
qvi4DxBBy;{&|`5*k{V;Kt0X}N;>a?K8S*Fp;_gVN3KAbY%vfNj#}MWK

literal 0
HcmV?d00001

diff --git a/tests/testfilesplitranges4.debug.bz2 b/tests/testfilesplitranges4.debug.bz2
new file mode 100755
index 0000000000000000000000000000000000000000..df8e3ac480e56c9cd42bb4c658672ee67c55b057
GIT binary patch
literal 2154
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

literal 0
HcmV?d00001

-- 
2.17.0

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] libdw: Handle GNU DebugFission split ranges.
  2018-05-19 14:04 [PATCH] libdw: Handle GNU DebugFission split ranges Mark Wielaard
@ 2018-05-22 22:42 ` Mark Wielaard
  2018-05-24 13:26 ` Mark Wielaard
  1 sibling, 0 replies; 3+ messages in thread
From: Mark Wielaard @ 2018-05-22 22:42 UTC (permalink / raw)
  To: elfutils-devel

On Sat, May 19, 2018 at 04:03:51PM +0200, Mark Wielaard wrote:
> GNU DebugFission split dwarf handles DW_FORM_sec_offset specially for
> attributes that point to ranges. The .debug_ranges section is not in
> the .dwo file, but in the main/skeleton object file. The sec_offset is
> not relocated (in the ELF file), but is an offset against the skeleton
> DIE DW_AT_GNU_ranges_base attribute. dwarf_formudata is changed so it
> still looks like a normal offset ptr into the .debug_ranges section.
> dwarf_ranges is adapted to look for the .debug_ranges in the main object
> file. dwarf_highpc and dwarf_lowpc now handle the highpc and lowpc
> attributes being inherited for the split unit DIE from the skeleton.
> 
> A new testcase is added to iterate over all ranges in a split GNU
> DebugFission file.

Pushed to master.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] libdw: Handle GNU DebugFission split ranges.
  2018-05-19 14:04 [PATCH] libdw: Handle GNU DebugFission split ranges Mark Wielaard
  2018-05-22 22:42 ` Mark Wielaard
@ 2018-05-24 13:26 ` Mark Wielaard
  1 sibling, 0 replies; 3+ messages in thread
From: Mark Wielaard @ 2018-05-24 13:26 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 1126 bytes --]

On Sat, 2018-05-19 at 16:03 +0200, Mark Wielaard wrote:
> GNU DebugFission split dwarf handles DW_FORM_sec_offset specially for
> attributes that point to ranges. The .debug_ranges section is not in
> the .dwo file, but in the main/skeleton object file. The sec_offset is
> not relocated (in the ELF file), but is an offset against the skeleton
> DIE DW_AT_GNU_ranges_base attribute. dwarf_formudata is changed so it
> still looks like a normal offset ptr into the .debug_ranges section.
> dwarf_ranges is adapted to look for the .debug_ranges in the main object
> file. dwarf_highpc and dwarf_lowpc now handle the highpc and lowpc
> attributes being inherited for the split unit DIE from the skeleton.
> 
> A new testcase is added to iterate over all ranges in a split GNU
> DebugFission file.

After double checking the test results after incorporating the full
DWARF5 rnglists support into readelf and libdw I found an embarrassing
bug. We didn't initialize the CU ranges_base causing some bad test
results. We also didn't handle bad DWARF correctly in one case. I am
pushing the following fixes for this.

[-- Attachment #2: Type: text/x-patch, Size: 3883 bytes --]

From c2d14cc492aa7fd28740d5789fede64ce81a063b Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mark@klomp.org>
Date: Thu, 24 May 2018 15:20:25 +0200
Subject: [PATCH] libdw: Initialize ranges_base, add invalid DWARF test and fix
 expected output.

We never initialized the CU ranges_base, which meant we didn't actually
calculate it correctly. This caused bad ranges on some DIEs. The expected
output in the testcase was wrong. We also crashed on invalid dwarf.

Signed-off-by: Mark Wielaard <mark@klomp.org>
---
 libdw/ChangeLog               | 5 +++++
 libdw/dwarf_ranges.c          | 6 ++++++
 libdw/libdw_findcu.c          | 1 +
 tests/ChangeLog               | 7 ++++++-
 tests/get-units-invalid.c     | 7 +++++++
 tests/run-all-dwarf-ranges.sh | 7 ++++---
 6 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 4db0f5c..c302628 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2018-05-24  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_ranges.c (dwarf_ranges): Check for NULL cu.
+	* libdw_findcu.c (__libdw_intern_next_unit): Initialize ranges_base.
+
 2018-05-18  Mark Wielaard  <mark@klomp.org>
 
 	* dwarf_formudata.c (__libdw_formptr): Handle the special case
diff --git a/libdw/dwarf_ranges.c b/libdw/dwarf_ranges.c
index b0450cf..52a61ee 100644
--- a/libdw/dwarf_ranges.c
+++ b/libdw/dwarf_ranges.c
@@ -123,6 +123,12 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
   /* We have to look for a noncontiguous range.  */
   size_t secidx = IDX_debug_ranges;
   Dwarf_CU *cu = die->cu;
+  if (cu == NULL)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return -1;
+    }
+
   const Elf_Data *d = cu->dbg->sectiondata[secidx];
   if (d == NULL && cu->unit_type == DW_UT_split_compile)
     {
diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c
index d22ddae..83c2eb1 100644
--- a/libdw/libdw_findcu.c
+++ b/libdw/libdw_findcu.c
@@ -121,6 +121,7 @@ __libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
   newp->base_address = (Dwarf_Addr) -1;
   newp->addr_base = (Dwarf_Off) -1;
   newp->str_off_base = (Dwarf_Off) -1;
+  newp->ranges_base = (Dwarf_Off) -1;
 
   newp->startp = data->d_buf + newp->start;
   newp->endp = data->d_buf + newp->end;
diff --git a/tests/ChangeLog b/tests/ChangeLog
index a021a01..86bcf9d 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,6 +1,11 @@
+2018-05-24  Mark Wielaard  <mark@klomp.org>
+
+	* get-units-invalid.c (main): Add check for invalid dwarf_ranges.
+	* run-all-dwarf-ranges.sh: Correct expected output.
+
 2018-05-18  Mark Wielaard  <mark@klomp.org>
 
-	* tests/Makefiles.am (check_PROGRAMS): Add all-dwarf-ranges.
+	* Makefiles.am (check_PROGRAMS): Add all-dwarf-ranges.
 	(TESTS): Add run-all-dwarf-ranges.sh.
 	(EXTRA_DIST): Add run-all-dwarf-ranges.sh,
 	testfilesplitranges4.debug.bz2, testfile-ranges-hello.dwo.bz2
diff --git a/tests/get-units-invalid.c b/tests/get-units-invalid.c
index 9ec16ee..58b32c0 100644
--- a/tests/get-units-invalid.c
+++ b/tests/get-units-invalid.c
@@ -79,6 +79,13 @@ main (int argc, char *argv[])
 			  dwarf_diename (&result));
 		  return -1;
 		}
+	      Dwarf_Addr base, start, end;
+	      if (dwarf_ranges (&subdie, 0, &base, &start, &end) != -1)
+		{
+		  printf ("Should NOT have a ranges: %s\n",
+			  dwarf_diename (&result));
+		  return -1;
+		}
 	    }
 	  else if (unit_type == DW_UT_type)
 	    printf ("subdie: %s\n", dwarf_diename (&subdie));
diff --git a/tests/run-all-dwarf-ranges.sh b/tests/run-all-dwarf-ranges.sh
index 0bd641b..ba5528d 100755
--- a/tests/run-all-dwarf-ranges.sh
+++ b/tests/run-all-dwarf-ranges.sh
@@ -37,11 +37,12 @@ die: world.c (11)
  400500..400567
 
 die: happy (1d)
- 8009e0..8009ff
- 8008e0..8008f7
+ 40051c..400526
+ 400530..400534
+ 400535..40053f
 
 die: sad (1d)
- 400530..400534
+ 40051c..400526
  400535..40053f
 
 EOF
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-05-24 13:26 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-19 14:04 [PATCH] libdw: Handle GNU DebugFission split ranges Mark Wielaard
2018-05-22 22:42 ` Mark Wielaard
2018-05-24 13:26 ` Mark Wielaard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).