This revision was automatically updated to reflect the committed changes. Closed by commit rG2a42a5a2f414 (authored by jingham).
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D71372/new/ https://reviews.llvm.org/D71372 Files: lldb/include/lldb/Target/ThreadPlanStepOut.h lldb/source/Target/ThreadPlanStepOut.cpp lldb/test/Shell/Unwind/Inputs/thread-step-out-ret-addr-check.s lldb/test/Shell/Unwind/thread-step-out-ret-addr-check.test
Index: lldb/test/Shell/Unwind/thread-step-out-ret-addr-check.test =================================================================== --- /dev/null +++ lldb/test/Shell/Unwind/thread-step-out-ret-addr-check.test @@ -0,0 +1,17 @@ +# Test that `thread step-out` fails when the "return address" +# points to non-executable memory. + +# REQUIRES: target-x86_64, native + +# RUN: %clang_host %p/Inputs/call-asm.c %p/Inputs/thread-step-out-ret-addr-check.s -o %t +# RUN: %lldb %t -s %s -b 2>&1 | FileCheck %s + +breakpoint set -n nonstandard_stub +# CHECK: Breakpoint 1: where = {{.*}}`nonstandard_stub + +process launch +# CHECK: stop reason = breakpoint 1.1 + +thread step-out +# CHECK: Could not create return address breakpoint. +# CHECK: Return address (0x{{[a-f0-9]*}}) did not point to executable memory. Index: lldb/test/Shell/Unwind/Inputs/thread-step-out-ret-addr-check.s =================================================================== --- /dev/null +++ lldb/test/Shell/Unwind/Inputs/thread-step-out-ret-addr-check.s @@ -0,0 +1,20 @@ + .text + .globl asm_main +asm_main: + sub $0x8, %rsp + movq $0, (%rsp) + push %rsp + jmp _nonstandard_stub + +# Takes a single pointer argument via the stack, which is nonstandard for x64. +# Executing 'thread step-out' here will initially attempt to write a +# breakpoint to that stack address, but should fail because of the executable +# memory check. +_nonstandard_stub: + mov (%rsp), %rdi + mov (%rdi), %rsi + add $1, %rsi + mov %rsi, (%rdi) + + add $0x10, %rsp + ret Index: lldb/source/Target/ThreadPlanStepOut.cpp =================================================================== --- lldb/source/Target/ThreadPlanStepOut.cpp +++ lldb/source/Target/ThreadPlanStepOut.cpp @@ -126,6 +126,25 @@ if (m_return_addr == LLDB_INVALID_ADDRESS) return; + // Perform some additional validation on the return address. + uint32_t permissions = 0; + if (!m_thread.GetProcess()->GetLoadAddressPermissions(m_return_addr, + permissions)) { + m_constructor_errors.Printf("Return address (0x%" PRIx64 + ") permissions not found.", + m_return_addr); + LLDB_LOGF(log, "ThreadPlanStepOut(%p): %s", static_cast<void *>(this), + m_constructor_errors.GetData()); + return; + } else if (!(permissions & ePermissionsExecutable)) { + m_constructor_errors.Printf("Return address (0x%" PRIx64 + ") did not point to executable memory.", + m_return_addr); + LLDB_LOGF(log, "ThreadPlanStepOut(%p): %s", static_cast<void *>(this), + m_constructor_errors.GetData()); + return; + } + Breakpoint *return_bp = m_thread.CalculateTarget() ->CreateBreakpoint(m_return_addr, true, false) .get(); @@ -238,8 +257,13 @@ } if (m_return_bp_id == LLDB_INVALID_BREAK_ID) { - if (error) + if (error) { error->PutCString("Could not create return address breakpoint."); + if (m_constructor_errors.GetSize() > 0) { + error->PutCString(" "); + error->PutCString(m_constructor_errors.GetString()); + } + } return false; } Index: lldb/include/lldb/Target/ThreadPlanStepOut.h =================================================================== --- lldb/include/lldb/Target/ThreadPlanStepOut.h +++ lldb/include/lldb/Target/ThreadPlanStepOut.h @@ -72,6 +72,7 @@ std::vector<lldb::StackFrameSP> m_stepped_past_frames; lldb::ValueObjectSP m_return_valobj_sp; bool m_calculate_return_value; + StreamString m_constructor_errors; friend lldb::ThreadPlanSP Thread::QueueThreadPlanForStepOut( bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits