summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2018-04-26 11:53:49 +0200
committerMark Wielaard <mark@klomp.org>2018-05-15 11:25:27 +0200
commit6ed8b94952ddf155960c799ef76f3048f033e873 (patch)
treeb9270241542b3575e08f3639829137dee8caaa67
parentb9c76ded0f07d270bbb9314fb970bb0afcb71d58 (diff)
downloadelfutils-6ed8b94952ddf155960c799ef76f3048f033e873.tar.gz
readelf: Add DWARF5 .debug_line support.
This only changes the parsing of the directory and file name tables. It does this by sharing the printing of (non-CU based) from data from the .debug_macro code. Adding support for printing strx[1234] form data by sharing the code that detects the correct str_offsets_base in libdw. The header format is also cleaned up a bit so that it better lines out. Testcases adjusted and new ones added. Signed-off-by: Mark Wielaard <mark@klomp.org>
-rw-r--r--libdw/ChangeLog7
-rw-r--r--libdw/dwarf_formstring.c17
-rw-r--r--libdw/libdwP.h107
-rw-r--r--src/ChangeLog11
-rw-r--r--src/readelf.c711
-rw-r--r--tests/ChangeLog6
-rwxr-xr-xtests/run-readelf-line.sh712
-rwxr-xr-xtests/run-readelf-zdebug.sh20
8 files changed, 1333 insertions, 258 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 86d2b78a..efdd927f 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,10 @@
+2018-05-09 Mark Wielaard <mark@klomp.org>
+
+ * dwarf_formstring.c (__libdw_cu_str_off_base): Moved to...
+ * libdwP.h (__libdw_cu_str_off_base): ...here. Make static inline.
+ (str_offsets_base_off): New internal function that also parses
+ .debug_str_offsets header if necessary.
+
2018-05-11 Mark Wielaard <mark@klomp.org>
* dwarf_siblingof.c (dwarf_siblingof): Don't reference cu till it is
diff --git a/libdw/dwarf_formstring.c b/libdw/dwarf_formstring.c
index c55c7f04..251784df 100644
--- a/libdw/dwarf_formstring.c
+++ b/libdw/dwarf_formstring.c
@@ -177,20 +177,3 @@ dwarf_formstring (Dwarf_Attribute *attrp)
return (const char *) data->d_buf + off;
}
INTDEF(dwarf_formstring)
-
-Dwarf_Off __libdw_cu_str_off_base (Dwarf_CU *cu)
-{
- if (cu->str_off_base == (Dwarf_Off) -1)
- {
- Dwarf_Die cu_die = CUDIE(cu);
- Dwarf_Attribute attr;
- if (dwarf_attr (&cu_die, DW_AT_str_offsets_base, &attr) != NULL)
- {
- Dwarf_Word off;
- if (dwarf_formudata (&attr, &off) == 0)
- cu->str_off_base = off;
- }
- }
-
- return cu->str_off_base;
-}
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 7aa290e5..da0383f4 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -933,8 +933,113 @@ Dwarf_Addr __libdw_cu_base_address (Dwarf_CU *cu);
/* Get the address base for the CU, fetches it when not yet set. */
Dwarf_Off __libdw_cu_addr_base (Dwarf_CU *cu);
+/* Gets the .debug_str_offsets base offset to use. static inline to
+ be shared between libdw and eu-readelf. */
+static inline Dwarf_Off
+str_offsets_base_off (Dwarf *dbg, Dwarf_CU *cu)
+{
+ /* If we don't have a CU, then find and use the first one in the
+ debug file (when we support .dwp files, we must actually find the
+ one matching our "caller" - aka macro or line). If we (now) have
+ a cu and str_offsets_base attribute, just use that. Otherwise
+ use the first offset. But we might have to parse the header
+ first, but only if this is version 5. Assume if all else fails,
+ this is version 4, without header. */
+
+ if (cu == NULL && dbg != NULL)
+ {
+ Dwarf_CU *first_cu;
+ if (dwarf_get_units (dbg, NULL, &first_cu,
+ NULL, NULL, NULL, NULL) == 0)
+ cu = first_cu;
+ }
+
+ if (cu != NULL)
+ {
+ if (cu->str_off_base == (Dwarf_Off) -1)
+ {
+ Dwarf_Die cu_die = CUDIE(cu);
+ Dwarf_Attribute attr;
+ if (dwarf_attr (&cu_die, DW_AT_str_offsets_base, &attr) != NULL)
+ {
+ Dwarf_Word off;
+ if (dwarf_formudata (&attr, &off) == 0)
+ {
+ cu->str_off_base = off;
+ return cu->str_off_base;
+ }
+ }
+ /* For older DWARF simply assume zero (no header). */
+ if (cu->version < 5)
+ {
+ cu->str_off_base = 0;
+ return cu->str_off_base;
+ }
+ }
+ else
+ return cu->str_off_base;
+ }
+
+ /* No str_offsets_base attribute, we have to assume "zero".
+ But there could be a header first. */
+ Dwarf_Off off = 0;
+ if (dbg == NULL)
+ goto no_header;
+
+ Elf_Data *data = dbg->sectiondata[IDX_debug_str_offsets];
+ if (data == NULL)
+ goto no_header;
+
+ const unsigned char *start;
+ const unsigned char *readp;
+ const unsigned char *readendp;
+ start = readp = (const unsigned char *) data->d_buf;
+ readendp = (const unsigned char *) data->d_buf + data->d_size;
+
+ uint64_t unit_length;
+ uint16_t version;
+
+ unit_length = read_4ubyte_unaligned_inc (dbg, readp);
+ if (unlikely (unit_length == 0xffffffff))
+ {
+ if (unlikely (readendp - readp < 8))
+ goto no_header;
+ unit_length = read_8ubyte_unaligned_inc (dbg, readp);
+ /* In theory the offset size could be different
+ between CU and str_offsets unit. But we just
+ ignore that here. */
+ }
+
+ /* We need at least 2-bytes (version) + 2-bytes (padding) =
+ 4 bytes to complete the header. And this unit cannot go
+ beyond the section data. */
+ if (readendp - readp < 4
+ || unit_length < 4
+ || (uint64_t) (readendp - readp) < unit_length)
+ goto no_header;
+
+ version = read_2ubyte_unaligned_inc (dbg, readp);
+ if (version != 5)
+ goto no_header;
+ /* padding */
+ read_2ubyte_unaligned_inc (dbg, readp);
+
+ off = (Dwarf_Off) (readp - start);
+
+ no_header:
+ if (cu != NULL)
+ cu->str_off_base = off;
+
+ return off;
+}
+
+
/* Get the string offsets base for the CU, fetches it when not yet set. */
-Dwarf_Off __libdw_cu_str_off_base (Dwarf_CU *cu);
+static inline Dwarf_Off __libdw_cu_str_off_base (Dwarf_CU *cu)
+{
+ return str_offsets_base_off (NULL, cu);
+}
+
/* Given a file descriptor, dir and file returns a full path. If the
file is absolute (starts with a /) a copy of file is returned. If
diff --git a/src/ChangeLog b/src/ChangeLog
index 24504077..3870508a 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,14 @@
+2018-05-09 Mark Wielaard <mark@klomp.org>
+
+ * readelf.c (dwarf_line_content_description_string): New function.
+ (dwarf_line_content_description_name): Likewise.
+ (print_bytes): Likewise.
+ (print_form_data): Likewise. Based on code taken from...
+ (print_debug_macro_section): ...here. Now calls print_form_data
+ and str_offsets_base_off.
+ (print_debug_line_section): Parse DWARF5 header, directory and file
+ name tables.
+
2018-05-12 Mark Wielaard <mark@klomp.org>
* addr2line.c (main): Add fflush (stdout) after handle_address ()
diff --git a/src/readelf.c b/src/readelf.c
index 4b66cd0d..c3154cae 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -1,7 +1,6 @@
/* Print information from ELF file in human-readable form.
- Copyright (C) 1999-2017 Red Hat, Inc.
+ Copyright (C) 1999-2018 Red Hat, Inc.
This file is part of elfutils.
- Written by Ulrich Drepper <drepper@redhat.com>, 1999.
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
@@ -3975,6 +3974,20 @@ dwarf_unit_string (unsigned int type)
}
+static const char *
+dwarf_line_content_description_string (unsigned int kind)
+{
+ switch (kind)
+ {
+#define DWARF_ONE_KNOWN_DW_LNCT(NAME, CODE) case CODE: return #NAME;
+ DWARF_ALL_KNOWN_DW_LNCT
+#undef DWARF_ONE_KNOWN_DW_LNCT
+ default:
+ return NULL;
+ }
+}
+
+
/* Used by all dwarf_foo_name functions. */
static const char *
string_or_unknown (const char *known, unsigned int code,
@@ -4122,6 +4135,15 @@ dwarf_unit_name (unsigned int type)
}
+static const char *
+dwarf_line_content_description_name (unsigned int kind)
+{
+ const char *ret = dwarf_line_content_description_string (kind);
+ return string_or_unknown (ret, kind, DW_LNCT_lo_user, DW_LNCT_hi_user,
+ false);
+}
+
+
static void
print_block (size_t n, const void *block)
{
@@ -4139,6 +4161,17 @@ print_block (size_t n, const void *block)
}
static void
+print_bytes (size_t n, const unsigned char *bytes)
+{
+ while (n-- > 0)
+ {
+ printf ("%02x", *bytes++);
+ if (n > 0)
+ printf (" ");
+ }
+}
+
+static void
print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
unsigned int vers, unsigned int addrsize, unsigned int offset_size,
struct Dwarf_CU *cu, Dwarf_Word len, const unsigned char *data)
@@ -6749,6 +6782,230 @@ print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
}
+/* Print the value of a form.
+ Returns new value of readp, or readendp on failure. */
+static const unsigned char *
+print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
+ const unsigned char *readendp, unsigned int offset_len,
+ Dwarf_Off str_offsets_base)
+{
+ Dwarf_Word val;
+ unsigned char *endp;
+ Elf_Data *data;
+ char *str;
+ switch (form)
+ {
+ case DW_FORM_data1:
+ if (readendp - readp < 1)
+ {
+ invalid_data:
+ error (0, 0, "invalid data");
+ return readendp;
+ }
+ val = *readp++;
+ printf (" %" PRIx8, (unsigned int) val);
+ break;
+
+ case DW_FORM_data2:
+ if (readendp - readp < 2)
+ goto invalid_data;
+ val = read_2ubyte_unaligned_inc (dbg, readp);
+ printf(" %" PRIx16, (unsigned int) val);
+ break;
+
+ case DW_FORM_data4:
+ if (readendp - readp < 4)
+ goto invalid_data;
+ val = read_4ubyte_unaligned_inc (dbg, readp);
+ printf (" %" PRIx32, (unsigned int) val);
+ break;
+
+ case DW_FORM_data8:
+ if (readendp - readp < 8)
+ goto invalid_data;
+ val = read_8ubyte_unaligned_inc (dbg, readp);
+ printf (" %" PRIx64, val);
+ break;
+
+ case DW_FORM_sdata:
+ if (readendp - readp < 1)
+ goto invalid_data;
+ get_sleb128 (val, readp, readendp);
+ printf (" %" PRIx64, val);
+ break;
+
+ case DW_FORM_udata:
+ if (readendp - readp < 1)
+ goto invalid_data;
+ get_uleb128 (val, readp, readendp);
+ printf (" %" PRIx64, val);
+ break;
+
+ case DW_FORM_block:
+ if (readendp - readp < 1)
+ goto invalid_data;
+ get_uleb128 (val, readp, readendp);
+ if (readendp - readp < (ptrdiff_t) val)
+ goto invalid_data;
+ print_bytes (val, readp);
+ readp += val;
+ break;
+
+ case DW_FORM_block1:
+ if (readendp - readp < 1)
+ goto invalid_data;
+ val = *readp++;
+ if (readendp - readp < (ptrdiff_t) val)
+ goto invalid_data;
+ print_bytes (val, readp);
+ readp += val;
+ break;
+
+ case DW_FORM_block2:
+ if (readendp - readp < 2)
+ goto invalid_data;
+ val = read_2ubyte_unaligned_inc (dbg, readp);
+ if (readendp - readp < (ptrdiff_t) val)
+ goto invalid_data;
+ print_bytes (val, readp);
+ readp += val;
+ break;
+
+ case DW_FORM_block4:
+ if (readendp - readp < 2)
+ goto invalid_data;
+ val = read_4ubyte_unaligned_inc (dbg, readp);
+ if (readendp - readp < (ptrdiff_t) val)
+ goto invalid_data;
+ print_bytes (val, readp);
+ readp += val;
+ break;
+
+ case DW_FORM_data16:
+ if (readendp - readp < 16)
+ goto invalid_data;
+ print_bytes (16, readp);
+ readp += 16;
+ break;
+
+ case DW_FORM_flag:
+ if (readendp - readp < 1)
+ goto invalid_data;
+ val = *readp++;
+ printf ("%s", val != 0 ? gettext ("yes") : gettext ("no"));
+ break;
+
+ case DW_FORM_string:
+ endp = memchr (readp, '\0', readendp - readp);
+ if (endp == NULL)
+ goto invalid_data;
+ printf ("%s", readp);
+ readp = endp + 1;
+ break;
+
+ case DW_FORM_strp:
+ case DW_FORM_line_strp:
+ case DW_FORM_strp_sup:
+ if (readendp - readp < offset_len)
+ goto invalid_data;
+ if (offset_len == 8)
+ val = read_8ubyte_unaligned_inc (dbg, readp);
+ else
+ val = read_4ubyte_unaligned_inc (dbg, readp);
+ if (form == DW_FORM_strp)
+ data = dbg->sectiondata[IDX_debug_str];
+ else if (form == DW_FORM_line_strp)
+ data = dbg->sectiondata[IDX_debug_line_str];
+ else /* form == DW_FORM_strp_sup */
+ {
+ Dwarf *alt = dwarf_getalt (dbg);
+ data = alt != NULL ? alt->sectiondata[IDX_debug_str] : NULL;
+ }
+ if (data == NULL || val >= data->d_size
+ || memchr (data->d_buf + val, '\0', data->d_size - val) == NULL)
+ str = "???";
+ else
+ str = (char *) data->d_buf + val;
+ printf ("%s (%" PRIu64 ")", str, val);
+ break;
+
+ case DW_FORM_sec_offset:
+ if (readendp - readp < offset_len)
+ goto invalid_data;
+ if (offset_len == 8)
+ val = read_8ubyte_unaligned_inc (dbg, readp);
+ else
+ val = read_4ubyte_unaligned_inc (dbg, readp);
+ printf ("[%" PRIx64 "]", val);
+ break;
+
+ case DW_FORM_strx:
+ if (readendp - readp < 1)
+ goto invalid_data;
+ get_uleb128 (val, readp, readendp);
+ strx_val:
+ data = dbg->sectiondata[IDX_debug_str_offsets];
+ if (data == NULL
+ || data->d_size - str_offsets_base < val)
+ str = "???";
+ else
+ {
+ readp = data->d_buf + str_offsets_base + val;
+ readendp = data->d_buf + data->d_size;
+ if (readendp - readp < offset_len)
+ str = "???";
+ else
+ {
+ Dwarf_Off idx;
+ if (offset_len == 8)
+ idx = read_8ubyte_unaligned_inc (dbg, readp);
+ else
+ idx = read_4ubyte_unaligned_inc (dbg, readp);
+
+ data = dbg->sectiondata[IDX_debug_str];
+ if (data == NULL || idx >= data->d_size
+ || memchr (data->d_buf + idx, '\0',
+ data->d_size - idx) == NULL)
+ str = "???";
+ else
+ str = (char *) data->d_buf + idx;
+ }
+ }
+ printf ("%s (%" PRIu64 ")", str, val);
+ break;
+
+ case DW_FORM_strx1:
+ if (readendp - readp < 1)
+ goto invalid_data;
+ val = *readp;
+ goto strx_val;
+
+ case DW_FORM_strx2:
+ if (readendp - readp < 2)
+ goto invalid_data;
+ val = read_2ubyte_unaligned (dbg, readp);
+ goto strx_val;
+
+ case DW_FORM_strx3:
+ if (readendp - readp < 3)
+ goto invalid_data;
+ val = read_3ubyte_unaligned (dbg, readp);
+ goto strx_val;
+
+ case DW_FORM_strx4:
+ if (readendp - readp < 4)
+ goto invalid_data;
+ val = read_4ubyte_unaligned (dbg, readp);
+ goto strx_val;
+
+ default:
+ error (0, 0, gettext ("unknown form: %s"), dwarf_form_name (form));
+ return readendp;
+ }
+
+ return readp;
+}
+
static void
print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
@@ -6806,35 +7063,67 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
}
/* Check whether we have enough room in the section. */
- if (unlikely (unit_length > (size_t) (lineendp - linep)
- || unit_length < 2 + length + 5 * 1))
+ if (unlikely (unit_length > (size_t) (lineendp - linep)))
goto invalid_data;
lineendp = linep + unit_length;
/* The next element of the header is the version identifier. */
+ if ((size_t) (lineendp - linep) < 2)
+ goto invalid_data;
uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
+ size_t address_size
+ = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+ unsigned char segment_selector_size = 0;
+ if (version > 4)
+ {
+ if ((size_t) (lineendp - linep) < 2)
+ goto invalid_data;
+ address_size = *linep++;
+ segment_selector_size = *linep++;
+ }
+
/* Next comes the header length. */
Dwarf_Word header_length;
if (length == 4)
- header_length = read_4ubyte_unaligned_inc (dbg, linep);
+ {
+ if ((size_t) (lineendp - linep) < 4)
+ goto invalid_data;
+ header_length = read_4ubyte_unaligned_inc (dbg, linep);
+ }
else
- header_length = read_8ubyte_unaligned_inc (dbg, linep);
- //const unsigned char *header_start = linep;
+ {
+ if ((size_t) (lineendp - linep) < 8)
+ goto invalid_data;
+ header_length = read_8ubyte_unaligned_inc (dbg, linep);
+ }
/* Next the minimum instruction length. */
+ if ((size_t) (lineendp - linep) < 1)
+ goto invalid_data;
uint_fast8_t minimum_instr_len = *linep++;
/* Next the maximum operations per instruction, in version 4 format. */
- uint_fast8_t max_ops_per_instr = version < 4 ? 1 : *linep++;
+ uint_fast8_t max_ops_per_instr;
+ if (version < 4)
+ max_ops_per_instr = 1;
+ else
+ {
+ if ((size_t) (lineendp - linep) < 1)
+ goto invalid_data;
+ max_ops_per_instr = *linep++;
+ }
+
+ /* We need at least 4 more bytes. */
+ if ((size_t) (lineendp - linep) < 4)
+ goto invalid_data;
- /* Then the flag determining the default value of the is_stmt
- register. */
+ /* Then the flag determining the default value of the is_stmt
+ register. */
uint_fast8_t default_is_stmt = *linep++;
/* Now the line base. */
- int_fast8_t line_base = *((const int_fast8_t *) linep);
- ++linep;
+ int_fast8_t line_base = *linep++;
/* And the line range. */
uint_fast8_t line_range = *linep++;
@@ -6844,22 +7133,49 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
/* Print what we got so far. */
printf (gettext ("\n"
- " Length: %" PRIu64 "\n"
- " DWARF version: %" PRIuFAST16 "\n"
- " Prologue length: %" PRIu64 "\n"
- " Minimum instruction length: %" PRIuFAST8 "\n"
- " Maximum operations per instruction: %" PRIuFAST8 "\n"
- " Initial value if '%s': %" PRIuFAST8 "\n"
- " Line base: %" PRIdFAST8 "\n"
- " Line range: %" PRIuFAST8 "\n"
- " Opcode base: %" PRIuFAST8 "\n"
+ " Length: %" PRIu64 "\n"
+ " DWARF version: %" PRIuFAST16 "\n"
+ " Prologue length: %" PRIu64 "\n"
+ " Address size: %zd\n"
+ " Segment selector size: %zd\n"
+ " Min instruction length: %" PRIuFAST8 "\n"
+ " Max operations per instruction: %" PRIuFAST8 "\n"
+ " Initial value if 'is_stmt': %" PRIuFAST8 "\n"
+ " Line base: %" PRIdFAST8 "\n"
+ " Line range: %" PRIuFAST8 "\n"
+ " Opcode base: %" PRIuFAST8 "\n"
"\n"
"Opcodes:\n"),
(uint64_t) unit_length, version, (uint64_t) header_length,
+ address_size, (size_t) segment_selector_size,
minimum_instr_len, max_ops_per_instr,
- "is_stmt", default_is_stmt, line_base,
+ default_is_stmt, line_base,
line_range, opcode_base);
+ if (version < 2 || version > 5)
+ {
+ error (0, 0, gettext ("cannot handle .debug_line version: %u\n"),
+ (unsigned int) version);
+ linep = lineendp;
+ continue;
+ }
+
+ if (address_size != 4 && address_size != 8)
+ {
+ error (0, 0, gettext ("cannot handle address size: %u\n"),
+ (unsigned int) address_size);
+ linep = lineendp;
+ continue;
+ }
+
+ if (segment_selector_size != 0)
+ {
+ error (0, 0, gettext ("cannot handle segment selector size: %u\n"),
+ (unsigned int) segment_selector_size);
+ linep = lineendp;
+ continue;
+ }
+
if (unlikely (linep + opcode_base - 1 >= lineendp))
{
invalid_unit:
@@ -6884,59 +7200,178 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
(int) linep[cnt - 1]),
opcode_base_l10, cnt, linep[cnt - 1]);
linep += opcode_base - 1;
+
if (unlikely (linep >= lineendp))
goto invalid_unit;
+ Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, NULL);
+
puts (gettext ("\nDirectory table:"));
- while (*linep != 0)
+ if (version > 4)
{
- unsigned char *endp = memchr (linep, '\0', lineendp - linep);
- if (unlikely (endp == NULL))
- goto invalid_unit;
+ struct encpair { uint16_t desc; uint16_t form; };
+ struct encpair enc[256];
+
+ printf (gettext (" ["));
+ if ((size_t) (lineendp - linep) < 1)
+ goto invalid_data;
+ unsigned char directory_entry_format_count = *linep++;
+ for (int i = 0; i < directory_entry_format_count; i++)
+ {
+ uint16_t desc, form;
+ if ((size_t) (lineendp - linep) < 1)
+ goto invalid_data;
+ get_uleb128 (desc, linep, lineendp);
+ if ((size_t) (lineendp - linep) < 1)
+ goto invalid_data;
+ get_uleb128 (form, linep, lineendp);
+
+ enc[i].desc = desc;
+ enc[i].form = form;
+
+ printf ("%s(%s)",
+ dwarf_line_content_description_name (desc),
+ dwarf_form_name (form));
+ if (i + 1 < directory_entry_format_count)
+ printf (", ");
+ }
+ printf ("]\n");
+
+ uint64_t directories_count;
+ if ((size_t) (lineendp - linep) < 1)
+ goto invalid_data;
+ get_uleb128 (directories_count, linep, lineendp);
- printf (" %s\n", (char *) linep);
+ if (directory_entry_format_count == 0
+ && directories_count != 0)
+ goto invalid_data;
+
+ for (uint64_t i = 0; i < directories_count; i++)
+ {
+ printf (" %-5lu ", i);
+ for (int j = 0; j < directory_entry_format_count; j++)
+ {
+ linep = print_form_data (dbg, enc[j].form,
+ linep, lineendp, length,
+ str_offsets_base);
+ if (j + 1 < directory_entry_format_count)
+ printf (", ");
+ }
+ printf ("\n");
+ }
+ }
+ else
+ {
+ while (*linep != 0)
+ {
+ unsigned char *endp = memchr (linep, '\0', lineendp - linep);
+ if (unlikely (endp == NULL))
+ goto invalid_unit;
- linep = endp + 1;
+ printf (" %s\n", (char *) linep);
+
+ linep = endp + 1;
+ }
+ /* Skip the final NUL byte. */
+ ++linep;
}
- /* Skip the final NUL byte. */
- ++linep;
if (unlikely (linep >= lineendp))
goto invalid_unit;
- puts (gettext ("\nFile name table:\n"
- " Entry Dir Time Size Name"));
- for (unsigned int cnt = 1; *linep != 0; ++cnt)
+
+ puts (gettext ("\nFile name table:"));
+ if (version > 4)
{
- /* First comes the file name. */
- char *fname = (char *) linep;
- unsigned char *endp = memchr (fname, '\0', lineendp - linep);
- if (unlikely (endp == NULL))
- goto invalid_unit;
- linep = endp + 1;
+ struct encpair { uint16_t desc; uint16_t form; };
+ struct encpair enc[256];
- /* Then the index. */
- unsigned int diridx;
- if (lineendp - linep < 1)
- goto invalid_unit;
- get_uleb128 (diridx, linep, lineendp);
+ printf (gettext (" ["));
+ if ((size_t) (lineendp - linep) < 1)
+ goto invalid_data;
+ unsigned char file_name_format_count = *linep++;
+ for (int i = 0; i < file_name_format_count; i++)
+ {
+ uint64_t desc, form;
+ if ((size_t) (lineendp - linep) < 1)
+ goto invalid_data;
+ get_uleb128 (desc, linep, lineendp);
+ if ((size_t) (lineendp - linep) < 1)
+ goto invalid_data;
+ get_uleb128 (form, linep, lineendp);
- /* Next comes the modification time. */
- unsigned int mtime;
- if (lineendp - linep < 1)
- goto invalid_unit;
- get_uleb128 (mtime, linep, lineendp);
+ if (! libdw_valid_user_form (form))
+ goto invalid_data;
- /* Finally the length of the file. */
- unsigned int fsize;
- if (lineendp - linep < 1)
- goto invalid_unit;
- get_uleb128 (fsize, linep, lineendp);
+ enc[i].desc = desc;
+ enc[i].form = form;
- printf (" %-5u %-5u %-9u %-9u %s\n",
- cnt, diridx, mtime, fsize, fname);
+ printf ("%s(%s)",
+ dwarf_line_content_description_name (desc),
+ dwarf_form_name (form));
+ if (i + 1 < file_name_format_count)
+ printf (", ");
+ }
+ printf ("]\n");
+
+ uint64_t file_name_count;
+ if ((size_t) (lineendp - linep) < 1)
+ goto invalid_data;
+ get_uleb128 (file_name_count, linep, lineendp);
+
+ if (file_name_format_count == 0
+ && file_name_count != 0)
+ goto invalid_data;
+
+ for (uint64_t i = 0; i < file_name_count; i++)
+ {
+ printf (" %-5lu ", i);
+ for (int j = 0; j < file_name_format_count; j++)
+ {
+ linep = print_form_data (dbg, enc[j].form,
+ linep, lineendp, length,
+ str_offsets_base);
+ if (j + 1 < file_name_format_count)
+ printf (", ");
+ }
+ printf ("\n");
+ }
+ }
+ else
+ {
+ puts (gettext (" Entry Dir Time Size Name"));
+ for (unsigned int cnt = 1; *linep != 0; ++cnt)
+ {
+ /* First comes the file name. */
+ char *fname = (char *) linep;
+ unsigned char *endp = memchr (fname, '\0', lineendp - linep);
+ if (unlikely (endp == NULL))
+ goto invalid_unit;
+ linep = endp + 1;
+
+ /* Then the index. */
+ unsigned int diridx;
+ if (lineendp - linep < 1)
+ goto invalid_unit;
+ get_uleb128 (diridx, linep, lineendp);
+
+ /* Next comes the modification time. */
+ unsigned int mtime;
+ if (lineendp - linep < 1)
+ goto invalid_unit;
+ get_uleb128 (mtime, linep, lineendp);
+
+ /* Finally the length of the file. */
+ unsigned int fsize;
+ if (lineendp - linep < 1)
+ goto invalid_unit;
+ get_uleb128 (fsize, linep, lineendp);
+
+ printf (" %-5u %-5u %-9u %-9u %s\n",
+ cnt, diridx, mtime, fsize, fname);
+ }
+ /* Skip the final NUL byte. */
+ ++linep;
}
- /* Skip the final NUL byte. */
- ++linep;
puts (gettext ("\nLine number statements:"));
Dwarf_Word address = 0;
@@ -6944,10 +7379,6 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
size_t line = 1;
uint_fast8_t is_stmt = default_is_stmt;
- /* Default address value, in case we do not find the CU. */
- size_t address_size
- = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
-
/* Determine the CU this block is for. */
Dwarf_Off cuoffset;
Dwarf_Off ncuoffset = 0;
@@ -7727,6 +8158,18 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
line_offset);
}
+ struct mac_culist *cu = NULL;
+ if (line_offset != (Dwarf_Off) -1)
+ {
+ cu = culist;
+ while (cu != NULL && line_offset != cu->offset)
+ cu = cu->next;
+ }
+
+ Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, (cu != NULL
+ ? cu->die.cu
+ : NULL));
+
const unsigned char *vendor[DW_MACRO_hi_user - DW_MACRO_lo_user];
memset (vendor, 0, sizeof vendor);
if (flag & 0x04)
@@ -7810,22 +8253,16 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
/* Find the CU DIE that matches this line offset. */
const char *fname = "???";
- if (line_offset != (Dwarf_Off) -1)
+ if (cu != NULL)
{
- struct mac_culist *cu = culist;
- while (cu != NULL && line_offset != cu->offset)
- cu = cu->next;
- if (cu != NULL)
- {
- if (cu->files == NULL
- && dwarf_getsrcfiles (&cu->die, &cu->files,
- NULL) != 0)
- cu->files = (Dwarf_Files *) -1l;
-
- if (cu->files != (Dwarf_Files *) -1l)
- fname = (dwarf_filesrc (cu->files, u128_2,
- NULL, NULL) ?: "???");
- }
+ if (cu->files == NULL
+ && dwarf_getsrcfiles (&cu->die, &cu->files,
+ NULL) != 0)
+ cu->files = (Dwarf_Files *) -1l;
+
+ if (cu->files != (Dwarf_Files *) -1l)
+ fname = (dwarf_filesrc (cu->files, u128_2,
+ NULL, NULL) ?: "???");
}
printf ("%*sstart_file %u, [%u] %s\n",
level, "", u128, u128_2, fname);
@@ -7971,125 +8408,11 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
while (args > 0)
{
unsigned int form = *op_desc++;
- Dwarf_Word val;
- switch (form)
- {
- case DW_FORM_data1:
- if (readp + 1 > readendp)
- goto invalid_data;
- val = *readp++;
- printf (" %" PRIx8, (unsigned int) val);
- break;
-
- case DW_FORM_data2:
- if (readp + 2 > readendp)
- goto invalid_data;
- val = read_2ubyte_unaligned_inc (dbg, readp);
- printf(" %" PRIx16, (unsigned int) val);
- break;
-
- case DW_FORM_data4:
- if (readp + 4 > readendp)
- goto invalid_data;
- val = read_4ubyte_unaligned_inc (dbg, readp);
- printf (" %" PRIx32, (unsigned int) val);
- break;
-
- case DW_FORM_data8:
- if (readp + 8 > readendp)
- goto invalid_data;
- val = read_8ubyte_unaligned_inc (dbg, readp);
- printf (" %" PRIx64, val);
- break;
-
- case DW_FORM_sdata:
- get_sleb128 (val, readp, readendp);
- printf (" %" PRIx64, val);
- break;
-
- case DW_FORM_udata:
- get_uleb128 (val, readp, readendp);
- printf (" %" PRIx64, val);
- break;
-
- case DW_FORM_block:
- get_uleb128 (val, readp, readendp);
- printf (" block[%" PRIu64 "]", val);
- if (readp + val > readendp)
- goto invalid_data;
- readp += val;
- break;
-
- case DW_FORM_block1:
- if (readp + 1 > readendp)
- goto invalid_data;
- val = *readp++;
- printf (" block[%" PRIu64 "]", val);
- if (readp + val > readendp)
- goto invalid_data;
- break;
-
- case DW_FORM_block2:
- if (readp + 2 > readendp)
- goto invalid_data;
- val = read_2ubyte_unaligned_inc (dbg, readp);
- printf (" block[%" PRIu64 "]", val);
- if (readp + val > readendp)
- goto invalid_data;
- break;
-
- case DW_FORM_block4:
- if (readp + 2 > readendp)
- goto invalid_data;
- val =read_4ubyte_unaligned_inc (dbg, readp);
- printf (" block[%" PRIu64 "]", val);
- if (readp + val > readendp)
- goto invalid_data;
- break;
-
- case DW_FORM_flag:
- if (readp + 1 > readendp)
- goto invalid_data;
- val = *readp++;
- printf (" %s", val != 0 ? gettext ("yes") : gettext ("no"));
- break;
-
- case DW_FORM_string:
- endp = memchr (readp, '\0', readendp - readp);
- if (endp == NULL)
- goto invalid_data;
- printf (" %s", readp);
- readp = endp + 1;
- break;
-
- case DW_FORM_strp:
- if (readp + offset_len > readendp)
- goto invalid_data;
- if (offset_len == 8)
- val = read_8ubyte_unaligned_inc (dbg, readp);
- else
- val = read_4ubyte_unaligned_inc (dbg, readp);
- printf (" %s", dwarf_getstring (dbg, val, NULL));
- break;
-
- case DW_FORM_sec_offset:
- if (readp + offset_len > readendp)
- goto invalid_data;
- if (offset_len == 8)
- val = read_8ubyte_unaligned_inc (dbg, readp);
- else
- val = read_4ubyte_unaligned_inc (dbg, readp);
- printf (" %" PRIx64, val);
- break;
-
- default:
- error (0, 0, gettext ("vendor opcode not verified?"));
- return;
- }
-
+ print_form_data (dbg, form, readp, readendp, offset_len,
+ str_offsets_base);
args--;
if (args > 0)
- putchar_unlocked (',');
+ printf (", ");
}
putchar_unlocked ('\n');
}
diff --git a/tests/ChangeLog b/tests/ChangeLog
index b236ee79..16011c80 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,9 @@
+2018-05-09 Mark Wielaard <mark@klomp.org>
+
+ * run-readelf-zdebug.sh: Adjust test output for new header layout.
+ * run-readelf-line.sh: Likewise. Add new tests for testfile-dwarf-4
+ and testfile-dwarf-5.
+
2018-05-11 Mark Wielaard <mark@klomp.org>
* Makefile.am (check_PROGRAMS): Add get-units-invalid.
diff --git a/tests/run-readelf-line.sh b/tests/run-readelf-line.sh
index b08752ee..a95e6aa9 100755
--- a/tests/run-readelf-line.sh
+++ b/tests/run-readelf-line.sh
@@ -1,5 +1,5 @@
#! /bin/sh
-# Copyright (C) 2013 Red Hat, Inc.
+# Copyright (C) 2013, 2018 Red Hat, Inc.
# This file is part of elfutils.
#
# This file is free software; you can redistribute it and/or modify
@@ -28,15 +28,17 @@ DWARF section [30] '.debug_line' at offset 0x15f6:
Table at offset 0:
- Length: 83
- DWARF version: 2
- Prologue length: 43
- Minimum instruction length: 1
- Maximum operations per instruction: 1
- Initial value if 'is_stmt': 1
- Line base: -5
- Line range: 14
- Opcode base: 13
+ Length: 83
+ DWARF version: 2
+ Prologue length: 43
+ Address size: 4
+ Segment selector size: 0
+ Min instruction length: 1
+ Max operations per instruction: 1
+ Initial value if 'is_stmt': 1
+ Line base: -5
+ Line range: 14
+ Opcode base: 13
Opcodes:
[ 1] 0 arguments
@@ -83,15 +85,17 @@ Line number statements:
Table at offset 87:
- Length: 72
- DWARF version: 2
- Prologue length: 28
- Minimum instruction length: 1
- Maximum operations per instruction: 1
- Initial value if 'is_stmt': 1
- Line base: -5
- Line range: 14
- Opcode base: 13
+ Length: 72
+ DWARF version: 2
+ Prologue length: 28
+ Address size: 4
+ Segment selector size: 0
+ Min instruction length: 1
+ Max operations per instruction: 1
+ Initial value if 'is_stmt': 1
+ Line base: -5
+ Line range: 14
+ Opcode base: 13
Opcodes:
[ 1] 0 arguments
@@ -133,15 +137,17 @@ Line number statements:
Table at offset 163:
- Length: 106
- DWARF version: 2
- Prologue length: 43
- Minimum instruction length: 1
- Maximum operations per instruction: 1
- Initial value if 'is_stmt': 1
- Line base: -5
- Line range: 14
- Opcode base: 13
+ Length: 106
+ DWARF version: 2
+ Prologue length: 43
+ Address size: 4
+ Segment selector size: 0
+ Min instruction length: 1
+ Max operations per instruction: 1
+ Initial value if 'is_stmt': 1
+ Line base: -5
+ Line range: 14
+ Opcode base: 13
Opcodes:
[ 1] 0 arguments
@@ -280,15 +286,17 @@ DWARF section [29] '.debug_line' at offset 0xdf6:
Table at offset 0:
- Length: 69
- DWARF version: 2
- Prologue length: 30
- Minimum instruction length: 4
- Maximum operations per instruction: 1
- Initial value if 'is_stmt': 1
- Line base: -5
- Line range: 14
- Opcode base: 13
+ Length: 69
+ DWARF version: 2
+ Prologue length: 30
+ Address size: 8
+ Segment selector size: 0
+ Min instruction length: 4
+ Max operations per instruction: 1
+ Initial value if 'is_stmt': 1
+ Line base: -5
+ Line range: 14
+ Opcode base: 13
Opcodes:
[ 1] 0 arguments
@@ -508,4 +516,634 @@ DWARF section [29] '.debug_line' at offset 0x171f:
EOF
+# After discarding the different offsets in the line number statements,
+# the remaining difference between 4 and 5 is (besides the header/length)
+# Just the representation of the directory and line tables:
+
+# Directory table:
+# - /opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include
+# + [path(line_strp)]
+# + 0 /var/tmp/hello (90)
+# + 1 /opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include (17)
+#
+# File name table:
+# - Entry Dir Time Size Name
+# - 1 0 0 0 hello.c
+# - 2 0 0 0 hello.h
+# - 3 1 0 0 stddef.h
+# + [path(line_strp), directory_index(data1)]
+# + 0 hello.c (9), 0
+# + 1 hello.c (9), 0
+# + 2 hello.h (82), 0
+# + 3 stddef.h (0), 1
+#
+# Directory table:
+# - /usr/include
+# + [path(line_strp)]
+# + 0 /var/tmp/hello (90)
+# + 1 /usr/include (122)
+#
+# File name table:
+# - Entry Dir Time Size Name
+# - 1 0 0 0 world.c
+# - 2 0 0 0 hello.h
+# - 3 1 0 0 stdlib.h
+# + [path(line_strp), directory_index(data1)]
+# + 0 world.c (114), 0
+# + 1 world.c (114), 0
+# + 2 hello.h (82), 0
+# + 3 stdlib.h (105), 1
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=line testfile-dwarf-4 << \EOF
+
+DWARF section [29] '.debug_line' at offset 0x1734:
+
+Table at offset 0:
+
+ Length: 608
+ DWARF version: 4
+ Prologue length: 119
+ Address size: 8
+ Segment selector size: 0
+ Min instruction length: 1
+ Max operations per instruction: 1
+ Initial value if 'is_stmt': 1
+ Line base: -10
+ Line range: 242
+ Opcode base: 13
+
+Opcodes:
+ [ 1] 0 arguments
+ [ 2] 1 argument
+ [ 3] 1 argument
+ [ 4] 1 argument
+ [ 5] 1 argument
+ [ 6] 0 arguments
+ [ 7] 0 arguments
+ [ 8] 0 arguments
+ [ 9] 1 argument
+ [10] 0 arguments
+ [11] 0 arguments
+ [12] 1 argument
+
+Directory table:
+ /opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include
+
+File name table:
+ Entry Dir Time Size Name
+ 1 0 0 0 hello.c
+ 2 0 0 0 hello.h
+ 3 1 0 0 stddef.h
+
+Line number statements:
+ [ 81] extended opcode 2: set address to 0x400510 <foo>
+ [ 8c] special opcode 43: address+0 = 0x400510 <foo>, line+20 = 21
+ [ 8d] set column to 1
+ [ 8f] extended opcode 2: set address to 0x400510 <foo>
+ [ 9a] special opcode 24: address+0 = 0x400510 <foo>, line+1 = 22
+ [ 9b] set column to 3
+ [ 9d] extended opcode 2: set address to 0x400510 <foo>
+ [ a8] set 'is_stmt' to 0
+ [ a9] copy
+ [ aa] set column to 6
+ [ ac] extended opcode 2: set address to 0x400514 <foo+0x4>
+ [ b7] special opcode 26: address+0 = 0x400514 <foo+0x4>, line+3 = 25
+ [ b8] set column to 34
+ [ ba] extended opcode 2: set address to 0x40051a <foo+0xa>
+ [ c5] set 'is_stmt' to 1
+ [ c6] copy
+ [ c7] set column to 3
+ [ c9] extended opcode 2: set address to 0x40051a <foo+0xa>
+ [ d4] set 'is_stmt' to 0
+ [ d5] copy
+ [ d6] set column to 34
+ [ d8] extended opcode 2: set address to 0x40051e <foo+0xe>
+ [ e3] special opcode 24: address+0 = 0x40051e <foo+0xe>, line+1 = 26
+ [ e4] set column to 1
+ [ e6] extended opcode 2: set address to 0x400528 <foo+0x18>
+ [ f1] extended opcode 4: set discriminator to 1
+ [ f5] special opcode 22: address+0 = 0x400528 <foo+0x18>, line-1 = 25
+ [ f6] set column to 18
+ [ f8] extended opcode 2: set address to 0x40052b <foo+0x1b>
+ [ 103] set file to 2
+ [ 105] set 'is_stmt' to 1
+ [ 106] advance line by constant -18 to 7
+ [ 108] copy
+ [ 109] set column to 3
+ [ 10b] extended opcode 2: set address to 0x40052b <foo+0x1b>
+ [ 116] special opcode 25: address+0 = 0x40052b <foo+0x1b>, line+2 = 9
+ [ 117] set column to 3
+ [ 119] extended opcode 2: set address to 0x40052b <foo+0x1b>
+ [ 124] set 'is_stmt' to 0
+ [ 125] copy
+ [ 126] set column to 6
+ [ 128] extended opcode 2: set address to 0x40052f <foo+0x1f>
+ [ 133] extended opcode 4: set discriminator to 0
+ [ 137] set 'is_stmt' to 1
+ [ 138] special opcode 24: address+0 = 0x40052f <foo+0x1f>, line+1 = 10
+ [ 139] set column to 5
+ [ 13b] extended opcode 2: set address to 0x40052f <foo+0x1f>
+ [ 146] set 'is_stmt' to 0
+ [ 147] copy
+ [ 148] set column to 7
+ [ 14a] extended opcode 2: set address to 0x400531 <foo+0x21>
+ [ 155] set 'is_stmt' to 1
+ [ 156] special opcode 25: address+0 = 0x400531 <foo+0x21>, line+2 = 12
+ [ 157] set column to 3
+ [ 159] extended opcode 2: set address to 0x400531 <foo+0x21>
+ [ 164] set file to 1
+ [ 166] special opcode 21: address+0 = 0x400531 <foo+0x21>, line-2 = 10
+ [ 167] set column to 3
+ [ 169] extended opcode 2: set address to 0x400531 <foo+0x21>
+ [ 174] special opcode 25: address+0 = 0x400531 <foo+0x21>, line+2 = 12
+ [ 175] set column to 3
+ [ 177] extended opcode 2: set address to 0x400531 <foo+0x21>
+ [ 182] set 'is_stmt' to 0
+ [ 183] copy
+ [ 184] set column to 6
+ [ 186] extended opcode 2: set address to 0x400535 <foo+0x25>
+ [ 191] set 'is_stmt' to 1
+ [ 192] special opcode 24: address+0 = 0x400535 <foo+0x25>, line+1 = 13
+ [ 193] set column to 5
+ [ 195] extended opcode 2: set address to 0x400535 <foo+0x25>
+ [ 1a0] set 'is_stmt' to 0
+ [ 1a1] copy
+ [ 1a2] set column to 7
+ [ 1a4] extended opcode 2: set address to 0x400539 <foo+0x29>
+ [ 1af] set 'is_stmt' to 1
+ [ 1b0] special opcode 25: address+0 = 0x400539 <foo+0x29>, line+2 = 15
+ [ 1b1] set column to 3
+ [ 1b3] extended opcode 2: set address to 0x400539 <foo+0x29>
+ [ 1be] special opcode 30: address+0 = 0x400539 <foo+0x29>, line+7 = 22
+ [ 1bf] set column to 3
+ [ 1c1] extended opcode 2: set address to 0x400539 <foo+0x29>
+ [ 1cc] set 'is_stmt' to 0
+ [ 1cd] copy
+ [ 1ce] set column to 6
+ [ 1d0] extended opcode 2: set address to 0x40053d <foo+0x2d>
+ [ 1db] set 'is_stmt' to 1
+ [ 1dc] special opcode 24: address+0 = 0x40053d <foo+0x2d>, line+1 = 23
+ [ 1dd] set column to 5
+ [ 1df] extended opcode 2: set address to 0x40053d <foo+0x2d>
+ [ 1ea] set 'is_stmt' to 0
+ [ 1eb] copy
+ [ 1ec] set column to 12
+ [ 1ee] extended opcode 2: set address to 0x400550 <baz>
+ [ 1f9] set 'is_stmt' to 1
+ [ 1fa] advance line by constant -14 to 9
+ [ 1fc] copy
+ [ 1fd] set column to 1
+ [ 1ff] extended opcode 2: set address to 0x400550 <baz>
+ [ 20a] special opcode 24: address+0 = 0x400550 <baz>, line+1 = 10
+ [ 20b] set column to 3
+ [ 20d] extended opcode 2: set address to 0x400550 <baz>
+ [ 218] special opcode 25: address+0 = 0x400550 <baz>, line+2 = 12
+ [ 219] set column to 3
+ [ 21b] extended opcode 2: set address to 0x400550 <baz>
+ [ 226] set 'is_stmt' to 0
+ [ 227] copy
+ [ 228] set column to 9
+ [ 22a] extended opcode 2: set address to 0x400556 <baz+0x6>
+ [ 235] special opcode 24: address+0 = 0x400556 <baz+0x6>, line+1 = 13
+ [ 236] set column to 7
+ [ 238] extended opcode 2: set address to 0x40055f <baz+0xf>
+ [ 243] set 'is_stmt' to 1
+ [ 244] special opcode 25: address+0 = 0x40055f <baz+0xf>, line+2 = 15
+ [ 245] set column to 3
+ [ 247] extended opcode 2: set address to 0x40055f <baz+0xf>
+ [ 252] set 'is_stmt' to 0
+ [ 253] copy
+ [ 254] set column to 7
+ [ 256] extended opcode 2: set address to 0x400561
+ [ 261] extended opcode 1: end of sequence
+
+Table at offset 612:
+
+ Length: 450
+ DWARF version: 4
+ Prologue length: 67
+ Address size: 8
+ Segment selector size: 0
+ Min instruction length: 1
+ Max operations per instruction: 1
+ Initial value if 'is_stmt': 1
+ Line base: -10
+ Line range: 242
+ Opcode base: 13
+
+Opcodes:
+ [ 1] 0 arguments
+ [ 2] 1 argument
+ [ 3] 1 argument
+ [ 4] 1 argument
+ [ 5] 1 argument
+ [ 6] 0 arguments
+ [ 7] 0 arguments
+ [ 8] 0 arguments
+ [ 9] 1 argument
+ [10] 0 arguments
+ [11] 0 arguments
+ [12] 1 argument
+
+Directory table:
+ /usr/include
+
+File name table:
+ Entry Dir Time Size Name
+ 1 0 0 0 world.c
+ 2 0 0 0 hello.h
+ 3 1 0 0 stdlib.h
+
+Line number statements:
+ [ 2b1] extended opcode 2: set address to 0x400410 <main>
+ [ 2bc] special opcode 37: address+0 = 0x400410 <main>, line+14 = 15
+ [ 2bd] set column to 1
+ [ 2bf] extended opcode 2: set address to 0x400410 <main>
+ [ 2ca] special opcode 24: address+0 = 0x400410 <main>, line+1 = 16
+ [ 2cb] set column to 3
+ [ 2cd] extended opcode 2: set address to 0x400410 <main>
+ [ 2d8] special opcode 24: address+0 = 0x400410 <main>, line+1 = 17
+ [ 2d9] set column to 3
+ [ 2db] extended opcode 2: set address to 0x400410 <main>
+ [ 2e6] set 'is_stmt' to 0
+ [ 2e7] special opcode 21: address+0 = 0x400410 <main>, line-2 = 15
+ [ 2e8] set column to 1
+ [ 2ea] extended opcode 2: set address to 0x400419 <main+0x9>
+ [ 2f5] special opcode 25: address+0 = 0x400419 <main+0x9>, line+2 = 17
+ [ 2f6] set column to 6
+ [ 2f8] extended opcode 2: set address to 0x40041e <main+0xe>
+ [ 303] set 'is_stmt' to 1
+ [ 304] special opcode 24: address+0 = 0x40041e <main+0xe>, line+1 = 18
+ [ 305] set column to 5
+ [ 307] extended opcode 2: set address to 0x40041e <main+0xe>
+ [ 312] set 'is_stmt' to 0
+ [ 313] copy
+ [ 314] set column to 7
+ [ 316] extended opcode 2: set address to 0x400421 <main+0x11>
+ [ 321] set 'is_stmt' to 1
+ [ 322] special opcode 27: address+0 = 0x400421 <main+0x11>, line+4 = 22
+ [ 323] set column to 3
+ [ 325] extended opcode 2: set address to 0x400430 <_start>
+ [ 330] extended opcode 1: end of sequence
+ [ 333] extended opcode 2: set address to 0x400570 <calc>
+ [ 33e] special opcode 28: address+0 = 0x400570 <calc>, line+5 = 6
+ [ 33f] set column to 1
+ [ 341] extended opcode 2: set address to 0x400570 <calc>
+ [ 34c] special opcode 24: address+0 = 0x400570 <calc>, line+1 = 7
+ [ 34d] set column to 3
+ [ 34f] extended opcode 2: set address to 0x400570 <calc>
+ [ 35a] set 'is_stmt' to 0
+ [ 35b] copy
+ [ 35c] set column to 6
+ [ 35e] extended opcode 2: set address to 0x400575 <calc+0x5>
+ [ 369] extended opcode 4: set discriminator to 1
+ [ 36d] copy
+ [ 36e] set column to 24
+ [ 370] extended opcode 2: set address to 0x400578 <calc+0x8>
+ [ 37b] copy
+ [ 37c] set column to 17
+ [ 37e] extended opcode 2: set address to 0x40057d <calc+0xd>
+ [ 389] extended opcode 4: set discriminator to 0
+ [ 38d] set 'is_stmt' to 1
+ [ 38e] special opcode 26: address+0 = 0x40057d <calc+0xd>, line+3 = 10
+ [ 38f] set column to 3
+ [ 391] extended opcode 2: set address to 0x40057d <calc+0xd>
+ [ 39c] set 'is_stmt' to 0
+ [ 39d] copy
+ [ 39e] set column to 10
+ [ 3a0] extended opcode 2: set address to 0x400583 <calc+0x13>
+ [ 3ab] set file to 2
+ [ 3ad] copy
+ [ 3ae] set column to 7
+ [ 3b0] extended opcode 2: set address to 0x400585 <calc+0x15>
+ [ 3bb] set file to 1
+ [ 3bd] copy
+ [ 3be] set column to 10
+ [ 3c0] extended opcode 2: set address to 0x400588 <calc+0x18>
+ [ 3cb] set file to 2
+ [ 3cd] set 'is_stmt' to 1
+ [ 3ce] special opcode 20: address+0 = 0x400588 <calc+0x18>, line-3 = 7
+ [ 3cf] set column to 3
+ [ 3d1] extended opcode 2: set address to 0x400588 <calc+0x18>
+ [ 3dc] special opcode 25: address+0 = 0x400588 <calc+0x18>, line+2 = 9
+ [ 3dd] set column to 3
+ [ 3df] extended opcode 2: set address to 0x400588 <calc+0x18>
+ [ 3ea] set 'is_stmt' to 0
+ [ 3eb] special opcode 24: address+0 = 0x400588 <calc+0x18>, line+1 = 10
+ [ 3ec] set column to 7
+ [ 3ee] extended opcode 2: set address to 0x40058f <calc+0x1f>
+ [ 3f9] set 'is_stmt' to 1
+ [ 3fa] special opcode 25: address+0 = 0x40058f <calc+0x1f>, line+2 = 12
+ [ 3fb] set column to 3
+ [ 3fd] extended opcode 2: set address to 0x40058f <calc+0x1f>
+ [ 408] set 'is_stmt' to 0
+ [ 409] copy
+ [ 40a] set column to 10
+ [ 40c] extended opcode 2: set address to 0x400598 <calc+0x28>
+ [ 417] set file to 1
+ [ 419] special opcode 22: address+0 = 0x400598 <calc+0x28>, line-1 = 11
+ [ 41a] set column to 1
+ [ 41c] extended opcode 2: set address to 0x40059b
+ [ 427] extended opcode 1: end of sequence
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=line testfile-dwarf-5 << \EOF
+
+DWARF section [29] '.debug_line' at offset 0x171f:
+
+Table at offset 0:
+
+ Length: 547
+ DWARF version: 5
+ Prologue length: 56
+ Address size: 8
+ Segment selector size: 0
+ Min instruction length: 1
+ Max operations per instruction: 1
+ Initial value if 'is_stmt': 1
+ Line base: -10
+ Line range: 242
+ Opcode base: 13
+
+Opcodes:
+ [ 1] 0 arguments
+ [ 2] 1 argument
+ [ 3] 1 argument
+ [ 4] 1 argument
+ [ 5] 1 argument
+ [ 6] 0 arguments
+ [ 7] 0 arguments
+ [ 8] 0 arguments
+ [ 9] 1 argument
+ [10] 0 arguments
+ [11] 0 arguments
+ [12] 1 argument
+
+Directory table:
+ [path(line_strp)]
+ 0 /var/tmp/hello (90)
+ 1 /opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include (17)
+
+File name table:
+ [path(line_strp), directory_index(data1)]
+ 0 hello.c (9), 0
+ 1 hello.c (9), 0
+ 2 hello.h (82), 0
+ 3 stddef.h (0), 1
+
+Line number statements:
+ [ 44] extended opcode 2: set address to 0x400510 <foo>
+ [ 4f] special opcode 43: address+0 = 0x400510 <foo>, line+20 = 21
+ [ 50] set column to 1
+ [ 52] extended opcode 2: set address to 0x400510 <foo>
+ [ 5d] special opcode 24: address+0 = 0x400510 <foo>, line+1 = 22
+ [ 5e] set column to 3
+ [ 60] extended opcode 2: set address to 0x400510 <foo>
+ [ 6b] set 'is_stmt' to 0
+ [ 6c] copy
+ [ 6d] set column to 6
+ [ 6f] extended opcode 2: set address to 0x400514 <foo+0x4>
+ [ 7a] special opcode 26: address+0 = 0x400514 <foo+0x4>, line+3 = 25
+ [ 7b] set column to 34
+ [ 7d] extended opcode 2: set address to 0x40051a <foo+0xa>
+ [ 88] set 'is_stmt' to 1
+ [ 89] copy
+ [ 8a] set column to 3
+ [ 8c] extended opcode 2: set address to 0x40051a <foo+0xa>
+ [ 97] set 'is_stmt' to 0
+ [ 98] copy
+ [ 99] set column to 34
+ [ 9b] extended opcode 2: set address to 0x40051e <foo+0xe>
+ [ a6] special opcode 24: address+0 = 0x40051e <foo+0xe>, line+1 = 26
+ [ a7] set column to 1
+ [ a9] extended opcode 2: set address to 0x400528 <foo+0x18>
+ [ b4] extended opcode 4: set discriminator to 1
+ [ b8] special opcode 22: address+0 = 0x400528 <foo+0x18>, line-1 = 25
+ [ b9] set column to 18
+ [ bb] extended opcode 2: set address to 0x40052b <foo+0x1b>
+ [ c6] set file to 2
+ [ c8] set 'is_stmt' to 1
+ [ c9] advance line by constant -18 to 7
+ [ cb] copy
+ [ cc] set column to 3
+ [ ce] extended opcode 2: set address to 0x40052b <foo+0x1b>
+ [ d9] special opcode 25: address+0 = 0x40052b <foo+0x1b>, line+2 = 9
+ [ da] set column to 3
+ [ dc] extended opcode 2: set address to 0x40052b <foo+0x1b>
+ [ e7] set 'is_stmt' to 0
+ [ e8] copy
+ [ e9] set column to 6
+ [ eb] extended opcode 2: set address to 0x40052f <foo+0x1f>
+ [ f6] extended opcode 4: set discriminator to 0
+ [ fa] set 'is_stmt' to 1
+ [ fb] special opcode 24: address+0 = 0x40052f <foo+0x1f>, line+1 = 10
+ [ fc] set column to 5
+ [ fe] extended opcode 2: set address to 0x40052f <foo+0x1f>
+ [ 109] set 'is_stmt' to 0
+ [ 10a] copy
+ [ 10b] set column to 7
+ [ 10d] extended opcode 2: set address to 0x400531 <foo+0x21>
+ [ 118] set 'is_stmt' to 1
+ [ 119] special opcode 25: address+0 = 0x400531 <foo+0x21>, line+2 = 12
+ [ 11a] set column to 3
+ [ 11c] extended opcode 2: set address to 0x400531 <foo+0x21>
+ [ 127] set file to 1
+ [ 129] special opcode 21: address+0 = 0x400531 <foo+0x21>, line-2 = 10
+ [ 12a] set column to 3
+ [ 12c] extended opcode 2: set address to 0x400531 <foo+0x21>
+ [ 137] special opcode 25: address+0 = 0x400531 <foo+0x21>, line+2 = 12
+ [ 138] set column to 3
+ [ 13a] extended opcode 2: set address to 0x400531 <foo+0x21>
+ [ 145] set 'is_stmt' to 0
+ [ 146] copy
+ [ 147] set column to 6
+ [ 149] extended opcode 2: set address to 0x400535 <foo+0x25>
+ [ 154] set 'is_stmt' to 1
+ [ 155] special opcode 24: address+0 = 0x400535 <foo+0x25>, line+1 = 13
+ [ 156] set column to 5
+ [ 158] extended opcode 2: set address to 0x400535 <foo+0x25>
+ [ 163] set 'is_stmt' to 0
+ [ 164] copy
+ [ 165] set column to 7
+ [ 167] extended opcode 2: set address to 0x400539 <foo+0x29>
+ [ 172] set 'is_stmt' to 1
+ [ 173] special opcode 25: address+0 = 0x400539 <foo+0x29>, line+2 = 15
+ [ 174] set column to 3
+ [ 176] extended opcode 2: set address to 0x400539 <foo+0x29>
+ [ 181] special opcode 30: address+0 = 0x400539 <foo+0x29>, line+7 = 22
+ [ 182] set column to 3
+ [ 184] extended opcode 2: set address to 0x400539 <foo+0x29>
+ [ 18f] set 'is_stmt' to 0
+ [ 190] copy
+ [ 191] set column to 6
+ [ 193] extended opcode 2: set address to 0x40053d <foo+0x2d>
+ [ 19e] set 'is_stmt' to 1
+ [ 19f] special opcode 24: address+0 = 0x40053d <foo+0x2d>, line+1 = 23
+ [ 1a0] set column to 5
+ [ 1a2] extended opcode 2: set address to 0x40053d <foo+0x2d>
+ [ 1ad] set 'is_stmt' to 0
+ [ 1ae] copy
+ [ 1af] set column to 12
+ [ 1b1] extended opcode 2: set address to 0x400550 <baz>
+ [ 1bc] set 'is_stmt' to 1
+ [ 1bd] advance line by constant -14 to 9
+ [ 1bf] copy
+ [ 1c0] set column to 1
+ [ 1c2] extended opcode 2: set address to 0x400550 <baz>
+ [ 1cd] special opcode 24: address+0 = 0x400550 <baz>, line+1 = 10
+ [ 1ce] set column to 3
+ [ 1d0] extended opcode 2: set address to 0x400550 <baz>
+ [ 1db] special opcode 25: address+0 = 0x400550 <baz>, line+2 = 12
+ [ 1dc] set column to 3
+ [ 1de] extended opcode 2: set address to 0x400550 <baz>
+ [ 1e9] set 'is_stmt' to 0
+ [ 1ea] copy
+ [ 1eb] set column to 9
+ [ 1ed] extended opcode 2: set address to 0x400556 <baz+0x6>
+ [ 1f8] special opcode 24: address+0 = 0x400556 <baz+0x6>, line+1 = 13
+ [ 1f9] set column to 7
+ [ 1fb] extended opcode 2: set address to 0x40055f <baz+0xf>
+ [ 206] set 'is_stmt' to 1
+ [ 207] special opcode 25: address+0 = 0x40055f <baz+0xf>, line+2 = 15
+ [ 208] set column to 3
+ [ 20a] extended opcode 2: set address to 0x40055f <baz+0xf>
+ [ 215] set 'is_stmt' to 0
+ [ 216] copy
+ [ 217] set column to 7
+ [ 219] extended opcode 2: set address to 0x400561
+ [ 224] extended opcode 1: end of sequence
+
+Table at offset 551:
+
+ Length: 441
+ DWARF version: 5
+ Prologue length: 56
+ Address size: 8
+ Segment selector size: 0
+ Min instruction length: 1
+ Max operations per instruction: 1
+ Initial value if 'is_stmt': 1
+ Line base: -10
+ Line range: 242
+ Opcode base: 13
+
+Opcodes:
+ [ 1] 0 arguments
+ [ 2] 1 argument
+ [ 3] 1 argument
+ [ 4] 1 argument
+ [ 5] 1 argument
+ [ 6] 0 arguments
+ [ 7] 0 arguments
+ [ 8] 0 arguments
+ [ 9] 1 argument
+ [10] 0 arguments
+ [11] 0 arguments
+ [12] 1 argument
+
+Directory table:
+ [path(line_strp)]
+ 0 /var/tmp/hello (90)
+ 1 /usr/include (122)
+
+File name table:
+ [path(line_strp), directory_index(data1)]
+ 0 world.c (114), 0
+ 1 world.c (114), 0
+ 2 hello.h (82), 0
+ 3 stdlib.h (105), 1
+
+Line number statements:
+ [ 26b] extended opcode 2: set address to 0x400410 <main>
+ [ 276] special opcode 37: address+0 = 0x400410 <main>, line+14 = 15
+ [ 277] set column to 1
+ [ 279] extended opcode 2: set address to 0x400410 <main>
+ [ 284] special opcode 24: address+0 = 0x400410 <main>, line+1 = 16
+ [ 285] set column to 3
+ [ 287] extended opcode 2: set address to 0x400410 <main>
+ [ 292] special opcode 24: address+0 = 0x400410 <main>, line+1 = 17
+ [ 293] set column to 3
+ [ 295] extended opcode 2: set address to 0x400410 <main>
+ [ 2a0] set 'is_stmt' to 0
+ [ 2a1] special opcode 21: address+0 = 0x400410 <main>, line-2 = 15
+ [ 2a2] set column to 1
+ [ 2a4] extended opcode 2: set address to 0x400419 <main+0x9>
+ [ 2af] special opcode 25: address+0 = 0x400419 <main+0x9>, line+2 = 17
+ [ 2b0] set column to 6
+ [ 2b2] extended opcode 2: set address to 0x40041e <main+0xe>
+ [ 2bd] set 'is_stmt' to 1
+ [ 2be] special opcode 24: address+0 = 0x40041e <main+0xe>, line+1 = 18
+ [ 2bf] set column to 5
+ [ 2c1] extended opcode 2: set address to 0x40041e <main+0xe>
+ [ 2cc] set 'is_stmt' to 0
+ [ 2cd] copy
+ [ 2ce] set column to 7
+ [ 2d0] extended opcode 2: set address to 0x400421 <main+0x11>
+ [ 2db] set 'is_stmt' to 1
+ [ 2dc] special opcode 27: address+0 = 0x400421 <main+0x11>, line+4 = 22
+ [ 2dd] set column to 3
+ [ 2df] extended opcode 2: set address to 0x400430 <_start>
+ [ 2ea] extended opcode 1: end of sequence
+ [ 2ed] extended opcode 2: set address to 0x400570 <calc>
+ [ 2f8] special opcode 28: address+0 = 0x400570 <calc>, line+5 = 6
+ [ 2f9] set column to 1
+ [ 2fb] extended opcode 2: set address to 0x400570 <calc>
+ [ 306] special opcode 24: address+0 = 0x400570 <calc>, line+1 = 7
+ [ 307] set column to 3
+ [ 309] extended opcode 2: set address to 0x400570 <calc>
+ [ 314] set 'is_stmt' to 0
+ [ 315] copy
+ [ 316] set column to 6
+ [ 318] extended opcode 2: set address to 0x400575 <calc+0x5>
+ [ 323] extended opcode 4: set discriminator to 1
+ [ 327] copy
+ [ 328] set column to 24
+ [ 32a] extended opcode 2: set address to 0x400578 <calc+0x8>
+ [ 335] copy
+ [ 336] set column to 17
+ [ 338] extended opcode 2: set address to 0x40057d <calc+0xd>
+ [ 343] extended opcode 4: set discriminator to 0
+ [ 347] set 'is_stmt' to 1
+ [ 348] special opcode 26: address+0 = 0x40057d <calc+0xd>, line+3 = 10
+ [ 349] set column to 3
+ [ 34b] extended opcode 2: set address to 0x40057d <calc+0xd>
+ [ 356] set 'is_stmt' to 0
+ [ 357] copy
+ [ 358] set column to 10
+ [ 35a] extended opcode 2: set address to 0x400583 <calc+0x13>
+ [ 365] set file to 2
+ [ 367] copy
+ [ 368] set column to 7
+ [ 36a] extended opcode 2: set address to 0x400585 <calc+0x15>
+ [ 375] set file to 1
+ [ 377] copy
+ [ 378] set column to 10
+ [ 37a] extended opcode 2: set address to 0x400588 <calc+0x18>
+ [ 385] set file to 2
+ [ 387] set 'is_stmt' to 1
+ [ 388] special opcode 20: address+0 = 0x400588 <calc+0x18>, line-3 = 7
+ [ 389] set column to 3
+ [ 38b] extended opcode 2: set address to 0x400588 <calc+0x18>
+ [ 396] special opcode 25: address+0 = 0x400588 <calc+0x18>, line+2 = 9
+ [ 397] set column to 3
+ [ 399] extended opcode 2: set address to 0x400588 <calc+0x18>
+ [ 3a4] set 'is_stmt' to 0
+ [ 3a5] special opcode 24: address+0 = 0x400588 <calc+0x18>, line+1 = 10
+ [ 3a6] set column to 7
+ [ 3a8] extended opcode 2: set address to 0x40058f <calc+0x1f>
+ [ 3b3] set 'is_stmt' to 1
+ [ 3b4] special opcode 25: address+0 = 0x40058f <calc+0x1f>, line+2 = 12
+ [ 3b5] set column to 3
+ [ 3b7] extended opcode 2: set address to 0x40058f <calc+0x1f>
+ [ 3c2] set 'is_stmt' to 0
+ [ 3c3] copy
+ [ 3c4] set column to 10
+ [ 3c6] extended opcode 2: set address to 0x400598 <calc+0x28>
+ [ 3d1] set file to 1
+ [ 3d3] special opcode 22: address+0 = 0x400598 <calc+0x28>, line-1 = 11
+ [ 3d4] set column to 1
+ [ 3d6] extended opcode 2: set address to 0x40059b
+ [ 3e1] extended opcode 1: end of sequence
+EOF
+
exit 0
diff --git a/tests/run-readelf-zdebug.sh b/tests/run-readelf-zdebug.sh
index 28128ad9..878e0ba8 100755
--- a/tests/run-readelf-zdebug.sh
+++ b/tests/run-readelf-zdebug.sh
@@ -361,15 +361,17 @@ DWARF section [34] '.debug_line' at offset 0x104c:
Table at offset 0:
- Length: 70
- DWARF version: 2
- Prologue length: 40
- Minimum instruction length: 1
- Maximum operations per instruction: 1
- Initial value if 'is_stmt': 1
- Line base: -5
- Line range: 14
- Opcode base: 13
+ Length: 70
+ DWARF version: 2
+ Prologue length: 40
+ Address size: 8
+ Segment selector size: 0
+ Min instruction length: 1
+ Max operations per instruction: 1
+ Initial value if 'is_stmt': 1
+ Line base: -5
+ Line range: 14
+ Opcode base: 13
Opcodes:
[ 1] 0 arguments