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 @@ -373,6 +373,20 @@ S << MRI->getName(*LLVMRegNum); break; } + case dwarf::DW_OP_bregx: { + int DwarfRegNum = Op.getRawOperand(0); + int64_t Offset = Op.getRawOperand(1); + Optional LLVMRegNum = MRI->getLLVMRegNum(DwarfRegNum, false); + if (!LLVMRegNum) { + OS << ""; + return false; + } + raw_svector_ostream S(Stack.emplace_back().String); + S << MRI->getName(*LLVMRegNum); + if (Offset) + S << format("%+" PRId64, Offset); + break; + } default: if (Opcode >= dwarf::DW_OP_reg0 && Opcode <= dwarf::DW_OP_reg31) { uint64_t DwarfRegNum = Opcode - dwarf::DW_OP_reg0; @@ -383,6 +397,19 @@ } 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; + int64_t Offset = Op.getRawOperand(0); + Optional LLVMRegNum = MRI->getLLVMRegNum(DwarfRegNum, false); + if (!LLVMRegNum) { + OS << ""; + return false; + } + raw_svector_ostream S(Stack.emplace_back().String); + S << MRI->getName(*LLVMRegNum); + if (Offset) + S << format("%+" PRId64, Offset); } else { // If we hit an unknown operand, we don't know its effect on the stack, // so bail out on the whole expression. @@ -396,7 +423,11 @@ } assert(Stack.size() == 1 && "expected one value on stack"); - OS << Stack.front().String; + + if (Stack.front().Kind == PrintedExpr::Address) + OS << "[" << Stack.front().String << "]"; + else + OS << Stack.front().String; return true; } diff --git a/llvm/test/tools/llvm-objdump/ARM/debug-vars-breg.s b/llvm/test/tools/llvm-objdump/ARM/debug-vars-breg.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/ARM/debug-vars-breg.s @@ -0,0 +1,287 @@ +# RUN: llvm-mc --triple armv8a--none-eabi < %s --filetype=obj | \ +# RUN: llvm-objdump - -d --debug-vars --no-show-raw-insn | \ +# RUN: FileCheck %s + +## Check that the --debug-vars option works for memory locations using the +## DW_OP_breg opcodes. + +## Generated with this compile command and source code: +## clang --target=arm--none-eabi -march=armv7-a -c debug.c -O1 -g -S -o - + +## void bar(int*); +## void foo(int a) { +## bar(&a); +## } + +# CHECK: Disassembly of section .text: +# CHECK-EMPTY: +# CHECK-NEXT: 00000000 foo: +# CHECK-NEXT: ┠─ a = R0 +# CHECK-NEXT: 0: push {r11, lr} ┃ +# CHECK-NEXT: 4: mov r11, sp ┃ +# CHECK-NEXT: 8: sub sp, sp, #8 ┃ +# CHECK-NEXT: ┃ ┌─ a = [SP+4] +# CHECK-NEXT: c: str r0, [sp, #4] ┻ ╈ +# CHECK-NEXT: 10: add r0, sp, #4 ┃ +# CHECK-NEXT: 14: bl #-8 ┃ +# CHECK-NEXT: 18: mov sp, r11 ┻ +# CHECK-NEXT: 1c: pop {r11, pc} + + + .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 foo + .p2align 2 + .type foo,%function + .code 32 +foo: +.Lfunc_begin0: + .loc 1 2 0 + .fnstart + .cfi_sections .debug_frame + .cfi_startproc + .save {r11, lr} + push {r11, lr} + .cfi_def_cfa_offset 8 + .cfi_offset lr, -4 + .cfi_offset r11, -8 + .setfp r11, sp + mov r11, sp + .cfi_def_cfa_register r11 + .pad #8 + sub sp, sp, #8 + str r0, [sp, #4] +.Ltmp0: + add r0, sp, #4 +.Ltmp1: + .loc 1 3 3 prologue_end + bl bar +.Ltmp2: + .loc 1 4 1 + mov sp, r11 +.Ltmp3: + pop {r11, pc} +.Ltmp4: +.Lfunc_end0: + .size foo, .Lfunc_end0-foo + .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 "foo" +.Linfo_string6: + .asciz "a" + .section .debug_loc,"",%progbits +.Ldebug_loc0: + .long .Lfunc_begin0-.Lfunc_begin0 + .long .Ltmp0-.Lfunc_begin0 + .short 1 + .byte 80 + .long .Ltmp0-.Lfunc_begin0 + .long .Ltmp3-.Lfunc_begin0 + .short 2 + .byte 125 + .byte 4 + .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 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 + .ascii "\211\202\001" + .byte 0 + .byte 49 + .byte 19 + .byte 17 + .byte 1 + .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_end0-.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 + + + .byte 7 + .long .Ldebug_loc0 + .long .Linfo_string6 + .byte 1 + .byte 2 + .long 56 + .byte 8 + .long 38 + .long .Ltmp2 + .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-bregx.s b/llvm/test/tools/llvm-objdump/ARM/debug-vars-bregx.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/ARM/debug-vars-bregx.s @@ -0,0 +1,291 @@ +# RUN: llvm-mc --triple armv8a--none-eabi < %s --filetype=obj | \ +# RUN: llvm-objdump - -d --debug-vars --no-show-raw-insn | \ +# RUN: FileCheck %s + +## Check that the --debug-vars option works for memory locations using the +## DW_OP_bregx opcode. + +## Generated with this compile command and source code, then modified to use +## DW_OP_bregx instead of DW_OP_breg13: +## clang --target=arm--none-eabi -march=armv7-a -c debug.c -O1 -g -S -o - + +## void bar(int*); +## void foo(int a) { +## bar(&a); +## } + +# CHECK: Disassembly of section .text: +# CHECK-EMPTY: +# CHECK-NEXT: 00000000 foo: +# CHECK-NEXT: ┠─ a = R0 +# CHECK-NEXT: 0: push {r11, lr} ┃ +# CHECK-NEXT: 4: mov r11, sp ┃ +# CHECK-NEXT: 8: sub sp, sp, #8 ┃ +# CHECK-NEXT: ┃ ┌─ a = [SP+4] +# CHECK-NEXT: c: str r0, [sp, #4] ┻ ╈ +# CHECK-NEXT: 10: add r0, sp, #4 ┃ +# CHECK-NEXT: 14: bl #-8 ┃ +# CHECK-NEXT: 18: mov sp, r11 ┻ +# CHECK-NEXT: 1c: pop {r11, pc} + + + .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 foo + .p2align 2 + .type foo,%function + .code 32 +foo: +.Lfunc_begin0: + .loc 1 2 0 + .fnstart + .cfi_sections .debug_frame + .cfi_startproc + .save {r11, lr} + push {r11, lr} + .cfi_def_cfa_offset 8 + .cfi_offset lr, -4 + .cfi_offset r11, -8 + .setfp r11, sp + mov r11, sp + .cfi_def_cfa_register r11 + .pad #8 + sub sp, sp, #8 + str r0, [sp, #4] +.Ltmp0: + add r0, sp, #4 +.Ltmp1: + .loc 1 3 3 prologue_end + bl bar +.Ltmp2: + .loc 1 4 1 + mov sp, r11 +.Ltmp3: + pop {r11, pc} +.Ltmp4: +.Lfunc_end0: + .size foo, .Lfunc_end0-foo + .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 "foo" +.Linfo_string6: + .asciz "a" + .section .debug_loc,"",%progbits +.Ldebug_loc0: + .long .Lfunc_begin0-.Lfunc_begin0 + .long .Ltmp0-.Lfunc_begin0 + .short 1 + .byte 80 + .long .Ltmp0-.Lfunc_begin0 + .long .Ltmp3-.Lfunc_begin0 + // Modified debug info: + .short 3 // Expr length 3 bytes + .byte 0x92 // DW_OP_bregx + .byte 13 // Register SP + .byte 4 // Offset 4 + // End modified debug info. + .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 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 + .ascii "\211\202\001" + .byte 0 + .byte 49 + .byte 19 + .byte 17 + .byte 1 + .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_end0-.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 + + + .byte 7 + .long .Ldebug_loc0 + .long .Linfo_string6 + .byte 1 + .byte 2 + .long 56 + .byte 8 + .long 38 + .long .Ltmp2 + .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: