diff options
Diffstat (limited to 'source/Symbol/FuncUnwinders.cpp')
-rw-r--r-- | source/Symbol/FuncUnwinders.cpp | 164 |
1 files changed, 90 insertions, 74 deletions
diff --git a/source/Symbol/FuncUnwinders.cpp b/source/Symbol/FuncUnwinders.cpp index 35ce72f32b61e..09cb9b00aaf3b 100644 --- a/source/Symbol/FuncUnwinders.cpp +++ b/source/Symbol/FuncUnwinders.cpp @@ -1,9 +1,8 @@ //===-- FuncUnwinders.cpp ----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -14,22 +13,24 @@ #include "lldb/Symbol/CompactUnwindInfo.h" #include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Symbol/UnwindTable.h" #include "lldb/Target/ABI.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" #include "lldb/Target/RegisterNumber.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/UnwindAssembly.h" +#include <memory> + using namespace lldb; using namespace lldb_private; -//------------------------------------------------ /// constructor -//------------------------------------------------ FuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, AddressRange range) : m_unwind_table(unwind_table), m_range(range), m_mutex(), @@ -43,35 +44,35 @@ FuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, AddressRange range) m_tried_unwind_plan_eh_frame_augmented(false), m_tried_unwind_plan_debug_frame_augmented(false), m_tried_unwind_plan_compact_unwind(false), - m_tried_unwind_plan_arm_unwind(false), m_tried_unwind_fast(false), + m_tried_unwind_plan_arm_unwind(false), + m_tried_unwind_plan_symbol_file(false), m_tried_unwind_fast(false), m_tried_unwind_arch_default(false), m_tried_unwind_arch_default_at_func_entry(false), m_first_non_prologue_insn() {} -//------------------------------------------------ /// destructor -//------------------------------------------------ FuncUnwinders::~FuncUnwinders() {} UnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite(Target &target, - int current_offset) { + Thread &thread) { std::lock_guard<std::recursive_mutex> guard(m_mutex); - if (UnwindPlanSP plan_sp = GetEHFrameUnwindPlan(target, current_offset)) + if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread)) return plan_sp; - if (UnwindPlanSP plan_sp = GetDebugFrameUnwindPlan(target, current_offset)) + if (UnwindPlanSP plan_sp = GetDebugFrameUnwindPlan(target)) return plan_sp; - if (UnwindPlanSP plan_sp = GetCompactUnwindUnwindPlan(target, current_offset)) + if (UnwindPlanSP plan_sp = GetEHFrameUnwindPlan(target)) return plan_sp; - if (UnwindPlanSP plan_sp = GetArmUnwindUnwindPlan(target, current_offset)) + if (UnwindPlanSP plan_sp = GetCompactUnwindUnwindPlan(target)) + return plan_sp; + if (UnwindPlanSP plan_sp = GetArmUnwindUnwindPlan(target)) return plan_sp; return nullptr; } -UnwindPlanSP FuncUnwinders::GetCompactUnwindUnwindPlan(Target &target, - int current_offset) { +UnwindPlanSP FuncUnwinders::GetCompactUnwindUnwindPlan(Target &target) { std::lock_guard<std::recursive_mutex> guard(m_mutex); if (m_unwind_plan_compact_unwind.size() > 0) return m_unwind_plan_compact_unwind[0]; // FIXME support multiple compact @@ -82,8 +83,6 @@ UnwindPlanSP FuncUnwinders::GetCompactUnwindUnwindPlan(Target &target, m_tried_unwind_plan_compact_unwind = true; if (m_range.GetBaseAddress().IsValid()) { Address current_pc(m_range.GetBaseAddress()); - if (current_offset != -1) - current_pc.SetOffset(current_pc.GetOffset() + current_offset); CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo(); if (compact_unwind) { UnwindPlanSP unwind_plan_sp(new UnwindPlan(lldb::eRegisterKindGeneric)); @@ -98,53 +97,43 @@ UnwindPlanSP FuncUnwinders::GetCompactUnwindUnwindPlan(Target &target, return UnwindPlanSP(); } -UnwindPlanSP FuncUnwinders::GetEHFrameUnwindPlan(Target &target, - int current_offset) { +UnwindPlanSP FuncUnwinders::GetEHFrameUnwindPlan(Target &target) { std::lock_guard<std::recursive_mutex> guard(m_mutex); if (m_unwind_plan_eh_frame_sp.get() || m_tried_unwind_plan_eh_frame) return m_unwind_plan_eh_frame_sp; m_tried_unwind_plan_eh_frame = true; if (m_range.GetBaseAddress().IsValid()) { - Address current_pc(m_range.GetBaseAddress()); - if (current_offset != -1) - current_pc.SetOffset(current_pc.GetOffset() + current_offset); DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo(); if (eh_frame) { - m_unwind_plan_eh_frame_sp.reset( - new UnwindPlan(lldb::eRegisterKindGeneric)); - if (!eh_frame->GetUnwindPlan(current_pc, *m_unwind_plan_eh_frame_sp)) + m_unwind_plan_eh_frame_sp = + std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); + if (!eh_frame->GetUnwindPlan(m_range, *m_unwind_plan_eh_frame_sp)) m_unwind_plan_eh_frame_sp.reset(); } } return m_unwind_plan_eh_frame_sp; } -UnwindPlanSP FuncUnwinders::GetDebugFrameUnwindPlan(Target &target, - int current_offset) { +UnwindPlanSP FuncUnwinders::GetDebugFrameUnwindPlan(Target &target) { std::lock_guard<std::recursive_mutex> guard(m_mutex); if (m_unwind_plan_debug_frame_sp || m_tried_unwind_plan_debug_frame) return m_unwind_plan_debug_frame_sp; m_tried_unwind_plan_debug_frame = true; if (m_range.GetBaseAddress().IsValid()) { - Address current_pc(m_range.GetBaseAddress()); - if (current_offset != -1) - current_pc.SetOffset(current_pc.GetOffset() + current_offset); DWARFCallFrameInfo *debug_frame = m_unwind_table.GetDebugFrameInfo(); if (debug_frame) { - m_unwind_plan_debug_frame_sp.reset( - new UnwindPlan(lldb::eRegisterKindGeneric)); - if (!debug_frame->GetUnwindPlan(current_pc, - *m_unwind_plan_debug_frame_sp)) + m_unwind_plan_debug_frame_sp = + std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); + if (!debug_frame->GetUnwindPlan(m_range, *m_unwind_plan_debug_frame_sp)) m_unwind_plan_debug_frame_sp.reset(); } } return m_unwind_plan_debug_frame_sp; } -UnwindPlanSP FuncUnwinders::GetArmUnwindUnwindPlan(Target &target, - int current_offset) { +UnwindPlanSP FuncUnwinders::GetArmUnwindUnwindPlan(Target &target) { std::lock_guard<std::recursive_mutex> guard(m_mutex); if (m_unwind_plan_arm_unwind_sp.get() || m_tried_unwind_plan_arm_unwind) return m_unwind_plan_arm_unwind_sp; @@ -152,12 +141,10 @@ UnwindPlanSP FuncUnwinders::GetArmUnwindUnwindPlan(Target &target, m_tried_unwind_plan_arm_unwind = true; if (m_range.GetBaseAddress().IsValid()) { Address current_pc(m_range.GetBaseAddress()); - if (current_offset != -1) - current_pc.SetOffset(current_pc.GetOffset() + current_offset); ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo(); if (arm_unwind_info) { - m_unwind_plan_arm_unwind_sp.reset( - new UnwindPlan(lldb::eRegisterKindGeneric)); + m_unwind_plan_arm_unwind_sp = + std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); if (!arm_unwind_info->GetUnwindPlan(target, current_pc, *m_unwind_plan_arm_unwind_sp)) m_unwind_plan_arm_unwind_sp.reset(); @@ -166,9 +153,40 @@ UnwindPlanSP FuncUnwinders::GetArmUnwindUnwindPlan(Target &target, return m_unwind_plan_arm_unwind_sp; } +namespace { +class RegisterContextToInfo: public SymbolFile::RegisterInfoResolver { +public: + RegisterContextToInfo(RegisterContext &ctx) : m_ctx(ctx) {} + + const RegisterInfo *ResolveName(llvm::StringRef name) const { + return m_ctx.GetRegisterInfoByName(name); + } + const RegisterInfo *ResolveNumber(lldb::RegisterKind kind, + uint32_t number) const { + return m_ctx.GetRegisterInfo(kind, number); + } + +private: + RegisterContext &m_ctx; +}; +} // namespace + +UnwindPlanSP FuncUnwinders::GetSymbolFileUnwindPlan(Thread &thread) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + if (m_unwind_plan_symbol_file_sp.get() || m_tried_unwind_plan_symbol_file) + return m_unwind_plan_symbol_file_sp; + + m_tried_unwind_plan_symbol_file = true; + if (SymbolFile *symfile = m_unwind_table.GetSymbolFile()) { + m_unwind_plan_symbol_file_sp = symfile->GetUnwindPlan( + m_range.GetBaseAddress(), + RegisterContextToInfo(*thread.GetRegisterContext())); + } + return m_unwind_plan_symbol_file_sp; +} + UnwindPlanSP FuncUnwinders::GetEHFrameAugmentedUnwindPlan(Target &target, - Thread &thread, - int current_offset) { + Thread &thread) { std::lock_guard<std::recursive_mutex> guard(m_mutex); if (m_unwind_plan_eh_frame_augmented_sp.get() || m_tried_unwind_plan_eh_frame_augmented) @@ -186,11 +204,12 @@ UnwindPlanSP FuncUnwinders::GetEHFrameAugmentedUnwindPlan(Target &target, m_tried_unwind_plan_eh_frame_augmented = true; - UnwindPlanSP eh_frame_plan = GetEHFrameUnwindPlan(target, current_offset); + UnwindPlanSP eh_frame_plan = GetEHFrameUnwindPlan(target); if (!eh_frame_plan) return m_unwind_plan_eh_frame_augmented_sp; - m_unwind_plan_eh_frame_augmented_sp.reset(new UnwindPlan(*eh_frame_plan)); + m_unwind_plan_eh_frame_augmented_sp = + std::make_shared<UnwindPlan>(*eh_frame_plan); // Augment the eh_frame instructions with epilogue descriptions if necessary // so the UnwindPlan can be used at any instruction in the function. @@ -207,9 +226,8 @@ UnwindPlanSP FuncUnwinders::GetEHFrameAugmentedUnwindPlan(Target &target, return m_unwind_plan_eh_frame_augmented_sp; } -UnwindPlanSP -FuncUnwinders::GetDebugFrameAugmentedUnwindPlan(Target &target, Thread &thread, - int current_offset) { +UnwindPlanSP FuncUnwinders::GetDebugFrameAugmentedUnwindPlan(Target &target, + Thread &thread) { std::lock_guard<std::recursive_mutex> guard(m_mutex); if (m_unwind_plan_debug_frame_augmented_sp.get() || m_tried_unwind_plan_debug_frame_augmented) @@ -227,13 +245,12 @@ FuncUnwinders::GetDebugFrameAugmentedUnwindPlan(Target &target, Thread &thread, m_tried_unwind_plan_debug_frame_augmented = true; - UnwindPlanSP debug_frame_plan = - GetDebugFrameUnwindPlan(target, current_offset); + UnwindPlanSP debug_frame_plan = GetDebugFrameUnwindPlan(target); if (!debug_frame_plan) return m_unwind_plan_debug_frame_augmented_sp; - m_unwind_plan_debug_frame_augmented_sp.reset( - new UnwindPlan(*debug_frame_plan)); + m_unwind_plan_debug_frame_augmented_sp = + std::make_shared<UnwindPlan>(*debug_frame_plan); // Augment the debug_frame instructions with epilogue descriptions if // necessary so the UnwindPlan can be used at any instruction in the @@ -251,8 +268,7 @@ FuncUnwinders::GetDebugFrameAugmentedUnwindPlan(Target &target, Thread &thread, } UnwindPlanSP FuncUnwinders::GetAssemblyUnwindPlan(Target &target, - Thread &thread, - int current_offset) { + Thread &thread) { std::lock_guard<std::recursive_mutex> guard(m_mutex); if (m_unwind_plan_assembly_sp.get() || m_tried_unwind_plan_assembly || !m_unwind_table.GetAllowAssemblyEmulationUnwindPlans()) { @@ -263,7 +279,8 @@ UnwindPlanSP FuncUnwinders::GetAssemblyUnwindPlan(Target &target, UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); if (assembly_profiler_sp) { - m_unwind_plan_assembly_sp.reset(new UnwindPlan(lldb::eRegisterKindGeneric)); + m_unwind_plan_assembly_sp = + std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly( m_range, thread, *m_unwind_plan_assembly_sp)) { m_unwind_plan_assembly_sp.reset(); @@ -307,16 +324,14 @@ LazyBool FuncUnwinders::CompareUnwindPlansForIdenticalInitialPCLocation( } UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target, - Thread &thread, - int current_offset) { - UnwindPlanSP eh_frame_sp = GetEHFrameUnwindPlan(target, current_offset); + Thread &thread) { + UnwindPlanSP eh_frame_sp = GetEHFrameUnwindPlan(target); if (!eh_frame_sp) - eh_frame_sp = GetDebugFrameUnwindPlan(target, current_offset); + eh_frame_sp = GetDebugFrameUnwindPlan(target); UnwindPlanSP arch_default_at_entry_sp = GetUnwindPlanArchitectureDefaultAtFunctionEntry(thread); UnwindPlanSP arch_default_sp = GetUnwindPlanArchitectureDefault(thread); - UnwindPlanSP assembly_sp = - GetAssemblyUnwindPlan(target, thread, current_offset); + UnwindPlanSP assembly_sp = GetAssemblyUnwindPlan(target, thread); // This point of this code is to detect when a function is using a non- // standard ABI, and the eh_frame correctly describes that alternate ABI. @@ -345,11 +360,11 @@ UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target, return eh_frame_sp; } - if (UnwindPlanSP plan_sp = - GetEHFrameAugmentedUnwindPlan(target, thread, current_offset)) + if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread)) + return plan_sp; + if (UnwindPlanSP plan_sp = GetDebugFrameAugmentedUnwindPlan(target, thread)) return plan_sp; - if (UnwindPlanSP plan_sp = - GetDebugFrameAugmentedUnwindPlan(target, thread, current_offset)) + if (UnwindPlanSP plan_sp = GetEHFrameAugmentedUnwindPlan(target, thread)) return plan_sp; return assembly_sp; @@ -365,7 +380,8 @@ UnwindPlanSP FuncUnwinders::GetUnwindPlanFastUnwind(Target &target, UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); if (assembly_profiler_sp) { - m_unwind_plan_fast_sp.reset(new UnwindPlan(lldb::eRegisterKindGeneric)); + m_unwind_plan_fast_sp = + std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); if (!assembly_profiler_sp->GetFastUnwindPlan(m_range, thread, *m_unwind_plan_fast_sp)) { m_unwind_plan_fast_sp.reset(); @@ -386,8 +402,8 @@ UnwindPlanSP FuncUnwinders::GetUnwindPlanArchitectureDefault(Thread &thread) { if (process_sp) { ABI *abi = process_sp->GetABI().get(); if (abi) { - m_unwind_plan_arch_default_sp.reset( - new UnwindPlan(lldb::eRegisterKindGeneric)); + m_unwind_plan_arch_default_sp = + std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); if (!abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp)) { m_unwind_plan_arch_default_sp.reset(); } @@ -411,8 +427,8 @@ FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry(Thread &thread) { if (process_sp) { ABI *abi = process_sp->GetABI().get(); if (abi) { - m_unwind_plan_arch_default_at_func_entry_sp.reset( - new UnwindPlan(lldb::eRegisterKindGeneric)); + m_unwind_plan_arch_default_at_func_entry_sp = + std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); if (!abi->CreateFunctionEntryUnwindPlan( *m_unwind_plan_arch_default_at_func_entry_sp)) { m_unwind_plan_arch_default_at_func_entry_sp.reset(); @@ -453,9 +469,9 @@ FuncUnwinders::GetUnwindAssemblyProfiler(Target &target) { Address FuncUnwinders::GetLSDAAddress(Target &target) { Address lsda_addr; - UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target, -1); + UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target); if (unwind_plan_sp.get() == nullptr) { - unwind_plan_sp = GetCompactUnwindUnwindPlan(target, -1); + unwind_plan_sp = GetCompactUnwindUnwindPlan(target); } if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) { lsda_addr = unwind_plan_sp->GetLSDAAddress(); @@ -466,9 +482,9 @@ Address FuncUnwinders::GetLSDAAddress(Target &target) { Address FuncUnwinders::GetPersonalityRoutinePtrAddress(Target &target) { Address personality_addr; - UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target, -1); + UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target); if (unwind_plan_sp.get() == nullptr) { - unwind_plan_sp = GetCompactUnwindUnwindPlan(target, -1); + unwind_plan_sp = GetCompactUnwindUnwindPlan(target); } if (unwind_plan_sp.get() && unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) { |