static const char *
+dwarf_loc_list_encoding_string (unsigned int kind)
+{
+ switch (kind)
+ {
+#define DWARF_ONE_KNOWN_DW_LLE(NAME, CODE) case CODE: return #NAME;
+ DWARF_ALL_KNOWN_DW_LLE
+#undef DWARF_ONE_KNOWN_DW_LLE
+ default:
+ return NULL;
+ }
+}
+
+
+static const char *
dwarf_line_content_description_string (unsigned int kind)
{
switch (kind)
static const char *
+dwarf_loc_list_encoding_name (unsigned int kind)
+{
+ const char *ret = dwarf_loc_list_encoding_string (kind);
+ return string_or_unknown (ret, kind, 0, 0, false);
+}
+
+
+static const char *
dwarf_line_content_description_name (unsigned int kind)
{
const char *ret = dwarf_line_content_description_string (kind);
#define listptr_address_size(p) ((p)->addr64 ? 8 : 4)
static Dwarf_Addr
-listptr_base (struct listptr *p)
+cudie_base (Dwarf_Die *cudie)
{
Dwarf_Addr base;
- Dwarf_Die cu = CUDIE (p->cu);
/* Find the base address of the compilation unit. It will normally
be specified by DW_AT_low_pc. In DWARF-3 draft 4, the base
address could be overridden by DW_AT_entry_pc. It's been
removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc for
compilation units with discontinuous ranges. */
- if (unlikely (dwarf_lowpc (&cu, &base) != 0))
+ if (unlikely (dwarf_lowpc (cudie, &base) != 0))
{
Dwarf_Attribute attr_mem;
- if (dwarf_formaddr (dwarf_attr (&cu, DW_AT_entry_pc, &attr_mem),
+ if (dwarf_formaddr (dwarf_attr (cudie, DW_AT_entry_pc, &attr_mem),
&base) != 0)
base = 0;
}
return base;
}
+static Dwarf_Addr
+listptr_base (struct listptr *p)
+{
+ Dwarf_Die cu = CUDIE (p->cu);
+ return cudie_base (&cu);
+}
+
static int
compare_listptr (const void *a, const void *b, void *arg)
{
struct listptr *table;
};
-static struct listptr_table known_loclistptr;
+static struct listptr_table known_locsptr;
+static struct listptr_table known_loclistsptr;
static struct listptr_table known_rangelistptr;
static struct listptr_table known_rnglistptr;
}
}
+
+static bool is_split_dwarf (Dwarf *dbg, uint64_t *id, Dwarf_CU **split_cu);
+
+/* Returns true and sets cu and cu_base if the given Dwarf is a split
+ DWARF (.dwo) file. */
+static bool
+split_dwarf_cu_base (Dwarf *dbg, Dwarf_CU **cu, Dwarf_Addr *cu_base)
+{
+ uint64_t id;
+ if (is_split_dwarf (dbg, &id, cu))
+ {
+ Dwarf_Die cudie;
+ if (dwarf_cu_info (*cu, NULL, NULL, &cudie, NULL, NULL, NULL, NULL) == 0)
+ {
+ *cu_base = cudie_base (&cudie);
+ return true;
+ }
+ }
+ return false;
+}
+
/* Print content of DWARF .debug_rnglists section. */
static void
print_debug_rnglists_section (Dwfl_Module *dwflmod,
if (listptr_cu (&known_rnglistptr, &listptr_idx,
(Dwarf_Off) offset,
(Dwarf_Off) (nexthdr - (unsigned char *) data->d_buf),
- &cu_base, &cu))
+ &cu_base, &cu)
+ || split_dwarf_cu_base (dbg, &cu, &cu_base))
{
char *basestr = format_dwarf_addr (dwflmod, address_size,
cu_base, cu_base);
case DW_AT_GNU_call_site_target_clobbered:
case DW_AT_GNU_locviews:
{
- bool nlpt = notice_listptr (section_loc, &known_loclistptr,
- cbargs->addrsize, cbargs->offset_size,
- cbargs->cu, num, attr);
+ bool nlpt;
+ if (cbargs->cu->version < 5)
+ nlpt = notice_listptr (section_loc, &known_locsptr,
+ cbargs->addrsize, cbargs->offset_size,
+ cbargs->cu, num, attr);
+ else
+ {
+ /* Only register for a real section offset. Otherwise
+ it is a DW_FORM_loclistx which is just an index
+ number and we should already have registered the
+ section offset for the index when we saw the
+ DW_AT_loclists_base CU attribute. */
+ if (form == DW_FORM_sec_offset)
+ nlpt = notice_listptr (section_loc, &known_loclistsptr,
+ cbargs->addrsize, cbargs->offset_size,
+ cbargs->cu, num, attr);
+ else
+ nlpt = true;
+
+ }
+
+ if (!cbargs->silent)
+ {
+ if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
+ printf (" %*s%-20s (%s) location list [%6"
+ PRIxMAX "]%s\n",
+ (int) (level * 2), "", dwarf_attr_name (attr),
+ dwarf_form_name (form), (uintmax_t) num,
+ nlpt ? "" : " <WARNING offset too big>");
+ else
+ printf (" %*s%-20s (%s) location index [%6"
+ PRIxMAX "]\n",
+ (int) (level * 2), "", dwarf_attr_name (attr),
+ dwarf_form_name (form), (uintmax_t) num);
+ }
+ }
+ return DWARF_CB_OK;
+
+ case DW_AT_loclists_base:
+ {
+ bool nlpt = notice_listptr (section_loc, &known_loclistsptr,
+ cbargs->addrsize, cbargs->offset_size,
+ cbargs->cu, num, attr);
+
if (!cbargs->silent)
printf (" %*s%-20s (%s) location list [%6" PRIxMAX "]%s\n",
(int) (level * 2), "", dwarf_attr_name (attr),
static void
+print_debug_loclists_section (Dwfl_Module *dwflmod,
+ Ebl *ebl, GElf_Ehdr *ehdr,
+ Elf_Scn *scn, GElf_Shdr *shdr,
+ Dwarf *dbg)
+{
+ printf (gettext ("\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+ elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ (uint64_t) shdr->sh_offset);
+
+ Elf_Data *data = (dbg->sectiondata[IDX_debug_loclists]
+ ?: elf_rawdata (scn, NULL));
+ if (unlikely (data == NULL))
+ {
+ error (0, 0, gettext ("cannot get .debug_loclists content: %s"),
+ elf_errmsg (-1));
+ return;
+ }
+
+ /* For the listptr to get the base address/CU. */
+ sort_listptr (&known_loclistsptr, "loclistsptr");
+ size_t listptr_idx = 0;
+
+ const unsigned char *readp = data->d_buf;
+ const unsigned char *const dataend = ((unsigned char *) data->d_buf
+ + data->d_size);
+ while (readp < dataend)
+ {
+ if (unlikely (readp > dataend - 4))
+ {
+ invalid_data:
+ error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
+ elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
+ return;
+ }
+
+ ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
+ printf (gettext ("Table at Offset 0x%" PRIx64 ":\n\n"),
+ (uint64_t) offset);
+
+ 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 invalid_data;
+
+ unit_length = read_8ubyte_unaligned_inc (dbg, readp);
+ offset_size = 8;
+ }
+ printf (gettext (" Length: %8" PRIu64 "\n"), unit_length);
+
+ /* We need at least 2-bytes + 1-byte + 1-byte + 4-bytes = 8
+ bytes to complete the header. And this unit cannot go beyond
+ the section data. */
+ if (readp > dataend - 8
+ || unit_length < 8
+ || unit_length > (uint64_t) (dataend - readp))
+ goto invalid_data;
+
+ const unsigned char *nexthdr = readp + unit_length;
+
+ uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
+ printf (gettext (" DWARF version: %8" PRIu16 "\n"), version);
+
+ if (version != 5)
+ {
+ error (0, 0, gettext ("Unknown version"));
+ goto next_table;
+ }
+
+ uint8_t address_size = *readp++;
+ printf (gettext (" Address size: %8" PRIu64 "\n"),
+ (uint64_t) address_size);
+
+ if (address_size != 4 && address_size != 8)
+ {
+ error (0, 0, gettext ("unsupported address size"));
+ goto next_table;
+ }
+
+ uint8_t segment_size = *readp++;
+ printf (gettext (" Segment size: %8" PRIu64 "\n"),
+ (uint64_t) segment_size);
+
+ if (segment_size != 0)
+ {
+ error (0, 0, gettext ("unsupported segment size"));
+ goto next_table;
+ }
+
+ uint32_t offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
+ printf (gettext (" Offset entries: %8" PRIu64 "\n"),
+ (uint64_t) offset_entry_count);
+
+ /* We need the CU that uses this unit to get the initial base address. */
+ Dwarf_Addr cu_base = 0;
+ struct Dwarf_CU *cu = NULL;
+ if (listptr_cu (&known_loclistsptr, &listptr_idx,
+ (Dwarf_Off) offset,
+ (Dwarf_Off) (nexthdr - (unsigned char *) data->d_buf),
+ &cu_base, &cu)
+ || split_dwarf_cu_base (dbg, &cu, &cu_base))
+ {
+ char *basestr = format_dwarf_addr (dwflmod, address_size,
+ cu_base, cu_base);
+ Dwarf_Die cudie;
+ if (dwarf_cu_die (cu, &cudie,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL) == NULL)
+ printf (gettext (" Unknown CU base: %s\n"), basestr);
+ else
+ printf (gettext (" CU [%6" PRIx64 "] base: %s\n"),
+ dwarf_dieoffset (&cudie), basestr);
+ free (basestr);
+ }
+ else
+ printf (gettext (" Not associated with a CU.\n"));
+
+ printf ("\n");
+
+ const unsigned char *offset_array_start = readp;
+ if (offset_entry_count > 0)
+ {
+ uint64_t needed = offset_entry_count * offset_size;
+ if (unit_length - 8 < needed)
+ {
+ error (0, 0,
+ gettext ("too many offset entries for unit length"));
+ goto next_table;
+ }
+
+ printf (gettext (" Offsets starting at 0x%" PRIx64 ":\n"),
+ (uint64_t) (offset_array_start
+ - (unsigned char *) data->d_buf));
+ for (uint32_t idx = 0; idx < offset_entry_count; idx++)
+ {
+ printf (" [%6" PRIu32 "] ", idx);
+ if (offset_size == 4)
+ {
+ uint32_t off = read_4ubyte_unaligned_inc (dbg, readp);
+ printf ("0x%" PRIx32 "\n", off);
+ }
+ else
+ {
+ uint64_t off = read_8ubyte_unaligned_inc (dbg, readp);
+ printf ("0x%" PRIx64 "\n", off);
+ }
+ }
+ printf ("\n");
+ }
+
+ Dwarf_Addr base = cu_base;
+ bool start_of_list = true;
+ while (readp < nexthdr)
+ {
+ uint8_t kind = *readp++;
+ uint64_t op1, op2, len;
+ char *a1, *a2;
+
+ /* Skip padding. */
+ if (start_of_list && kind == DW_LLE_end_of_list)
+ continue;
+
+ if (start_of_list)
+ {
+ base = cu_base;
+ printf (" Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
+ (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
+ (uint64_t) (readp - offset_array_start - 1));
+ start_of_list = false;
+ }
+
+ printf (" %s", dwarf_loc_list_encoding_name (kind));
+ switch (kind)
+ {
+ case DW_LLE_end_of_list:
+ start_of_list = true;
+ printf ("\n\n");
+ break;
+
+ case DW_LLE_base_addressx:
+ if ((uint64_t) (nexthdr - readp) < 1)
+ {
+ invalid_entry:
+ error (0, 0, gettext ("invalid loclists data"));
+ goto next_table;
+ }
+ get_uleb128 (op1, readp, nexthdr);
+ printf (" %" PRIx64 "\n", op1);
+ if (! print_unresolved_addresses)
+ {
+ Dwarf_Addr addr;
+ if (get_indexed_addr (cu, op1, &addr) != 0)
+ printf (" ???\n");
+ else
+ {
+ a1 = format_dwarf_addr (dwflmod, address_size,
+ addr, addr);
+ printf (" %s\n", a1);
+ free (a1);
+ }
+ }
+ break;
+
+ case DW_LLE_startx_endx:
+ if ((uint64_t) (nexthdr - readp) < 1)
+ goto invalid_entry;
+ get_uleb128 (op1, readp, nexthdr);
+ if ((uint64_t) (nexthdr - readp) < 1)
+ goto invalid_entry;
+ get_uleb128 (op2, readp, nexthdr);
+ printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
+ if (! print_unresolved_addresses)
+ {
+ Dwarf_Addr addr1;
+ Dwarf_Addr addr2;
+ if (get_indexed_addr (cu, op1, &addr1) != 0
+ || get_indexed_addr (cu, op2, &addr2) != 0)
+ {
+ printf (" ???..\n");
+ printf (" ???\n");
+ }
+ else
+ {
+ a1 = format_dwarf_addr (dwflmod, address_size,
+ addr1, addr1);
+ a2 = format_dwarf_addr (dwflmod, address_size,
+ addr2 - 1, addr2);
+ printf (" %s..\n", a1);
+ printf (" %s\n", a2);
+ free (a1);
+ free (a2);
+ }
+ }
+ if ((uint64_t) (nexthdr - readp) < 1)
+ goto invalid_entry;
+ get_uleb128 (len, readp, nexthdr);
+ if ((uint64_t) (nexthdr - readp) < len)
+ goto invalid_entry;
+ print_ops (dwflmod, dbg, 8, 8, version,
+ address_size, offset_size, cu, len, readp);
+ readp += len;
+ break;
+
+ case DW_LLE_startx_length:
+ if ((uint64_t) (nexthdr - readp) < 1)
+ goto invalid_entry;
+ get_uleb128 (op1, readp, nexthdr);
+ if ((uint64_t) (nexthdr - readp) < 1)
+ goto invalid_entry;
+ get_uleb128 (op2, readp, nexthdr);
+ printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
+ if (! print_unresolved_addresses)
+ {
+ Dwarf_Addr addr1;
+ Dwarf_Addr addr2;
+ if (get_indexed_addr (cu, op1, &addr1) != 0)
+ {
+ printf (" ???..\n");
+ printf (" ???\n");
+ }
+ else
+ {
+ addr2 = addr1 + op2;
+ a1 = format_dwarf_addr (dwflmod, address_size,
+ addr1, addr1);
+ a2 = format_dwarf_addr (dwflmod, address_size,
+ addr2 - 1, addr2);
+ printf (" %s..\n", a1);
+ printf (" %s..\n", a2);
+ free (a1);
+ free (a2);
+ }
+ }
+ if ((uint64_t) (nexthdr - readp) < 1)
+ goto invalid_entry;
+ get_uleb128 (len, readp, nexthdr);
+ if ((uint64_t) (nexthdr - readp) < len)
+ goto invalid_entry;
+ print_ops (dwflmod, dbg, 8, 8, version,
+ address_size, offset_size, cu, len, readp);
+ readp += len;
+ break;
+
+ case DW_LLE_offset_pair:
+ if ((uint64_t) (nexthdr - readp) < 1)
+ goto invalid_entry;
+ get_uleb128 (op1, readp, nexthdr);
+ if ((uint64_t) (nexthdr - readp) < 1)
+ goto invalid_entry;
+ get_uleb128 (op2, readp, nexthdr);
+ printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
+ if (! print_unresolved_addresses)
+ {
+ op1 += base;
+ op2 += base;
+ a1 = format_dwarf_addr (dwflmod, address_size, op1, op1);
+ a2 = format_dwarf_addr (dwflmod, address_size,
+ op2 - 1, op2);
+ printf (" %s..\n", a1);
+ printf (" %s\n", a2);
+ free (a1);
+ free (a2);
+ }
+ if ((uint64_t) (nexthdr - readp) < 1)
+ goto invalid_entry;
+ get_uleb128 (len, readp, nexthdr);
+ if ((uint64_t) (nexthdr - readp) < len)
+ goto invalid_entry;
+ print_ops (dwflmod, dbg, 8, 8, version,
+ address_size, offset_size, cu, len, readp);
+ readp += len;
+ break;
+
+ case DW_LLE_default_location:
+ if ((uint64_t) (nexthdr - readp) < 1)
+ goto invalid_entry;
+ get_uleb128 (len, readp, nexthdr);
+ if ((uint64_t) (nexthdr - readp) < len)
+ goto invalid_entry;
+ print_ops (dwflmod, dbg, 8, 8, version,
+ address_size, offset_size, cu, len, readp);
+ readp += len;
+ break;
+
+ case DW_LLE_base_address:
+ if (address_size == 4)
+ {
+ if ((uint64_t) (nexthdr - readp) < 4)
+ goto invalid_entry;
+ op1 = read_4ubyte_unaligned_inc (dbg, readp);
+ }
+ else
+ {
+ if ((uint64_t) (nexthdr - readp) < 8)
+ goto invalid_entry;
+ op1 = read_8ubyte_unaligned_inc (dbg, readp);
+ }
+ base = op1;
+ printf (" 0x%" PRIx64 "\n", base);
+ if (! print_unresolved_addresses)
+ {
+ a1 = format_dwarf_addr (dwflmod, address_size, base, base);
+ printf (" %s\n", a1);
+ free (a1);
+ }
+ break;
+
+ case DW_LLE_start_end:
+ if (address_size == 4)
+ {
+ if ((uint64_t) (nexthdr - readp) < 8)
+ goto invalid_entry;
+ op1 = read_4ubyte_unaligned_inc (dbg, readp);
+ op2 = read_4ubyte_unaligned_inc (dbg, readp);
+ }
+ else
+ {
+ if ((uint64_t) (nexthdr - readp) < 16)
+ goto invalid_entry;
+ op1 = read_8ubyte_unaligned_inc (dbg, readp);
+ op2 = read_8ubyte_unaligned_inc (dbg, readp);
+ }
+ printf (" 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
+ if (! print_unresolved_addresses)
+ {
+ a1 = format_dwarf_addr (dwflmod, address_size, op1, op1);
+ a2 = format_dwarf_addr (dwflmod, address_size,
+ op2 - 1, op2);
+ printf (" %s..\n", a1);
+ printf (" %s\n", a2);
+ free (a1);
+ free (a2);
+ }
+ if ((uint64_t) (nexthdr - readp) < 1)
+ goto invalid_entry;
+ get_uleb128 (len, readp, nexthdr);
+ if ((uint64_t) (nexthdr - readp) < len)
+ goto invalid_entry;
+ print_ops (dwflmod, dbg, 8, 8, version,
+ address_size, offset_size, cu, len, readp);
+ readp += len;
+ break;
+
+ case DW_LLE_start_length:
+ if (address_size == 4)
+ {
+ if ((uint64_t) (nexthdr - readp) < 4)
+ goto invalid_entry;
+ op1 = read_4ubyte_unaligned_inc (dbg, readp);
+ }
+ else
+ {
+ if ((uint64_t) (nexthdr - readp) < 8)
+ goto invalid_entry;
+ op1 = read_8ubyte_unaligned_inc (dbg, readp);
+ }
+ if ((uint64_t) (nexthdr - readp) < 1)
+ goto invalid_entry;
+ get_uleb128 (op2, readp, nexthdr);
+ printf (" 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
+ if (! print_unresolved_addresses)
+ {
+ a1 = format_dwarf_addr (dwflmod, address_size, op1, op1);
+ op2 = op1 + op2;
+ a2 = format_dwarf_addr (dwflmod, address_size,
+ op2 - 1, op2);
+ printf (" %s..\n", a1);
+ printf (" %s\n", a2);
+ free (a1);
+ free (a2);
+ }
+ if ((uint64_t) (nexthdr - readp) < 1)
+ goto invalid_entry;
+ get_uleb128 (len, readp, nexthdr);
+ if ((uint64_t) (nexthdr - readp) < len)
+ goto invalid_entry;
+ print_ops (dwflmod, dbg, 8, 8, version,
+ address_size, offset_size, cu, len, readp);
+ readp += len;
+ break;
+
+ default:
+ goto invalid_entry;
+ }
+ }
+
+ next_table:
+ if (readp != nexthdr)
+ {
+ size_t padding = nexthdr - readp;
+ printf (gettext (" %zu padding bytes\n\n"), padding);
+ readp = nexthdr;
+ }
+ }
+}
+
+
+static void
print_debug_loc_section (Dwfl_Module *dwflmod,
Ebl *ebl, GElf_Ehdr *ehdr,
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
(uint64_t) shdr->sh_offset);
- sort_listptr (&known_loclistptr, "loclistptr");
+ sort_listptr (&known_locsptr, "loclistptr");
size_t listptr_idx = 0;
uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
Dwarf_CU *cu = last_cu;
unsigned int attr = 0;
- if (first && skip_listptr_hole (&known_loclistptr, &listptr_idx,
+ if (first && skip_listptr_hole (&known_locsptr, &listptr_idx,
&address_size, &offset_size, &base,
&cu, offset, &readp, endp, &attr))
continue;
if (attr == DW_AT_GNU_locviews)
{
- Dwarf_Off next_off = next_listptr_offset (&known_loclistptr,
+ Dwarf_Off next_off = next_listptr_offset (&known_loclistsptr,
listptr_idx);
const unsigned char *locp = readp;
const unsigned char *locendp;
NEW_SECTION (types),
NEW_SECTION (line),
NEW_SECTION (loc),
+ /* loclists is loc for DWARF5. */
+ { ".debug_loclists", section_loc,
+ print_debug_loclists_section },
NEW_SECTION (pubnames),
NEW_SECTION (str),
/* A DWARF5 specialised debug string section. */
dwfl_end (skel_dwfl);
free (skel_name);
- reset_listptr (&known_loclistptr);
+ reset_listptr (&known_locsptr);
+ reset_listptr (&known_loclistsptr);
reset_listptr (&known_rangelistptr);
reset_listptr (&known_rnglistptr);
}
range 12, 1a
EOF
+# .debug_rnglists (DWARF5), see tests/testfile-dwarf-45.source
+testfiles testfile-dwarf-5
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=loc testfile-dwarf-5<<\EOF
+
+DWARF section [31] '.debug_loclists' at offset 0x1c0c:
+Table at Offset 0x0:
+
+ Length: 96
+ DWARF version: 5
+ Address size: 8
+ Segment size: 0
+ Offset entries: 0
+ CU [ c] base: 0x0000000000400510 <foo>
+
+ Offset: c, Index: 0
+ offset_pair 0, a
+ 0x0000000000400510 <foo>..
+ 0x0000000000400519 <foo+0x9>
+ [ 0] reg5
+ offset_pair a, 34
+ 0x000000000040051a <foo+0xa>..
+ 0x0000000000400543 <foo+0x33>
+ [ 0] entry_value:
+ [ 0] reg5
+ [ 3] stack_value
+ end_of_list
+
+ Offset: 1a, Index: e
+ offset_pair 1b, 2d
+ 0x000000000040052b <foo+0x1b>..
+ 0x000000000040053c <foo+0x2c>
+ [ 0] addr 0x601038 <m>
+ end_of_list
+
+ Offset: 28, Index: 1c
+ offset_pair 1b, 21
+ 0x000000000040052b <foo+0x1b>..
+ 0x0000000000400530 <foo+0x20>
+ [ 0] reg5
+ end_of_list
+
+ Offset: 2e, Index: 22
+ offset_pair 1b, 27
+ 0x000000000040052b <foo+0x1b>..
+ 0x0000000000400536 <foo+0x26>
+ [ 0] reg5
+ offset_pair 29, 2d
+ 0x0000000000400539 <foo+0x29>..
+ 0x000000000040053c <foo+0x2c>
+ [ 0] reg5
+ end_of_list
+
+ Offset: 39, Index: 2d
+ offset_pair 21, 27
+ 0x0000000000400531 <foo+0x21>..
+ 0x0000000000400536 <foo+0x26>
+ [ 0] reg5
+ offset_pair 29, 2d
+ 0x0000000000400539 <foo+0x29>..
+ 0x000000000040053c <foo+0x2c>
+ [ 0] reg5
+ end_of_list
+
+ Offset: 44, Index: 38
+ offset_pair 21, 2d
+ 0x0000000000400531 <foo+0x21>..
+ 0x000000000040053c <foo+0x2c>
+ [ 0] reg5
+ end_of_list
+
+ Offset: 4a, Index: 3e
+ offset_pair 2d, 33
+ 0x000000000040053d <foo+0x2d>..
+ 0x0000000000400542 <foo+0x32>
+ [ 0] reg5
+ end_of_list
+
+ Offset: 50, Index: 44
+ offset_pair 40, 4f
+ 0x0000000000400550 <baz>..
+ 0x000000000040055e <baz+0xe>
+ [ 0] reg5
+ offset_pair 4f, 51
+ 0x000000000040055f <baz+0xf>..
+ 0x0000000000400560 <baz+0x10>
+ [ 0] entry_value:
+ [ 0] reg5
+ [ 3] stack_value
+ end_of_list
+
+ Offset: 5e, Index: 52
+ offset_pair 40, 50
+ 0x0000000000400550 <baz>..
+ 0x000000000040055f <baz+0xf>
+ [ 0] reg5
+ end_of_list
+
+Table at Offset 0x64:
+
+ Length: 159
+ DWARF version: 5
+ Address size: 8
+ Segment size: 0
+ Offset entries: 0
+ CU [ 218] base: 000000000000000000
+
+ Offset: 70, Index: 0
+ base_address 0x400410
+ 0x0000000000400410 <main>
+ offset_pair 0, 14
+ 0x0000000000400410 <main>..
+ 0x0000000000400423 <main+0x13>
+ [ 0] reg5
+ offset_pair 14, 20
+ 0x0000000000400424 <main+0x14>..
+ 0x000000000040042f <main+0x1f>
+ [ 0] entry_value:
+ [ 0] reg5
+ [ 3] stack_value
+ end_of_list
+
+ Offset: 87, Index: 17
+ base_address 0x400410
+ 0x0000000000400410 <main>
+ offset_pair 0, 18
+ 0x0000000000400410 <main>..
+ 0x0000000000400427 <main+0x17>
+ [ 0] reg4
+ offset_pair 18, 20
+ 0x0000000000400428 <main+0x18>..
+ 0x000000000040042f <main+0x1f>
+ [ 0] entry_value:
+ [ 0] reg4
+ [ 3] stack_value
+ end_of_list
+
+ Offset: 9e, Index: 2e
+ start_length 0x400421, 7
+ 0x0000000000400421 <main+0x11>..
+ 0x0000000000400427 <main+0x17>
+ [ 0] reg0
+ end_of_list
+
+ Offset: ab, Index: 3b
+ base_address 0x400570
+ 0x0000000000400570 <calc>
+ offset_pair 0, 8
+ 0x0000000000400570 <calc>..
+ 0x0000000000400577 <calc+0x7>
+ [ 0] reg5
+ offset_pair 8, 2b
+ 0x0000000000400578 <calc+0x8>..
+ 0x000000000040059a <calc+0x2a>
+ [ 0] entry_value:
+ [ 0] reg5
+ [ 3] stack_value
+ end_of_list
+
+ Offset: c2, Index: 52
+ start_length 0x400588, b
+ 0x0000000000400588 <calc+0x18>..
+ 0x0000000000400592 <calc+0x22>
+ [ 0] reg0
+ end_of_list
+
+ Offset: cf, Index: 5f
+ base_address 0x400588
+ 0x0000000000400588 <calc+0x18>
+ offset_pair 0, 2
+ 0x0000000000400588 <calc+0x18>..
+ 0x0000000000400589 <calc+0x19>
+ [ 0] reg1
+ offset_pair 2, 7
+ 0x000000000040058a <calc+0x1a>..
+ 0x000000000040058e <calc+0x1e>
+ [ 0] reg5
+ offset_pair 7, b
+ 0x000000000040058f <calc+0x1f>..
+ 0x0000000000400592 <calc+0x22>
+ [ 0] entry_value:
+ [ 0] reg5
+ [ 3] deref_size 1
+ [ 5] const1u 56
+ [ 7] shl
+ [ 8] const1u 56
+ [10] shra
+ [11] stack_value
+ end_of_list
+
+ Offset: f3, Index: 83
+ base_address 0x400588
+ 0x0000000000400588 <calc+0x18>
+ offset_pair 0, 2
+ 0x0000000000400588 <calc+0x18>..
+ 0x0000000000400589 <calc+0x19>
+ [ 0] reg1
+ offset_pair 2, b
+ 0x000000000040058a <calc+0x1a>..
+ 0x0000000000400592 <calc+0x22>
+ [ 0] reg5
+ end_of_list
+
+EOF
+
+# Same as above, but for DWARF4, note completely different encoding, but
+# the information is the same (check with diff -uwb).
+testfiles testfile-dwarf-4
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=loc testfile-dwarf-4<<\EOF
+
+DWARF section [31] '.debug_loc' at offset 0x1c86:
+
+ CU [ b] base: 0x0000000000400510 <foo>
+ [ 0] range 0, a
+ 0x0000000000400510 <foo>..
+ 0x0000000000400519 <foo+0x9>
+ [ 0] reg5
+ range a, 34
+ 0x000000000040051a <foo+0xa>..
+ 0x0000000000400543 <foo+0x33>
+ [ 0] GNU_entry_value:
+ [ 0] reg5
+ [ 3] stack_value
+ [ 39] range 1b, 2d
+ 0x000000000040052b <foo+0x1b>..
+ 0x000000000040053c <foo+0x2c>
+ [ 0] addr 0x601038 <m>
+ [ 64] range 1b, 21
+ 0x000000000040052b <foo+0x1b>..
+ 0x0000000000400530 <foo+0x20>
+ [ 0] reg5
+ [ 87] range 1b, 27
+ 0x000000000040052b <foo+0x1b>..
+ 0x0000000000400536 <foo+0x26>
+ [ 0] reg5
+ range 29, 2d
+ 0x0000000000400539 <foo+0x29>..
+ 0x000000000040053c <foo+0x2c>
+ [ 0] reg5
+ [ bd] range 21, 27
+ 0x0000000000400531 <foo+0x21>..
+ 0x0000000000400536 <foo+0x26>
+ [ 0] reg5
+ range 29, 2d
+ 0x0000000000400539 <foo+0x29>..
+ 0x000000000040053c <foo+0x2c>
+ [ 0] reg5
+ [ f3] range 21, 2d
+ 0x0000000000400531 <foo+0x21>..
+ 0x000000000040053c <foo+0x2c>
+ [ 0] reg5
+ [ 116] range 2d, 33
+ 0x000000000040053d <foo+0x2d>..
+ 0x0000000000400542 <foo+0x32>
+ [ 0] reg5
+ [ 139] range 40, 4f
+ 0x0000000000400550 <baz>..
+ 0x000000000040055e <baz+0xe>
+ [ 0] reg5
+ range 4f, 51
+ 0x000000000040055f <baz+0xf>..
+ 0x0000000000400560 <baz+0x10>
+ [ 0] GNU_entry_value:
+ [ 0] reg5
+ [ 3] stack_value
+ [ 172] range 40, 50
+ 0x0000000000400550 <baz>..
+ 0x000000000040055f <baz+0xf>
+ [ 0] reg5
+
+ CU [ 21c] base: 000000000000000000
+ [ 195] range 400410, 400424
+ 0x0000000000400410 <main>..
+ 0x0000000000400423 <main+0x13>
+ [ 0] reg5
+ range 400424, 400430
+ 0x0000000000400424 <main+0x14>..
+ 0x000000000040042f <main+0x1f>
+ [ 0] GNU_entry_value:
+ [ 0] reg5
+ [ 3] stack_value
+ [ 1ce] range 400410, 400428
+ 0x0000000000400410 <main>..
+ 0x0000000000400427 <main+0x17>
+ [ 0] reg4
+ range 400428, 400430
+ 0x0000000000400428 <main+0x18>..
+ 0x000000000040042f <main+0x1f>
+ [ 0] GNU_entry_value:
+ [ 0] reg4
+ [ 3] stack_value
+ [ 207] range 400421, 400428
+ 0x0000000000400421 <main+0x11>..
+ 0x0000000000400427 <main+0x17>
+ [ 0] reg0
+ [ 22a] range 400570, 400578
+ 0x0000000000400570 <calc>..
+ 0x0000000000400577 <calc+0x7>
+ [ 0] reg5
+ range 400578, 40059b
+ 0x0000000000400578 <calc+0x8>..
+ 0x000000000040059a <calc+0x2a>
+ [ 0] GNU_entry_value:
+ [ 0] reg5
+ [ 3] stack_value
+ [ 263] range 400588, 400593
+ 0x0000000000400588 <calc+0x18>..
+ 0x0000000000400592 <calc+0x22>
+ [ 0] reg0
+ [ 286] range 400588, 40058a
+ 0x0000000000400588 <calc+0x18>..
+ 0x0000000000400589 <calc+0x19>
+ [ 0] reg1
+ range 40058a, 40058f
+ 0x000000000040058a <calc+0x1a>..
+ 0x000000000040058e <calc+0x1e>
+ [ 0] reg5
+ range 40058f, 400593
+ 0x000000000040058f <calc+0x1f>..
+ 0x0000000000400592 <calc+0x22>
+ [ 0] GNU_entry_value:
+ [ 0] reg5
+ [ 3] deref_size 1
+ [ 5] const1u 56
+ [ 7] shl
+ [ 8] const1u 56
+ [10] shra
+ [11] stack_value
+ [ 2da] range 400588, 40058a
+ 0x0000000000400588 <calc+0x18>..
+ 0x0000000000400589 <calc+0x19>
+ [ 0] reg1
+ range 40058a, 400593
+ 0x000000000040058a <calc+0x1a>..
+ 0x0000000000400592 <calc+0x22>
+ [ 0] reg5
+EOF
+
+# Split DWARF5 variant. Note that the .debug_loclists moved to the .dwo file
+# and now uses an index and addrx indirections.
+testfiles testfile-splitdwarf-5 testfile-hello5.dwo testfile-world5.dwo
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=loc --dwarf-skeleton=testfile-splitdwarf-5 testfile-hello5.dwo testfile-world5.dwo <<\EOF
+
+testfile-hello5.dwo:
+
+
+DWARF section [ 3] '.debug_loclists.dwo' at offset 0x236:
+Table at Offset 0x0:
+
+ Length: 125
+ DWARF version: 5
+ Address size: 8
+ Segment size: 0
+ Offset entries: 9
+ CU [ 14] base: 0x0000000000401160 <foo>
+
+ Offsets starting at 0xc:
+ [ 0] 0x24
+ [ 1] 0x32
+ [ 2] 0x39
+ [ 3] 0x3f
+ [ 4] 0x4a
+ [ 5] 0x55
+ [ 6] 0x5b
+ [ 7] 0x61
+ [ 8] 0x6f
+
+ Offset: 30, Index: 24
+ startx_length f, a
+ 0x0000000000401160 <foo>..
+ 0x0000000000401169 <foo+0x9>..
+ [ 0] reg5
+ startx_length 0, 2a
+ 0x000000000040116a <foo+0xa>..
+ 0x0000000000401193 <foo+0x33>..
+ [ 0] entry_value:
+ [ 0] reg5
+ [ 3] stack_value
+ end_of_list
+
+ Offset: 3e, Index: 32
+ startx_length 11, 12
+ 0x000000000040117b <foo+0x1b>..
+ 0x000000000040118c <foo+0x2c>..
+ [ 0] addrx [18] 0x404038 <m>
+ end_of_list
+
+ Offset: 45, Index: 39
+ startx_length 11, 6
+ 0x000000000040117b <foo+0x1b>..
+ 0x0000000000401180 <foo+0x20>..
+ [ 0] reg5
+ end_of_list
+
+ Offset: 4b, Index: 3f
+ startx_length 11, c
+ 0x000000000040117b <foo+0x1b>..
+ 0x0000000000401186 <foo+0x26>..
+ [ 0] reg5
+ startx_length 1, 4
+ 0x0000000000401189 <foo+0x29>..
+ 0x000000000040118c <foo+0x2c>..
+ [ 0] reg5
+ end_of_list
+
+ Offset: 56, Index: 4a
+ startx_length 4, 6
+ 0x0000000000401181 <foo+0x21>..
+ 0x0000000000401186 <foo+0x26>..
+ [ 0] reg5
+ startx_length 1, 4
+ 0x0000000000401189 <foo+0x29>..
+ 0x000000000040118c <foo+0x2c>..
+ [ 0] reg5
+ end_of_list
+
+ Offset: 61, Index: 55
+ startx_length 4, c
+ 0x0000000000401181 <foo+0x21>..
+ 0x000000000040118c <foo+0x2c>..
+ [ 0] reg5
+ end_of_list
+
+ Offset: 67, Index: 5b
+ startx_length 2, 6
+ 0x000000000040118d <foo+0x2d>..
+ 0x0000000000401192 <foo+0x32>..
+ [ 0] reg5
+ end_of_list
+
+ Offset: 6d, Index: 61
+ startx_length 9, f
+ 0x00000000004011a0 <baz>..
+ 0x00000000004011ae <baz+0xe>..
+ [ 0] reg5
+ startx_length 5, 2
+ 0x00000000004011af <baz+0xf>..
+ 0x00000000004011b0 <baz+0x10>..
+ [ 0] entry_value:
+ [ 0] reg5
+ [ 3] stack_value
+ end_of_list
+
+ Offset: 7b, Index: 6f
+ startx_length 9, 10
+ 0x00000000004011a0 <baz>..
+ 0x00000000004011af <baz+0xf>..
+ [ 0] reg5
+ end_of_list
+
+
+testfile-world5.dwo:
+
+
+DWARF section [ 3] '.debug_loclists.dwo' at offset 0x217:
+Table at Offset 0x0:
+
+ Length: 128
+ DWARF version: 5
+ Address size: 8
+ Segment size: 0
+ Offset entries: 7
+ CU [ 14] base: 000000000000000000
+
+ Offsets starting at 0xc:
+ [ 0] 0x1c
+ [ 1] 0x2a
+ [ 2] 0x38
+ [ 3] 0x3e
+ [ 4] 0x4c
+ [ 5] 0x52
+ [ 6] 0x6d
+
+ Offset: 28, Index: 1c
+ startx_length 2, 14
+ 0x0000000000401060 <main>..
+ 0x0000000000401073 <main+0x13>..
+ [ 0] reg5
+ startx_length 4, c
+ 0x0000000000401074 <main+0x14>..
+ 0x000000000040107f <main+0x1f>..
+ [ 0] entry_value:
+ [ 0] reg5
+ [ 3] stack_value
+ end_of_list
+
+ Offset: 36, Index: 2a
+ startx_length 2, 18
+ 0x0000000000401060 <main>..
+ 0x0000000000401077 <main+0x17>..
+ [ 0] reg4
+ startx_length 7, 6
+ 0x0000000000401078 <main+0x18>..
+ 0x000000000040107d <main+0x1d>..
+ [ 0] entry_value:
+ [ 0] reg4
+ [ 3] stack_value
+ end_of_list
+
+ Offset: 44, Index: 38
+ startx_length 3, 7
+ 0x0000000000401071 <main+0x11>..
+ 0x0000000000401077 <main+0x17>..
+ [ 0] reg0
+ end_of_list
+
+ Offset: 4a, Index: 3e
+ startx_length d, 8
+ 0x00000000004011c0 <calc>..
+ 0x00000000004011c7 <calc+0x7>..
+ [ 0] reg5
+ startx_length e, 23
+ 0x00000000004011c8 <calc+0x8>..
+ 0x00000000004011ea <calc+0x2a>..
+ [ 0] entry_value:
+ [ 0] reg5
+ [ 3] stack_value
+ end_of_list
+
+ Offset: 58, Index: 4c
+ startx_length f, b
+ 0x00000000004011d8 <calc+0x18>..
+ 0x00000000004011e2 <calc+0x22>..
+ [ 0] reg0
+ end_of_list
+
+ Offset: 5e, Index: 52
+ startx_length f, 2
+ 0x00000000004011d8 <calc+0x18>..
+ 0x00000000004011d9 <calc+0x19>..
+ [ 0] reg1
+ startx_length 10, 5
+ 0x00000000004011da <calc+0x1a>..
+ 0x00000000004011de <calc+0x1e>..
+ [ 0] reg5
+ startx_length 0, 4
+ 0x00000000004011df <calc+0x1f>..
+ 0x00000000004011e2 <calc+0x22>..
+ [ 0] entry_value:
+ [ 0] reg5
+ [ 3] deref_size 1
+ [ 5] const1u 56
+ [ 7] shl
+ [ 8] const1u 56
+ [10] shra
+ [11] stack_value
+ end_of_list
+
+ Offset: 79, Index: 6d
+ startx_length f, 2
+ 0x00000000004011d8 <calc+0x18>..
+ 0x00000000004011d9 <calc+0x19>..
+ [ 0] reg1
+ startx_length 10, 9
+ 0x00000000004011da <calc+0x1a>..
+ 0x00000000004011e2 <calc+0x22>..
+ [ 0] reg5
+ end_of_list
+
+EOF
+
exit 0