[AMD Official Use Only - General] Hi, When an executable is compiled with -gdwarf-5 option, bintools such as objdump, readelf do not recognize some of the new DWARF-5 tags. The below binutils patch is to support one of the new DWARF-5 operation encoding tag DW_OP_addrx. Before patch: <1><86>: Abbrev Number: 3 (DW_TAG_variable) <87> DW_AT_name : (indexed string: 0xc): uni_lang_p <88> DW_AT_type : <0x4a> <8c> DW_AT_external : 1 <8c> DW_AT_decl_file : 0 <8d> DW_AT_decl_line : 64 <8e> DW_AT_location : 2 byte block: a1 4 ((Unknown location op 0xa1)) After patch: <1><86>: Abbrev Number: 3 (DW_TAG_variable) <87> DW_AT_name : (indexed string: 0xc): uni_lang_p <88> DW_AT_type : <0x4a> <8c> DW_AT_external : 1 <8c> DW_AT_decl_file : 0 <8d> DW_AT_decl_line : 64 <8e> DW_AT_location : (DW_OP_addrx <0x4>) Generated .s file with clang to test this feature as gcc does not emit this tag. Please review. Regards, Kavitha ====================================================================== Binutils tools objdump and readelf to support new dwarf-5 operation encoding, such as, DW_OP_addrx. Added test points in objdump.exp and readlef.exp. --- binutils/dwarf.c | 11 +- binutils/testsuite/binutils-all/objdump.exp | 48 ++- binutils/testsuite/binutils-all/readelf.exp | 62 +++ binutils/testsuite/binutils-all/testprog.s | 426 ++++++++++++++++++++ 4 files changed, 543 insertions(+), 4 deletions(-) create mode 100644 binutils/testsuite/binutils-all/testprog.s diff --git a/binutils/dwarf.c b/binutils/dwarf.c index bc862f77c04..fc754f4f73d 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -1721,6 +1721,10 @@ decode_location_expression (unsigned char * data, printf ("DW_OP_GNU_parameter_ref: <0x%s>", dwarf_vmatoa ("x", cu_offset + uvalue)); break; + case DW_OP_addrx: + READ_ULEB (uvalue, data, end); + printf ("DW_OP_addrx <0x%s>", dwarf_vmatoa ("x", uvalue)); + break; case DW_OP_GNU_addr_index: READ_ULEB (uvalue, data, end); printf ("DW_OP_GNU_addr_index <0x%s>", dwarf_vmatoa ("x", uvalue)); @@ -2661,9 +2665,10 @@ read_and_display_attr_value (unsigned long attribute, uvalue = check_uvalue (block_start, uvalue, end); - if (do_loc) - data = block_start + uvalue; - else + data = block_start + uvalue; + + /* DW_OP_addrx has only the index and not address. */ + if (!do_loc && ((unsigned)(*block_start) != DW_OP_addrx)) data = display_block (block_start, uvalue, end, delimiter); break; diff --git a/binutils/testsuite/binutils-all/objdump.exp b/binutils/testsuite/binutils-all/objdump.exp index 0f160ae5a06..f0a4611dd1f 100644 --- a/binutils/testsuite/binutils-all/objdump.exp +++ b/binutils/testsuite/binutils-all/objdump.exp @@ -513,6 +513,52 @@ if { ![is_elf_format] } then { } } +# Test objdump -Wi on a file containing dwarf-5 encodings information. + +if { ![is_elf_format] } then { + unsupported "objdump DW_OP_addrx test" +} elseif { ![binutils_assemble $srcdir/$subdir/testprog.s tmpdir/testprog.${obj}] } then { + fail "objdump DW_OP_addrx test" +} else { + if [is_remote host] { + set op_testfile [remote_download host tmpdir/testprog.${obj}] + } else { + set op_testfile tmpdir/testprog.${obj} + } + + set got [remote_exec host "$OBJDUMP $OBJDUMPFLAGS -Wi $op_testfile" "" "/dev/null" "objdump.out"] + + if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then { + fail "objdump -Wi (reason: unexpected output)" + send_log $got + send_log "\n" + } + + set output [remote_upload host objdump.out] + + if ![file size $output] then { + # If the output file is empty, then this target does not + # generate dwarf2 output. This is not a failure. + verbose "No output from 'objdump -wi'" + untested "objdump -wi" + return + } + + # Search for strings that should be in the output. + set sought ".*\(DW_OP_addrx <0\).*" + + set lines [grep $output $sought] + if ![llength $lines] then { + fail "objdump -Wi: missing: $sought" + send_log objdump.out + return + } else { + pass "objdump -Wi for DW_OP_addrx" + } + + file_on_host delete $output +} + proc test_build_id_debuglink {} { global srcdir global subdir @@ -522,7 +568,7 @@ proc test_build_id_debuglink {} { global OBJDUMP global CFLAGS_FOR_TARGET global exe - + set test "build-id-debuglink" # Use a fixed build-id. diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp index 8ff756e506f..db0fe88cef7 100644 --- a/binutils/testsuite/binutils-all/readelf.exp +++ b/binutils/testsuite/binutils-all/readelf.exp @@ -214,6 +214,67 @@ proc readelf_wi_test {} { pass "readelf -wi" } +# Testing the "readelf -wi" option for dwarf-5 specific information. +# readelf_wi_test_5{} can be merged to readelf_wi_test{} once gcc +# supports dwarf-5 encodings. + +proc readelf_wi_test_5 {} { + global READELF + global READELFFLAGS + global srcdir + global subdir + + # Compile the second test file. + if {![binutils_assemble $srcdir/$subdir/testprog.s tmpdir/testprog.o]} { + verbose "Unable to assemble test file." + untested "readelf -wi (dwarf-5)" + return + } + + # Download it. + set tempfile [remote_download host tmpdir/testprog.o] + + # Run "readelf -wi" on it. + set got [remote_exec host "$READELF $READELFFLAGS -wi $tempfile" "" "/dev/null" "readelf.out"] + + # Upload the results. + set output [remote_upload host readelf.out] + + file_on_host delete $tempfile + + # Strip any superflous warnings. + set got [prune_readelf_wi_warnings [lindex $got 1]] + + if ![string match "" $got] then { + fail "readelf $READELFFLAGS -wi (dwarf-5) (reason: unexpected output)" + send_log $got + send_log "\n" + return + } + + if ![file size $output] then { + # If the output file is empty, then this target does not + # generate dwarf2 output. This is not a failure. + verbose "No output from 'readelf -wi (dwarf-5)'" + untested "readelf -wi (dwarf-5)" + return + } + + # Search for strings that should be in the output. + set sought ".*\(DW_OP_addrx <0\).*" + + set lines [grep $output $sought] + if ![llength $lines] then { + fail "readelf -wi (dwarf-5): missing: $sought" + send_log readelf.out + return + } else { + pass "readelf -wi (dwarf-5)" + } + + file_on_host delete $output +} + # This tests "readelf -wa", but on a file with a compressed # .debug_abbrev section. @@ -390,6 +451,7 @@ if {![binutils_assemble $srcdir/$subdir/mangled.s tmpdir/mangled.o]} then { } readelf_wi_test +readelf_wi_test_5 readelf_compressed_wa_test readelf_dump_test diff --git a/binutils/testsuite/binutils-all/testprog.s b/binutils/testsuite/binutils-all/testprog.s new file mode 100644 index 00000000000..9db95e24ac2 --- /dev/null +++ b/binutils/testsuite/binutils-all/testprog.s @@ -0,0 +1,426 @@ +# Generated from testprog.c +# clang -gdwarf-5 -S testprog.c -fno-addrsig + + .text + .file "testprog.c" + .file 0 "/home/kavitha/workarea/binutils-gdb-amd/binutils/testsuite/binutils-all" "testprog.c" md5 0x1a2591dc3647301324c8184161bb46ff + .globl fn # -- Begin function fn + .p2align 4, 0x90 + .type fn,@function +fn: # @fn +.Lfunc_begin0: + .loc 0 13 0 # testprog.c:13:0 + .cfi_startproc +# %bb.0: + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp +.Ltmp0: + .loc 0 14 3 prologue_end # testprog.c:14:3 + movl $3, %eax + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size fn, .Lfunc_end0-fn + .cfi_endproc + # -- End function + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin1: + .loc 0 19 0 # testprog.c:19:0 + .cfi_startproc +# %bb.0: + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + subq $16, %rsp + movl $0, -4(%rbp) +.Ltmp2: + .loc 0 20 14 prologue_end # testprog.c:20:14 + cmpl $0, common + .loc 0 21 7 # testprog.c:21:7 + jne .LBB1_4 +# %bb.1: + .loc 0 21 17 is_stmt 0 # testprog.c:21:17 + cmpl $1, global + .loc 0 22 7 is_stmt 1 # testprog.c:22:7 + jne .LBB1_4 +# %bb.2: + .loc 0 22 16 is_stmt 0 # testprog.c:22:16 + cmpl $2, local + .loc 0 23 7 is_stmt 1 # testprog.c:23:7 + jne .LBB1_4 +# %bb.3: + .loc 0 23 10 is_stmt 0 # testprog.c:23:10 + movl $string, %edi + movl $.L.str, %esi + callq strcmp + .loc 0 23 36 # testprog.c:23:36 + cmpl $0, %eax +.Ltmp3: + .loc 0 20 7 is_stmt 1 # testprog.c:20:7 + je .LBB1_5 +.LBB1_4: +.Ltmp4: + .loc 0 25 7 # testprog.c:25:7 + movabsq $.L.str.1, %rdi + movb $0, %al + callq printf + .loc 0 26 7 # testprog.c:26:7 + movl $1, -4(%rbp) + jmp .LBB1_6 +.Ltmp5: +.LBB1_5: + .loc 0 29 3 # testprog.c:29:3 + movabsq $.L.str.2, %rdi + movb $0, %al + callq printf + .loc 0 30 3 # testprog.c:30:3 + movl $0, -4(%rbp) +.LBB1_6: + .loc 0 31 1 # testprog.c:31:1 + movl -4(%rbp), %eax + addq $16, %rsp + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp6: +.Lfunc_end1: + .size main, .Lfunc_end1-main + .cfi_endproc + # -- End function + .type global,@object # @global + .data + .globl global + .p2align 2 +global: + .long 1 # 0x1 + .size global, 4 + + .type common,@object # @common + .bss + .globl common + .p2align 2 +common: + .long 0 # 0x0 + .size common, 4 + + .type local,@object # @local + .data + .p2align 2 +local: + .long 2 # 0x2 + .size local, 4 + + .type string,@object # @string + .section .rodata,"a",@progbits +string: + .asciz "string" + .size string, 7 + + .type .L.str,@object # @.str + .section .rodata.str1.1,"aMS",@progbits,1 +.L.str: + .asciz "string" + .size .L.str, 7 + + .type .L.str.1,@object # @.str.1 +.L.str.1: + .asciz "failed\n" + .size .L.str.1, 8 + + .type .L.str.2,@object # @.str.2 +.L.str.2: + .asciz "ok\n" + .size .L.str.2, 4 + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 1 # DW_TAG_array_type + .byte 1 # DW_CHILDREN_yes + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 33 # DW_TAG_subrange_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 55 # DW_AT_count + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 38 # DW_TAG_const_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 0 # DW_CHILDREN_no + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 39 # DW_AT_prototyped + .byte 25 # DW_FORM_flag_present + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x7f DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 12 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 4 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 2 # Abbrev [2] 0x23:0xb DW_TAG_variable + .byte 3 # DW_AT_name + .long 46 # DW_AT_type + # DW_AT_external + .byte 0 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 0 + .byte 3 # Abbrev [3] 0x2e:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 2 # Abbrev [2] 0x32:0xb DW_TAG_variable + .byte 5 # DW_AT_name + .long 46 # DW_AT_type + # DW_AT_external + .byte 0 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 1 + .byte 4 # Abbrev [4] 0x3d:0xb DW_TAG_variable + .byte 6 # DW_AT_name + .long 46 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 2 + .byte 4 # Abbrev [4] 0x48:0xb DW_TAG_variable + .byte 7 # DW_AT_name + .long 83 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 3 + .byte 5 # Abbrev [5] 0x53:0xc DW_TAG_array_type + .long 95 # DW_AT_type + .byte 6 # Abbrev [6] 0x58:0x6 DW_TAG_subrange_type + .long 104 # DW_AT_type + .byte 7 # DW_AT_count + .byte 0 # End Of Children Mark + .byte 7 # Abbrev [7] 0x5f:0x5 DW_TAG_const_type + .long 100 # DW_AT_type + .byte 3 # Abbrev [3] 0x64:0x4 DW_TAG_base_type + .byte 8 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 8 # Abbrev [8] 0x68:0x4 DW_TAG_base_type + .byte 9 # DW_AT_name + .byte 8 # DW_AT_byte_size + .byte 7 # DW_AT_encoding + .byte 9 # Abbrev [9] 0x6c:0xf DW_TAG_subprogram + .byte 4 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .byte 10 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 12 # DW_AT_decl_line + # DW_AT_prototyped + .long 46 # DW_AT_type + # DW_AT_external + .byte 9 # Abbrev [9] 0x7b:0xf DW_TAG_subprogram + .byte 5 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .byte 11 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 18 # DW_AT_decl_line + # DW_AT_prototyped + .long 46 # DW_AT_type + # DW_AT_external + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 52 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "Ubuntu clang version 12.0.0-3ubuntu1~20.04.5" # string offset=0 +.Linfo_string1: + .asciz "testprog.c" # string offset=45 +.Linfo_string2: + .asciz "/home/kavitha/workarea/binutils-gdb-amd/binutils/testsuite/binutils-all" # string offset=56 +.Linfo_string3: + .asciz "global" # string offset=128 +.Linfo_string4: + .asciz "int" # string offset=135 +.Linfo_string5: + .asciz "common" # string offset=139 +.Linfo_string6: + .asciz "local" # string offset=146 +.Linfo_string7: + .asciz "string" # string offset=152 +.Linfo_string8: + .asciz "char" # string offset=159 +.Linfo_string9: + .asciz "__ARRAY_SIZE_TYPE__" # string offset=164 +.Linfo_string10: + .asciz "fn" # string offset=184 +.Linfo_string11: + .asciz "main" # string offset=187 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .long .Linfo_string9 + .long .Linfo_string10 + .long .Linfo_string11 + .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 global + .quad common + .quad local + .quad string + .quad .Lfunc_begin0 + .quad .Lfunc_begin1 +.Ldebug_addr_end0: + .ident "Ubuntu clang version 12.0.0-3ubuntu1~20.04.5" + .section ".note.GNU-stack","",@progbits + .section .debug_line,"",@progbits +.Lline_table_start0: --