labath created this revision. labath added reviewers: jasonmolenda, clayborg.
Previous patch (r360409) introduced the "symbol file unwind plan" concept, but that plan wasn't used for unwinding yet. With this patch, we start to consider the new plan as a possible strategy for both synchronous and asynchronous unwinding. I also add a test that asserts that unwinding via breakpad STACK CFI info works end-to-end. https://reviews.llvm.org/D61853 Files: include/lldb/Symbol/FuncUnwinders.h lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-cfi.dmp lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-cfi.syms lit/SymbolFile/Breakpad/stack-cfi-parsing.test lit/SymbolFile/Breakpad/unwind-via-stack-cfi.test source/Commands/CommandObjectTarget.cpp source/Plugins/Process/Utility/RegisterContextLLDB.cpp source/Symbol/FuncUnwinders.cpp
Index: source/Symbol/FuncUnwinders.cpp =================================================================== --- source/Symbol/FuncUnwinders.cpp +++ source/Symbol/FuncUnwinders.cpp @@ -54,7 +54,8 @@ FuncUnwinders::~FuncUnwinders() {} -UnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite(Target &target) { +UnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite(Target &target, + Thread &thread) { std::lock_guard<std::recursive_mutex> guard(m_mutex); if (UnwindPlanSP plan_sp = GetEHFrameUnwindPlan(target)) @@ -65,6 +66,8 @@ return plan_sp; if (UnwindPlanSP plan_sp = GetArmUnwindUnwindPlan(target)) return plan_sp; + if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread)) + return plan_sp; return nullptr; } @@ -361,6 +364,8 @@ return plan_sp; if (UnwindPlanSP plan_sp = GetDebugFrameAugmentedUnwindPlan(target, thread)) return plan_sp; + if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread)) + return plan_sp; return assembly_sp; } Index: source/Plugins/Process/Utility/RegisterContextLLDB.cpp =================================================================== --- source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -244,8 +244,8 @@ } if (func_unwinders_sp.get() != nullptr) - call_site_unwind_plan = - func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget()); + call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite( + process->GetTarget(), m_thread); if (call_site_unwind_plan.get() != nullptr) { m_fallback_unwind_plan_sp = call_site_unwind_plan; @@ -873,7 +873,8 @@ // location what helps in the most common cases when the instruction // emulation fails. UnwindPlanSP call_site_unwind_plan = - func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget()); + func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), + m_thread); if (call_site_unwind_plan && call_site_unwind_plan.get() != unwind_plan_sp.get() && call_site_unwind_plan->GetSourceName() != @@ -909,8 +910,8 @@ // Typically this is unwind info from an eh_frame section intended for // exception handling; only valid at call sites if (process) { - unwind_plan_sp = - func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget()); + unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite( + process->GetTarget(), m_thread); } int valid_offset = -1; if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) { @@ -940,7 +941,8 @@ // code it is often written in a way that it valid at all location what // helps in the most common cases when the instruction emulation fails. UnwindPlanSP call_site_unwind_plan = - func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget()); + func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), + m_thread); if (call_site_unwind_plan && call_site_unwind_plan.get() != unwind_plan_sp.get() && call_site_unwind_plan->GetSourceName() != Index: source/Commands/CommandObjectTarget.cpp =================================================================== --- source/Commands/CommandObjectTarget.cpp +++ source/Commands/CommandObjectTarget.cpp @@ -3521,7 +3521,7 @@ non_callsite_unwind_plan->GetSourceName().AsCString()); } UnwindPlanSP callsite_unwind_plan = - func_unwinders_sp->GetUnwindPlanAtCallSite(*target); + func_unwinders_sp->GetUnwindPlanAtCallSite(*target, *thread); if (callsite_unwind_plan) { result.GetOutputStream().Printf( "Synchronous (restricted to call-sites) UnwindPlan is '%s'\n", Index: lit/SymbolFile/Breakpad/unwind-via-stack-cfi.test =================================================================== --- /dev/null +++ lit/SymbolFile/Breakpad/unwind-via-stack-cfi.test @@ -0,0 +1,21 @@ +# RUN: %lldb -c %S/Inputs/unwind-via-stack-cfi.dmp \ +# RUN: -o "target symbols add %S/Inputs/unwind-via-stack-cfi.syms" -s %s -b\ +# RUN: | FileCheck %s + +image show-unwind -n bar +# CHECK-LABEL: image show-unwind -n bar +# CHECK: Asynchronous (not restricted to call-sites) UnwindPlan is 'breakpad STACK CFI' +# CHECK: Synchronous (restricted to call-sites) UnwindPlan is 'breakpad STACK CFI' +# CHECK: Symbol file UnwindPlan: +# CHECK-NEXT: This UnwindPlan originally sourced from breakpad STACK CFI +# CHECK-NEXT: This UnwindPlan is sourced from the compiler: yes. +# CHECK-NEXT: This UnwindPlan is valid at all instruction locations: no. +# CHECK-NEXT: Address range of this UnwindPlan: [linux-x86_64_not_crashed..module_image + 1056-0x0000000000000449) +# CHECK-NEXT: row[0]: 0: CFA=DW_OP_breg6 +0, DW_OP_deref => rbp=DW_OP_pick 0x00, DW_OP_deref rsp=DW_OP_pick 0x00, DW_OP_consts +16, DW_OP_plus rip=DW_OP_pick 0x00, DW_OP_consts +8, DW_OP_plus , DW_OP_deref + +thread backtrace +# CHECK-LABEL: thread backtrace +# CHECK: frame #0: 0x00007f6b5a9ebfc3 libbreakpad.so +# CHECK: frame #1: 0x0000000000400430 linux-x86_64_not_crashed`bar + 16 +# CHECK: frame #2: 0x0000000000400497 linux-x86_64_not_crashed`_start + 23 +# CHECK-NOT: frame Index: lit/SymbolFile/Breakpad/stack-cfi-parsing.test =================================================================== --- lit/SymbolFile/Breakpad/stack-cfi-parsing.test +++ lit/SymbolFile/Breakpad/stack-cfi-parsing.test @@ -4,6 +4,8 @@ image show-unwind -n func0 # CHECK-LABEL: image show-unwind -n func0 +# CHECK: Asynchronous (not restricted to call-sites) UnwindPlan is 'breakpad STACK CFI' +# CHECK: Synchronous (restricted to call-sites) UnwindPlan is 'breakpad STACK CFI' # CHECK: Symbol file UnwindPlan: # CHECK-NEXT: This UnwindPlan originally sourced from breakpad STACK CFI # CHECK-NEXT: This UnwindPlan is sourced from the compiler: yes. @@ -42,6 +44,8 @@ # Finally, try an unwind plan with just a single row image show-unwind -n func9 # CHECK-LABEL: image show-unwind -n func9 +# CHECK: Asynchronous (not restricted to call-sites) UnwindPlan is 'breakpad STACK CFI' +# CHECK: Synchronous (restricted to call-sites) UnwindPlan is 'breakpad STACK CFI' # CHECK: Symbol file UnwindPlan: # CHECK: Address range of this UnwindPlan: [stack-cfi-parsing.out..module_image + 9-0x000000000000000a) # CHECK: row[0]: 0: CFA=DW_OP_breg6 +0 => rip=DW_OP_breg0 +0 Index: lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-cfi.syms =================================================================== --- /dev/null +++ lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-cfi.syms @@ -0,0 +1,6 @@ +MODULE Linux x86_64 603FCF6CA7FF4BCC86AE8FF44DB2576A0 linux-x86_64_not_crashed +INFO CODE_ID 6CCF3F60FFA7CC4B86AE8FF44DB2576A68983611 +PUBLIC 420 0 bar +PUBLIC 450 0 foo +PUBLIC 480 0 _start +STACK CFI INIT 420 29 .cfa: $rbp ^ .ra: .cfa 8 + ^ $rsp: .cfa 16 + $rbp: .cfa ^ Index: include/lldb/Symbol/FuncUnwinders.h =================================================================== --- include/lldb/Symbol/FuncUnwinders.h +++ include/lldb/Symbol/FuncUnwinders.h @@ -35,7 +35,7 @@ ~FuncUnwinders(); - lldb::UnwindPlanSP GetUnwindPlanAtCallSite(Target &target); + lldb::UnwindPlanSP GetUnwindPlanAtCallSite(Target &target, Thread &thread); lldb::UnwindPlanSP GetUnwindPlanAtNonCallSite(Target &target, lldb_private::Thread &thread);
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits