Parse the .debug_rnglists section for DWARF5 --debug-dump=ranges.
Add testcase to show both "normal" and "split" DWARF variants are
handled for DWARF4 and DWARF5.
Signed-off-by: Mark Wielaard
---
libdw/ChangeLog | 11 +
libdw/dwarf.h | 13 ++
libdw/dwarf_begin_elf.c | 1 +
libdw/dwarf_error.c | 1 +
libdw/dwarf_formudata.c | 23 +-
libdw/dwarf_getscopes.c | 4 +-
libdw/libdwP.h | 2 +
src/ChangeLog | 13 ++
src/readelf.c | 529 ++--
tests/ChangeLog | 6 +
tests/Makefile.am | 3 +-
tests/run-readelf-ranges.sh | 236
12 files changed, 820 insertions(+), 22 deletions(-)
create mode 100755 tests/run-readelf-ranges.sh
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 3045359..b47fac7 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,14 @@
+2018-04-11 Mark Wielaard
+
+ * dwarf.h: Add DWARF5 range list entry DW_RLE encodings.
+ * begin_elf.c (dwarf_scnnames): Add IDX_debug_rnglists.
+ * dwarf_error.c (errmsgs): Add DWARF_E_NO_DEBUG_RNGLISTS.
+ * dwarf_formudata.c (dwarf_formudata): Handle DW_AT_rnglists_base
+ and DW_FORM_rnglistx.
+ * dwarf_getscopes.c (pc_match): Also check for
+ DWARF_E_NO_DEBUG_RNGLISTS.
+ * libdwP.h: Add IDX_debug_rnglists.
+
2018-05-22 Mark Wielaard
* dwarf_getlocation.c (__libdw_cu_base_address): Treat errors of
diff --git a/libdw/dwarf.h b/libdw/dwarf.h
index c438399..9c2495e 100644
--- a/libdw/dwarf.h
+++ b/libdw/dwarf.h
@@ -886,6 +886,19 @@ enum
#define DW_MACRO_GNU_hi_userDW_MACRO_hi_user
+/* Range list entry encoding. */
+enum
+ {
+DW_RLE_end_of_list = 0x0,
+DW_RLE_base_addressx = 0x1,
+DW_RLE_startx_endx = 0x2,
+DW_RLE_startx_length = 0x3,
+DW_RLE_offset_pair = 0x4,
+DW_RLE_base_address = 0x5,
+DW_RLE_start_end = 0x6,
+DW_RLE_start_length = 0x7
+ };
+
/* DWARF call frame instruction encodings. */
enum
{
diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c
index 5d8e79e..2e8c5f3 100644
--- a/libdw/dwarf_begin_elf.c
+++ b/libdw/dwarf_begin_elf.c
@@ -64,6 +64,7 @@ static const char dwarf_scnnames[IDX_last][19] =
[IDX_debug_macinfo] = ".debug_macinfo",
[IDX_debug_macro] = ".debug_macro",
[IDX_debug_ranges] = ".debug_ranges",
+ [IDX_debug_rnglists] = ".debug_rnglists",
[IDX_gnu_debugaltlink] = ".gnu_debugaltlink"
};
#define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0]))
diff --git a/libdw/dwarf_error.c b/libdw/dwarf_error.c
index 63c8bbe..2e8cd77 100644
--- a/libdw/dwarf_error.c
+++ b/libdw/dwarf_error.c
@@ -93,6 +93,7 @@ static const char *errmsgs[] =
[DWARF_E_NO_FLAG] = N_("no flag value"),
[DWARF_E_INVALID_OFFSET] = N_("invalid offset"),
[DWARF_E_NO_DEBUG_RANGES] = N_(".debug_ranges section missing"),
+[DWARF_E_NO_DEBUG_RNGLISTS] = N_(".debug_rnglists section missing"),
[DWARF_E_INVALID_CFI] = N_("invalid CFI section"),
[DWARF_E_NO_ALT_DEBUGLINK] = N_("no alternative debug link found"),
[DWARF_E_INVALID_OPCODE] = N_("invalid opcode"),
diff --git a/libdw/dwarf_formudata.c b/libdw/dwarf_formudata.c
index d56e7dc..280fef2 100644
--- a/libdw/dwarf_formudata.c
+++ b/libdw/dwarf_formudata.c
@@ -211,11 +211,23 @@ dwarf_formudata (Dwarf_Attribute *attr, Dwarf_Word
*return_uval)
case DW_AT_ranges:
case DW_AT_start_scope:
case DW_AT_GNU_ranges_base:
- /* rangelistptr */
- if (__libdw_formptr (attr, IDX_debug_ranges,
- DWARF_E_NO_DEBUG_RANGES, NULL,
- return_uval) == NULL)
- return -1;
+ case DW_AT_rnglists_base:
+ if (attr->cu->version < 5)
+ {
+ /* rangelistptr */
+ if (__libdw_formptr (attr, IDX_debug_ranges,
+ DWARF_E_NO_DEBUG_RANGES, NULL,
+ return_uval) == NULL)
+ return -1;
+ }
+ else
+ {
+ /* rnglistsptr */
+ if (__libdw_formptr (attr, IDX_debug_rnglists,
+ DWARF_E_NO_DEBUG_RNGLISTS, NULL,
+ return_uval) == NULL)
+ return -1;
+ }
break;
case DW_AT_stmt_list:
@@ -278,6 +290,7 @@ dwarf_formudata (Dwarf_Attribute *attr, Dwarf_Word
*return_uval)
break;
case DW_FORM_udata:
+case DW_FORM_rnglistx:
if (datap + 1 > endp)
goto invalid;
get_uleb128 (*return_uval, datap, endp);
diff --git a/libdw/dwarf_getscopes.c b/libdw/dwarf_getscopes.c
index df480d3..5662eec 100644
--- a/libdw/dwarf_getscopes.c
+++ b/libdw/dwarf_getscopes.c
@@ -62,7 +62,9 @@ pc_match (un