From ae4ec62cc9a027ed017f640305be9c3d630f5775 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Mon, 27 May 2019 11:53:24 +0000 Subject: [PATCH] FuncUnwinders: prefer debug_frame over eh_frame The two sections usually contain the same information, and we rarely have both kinds of entries for a single function. However, in theory the debug_frame plan can be more complete, whereas eh_frame is only required to be correct at places where exceptions can be thrown. Reviewers: jasonmolenda, clayborg Subscribers: lldb-commits Differential Revision: https://reviews.llvm.org/D62374 llvm-svn: 361758 --- .../Inputs/prefer-debug-over-eh-frame.s | 38 +++++++++++++++++++ .../Unwind/prefer-debug-over-eh-frame.test | 23 +++++++++++ lldb/source/Symbol/FuncUnwinders.cpp | 8 ++-- 3 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 lldb/lit/Unwind/Inputs/prefer-debug-over-eh-frame.s create mode 100644 lldb/lit/Unwind/prefer-debug-over-eh-frame.test diff --git a/lldb/lit/Unwind/Inputs/prefer-debug-over-eh-frame.s b/lldb/lit/Unwind/Inputs/prefer-debug-over-eh-frame.s new file mode 100644 index 000000000000..c9b7a785c341 --- /dev/null +++ b/lldb/lit/Unwind/Inputs/prefer-debug-over-eh-frame.s @@ -0,0 +1,38 @@ + .cfi_sections .eh_frame, .debug_frame + .text + .globl bar +bar: + .cfi_startproc + leal (%edi, %edi), %eax + ret + .cfi_endproc + + .globl foo +foo: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + call bar + addl $1, %eax + popq %rbp + ret + .cfi_endproc + + .globl asm_main +asm_main: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + movl $47, %edi + + call foo + popq %rbp + .cfi_def_cfa 7, 8 + ret + .cfi_endproc diff --git a/lldb/lit/Unwind/prefer-debug-over-eh-frame.test b/lldb/lit/Unwind/prefer-debug-over-eh-frame.test new file mode 100644 index 000000000000..49113466b607 --- /dev/null +++ b/lldb/lit/Unwind/prefer-debug-over-eh-frame.test @@ -0,0 +1,23 @@ +# Test that we prefer debug_frame over eh_frame unwind plans. They usually +# contain the same information, and we rarely have both kinds of entries for a +# single function. However, in theory the debug_frame plan can be more complete, +# whereas eh_frame is only required to be correct at places where exceptions can +# be thrown. + +# UNSUPPORTED: system-windows +# REQUIRES: target-x86_64, native + +# RUN: %clang %p/Inputs/call-asm.c %p/Inputs/prefer-debug-over-eh-frame.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 + +target modules show-unwind -n foo +# CHECK: Asynchronous (not restricted to call-sites) UnwindPlan is 'DWARF CFI plus augmentation from assembly parsing' +# CHECK: Synchronous (restricted to call-sites) UnwindPlan is 'DWARF CFI' +# CHECK: eh_frame UnwindPlan: +# CHECK: debug_frame UnwindPlan: diff --git a/lldb/source/Symbol/FuncUnwinders.cpp b/lldb/source/Symbol/FuncUnwinders.cpp index 33b2e2959898..09cb9b00aaf3 100644 --- a/lldb/source/Symbol/FuncUnwinders.cpp +++ b/lldb/source/Symbol/FuncUnwinders.cpp @@ -60,10 +60,10 @@ UnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite(Target &target, if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread)) return plan_sp; - if (UnwindPlanSP plan_sp = GetEHFrameUnwindPlan(target)) - return plan_sp; if (UnwindPlanSP plan_sp = GetDebugFrameUnwindPlan(target)) return plan_sp; + if (UnwindPlanSP plan_sp = GetEHFrameUnwindPlan(target)) + return plan_sp; if (UnwindPlanSP plan_sp = GetCompactUnwindUnwindPlan(target)) return plan_sp; if (UnwindPlanSP plan_sp = GetArmUnwindUnwindPlan(target)) @@ -362,10 +362,10 @@ UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target, 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)) return plan_sp; + if (UnwindPlanSP plan_sp = GetEHFrameAugmentedUnwindPlan(target, thread)) + return plan_sp; return assembly_sp; }