Skip to content

Commit

Permalink
[FuncUnwinders] Use "symbol file" unwind plans for unwinding
Browse files Browse the repository at this point in the history
Summary:
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.

Reviewers: jasonmolenda, clayborg

Subscribers: lldb-commits, amccarth, markmentovai

Differential Revision: https://reviews.llvm.org/D61853

llvm-svn: 361618
  • Loading branch information
labath committed May 24, 2019
1 parent 7d4a678 commit 1a0312c
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 9 deletions.
2 changes: 1 addition & 1 deletion lldb/include/lldb/Symbol/FuncUnwinders.h
Expand Up @@ -35,7 +35,7 @@ class FuncUnwinders {

~FuncUnwinders();

lldb::UnwindPlanSP GetUnwindPlanAtCallSite(Target &target);
lldb::UnwindPlanSP GetUnwindPlanAtCallSite(Target &target, Thread &thread);

lldb::UnwindPlanSP GetUnwindPlanAtNonCallSite(Target &target,
lldb_private::Thread &thread);
Expand Down
6 changes: 6 additions & 0 deletions lldb/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 ^
43 changes: 43 additions & 0 deletions lldb/lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-cfi.yaml
@@ -0,0 +1,43 @@
--- !minidump
Streams:
- Type: ThreadList
Threads:
- Thread Id: 0x000074F3
Context: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B001000000000006CAE000000006B7FC05A0000C81D415A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A2BF9E5A6B7F0000000000000000000000000000000000008850C14BFD7F00009850C14BFD7F00000100000000000000B04AC14BFD7F0000000000000000000060812D01000000000800000000000000B065E05A6B7F00008004400000000000E050C14BFD7F00000000000000000000000000000000000030044000000000007F03FFFF0000FFFFFFFFFFFF000000000000000000000000801F00006B7F00000400000000000000B84CC14BFD7F0000304D405A6B7F0000C84DC14BFD7F0000C0AA405A6B7F00004F033D0000000000B84DC14BFD7F0000E84DC14BFD7F0000000000000000000000000000000000000070E05A6B7F000078629E5A6B7F0000C81D415A6B7F0000804F9E5A6B7F00000000000001000000E603000001000000E093115A6B7F0000804EC14BFD7F0000584EC14BFD7F000099ADC05A6B7F00000100000000000000AAAAD77D0000000002000000000000000800000000000000B065E05A6B7F0000E6B7C05A6B7F0000010000006B7F0000884DC14BFD7F0000106F7C5A6B7F0000984EC14BFD7F0000488B7C5A6B7F0000C4A71CB90000000001000000000000000800000000000000B065E05A6B7F000048B6C05A6B7F0000702AE25A6B7F0000D84DC14BFD7F000030489E5A6B7F0000E84EC14BFD7F0000E05E9E5A6B7F00000991F0460000000001000000000000000800000000000000B065E05A6B7F000048B6C05A6B7F00000100000000000000284EC14BFD7F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Stack:
Start of Memory Range: 0x00007FFD4BC15080
Content: 30044000000000000000000000000000FFFFFFFF03000000B850C14BFD7F0000670440000000000000000000000000000000000001000000D850C14BFD7F0000970440000000000000000000000000000000000000000000000000000000000001000000000000009F67C14BFD7F00000000000000000000BA67C14BFD7F0000
- Type: ModuleList
Modules:
- Base of Image: 0x0000000000400000
Size of Image: 0x00001000
Module Name: '/tmp/unwind-via-stack-cfi'
CodeView Record: 4C4570426CCF3F60FFA7CC4B86AE8FF44DB2576A68983611
- Type: MemoryList
Memory Ranges:
- Start of Memory Range: 0x00007FFD4BC15080
Content: 30044000000000000000000000000000FFFFFFFF03000000B850C14BFD7F0000670440000000000000000000000000000000000001000000D850C14BFD7F0000970440000000000000000000000000000000000000000000000000000000000001000000000000009F67C14BFD7F00000000000000000000BA67C14BFD7F0000
- Type: SystemInfo
Processor Arch: AMD64
Processor Level: 6
Processor Revision: 15876
Number of Processors: 40
Platform ID: Linux
CSD Version: 'Linux 3.13.0-91-generic'
CPU:
Vendor ID: GenuineIntel
Version Info: 0x00000000
Feature Info: 0x00000000
- Type: LinuxProcStatus
Text: |
Name: unwind-via-stack-cfi
State: t (tracing stop)
Tgid: 29939
Ngid: 0
Pid: 29939
PPid: 29370
TracerPid: 29940
Uid: 1001 1001 1001 1001
Gid: 1001 1001 1001 1001
...
4 changes: 4 additions & 0 deletions lldb/lit/SymbolFile/Breakpad/stack-cfi-parsing.test
Expand Up @@ -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.
Expand Down Expand Up @@ -42,6 +44,8 @@ image show-unwind -n func7
# 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
Expand Down
20 changes: 20 additions & 0 deletions lldb/lit/SymbolFile/Breakpad/unwind-via-stack-cfi.test
@@ -0,0 +1,20 @@
# RUN: yaml2obj %S/Inputs/unwind-via-stack-cfi.yaml > %t
# RUN: %lldb -c %t -o "target symbols add %S/Inputs/unwind-via-stack-cfi.syms" \
# RUN: -s %s -b | 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: [unwind-via-stack-cfi..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: 0x0000000000400430 unwind-via-stack-cfi`bar + 16
# CHECK: frame #1: 0x0000000000400497 unwind-via-stack-cfi`_start + 23
# CHECK-NOT: frame
2 changes: 1 addition & 1 deletion lldb/source/Commands/CommandObjectTarget.cpp
Expand Up @@ -3521,7 +3521,7 @@ class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed {
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",
Expand Down
14 changes: 8 additions & 6 deletions lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
Expand Up @@ -244,8 +244,8 @@ void RegisterContextLLDB::InitializeZerothFrame() {
}

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;
Expand Down Expand Up @@ -873,7 +873,8 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
// 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() !=
Expand Down Expand Up @@ -909,8 +910,8 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
// 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)) {
Expand Down Expand Up @@ -940,7 +941,8 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
// 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() !=
Expand Down
7 changes: 6 additions & 1 deletion lldb/source/Symbol/FuncUnwinders.cpp
Expand Up @@ -54,9 +54,12 @@ FuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, AddressRange range)

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 = GetSymbolFileUnwindPlan(thread))
return plan_sp;
if (UnwindPlanSP plan_sp = GetEHFrameUnwindPlan(target))
return plan_sp;
if (UnwindPlanSP plan_sp = GetDebugFrameUnwindPlan(target))
Expand Down Expand Up @@ -357,6 +360,8 @@ UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target,
return eh_frame_sp;
}

if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread))
return plan_sp;
if (UnwindPlanSP plan_sp = GetEHFrameAugmentedUnwindPlan(target, thread))
return plan_sp;
if (UnwindPlanSP plan_sp = GetDebugFrameAugmentedUnwindPlan(target, thread))
Expand Down

0 comments on commit 1a0312c

Please sign in to comment.