diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -647,11 +647,13 @@ // Vendor extensions: // Extensions for GNU-style thread-local storage. HANDLE_DW_OP(0xe0, GNU_push_tls_address, 0, GNU) +HANDLE_DW_OP(0xf2, GNU_implicit_pointer, 0, GNU) // The GNU entry value extension. HANDLE_DW_OP(0xf3, GNU_entry_value, 0, GNU) // Extensions for Fission proposal. HANDLE_DW_OP(0xfb, GNU_addr_index, 0, GNU) HANDLE_DW_OP(0xfc, GNU_const_index, 0, GNU) +HANDLE_DW_OP(0xf5, GNU_regval_type, 0, GNU) // DWARF languages. HANDLE_DW_LANG(0x0001, C89, 0, 2, DWARF) diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h @@ -119,6 +119,10 @@ return Op; } + iterator skip_bytes(uint32_t Add) { + return iterator(Expr, Op.EndOffset + Add); + } + class Operation &operator*() { return Op; } diff --git a/llvm/include/llvm/Support/FormattedStream.h b/llvm/include/llvm/Support/FormattedStream.h --- a/llvm/include/llvm/Support/FormattedStream.h +++ b/llvm/include/llvm/Support/FormattedStream.h @@ -106,10 +106,16 @@ formatted_raw_ostream &PadToColumn(unsigned NewCol); /// getColumn - Return the column number - unsigned getColumn() { return Position.first; } + unsigned getColumn() { + ComputePosition(getBufferStart(), GetNumBytesInBuffer()); + return Position.first; + } /// getLine - Return the line number - unsigned getLine() { return Position.second; } + unsigned getLine() { + ComputePosition(getBufferStart(), GetNumBytesInBuffer()); + return Position.second; + } raw_ostream &resetColor() override { TheStream->resetColor(); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -494,8 +494,16 @@ return createStringError(inconvertibleErrorCode(), "No %s", dwarf::AttributeString(Attr).data()); - if (Optional Off = Location->getAsSectionOffset()) - return U->findLoclistFromOffset(*Off); + if (Optional Off = Location->getAsSectionOffset()) { + if (Location->getForm() == DW_FORM_loclistx) { + if (auto LoclistOffset = U->getLoclistOffset(*Off)) { + uint64_t Offset = *LoclistOffset + U->getLocSectionBase(); + return U->findLoclistFromOffset(Offset); + } + } else { + return U->findLoclistFromOffset(*Off); + } + } if (Optional> Expr = Location->getAsBlock()) { return DWARFLocationExpressionsVector{ diff --git a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp @@ -101,6 +101,13 @@ Descriptions[DW_OP_convert] = Desc(Op::Dwarf5, Op::BaseTypeRef); Descriptions[DW_OP_entry_value] = Desc(Op::Dwarf5, Op::SizeLEB); + Descriptions[DW_OP_regval_type] = Desc(Op::Dwarf5, Op::SizeLEB, Op::SizeLEB); + Descriptions[DW_OP_GNU_regval_type] = + Desc(Op::Dwarf5, Op::SizeLEB, Op::SizeLEB); + Descriptions[DW_OP_implicit_pointer] = + Desc(Op::Dwarf5, Op::SizeRefAddr, Op::SignedSizeLEB); + Descriptions[DW_OP_GNU_implicit_pointer] = + Desc(Op::Dwarf5, Op::SizeRefAddr, Op::SignedSizeLEB); return Descriptions; } diff --git a/llvm/lib/Support/FormattedStream.cpp b/llvm/lib/Support/FormattedStream.cpp --- a/llvm/lib/Support/FormattedStream.cpp +++ b/llvm/lib/Support/FormattedStream.cpp @@ -26,8 +26,33 @@ // Keep track of the current column and line by scanning the string for // special characters + bool MultiByte = false; for (const char *End = Ptr + Size; Ptr != End; ++Ptr) { + // If this is a multi-byte sequence, skip the extra bytes, and don't check + // for special whitespace characters. + if ((*Ptr & 0b11100000) == 0b11000000) { + Ptr += 1; + MultiByte = true; + } else if ((*Ptr & 0b11110000) == 0b11100000) { + Ptr += 2; + MultiByte = true; + } else if ((*Ptr & 0b11111000) == 0b11110000) { + Ptr += 3; + MultiByte = true; + } + + // The string should never end part way through a multi-byte sequence. + assert(Ptr < End && "Malformed multi-byte sequence"); + ++Column; + + // If this is the final byte of a multi-byte sequence, it can't be any of + // the special whitespace characters below. + if (MultiByte) { + MultiByte = false; + continue; + } + switch (*Ptr) { case '\n': Line += 1; diff --git a/llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf4-sections.s b/llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf4-sections.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf4-sections.s @@ -0,0 +1,790 @@ +// RUN: llvm-mc -triple armv8a--none-eabi < %s -filetype=obj | \ +// RUN: llvm-objdump - -d -debug-vars | \ +// RUN: FileCheck %s --check-prefix=RAW +// RUN: llvm-mc -triple armv8a--none-eabi < %s -filetype=obj | \ +// RUN: llvm-objdump - -d -debug-vars -no-show-raw-insn | \ +// RUN: FileCheck %s --check-prefix=NO-RAW + +// Generated with this compile command and source: +// +// clang --target=arm--none-eabi -march=armv7-a -c debug.c -O2 -gdwarf-4 -S -o - -ffunction-sections +// +// void bar(int*); +// int baz(long a, int b, int c) { +// int d = a + b; +// bar(&d); +// int e = d * c; +// return e; +// } +// +// struct S { +// int a; +// int b; +// }; +// int foo(struct S x) { +// int y = x.a + x.b; +// return y; +// } +// +// int quxx(int a, int b, int c, int d, int x, int y) { +// int z = x + y; +// return z; +// } + +// RAW: Disassembly of section .text.baz: +// RAW-EMPTY: +// RAW: 00000000 baz: +// RAW: line 2, column 0 ┠─ b = R1 +// RAW: ┃ ┠─ a = R0 +// RAW: ┃ ┃ ┠─ c = R2 +// RAW: 0: 10 4c 2d e9 push {r4, r10, r11, lr} ┃ ┃ ┃ +// RAW: 4: 08 b0 8d e2 add r11, sp, #8 ┃ ┃ ┃ +// RAW: 8: 08 d0 4d e2 sub sp, sp, #8 ┃ ┃ ┃ +// RAW: line 3, column 13 ┃ ┃ ┌─ d = R0 +// RAW: c: 00 00 81 e0 add r0, r1, r0 ┃ ┻ ╈ ┃ +// RAW: ┃ ┌─ d = [SP+4] +// RAW: 10: 04 00 8d e5 str r0, [sp, #4] ┃ ╈ ┻ ┃ +// RAW: line 0, column 7 ┃ ┃ ┃ +// RAW: 14: 04 00 8d e2 add r0, sp, #4 ┃ ┃ ┃ +// RAW: ┃ ┃ ┌─ a = R0 +// RAW: ┃ ┃ │ ┃ ┌─ c = R4 +// RAW: 18: 02 40 a0 e1 mov r4, r2 ┃ ┃ ╈ ┻ ╈ +// RAW: line 4, column 3 ┃ ┃ ┃ ┃ +// RAW: 1c: fe ff ff eb bl #-8 ┻ ┃ ┻ ┃ +// RAW: line 5, column 11 ┌─ d = R0 ┃ +// RAW: 20: 04 00 9d e5 ldr r0, [sp, #4] ╈ ┻ ┃ +// RAW: ┃ ┌─ e = R0 +// RAW: 24: 90 04 00 e0 mul r0, r0, r4 ┻ ╈ ┃ +// RAW: line 6, column 3 ┃ ┃ +// RAW: 28: 08 d0 4b e2 sub sp, r11, #8 ┃ ┃ +// RAW: 2c: 10 8c bd e8 pop {r4, r10, r11, pc} ┻ ┻ +// RAW-EMPTY: +// RAW: Disassembly of section .text.foo: +// RAW-EMPTY: +// RAW: 00000000 foo: +// RAW: line 13, column 0 ┠─ x = [0,4): R0 [4,8): R1 +// RAW: ┃ ┌─ x = [0,4): ??? [4,8): R1 +// RAW: ┃ │ ┌─ y = R0 +// RAW: 0: 01 00 80 e0 add r0, r0, r1 ┻ ╈ ╈ +// RAW: line 15, column 3 ┃ ┃ +// RAW: 4: 1e ff 2f e1 bx lr ┻ ┻ +// RAW-EMPTY: +// RAW: Disassembly of section .text.quxx: +// RAW-EMPTY: +// RAW: 00000000 quxx: +// RAW: line 18, column 0 ┠─ a = R0 ┃ +// RAW: ┃ ┠─ b = R1 +// RAW: ┃ ┃ ┠─ c = R2 +// RAW: ┃ ┃ ┃ ┠─ d = R3 +// RAW: ┃ ┃ ┃ ┃ ┠─ x = [SP] +// RAW: ┃ ┃ ┃ ┃ ┃ ┠─ y = [SP+4] +// RAW: 0: 03 00 9d e8 ldm sp, {r0, r1} ┻ ┻ ┃ ┃ ┃ ┃ +// RAW: line 19, column 13 ┌─ z = R0 ┃ +// RAW: 4: 00 00 81 e0 add r0, r1, r0 ╈ ┃ ┃ ┃ ┃ +// RAW: line 20, column 3 ┃ ┃ ┃ ┃ ┃ +// RAW: 8: 1e ff 2f e1 bx lr ┻ ┻ ┻ ┻ ┻ + +// NO-RAW: Disassembly of section .text.baz: +// NO-RAW-EMPTY: +// NO-RAW: 00000000 baz: +// NO-RAW: line 2, column 0 ┠─ b = R1 +// NO-RAW: ┃ ┠─ a = R0 +// NO-RAW: ┃ ┃ ┠─ c = R2 +// NO-RAW: 0: push {r4, r10, r11, lr} ┃ ┃ ┃ +// NO-RAW: 4: add r11, sp, #8 ┃ ┃ ┃ +// NO-RAW: 8: sub sp, sp, #8 ┃ ┃ ┃ +// NO-RAW: line 3, column 13 ┃ ┃ ┌─ d = R0 +// NO-RAW: c: add r0, r1, r0 ┃ ┻ ╈ ┃ +// NO-RAW: ┃ ┌─ d = [SP+4] +// NO-RAW: 10: str r0, [sp, #4] ┃ ╈ ┻ ┃ +// NO-RAW: line 0, column 7 ┃ ┃ ┃ +// NO-RAW: 14: add r0, sp, #4 ┃ ┃ ┃ +// NO-RAW: ┃ ┃ ┌─ a = R0 +// NO-RAW: ┃ ┃ │ ┃ ┌─ c = R4 +// NO-RAW: 18: mov r4, r2 ┃ ┃ ╈ ┻ ╈ +// NO-RAW: line 4, column 3 ┃ ┃ ┃ ┃ +// NO-RAW: 1c: bl #-8 ┻ ┃ ┻ ┃ +// NO-RAW: line 5, column 11 ┌─ d = R0 ┃ +// NO-RAW: 20: ldr r0, [sp, #4] ╈ ┻ ┃ +// NO-RAW: ┃ ┌─ e = R0 +// NO-RAW: 24: mul r0, r0, r4 ┻ ╈ ┃ +// NO-RAW: line 6, column 3 ┃ ┃ +// NO-RAW: 28: sub sp, r11, #8 ┃ ┃ +// NO-RAW: 2c: pop {r4, r10, r11, pc} ┻ ┻ +// NO-RAW-EMPTY: +// NO-RAW: Disassembly of section .text.foo: +// NO-RAW-EMPTY: +// NO-RAW: 00000000 foo: +// NO-RAW: line 13, column 0 ┠─ x = [0,4): R0 [4,8): R1 +// NO-RAW: ┃ ┌─ x = [0,4): ??? [4,8): R1 +// NO-RAW: ┃ │ ┌─ y = R0 +// NO-RAW: 0: add r0, r0, r1 ┻ ╈ ╈ +// NO-RAW: line 15, column 3 ┃ ┃ +// NO-RAW: 4: bx lr ┻ ┻ +// NO-RAW-EMPTY: +// NO-RAW: Disassembly of section .text.quxx: +// NO-RAW-EMPTY: +// NO-RAW: 00000000 quxx: +// NO-RAW: line 18, column 0 ┠─ a = R0 ┃ +// NO-RAW: ┃ ┠─ b = R1 +// NO-RAW: ┃ ┃ ┠─ c = R2 +// NO-RAW: ┃ ┃ ┃ ┠─ d = R3 +// NO-RAW: ┃ ┃ ┃ ┃ ┠─ x = [SP] +// NO-RAW: ┃ ┃ ┃ ┃ ┃ ┠─ y = [SP+4] +// NO-RAW: 0: ldm sp, {r0, r1} ┻ ┻ ┃ ┃ ┃ ┃ +// NO-RAW: line 19, column 13 ┌─ z = R0 ┃ +// NO-RAW: 4: add r0, r1, r0 ╈ ┃ ┃ ┃ ┃ +// NO-RAW: line 20, column 3 ┃ ┃ ┃ ┃ ┃ +// NO-RAW: 8: bx lr ┻ ┻ ┻ ┻ ┻ + + .text + .syntax unified + .eabi_attribute 67, "2.09" + .eabi_attribute 6, 10 + .eabi_attribute 7, 65 + .eabi_attribute 8, 1 + .eabi_attribute 9, 2 + .fpu neon + .eabi_attribute 34, 0 + .eabi_attribute 17, 1 + .eabi_attribute 20, 1 + .eabi_attribute 21, 1 + .eabi_attribute 23, 3 + .eabi_attribute 24, 1 + .eabi_attribute 25, 1 + .eabi_attribute 38, 1 + .eabi_attribute 18, 4 + .eabi_attribute 26, 2 + .eabi_attribute 14, 0 + .file "debug.c" + .file 1 "/work/scratch" "debug.c" + .section .text.baz,"ax",%progbits + .globl baz + .p2align 2 + .type baz,%function + .code 32 +baz: +.Lfunc_begin0: + .loc 1 2 0 + .fnstart + .cfi_sections .debug_frame + .cfi_startproc + .save {r4, r10, r11, lr} + push {r4, r10, r11, lr} + .cfi_def_cfa_offset 16 + .cfi_offset lr, -4 + .cfi_offset r11, -8 + .cfi_offset r10, -12 + .cfi_offset r4, -16 + .setfp r11, sp, #8 + add r11, sp, #8 + .cfi_def_cfa r11, 8 + .pad #8 + sub sp, sp, #8 +.Ltmp0: + .loc 1 3 13 prologue_end + add r0, r1, r0 +.Ltmp1: + .loc 1 3 7 is_stmt 0 + str r0, [sp, #4] +.Ltmp2: + .loc 1 0 7 + add r0, sp, #4 + mov r4, r2 +.Ltmp3: + .loc 1 4 3 is_stmt 1 + bl bar +.Ltmp4: + .loc 1 5 11 + ldr r0, [sp, #4] +.Ltmp5: + .loc 1 5 13 is_stmt 0 + mul r0, r0, r4 +.Ltmp6: + .loc 1 6 3 is_stmt 1 + sub sp, r11, #8 + pop {r4, r10, r11, pc} +.Ltmp7: +.Lfunc_end0: + .size baz, .Lfunc_end0-baz + .cfi_endproc + .cantunwind + .fnend + + .section .text.foo,"ax",%progbits + .globl foo + .p2align 2 + .type foo,%function + .code 32 +foo: +.Lfunc_begin1: + .loc 1 13 0 + .fnstart + .cfi_startproc + .loc 1 14 15 prologue_end + add r0, r0, r1 +.Ltmp8: + .loc 1 15 3 + bx lr +.Ltmp9: +.Lfunc_end1: + .size foo, .Lfunc_end1-foo + .cfi_endproc + .cantunwind + .fnend + + .section .text.quxx,"ax",%progbits + .globl quxx + .p2align 2 + .type quxx,%function + .code 32 +quxx: +.Lfunc_begin2: + .loc 1 18 0 + .fnstart + .cfi_startproc + ldm sp, {r0, r1} +.Ltmp10: + .loc 1 19 13 prologue_end + add r0, r1, r0 +.Ltmp11: + .loc 1 20 3 + bx lr +.Ltmp12: +.Lfunc_end2: + .size quxx, .Lfunc_end2-quxx + .cfi_endproc + .cantunwind + .fnend + + .section .debug_str,"MS",%progbits,1 +.Linfo_string0: + .asciz "clang version 10.0.0 (git@github.com:llvm/llvm-project.git e73f78acd34360f7450b81167d9dc858ccddc262)" +.Linfo_string1: + .asciz "debug.c" +.Linfo_string2: + .asciz "/work/scratch" +.Linfo_string3: + .asciz "bar" +.Linfo_string4: + .asciz "int" +.Linfo_string5: + .asciz "baz" +.Linfo_string6: + .asciz "foo" +.Linfo_string7: + .asciz "quxx" +.Linfo_string8: + .asciz "a" +.Linfo_string9: + .asciz "long int" +.Linfo_string10: + .asciz "b" +.Linfo_string11: + .asciz "c" +.Linfo_string12: + .asciz "d" +.Linfo_string13: + .asciz "e" +.Linfo_string14: + .asciz "x" +.Linfo_string15: + .asciz "S" +.Linfo_string16: + .asciz "y" +.Linfo_string17: + .asciz "z" + .section .debug_loc,"",%progbits +.Ldebug_loc0: + .long -1 + .long .Lfunc_begin0 + .long .Lfunc_begin0-.Lfunc_begin0 + .long .Ltmp1-.Lfunc_begin0 + .short 1 + .byte 80 + .long .Ltmp3-.Lfunc_begin0 + .long .Ltmp4-.Lfunc_begin0 + .short 1 + .byte 80 + .long 0 + .long 0 +.Ldebug_loc1: + .long -1 + .long .Lfunc_begin0 + .long .Lfunc_begin0-.Lfunc_begin0 + .long .Ltmp4-.Lfunc_begin0 + .short 1 + .byte 81 + .long 0 + .long 0 +.Ldebug_loc2: + .long -1 + .long .Lfunc_begin0 + .long .Lfunc_begin0-.Lfunc_begin0 + .long .Ltmp3-.Lfunc_begin0 + .short 1 + .byte 82 + .long .Ltmp3-.Lfunc_begin0 + .long .Ltmp7-.Lfunc_begin0 + .short 1 + .byte 84 + .long 0 + .long 0 +.Ldebug_loc3: + .long -1 + .long .Lfunc_begin0 + .long .Ltmp1-.Lfunc_begin0 + .long .Ltmp2-.Lfunc_begin0 + .short 1 + .byte 80 + .long .Ltmp2-.Lfunc_begin0 + .long .Ltmp5-.Lfunc_begin0 + .short 2 + .byte 125 + .byte 4 + .long .Ltmp5-.Lfunc_begin0 + .long .Ltmp6-.Lfunc_begin0 + .short 1 + .byte 80 + .long 0 + .long 0 +.Ldebug_loc4: + .long -1 + .long .Lfunc_begin0 + .long .Ltmp6-.Lfunc_begin0 + .long .Lfunc_end0-.Lfunc_begin0 + .short 1 + .byte 80 + .long 0 + .long 0 +.Ldebug_loc5: + .long -1 + .long .Lfunc_begin1 + .long .Lfunc_begin1-.Lfunc_begin1 + .long .Ltmp8-.Lfunc_begin1 + .short 6 + .byte 80 + .byte 147 + .byte 4 + .byte 81 + .byte 147 + .byte 4 + .long .Ltmp8-.Lfunc_begin1 + .long .Lfunc_end1-.Lfunc_begin1 + .short 5 + .byte 147 + .byte 4 + .byte 81 + .byte 147 + .byte 4 + .long 0 + .long 0 +.Ldebug_loc6: + .long -1 + .long .Lfunc_begin1 + .long .Ltmp8-.Lfunc_begin1 + .long .Lfunc_end1-.Lfunc_begin1 + .short 1 + .byte 80 + .long 0 + .long 0 +.Ldebug_loc7: + .long -1 + .long .Lfunc_begin2 + .long .Lfunc_begin2-.Lfunc_begin2 + .long .Ltmp10-.Lfunc_begin2 + .short 1 + .byte 80 + .long 0 + .long 0 +.Ldebug_loc8: + .long -1 + .long .Lfunc_begin2 + .long .Lfunc_begin2-.Lfunc_begin2 + .long .Ltmp10-.Lfunc_begin2 + .short 1 + .byte 81 + .long 0 + .long 0 +.Ldebug_loc9: + .long -1 + .long .Lfunc_begin2 + .long .Ltmp11-.Lfunc_begin2 + .long .Lfunc_end2-.Lfunc_begin2 + .short 1 + .byte 80 + .long 0 + .long 0 + .section .debug_abbrev,"",%progbits + .byte 1 + .byte 17 + .byte 1 + .byte 37 + .byte 14 + .byte 19 + .byte 5 + .byte 3 + .byte 14 + .byte 16 + .byte 23 + .byte 27 + .byte 14 + .byte 17 + .byte 1 + .byte 85 + .byte 23 + .byte 0 + .byte 0 + .byte 2 + .byte 46 + .byte 1 + .byte 3 + .byte 14 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 39 + .byte 25 + .byte 60 + .byte 25 + .byte 63 + .byte 25 + .byte 0 + .byte 0 + .byte 3 + .byte 5 + .byte 0 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 4 + .byte 15 + .byte 0 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 5 + .byte 36 + .byte 0 + .byte 3 + .byte 14 + .byte 62 + .byte 11 + .byte 11 + .byte 11 + .byte 0 + .byte 0 + .byte 6 + .byte 46 + .byte 1 + .byte 17 + .byte 1 + .byte 18 + .byte 6 + .byte 64 + .byte 24 + .ascii "\227B" + .byte 25 + .byte 3 + .byte 14 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 39 + .byte 25 + .byte 73 + .byte 19 + .byte 63 + .byte 25 + .byte 0 + .byte 0 + .byte 7 + .byte 5 + .byte 0 + .byte 2 + .byte 23 + .byte 3 + .byte 14 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 8 + .byte 52 + .byte 0 + .byte 2 + .byte 23 + .byte 3 + .byte 14 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 9 + .ascii "\211\202\001" + .byte 0 + .byte 49 + .byte 19 + .byte 17 + .byte 1 + .byte 0 + .byte 0 + .byte 10 + .byte 5 + .byte 0 + .byte 2 + .byte 24 + .byte 3 + .byte 14 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 11 + .byte 19 + .byte 1 + .byte 3 + .byte 14 + .byte 11 + .byte 11 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 0 + .byte 0 + .byte 12 + .byte 13 + .byte 0 + .byte 3 + .byte 14 + .byte 73 + .byte 19 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 56 + .byte 11 + .byte 0 + .byte 0 + .byte 0 + .section .debug_info,"",%progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 +.Ldebug_info_start0: + .short 4 + .long .debug_abbrev + .byte 4 + .byte 1 + .long .Linfo_string0 + .short 12 + .long .Linfo_string1 + .long .Lline_table_start0 + .long .Linfo_string2 + .long 0 + .long .Ldebug_ranges0 + .byte 2 + .long .Linfo_string3 + .byte 1 + .byte 1 + + + + .byte 3 + .long 51 + .byte 0 + .byte 4 + .long 56 + .byte 5 + .long .Linfo_string4 + .byte 5 + .byte 4 + .byte 6 + .long .Lfunc_begin0 + .long .Lfunc_end0-.Lfunc_begin0 + .byte 1 + .byte 91 + + .long .Linfo_string5 + .byte 1 + .byte 2 + + .long 56 + + .byte 7 + .long .Ldebug_loc0 + .long .Linfo_string8 + .byte 1 + .byte 2 + .long 342 + .byte 7 + .long .Ldebug_loc1 + .long .Linfo_string10 + .byte 1 + .byte 2 + .long 56 + .byte 7 + .long .Ldebug_loc2 + .long .Linfo_string11 + .byte 1 + .byte 2 + .long 56 + .byte 8 + .long .Ldebug_loc3 + .long .Linfo_string12 + .byte 1 + .byte 3 + .long 56 + .byte 8 + .long .Ldebug_loc4 + .long .Linfo_string13 + .byte 1 + .byte 5 + .long 56 + .byte 9 + .long 38 + .long .Ltmp4 + .byte 0 + .byte 6 + .long .Lfunc_begin1 + .long .Lfunc_end1-.Lfunc_begin1 + .byte 1 + .byte 91 + + .long .Linfo_string6 + .byte 1 + .byte 13 + + .long 56 + + .byte 7 + .long .Ldebug_loc5 + .long .Linfo_string14 + .byte 1 + .byte 13 + .long 349 + .byte 8 + .long .Ldebug_loc6 + .long .Linfo_string16 + .byte 1 + .byte 14 + .long 56 + .byte 0 + .byte 6 + .long .Lfunc_begin2 + .long .Lfunc_end2-.Lfunc_begin2 + .byte 1 + .byte 91 + + .long .Linfo_string7 + .byte 1 + .byte 18 + + .long 56 + + .byte 7 + .long .Ldebug_loc7 + .long .Linfo_string8 + .byte 1 + .byte 18 + .long 56 + .byte 7 + .long .Ldebug_loc8 + .long .Linfo_string10 + .byte 1 + .byte 18 + .long 56 + .byte 10 + .byte 1 + .byte 82 + .long .Linfo_string11 + .byte 1 + .byte 18 + .long 56 + .byte 10 + .byte 1 + .byte 83 + .long .Linfo_string12 + .byte 1 + .byte 18 + .long 56 + .byte 10 + .byte 2 + .byte 125 + .byte 0 + .long .Linfo_string14 + .byte 1 + .byte 18 + .long 56 + .byte 10 + .byte 2 + .byte 125 + .byte 4 + .long .Linfo_string16 + .byte 1 + .byte 18 + .long 56 + .byte 8 + .long .Ldebug_loc9 + .long .Linfo_string17 + .byte 1 + .byte 19 + .long 56 + .byte 0 + .byte 5 + .long .Linfo_string9 + .byte 5 + .byte 4 + .byte 11 + .long .Linfo_string15 + .byte 8 + .byte 1 + .byte 9 + .byte 12 + .long .Linfo_string8 + .long 56 + .byte 1 + .byte 10 + .byte 0 + .byte 12 + .long .Linfo_string10 + .long 56 + .byte 1 + .byte 11 + .byte 4 + .byte 0 + .byte 0 +.Ldebug_info_end0: + .section .debug_ranges,"",%progbits +.Ldebug_ranges0: + .long .Lfunc_begin0 + .long .Lfunc_end0 + .long .Lfunc_begin1 + .long .Lfunc_end1 + .long .Lfunc_begin2 + .long .Lfunc_end2 + .long 0 + .long 0 + .ident "clang version 10.0.0 (git@github.com:llvm/llvm-project.git e73f78acd34360f7450b81167d9dc858ccddc262)" + .section ".note.GNU-stack","",%progbits + .addrsig + .eabi_attribute 30, 1 + .section .debug_line,"",%progbits +.Lline_table_start0: diff --git a/llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf4.s b/llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf4.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf4.s @@ -0,0 +1,749 @@ +// RUN: llvm-mc -triple armv8a--none-eabi < %s -filetype=obj | \ +// RUN: llvm-objdump - -d -debug-vars | \ +// RUN: FileCheck %s --check-prefix=RAW +// RUN: llvm-mc -triple armv8a--none-eabi < %s -filetype=obj | \ +// RUN: llvm-objdump - -d -debug-vars -no-show-raw-insn | \ +// RUN: FileCheck %s --check-prefix=NO-RAW + +// Generated with this compile command and source: +// +// clang --target=arm--none-eabi -march=armv7-a -c debug.c -O2 -gdwarf-4 -S -o - +// +// void bar(int*); +// int baz(long a, int b, int c) { +// int d = a + b; +// bar(&d); +// int e = d * c; +// return e; +// } +// +// struct S { +// int a; +// int b; +// }; +// int foo(struct S x) { +// int y = x.a + x.b; +// return y; +// } +// +// int quxx(int a, int b, int c, int d, int x, int y) { +// int z = x + y; +// return z; +// } + +// RAW: Disassembly of section .text: +// RAW-EMPTY: +// RAW: 00000000 baz: +// RAW: line 2, column 0 ┠─ b = R1 +// RAW: ┃ ┠─ a = R0 +// RAW: ┃ ┃ ┠─ c = R2 +// RAW: 0: 10 4c 2d e9 push {r4, r10, r11, lr} ┃ ┃ ┃ +// RAW: 4: 08 b0 8d e2 add r11, sp, #8 ┃ ┃ ┃ +// RAW: 8: 08 d0 4d e2 sub sp, sp, #8 ┃ ┃ ┃ +// RAW: line 3, column 13 ┃ ┃ ┌─ d = R0 +// RAW: c: 00 00 81 e0 add r0, r1, r0 ┃ ┻ ╈ ┃ +// RAW: ┃ ┌─ d = [SP+4] +// RAW: 10: 04 00 8d e5 str r0, [sp, #4] ┃ ╈ ┻ ┃ +// RAW: line 0, column 7 ┃ ┃ ┃ +// RAW: 14: 04 00 8d e2 add r0, sp, #4 ┃ ┃ ┃ +// RAW: ┃ ┃ ┌─ a = R0 +// RAW: ┃ ┃ │ ┃ ┌─ c = R4 +// RAW: 18: 02 40 a0 e1 mov r4, r2 ┃ ┃ ╈ ┻ ╈ +// RAW: line 4, column 3 ┃ ┃ ┃ ┃ +// RAW: 1c: fe ff ff eb bl #-8 ┻ ┃ ┻ ┃ +// RAW: line 5, column 11 ┌─ d = R0 ┃ +// RAW: 20: 04 00 9d e5 ldr r0, [sp, #4] ╈ ┻ ┃ +// RAW: ┃ ┌─ e = R0 +// RAW: 24: 90 04 00 e0 mul r0, r0, r4 ┻ ╈ ┃ +// RAW: line 6, column 3 ┃ ┃ +// RAW: 28: 08 d0 4b e2 sub sp, r11, #8 ┃ ┃ +// RAW: 2c: 10 8c bd e8 pop {r4, r10, r11, pc} ┻ ┻ +// RAW-EMPTY: +// RAW: 00000030 foo: +// RAW: line 13, column 0 ┠─ x = [0,4): R0 [4,8): R1 +// RAW: ┃ ┌─ x = [0,4): ??? [4,8): R1 +// RAW: ┃ │ ┌─ y = R0 +// RAW: 30: 01 00 80 e0 add r0, r0, r1 ┻ ╈ ╈ +// RAW: line 15, column 3 ┃ ┃ +// RAW: 34: 1e ff 2f e1 bx lr ┻ ┻ +// RAW-EMPTY: +// RAW: 00000038 quxx: +// RAW: line 18, column 0 ┠─ a = R0 ┃ +// RAW: ┃ ┠─ b = R1 +// RAW: ┃ ┃ ┠─ c = R2 +// RAW: ┃ ┃ ┃ ┠─ d = R3 +// RAW: ┃ ┃ ┃ ┃ ┠─ x = [SP] +// RAW: ┃ ┃ ┃ ┃ ┃ ┠─ y = [SP+4] +// RAW: 38: 03 00 9d e8 ldm sp, {r0, r1} ┻ ┻ ┃ ┃ ┃ ┃ +// RAW: line 19, column 13 ┌─ z = R0 ┃ +// RAW: 3c: 00 00 81 e0 add r0, r1, r0 ╈ ┃ ┃ ┃ ┃ +// RAW: line 20, column 3 ┃ ┃ ┃ ┃ ┃ +// RAW: 40: 1e ff 2f e1 bx lr ┻ ┻ ┻ ┻ ┻ + +// NO-RAW: Disassembly of section .text: +// NO-RAW-EMPTY: +// NO-RAW: 00000000 baz: +// NO-RAW: line 2, column 0 ┠─ b = R1 +// NO-RAW: ┃ ┠─ a = R0 +// NO-RAW: ┃ ┃ ┠─ c = R2 +// NO-RAW: 0: push {r4, r10, r11, lr} ┃ ┃ ┃ +// NO-RAW: 4: add r11, sp, #8 ┃ ┃ ┃ +// NO-RAW: 8: sub sp, sp, #8 ┃ ┃ ┃ +// NO-RAW: line 3, column 13 ┃ ┃ ┌─ d = R0 +// NO-RAW: c: add r0, r1, r0 ┃ ┻ ╈ ┃ +// NO-RAW: ┃ ┌─ d = [SP+4] +// NO-RAW: 10: str r0, [sp, #4] ┃ ╈ ┻ ┃ +// NO-RAW: line 0, column 7 ┃ ┃ ┃ +// NO-RAW: 14: add r0, sp, #4 ┃ ┃ ┃ +// NO-RAW: ┃ ┃ ┌─ a = R0 +// NO-RAW: ┃ ┃ │ ┃ ┌─ c = R4 +// NO-RAW: 18: mov r4, r2 ┃ ┃ ╈ ┻ ╈ +// NO-RAW: line 4, column 3 ┃ ┃ ┃ ┃ +// NO-RAW: 1c: bl #-8 ┻ ┃ ┻ ┃ +// NO-RAW: line 5, column 11 ┌─ d = R0 ┃ +// NO-RAW: 20: ldr r0, [sp, #4] ╈ ┻ ┃ +// NO-RAW: ┃ ┌─ e = R0 +// NO-RAW: 24: mul r0, r0, r4 ┻ ╈ ┃ +// NO-RAW: line 6, column 3 ┃ ┃ +// NO-RAW: 28: sub sp, r11, #8 ┃ ┃ +// NO-RAW: 2c: pop {r4, r10, r11, pc} ┻ ┻ +// NO-RAW-EMPTY: +// NO-RAW: 00000030 foo: +// NO-RAW: line 13, column 0 ┠─ x = [0,4): R0 [4,8): R1 +// NO-RAW: ┃ ┌─ x = [0,4): ??? [4,8): R1 +// NO-RAW: ┃ │ ┌─ y = R0 +// NO-RAW: 30: add r0, r0, r1 ┻ ╈ ╈ +// NO-RAW: line 15, column 3 ┃ ┃ +// NO-RAW: 34: bx lr ┻ ┻ +// NO-RAW-EMPTY: +// NO-RAW: 00000038 quxx: +// NO-RAW: line 18, column 0 ┠─ a = R0 ┃ +// NO-RAW: ┃ ┠─ b = R1 +// NO-RAW: ┃ ┃ ┠─ c = R2 +// NO-RAW: ┃ ┃ ┃ ┠─ d = R3 +// NO-RAW: ┃ ┃ ┃ ┃ ┠─ x = [SP] +// NO-RAW: ┃ ┃ ┃ ┃ ┃ ┠─ y = [SP+4] +// NO-RAW: 38: ldm sp, {r0, r1} ┻ ┻ ┃ ┃ ┃ ┃ +// NO-RAW: line 19, column 13 ┌─ z = R0 ┃ +// NO-RAW: 3c: add r0, r1, r0 ╈ ┃ ┃ ┃ ┃ +// NO-RAW: line 20, column 3 ┃ ┃ ┃ ┃ ┃ +// NO-RAW: 40: bx lr ┻ ┻ ┻ ┻ ┻ + + .text + .syntax unified + .eabi_attribute 67, "2.09" + .eabi_attribute 6, 10 + .eabi_attribute 7, 65 + .eabi_attribute 8, 1 + .eabi_attribute 9, 2 + .fpu neon + .eabi_attribute 34, 0 + .eabi_attribute 17, 1 + .eabi_attribute 20, 1 + .eabi_attribute 21, 1 + .eabi_attribute 23, 3 + .eabi_attribute 24, 1 + .eabi_attribute 25, 1 + .eabi_attribute 38, 1 + .eabi_attribute 18, 4 + .eabi_attribute 26, 2 + .eabi_attribute 14, 0 + .file "debug.c" + .file 1 "/work/scratch" "debug.c" + .globl baz + .p2align 2 + .type baz,%function + .code 32 +baz: +.Lfunc_begin0: + .loc 1 2 0 + .fnstart + .cfi_sections .debug_frame + .cfi_startproc + .save {r4, r10, r11, lr} + push {r4, r10, r11, lr} + .cfi_def_cfa_offset 16 + .cfi_offset lr, -4 + .cfi_offset r11, -8 + .cfi_offset r10, -12 + .cfi_offset r4, -16 + .setfp r11, sp, #8 + add r11, sp, #8 + .cfi_def_cfa r11, 8 + .pad #8 + sub sp, sp, #8 +.Ltmp0: + .loc 1 3 13 prologue_end + add r0, r1, r0 +.Ltmp1: + .loc 1 3 7 is_stmt 0 + str r0, [sp, #4] +.Ltmp2: + .loc 1 0 7 + add r0, sp, #4 + mov r4, r2 +.Ltmp3: + .loc 1 4 3 is_stmt 1 + bl bar +.Ltmp4: + .loc 1 5 11 + ldr r0, [sp, #4] +.Ltmp5: + .loc 1 5 13 is_stmt 0 + mul r0, r0, r4 +.Ltmp6: + .loc 1 6 3 is_stmt 1 + sub sp, r11, #8 + pop {r4, r10, r11, pc} +.Ltmp7: +.Lfunc_end0: + .size baz, .Lfunc_end0-baz + .cfi_endproc + .cantunwind + .fnend + + .globl foo + .p2align 2 + .type foo,%function + .code 32 +foo: +.Lfunc_begin1: + .loc 1 13 0 + .fnstart + .cfi_startproc + .loc 1 14 15 prologue_end + add r0, r0, r1 +.Ltmp8: + .loc 1 15 3 + bx lr +.Ltmp9: +.Lfunc_end1: + .size foo, .Lfunc_end1-foo + .cfi_endproc + .cantunwind + .fnend + + .globl quxx + .p2align 2 + .type quxx,%function + .code 32 +quxx: +.Lfunc_begin2: + .loc 1 18 0 + .fnstart + .cfi_startproc + ldm sp, {r0, r1} +.Ltmp10: + .loc 1 19 13 prologue_end + add r0, r1, r0 +.Ltmp11: + .loc 1 20 3 + bx lr +.Ltmp12: +.Lfunc_end2: + .size quxx, .Lfunc_end2-quxx + .cfi_endproc + .cantunwind + .fnend + + .section .debug_str,"MS",%progbits,1 +.Linfo_string0: + .asciz "clang version 10.0.0 (git@github.com:llvm/llvm-project.git e73f78acd34360f7450b81167d9dc858ccddc262)" +.Linfo_string1: + .asciz "debug.c" +.Linfo_string2: + .asciz "/work/scratch" +.Linfo_string3: + .asciz "bar" +.Linfo_string4: + .asciz "int" +.Linfo_string5: + .asciz "baz" +.Linfo_string6: + .asciz "foo" +.Linfo_string7: + .asciz "quxx" +.Linfo_string8: + .asciz "a" +.Linfo_string9: + .asciz "long int" +.Linfo_string10: + .asciz "b" +.Linfo_string11: + .asciz "c" +.Linfo_string12: + .asciz "d" +.Linfo_string13: + .asciz "e" +.Linfo_string14: + .asciz "x" +.Linfo_string15: + .asciz "S" +.Linfo_string16: + .asciz "y" +.Linfo_string17: + .asciz "z" + .section .debug_loc,"",%progbits +.Ldebug_loc0: + .long .Lfunc_begin0-.Lfunc_begin0 + .long .Ltmp1-.Lfunc_begin0 + .short 1 + .byte 80 + .long .Ltmp3-.Lfunc_begin0 + .long .Ltmp4-.Lfunc_begin0 + .short 1 + .byte 80 + .long 0 + .long 0 +.Ldebug_loc1: + .long .Lfunc_begin0-.Lfunc_begin0 + .long .Ltmp4-.Lfunc_begin0 + .short 1 + .byte 81 + .long 0 + .long 0 +.Ldebug_loc2: + .long .Lfunc_begin0-.Lfunc_begin0 + .long .Ltmp3-.Lfunc_begin0 + .short 1 + .byte 82 + .long .Ltmp3-.Lfunc_begin0 + .long .Ltmp7-.Lfunc_begin0 + .short 1 + .byte 84 + .long 0 + .long 0 +.Ldebug_loc3: + .long .Ltmp1-.Lfunc_begin0 + .long .Ltmp2-.Lfunc_begin0 + .short 1 + .byte 80 + .long .Ltmp2-.Lfunc_begin0 + .long .Ltmp5-.Lfunc_begin0 + .short 2 + .byte 125 + .byte 4 + .long .Ltmp5-.Lfunc_begin0 + .long .Ltmp6-.Lfunc_begin0 + .short 1 + .byte 80 + .long 0 + .long 0 +.Ldebug_loc4: + .long .Ltmp6-.Lfunc_begin0 + .long .Lfunc_end0-.Lfunc_begin0 + .short 1 + .byte 80 + .long 0 + .long 0 +.Ldebug_loc5: + .long .Lfunc_begin1-.Lfunc_begin0 + .long .Ltmp8-.Lfunc_begin0 + .short 6 + .byte 80 + .byte 147 + .byte 4 + .byte 81 + .byte 147 + .byte 4 + .long .Ltmp8-.Lfunc_begin0 + .long .Lfunc_end1-.Lfunc_begin0 + .short 5 + .byte 147 + .byte 4 + .byte 81 + .byte 147 + .byte 4 + .long 0 + .long 0 +.Ldebug_loc6: + .long .Ltmp8-.Lfunc_begin0 + .long .Lfunc_end1-.Lfunc_begin0 + .short 1 + .byte 80 + .long 0 + .long 0 +.Ldebug_loc7: + .long .Lfunc_begin2-.Lfunc_begin0 + .long .Ltmp10-.Lfunc_begin0 + .short 1 + .byte 80 + .long 0 + .long 0 +.Ldebug_loc8: + .long .Lfunc_begin2-.Lfunc_begin0 + .long .Ltmp10-.Lfunc_begin0 + .short 1 + .byte 81 + .long 0 + .long 0 +.Ldebug_loc9: + .long .Ltmp11-.Lfunc_begin0 + .long .Lfunc_end2-.Lfunc_begin0 + .short 1 + .byte 80 + .long 0 + .long 0 + .section .debug_abbrev,"",%progbits + .byte 1 + .byte 17 + .byte 1 + .byte 37 + .byte 14 + .byte 19 + .byte 5 + .byte 3 + .byte 14 + .byte 16 + .byte 23 + .byte 27 + .byte 14 + .byte 17 + .byte 1 + .byte 18 + .byte 6 + .byte 0 + .byte 0 + .byte 2 + .byte 46 + .byte 1 + .byte 3 + .byte 14 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 39 + .byte 25 + .byte 60 + .byte 25 + .byte 63 + .byte 25 + .byte 0 + .byte 0 + .byte 3 + .byte 5 + .byte 0 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 4 + .byte 15 + .byte 0 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 5 + .byte 36 + .byte 0 + .byte 3 + .byte 14 + .byte 62 + .byte 11 + .byte 11 + .byte 11 + .byte 0 + .byte 0 + .byte 6 + .byte 46 + .byte 1 + .byte 17 + .byte 1 + .byte 18 + .byte 6 + .byte 64 + .byte 24 + .ascii "\227B" + .byte 25 + .byte 3 + .byte 14 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 39 + .byte 25 + .byte 73 + .byte 19 + .byte 63 + .byte 25 + .byte 0 + .byte 0 + .byte 7 + .byte 5 + .byte 0 + .byte 2 + .byte 23 + .byte 3 + .byte 14 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 8 + .byte 52 + .byte 0 + .byte 2 + .byte 23 + .byte 3 + .byte 14 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 9 + .ascii "\211\202\001" + .byte 0 + .byte 49 + .byte 19 + .byte 17 + .byte 1 + .byte 0 + .byte 0 + .byte 10 + .byte 5 + .byte 0 + .byte 2 + .byte 24 + .byte 3 + .byte 14 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 11 + .byte 19 + .byte 1 + .byte 3 + .byte 14 + .byte 11 + .byte 11 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 0 + .byte 0 + .byte 12 + .byte 13 + .byte 0 + .byte 3 + .byte 14 + .byte 73 + .byte 19 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 56 + .byte 11 + .byte 0 + .byte 0 + .byte 0 + .section .debug_info,"",%progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 +.Ldebug_info_start0: + .short 4 + .long .debug_abbrev + .byte 4 + .byte 1 + .long .Linfo_string0 + .short 12 + .long .Linfo_string1 + .long .Lline_table_start0 + .long .Linfo_string2 + .long .Lfunc_begin0 + .long .Lfunc_end2-.Lfunc_begin0 + .byte 2 + .long .Linfo_string3 + .byte 1 + .byte 1 + + + + .byte 3 + .long 51 + .byte 0 + .byte 4 + .long 56 + .byte 5 + .long .Linfo_string4 + .byte 5 + .byte 4 + .byte 6 + .long .Lfunc_begin0 + .long .Lfunc_end0-.Lfunc_begin0 + .byte 1 + .byte 91 + + .long .Linfo_string5 + .byte 1 + .byte 2 + + .long 56 + + .byte 7 + .long .Ldebug_loc0 + .long .Linfo_string8 + .byte 1 + .byte 2 + .long 342 + .byte 7 + .long .Ldebug_loc1 + .long .Linfo_string10 + .byte 1 + .byte 2 + .long 56 + .byte 7 + .long .Ldebug_loc2 + .long .Linfo_string11 + .byte 1 + .byte 2 + .long 56 + .byte 8 + .long .Ldebug_loc3 + .long .Linfo_string12 + .byte 1 + .byte 3 + .long 56 + .byte 8 + .long .Ldebug_loc4 + .long .Linfo_string13 + .byte 1 + .byte 5 + .long 56 + .byte 9 + .long 38 + .long .Ltmp4 + .byte 0 + .byte 6 + .long .Lfunc_begin1 + .long .Lfunc_end1-.Lfunc_begin1 + .byte 1 + .byte 91 + + .long .Linfo_string6 + .byte 1 + .byte 13 + + .long 56 + + .byte 7 + .long .Ldebug_loc5 + .long .Linfo_string14 + .byte 1 + .byte 13 + .long 349 + .byte 8 + .long .Ldebug_loc6 + .long .Linfo_string16 + .byte 1 + .byte 14 + .long 56 + .byte 0 + .byte 6 + .long .Lfunc_begin2 + .long .Lfunc_end2-.Lfunc_begin2 + .byte 1 + .byte 91 + + .long .Linfo_string7 + .byte 1 + .byte 18 + + .long 56 + + .byte 7 + .long .Ldebug_loc7 + .long .Linfo_string8 + .byte 1 + .byte 18 + .long 56 + .byte 7 + .long .Ldebug_loc8 + .long .Linfo_string10 + .byte 1 + .byte 18 + .long 56 + .byte 10 + .byte 1 + .byte 82 + .long .Linfo_string11 + .byte 1 + .byte 18 + .long 56 + .byte 10 + .byte 1 + .byte 83 + .long .Linfo_string12 + .byte 1 + .byte 18 + .long 56 + .byte 10 + .byte 2 + .byte 125 + .byte 0 + .long .Linfo_string14 + .byte 1 + .byte 18 + .long 56 + .byte 10 + .byte 2 + .byte 125 + .byte 4 + .long .Linfo_string16 + .byte 1 + .byte 18 + .long 56 + .byte 8 + .long .Ldebug_loc9 + .long .Linfo_string17 + .byte 1 + .byte 19 + .long 56 + .byte 0 + .byte 5 + .long .Linfo_string9 + .byte 5 + .byte 4 + .byte 11 + .long .Linfo_string15 + .byte 8 + .byte 1 + .byte 9 + .byte 12 + .long .Linfo_string8 + .long 56 + .byte 1 + .byte 10 + .byte 0 + .byte 12 + .long .Linfo_string10 + .long 56 + .byte 1 + .byte 11 + .byte 4 + .byte 0 + .byte 0 +.Ldebug_info_end0: + .ident "clang version 10.0.0 (git@github.com:llvm/llvm-project.git e73f78acd34360f7450b81167d9dc858ccddc262)" + .section ".note.GNU-stack","",%progbits + .addrsig + .eabi_attribute 30, 1 + .section .debug_line,"",%progbits +.Lline_table_start0: diff --git a/llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf5-sections.s b/llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf5-sections.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf5-sections.s @@ -0,0 +1,866 @@ +// RUN: llvm-mc -triple armv8a--none-eabi < %s -filetype=obj --dwarf-version=5 | \ +// RUN: llvm-objdump - -d -debug-vars | \ +// RUN: FileCheck %s --check-prefix=RAW +// RUN: llvm-mc -triple armv8a--none-eabi < %s -filetype=obj --dwarf-version=5 | \ +// RUN: llvm-objdump - -d -debug-vars -no-show-raw-insn | \ +// RUN: FileCheck %s --check-prefix=NO-RAW + +// Generated with this compile command and source: +// +// clang --target=arm--none-eabi -march=armv7-a -c debug.c -O2 -gdwarf-4 -S -o - -ffunction-sections +// +// void bar(int*); +// int baz(long a, int b, int c) { +// int d = a + b; +// bar(&d); +// int e = d * c; +// return e; +// } +// +// struct S { +// int a; +// int b; +// }; +// int foo(struct S x) { +// int y = x.a + x.b; +// return y; +// } +// +// int quxx(int a, int b, int c, int d, int x, int y) { +// int z = x + y; +// return z; +// } + +// RAW: Disassembly of section .text.baz: +// RAW-EMPTY: +// RAW: 00000000 baz: +// RAW: line 2, column 0 ┠─ b = R1 +// RAW: ┃ ┠─ a = R0 +// RAW: ┃ ┃ ┠─ c = R2 +// RAW: 0: 10 4c 2d e9 push {r4, r10, r11, lr} ┃ ┃ ┃ +// RAW: 4: 08 b0 8d e2 add r11, sp, #8 ┃ ┃ ┃ +// RAW: 8: 08 d0 4d e2 sub sp, sp, #8 ┃ ┃ ┃ +// RAW: line 3, column 13 ┃ ┃ ┌─ d = R0 +// RAW: c: 00 00 81 e0 add r0, r1, r0 ┃ ┻ ╈ ┃ +// RAW: ┃ ┌─ d = [SP+4] +// RAW: 10: 04 00 8d e5 str r0, [sp, #4] ┃ ╈ ┻ ┃ +// RAW: line 0, column 7 ┃ ┃ ┃ +// RAW: 14: 04 00 8d e2 add r0, sp, #4 ┃ ┃ ┃ +// RAW: ┃ ┃ ┌─ a = R0 +// RAW: ┃ ┃ │ ┃ ┌─ c = R4 +// RAW: 18: 02 40 a0 e1 mov r4, r2 ┃ ┃ ╈ ┻ ╈ +// RAW: line 4, column 3 ┃ ┃ ┃ ┃ +// RAW: 1c: fe ff ff eb bl #-8 ┻ ┃ ┻ ┃ +// RAW: line 5, column 11 ┌─ d = R0 ┃ +// RAW: 20: 04 00 9d e5 ldr r0, [sp, #4] ╈ ┻ ┃ +// RAW: ┃ ┌─ e = R0 +// RAW: 24: 90 04 00 e0 mul r0, r0, r4 ┻ ╈ ┃ +// RAW: line 6, column 3 ┃ ┃ +// RAW: 28: 08 d0 4b e2 sub sp, r11, #8 ┃ ┃ +// RAW: 2c: 10 8c bd e8 pop {r4, r10, r11, pc} ┻ ┻ +// RAW-EMPTY: +// RAW: Disassembly of section .text.foo: +// RAW-EMPTY: +// RAW: 00000000 foo: +// RAW: line 13, column 0 ┠─ x = [0,4): R0 [4,8): R1 +// RAW: ┃ ┌─ x = [0,4): ??? [4,8): R1 +// RAW: ┃ │ ┌─ y = R0 +// RAW: 0: 01 00 80 e0 add r0, r0, r1 ┻ ╈ ╈ +// RAW: line 15, column 3 ┃ ┃ +// RAW: 4: 1e ff 2f e1 bx lr ┻ ┻ +// RAW-EMPTY: +// RAW: Disassembly of section .text.quxx: +// RAW-EMPTY: +// RAW: 00000000 quxx: +// RAW: line 18, column 0 ┠─ a = R0 ┃ +// RAW: ┃ ┠─ b = R1 +// RAW: ┃ ┃ ┠─ c = R2 +// RAW: ┃ ┃ ┃ ┠─ d = R3 +// RAW: ┃ ┃ ┃ ┃ ┠─ x = [SP] +// RAW: ┃ ┃ ┃ ┃ ┃ ┠─ y = [SP+4] +// RAW: 0: 03 00 9d e8 ldm sp, {r0, r1} ┻ ┻ ┃ ┃ ┃ ┃ +// RAW: line 19, column 13 ┌─ z = R0 ┃ +// RAW: 4: 00 00 81 e0 add r0, r1, r0 ╈ ┃ ┃ ┃ ┃ +// RAW: line 20, column 3 ┃ ┃ ┃ ┃ ┃ +// RAW: 8: 1e ff 2f e1 bx lr ┻ ┻ ┻ ┻ ┻ + +// NO-RAW: Disassembly of section .text.baz: +// NO-RAW-EMPTY: +// NO-RAW: 00000000 baz: +// NO-RAW: line 2, column 0 ┠─ b = R1 +// NO-RAW: ┃ ┠─ a = R0 +// NO-RAW: ┃ ┃ ┠─ c = R2 +// NO-RAW: 0: push {r4, r10, r11, lr} ┃ ┃ ┃ +// NO-RAW: 4: add r11, sp, #8 ┃ ┃ ┃ +// NO-RAW: 8: sub sp, sp, #8 ┃ ┃ ┃ +// NO-RAW: line 3, column 13 ┃ ┃ ┌─ d = R0 +// NO-RAW: c: add r0, r1, r0 ┃ ┻ ╈ ┃ +// NO-RAW: ┃ ┌─ d = [SP+4] +// NO-RAW: 10: str r0, [sp, #4] ┃ ╈ ┻ ┃ +// NO-RAW: line 0, column 7 ┃ ┃ ┃ +// NO-RAW: 14: add r0, sp, #4 ┃ ┃ ┃ +// NO-RAW: ┃ ┃ ┌─ a = R0 +// NO-RAW: ┃ ┃ │ ┃ ┌─ c = R4 +// NO-RAW: 18: mov r4, r2 ┃ ┃ ╈ ┻ ╈ +// NO-RAW: line 4, column 3 ┃ ┃ ┃ ┃ +// NO-RAW: 1c: bl #-8 ┻ ┃ ┻ ┃ +// NO-RAW: line 5, column 11 ┌─ d = R0 ┃ +// NO-RAW: 20: ldr r0, [sp, #4] ╈ ┻ ┃ +// NO-RAW: ┃ ┌─ e = R0 +// NO-RAW: 24: mul r0, r0, r4 ┻ ╈ ┃ +// NO-RAW: line 6, column 3 ┃ ┃ +// NO-RAW: 28: sub sp, r11, #8 ┃ ┃ +// NO-RAW: 2c: pop {r4, r10, r11, pc} ┻ ┻ +// NO-RAW-EMPTY: +// NO-RAW: Disassembly of section .text.foo: +// NO-RAW-EMPTY: +// NO-RAW: 00000000 foo: +// NO-RAW: line 13, column 0 ┠─ x = [0,4): R0 [4,8): R1 +// NO-RAW: ┃ ┌─ x = [0,4): ??? [4,8): R1 +// NO-RAW: ┃ │ ┌─ y = R0 +// NO-RAW: 0: add r0, r0, r1 ┻ ╈ ╈ +// NO-RAW: line 15, column 3 ┃ ┃ +// NO-RAW: 4: bx lr ┻ ┻ +// NO-RAW-EMPTY: +// NO-RAW: Disassembly of section .text.quxx: +// NO-RAW-EMPTY: +// NO-RAW: 00000000 quxx: +// NO-RAW: line 18, column 0 ┠─ a = R0 ┃ +// NO-RAW: ┃ ┠─ b = R1 +// NO-RAW: ┃ ┃ ┠─ c = R2 +// NO-RAW: ┃ ┃ ┃ ┠─ d = R3 +// NO-RAW: ┃ ┃ ┃ ┃ ┠─ x = [SP] +// NO-RAW: ┃ ┃ ┃ ┃ ┃ ┠─ y = [SP+4] +// NO-RAW: 0: ldm sp, {r0, r1} ┻ ┻ ┃ ┃ ┃ ┃ +// NO-RAW: line 19, column 13 ┌─ z = R0 ┃ +// NO-RAW: 4: add r0, r1, r0 ╈ ┃ ┃ ┃ ┃ +// NO-RAW: line 20, column 3 ┃ ┃ ┃ ┃ ┃ +// NO-RAW: 8: bx lr ┻ ┻ ┻ ┻ ┻ + + .text + .syntax unified + .eabi_attribute 67, "2.09" + .eabi_attribute 6, 10 + .eabi_attribute 7, 65 + .eabi_attribute 8, 1 + .eabi_attribute 9, 2 + .fpu neon + .eabi_attribute 34, 0 + .eabi_attribute 17, 1 + .eabi_attribute 20, 1 + .eabi_attribute 21, 1 + .eabi_attribute 23, 3 + .eabi_attribute 24, 1 + .eabi_attribute 25, 1 + .eabi_attribute 38, 1 + .eabi_attribute 18, 4 + .eabi_attribute 26, 2 + .eabi_attribute 14, 0 + .file "debug.c" + .file 0 "/work/scratch" "debug.c" md5 0x4c6163a553bc9aedc49d96b4eb628daa + .section .text.baz,"ax",%progbits + .globl baz + .p2align 2 + .type baz,%function + .code 32 +baz: +.Lfunc_begin0: + .loc 0 2 0 + .fnstart + .cfi_sections .debug_frame + .cfi_startproc + .save {r4, r10, r11, lr} + push {r4, r10, r11, lr} + .cfi_def_cfa_offset 16 + .cfi_offset lr, -4 + .cfi_offset r11, -8 + .cfi_offset r10, -12 + .cfi_offset r4, -16 + .setfp r11, sp, #8 + add r11, sp, #8 + .cfi_def_cfa r11, 8 + .pad #8 + sub sp, sp, #8 +.Ltmp0: + .loc 0 3 13 prologue_end + add r0, r1, r0 +.Ltmp1: + .loc 0 3 7 is_stmt 0 + str r0, [sp, #4] +.Ltmp2: + .loc 0 0 7 + add r0, sp, #4 + mov r4, r2 +.Ltmp3: + .loc 0 4 3 is_stmt 1 + bl bar +.Ltmp4: + .loc 0 5 11 + ldr r0, [sp, #4] +.Ltmp5: + .loc 0 5 13 is_stmt 0 + mul r0, r0, r4 +.Ltmp6: + .loc 0 6 3 is_stmt 1 + sub sp, r11, #8 + pop {r4, r10, r11, pc} +.Ltmp7: +.Lfunc_end0: + .size baz, .Lfunc_end0-baz + .cfi_endproc + .cantunwind + .fnend + + .section .text.foo,"ax",%progbits + .globl foo + .p2align 2 + .type foo,%function + .code 32 +foo: +.Lfunc_begin1: + .loc 0 13 0 + .fnstart + .cfi_startproc + .loc 0 14 15 prologue_end + add r0, r0, r1 +.Ltmp8: + .loc 0 15 3 + bx lr +.Ltmp9: +.Lfunc_end1: + .size foo, .Lfunc_end1-foo + .cfi_endproc + .cantunwind + .fnend + + .section .text.quxx,"ax",%progbits + .globl quxx + .p2align 2 + .type quxx,%function + .code 32 +quxx: +.Lfunc_begin2: + .loc 0 18 0 + .fnstart + .cfi_startproc + ldm sp, {r0, r1} +.Ltmp10: + .loc 0 19 13 prologue_end + add r0, r1, r0 +.Ltmp11: + .loc 0 20 3 + bx lr +.Ltmp12: +.Lfunc_end2: + .size quxx, .Lfunc_end2-quxx + .cfi_endproc + .cantunwind + .fnend + + .section .debug_str_offsets,"",%progbits + .long 76 + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",%progbits,1 +.Linfo_string0: + .asciz "clang version 10.0.0 (git@github.com:llvm/llvm-project.git e73f78acd34360f7450b81167d9dc858ccddc262)" +.Linfo_string1: + .asciz "debug.c" +.Linfo_string2: + .asciz "/work/scratch" +.Linfo_string3: + .asciz "bar" +.Linfo_string4: + .asciz "int" +.Linfo_string5: + .asciz "baz" +.Linfo_string6: + .asciz "foo" +.Linfo_string7: + .asciz "quxx" +.Linfo_string8: + .asciz "a" +.Linfo_string9: + .asciz "long int" +.Linfo_string10: + .asciz "b" +.Linfo_string11: + .asciz "c" +.Linfo_string12: + .asciz "d" +.Linfo_string13: + .asciz "e" +.Linfo_string14: + .asciz "x" +.Linfo_string15: + .asciz "S" +.Linfo_string16: + .asciz "y" +.Linfo_string17: + .asciz "z" + .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 + .long .Linfo_string12 + .long .Linfo_string13 + .long .Linfo_string14 + .long .Linfo_string15 + .long .Linfo_string16 + .long .Linfo_string17 + .section .debug_loclists,"",%progbits + .long .Ldebug_loclist_table_end0-.Ldebug_loclist_table_start0 +.Ldebug_loclist_table_start0: + .short 5 + .byte 4 + .byte 0 + .long 10 +.Lloclists_table_base0: + .long .Ldebug_loc0-.Lloclists_table_base0 + .long .Ldebug_loc1-.Lloclists_table_base0 + .long .Ldebug_loc2-.Lloclists_table_base0 + .long .Ldebug_loc3-.Lloclists_table_base0 + .long .Ldebug_loc4-.Lloclists_table_base0 + .long .Ldebug_loc5-.Lloclists_table_base0 + .long .Ldebug_loc6-.Lloclists_table_base0 + .long .Ldebug_loc7-.Lloclists_table_base0 + .long .Ldebug_loc8-.Lloclists_table_base0 + .long .Ldebug_loc9-.Lloclists_table_base0 +.Ldebug_loc0: + .byte 1 + .byte 0 + .byte 4 + .uleb128 .Lfunc_begin0-.Lfunc_begin0 + .uleb128 .Ltmp1-.Lfunc_begin0 + .byte 1 + .byte 80 + .byte 4 + .uleb128 .Ltmp3-.Lfunc_begin0 + .uleb128 .Ltmp4-.Lfunc_begin0 + .byte 1 + .byte 80 + .byte 0 +.Ldebug_loc1: + .byte 3 + .byte 0 + .uleb128 .Ltmp4-.Lfunc_begin0 + .byte 1 + .byte 81 + .byte 0 +.Ldebug_loc2: + .byte 1 + .byte 0 + .byte 4 + .uleb128 .Lfunc_begin0-.Lfunc_begin0 + .uleb128 .Ltmp3-.Lfunc_begin0 + .byte 1 + .byte 82 + .byte 4 + .uleb128 .Ltmp3-.Lfunc_begin0 + .uleb128 .Ltmp7-.Lfunc_begin0 + .byte 1 + .byte 84 + .byte 0 +.Ldebug_loc3: + .byte 1 + .byte 0 + .byte 4 + .uleb128 .Ltmp1-.Lfunc_begin0 + .uleb128 .Ltmp2-.Lfunc_begin0 + .byte 1 + .byte 80 + .byte 4 + .uleb128 .Ltmp2-.Lfunc_begin0 + .uleb128 .Ltmp5-.Lfunc_begin0 + .byte 2 + .byte 125 + .byte 4 + .byte 4 + .uleb128 .Ltmp5-.Lfunc_begin0 + .uleb128 .Ltmp6-.Lfunc_begin0 + .byte 1 + .byte 80 + .byte 0 +.Ldebug_loc4: + .byte 1 + .byte 0 + .byte 4 + .uleb128 .Ltmp6-.Lfunc_begin0 + .uleb128 .Lfunc_end0-.Lfunc_begin0 + .byte 1 + .byte 80 + .byte 0 +.Ldebug_loc5: + .byte 1 + .byte 1 + .byte 4 + .uleb128 .Lfunc_begin1-.Lfunc_begin1 + .uleb128 .Ltmp8-.Lfunc_begin1 + .byte 6 + .byte 80 + .byte 147 + .byte 4 + .byte 81 + .byte 147 + .byte 4 + .byte 4 + .uleb128 .Ltmp8-.Lfunc_begin1 + .uleb128 .Lfunc_end1-.Lfunc_begin1 + .byte 5 + .byte 147 + .byte 4 + .byte 81 + .byte 147 + .byte 4 + .byte 0 +.Ldebug_loc6: + .byte 1 + .byte 1 + .byte 4 + .uleb128 .Ltmp8-.Lfunc_begin1 + .uleb128 .Lfunc_end1-.Lfunc_begin1 + .byte 1 + .byte 80 + .byte 0 +.Ldebug_loc7: + .byte 3 + .byte 2 + .uleb128 .Ltmp10-.Lfunc_begin2 + .byte 1 + .byte 80 + .byte 0 +.Ldebug_loc8: + .byte 3 + .byte 2 + .uleb128 .Ltmp10-.Lfunc_begin2 + .byte 1 + .byte 81 + .byte 0 +.Ldebug_loc9: + .byte 1 + .byte 2 + .byte 4 + .uleb128 .Ltmp11-.Lfunc_begin2 + .uleb128 .Lfunc_end2-.Lfunc_begin2 + .byte 1 + .byte 80 + .byte 0 +.Ldebug_loclist_table_end0: + .section .debug_abbrev,"",%progbits + .byte 1 + .byte 17 + .byte 1 + .byte 37 + .byte 37 + .byte 19 + .byte 5 + .byte 3 + .byte 37 + .byte 114 + .byte 23 + .byte 16 + .byte 23 + .byte 27 + .byte 37 + .byte 17 + .byte 1 + .byte 85 + .byte 35 + .byte 115 + .byte 23 + .byte 116 + .byte 23 + .ascii "\214\001" + .byte 23 + .byte 0 + .byte 0 + .byte 2 + .byte 46 + .byte 1 + .byte 3 + .byte 37 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 39 + .byte 25 + .byte 60 + .byte 25 + .byte 63 + .byte 25 + .byte 0 + .byte 0 + .byte 3 + .byte 5 + .byte 0 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 4 + .byte 15 + .byte 0 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 5 + .byte 36 + .byte 0 + .byte 3 + .byte 37 + .byte 62 + .byte 11 + .byte 11 + .byte 11 + .byte 0 + .byte 0 + .byte 6 + .byte 46 + .byte 1 + .byte 17 + .byte 27 + .byte 18 + .byte 6 + .byte 64 + .byte 24 + .byte 122 + .byte 25 + .byte 3 + .byte 37 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 39 + .byte 25 + .byte 73 + .byte 19 + .byte 63 + .byte 25 + .byte 0 + .byte 0 + .byte 7 + .byte 5 + .byte 0 + .byte 2 + .byte 34 + .byte 3 + .byte 37 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 8 + .byte 52 + .byte 0 + .byte 2 + .byte 34 + .byte 3 + .byte 37 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 9 + .byte 72 + .byte 0 + .byte 127 + .byte 19 + .byte 125 + .byte 1 + .byte 0 + .byte 0 + .byte 10 + .byte 5 + .byte 0 + .byte 2 + .byte 24 + .byte 3 + .byte 37 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 11 + .byte 19 + .byte 1 + .byte 3 + .byte 37 + .byte 11 + .byte 11 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 0 + .byte 0 + .byte 12 + .byte 13 + .byte 0 + .byte 3 + .byte 37 + .byte 73 + .byte 19 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 56 + .byte 11 + .byte 0 + .byte 0 + .byte 0 + .section .debug_info,"",%progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 +.Ldebug_info_start0: + .short 5 + .byte 1 + .byte 4 + .long .debug_abbrev + .byte 1 + .byte 0 + .short 12 + .byte 1 + .long .Lstr_offsets_base0 + .long .Lline_table_start0 + .byte 2 + .long 0 + .byte 0 + .long .Laddr_table_base0 + .long .Lrnglists_table_base0 + .long .Lloclists_table_base0 + .byte 2 + .byte 3 + .byte 0 + .byte 1 + + + + .byte 3 + .long 53 + .byte 0 + .byte 4 + .long 58 + .byte 5 + .byte 4 + .byte 5 + .byte 4 + .byte 6 + .byte 0 + .long .Lfunc_end0-.Lfunc_begin0 + .byte 1 + .byte 91 + + .byte 5 + .byte 0 + .byte 2 + + .long 58 + + .byte 7 + .byte 0 + .byte 8 + .byte 0 + .byte 2 + .long 251 + .byte 7 + .byte 1 + .byte 10 + .byte 0 + .byte 2 + .long 58 + .byte 7 + .byte 2 + .byte 11 + .byte 0 + .byte 2 + .long 58 + .byte 8 + .byte 3 + .byte 12 + .byte 0 + .byte 3 + .long 58 + .byte 8 + .byte 4 + .byte 13 + .byte 0 + .byte 5 + .long 58 + .byte 9 + .long 43 + .long .Ltmp4-.Lfunc_begin0 + .byte 0 + .byte 6 + .byte 1 + .long .Lfunc_end1-.Lfunc_begin1 + .byte 1 + .byte 91 + + .byte 6 + .byte 0 + .byte 13 + + .long 58 + + .byte 7 + .byte 5 + .byte 14 + .byte 0 + .byte 13 + .long 255 + .byte 8 + .byte 6 + .byte 16 + .byte 0 + .byte 14 + .long 58 + .byte 0 + .byte 6 + .byte 2 + .long .Lfunc_end2-.Lfunc_begin2 + .byte 1 + .byte 91 + + .byte 7 + .byte 0 + .byte 18 + + .long 58 + + .byte 7 + .byte 7 + .byte 8 + .byte 0 + .byte 18 + .long 58 + .byte 7 + .byte 8 + .byte 10 + .byte 0 + .byte 18 + .long 58 + .byte 10 + .byte 1 + .byte 82 + .byte 11 + .byte 0 + .byte 18 + .long 58 + .byte 10 + .byte 1 + .byte 83 + .byte 12 + .byte 0 + .byte 18 + .long 58 + .byte 10 + .byte 2 + .byte 125 + .byte 0 + .byte 14 + .byte 0 + .byte 18 + .long 58 + .byte 10 + .byte 2 + .byte 125 + .byte 4 + .byte 16 + .byte 0 + .byte 18 + .long 58 + .byte 8 + .byte 9 + .byte 17 + .byte 0 + .byte 19 + .long 58 + .byte 0 + .byte 5 + .byte 9 + .byte 5 + .byte 4 + .byte 11 + .byte 15 + .byte 8 + .byte 0 + .byte 9 + .byte 12 + .byte 8 + .long 58 + .byte 0 + .byte 10 + .byte 0 + .byte 12 + .byte 10 + .long 58 + .byte 0 + .byte 11 + .byte 4 + .byte 0 + .byte 0 +.Ldebug_info_end0: + .section .debug_rnglists,"",%progbits + .long .Ldebug_rnglist_table_end0-.Ldebug_rnglist_table_start0 +.Ldebug_rnglist_table_start0: + .short 5 + .byte 4 + .byte 0 + .long 1 +.Lrnglists_table_base0: + .long .Ldebug_ranges0-.Lrnglists_table_base0 +.Ldebug_ranges0: + .byte 3 + .byte 0 + .uleb128 .Lfunc_end0-.Lfunc_begin0 + .byte 3 + .byte 1 + .uleb128 .Lfunc_end1-.Lfunc_begin1 + .byte 3 + .byte 2 + .uleb128 .Lfunc_end2-.Lfunc_begin2 + .byte 0 +.Ldebug_rnglist_table_end0: + .section .debug_addr,"",%progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 +.Ldebug_addr_start0: + .short 5 + .byte 4 + .byte 0 +.Laddr_table_base0: + .long .Lfunc_begin0 + .long .Lfunc_begin1 + .long .Lfunc_begin2 +.Ldebug_addr_end0: + .ident "clang version 10.0.0 (git@github.com:llvm/llvm-project.git e73f78acd34360f7450b81167d9dc858ccddc262)" + .section ".note.GNU-stack","",%progbits + .addrsig + .eabi_attribute 30, 1 + .section .debug_line,"",%progbits +.Lline_table_start0: diff --git a/llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf5.s b/llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf5.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf5.s @@ -0,0 +1,817 @@ +// RUN: llvm-mc -triple armv8a--none-eabi < %s -filetype=obj --dwarf-version=5 | \ +// RUN: llvm-objdump - -d -debug-vars | \ +// RUN: FileCheck %s --check-prefix=RAW +// RUN: llvm-mc -triple armv8a--none-eabi < %s -filetype=obj --dwarf-version=5 | \ +// RUN: llvm-objdump - -d -debug-vars -no-show-raw-insn | \ +// RUN: FileCheck %s --check-prefix=NO-RAW + +// Generated with this compile command and source: +// +// clang --target=arm--none-eabi -march=armv7-a -c debug.c -O2 -gdwarf-5 -S -o - +// +// void bar(int*); +// int baz(long a, int b, int c) { +// int d = a + b; +// bar(&d); +// int e = d * c; +// return e; +// } +// +// struct S { +// int a; +// int b; +// }; +// int foo(struct S x) { +// int y = x.a + x.b; +// return y; +// } +// +// int quxx(int a, int b, int c, int d, int x, int y) { +// int z = x + y; +// return z; +// } + +// RAW: Disassembly of section .text: +// RAW-EMPTY: +// RAW: 00000000 baz: +// RAW: line 2, column 0 ┠─ b = R1 +// RAW: ┃ ┠─ a = R0 +// RAW: ┃ ┃ ┠─ c = R2 +// RAW: 0: 10 4c 2d e9 push {r4, r10, r11, lr} ┃ ┃ ┃ +// RAW: 4: 08 b0 8d e2 add r11, sp, #8 ┃ ┃ ┃ +// RAW: 8: 08 d0 4d e2 sub sp, sp, #8 ┃ ┃ ┃ +// RAW: line 3, column 13 ┃ ┃ ┌─ d = R0 +// RAW: c: 00 00 81 e0 add r0, r1, r0 ┃ ┻ ╈ ┃ +// RAW: ┃ ┌─ d = [SP+4] +// RAW: 10: 04 00 8d e5 str r0, [sp, #4] ┃ ╈ ┻ ┃ +// RAW: line 0, column 7 ┃ ┃ ┃ +// RAW: 14: 04 00 8d e2 add r0, sp, #4 ┃ ┃ ┃ +// RAW: ┃ ┃ ┌─ a = R0 +// RAW: ┃ ┃ │ ┃ ┌─ c = R4 +// RAW: 18: 02 40 a0 e1 mov r4, r2 ┃ ┃ ╈ ┻ ╈ +// RAW: line 4, column 3 ┃ ┃ ┃ ┃ +// RAW: 1c: fe ff ff eb bl #-8 ┻ ┃ ┻ ┃ +// RAW: line 5, column 11 ┌─ d = R0 ┃ +// RAW: 20: 04 00 9d e5 ldr r0, [sp, #4] ╈ ┻ ┃ +// RAW: ┃ ┌─ e = R0 +// RAW: 24: 90 04 00 e0 mul r0, r0, r4 ┻ ╈ ┃ +// RAW: line 6, column 3 ┃ ┃ +// RAW: 28: 08 d0 4b e2 sub sp, r11, #8 ┃ ┃ +// RAW: 2c: 10 8c bd e8 pop {r4, r10, r11, pc} ┻ ┻ +// RAW-EMPTY: +// RAW: 00000030 foo: +// RAW: line 13, column 0 ┠─ x = [0,4): R0 [4,8): R1 +// RAW: ┃ ┌─ x = [0,4): ??? [4,8): R1 +// RAW: ┃ │ ┌─ y = R0 +// RAW: 30: 01 00 80 e0 add r0, r0, r1 ┻ ╈ ╈ +// RAW: line 15, column 3 ┃ ┃ +// RAW: 34: 1e ff 2f e1 bx lr ┻ ┻ +// RAW-EMPTY: +// RAW: 00000038 quxx: +// RAW: line 18, column 0 ┠─ a = R0 ┃ +// RAW: ┃ ┠─ b = R1 +// RAW: ┃ ┃ ┠─ c = R2 +// RAW: ┃ ┃ ┃ ┠─ d = R3 +// RAW: ┃ ┃ ┃ ┃ ┠─ x = [SP] +// RAW: ┃ ┃ ┃ ┃ ┃ ┠─ y = [SP+4] +// RAW: 38: 03 00 9d e8 ldm sp, {r0, r1} ┻ ┻ ┃ ┃ ┃ ┃ +// RAW: line 19, column 13 ┌─ z = R0 ┃ +// RAW: 3c: 00 00 81 e0 add r0, r1, r0 ╈ ┃ ┃ ┃ ┃ +// RAW: line 20, column 3 ┃ ┃ ┃ ┃ ┃ +// RAW: 40: 1e ff 2f e1 bx lr ┻ ┻ ┻ ┻ ┻ + +// NO-RAW: Disassembly of section .text: +// NO-RAW-EMPTY: +// NO-RAW: 00000000 baz: +// NO-RAW: line 2, column 0 ┠─ b = R1 +// NO-RAW: ┃ ┠─ a = R0 +// NO-RAW: ┃ ┃ ┠─ c = R2 +// NO-RAW: 0: push {r4, r10, r11, lr} ┃ ┃ ┃ +// NO-RAW: 4: add r11, sp, #8 ┃ ┃ ┃ +// NO-RAW: 8: sub sp, sp, #8 ┃ ┃ ┃ +// NO-RAW: line 3, column 13 ┃ ┃ ┌─ d = R0 +// NO-RAW: c: add r0, r1, r0 ┃ ┻ ╈ ┃ +// NO-RAW: ┃ ┌─ d = [SP+4] +// NO-RAW: 10: str r0, [sp, #4] ┃ ╈ ┻ ┃ +// NO-RAW: line 0, column 7 ┃ ┃ ┃ +// NO-RAW: 14: add r0, sp, #4 ┃ ┃ ┃ +// NO-RAW: ┃ ┃ ┌─ a = R0 +// NO-RAW: ┃ ┃ │ ┃ ┌─ c = R4 +// NO-RAW: 18: mov r4, r2 ┃ ┃ ╈ ┻ ╈ +// NO-RAW: line 4, column 3 ┃ ┃ ┃ ┃ +// NO-RAW: 1c: bl #-8 ┻ ┃ ┻ ┃ +// NO-RAW: line 5, column 11 ┌─ d = R0 ┃ +// NO-RAW: 20: ldr r0, [sp, #4] ╈ ┻ ┃ +// NO-RAW: ┃ ┌─ e = R0 +// NO-RAW: 24: mul r0, r0, r4 ┻ ╈ ┃ +// NO-RAW: line 6, column 3 ┃ ┃ +// NO-RAW: 28: sub sp, r11, #8 ┃ ┃ +// NO-RAW: 2c: pop {r4, r10, r11, pc} ┻ ┻ +// NO-RAW-EMPTY: +// NO-RAW: 00000030 foo: +// NO-RAW: line 13, column 0 ┠─ x = [0,4): R0 [4,8): R1 +// NO-RAW: ┃ ┌─ x = [0,4): ??? [4,8): R1 +// NO-RAW: ┃ │ ┌─ y = R0 +// NO-RAW: 30: add r0, r0, r1 ┻ ╈ ╈ +// NO-RAW: line 15, column 3 ┃ ┃ +// NO-RAW: 34: bx lr ┻ ┻ +// NO-RAW-EMPTY: +// NO-RAW: 00000038 quxx: +// NO-RAW: line 18, column 0 ┠─ a = R0 ┃ +// NO-RAW: ┃ ┠─ b = R1 +// NO-RAW: ┃ ┃ ┠─ c = R2 +// NO-RAW: ┃ ┃ ┃ ┠─ d = R3 +// NO-RAW: ┃ ┃ ┃ ┃ ┠─ x = [SP] +// NO-RAW: ┃ ┃ ┃ ┃ ┃ ┠─ y = [SP+4] +// NO-RAW: 38: ldm sp, {r0, r1} ┻ ┻ ┃ ┃ ┃ ┃ +// NO-RAW: line 19, column 13 ┌─ z = R0 ┃ +// NO-RAW: 3c: add r0, r1, r0 ╈ ┃ ┃ ┃ ┃ +// NO-RAW: line 20, column 3 ┃ ┃ ┃ ┃ ┃ +// NO-RAW: 40: bx lr ┻ ┻ ┻ ┻ ┻ + + .text + .syntax unified + .eabi_attribute 67, "2.09" + .eabi_attribute 6, 10 + .eabi_attribute 7, 65 + .eabi_attribute 8, 1 + .eabi_attribute 9, 2 + .fpu neon + .eabi_attribute 34, 0 + .eabi_attribute 17, 1 + .eabi_attribute 20, 1 + .eabi_attribute 21, 1 + .eabi_attribute 23, 3 + .eabi_attribute 24, 1 + .eabi_attribute 25, 1 + .eabi_attribute 38, 1 + .eabi_attribute 18, 4 + .eabi_attribute 26, 2 + .eabi_attribute 14, 0 + .file "debug.c" + .file 0 "/work/scratch" "debug.c" md5 0x4c6163a553bc9aedc49d96b4eb628daa + .globl baz + .p2align 2 + .type baz,%function + .code 32 +baz: +.Lfunc_begin0: + .loc 0 2 0 + .fnstart + .cfi_sections .debug_frame + .cfi_startproc + .save {r4, r10, r11, lr} + push {r4, r10, r11, lr} + .cfi_def_cfa_offset 16 + .cfi_offset lr, -4 + .cfi_offset r11, -8 + .cfi_offset r10, -12 + .cfi_offset r4, -16 + .setfp r11, sp, #8 + add r11, sp, #8 + .cfi_def_cfa r11, 8 + .pad #8 + sub sp, sp, #8 +.Ltmp0: + .loc 0 3 13 prologue_end + add r0, r1, r0 +.Ltmp1: + .loc 0 3 7 is_stmt 0 + str r0, [sp, #4] +.Ltmp2: + .loc 0 0 7 + add r0, sp, #4 + mov r4, r2 +.Ltmp3: + .loc 0 4 3 is_stmt 1 + bl bar +.Ltmp4: + .loc 0 5 11 + ldr r0, [sp, #4] +.Ltmp5: + .loc 0 5 13 is_stmt 0 + mul r0, r0, r4 +.Ltmp6: + .loc 0 6 3 is_stmt 1 + sub sp, r11, #8 + pop {r4, r10, r11, pc} +.Ltmp7: +.Lfunc_end0: + .size baz, .Lfunc_end0-baz + .cfi_endproc + .cantunwind + .fnend + + .globl foo + .p2align 2 + .type foo,%function + .code 32 +foo: +.Lfunc_begin1: + .loc 0 13 0 + .fnstart + .cfi_startproc + .loc 0 14 15 prologue_end + add r0, r0, r1 +.Ltmp8: + .loc 0 15 3 + bx lr +.Ltmp9: +.Lfunc_end1: + .size foo, .Lfunc_end1-foo + .cfi_endproc + .cantunwind + .fnend + + .globl quxx + .p2align 2 + .type quxx,%function + .code 32 +quxx: +.Lfunc_begin2: + .loc 0 18 0 + .fnstart + .cfi_startproc + ldm sp, {r0, r1} +.Ltmp10: + .loc 0 19 13 prologue_end + add r0, r1, r0 +.Ltmp11: + .loc 0 20 3 + bx lr +.Ltmp12: +.Lfunc_end2: + .size quxx, .Lfunc_end2-quxx + .cfi_endproc + .cantunwind + .fnend + + .section .debug_str_offsets,"",%progbits + .long 76 + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",%progbits,1 +.Linfo_string0: + .asciz "clang version 10.0.0 (git@github.com:llvm/llvm-project.git e73f78acd34360f7450b81167d9dc858ccddc262)" +.Linfo_string1: + .asciz "debug.c" +.Linfo_string2: + .asciz "/work/scratch" +.Linfo_string3: + .asciz "bar" +.Linfo_string4: + .asciz "int" +.Linfo_string5: + .asciz "baz" +.Linfo_string6: + .asciz "foo" +.Linfo_string7: + .asciz "quxx" +.Linfo_string8: + .asciz "a" +.Linfo_string9: + .asciz "long int" +.Linfo_string10: + .asciz "b" +.Linfo_string11: + .asciz "c" +.Linfo_string12: + .asciz "d" +.Linfo_string13: + .asciz "e" +.Linfo_string14: + .asciz "x" +.Linfo_string15: + .asciz "S" +.Linfo_string16: + .asciz "y" +.Linfo_string17: + .asciz "z" + .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 + .long .Linfo_string12 + .long .Linfo_string13 + .long .Linfo_string14 + .long .Linfo_string15 + .long .Linfo_string16 + .long .Linfo_string17 + .section .debug_loclists,"",%progbits + .long .Ldebug_loclist_table_end0-.Ldebug_loclist_table_start0 +.Ldebug_loclist_table_start0: + .short 5 + .byte 4 + .byte 0 + .long 10 +.Lloclists_table_base0: + .long .Ldebug_loc0-.Lloclists_table_base0 + .long .Ldebug_loc1-.Lloclists_table_base0 + .long .Ldebug_loc2-.Lloclists_table_base0 + .long .Ldebug_loc3-.Lloclists_table_base0 + .long .Ldebug_loc4-.Lloclists_table_base0 + .long .Ldebug_loc5-.Lloclists_table_base0 + .long .Ldebug_loc6-.Lloclists_table_base0 + .long .Ldebug_loc7-.Lloclists_table_base0 + .long .Ldebug_loc8-.Lloclists_table_base0 + .long .Ldebug_loc9-.Lloclists_table_base0 +.Ldebug_loc0: + .byte 4 + .uleb128 .Lfunc_begin0-.Lfunc_begin0 + .uleb128 .Ltmp1-.Lfunc_begin0 + .byte 1 + .byte 80 + .byte 4 + .uleb128 .Ltmp3-.Lfunc_begin0 + .uleb128 .Ltmp4-.Lfunc_begin0 + .byte 1 + .byte 80 + .byte 0 +.Ldebug_loc1: + .byte 4 + .uleb128 .Lfunc_begin0-.Lfunc_begin0 + .uleb128 .Ltmp4-.Lfunc_begin0 + .byte 1 + .byte 81 + .byte 0 +.Ldebug_loc2: + .byte 4 + .uleb128 .Lfunc_begin0-.Lfunc_begin0 + .uleb128 .Ltmp3-.Lfunc_begin0 + .byte 1 + .byte 82 + .byte 4 + .uleb128 .Ltmp3-.Lfunc_begin0 + .uleb128 .Ltmp7-.Lfunc_begin0 + .byte 1 + .byte 84 + .byte 0 +.Ldebug_loc3: + .byte 4 + .uleb128 .Ltmp1-.Lfunc_begin0 + .uleb128 .Ltmp2-.Lfunc_begin0 + .byte 1 + .byte 80 + .byte 4 + .uleb128 .Ltmp2-.Lfunc_begin0 + .uleb128 .Ltmp5-.Lfunc_begin0 + .byte 2 + .byte 125 + .byte 4 + .byte 4 + .uleb128 .Ltmp5-.Lfunc_begin0 + .uleb128 .Ltmp6-.Lfunc_begin0 + .byte 1 + .byte 80 + .byte 0 +.Ldebug_loc4: + .byte 4 + .uleb128 .Ltmp6-.Lfunc_begin0 + .uleb128 .Lfunc_end0-.Lfunc_begin0 + .byte 1 + .byte 80 + .byte 0 +.Ldebug_loc5: + .byte 4 + .uleb128 .Lfunc_begin1-.Lfunc_begin0 + .uleb128 .Ltmp8-.Lfunc_begin0 + .byte 6 + .byte 80 + .byte 147 + .byte 4 + .byte 81 + .byte 147 + .byte 4 + .byte 4 + .uleb128 .Ltmp8-.Lfunc_begin0 + .uleb128 .Lfunc_end1-.Lfunc_begin0 + .byte 5 + .byte 147 + .byte 4 + .byte 81 + .byte 147 + .byte 4 + .byte 0 +.Ldebug_loc6: + .byte 4 + .uleb128 .Ltmp8-.Lfunc_begin0 + .uleb128 .Lfunc_end1-.Lfunc_begin0 + .byte 1 + .byte 80 + .byte 0 +.Ldebug_loc7: + .byte 4 + .uleb128 .Lfunc_begin2-.Lfunc_begin0 + .uleb128 .Ltmp10-.Lfunc_begin0 + .byte 1 + .byte 80 + .byte 0 +.Ldebug_loc8: + .byte 4 + .uleb128 .Lfunc_begin2-.Lfunc_begin0 + .uleb128 .Ltmp10-.Lfunc_begin0 + .byte 1 + .byte 81 + .byte 0 +.Ldebug_loc9: + .byte 4 + .uleb128 .Ltmp11-.Lfunc_begin0 + .uleb128 .Lfunc_end2-.Lfunc_begin0 + .byte 1 + .byte 80 + .byte 0 +.Ldebug_loclist_table_end0: + .section .debug_abbrev,"",%progbits + .byte 1 + .byte 17 + .byte 1 + .byte 37 + .byte 37 + .byte 19 + .byte 5 + .byte 3 + .byte 37 + .byte 114 + .byte 23 + .byte 16 + .byte 23 + .byte 27 + .byte 37 + .byte 17 + .byte 27 + .byte 18 + .byte 6 + .byte 115 + .byte 23 + .ascii "\214\001" + .byte 23 + .byte 0 + .byte 0 + .byte 2 + .byte 46 + .byte 1 + .byte 3 + .byte 37 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 39 + .byte 25 + .byte 60 + .byte 25 + .byte 63 + .byte 25 + .byte 0 + .byte 0 + .byte 3 + .byte 5 + .byte 0 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 4 + .byte 15 + .byte 0 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 5 + .byte 36 + .byte 0 + .byte 3 + .byte 37 + .byte 62 + .byte 11 + .byte 11 + .byte 11 + .byte 0 + .byte 0 + .byte 6 + .byte 46 + .byte 1 + .byte 17 + .byte 27 + .byte 18 + .byte 6 + .byte 64 + .byte 24 + .byte 122 + .byte 25 + .byte 3 + .byte 37 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 39 + .byte 25 + .byte 73 + .byte 19 + .byte 63 + .byte 25 + .byte 0 + .byte 0 + .byte 7 + .byte 5 + .byte 0 + .byte 2 + .byte 34 + .byte 3 + .byte 37 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 8 + .byte 52 + .byte 0 + .byte 2 + .byte 34 + .byte 3 + .byte 37 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 9 + .byte 72 + .byte 0 + .byte 127 + .byte 19 + .byte 125 + .byte 1 + .byte 0 + .byte 0 + .byte 10 + .byte 5 + .byte 0 + .byte 2 + .byte 24 + .byte 3 + .byte 37 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 73 + .byte 19 + .byte 0 + .byte 0 + .byte 11 + .byte 19 + .byte 1 + .byte 3 + .byte 37 + .byte 11 + .byte 11 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 0 + .byte 0 + .byte 12 + .byte 13 + .byte 0 + .byte 3 + .byte 37 + .byte 73 + .byte 19 + .byte 58 + .byte 11 + .byte 59 + .byte 11 + .byte 56 + .byte 11 + .byte 0 + .byte 0 + .byte 0 + .section .debug_info,"",%progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 +.Ldebug_info_start0: + .short 5 + .byte 1 + .byte 4 + .long .debug_abbrev + .byte 1 + .byte 0 + .short 12 + .byte 1 + .long .Lstr_offsets_base0 + .long .Lline_table_start0 + .byte 2 + .byte 0 + .long .Lfunc_end2-.Lfunc_begin0 + .long .Laddr_table_base0 + .long .Lloclists_table_base0 + .byte 2 + .byte 3 + .byte 0 + .byte 1 + + + + .byte 3 + .long 49 + .byte 0 + .byte 4 + .long 54 + .byte 5 + .byte 4 + .byte 5 + .byte 4 + .byte 6 + .byte 0 + .long .Lfunc_end0-.Lfunc_begin0 + .byte 1 + .byte 91 + + .byte 5 + .byte 0 + .byte 2 + + .long 54 + + .byte 7 + .byte 0 + .byte 8 + .byte 0 + .byte 2 + .long 247 + .byte 7 + .byte 1 + .byte 10 + .byte 0 + .byte 2 + .long 54 + .byte 7 + .byte 2 + .byte 11 + .byte 0 + .byte 2 + .long 54 + .byte 8 + .byte 3 + .byte 12 + .byte 0 + .byte 3 + .long 54 + .byte 8 + .byte 4 + .byte 13 + .byte 0 + .byte 5 + .long 54 + .byte 9 + .long 39 + .long .Ltmp4-.Lfunc_begin0 + .byte 0 + .byte 6 + .byte 1 + .long .Lfunc_end1-.Lfunc_begin1 + .byte 1 + .byte 91 + + .byte 6 + .byte 0 + .byte 13 + + .long 54 + + .byte 7 + .byte 5 + .byte 14 + .byte 0 + .byte 13 + .long 251 + .byte 8 + .byte 6 + .byte 16 + .byte 0 + .byte 14 + .long 54 + .byte 0 + .byte 6 + .byte 2 + .long .Lfunc_end2-.Lfunc_begin2 + .byte 1 + .byte 91 + + .byte 7 + .byte 0 + .byte 18 + + .long 54 + + .byte 7 + .byte 7 + .byte 8 + .byte 0 + .byte 18 + .long 54 + .byte 7 + .byte 8 + .byte 10 + .byte 0 + .byte 18 + .long 54 + .byte 10 + .byte 1 + .byte 82 + .byte 11 + .byte 0 + .byte 18 + .long 54 + .byte 10 + .byte 1 + .byte 83 + .byte 12 + .byte 0 + .byte 18 + .long 54 + .byte 10 + .byte 2 + .byte 125 + .byte 0 + .byte 14 + .byte 0 + .byte 18 + .long 54 + .byte 10 + .byte 2 + .byte 125 + .byte 4 + .byte 16 + .byte 0 + .byte 18 + .long 54 + .byte 8 + .byte 9 + .byte 17 + .byte 0 + .byte 19 + .long 54 + .byte 0 + .byte 5 + .byte 9 + .byte 5 + .byte 4 + .byte 11 + .byte 15 + .byte 8 + .byte 0 + .byte 9 + .byte 12 + .byte 8 + .long 54 + .byte 0 + .byte 10 + .byte 0 + .byte 12 + .byte 10 + .long 54 + .byte 0 + .byte 11 + .byte 4 + .byte 0 + .byte 0 +.Ldebug_info_end0: + .section .debug_addr,"",%progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 +.Ldebug_addr_start0: + .short 5 + .byte 4 + .byte 0 +.Laddr_table_base0: + .long .Lfunc_begin0 + .long .Lfunc_begin1 + .long .Lfunc_begin2 +.Ldebug_addr_end0: + .ident "clang version 10.0.0 (git@github.com:llvm/llvm-project.git e73f78acd34360f7450b81167d9dc858ccddc262)" + .section ".note.GNU-stack","",%progbits + .addrsig + .eabi_attribute 30, 1 + .section .debug_line,"",%progbits +.Lline_table_start0: diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -16,7 +16,10 @@ //===----------------------------------------------------------------------===// #include "llvm-objdump.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetOperations.h" #include "llvm/ADT/StringExtras.h" @@ -24,6 +27,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/CodeGen/FaultMaps.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/DebugInfo/Symbolize/Symbolize.h" #include "llvm/Demangle/Demangle.h" #include "llvm/MC/MCAsmInfo.h" @@ -66,10 +70,13 @@ #include #include #include +#include #include #include #include +#define DEBUG_TYPE "objdump" + using namespace llvm::object; namespace llvm { @@ -334,6 +341,9 @@ cl::cat(ObjdumpCat)); static cl::alias WideShort("w", cl::Grouping, cl::aliasopt(Wide)); +static cl::opt DbgVariables("debug-vars", cl::init(false)); +static cl::opt DbgIndent("debug-vars-indent", cl::init(50)); + static cl::extrahelp HelpResponse("\nPass @FILE as argument to read options from FILE.\n"); @@ -566,7 +576,7 @@ Symbolizer.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts)); } virtual ~SourcePrinter() = default; - virtual void printSourceLine(raw_ostream &OS, + virtual void printSourceLine(formatted_raw_ostream &OS, object::SectionedAddress Address, StringRef ObjectFilename, StringRef Delimiter = "; "); @@ -602,7 +612,7 @@ return true; } -void SourcePrinter::printSourceLine(raw_ostream &OS, +void SourcePrinter::printSourceLine(formatted_raw_ostream &OS, object::SectionedAddress Address, StringRef ObjectFilename, StringRef Delimiter) { @@ -670,15 +680,16 @@ return isArmElf(Obj) || isAArch64Elf(Obj); } -static void printRelocation(StringRef FileName, const RelocationRef &Rel, - uint64_t Address, bool Is64Bits) { +static void printRelocation(formatted_raw_ostream &OS, StringRef FileName, + const RelocationRef &Rel, uint64_t Address, + bool Is64Bits) { StringRef Fmt = Is64Bits ? "\t\t%016" PRIx64 ": " : "\t\t\t%08" PRIx64 ": "; SmallString<16> Name; SmallString<32> Val; Rel.getTypeName(Name); if (Error E = getRelocationValueString(Rel, Val)) reportError(std::move(E), FileName); - outs() << format(Fmt.data(), Address) << Name << "\t" << Val << "\n"; + OS << format(Fmt.data(), Address) << Name << "\t" << Val; } class PrettyPrinter { @@ -686,7 +697,7 @@ virtual ~PrettyPrinter() = default; virtual void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, - object::SectionedAddress Address, raw_ostream &OS, + object::SectionedAddress Address, formatted_raw_ostream &OS, StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP, StringRef ObjectFilename, std::vector *Rels = nullptr) { @@ -718,7 +729,7 @@ class HexagonPrettyPrinter : public PrettyPrinter { public: void printLead(ArrayRef Bytes, uint64_t Address, - raw_ostream &OS) { + formatted_raw_ostream &OS) { uint32_t opcode = (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | Bytes[0]; if (!NoLeadingAddr) @@ -730,7 +741,7 @@ } } void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, - object::SectionedAddress Address, raw_ostream &OS, + object::SectionedAddress Address, formatted_raw_ostream &OS, StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP, StringRef ObjectFilename, std::vector *Rels) override { @@ -761,7 +772,7 @@ auto PrintReloc = [&]() -> void { while ((RelCur != RelEnd) && (RelCur->getOffset() <= Address.Address)) { if (RelCur->getOffset() == Address.Address) { - printRelocation(ObjectFilename, *RelCur, Address.Address, false); + printRelocation(OS, ObjectFilename, *RelCur, Address.Address, false); return; } ++RelCur; @@ -800,7 +811,7 @@ class AMDGCNPrettyPrinter : public PrettyPrinter { public: void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, - object::SectionedAddress Address, raw_ostream &OS, + object::SectionedAddress Address, formatted_raw_ostream &OS, StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP, StringRef ObjectFilename, std::vector *Rels) override { @@ -852,7 +863,7 @@ class BPFPrettyPrinter : public PrettyPrinter { public: void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, - object::SectionedAddress Address, raw_ostream &OS, + object::SectionedAddress Address, formatted_raw_ostream &OS, StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP, StringRef ObjectFilename, std::vector *Rels) override { @@ -1110,6 +1121,535 @@ } } +struct PrintedExpr { + enum ExprKind { + Address, + Value, + }; + ExprKind Kind; + SmallString<20> String; + + PrintedExpr(ExprKind K = Address) : Kind(K) {} +}; + +static void PrettyPrintDWARFOps(raw_ostream &OS, DWARFExpression::iterator I, + const DWARFExpression::iterator E, + const MCRegisterInfo *MRI, + SmallString<20> FrameBase, + bool ForFrameBase = false) { + SmallVector Stack; + unsigned PieceStart = 0; + + while (I != E) { + auto &Op = *I; + unsigned Opcode = Op.getCode(); + if (Opcode == dwarf::DW_OP_piece) { + // DW_OP_piece - record piece of larger object. + assert(Stack.size() <= 1 && "too many values on stack"); + uint64_t PieceSize = Op.getRawOperand(0); + if (PieceStart != 0) + OS << " "; + if (OS.has_colors()) + OS.changeColor(raw_ostream::YELLOW); + OS << "[" << PieceStart << "," << (PieceStart + PieceSize) << "): "; + if (OS.has_colors()) + OS.changeColor(raw_ostream::CYAN); + if (Stack.empty()) + OS << "???"; + else if (Stack.front().Kind == PrintedExpr::Address && !ForFrameBase) + OS << "[" << Stack.front().String << "]"; + else + OS << Stack.front().String; + Stack.clear(); + PieceStart += PieceSize; + } else if (Opcode >= dwarf::DW_OP_reg0 && Opcode <= dwarf::DW_OP_reg31) { + // Register contents + int DwarfRegNum = Opcode - dwarf::DW_OP_reg0; + int LLVMRegNum = *MRI->getLLVMRegNum(DwarfRegNum, false); + raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String); + S << MRI->getName(LLVMRegNum); + } else if (Opcode == dwarf::DW_OP_regx) { + int DwarfRegNum = Op.getRawOperand(0); + int LLVMRegNum = *MRI->getLLVMRegNum(DwarfRegNum, false); + raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String); + S << MRI->getName(LLVMRegNum); + } else if (Opcode >= dwarf::DW_OP_breg0 && Opcode <= dwarf::DW_OP_breg31) { + int DwarfRegNum = Opcode - dwarf::DW_OP_breg0; + int LLVMRegNum = *MRI->getLLVMRegNum(DwarfRegNum, false); + int64_t Offset = Op.getRawOperand(0); + raw_svector_ostream S(Stack.emplace_back().String); + S << MRI->getName(LLVMRegNum); + if (Offset) + S << format("%+" PRId64, Offset); + } else if (Opcode == dwarf::DW_OP_bregx) { + int DwarfRegNum = Op.getRawOperand(0); + int LLVMRegNum = *MRI->getLLVMRegNum(DwarfRegNum, false); + int64_t Offset = Op.getRawOperand(1); + raw_svector_ostream S(Stack.emplace_back().String); + S << MRI->getName(LLVMRegNum); + if (Offset) + S << format("%+" PRId64, Offset); + } else if (Opcode == dwarf::DW_OP_fbreg) { + int64_t Offset = Op.getRawOperand(0); + raw_svector_ostream S(Stack.emplace_back().String); + S << FrameBase; + if (Offset) + S << format("%+" PRId64, Offset); + } else if (Opcode >= dwarf::DW_OP_lit0 && Opcode <= dwarf::DW_OP_lit31) { + unsigned Val = Opcode - dwarf::DW_OP_lit0; + raw_svector_ostream S(Stack.emplace_back().String); + S << Val; + } else if (Opcode == dwarf::DW_OP_consts || + Opcode == dwarf::DW_OP_const1s || + Opcode == dwarf::DW_OP_const2s || + Opcode == dwarf::DW_OP_const4s || + Opcode == dwarf::DW_OP_const8s) { + // Signed constant + int64_t Val = Op.getRawOperand(0); + raw_svector_ostream S(Stack.emplace_back().String); + S << Val; + } else if (Opcode == dwarf::DW_OP_constu || + Opcode == dwarf::DW_OP_const1u || + Opcode == dwarf::DW_OP_const2u || + Opcode == dwarf::DW_OP_const4u || + Opcode == dwarf::DW_OP_const8u) { + // Unsigned constant + uint64_t Val = Op.getRawOperand(0); + raw_svector_ostream S(Stack.emplace_back().String); + S << Val; + } else if (Opcode == dwarf::DW_OP_implicit_value) { + uint64_t Len = Op.getRawOperand(0); + raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String); + S << ""; + } else if (Opcode == dwarf::DW_OP_stack_value) { + assert(!Stack.empty()); + Stack.back().Kind = PrintedExpr::Value; + } else if (Opcode == dwarf::DW_OP_entry_value || + Opcode == dwarf::DW_OP_GNU_entry_value) { + int64_t SubExprLength = Op.getRawOperand(0); + DWARFExpression::iterator SubExprEnd = I.skip_bytes(SubExprLength); + ++I; + raw_svector_ostream S(Stack.emplace_back().String); + S << "entry("; + PrettyPrintDWARFOps(S, I, SubExprEnd, MRI, FrameBase); + S << ")"; + I = SubExprEnd; + continue; + } else if (Opcode == dwarf::DW_OP_deref || + Opcode == dwarf::DW_OP_deref_size) { + // TODO: The current expression syntax doesn't include the size of memory + // accesses, but probably should. + PrintedExpr PoppedVal = Stack.pop_back_val(); + raw_svector_ostream S(Stack.emplace_back().String); + S << "[" << PoppedVal.String << "]"; + } else if (Opcode == dwarf::DW_OP_abs || Opcode == dwarf::DW_OP_neg || + Opcode == dwarf::DW_OP_not) { + // Unary operations + PrintedExpr ExprOp = Stack.pop_back_val(); + raw_svector_ostream S(Stack.emplace_back().String); + switch (Opcode) { + case dwarf::DW_OP_abs: S << "abs(" << ExprOp.String << ")"; break; + case dwarf::DW_OP_neg: S << "-" << ExprOp.String; break; + case dwarf::DW_OP_not: S << "~" << ExprOp.String; break; + default: llvm_unreachable("unexpected opcode"); + } + } else if (Opcode == dwarf::DW_OP_plus_uconst) { + // Unary operations with immediate on RHS + PrintedExpr LHS = Stack.pop_back_val(); + uint64_t RHS = Op.getRawOperand(0); + raw_svector_ostream S(Stack.emplace_back().String); + S << LHS.String << "+" << RHS; + } else if (Opcode == dwarf::DW_OP_and || Opcode == dwarf::DW_OP_div || + Opcode == dwarf::DW_OP_minus || Opcode == dwarf::DW_OP_mod || + Opcode == dwarf::DW_OP_mul || Opcode == dwarf::DW_OP_or || + Opcode == dwarf::DW_OP_plus || Opcode == dwarf::DW_OP_shl || + Opcode == dwarf::DW_OP_shr || Opcode == dwarf::DW_OP_shra) { + // Binary operations + PrintedExpr LHS = Stack.pop_back_val(); + PrintedExpr RHS = Stack.pop_back_val(); + raw_svector_ostream S(Stack.emplace_back().String); + S << LHS.String; + // FIXME: Define operator precedence, put parens in when needed. + switch (Opcode) { + case dwarf::DW_OP_and: S << "&"; break; + case dwarf::DW_OP_div: S << "/"; break; + case dwarf::DW_OP_minus: S << "-"; break; + case dwarf::DW_OP_mod: S << "%"; break; + case dwarf::DW_OP_mul: S << "*"; break; + case dwarf::DW_OP_or: S << "|"; break; + case dwarf::DW_OP_plus: S << "+"; break; + case dwarf::DW_OP_xor: S << "^"; break; + case dwarf::DW_OP_shl : S << "<<"; break; + // FIXME: different syntax for shr and shra + case dwarf::DW_OP_shr: S << ">>"; break; + case dwarf::DW_OP_shra: S << ">>"; break; + default: llvm_unreachable("unexpected opcode"); + } + S << RHS.String; + } else if (Opcode == dwarf::DW_OP_call_frame_cfa) { + raw_svector_ostream S(Stack.emplace_back().String); + S << "CFA"; + } else if (Opcode == dwarf::DW_OP_regval_type || + Opcode == dwarf::DW_OP_GNU_regval_type) { + // Register contents with type (we ignore the type for now) + int LLVMRegNum = *MRI->getLLVMRegNum(Op.getRawOperand(0), false); + raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String); + S << MRI->getName(LLVMRegNum); + } else if (Opcode == dwarf::DW_OP_addr) { + // Address, probably needs to care about relocations? + uint64_t Addr = Op.getRawOperand(0); + raw_svector_ostream S(Stack.emplace_back().String); + S << format("%#x", Addr); + } else if (Opcode == dwarf::DW_OP_implicit_pointer || + Opcode == dwarf::DW_OP_GNU_implicit_pointer) { + // Implicit pointer to thing described by debug info. + raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String); + S << ""; + } else { + dbgs() << ""; + llvm_unreachable("unknown op"); + } + ++I; + } + + assert((PieceStart != 0 && Stack.size() == 0) || + (PieceStart == 0 && Stack.size() == 1) && + "expected pieces and an empty stack, or one value on stack"); + if (!Stack.empty()) { + if (Stack.front().Kind == PrintedExpr::Address && !ForFrameBase) + OS << "[" << Stack.front().String << "]"; + else + OS << Stack.front().String; + } +} + +static void PrettyPrintDWARFExpr(raw_ostream &OS, const DWARFExpression *Expr, + const MCRegisterInfo *MRI, + const DWARFDie FuncDie) { + SmallString<20> FrameBase; + if (FuncDie) { + auto FrameBaseAttr = FuncDie.find(dwarf::DW_AT_frame_base); + if (FrameBaseAttr) { + StringRef FrameBaseStr((const char *)FrameBaseAttr->getAsBlock()->data(), + FrameBaseAttr->getAsBlock()->size()); + DataExtractor FrameBaseData(FrameBaseStr, true /* TODO endianness */, 0); + DWARFExpression FrameBaseExpr( + FrameBaseData, FuncDie.getDwarfUnit()->getVersion(), + FuncDie.getDwarfUnit()->getAddressByteSize()); + raw_svector_ostream S(FrameBase); + PrettyPrintDWARFOps(S, FrameBaseExpr.begin(), FrameBaseExpr.end(), MRI, + FrameBase, true); + } + } + + PrettyPrintDWARFOps(OS, Expr->begin(), Expr->end(), MRI, FrameBase); +} + +struct LiveVariable { + DWARFLocationExpression LocExpr; + const char *VarName; + DWARFUnit *Unit; + const DWARFDie FuncDie; + + LiveVariable(DWARFLocationExpression &LocExpr, const char *VarName, + DWARFUnit *Unit, const DWARFDie FuncDie) + : LocExpr(LocExpr), VarName(VarName), Unit(Unit), FuncDie(FuncDie) {} + + bool liveAtAddress(object::SectionedAddress Addr) { + if (LocExpr.Range == None) + return false; + return LocExpr.Range->SectionIndex == Addr.SectionIndex && + LocExpr.Range->LowPC <= Addr.Address && + LocExpr.Range->HighPC > Addr.Address; + } + + void print(raw_ostream &OS, const MCRegisterInfo *MRI) const { + DataExtractor Data({LocExpr.Expr.data(), LocExpr.Expr.size()}, + true /* TODO endianness */, 0); + DWARFExpression Expression(Data, Unit->getVersion(), + Unit->getAddressByteSize()); + PrettyPrintDWARFExpr(OS, &Expression, MRI, FuncDie); + } +}; + +struct LiveVariablePrinter { + struct Column { + unsigned VarIdx; + bool LiveIn; + bool LiveOut; + bool New; + + bool isActive() const { return VarIdx != ~0U; } + }; + + std::vector LiveVariables; + IndexedMap ActiveCols; + const MCRegisterInfo *MRI; + + LiveVariablePrinter(const MCRegisterInfo *MRI) + : LiveVariables(), ActiveCols({~0U, 0, 0, 0}), MRI(MRI) {} + + void dump() const { + for (const LiveVariable &LV : LiveVariables) { + dbgs() << LV.VarName << " @ " << LV.LocExpr.Range << ": "; + LV.print(dbgs(), MRI); + dbgs() << "\n"; + } + } + + void AddVariable(DWARFDie FuncDie, DWARFDie VarDie) { + uint64_t FuncLowPC, FuncHighPC, SectionIndex; + FuncDie.getLowAndHighPC(FuncLowPC, FuncHighPC, SectionIndex); + const char *VarName = VarDie.getName(DINameKind::ShortName); + DWARFUnit *U = VarDie.getDwarfUnit(); + + auto Locs = VarDie.getLocations(dwarf::DW_AT_location); + if (Locs) { + for (auto &LocExpr : *Locs) { + if (LocExpr.Range) { + // FIXME: getLocations seems to get the section index wrong for + // objects built with -ffunction-sections, for now we just fix it up + // here. + DWARFLocationExpression FixedExpr{ + DWARFAddressRange(LocExpr.Range->LowPC, LocExpr.Range->HighPC, + SectionIndex), + LocExpr.Expr}; + LiveVariables.emplace_back(FixedExpr, VarName, U, FuncDie); + } else { + // If the LocExpr does not have an associated range, it is valid for + // the whole of the function. TODO technically it is not valid for + // any range covered by another LocExpr, does that happen in reality? + DWARFLocationExpression WholeFuncExpr{ + DWARFAddressRange(FuncLowPC, FuncHighPC, SectionIndex), + LocExpr.Expr}; + LiveVariables.emplace_back(WholeFuncExpr, VarName, U, FuncDie); + } + } + } else { + consumeError(Locs.takeError()); + } + } + + void AddFunction(DWARFDie D) { + for (auto Child : D.children()) { + if (Child.getTag() == dwarf::DW_TAG_variable || + Child.getTag() == dwarf::DW_TAG_formal_parameter) { + AddVariable(D, Child); + } else { + AddFunction(Child); + } + } + } + + void AddCompileUnit(DWARFDie D) { + if (D.getTag() == dwarf::DW_TAG_subprogram) { + AddFunction(D); + } else { + for (auto Child : D.children()) + AddFunction(Child); + } + } + + // A live range starting at address A is actually live going into the + // instruction at A, so it's live at the gap between instructions at A. It + // might not be live out of the previous (address-ordered) instruction + // though, if it's in a different BB, how do we know the difference? That + // only occurs if there is no fall-through into this block, how can we + // force that for testing? + + unsigned findFreeColumn() { + for (unsigned ColIdx = 0; ColIdx < ActiveCols.size(); ++ColIdx) { + if (!ActiveCols[ColIdx].isActive()) + return ColIdx; + } + // TODO growth factor? + ActiveCols.grow(ActiveCols.size() + 1); + return ActiveCols.size() - 1; + } + + // Update to match the state of the instruction between ThisAddr and + // NextAddr. In the common case, any live range active at ThisAddr is + // live-in to the instruction, and any live range active at NextAddr is + // live-out of the instruction. If EndFunction is true, then ThisAddr and + // NextAddr are in different functions, so live ranges starting at NextAddr + // will be ignored, because they belong to the next function. + void update(object::SectionedAddress ThisAddr, + object::SectionedAddress NextAddr, bool EndFunction) { + // Any variables which were new aren't any more. + for (unsigned ColIdx = 0; ColIdx < ActiveCols.size(); ++ColIdx) + ActiveCols[ColIdx].New = false; + + // First, check variables which have already been assigned a column, so + // that we don't change their order. + SmallSet CheckedVarIdxs; + for (unsigned ColIdx = 0; ColIdx < ActiveCols.size(); ++ColIdx) { + if (!ActiveCols[ColIdx].isActive()) + continue; + CheckedVarIdxs.insert(ActiveCols[ColIdx].VarIdx); + LiveVariable &LV = LiveVariables[ActiveCols[ColIdx].VarIdx]; + ActiveCols[ColIdx].LiveIn = LV.liveAtAddress(ThisAddr); + ActiveCols[ColIdx].LiveOut = LV.liveAtAddress(NextAddr); + LLVM_DEBUG(dbgs() << "pass 1, " << ThisAddr.Address << "-" + << NextAddr.Address << ", " << LV.VarName << ", Col " + << ColIdx << ": LiveIn=" << ActiveCols[ColIdx].LiveIn + << ", LiveOut=" << ActiveCols[ColIdx].LiveOut << "\n"); + // If the variable range is neither live-in nor live-out, deallocate + // it's column. + if (!ActiveCols[ColIdx].LiveIn && !ActiveCols[ColIdx].LiveOut) + ActiveCols[ColIdx].VarIdx = ~0U; + } + + // Next, look for variables which don't already have a column, but which + // are now live. + if (!EndFunction) { + for (unsigned VarIdx = 0; VarIdx < LiveVariables.size(); ++VarIdx) { + if (CheckedVarIdxs.count(VarIdx)) + continue; + LiveVariable &LV = LiveVariables[VarIdx]; + bool LiveIn = LV.liveAtAddress(ThisAddr); + bool LiveOut = LV.liveAtAddress(NextAddr); + if (!LiveIn && !LiveOut) + continue; + + unsigned ColIdx = findFreeColumn(); + LLVM_DEBUG(dbgs() << "pass 2, " << ThisAddr.Address << "-" + << NextAddr.Address << ", " << LV.VarName << ", Col " + << ColIdx << ": LiveIn=" << LiveIn + << ", LiveOut=" << LiveOut << "\n"); + ActiveCols[ColIdx] = {VarIdx, LiveIn, LiveOut, true}; + } + } + } + + // Print live ranges to the right of an existing line. This assumes the + // line is not an instruction, so doesn't start or end any live ranges, so + // we only need to print active ranges or empty columns. If AfterInst is + // true, this is being printed after the last instruction fed to update(), + // otherwise this is being printed before it. + void printAfterOtherLine(formatted_raw_ostream &OS, bool AfterInst) { + if (ActiveCols.size()) { + unsigned FirstUnprintedColumn = MoveToFirstVarColumn(OS); + for (size_t ColIdx = FirstUnprintedColumn; ColIdx < ActiveCols.size(); + ++ColIdx) { + if (ActiveCols[ColIdx].isActive() && + (AfterInst ? ActiveCols[ColIdx].LiveOut + : ActiveCols[ColIdx].LiveIn)) + OS << "┃ "; + else + OS << " "; + } + } + OS << "\n"; + } + + // Indent to the first live-range column to the right of the currently + // printed line, and return the index of that column. + // TODO: formatted_raw_ostream uses "column" to mean a number of characters + // since the last \n, and we use it to mean the number of slots in which we + // put live variable lines. Pick a less overloaded word. + unsigned MoveToFirstVarColumn(formatted_raw_ostream &OS) { + unsigned FirstUnprintedColumn = + std::max((int)(OS.getColumn() - getIndentLevel() + 1) / 2, 0); + if ((getIndentLevel() + FirstUnprintedColumn * 2) > OS.getColumn()) + OS.PadToColumn(getIndentLevel() + FirstUnprintedColumn * 2); + return FirstUnprintedColumn; + } + + // Print any live variable range info needed to the right of a + // non-instruction line of disassembly. This is where we print the variable + // names and expressions, with thin line-drawing characters connecting them + // to the live range which starts at the next instruction. If MustPrint is + // true, we have to print at least one line (with the continuation of any + // already-active live ranges) because something has already been printed + // earlier on this line. + void printBetweenInsts(formatted_raw_ostream &OS, bool MustPrint) { + bool PrintedSomething = false; + for (unsigned ColIdx = 0; ColIdx < ActiveCols.size(); ++ColIdx) { + if (!ActiveCols[ColIdx].isActive()) + continue; + if (ActiveCols[ColIdx].New) { + // New live variable range for the next instruction, so print the + // variable name and location. + + // First we need to print the live range markers for any active + // columns to the left of this one. + OS.PadToColumn(getIndentLevel()); + for (unsigned ColIdx2 = 0; ColIdx2 < ColIdx; ++ColIdx2) { + if (ActiveCols[ColIdx2].isActive()) + OS << (ActiveCols[ColIdx2].LiveIn ? "┃ " : "│ "); + else + OS << " "; + } + + // Then print the variable name and location of the new live range, + // with box drawing characters joining it to the live range line. + OS << (ActiveCols[ColIdx].LiveIn ? "┠─ " : "┌─ "); + WithColor(OS, raw_ostream::GREEN) + << LiveVariables[ActiveCols[ColIdx].VarIdx].VarName; + OS << " = "; + { + WithColor ExprColor(OS, raw_ostream::CYAN); + LiveVariables[ActiveCols[ColIdx].VarIdx].print(OS, MRI); + } + + // If there are any columns to the right of the expression we just + // printed, then continue their live range lines. + unsigned FirstUnprintedColumn = MoveToFirstVarColumn(OS); + for (unsigned ColIdx2 = FirstUnprintedColumn; + ColIdx2 < ActiveCols.size(); ++ColIdx2) { + if (ActiveCols[ColIdx2].isActive() && ActiveCols[ColIdx2].LiveIn) + OS << "┃ "; + else + OS << " "; + } + + OS << "\n"; + PrintedSomething = true; + } + } + + // If we must print something (because we printed a line/column number), + // but don't have any new variables to print, then print a line which + // just continues any existing live ranges. + if (MustPrint && !PrintedSomething) { + printAfterOtherLine(OS, false); + } + } + + // Print the live variable ranges to the right of a disassembled + // instruction. + void printAfterInst(formatted_raw_ostream &OS) { + if (!ActiveCols.size()) + return; + // If the instruction was particularly long (e.g. it contained a long + // symbol name), then it might overrun the live variable lines. This + // isn't great, but it's not actually ambiguous until multiple + // consecutive instructions do this. + unsigned FirstUnprintedColumn = MoveToFirstVarColumn(OS); + for (unsigned ColIdx = FirstUnprintedColumn; ColIdx < ActiveCols.size(); + ++ColIdx) { + if (ActiveCols[ColIdx].isActive()) { + if (ActiveCols[ColIdx].LiveIn && ActiveCols[ColIdx].LiveOut) + OS << "┃ "; + else if (!ActiveCols[ColIdx].LiveIn && ActiveCols[ColIdx].LiveOut) + OS << "╈ "; + else if (ActiveCols[ColIdx].LiveIn && !ActiveCols[ColIdx].LiveOut) + OS << "┻ "; + else + llvm_unreachable("var must be live in or out!"); + } else { + OS << " "; + } + } + } + + // Get the column number (in characters) at which the first column of live + // variables should be printed. + unsigned getIndentLevel() const { + return DbgIndent + (NoShowRawInsn ? 16 : 40); + } +}; + static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj, MCContext &Ctx, MCDisassembler *PrimaryDisAsm, MCDisassembler *SecondaryDisAsm, @@ -1201,6 +1741,26 @@ array_pod_sort(SecSyms.second.begin(), SecSyms.second.end()); array_pod_sort(AbsoluteSymbols.begin(), AbsoluteSymbols.end()); + std::unique_ptr DICtx; + LiveVariablePrinter LVP(Ctx.getRegisterInfo()); + std::map StmtAddresses; + + if (DbgVariables) { + DICtx = DWARFContext::create(*Obj); + for (const auto &CU : DICtx->compile_units()) { + LVP.AddCompileUnit(CU->getUnitDIE(false)); + + auto LineTable = DICtx->getLineTableForUnit(CU.get()); + if (LineTable) { + for (auto Row : LineTable->Rows) + if (Row.IsStmt) + StmtAddresses.insert(std::make_pair(Row.Address, Row)); + } + } + } + + LLVM_DEBUG(LVP.dump()); + for (const SectionRef &Section : ToolSectionFilter(*Obj)) { if (FilterSections.empty() && !DisassembleAll && (!Section.isText() || Section.isVirtual())) @@ -1418,11 +1978,23 @@ if (Size == 0) Size = 1; + LVP.update({Index, Section.getIndex()}, + {Index + Size, Section.getIndex()}, Index + Size == End); + + formatted_raw_ostream FOS(outs()); + auto LineTableRow = StmtAddresses.find({Index, Section.getIndex()}); + bool ShowLineNum = (LineTableRow != StmtAddresses.end()) && DbgVariables; + if (ShowLineNum) { + WithColor(FOS, raw_ostream::YELLOW) + << " line " << LineTableRow->second.Line << ", column " + << LineTableRow->second.Column; + } + LVP.printBetweenInsts(FOS, ShowLineNum); PIP.printInst(*IP, Disassembled ? &Inst : nullptr, Bytes.slice(Index, Size), {SectionAddr + Index + VMAAdjustment, Section.getIndex()}, - outs(), "", *STI, &SP, Obj->getFileName(), &Rels); - outs() << CommentStream.str(); + FOS, "", *STI, &SP, Obj->getFileName(), &Rels); + FOS << CommentStream.str(); Comments.clear(); // Try to resolve the target of a call, tail call, etc. to a specific @@ -1473,15 +2045,17 @@ --TargetSym; uint64_t TargetAddress = std::get<0>(*TargetSym); StringRef TargetName = std::get<1>(*TargetSym); - outs() << " <" << TargetName; + FOS << " <" << TargetName; uint64_t Disp = Target - TargetAddress; if (Disp) - outs() << "+0x" << Twine::utohexstr(Disp); - outs() << '>'; + FOS << "+0x" << Twine::utohexstr(Disp); + FOS << '>'; } } } - outs() << "\n"; + + LVP.printAfterInst(FOS); + FOS << "\n"; // Hexagon does this in pretty printer if (Obj->getArch() != Triple::hexagon) { @@ -1507,8 +2081,9 @@ Offset += AdjustVMA; } - printRelocation(Obj->getFileName(), *RelCur, SectionAddr + Offset, - Is64Bits); + printRelocation(FOS, Obj->getFileName(), *RelCur, + SectionAddr + Offset, Is64Bits); + LVP.printAfterOtherLine(FOS, true); ++RelCur; } }