Index: include/llvm/Object/RelocVisitor.h =================================================================== --- include/llvm/Object/RelocVisitor.h +++ include/llvm/Object/RelocVisitor.h @@ -208,6 +208,14 @@ HasError = true; return RelocToApply(); } + case Triple::hexagon: + switch (RelocType) { + case llvm::ELF::R_HEX_32: + return visitELF_HEX_32(R, Value); + default: + HasError = true; + return RelocToApply(); + } default: HasError = true; return RelocToApply(); @@ -411,6 +419,11 @@ return RelocToApply(static_cast(Res), 4); } + RelocToApply visitELF_HEX_32(RelocationRef R, uint64_t Value) { + int64_t Addend = getELFAddend(R); + return RelocToApply(Value + Addend, 4); + } + RelocToApply visitELF_AMDGPU_ABS32(RelocationRef R, uint64_t Value) { int64_t Addend = getELFAddend(R); return RelocToApply(Value + Addend, 4); Index: test/tools/llvm-objdump/Hexagon/Inputs/source-interleave-x86_64.c =================================================================== --- /dev/null +++ test/tools/llvm-objdump/Hexagon/Inputs/source-interleave-x86_64.c @@ -0,0 +1,11 @@ +int a = 1; +int foo() +{ + return a; +} + + +int main() { + int *b = &a; + return *b + foo(); +} Index: test/tools/llvm-objdump/Hexagon/lit.local.cfg =================================================================== --- /dev/null +++ test/tools/llvm-objdump/Hexagon/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'Hexagon' in config.root.targets: + config.unsupported = True Index: test/tools/llvm-objdump/Hexagon/source-interleave-x86_64.s =================================================================== --- /dev/null +++ test/tools/llvm-objdump/Hexagon/source-interleave-x86_64.s @@ -0,0 +1,338 @@ +// RUN: sed -e "s,SRC_COMPDIR,%p/Inputs,g" %s > %t.s +// RUN: llvm-mc -o %t.o -filetype=obj -triple=hexagon-unknown-elf %t.s +// RUN: llvm-objdump -d -l %t.o | FileCheck --check-prefix="LINES" %t.s +// RUN: llvm-objdump -d -S %t.o | FileCheck --check-prefix="SOURCE" %t.s + .text + .file "source-interleave-x86_64.c" + .file 1 "source-interleave-x86_64.c" + .globl foo + .p2align 4 + .type foo,@function +foo: // @foo +.Lfunc_begin0: + .loc 1 3 0 // source-interleave-x86_64.c:3:0 + .cfi_startproc +// BB#0: // %entry + { + allocframe(#0) + } +.Ltmp1: + .cfi_def_cfa r30, 8 +.Ltmp2: + .cfi_offset r31, -4 +.Ltmp3: + .cfi_offset r30, -8 +.Ltmp4: + .loc 1 4 9 prologue_end // source-interleave-x86_64.c:4:9 + { + r0 = memw(#a) + } + .loc 1 4 2 is_stmt 0 // source-interleave-x86_64.c:4:2 + { + dealloc_return + } +.Ltmp5: +.Lfunc_end0: + .size foo, .Lfunc_end0-foo + .cfi_endproc + + .globl main + .p2align 4 + .type main,@function +main: // @main +.Lfunc_begin1: + .loc 1 8 0 is_stmt 1 // source-interleave-x86_64.c:8:0 + .cfi_startproc +// BB#0: // %entry + { + allocframe(#16) + } +.Ltmp7: + .cfi_def_cfa r30, 8 +.Ltmp8: + .cfi_offset r31, -4 +.Ltmp9: + .cfi_offset r30, -8 + { + r0 = #0 + } + { + memw(r30+#-4) = r0 + } +.Ltmp10: + .loc 1 9 7 prologue_end // source-interleave-x86_64.c:9:7 + { + r0 = ##a + } + { + memw(r30+#-8) = r0 + } + .loc 1 10 10 // source-interleave-x86_64.c:10:10 + { + r0 = memw(#a) + } + .loc 1 10 15 is_stmt 0 // source-interleave-x86_64.c:10:15 + { + memw(r30+#-12) = r0 + } // 4-byte Folded Spill + { + call foo + } + .loc 1 10 13 // source-interleave-x86_64.c:10:13 + { + r28 = memw(r30 + #-12) + } // 4-byte Folded Reload + { + r0 = add(r28, r0) + } + .loc 1 10 3 // source-interleave-x86_64.c:10:3 + { + dealloc_return + } +.Ltmp11: +.Lfunc_end1: + .size main, .Lfunc_end1-main + .cfi_endproc + + .type a,@object // @a + .section .sdata.4,"aw",@progbits + .globl a + .p2align 2 +a: + .word 1 // 0x1 + .size a, 4 + + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .string "clang version 4.0.0 (http://llvm.org/git/clang d19a95e94dc57c5a72fd25d64f26134aa7d25fa0) (http://llvm.org/git/llvm.git 313924e6ff8a332063f61d3fda03812c220762f6)" // string offset=0 +.Linfo_string1: + .string "source-interleave-x86_64.c" // string offset=161 +.Linfo_string2: + .string "SRC_COMPDIR" // string offset=188 +.Linfo_string3: + .string "a" // string offset=270 +.Linfo_string4: + .string "int" // string offset=272 +.Linfo_string5: + .string "foo" // string offset=276 +.Linfo_string6: + .string "main" // string offset=280 +.Linfo_string7: + .string "b" // string offset=285 + .section .debug_loc,"",@progbits + .section .debug_abbrev,"",@progbits +.Lsection_abbrev: + .byte 1 // Abbreviation Code + .byte 17 // DW_TAG_compile_unit + .byte 1 // DW_CHILDREN_yes + .byte 37 // DW_AT_producer + .byte 14 // DW_FORM_strp + .byte 19 // DW_AT_language + .byte 5 // DW_FORM_data2 + .byte 3 // DW_AT_name + .byte 14 // DW_FORM_strp + .byte 16 // DW_AT_stmt_list + .byte 23 // DW_FORM_sec_offset + .byte 27 // DW_AT_comp_dir + .byte 14 // DW_FORM_strp + .byte 17 // DW_AT_low_pc + .byte 1 // DW_FORM_addr + .byte 18 // DW_AT_high_pc + .byte 6 // DW_FORM_data4 + .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 14 // DW_FORM_strp + .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 14 // DW_FORM_strp + .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 46 // DW_TAG_subprogram + .byte 0 // DW_CHILDREN_no + .byte 17 // DW_AT_low_pc + .byte 1 // DW_FORM_addr + .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 14 // DW_FORM_strp + .byte 58 // DW_AT_decl_file + .byte 11 // DW_FORM_data1 + .byte 59 // DW_AT_decl_line + .byte 11 // DW_FORM_data1 + .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 5 // Abbreviation Code + .byte 46 // DW_TAG_subprogram + .byte 1 // DW_CHILDREN_yes + .byte 17 // DW_AT_low_pc + .byte 1 // DW_FORM_addr + .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 14 // DW_FORM_strp + .byte 58 // DW_AT_decl_file + .byte 11 // DW_FORM_data1 + .byte 59 // DW_AT_decl_line + .byte 11 // DW_FORM_data1 + .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 6 // Abbreviation Code + .byte 52 // DW_TAG_variable + .byte 0 // DW_CHILDREN_no + .byte 2 // DW_AT_location + .byte 24 // DW_FORM_exprloc + .byte 3 // DW_AT_name + .byte 14 // DW_FORM_strp + .byte 58 // DW_AT_decl_file + .byte 11 // DW_FORM_data1 + .byte 59 // DW_AT_decl_line + .byte 11 // DW_FORM_data1 + .byte 73 // DW_AT_type + .byte 19 // DW_FORM_ref4 + .byte 0 // EOM(1) + .byte 0 // EOM(2) + .byte 7 // Abbreviation Code + .byte 15 // DW_TAG_pointer_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 0 // EOM(3) + .section .debug_info,"",@progbits +.Lsection_info: +.Lcu_begin0: + .word 121 // Length of Unit + .half 4 // DWARF version number + .word .Lsection_abbrev // Offset Into Abbrev. Section + .byte 4 // Address Size (in bytes) + .byte 1 // Abbrev [1] 0xb:0x72 DW_TAG_compile_unit + .word .Linfo_string0 // DW_AT_producer + .half 12 // DW_AT_language + .word .Linfo_string1 // DW_AT_name + .word .Lline_table_start0 // DW_AT_stmt_list + .word .Linfo_string2 // DW_AT_comp_dir + .word .Lfunc_begin0 // DW_AT_low_pc + .word .Lfunc_end1-.Lfunc_begin0 // DW_AT_high_pc + .byte 2 // Abbrev [2] 0x26:0x11 DW_TAG_variable + .word .Linfo_string3 // DW_AT_name + .word 55 // DW_AT_type + // DW_AT_external + .byte 1 // DW_AT_decl_file + .byte 1 // DW_AT_decl_line + .byte 5 // DW_AT_location + .byte 3 + .word a + .byte 3 // Abbrev [3] 0x37:0x7 DW_TAG_base_type + .word .Linfo_string4 // DW_AT_name + .byte 5 // DW_AT_encoding + .byte 4 // DW_AT_byte_size + .byte 4 // Abbrev [4] 0x3e:0x15 DW_TAG_subprogram + .word .Lfunc_begin0 // DW_AT_low_pc + .word .Lfunc_end0-.Lfunc_begin0 // DW_AT_high_pc + .byte 1 // DW_AT_frame_base + .byte 110 + .word .Linfo_string5 // DW_AT_name + .byte 1 // DW_AT_decl_file + .byte 2 // DW_AT_decl_line + .word 55 // DW_AT_type + // DW_AT_external + .byte 5 // Abbrev [5] 0x53:0x24 DW_TAG_subprogram + .word .Lfunc_begin1 // DW_AT_low_pc + .word .Lfunc_end1-.Lfunc_begin1 // DW_AT_high_pc + .byte 1 // DW_AT_frame_base + .byte 110 + .word .Linfo_string6 // DW_AT_name + .byte 1 // DW_AT_decl_file + .byte 8 // DW_AT_decl_line + .word 55 // DW_AT_type + // DW_AT_external + .byte 6 // Abbrev [6] 0x68:0xe DW_TAG_variable + .byte 2 // DW_AT_location + .byte 145 + .byte 120 + .word .Linfo_string7 // DW_AT_name + .byte 1 // DW_AT_decl_file + .byte 9 // DW_AT_decl_line + .word 119 // DW_AT_type + .byte 0 // End Of Children Mark + .byte 7 // Abbrev [7] 0x77:0x5 DW_TAG_pointer_type + .word 55 // DW_AT_type + .byte 0 // End Of Children Mark + .section .debug_ranges,"",@progbits +.Ldebug_range: + .section .debug_macinfo,"",@progbits +.Ldebug_macinfo: +.Lcu_macro_begin0: + .byte 0 // End Of Macro List Mark + .section .debug_pubnames,"",@progbits + .word .LpubNames_end0-.LpubNames_begin0 // Length of Public Names Info +.LpubNames_begin0: + .half 2 // DWARF Version + .word .Lcu_begin0 // Offset of Compilation Unit Info + .word 125 // Compilation Unit Length + .word 38 // DIE offset + .string "a" // External Name + .word 62 // DIE offset + .string "foo" // External Name + .word 83 // DIE offset + .string "main" // External Name + .word 0 // End Mark +.LpubNames_end0: + .section .debug_pubtypes,"",@progbits + .word .LpubTypes_end0-.LpubTypes_begin0 // Length of Public Types Info +.LpubTypes_begin0: + .half 2 // DWARF Version + .word .Lcu_begin0 // Offset of Compilation Unit Info + .word 125 // Compilation Unit Length + .word 55 // DIE offset + .string "int" // External Name + .word 0 // End Mark +.LpubTypes_end0: + .cfi_sections .debug_frame + + .ident "clang version 4.0.0 (http://llvm.org/git/clang d19a95e94dc57c5a72fd25d64f26134aa7d25fa0) (http://llvm.org/git/llvm.git 313924e6ff8a332063f61d3fda03812c220762f6)" + .section ".note.GNU-stack","",@progbits + .section .debug_line,"",@progbits +.Lline_table_start0: + +//LINES: main: +//LINES-NEXT: SRC_COMPDIR/source-interleave-x86_64.c:8 + +//SOURCE: main: +//SOURCE-NEXT: int main() { Index: test/tools/llvm-objdump/X86/Inputs/source-interleave-x86_64.c =================================================================== --- /dev/null +++ test/tools/llvm-objdump/X86/Inputs/source-interleave-x86_64.c @@ -0,0 +1,11 @@ +int a = 1; +int foo() +{ + return a; +} + + +int main() { + int *b = &a; + return *b + foo(); +} Index: test/tools/llvm-objdump/X86/source-interleave.s =================================================================== --- /dev/null +++ test/tools/llvm-objdump/X86/source-interleave.s @@ -0,0 +1,317 @@ +// RUN: sed -e "s,SRC_COMPDIR,%p/Inputs,g" %s > %t.s +// RUN: llvm-mc -o %t.o -filetype=obj -triple=x86_64-pc-linux %t.s +// RUN: llvm-objdump -d -l %t.o | FileCheck --check-prefix="LINES" %t.s +// RUN: llvm-objdump -d -S %t.o | FileCheck --check-prefix="SOURCE" %t.s + + .text + .file "source-interleave-x86_64.c" + .file 1 "source-interleave-x86_64.c" + .globl foo + .align 16, 0x90 + .type foo,@function +foo: # @foo +.Lfunc_begin0: + .loc 1 3 0 # source-interleave-x86_64.c:3:0 + .cfi_startproc +# BB#0: + pushq %rbp +.Ltmp0: + .cfi_def_cfa_offset 16 +.Ltmp1: + .cfi_offset %rbp, -16 + movq %rsp, %rbp +.Ltmp2: + .cfi_def_cfa_register %rbp + .loc 1 4 9 prologue_end # source-interleave-x86_64.c:4:9 +.Ltmp3: + movl a, %eax + .loc 1 4 2 is_stmt 0 # source-interleave-x86_64.c:4:2 + popq %rbp + retq +.Ltmp4: +.Lfunc_end0: + .size foo, .Lfunc_end0-foo + .cfi_endproc + + .globl main + .align 16, 0x90 + .type main,@function +main: # @main +.Lfunc_begin1: + .loc 1 8 0 is_stmt 1 # source-interleave-x86_64.c:8:0 + .cfi_startproc +# BB#0: + pushq %rbp +.Ltmp5: + .cfi_def_cfa_offset 16 +.Ltmp6: + .cfi_offset %rbp, -16 + movq %rsp, %rbp +.Ltmp7: + .cfi_def_cfa_register %rbp + subq $32, %rsp + movabsq $a, %rax + movl $0, -4(%rbp) + .loc 1 9 7 prologue_end # source-interleave-x86_64.c:9:7 +.Ltmp8: + movq %rax, -16(%rbp) + .loc 1 10 11 # source-interleave-x86_64.c:10:11 + movq -16(%rbp), %rax + .loc 1 10 10 is_stmt 0 # source-interleave-x86_64.c:10:10 + movl (%rax), %ecx + .loc 1 10 15 # source-interleave-x86_64.c:10:15 + movl %ecx, -20(%rbp) # 4-byte Spill + callq foo + .loc 1 10 13 # source-interleave-x86_64.c:10:13 + movl -20(%rbp), %ecx # 4-byte Reload + addl %eax, %ecx + .loc 1 10 3 # source-interleave-x86_64.c:10:3 + movl %ecx, %eax + addq $32, %rsp + popq %rbp + retq +.Ltmp9: +.Lfunc_end1: + .size main, .Lfunc_end1-main + .cfi_endproc + + .type a,@object # @a + .data + .globl a + .align 4 +a: + .long 1 # 0x1 + .size a, 4 + + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 3.8.1-svn271772-1~exp1 (branches/release_38)" # string offset=0 +.Linfo_string1: + .asciz "source-interleave-x86_64.c" # string offset=59 +.Linfo_string2: + .asciz "SRC_COMPDIR" # string offset=86 +.Linfo_string3: + .asciz "a" # string offset=164 +.Linfo_string4: + .asciz "int" # string offset=166 +.Linfo_string5: + .asciz "foo" # string offset=170 +.Linfo_string6: + .asciz "main" # string offset=174 +.Linfo_string7: + .asciz "b" # string offset=179 + .section .debug_loc,"",@progbits + .section .debug_abbrev,"",@progbits +.Lsection_abbrev: + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .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 14 # DW_FORM_strp + .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 14 # DW_FORM_strp + .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 46 # DW_TAG_subprogram + .byte 0 # DW_CHILDREN_no + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .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 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .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 5 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .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 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .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 6 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 15 # DW_TAG_pointer_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 0 # EOM(3) + .section .debug_info,"",@progbits +.Lsection_info: +.Lcu_begin0: + .long 137 # Length of Unit + .short 4 # DWARF version number + .long .Lsection_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x82 DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 12 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin0 # DW_AT_high_pc + .byte 2 # Abbrev [2] 0x2a:0x15 DW_TAG_variable + .long .Linfo_string3 # DW_AT_name + .long 63 # DW_AT_type + # DW_AT_external + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 9 # DW_AT_location + .byte 3 + .quad a + .byte 3 # Abbrev [3] 0x3f:0x7 DW_TAG_base_type + .long .Linfo_string4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 4 # Abbrev [4] 0x46:0x19 DW_TAG_subprogram + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .long .Linfo_string5 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 63 # DW_AT_type + # DW_AT_external + .byte 5 # Abbrev [5] 0x5f:0x28 DW_TAG_subprogram + .quad .Lfunc_begin1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .long .Linfo_string6 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .long 63 # DW_AT_type + # DW_AT_external + .byte 6 # Abbrev [6] 0x78:0xe DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 112 + .long .Linfo_string7 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 135 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 7 # Abbrev [7] 0x87:0x5 DW_TAG_pointer_type + .long 63 # DW_AT_type + .byte 0 # End Of Children Mark + .section .debug_ranges,"",@progbits +.Ldebug_range: + .section .debug_macinfo,"",@progbits + .byte 0 # End Of Macro List Mark + .section .debug_pubnames,"",@progbits + .long .LpubNames_end0-.LpubNames_begin0 # Length of Public Names Info +.LpubNames_begin0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 141 # Compilation Unit Length + .long 42 # DIE offset + .asciz "a" # External Name + .long 70 # DIE offset + .asciz "foo" # External Name + .long 95 # DIE offset + .asciz "main" # External Name + .long 0 # End Mark +.LpubNames_end0: + .section .debug_pubtypes,"",@progbits + .long .LpubTypes_end0-.LpubTypes_begin0 # Length of Public Types Info +.LpubTypes_begin0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 141 # Compilation Unit Length + .long 63 # DIE offset + .asciz "int" # External Name + .long 0 # End Mark +.LpubTypes_end0: + + .ident "clang version 3.8.1-svn271772-1~exp1 (branches/release_38)" + .section ".note.GNU-stack","",@progbits + .section .debug_line,"",@progbits +.Lline_table_start0: + +//LINES: main: +//LINES-NEXT: ;;; SRC_COMPDIR/source-interleave-x86_64.c:8 + +//SOURCE: main: +//SOURCE-NEXT: ;;; int main() { + Index: tools/llvm-objdump/CMakeLists.txt =================================================================== --- tools/llvm-objdump/CMakeLists.txt +++ tools/llvm-objdump/CMakeLists.txt @@ -5,10 +5,12 @@ AllTargetsInfos CodeGen DebugInfoDWARF + DebugInfoPDB MC MCDisassembler Object Support + Symbolize ) add_llvm_tool(llvm-objdump Index: tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- tools/llvm-objdump/llvm-objdump.cpp +++ tools/llvm-objdump/llvm-objdump.cpp @@ -23,6 +23,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/CodeGen/FaultMaps.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/Symbolize/Symbolize.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler/MCDisassembler.h" @@ -60,6 +61,7 @@ #include #include #include +#include using namespace llvm; using namespace object; @@ -188,6 +190,18 @@ cl::values(clEnumValN(DIDT_Frames, "frames", ".debug_frame"), clEnumValEnd)); +cl::opt PrintSource("source", + cl::desc("Display source inlined with disassembly")); + +cl::alias PrintSourceShort("S", cl::desc("Alias for -source"), + cl::aliasopt(PrintSource)); + +cl::opt + PrintLines("line-numbers", + cl::desc("Display source line numbers with disassembly")); + +cl::alias PrintLinesShort("l", cl::desc("Alias for -line-numbers"), + cl::aliasopt(PrintLines)); static StringRef ToolName; namespace { @@ -361,13 +375,90 @@ } namespace { +class SourcePrinter { +protected: + DILineInfo OldLineInfo; + // Storage for the source + const ObjectFile *Obj; + std::unique_ptr Symbolizer; + std::unordered_map> SourceCache; + // Mark the line endings of the cached source + std::unordered_map> LineCache; + +public: + virtual ~SourcePrinter() {} + SourcePrinter() : Obj(nullptr), Symbolizer(nullptr) {} + SourcePrinter(const ObjectFile *Obj, StringRef DefaultArch) : Obj(Obj) { + symbolize::LLVMSymbolizer::Options SymbolizerOpts( + DILineInfoSpecifier::FunctionNameKind::None, true, false, false, + DefaultArch); + Symbolizer.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts)); + } + virtual void printSourceLine(raw_ostream &OS, uint64_t Address, + StringRef Delimiter = ";;; "); +}; + +void SourcePrinter::printSourceLine(raw_ostream &OS, uint64_t Address, + StringRef Delimiter) { + if (!Symbolizer) + return; + DILineInfo LineInfo = DILineInfo(); + auto ExpectecLineInfo = + Symbolizer->symbolizeCode(Obj->getFileName(), Address); + if (!ExpectecLineInfo) + consumeError(ExpectecLineInfo.takeError()); + else + LineInfo = *ExpectecLineInfo; + + if ((LineInfo.FileName == "") || OldLineInfo.Line == LineInfo.Line || + LineInfo.Line == 0) + return; + + if (PrintLines) + OS << Delimiter << LineInfo.FileName << ":" << LineInfo.Line << "\n"; + if (PrintSource) { + if (SourceCache.find(LineInfo.FileName) == SourceCache.end()) { + // Cache line numbers with the associated character pointers in the + // buffer + auto BufferOrError = MemoryBuffer::getFile(LineInfo.FileName); + if (BufferOrError) { + // Chomp the file to get lines + size_t BufferSize = (*BufferOrError)->getBufferSize(); + const char *BufferStart = (*BufferOrError)->getBufferStart(); + for (const char *Start = BufferStart, *End = BufferStart; + End < BufferStart + BufferSize; End++) + if (*End == '\n' || End == BufferStart + BufferSize - 1 || + (*End == '\r' && *(End + 1) == '\n')) { + LineCache[LineInfo.FileName].push_back( + StringRef(Start, End - Start)); + if (*End == '\r') + End++; + Start = End + 1; + } + SourceCache[LineInfo.FileName] = std::move(*BufferOrError); + } + } + auto FileBuffer = SourceCache.find(LineInfo.FileName); + if (FileBuffer != SourceCache.end()) { + auto LineBuffer = LineCache.find(LineInfo.FileName); + if (LineBuffer != LineCache.end()) + // Vector begins at 0, line numbers are non-zero + OS << Delimiter << LineBuffer->second[LineInfo.Line - 1].ltrim() + << "\n"; + } + } + OldLineInfo = LineInfo; +} + class PrettyPrinter { public: virtual ~PrettyPrinter(){} virtual void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, uint64_t Address, raw_ostream &OS, StringRef Annot, - MCSubtargetInfo const &STI) { + MCSubtargetInfo const &STI, SourcePrinter *SP) { + if (SP && (PrintSource || PrintLines)) + SP->printSourceLine(OS, Address); OS << format("%8" PRIx64 ":", Address); if (!NoShowRawInsn) { OS << "\t"; @@ -393,10 +484,9 @@ OS << format("%08" PRIx32, opcode); } } - void printInst(MCInstPrinter &IP, const MCInst *MI, - ArrayRef Bytes, uint64_t Address, - raw_ostream &OS, StringRef Annot, - MCSubtargetInfo const &STI) override { + void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, + uint64_t Address, raw_ostream &OS, StringRef Annot, + MCSubtargetInfo const &STI, SourcePrinter *SP) override { if (!MI) { printLead(Bytes, Address, OS); OS << " "; @@ -417,6 +507,8 @@ while(!HeadTail.first.empty()) { OS << Separator; Separator = "\n"; + if (SP && (PrintSource || PrintLines)) + SP->printSourceLine(OS, Address, ""); printLead(Bytes, Address, OS); OS << Preamble; Preamble = " "; @@ -441,18 +533,17 @@ class AMDGCNPrettyPrinter : public PrettyPrinter { public: - void printInst(MCInstPrinter &IP, - const MCInst *MI, - ArrayRef Bytes, - uint64_t Address, - raw_ostream &OS, - StringRef Annot, - MCSubtargetInfo const &STI) override { + void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, + uint64_t Address, raw_ostream &OS, StringRef Annot, + MCSubtargetInfo const &STI, SourcePrinter *SP) override { if (!MI) { OS << " "; return; } + if (SP && (PrintSource || PrintLines)) + SP->printSourceLine(OS, Address, "//"); + SmallString<40> InstStr; raw_svector_ostream IS(InstStr); @@ -990,6 +1081,8 @@ StringRef Fmt = Obj->getBytesInAddress() > 4 ? "\t\t%016" PRIx64 ": " : "\t\t\t%08" PRIx64 ": "; + SourcePrinter SP(Obj, TheTarget->getName()); + // Create a mapping, RelocSecs = SectionRelocMap[S], where sections // in RelocSecs contain the relocations for section S. std::error_code EC; @@ -1207,14 +1300,15 @@ if (Index >= End) break; - bool Disassembled = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), - SectionAddr + Index, DebugOut, - CommentStream); + bool Disassembled = DisAsm->getInstruction( + Inst, Size, Bytes.slice(Index), SectionAddr + Index, DebugOut, + CommentStream); if (Size == 0) Size = 1; + PIP.printInst(*IP, Disassembled ? &Inst : nullptr, - Bytes.slice(Index, Size), - SectionAddr + Index, outs(), "", *STI); + Bytes.slice(Index, Size), SectionAddr + Index, outs(), "", + *STI, &SP); outs() << CommentStream.str(); Comments.clear();