labath created this revision. labath added reviewers: jasonmolenda, clayborg. Herald added a subscriber: aprantl.
This behavior is specified in the Section 6.4.2.3 (Register Rule instructions) of the DWARF4 spec. We were not doing that, which meant that any register rule which was relying on the cfa value being there was not evaluated correctly (it was aborted due to "out of bounds" access). I'm not sure how come this wasn't noticed before, but I guess this has something to do with the fact that dwarf unwind expressions are not used very often, and when they are, the situation is so complicated that the CFA is of no use. I noticed this when I started emitting dwarf expressions for the unwind information present in breakpad symbol files. https://reviews.llvm.org/D61018 Files: lit/Unwind/Inputs/eh-frame-dwarf-unwind.s lit/Unwind/eh-frame-dwarf-unwind.test source/Plugins/Process/Utility/RegisterContextLLDB.cpp Index: source/Plugins/Process/Utility/RegisterContextLLDB.cpp =================================================================== --- source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -1507,9 +1507,11 @@ DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr, 0, unwindplan_regloc.GetDWARFExpressionLength()); dwarfexpr.SetRegisterKind(unwindplan_registerkind); + Value cfa_val = Scalar(m_cfa); + cfa_val.SetValueType(Value::eValueTypeLoadAddress); Value result; Status error; - if (dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr, result, + if (dwarfexpr.Evaluate(&exe_ctx, this, 0, &cfa_val, nullptr, result, &error)) { addr_t val; val = result.GetScalar().ULongLong(); Index: lit/Unwind/eh-frame-dwarf-unwind.test =================================================================== --- /dev/null +++ lit/Unwind/eh-frame-dwarf-unwind.test @@ -0,0 +1,22 @@ +# Test handing of dwarf expressions specifying the location of registers, if +# those expressions refer to the frame's CFA value. + +# REQUIRES: target-x86_64, system-linux, native + +# RUN: %clang %p/Inputs/eh-frame-dwarf-unwind.s -o %t +# RUN: %lldb %t -s %s -o exit | FileCheck %s + +breakpoint set -n bar +# CHECK: Breakpoint 1: where = {{.*}}`bar + +process launch +# CHECK: stop reason = breakpoint 1.1 + +thread backtrace +# CHECK: frame #0: {{.*}}`bar +# CHECK: frame #1: {{.*}}`foo + 5 +# CHECK: frame #2: {{.*}}`main + 19 + +target modules show-unwind -n foo +# CHECK: eh_frame UnwindPlan: +# CHECK: row[0]: 0: CFA=rsp +8 => rip=DW_OP_lit8 , DW_OP_minus , DW_OP_deref , DW_OP_const1u 0x47, DW_OP_minus Index: lit/Unwind/Inputs/eh-frame-dwarf-unwind.s =================================================================== --- /dev/null +++ lit/Unwind/Inputs/eh-frame-dwarf-unwind.s @@ -0,0 +1,49 @@ + .text + .globl bar + .type bar, @function +bar: +.LFB0: + .cfi_startproc + leal (%edi, %edi), %eax + ret + .cfi_endproc +.LFE0: + .size bar, .-bar + .globl foo + .type foo, @function +foo: +.LFB1: + .cfi_startproc + .cfi_escape 0x16, 0x10, 0x06, 0x38, 0x1c, 0x06, 0x08, 0x47, 0x1c + call bar + addl $1, %eax + popq %rdi + subq $0x47, %rdi + jmp *%rdi # Return + .cfi_endproc +.LFE1: + .size foo, .-foo + .globl main + .type main, @function +main: +.LFB2: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + movl $47, %edi + + # Non-standard calling convention. The real return address must be + # decremented by 0x47. + leaq 0x47+1f(%rip), %rax + pushq %rax + jmp foo # call +1: + popq %rbp + .cfi_def_cfa 7, 8 + ret + .cfi_endproc +.LFE2: + .size main, .-main
Index: source/Plugins/Process/Utility/RegisterContextLLDB.cpp =================================================================== --- source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -1507,9 +1507,11 @@ DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr, 0, unwindplan_regloc.GetDWARFExpressionLength()); dwarfexpr.SetRegisterKind(unwindplan_registerkind); + Value cfa_val = Scalar(m_cfa); + cfa_val.SetValueType(Value::eValueTypeLoadAddress); Value result; Status error; - if (dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr, result, + if (dwarfexpr.Evaluate(&exe_ctx, this, 0, &cfa_val, nullptr, result, &error)) { addr_t val; val = result.GetScalar().ULongLong(); Index: lit/Unwind/eh-frame-dwarf-unwind.test =================================================================== --- /dev/null +++ lit/Unwind/eh-frame-dwarf-unwind.test @@ -0,0 +1,22 @@ +# Test handing of dwarf expressions specifying the location of registers, if +# those expressions refer to the frame's CFA value. + +# REQUIRES: target-x86_64, system-linux, native + +# RUN: %clang %p/Inputs/eh-frame-dwarf-unwind.s -o %t +# RUN: %lldb %t -s %s -o exit | FileCheck %s + +breakpoint set -n bar +# CHECK: Breakpoint 1: where = {{.*}}`bar + +process launch +# CHECK: stop reason = breakpoint 1.1 + +thread backtrace +# CHECK: frame #0: {{.*}}`bar +# CHECK: frame #1: {{.*}}`foo + 5 +# CHECK: frame #2: {{.*}}`main + 19 + +target modules show-unwind -n foo +# CHECK: eh_frame UnwindPlan: +# CHECK: row[0]: 0: CFA=rsp +8 => rip=DW_OP_lit8 , DW_OP_minus , DW_OP_deref , DW_OP_const1u 0x47, DW_OP_minus Index: lit/Unwind/Inputs/eh-frame-dwarf-unwind.s =================================================================== --- /dev/null +++ lit/Unwind/Inputs/eh-frame-dwarf-unwind.s @@ -0,0 +1,49 @@ + .text + .globl bar + .type bar, @function +bar: +.LFB0: + .cfi_startproc + leal (%edi, %edi), %eax + ret + .cfi_endproc +.LFE0: + .size bar, .-bar + .globl foo + .type foo, @function +foo: +.LFB1: + .cfi_startproc + .cfi_escape 0x16, 0x10, 0x06, 0x38, 0x1c, 0x06, 0x08, 0x47, 0x1c + call bar + addl $1, %eax + popq %rdi + subq $0x47, %rdi + jmp *%rdi # Return + .cfi_endproc +.LFE1: + .size foo, .-foo + .globl main + .type main, @function +main: +.LFB2: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + movl $47, %edi + + # Non-standard calling convention. The real return address must be + # decremented by 0x47. + leaq 0x47+1f(%rip), %rax + pushq %rax + jmp foo # call +1: + popq %rbp + .cfi_def_cfa 7, 8 + ret + .cfi_endproc +.LFE2: + .size main, .-main
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits