This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] libdw: Handle .debug_rnglists in dwarf_ranges.


Handle all new DW_RLE opcodes in .debug_rnglists in dwarf_ranges. Extract
code for reading .debug_addr indexes from dwarf_formaddr as __libdw_addrx
to reuse in __libdw_read_begin_end_pair_inc. And add new testcase.

Signed-off-by: Mark Wielaard <mark@klomp.org>
---
 libdw/ChangeLog                      |  15 ++
 libdw/dwarf_formaddr.c               |  76 ++++----
 libdw/dwarf_getlocation.c            |   2 +-
 libdw/dwarf_ranges.c                 | 258 +++++++++++++++++++++++----
 libdw/libdwP.h                       |  84 ++++++++-
 src/ChangeLog                        |   3 +-
 src/readelf.c                        |   2 +
 tests/ChangeLog                      |   6 +
 tests/Makefile.am                    |   2 +-
 tests/run-all-dwarf-ranges.sh        |  55 ++++++
 tests/run-dwarf-ranges.sh            |  18 ++
 tests/testfile-ranges-hello5.dwo.bz2 | Bin 0 -> 1296 bytes
 tests/testfile-ranges-world5.dwo.bz2 | Bin 0 -> 1466 bytes
 tests/testfileranges5.debug.bz2      | Bin 0 -> 2857 bytes
 tests/testfilesplitranges5.debug.bz2 | Bin 0 -> 2235 bytes
 15 files changed, 442 insertions(+), 79 deletions(-)
 create mode 100644 tests/testfile-ranges-hello5.dwo.bz2
 create mode 100644 tests/testfile-ranges-world5.dwo.bz2
 create mode 100755 tests/testfileranges5.debug.bz2
 create mode 100755 tests/testfilesplitranges5.debug.bz2

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 9c0ab3c5..b19ebe96 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,18 @@
+2018-04-06  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_formaddr.c (__libdw_addrx): New function, extracted from...
+	(dwarf_formaddr): here. Use __libdw_addrx.
+	* dwarf_getlocation.c (getlocations_addr): Pass cu to
+	__libdw_read_begin_end_pair_inc.
+	* dwarf_ranges.c (__libdw_read_begin_end_pair_inc): Take cu as
+	argument. Handle .debug_rnglists.
+	(initial_offset): Handle .debug_rnglists and DW_FORM_rnglistx.
+	(dwarf_ranges): Likewise. Check cu isn't NULL before use. Pass cu to
+	__libdw_read_begin_end_pair_inc.
+	* libdwP.h (__libdw_read_begin_end_pair_inc): Take cu as argument.
+	(__libdw_cu_ranges_base): Handle DW_AT_rnglists_base.
+	(__libdw_addrx): New function definition.
+
 2018-04-11  Mark Wielaard  <mark@klomp.org>
 
 	* dwarf.h: Add DWARF5 range list entry DW_RLE encodings.
diff --git a/libdw/dwarf_formaddr.c b/libdw/dwarf_formaddr.c
index 3c89a5d2..9cd3d200 100644
--- a/libdw/dwarf_formaddr.c
+++ b/libdw/dwarf_formaddr.c
@@ -34,6 +34,48 @@
 #include "libdwP.h"
 
 
