[v4] binutils/dwarf: Print embedded source, when available
Checks
| Context |
Check |
Description |
| linaro-tcwg-bot/tcwg_binutils_build--master-arm |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_binutils_check--master-arm |
fail
|
Test failed
|
| linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 |
fail
|
Test failed
|
Commit Message
Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
---
v4:
Fixed formatting
Fixed namesourcepass scoping
Updated comments
Greatly simplified/commented test case
v3: Fixed failing test on aarch64
v2:
Fixed variable scoping
Fixed name of line number header entry
Added test
binutils/dwarf.c | 33 ++++++--
.../binutils-all/dw5-embedded-source.S | 78 +++++++++++++++++++
.../binutils-all/dw5-embedded-source.d | 18 +++++
binutils/testsuite/binutils-all/objdump.exp | 2 +
include/dwarf2.h | 2 +
5 files changed, 128 insertions(+), 5 deletions(-)
create mode 100644 binutils/testsuite/binutils-all/dw5-embedded-source.S
create mode 100644 binutils/testsuite/binutils-all/dw5-embedded-source.d
Comments
On 08.05.2026 13:28, Will Hawkins wrote:
> Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
> ---
> v4:
> Fixed formatting
> Fixed namesourcepass scoping
> Updated comments
> Greatly simplified/commented test case
Much appreciated, as it's much more readable now. Just one other nit below,
apart from my previously voiced more general concern towards the two new
enumerators.
> @@ -5872,13 +5876,32 @@ display_formatted_table (unsigned char *data,
>
> READ_ULEB (content_type, format, end);
> READ_ULEB (form, format, end);
> - bool do_loc = (content_type == DW_LNCT_path) != (namepass == 1);
> +
> + bool do_loc = ((content_type == DW_LNCT_path)
> + != (namesourcepass == 1))
> + | ((content_type == DW_LNCT_LLVM_source
While functionally correct, preferably || in something dealing with any
yielding boolean. (Likely can be adjusted by whoever ends up committing
this, assuming there'll be someone to approve it despite my concern.)
Jan
On Fri, May 15, 2026 at 7:52 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 08.05.2026 13:28, Will Hawkins wrote:
> > Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
> > ---
> > v4:
> > Fixed formatting
> > Fixed namesourcepass scoping
> > Updated comments
> > Greatly simplified/commented test case
>
> Much appreciated, as it's much more readable now. Just one other nit below,
> apart from my previously voiced more general concern towards the two new
> enumerators.
I agree -- I appreciate you pushing me to clean it up! I learned a ton
in the process.
>
> > @@ -5872,13 +5876,32 @@ display_formatted_table (unsigned char *data,
> >
> > READ_ULEB (content_type, format, end);
> > READ_ULEB (form, format, end);
> > - bool do_loc = (content_type == DW_LNCT_path) != (namepass == 1);
> > +
> > + bool do_loc = ((content_type == DW_LNCT_path)
> > + != (namesourcepass == 1))
> > + | ((content_type == DW_LNCT_LLVM_source
>
> While functionally correct, preferably || in something dealing with any
> yielding boolean. (Likely can be adjusted by whoever ends up committing
> this, assuming there'll be someone to approve it despite my concern.)
Will clean that up, thank you! Also, I have a small tweak to the test
case to make it pass on multiple architectures. Expect a v5 soon!
Thank you, again, for the feedback!
Will
>
> Jan
@@ -5847,6 +5847,10 @@ display_formatted_table (unsigned char *data,
case DW_LNCT_MD5:
printf (_("\tMD5\t\t\t"));
break;
+ case DW_LNCT_LLVM_source:
+ case DW_LNCT_source:
+ /* Source is displayed on next line and not in a column. */
+ break;
default:
printf (_("\t(Unknown format content type %" PRIu64 ")"),
content_type);
@@ -5861,8 +5865,8 @@ display_formatted_table (unsigned char *data,
unsigned char *datapass = data;
printf (" %d", last_entry++);
- /* Delay displaying name as the last entry for better screen layout. */
- for (namepass = 0; namepass < 2; namepass++)
+ /* Delay displaying name/source for better screen layout. */
+ for (int namesourcepass = 0; namesourcepass < 3; namesourcepass++)
{
format = format_start;
data = datapass;
@@ -5872,13 +5876,32 @@ display_formatted_table (unsigned char *data,
READ_ULEB (content_type, format, end);
READ_ULEB (form, format, end);
- bool do_loc = (content_type == DW_LNCT_path) != (namepass == 1);
+
+ bool do_loc = ((content_type == DW_LNCT_path)
+ != (namesourcepass == 1))
+ | ((content_type == DW_LNCT_LLVM_source
+ || content_type == DW_LNCT_source)
+ != (namesourcepass == 2));
+
+ char delimiter = '\t';
+
+ /* Print Source last (if available) and print it
+ starting on the next line. */
+ if (namesourcepass == 2
+ && (content_type == DW_LNCT_LLVM_source
+ || content_type == DW_LNCT_source))
+ {
+ delimiter = ' ';
+ putchar ('\n');
+ printf (" Source:");
+ }
data = read_and_display_attr_value (0, form, 0, start, data, end,
0, linfo->li_address_size,
linfo->li_offset_size,
linfo->li_version, NULL,
- do_loc, section, NULL, '\t',
- -1, false, 0, 0, false);
+ do_loc, section, NULL,
+ delimiter, -1, false, 0, 0,
+ false);
}
}
new file mode 100644
@@ -0,0 +1,78 @@
+ .text
+ .p2align 4, 0x90
+ .globl main
+ .type main, @function
+main:
+ .size main, .-main
+ .section .debug_line_str,"MS",@progbits,1
+.Lline_string1:
+ .asciz "/path/to/code/" /* string offset=0 */
+.Lline_string2:
+ .asciz "small.c" /* string offset=15 */
+.Lline_string3:
+ .asciz "int main() {\n return 0;\n}\n"/* string offset=23 */
+ .section .debug_addr,"",@progbits
+ .long .Ldebug_addr_end0-.Ldebug_addr_start0 /* Length of contribution */
+.Ldebug_addr_start0:
+ .short 5 /* DWARF version number */
+ .byte 8 /* Address size */
+ .byte 0 /* Segment selector size */
+.Laddr_table_base0:
+ .quad .Lbegin_func_main
+.Ldebug_addr_end0:
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
+ .long 0x39 /* prologue header length */
+ .value 0x5 /* dwarf version */
+
+ .byte 0x08 /* address size */
+ .byte 0x00 /* segment selector */
+
+ .long 0x3E /* header length = 62 */
+
+ .byte 0x01 /* min instruction length = 1 */
+ .byte 0x01 /* max ops per instruction = 1 */
+ .byte 0x01 /* default is statement */
+ .byte 0xfb /* line base */
+ .byte 0x0e /* line range = 14 */
+ .byte 0x0d /* opcode base = 13 */
+
+ .byte 0x00 /* operand counts for standard opcodes */
+ .byte 0x01
+ .byte 0x01
+ .byte 0x01
+ .byte 0x01
+ .byte 0x00
+ .byte 0x00
+ .byte 0x00
+ .byte 0x01
+ .byte 0x00
+ .byte 0x00
+ .byte 0x01
+
+ .byte 0x01 /* directory entry format count = 1 */
+ .uleb128 0x01 /* the path ... */
+ .uleb128 0x1f /* is a DW_FORM_line_strp */
+
+ .byte 0x01 /* directories count = 1 */
+ .long 0x00 /* offset of path string */
+
+ .byte 0x03 /* file entry format count = 3 */
+ .uleb128 0x01 /* the path ... */
+ .uleb128 0x1f /* is a DW_FORM_line_strp */
+ .uleb128 0x02 /* the directory index ... */
+ .uleb128 0x0f /* is a DW_FORM_udata */
+ .uleb128 0x2001 /* the source ... */
+ .uleb128 0x1f /* is a DW_FORM_line_strp */
+
+ .byte 0x01 /* file names count = 1 */
+ .long 0x0f /* offset of path string */
+ .byte 0x00 /* directory index */
+ .long 0x17 /* offset of source code */
+
+ .byte 0x04 /* set file index to 0 */
+ .uleb128 0x0
+
+ .byte 0x00 /* end sequence */
+ .byte 0x01
+ .byte 0x01
new file mode 100644
@@ -0,0 +1,18 @@
+#objdump: --dwarf=rawline
+#name: objdump (objdump --dwarf=rawline with embedded source)
+#source: dw5-embedded-source.S
+# Nicely print embedded source when displaying the line program in raw format
+
+#...
+ The Directory Table \(offset 0x22, lines 1, columns 1\):
+
+ Entry Name
+ 0 \(indirect line string, offset: 0\): \/path\/to\/code\/
+
+ The File Name Table \(offset 0x2f, lines 1, columns 3\):
+ Entry Dir Name
+ 0 0 \(indirect line string, offset: 0xf\): small.c
+ Source: \(indirect line string, offset: 0x17\): int main\(\) {
+ return 0;
+}
+#...
@@ -615,6 +615,8 @@ if { ![is_elf_format] } then {
file_on_host delete $output
}
+run_dump_test dw5-embedded-source
+
proc test_build_id_debuglink {option} {
global srcdir
global subdir
@@ -293,7 +293,9 @@ enum dwarf_line_number_content_type
DW_LNCT_timestamp = 0x3,
DW_LNCT_size = 0x4,
DW_LNCT_MD5 = 0x5,
+ DW_LNCT_source = 0x6,
DW_LNCT_lo_user = 0x2000,
+ DW_LNCT_LLVM_source = 0x2001,
DW_LNCT_hi_user = 0x3fff
};