+int
+__libdw_addrx (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr)
+{
+  Dwarf_Off addr_off = __libdw_cu_addr_base (cu);
+  if (addr_off == (Dwarf_Off) -1)
+    return -1;
+
+  Dwarf *dbg = cu->dbg;
+  if (dbg->sectiondata[IDX_debug_addr] == NULL)
+    {
+      __libdw_seterrno (DWARF_E_NO_DEBUG_ADDR);
+      return -1;
+    }
+
+  /* The section should at least contain room for one address.  */
+  int address_size = cu->address_size;
+  if (cu->address_size > dbg->sectiondata[IDX_debug_addr]->d_size)
+    {
+    invalid_offset:
+      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+      return -1;
+    }
+
+  if (addr_off > (dbg->sectiondata[IDX_debug_addr]->d_size
+		  - address_size))
+    goto invalid_offset;
+
+  idx *= address_size;
+  if (idx > (dbg->sectiondata[IDX_debug_addr]->d_size
+	     - address_size - addr_off))
+    goto invalid_offset;
+
+  const unsigned char *datap;
+  datap = dbg->sectiondata[IDX_debug_addr]->d_buf + addr_off + idx;
+  if (address_size == 4)
+    *addr = read_4ubyte_unaligned (dbg, datap);
+  else
+    *addr = read_8ubyte_unaligned (dbg, datap);
+
+  return 0;
+}
+
 int
 dwarf_formaddr (Dwarf_Attribute *attr, Dwarf_Addr *return_addr)
 {
@@ -98,41 +140,9 @@ dwarf_formaddr (Dwarf_Attribute *attr, Dwarf_Addr *return_addr)
 
   /* So we got an index.  Lets see if it is valid and we can get the actual
      address.  */
-
-  Dwarf_Off addr_off = __libdw_cu_addr_base (cu);
-  if (addr_off == (Dwarf_Off) -1)
+  if (__libdw_addrx (cu, idx, return_addr) != 0)
     return -1;
 
-  if (dbg->sectiondata[IDX_debug_addr] == NULL)
-    {
-      __libdw_seterrno (DWARF_E_NO_DEBUG_ADDR);
-      return -1;
-    }
-
-  /* The section should at least contain room for one address.  */
-  int address_size = cu->address_size;
-  if (cu->address_size > dbg->sectiondata[IDX_debug_addr]->d_size)
-    {
-    invalid_offset:
-      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
-      return -1;
-    }
-
-  if (addr_off > (dbg->sectiondata[IDX_debug_addr]->d_size
-		  - address_size))
-    goto invalid_offset;
-
-  idx *= address_size;
-  if (idx > (dbg->sectiondata[IDX_debug_addr]->d_size
-	     - address_size - addr_off))
-    goto invalid_offset;
-
-  datap = dbg->sectiondata[IDX_debug_addr]->d_buf + addr_off + idx;
-  if (address_size == 4)
-    *return_addr = read_4ubyte_unaligned (dbg, datap);
-  else
-    *return_addr = read_8ubyte_unaligned (dbg, datap);
-
   return 0;
 }
 INTDEF(dwarf_formaddr)
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
index ade3e6c5..0e7115f8 100644
--- a/libdw/dwarf_getlocation.c
+++ b/libdw/dwarf_getlocation.c
@@ -724,7 +724,7 @@ getlocations_addr (Dwarf_Attribute *attr, ptrdiff_t offset,
   Dwarf_Addr end;
 
  next:
-  switch (__libdw_read_begin_end_pair_inc (dbg, secidx,
+  switch (__libdw_read_begin_end_pair_inc (cu, secidx,
 					   &readp, readendp,
 					   cu->address_size,
 					   &begin, &end, basep))
diff --git a/libdw/dwarf_ranges.c b/libdw/dwarf_ranges.c
index 52a61eea..fa65e5c6 100644
--- a/libdw/dwarf_ranges.c
+++ b/libdw/dwarf_ranges.c
@@ -40,62 +40,244 @@
     - If it's end of rangelist, don't set anything and return 2
     - If an error occurs, don't set anything and return -1.  */
 internal_function int
-__libdw_read_begin_end_pair_inc (Dwarf *dbg, int sec_index,
+__libdw_read_begin_end_pair_inc (Dwarf_CU *cu, int sec_index,
 				 const unsigned char **addrp,
 				 const unsigned char *addrend,
 				 int width,
 				 Dwarf_Addr *beginp, Dwarf_Addr *endp,
 				 Dwarf_Addr *basep)
 {
-  Dwarf_Addr escape = (width == 8 ? (Elf64_Addr) -1
-		       : (Elf64_Addr) (Elf32_Addr) -1);
-  Dwarf_Addr begin;
-  Dwarf_Addr end;
-
-  const unsigned char *addr = *addrp;
-  if (addrend - addr < width * 2)
+  Dwarf *dbg = cu->dbg;
+  if (sec_index == IDX_debug_ranges || sec_index == IDX_debug_loc)
     {
-    invalid:
-      __libdw_seterrno (DWARF_E_INVALID_DWARF);
-      return -1;
-    }
+      Dwarf_Addr escape = (width == 8 ? (Elf64_Addr) -1
+			   : (Elf64_Addr) (Elf32_Addr) -1);
+      Dwarf_Addr begin;
+      Dwarf_Addr end;
 
-  bool begin_relocated = READ_AND_RELOCATE (__libdw_relocate_address, begin);
-  bool end_relocated = READ_AND_RELOCATE (__libdw_relocate_address, end);
-  *addrp = addr;
+      const unsigned char *addr = *addrp;
+      if (addrend - addr < width * 2)
+	{
+	invalid:
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return -1;
+	}
 
-  /* Unrelocated escape for begin means base address selection.  */
-  if (begin == escape && !begin_relocated)
-    {
-      if (unlikely (end == escape))
-	goto invalid;
+      bool begin_relocated = READ_AND_RELOCATE (__libdw_relocate_address,
+						begin);
+      bool end_relocated = READ_AND_RELOCATE (__libdw_relocate_address,
+					      end);
+      *addrp = addr;
 
-      *basep = end;
-      return 1;
-    }
+      /* Unrelocated escape for begin means base address selection.  */
+      if (begin == escape && !begin_relocated)
+	{
+	  if (unlikely (end == escape))
+	    goto invalid;
+
+	  *basep = end;
+	  return 1;
+	}
 
-  /* Unrelocated pair of zeroes means end of range list.  */
-  if (begin == 0 && end == 0 && !begin_relocated && !end_relocated)
-    return 2;
+      /* Unrelocated pair of zeroes means end of range list.  */
+      if (begin == 0 && end == 0 && !begin_relocated && !end_relocated)
+	return 2;
 
-  /* Don't check for begin_relocated == end_relocated.  Serve the data
-     to the client even though it may be buggy.  */
-  *beginp = begin + *basep;
-  *endp = end + *basep;
+      /* Don't check for begin_relocated == end_relocated.  Serve the data
+	 to the client even though it may be buggy.  */
+      *beginp = begin + *basep;
+      *endp = end + *basep;
 
-  return 0;
+      return 0;
+    }
+  else if (sec_index == IDX_debug_rnglists)
+    {
+      const unsigned char *addr = *addrp;
+      if (addrend - addr < 1)
+	goto invalid;
+
+      const char code = *addr++;
+      uint64_t begin = 0, end = 0, base = *basep, addr_idx;
+      switch (code)
+	{
+	case DW_RLE_end_of_list:
+	  *addrp = addr;
+	  return 2;
+
+	case DW_RLE_base_addressx:
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (addr_idx, addr, addrend);
+	  if (__libdw_addrx (cu, addr_idx, &base) != 0)
+	    return -1;
+
+	  *basep = base;
+	  *addrp = addr;
+	  return 1;
+
+	case DW_RLE_startx_endx:
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (addr_idx, addr, addrend);
+	  if (__libdw_addrx (cu, addr_idx, &begin) != 0)
+	    return -1;
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (addr_idx, addr, addrend);
+	  if (__libdw_addrx (cu, addr_idx, &end) != 0)
+	    return -1;
+
+	  *beginp = begin;
+	  *endp = end;
+	  *addrp = addr;
+	  return 0;
+
+	case DW_RLE_startx_length:
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (addr_idx, addr, addrend);
+	  if (__libdw_addrx (cu, addr_idx, &begin) != 0)
+	    return -1;
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (end, addr, addrend);
+
+	  *beginp = begin;
+	  *endp = begin + end;
+	  *addrp = addr;
+	  return 0;
+
+	case DW_RLE_offset_pair:
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (begin, addr, addrend);
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (end, addr, addrend);
+
+	  *beginp = begin + base;
+	  *endp = end + base;
+	  *addrp = addr;
+	  return 0;
+
+	case DW_RLE_base_address:
+	  if (addrend - addr < width)
+	    goto invalid;
+	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &base);
+
+	  *basep = base;
+	  *addrp = addr;
+	  return 1;
+
+	case DW_RLE_start_end:
+	  if (addrend - addr < 2 * width)
+	    goto invalid;
+	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin);
+	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &end);
+
+	  *beginp = begin;
+	  *endp = end;
+	  *addrp = addr;
+	  return 0;
+
+	case DW_RLE_start_length:
+	  if (addrend - addr < width)
+	    goto invalid;
+	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin);
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (end, addr, addrend);
+
+	  *beginp = begin;
+	  *endp = begin + end;
+	  *addrp = addr;
+	  return 0;
+
+	default:
+	  goto invalid;
+	}
+    }
+  else
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return -1;
+    }
 }
 
 static int
 initial_offset (Dwarf_Attribute *attr, ptrdiff_t *offset)
 {
-  size_t secidx = IDX_debug_ranges;
+  size_t secidx = (attr->cu->version < 5
+		   ? IDX_debug_ranges : IDX_debug_rnglists);
 
   Dwarf_Word start_offset;
-  if (__libdw_formptr (attr, secidx,
-		       DWARF_E_NO_DEBUG_RANGES,
-		       NULL, &start_offset) == NULL)
-    return -1;
+  if (attr->form == DW_FORM_rnglistx)
+    {
+      Dwarf_Word idx;
+      Dwarf_CU *cu = attr->cu;
+      const unsigned char *datap = attr->valp;
+      const unsigned char *endp = cu->endp;
+      if (datap >= endp)
+	{
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return -1;
+	}
+      get_uleb128 (idx, datap, endp);
+
+      Elf_Data *data = cu->dbg->sectiondata[secidx];
+      if (data == NULL && cu->unit_type == DW_UT_split_compile)
+	{
+	  cu = __libdw_find_split_unit (cu);
+	  if (cu != NULL)
+	    data = cu->dbg->sectiondata[secidx];
+	}
+
+      if (data == NULL)
+	{
+	  __libdw_seterrno (secidx == IDX_debug_ranges
+                            ? DWARF_E_NO_DEBUG_RANGES
+                            : DWARF_E_NO_DEBUG_RNGLISTS);
+	  return -1;
+	}
+
+      Dwarf_Off range_base_off = __libdw_cu_ranges_base (cu);
+
+      /* The section should at least contain room for one offset.  */
+      size_t sec_size = cu->dbg->sectiondata[secidx]->d_size;
+      size_t offset_size = cu->offset_size;
+      if (offset_size > sec_size)
+	{
+	invalid_offset:
+	  __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+	  return -1;
+	}
+
+      /* And the base offset should be at least inside the section.  */
+      if (range_base_off > (sec_size - offset_size))
+	goto invalid_offset;
+
+      size_t max_idx = (sec_size - offset_size - range_base_off) / offset_size;
+      if (idx > max_idx)
+	goto invalid_offset;
+
+      datap = (cu->dbg->sectiondata[secidx]->d_buf
+	       + range_base_off + (idx * offset_size));
+      if (offset_size == 4)
+	start_offset = read_4ubyte_unaligned (cu->dbg, datap);
+      else
+	start_offset = read_8ubyte_unaligned (cu->dbg, datap);
+
+      start_offset += range_base_off;
+    }
+  else
+    {
+      if (__libdw_formptr (attr, secidx,
+			   (secidx == IDX_debug_ranges
+			    ? DWARF_E_NO_DEBUG_RANGES
+			    : DWARF_E_NO_DEBUG_RNGLISTS),
+			   NULL, &start_offset) == NULL)
+	return -1;
+    }
 
   *offset = start_offset;
   return 0;
@@ -121,7 +303,6 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
     return 0;
 
   /* We have to look for a noncontiguous range.  */
-  size_t secidx = IDX_debug_ranges;
   Dwarf_CU *cu = die->cu;
   if (cu == NULL)
     {
@@ -129,6 +310,7 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
       return -1;
     }
 
+  size_t secidx = (cu->version < 5 ? IDX_debug_ranges : IDX_debug_rnglists);
   const Elf_Data *d = cu->dbg->sectiondata[secidx];
   if (d == NULL && cu->unit_type == DW_UT_split_compile)
     {
@@ -176,7 +358,7 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
   Dwarf_Addr end;
 
  next:
-  switch (__libdw_read_begin_end_pair_inc (cu->dbg, secidx,
+  switch (__libdw_read_begin_end_pair_inc (cu, secidx,
 					   &readp, readendp,
 					   cu->address_size,
 					   &begin, &end, basep))
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 3cfcc557..c419e37a 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -915,7 +915,7 @@ is_cudie (Dwarf_Die *cudie)
     - If it's base address selection record, set up *BASEP and return 1.
     - If it's end of rangelist, don't set anything and return 2
     - If an error occurs, don't set anything and return <0.  */
-int __libdw_read_begin_end_pair_inc (Dwarf *dbg, int sec_index,
+int __libdw_read_begin_end_pair_inc (Dwarf_CU *cu, int sec_index,
 				     const unsigned char **readp,
 				     const unsigned char *readend,
 				     int width,
@@ -1084,6 +1084,8 @@ static inline Dwarf_Off __libdw_cu_str_off_base (Dwarf_CU *cu)
 }
 
 
+/* Either a direct offset into .debug_ranges for version < 5, or the
+   start of the offset table in .debug_rnglists for version > 5.  */
 static inline Dwarf_Off
 __libdw_cu_ranges_base (Dwarf_CU *cu)
 {
@@ -1092,12 +1094,79 @@ __libdw_cu_ranges_base (Dwarf_CU *cu)
       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)
+      if (cu->version < 5)
 	{
-	  Dwarf_Word off;
-	  if (dwarf_formudata (&attr, &off) == 0)
-	    offset = off;
+	  if (dwarf_attr (&cu_die, DW_AT_GNU_ranges_base, &attr) != NULL)
+	    {
+	      Dwarf_Word off;
+	      if (dwarf_formudata (&attr, &off) == 0)
+		offset = off;
+	    }
+	}
+      else
+	{
+	  if (dwarf_attr (&cu_die, DW_AT_rnglists_base, &attr) != NULL)
+	    {
+	      Dwarf_Word off;
+	      if (dwarf_formudata (&attr, &off) == 0)
+		offset = off;
+	    }
+
+	  /* There wasn't an rnglists_base, if the Dwarf does have a
+	     .debug_rnglists section, then it might be we need the
+	     base after the first header. */
+	  Elf_Data *data = cu->dbg->sectiondata[IDX_debug_rnglists];
+	  if (offset == 0 && data != NULL)
+	    {
+	      Dwarf *dbg = cu->dbg;
+	      const unsigned char *readp = data->d_buf;
+	      const unsigned char *const dataend
+		= (unsigned char *) data->d_buf + data->d_size;
+
+	      uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
+	      unsigned int offset_size = 4;
+	      if (unlikely (unit_length == 0xffffffff))
+		{
+		  if (unlikely (readp > dataend - 8))
+		    goto no_header;
+
+		  unit_length = read_8ubyte_unaligned_inc (dbg, readp);
+		  offset_size = 8;
+		}
+
+	      if (readp > dataend - 8
+		  || unit_length < 8
+		  || unit_length > (uint64_t) (dataend - readp))
+		goto no_header;
+
+	      uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
+	      if (version != 5)
+		goto no_header;
+
+	      uint8_t address_size = *readp++;
+	      if (address_size != 4 && address_size != 8)
+		goto no_header;
+
+	      uint8_t segment_size = *readp++;
+	      if (segment_size != 0)
+		goto no_header;
+
+	      uint32_t offset_entry_count;
+	      offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
+
+	      const unsigned char *offset_array_start = readp;
+	      if (offset_entry_count <= 0)
+		goto no_header;
+
+	      uint64_t needed = offset_entry_count * offset_size;
+	      if (unit_length - 8 < needed)
+		goto no_header;
+
+	      offset = (Dwarf_Off) (offset_array_start
+				    - (unsigned char *) data->d_buf);
+	    }
 	}
+    no_header:
       cu->ranges_base = offset;
     }
 
@@ -1105,6 +1174,11 @@ __libdw_cu_ranges_base (Dwarf_CU *cu)
 }
 
 
+/* Given an address index for a CU return the address.
+   Returns -1 and sets libdw_errno if an error occurs.  */
+int __libdw_addrx (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr);
+
+
 /* 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/src/ChangeLog b/src/ChangeLog
index d28d89af..4772448c 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -6,7 +6,8 @@
 	(listptr_cu): New function.
 	(print_debug_rnglists_section): Likewise.
 	(attr_callback): Call notice_listptr for DW_AT_ranges. Handle
-	DW_AT_rnglists_base.
+	DW_AT_rnglists_base. Handle DW_FORM_rnglistx. DW_AT_start_scope
+	can also have a rnglist.
 	(print_debug_units): Do (silently) scan split DWARF also for
 	debug_ranges before DWARF5 to catch all rangelistptrs.
 	(print_debug): Recognize .debug_rnglists. Reset known_rnglistptr.
diff --git a/src/readelf.c b/src/readelf.c
index 071906fa..3f5c73b8 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -6702,6 +6702,7 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
       break;
 
     case DW_FORM_sec_offset:
+    case DW_FORM_rnglistx:
     case DW_FORM_implicit_const:
     case DW_FORM_udata:
     case DW_FORM_sdata:
@@ -6758,6 +6759,7 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 	  return DWARF_CB_OK;
 
 	case DW_AT_ranges:
+	case DW_AT_start_scope:
 	  {
 	    bool nlpt;
 	    if (cbargs->cu->version < 5)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 13d168de..f26651c9 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,9 @@
+2018-04-06  Mark Wielaard  <mark@klomp.org>
+
+	* testfileranges5.debug.bz2: New testfile.
+	* run-dwarf-ranges.sh: Run on testfileranges5.debug.
+	* tests/Makefile.am (EXTRA_DIST): Add testfileranges5.debug.bz2.
+
 2018-04-11  Mark Wielaard  <mark@klomp.org>
 
 	* run-readelf-ranges.sh: New test.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 54a3d1d5..bb80b78b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -203,7 +203,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 	     run-dwfl-addr-sect.sh run-early-offscn.sh \
 	     run-dwarf-getmacros.sh \
 	     run-dwarf-ranges.sh debug-ranges-no-lowpc.o.bz2 \
-	     testfileranges4.debug.bz2 \
+	     testfileranges4.debug.bz2 testfileranges5.debug.bz2 \
 	     run-test-flag-nobits.sh \
 	     run-dwarf-getstring.sh run-rerequest_tag.sh run-alldts.sh \
 	     testfile15.bz2 testfile15.debug.bz2 \
diff --git a/tests/run-all-dwarf-ranges.sh b/tests/run-all-dwarf-ranges.sh
index ad5e634f..cefb4231 100755
--- a/tests/run-all-dwarf-ranges.sh
+++ b/tests/run-all-dwarf-ranges.sh
@@ -71,4 +71,59 @@ die: no_subject (2e)
 
 EOF
 
+# Same with -gdwarf-5
+# gcc -c -O2 -o testfile-ranges-hello5.o -gsplit-dwarf -gdwarf-5 hello.c
+# gcc -c -O2 -o testfile-ranges-world5.o -gsplit-dwarf -gdwarf-5 world.c
+# gcc -o testfilesplitranges5 -O2 testfile-ranges-hello5.o testfile-ranges-world5.o
+# eu-strip -f testfilesplitranges5.debug testfilesplitranges5
+
+testfiles testfilesplitranges5.debug
+testfiles testfile-ranges-hello5.dwo testfile-ranges-world5.dwo
+
+testrun_compare ${abs_builddir}/all-dwarf-ranges testfilesplitranges5.debug <<\EOF
+die: hello.c (11)
+ 401150..40117a
+ 401050..401067
+
+die: no_say (2e)
+ 401160..40117a
+
+die: main (2e)
+ 401050..401067
+
+die: subject (1d)
+ 401053..40105f
+
+die: subject (2e)
+ 401150..401160
+
+die: world.c (11)
+ 401180..4011e7
+
+die: no_main (2e)
+ 4011d0..4011e7
+
+die: no_subject (1d)
+ 4011d3..4011df
+
+die: say (2e)
+ 401180..4011c0
+
+die: happy (1d)
+ 40119b..40119b
+ 40119c..4011a6
+ 4011b0..4011b4
+ 4011b5..4011bf
+
+die: sad (1d)
+ 40119b..40119b
+ 40119c..4011a6
+ 4011b4..4011b4
+ 4011b5..4011bf
+
+die: no_subject (2e)
+ 4011c0..4011d0
+
+EOF
+
 exit 0
diff --git a/tests/run-dwarf-ranges.sh b/tests/run-dwarf-ranges.sh
index f935eaf4..a58ee659 100755
--- a/tests/run-dwarf-ranges.sh
+++ b/tests/run-dwarf-ranges.sh
@@ -102,4 +102,22 @@ testrun_compare ${abs_builddir}/dwarf-ranges testfileranges4.debug 0x374 <<\EOF
 4005a5..4005ad (base 400540)
 EOF
 
+# Like above, but with -gdwarf-5.
+testfiles testfileranges5.debug
+testrun_compare ${abs_builddir}/dwarf-ranges testfileranges5.debug 0xc <<\EOF
+4004e0..4004ff (base 0)
+4003e0..4003f7 (base 0)
+EOF
+
+testrun_compare ${abs_builddir}/dwarf-ranges testfileranges5.debug 0x289 <<\EOF
+40051c..400526 (base 400500)
+400530..400534 (base 400500)
+400535..40053f (base 400500)
+EOF
+
+testrun_compare ${abs_builddir}/dwarf-ranges testfileranges5.debug 0x2a9 <<\EOF
+40051c..400526 (base 400500)
+400535..40053f (base 400500)
+EOF
+
 exit 0
diff --git a/tests/testfile-ranges-hello5.dwo.bz2 b/tests/testfile-ranges-hello5.dwo.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..03d252e14d9ffed0a12abad13afedbe5e4e116c6
GIT binary patch
literal 1296
zcmV+r1@HPoT4*^jL0KkKStVb6-~a+D|NsC0|NsC0`v3p`@Bjbr|Nr;@|Ns8~|3Ck4
z^|k;1_y52G{0C=U#&oe%Q#~d$p_)w^dLYR3hpFW<48=6{GCfa7(9;5Gnx2rv^#P3&
zMobB`nr4$ns2+)v8AhL~W|>BsY}FVVnh#S=3<T3gWSV*=O+8N(Isgp-82}mp4FCWE
zpay^d01W^D000Jn0000000E!?28MtD8WBj<Jx@{Uct#30sL2>@Q}s-rs%Z5xHm9kY
zhJzE-FluB0wE>z&j7))srcWuR)X>2_Oh6hM8hJEL834e5G#C(IK-xV)rlci3Pf6(0
zQ`7@Y36YRA4F-TcLm}!tO$`750Lb+;XfkP_dVmIjrhotd15E%l28MtD05mkvP+CY~
zaHLZUEjsa@>H(`D147a84A@E4{gfFT3zw{b4jcyy0;a9(8A~KqYC8Xo=TtAH_<)dg
zg(4(=4MGMPK@bBcDOQ=#KxyWt_OE~k@`w-#LJ0r{=Jy7w@c~693LsHLLP-RqAqXPt
zYD5VOl^_tIOsK^9IjkUD12#}b8ZrYnR`2rR-14~&1$-?_RiFT{CZ4+GWGJnpW#<@;
zwP#zhL5?izs@Rv(i1*^rWOqtHq!L9TsMLZ#N}$=#*>A>q<5>z8Ktqa2?arZ!<E3B>
zN1KB_y5$5o>nI6w7cXNVsnHt-R8lx4kO;D!q674V49jOTP|W=GL$N7Q<t2bUbdYQq
zsrs1^2*Y@tOxymVHE?~XNaT;5&0wS_jPPuEhOYRF!Vwq0wznlImpD?Wmpxr06%n!(
z6xH#u`}sv*JCO704p6*h8zqwr+JaQs#dZVjPjenhJ8IXg(!`y^odIwRg3xQv4O^@n
z2Pxp#pm0J#9U6QeI<#F})kc1d_7I@Hqyn!k3`ga(aOesIC;`;uNQ)Ntl{4^yugZb4
zjS($&)hjdrtxv3WJW!@Y-V_VeUn=3p`tdlpzX({Gycw;PB1)=$OX*OsiwG5tI^{dt
z@k_@Kz0RhV`k*lv8>^i8y1dXrKl49x{peo@t~%otE(DnpGE^gN6GWt#y1RJ=xJS@&
z86b~BSrihFTA%A??#6%w&_SV!MCJl}d;m15{DM)2mRprMyXPxIRL<diU<tm(^e!O$
z0yjr1m*WOmBt%JP1hGTk5@(QHGC(TDC|TkocWHLsOA9C$pdrxAmOM`Ztsl#TstN}#
z3ABa<5rZRwf#(F{9}I}DsEhVf&kh8dApi(zW6MNfFhXpYGbuzHR4xPcM}RZ&4&(q6
zYUz3-YlmD0%E>o^1Oq`ojE-^~A^6QYoW8~57OaT4jrOLZ%Q=|MBx&*^iocP!e*vmS
z=AP*l<e1`+$SmE_SfO0k@G9vdf|6-=U65JD=0gAg$yfuyDBuZ3SHKmPYb1h4W7qNO
zX8SZ$r7@sBoH}rjuFfo5J|vJW<ip|=Q?Z{h#;oNLJNGk}h8V8#a+yM4d5e(GvO<4M
zW5DU!?D=y#<)f{V@Kd8{BSM;uVvCW-%~Y^8)9(Lboqo%rtZ(+3-g7B6qOcW8g5TyT
z_H5Gbj+vE&vRMt@f5o`ZlK1$+E<TM^H`CzJq16O+0Y=~+vOOm*2#JgwI|!X(USTRU
zGUG-0c{r6hq1mmczkFA{qH|vMQmq!RKdd+|yrW}&QSMl*J9Okh<rrd>jxOYiaG@Yd
GzWcyBflLkn

literal 0
HcmV?d00001

diff --git a/tests/testfile-ranges-world5.dwo.bz2 b/tests/testfile-ranges-world5.dwo.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..1ee3b6ac5adc43e475a512e545736ea50e61c1c4
GIT binary patch
literal 1466
zcmV;r1x5NoT4*^jL0KkKS>RD1s{jH?fB*mg|M~a-|KI=r|KGp=zyJUL-~HG2_kaKY
z|Nj5~|NYPdUIVq;UN#P~!k(e!Jx@gSJwfU{Pe>VxJdk>g9+1iDJtwKAo~M-4Pauy`
zqd}&JspSmPH1t6A8&erg9;VY%)I6g@!i_ya`jcu6rj1WX^i4dY#Sc@{Nc5koXwx!?
z00000G|&J6pa2aT0077Vpc()G001-q88iSi000dD000000Z~Du^h^<iz|k?J+5s~{
zFab82G-Ln(22Cae(+xCC044;$j7DezU<6`d0MH4hm<fOg$VDV+q`{$(GzowKpqOYA
z0GeW800E>h0T=-o08d28fC#_<000T5n3*)uff{J^&;SiIkw&MfwHiG^rk<em(gV^1
zN2nSAXaE3Y27mw$NE!eEpa2Gd00000dVm8!05kvv1c42<+XED_n!d!t$1a@1pbVRV
zED@ZuH7_S)&9(q`?Pp-ByLHUPQe<FcFVbCE^~lah2}GnSB1PTQJbIxJ2iS-**^KPI
zlT)vl+w<K3Cxiq*AdpG`C#FgA$B-1JSfT|eh)E!njUfblTA~Dvl^_tY2UzhyAQYe!
zK-OnO!46^r@e9<`iz{zLNkG^pbqv{J6kX5qC5^>HdF5I`gE-e1wg*Kd$QS)GqzZBc
zK?K4-KXQOCOqzn!bjrvSjHtq*%(f*pOOd8onM)`m0k9N~GKI5=fscI9sl`p4Gyr}^
zxYo!VNgB7)JodEzzs_?w9MEBQ`?chTn}h-c7DT7V-xSJzK71nNIJEv?p>PVg4%@jD
zigZS%ks~GfE~FTJ^s*f#QaalL$cL7EM9c=S2Fz8E(PIdWx3;R9y<#0ezeHJ;KFA9%
zDV6Ts0J{I$lCIW7rk8mc^03Yv@We|J&*Ctxas|Kzf>mSe9pShtoSfws1S8;yw;)tz
z$OS0jc*7WG=K^GnG;Iz%|KKPKRcIkHK!hFdic<$6ghxm^>Hx1ukv!j4l#4V>A9zkT
zIF<!wED&p24hI1_sAg5w!Vc0P#k!NI>XAHN0G`W*NxY4^Yc8+ISc=0gPXc11S$Lw8
zg2As*r@^QBIDnRNH$d>o$|_I!owp6ReG=%Chw)#p0@N8{+eRV>-`bt5zA|=)QR=pg
zc{l;tSMDEvyb2595h*x!o*-bU!vsMmc>pW@{YMH=DNT5BnNvU{*6!|bd58OyQ*40{
z!~jeGu_L)a67+#VzJg>*j(;^f9Dy)fOa%M;2OR2hJ-}U_jY$+*0GuArf;9~FJ*1eh
zQ5#Sx@_?ZPY{p;Bi;<8LSOE<OpbeWa2wTJ&iRpzTa7;rYd;-KF*f6{fM=cD&Is>78
z6XNfp3MefZsvCfYMM(Nj01^1X0~A;nfD%*9cL4FGSkHh6F(uG#yENlpYoA9;V;La@
z94h&J5gh~o57uokj0fnA6Q_Tj72|+@S4bU9eaPe1NNG8dvCrEhy%$C^k6{X=@gN^(
zg$T(-IWppg3DHPy(Cofy@P7&_X-W?mVmJ!$X^lDUFo-UKNG%X-6|VfVV1j9W`P_8(
zSJsNqT8>Fv(|Pg`6J}t_i3a3t!+HlH2d(eu-54v07#Ys9dW3BKr6`9yDxHYTCL0OU
zd0&sE0MN-_RZ0P9TOo)^4JyfEn6GjBMqckVor#8@)kXWc`t1mYbJyI6V}81H5)%g5
z{E#E@E}BaBR}U=YszdXl&M}t5KN37|I_|oVchD42w);5IY}p(U&Y*xcAH*nda<v(N
z9(_#4QAy%~{HmIE=`Rd~lhui28OX%AEwHPBV}c!kjYl;IO+5SA7_##1d^;8Ek|dk8
za4ei{U=m$^UAw6^)>lExnpO}s!&*0ehRzh$o+PgRrPAo#a7tu41#dS5SD;>B2{)am
Ui?rcoB0u8pNT&)C910{AU^N7V=>Px#

literal 0
HcmV?d00001

diff --git a/tests/testfileranges5.debug.bz2 b/tests/testfileranges5.debug.bz2
new file mode 100755
index 0000000000000000000000000000000000000000..b7351ef51bfe2ebfd358fff0bd790a6929ffeb04
GIT binary patch
literal 2857
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
Hp~b5pMLHtc

literal 0
HcmV?d00001

diff --git a/tests/testfilesplitranges5.debug.bz2 b/tests/testfilesplitranges5.debug.bz2
new file mode 100755
index 0000000000000000000000000000000000000000..7e43492f80d7aa930da386a9edd7efbffee5436c
GIT binary patch
literal 2235
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
J5(aqcw?Lj>;Vb|E

literal 0
HcmV?d00001

-- 
2.17.0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]