Path: blob/main/contrib/llvm-project/lldb/source/Symbol/FuncUnwinders.cpp
39587 views
//===-- FuncUnwinders.cpp -------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Symbol/FuncUnwinders.h"9#include "lldb/Core/Address.h"10#include "lldb/Core/AddressRange.h"11#include "lldb/Symbol/ArmUnwindInfo.h"12#include "lldb/Symbol/CallFrameInfo.h"13#include "lldb/Symbol/CompactUnwindInfo.h"14#include "lldb/Symbol/DWARFCallFrameInfo.h"15#include "lldb/Symbol/ObjectFile.h"16#include "lldb/Symbol/SymbolFile.h"17#include "lldb/Symbol/UnwindPlan.h"18#include "lldb/Symbol/UnwindTable.h"19#include "lldb/Target/ABI.h"20#include "lldb/Target/ExecutionContext.h"21#include "lldb/Target/Process.h"22#include "lldb/Target/RegisterContext.h"23#include "lldb/Target/RegisterNumber.h"24#include "lldb/Target/Target.h"25#include "lldb/Target/Thread.h"26#include "lldb/Target/UnwindAssembly.h"2728#include <memory>2930using namespace lldb;31using namespace lldb_private;3233/// constructor3435FuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, AddressRange range)36: m_unwind_table(unwind_table), m_range(range), m_mutex(),37m_unwind_plan_assembly_sp(), m_unwind_plan_eh_frame_sp(),38m_unwind_plan_eh_frame_augmented_sp(), m_unwind_plan_compact_unwind(),39m_unwind_plan_arm_unwind_sp(), m_unwind_plan_fast_sp(),40m_unwind_plan_arch_default_sp(),41m_unwind_plan_arch_default_at_func_entry_sp(),42m_tried_unwind_plan_assembly(false), m_tried_unwind_plan_eh_frame(false),43m_tried_unwind_plan_object_file(false),44m_tried_unwind_plan_debug_frame(false),45m_tried_unwind_plan_object_file_augmented(false),46m_tried_unwind_plan_eh_frame_augmented(false),47m_tried_unwind_plan_debug_frame_augmented(false),48m_tried_unwind_plan_compact_unwind(false),49m_tried_unwind_plan_arm_unwind(false),50m_tried_unwind_plan_symbol_file(false), m_tried_unwind_fast(false),51m_tried_unwind_arch_default(false),52m_tried_unwind_arch_default_at_func_entry(false),53m_first_non_prologue_insn() {}5455/// destructor5657FuncUnwinders::~FuncUnwinders() = default;5859UnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite(Target &target,60Thread &thread) {61std::lock_guard<std::recursive_mutex> guard(m_mutex);6263if (UnwindPlanSP plan_sp = GetObjectFileUnwindPlan(target))64return plan_sp;65if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread))66return plan_sp;67if (UnwindPlanSP plan_sp = GetDebugFrameUnwindPlan(target))68return plan_sp;69if (UnwindPlanSP plan_sp = GetEHFrameUnwindPlan(target))70return plan_sp;71if (UnwindPlanSP plan_sp = GetCompactUnwindUnwindPlan(target))72return plan_sp;73if (UnwindPlanSP plan_sp = GetArmUnwindUnwindPlan(target))74return plan_sp;7576return nullptr;77}7879UnwindPlanSP FuncUnwinders::GetCompactUnwindUnwindPlan(Target &target) {80std::lock_guard<std::recursive_mutex> guard(m_mutex);81if (m_unwind_plan_compact_unwind.size() > 0)82return m_unwind_plan_compact_unwind[0]; // FIXME support multiple compact83// unwind plans for one func84if (m_tried_unwind_plan_compact_unwind)85return UnwindPlanSP();8687m_tried_unwind_plan_compact_unwind = true;88if (m_range.GetBaseAddress().IsValid()) {89Address current_pc(m_range.GetBaseAddress());90CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo();91if (compact_unwind) {92UnwindPlanSP unwind_plan_sp(new UnwindPlan(lldb::eRegisterKindGeneric));93if (compact_unwind->GetUnwindPlan(target, current_pc, *unwind_plan_sp)) {94m_unwind_plan_compact_unwind.push_back(unwind_plan_sp);95return m_unwind_plan_compact_unwind[0]; // FIXME support multiple96// compact unwind plans for one97// func98}99}100}101return UnwindPlanSP();102}103104lldb::UnwindPlanSP FuncUnwinders::GetObjectFileUnwindPlan(Target &target) {105std::lock_guard<std::recursive_mutex> guard(m_mutex);106if (m_unwind_plan_object_file_sp.get() ||107m_tried_unwind_plan_object_file)108return m_unwind_plan_object_file_sp;109110m_tried_unwind_plan_object_file = true;111if (m_range.GetBaseAddress().IsValid()) {112CallFrameInfo *object_file_frame = m_unwind_table.GetObjectFileUnwindInfo();113if (object_file_frame) {114m_unwind_plan_object_file_sp =115std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);116if (!object_file_frame->GetUnwindPlan(m_range,117*m_unwind_plan_object_file_sp))118m_unwind_plan_object_file_sp.reset();119}120}121return m_unwind_plan_object_file_sp;122}123124UnwindPlanSP FuncUnwinders::GetEHFrameUnwindPlan(Target &target) {125std::lock_guard<std::recursive_mutex> guard(m_mutex);126if (m_unwind_plan_eh_frame_sp.get() || m_tried_unwind_plan_eh_frame)127return m_unwind_plan_eh_frame_sp;128129m_tried_unwind_plan_eh_frame = true;130if (m_range.GetBaseAddress().IsValid()) {131DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();132if (eh_frame) {133m_unwind_plan_eh_frame_sp =134std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);135if (!eh_frame->GetUnwindPlan(m_range, *m_unwind_plan_eh_frame_sp))136m_unwind_plan_eh_frame_sp.reset();137}138}139return m_unwind_plan_eh_frame_sp;140}141142UnwindPlanSP FuncUnwinders::GetDebugFrameUnwindPlan(Target &target) {143std::lock_guard<std::recursive_mutex> guard(m_mutex);144if (m_unwind_plan_debug_frame_sp || m_tried_unwind_plan_debug_frame)145return m_unwind_plan_debug_frame_sp;146147m_tried_unwind_plan_debug_frame = true;148if (m_range.GetBaseAddress().IsValid()) {149DWARFCallFrameInfo *debug_frame = m_unwind_table.GetDebugFrameInfo();150if (debug_frame) {151m_unwind_plan_debug_frame_sp =152std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);153if (!debug_frame->GetUnwindPlan(m_range, *m_unwind_plan_debug_frame_sp))154m_unwind_plan_debug_frame_sp.reset();155}156}157return m_unwind_plan_debug_frame_sp;158}159160UnwindPlanSP FuncUnwinders::GetArmUnwindUnwindPlan(Target &target) {161std::lock_guard<std::recursive_mutex> guard(m_mutex);162if (m_unwind_plan_arm_unwind_sp.get() || m_tried_unwind_plan_arm_unwind)163return m_unwind_plan_arm_unwind_sp;164165m_tried_unwind_plan_arm_unwind = true;166if (m_range.GetBaseAddress().IsValid()) {167Address current_pc(m_range.GetBaseAddress());168ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo();169if (arm_unwind_info) {170m_unwind_plan_arm_unwind_sp =171std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);172if (!arm_unwind_info->GetUnwindPlan(target, current_pc,173*m_unwind_plan_arm_unwind_sp))174m_unwind_plan_arm_unwind_sp.reset();175}176}177return m_unwind_plan_arm_unwind_sp;178}179180namespace {181class RegisterContextToInfo: public SymbolFile::RegisterInfoResolver {182public:183RegisterContextToInfo(RegisterContext &ctx) : m_ctx(ctx) {}184185const RegisterInfo *ResolveName(llvm::StringRef name) const override {186return m_ctx.GetRegisterInfoByName(name);187}188const RegisterInfo *ResolveNumber(lldb::RegisterKind kind,189uint32_t number) const override {190return m_ctx.GetRegisterInfo(kind, number);191}192193private:194RegisterContext &m_ctx;195};196} // namespace197198UnwindPlanSP FuncUnwinders::GetSymbolFileUnwindPlan(Thread &thread) {199std::lock_guard<std::recursive_mutex> guard(m_mutex);200if (m_unwind_plan_symbol_file_sp.get() || m_tried_unwind_plan_symbol_file)201return m_unwind_plan_symbol_file_sp;202203m_tried_unwind_plan_symbol_file = true;204if (SymbolFile *symfile = m_unwind_table.GetSymbolFile()) {205m_unwind_plan_symbol_file_sp = symfile->GetUnwindPlan(206m_range.GetBaseAddress(),207RegisterContextToInfo(*thread.GetRegisterContext()));208}209return m_unwind_plan_symbol_file_sp;210}211212UnwindPlanSP213FuncUnwinders::GetObjectFileAugmentedUnwindPlan(Target &target,214Thread &thread) {215std::lock_guard<std::recursive_mutex> guard(m_mutex);216if (m_unwind_plan_object_file_augmented_sp.get() ||217m_tried_unwind_plan_object_file_augmented)218return m_unwind_plan_object_file_augmented_sp;219220m_tried_unwind_plan_object_file_augmented = true;221222UnwindPlanSP object_file_unwind_plan = GetObjectFileUnwindPlan(target);223if (!object_file_unwind_plan)224return m_unwind_plan_object_file_augmented_sp;225226m_unwind_plan_object_file_augmented_sp =227std::make_shared<UnwindPlan>(*object_file_unwind_plan);228229// Augment the instructions with epilogue descriptions if necessary230// so the UnwindPlan can be used at any instruction in the function.231232UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));233if (assembly_profiler_sp) {234if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite(235m_range, thread, *m_unwind_plan_object_file_augmented_sp)) {236m_unwind_plan_object_file_augmented_sp.reset();237}238} else {239m_unwind_plan_object_file_augmented_sp.reset();240}241return m_unwind_plan_object_file_augmented_sp;242}243244UnwindPlanSP FuncUnwinders::GetEHFrameAugmentedUnwindPlan(Target &target,245Thread &thread) {246std::lock_guard<std::recursive_mutex> guard(m_mutex);247if (m_unwind_plan_eh_frame_augmented_sp.get() ||248m_tried_unwind_plan_eh_frame_augmented)249return m_unwind_plan_eh_frame_augmented_sp;250251// Only supported on x86 architectures where we get eh_frame from the252// compiler that describes the prologue instructions perfectly, and sometimes253// the epilogue instructions too.254if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 &&255target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 &&256target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) {257m_tried_unwind_plan_eh_frame_augmented = true;258return m_unwind_plan_eh_frame_augmented_sp;259}260261m_tried_unwind_plan_eh_frame_augmented = true;262263UnwindPlanSP eh_frame_plan = GetEHFrameUnwindPlan(target);264if (!eh_frame_plan)265return m_unwind_plan_eh_frame_augmented_sp;266267m_unwind_plan_eh_frame_augmented_sp =268std::make_shared<UnwindPlan>(*eh_frame_plan);269270// Augment the eh_frame instructions with epilogue descriptions if necessary271// so the UnwindPlan can be used at any instruction in the function.272273UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));274if (assembly_profiler_sp) {275if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite(276m_range, thread, *m_unwind_plan_eh_frame_augmented_sp)) {277m_unwind_plan_eh_frame_augmented_sp.reset();278}279} else {280m_unwind_plan_eh_frame_augmented_sp.reset();281}282return m_unwind_plan_eh_frame_augmented_sp;283}284285UnwindPlanSP FuncUnwinders::GetDebugFrameAugmentedUnwindPlan(Target &target,286Thread &thread) {287std::lock_guard<std::recursive_mutex> guard(m_mutex);288if (m_unwind_plan_debug_frame_augmented_sp.get() ||289m_tried_unwind_plan_debug_frame_augmented)290return m_unwind_plan_debug_frame_augmented_sp;291292// Only supported on x86 architectures where we get debug_frame from the293// compiler that describes the prologue instructions perfectly, and sometimes294// the epilogue instructions too.295if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 &&296target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 &&297target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) {298m_tried_unwind_plan_debug_frame_augmented = true;299return m_unwind_plan_debug_frame_augmented_sp;300}301302m_tried_unwind_plan_debug_frame_augmented = true;303304UnwindPlanSP debug_frame_plan = GetDebugFrameUnwindPlan(target);305if (!debug_frame_plan)306return m_unwind_plan_debug_frame_augmented_sp;307308m_unwind_plan_debug_frame_augmented_sp =309std::make_shared<UnwindPlan>(*debug_frame_plan);310311// Augment the debug_frame instructions with epilogue descriptions if312// necessary so the UnwindPlan can be used at any instruction in the313// function.314315UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));316if (assembly_profiler_sp) {317if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite(318m_range, thread, *m_unwind_plan_debug_frame_augmented_sp)) {319m_unwind_plan_debug_frame_augmented_sp.reset();320}321} else322m_unwind_plan_debug_frame_augmented_sp.reset();323return m_unwind_plan_debug_frame_augmented_sp;324}325326UnwindPlanSP FuncUnwinders::GetAssemblyUnwindPlan(Target &target,327Thread &thread) {328std::lock_guard<std::recursive_mutex> guard(m_mutex);329if (m_unwind_plan_assembly_sp.get() || m_tried_unwind_plan_assembly ||330!m_unwind_table.GetAllowAssemblyEmulationUnwindPlans()) {331return m_unwind_plan_assembly_sp;332}333334m_tried_unwind_plan_assembly = true;335336UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));337if (assembly_profiler_sp) {338m_unwind_plan_assembly_sp =339std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);340if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly(341m_range, thread, *m_unwind_plan_assembly_sp)) {342m_unwind_plan_assembly_sp.reset();343}344}345return m_unwind_plan_assembly_sp;346}347348// This method compares the pc unwind rule in the first row of two UnwindPlans.349// If they have the same way of getting the pc value (e.g. "CFA - 8" + "CFA is350// sp"), then it will return LazyBoolTrue.351LazyBool FuncUnwinders::CompareUnwindPlansForIdenticalInitialPCLocation(352Thread &thread, const UnwindPlanSP &a, const UnwindPlanSP &b) {353LazyBool plans_are_identical = eLazyBoolCalculate;354355RegisterNumber pc_reg(thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);356uint32_t pc_reg_lldb_regnum = pc_reg.GetAsKind(eRegisterKindLLDB);357358if (a.get() && b.get()) {359UnwindPlan::RowSP a_first_row = a->GetRowAtIndex(0);360UnwindPlan::RowSP b_first_row = b->GetRowAtIndex(0);361362if (a_first_row.get() && b_first_row.get()) {363UnwindPlan::Row::RegisterLocation a_pc_regloc;364UnwindPlan::Row::RegisterLocation b_pc_regloc;365366a_first_row->GetRegisterInfo(pc_reg_lldb_regnum, a_pc_regloc);367b_first_row->GetRegisterInfo(pc_reg_lldb_regnum, b_pc_regloc);368369plans_are_identical = eLazyBoolYes;370371if (a_first_row->GetCFAValue() != b_first_row->GetCFAValue()) {372plans_are_identical = eLazyBoolNo;373}374if (a_pc_regloc != b_pc_regloc) {375plans_are_identical = eLazyBoolNo;376}377}378}379return plans_are_identical;380}381382UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target,383Thread &thread) {384UnwindPlanSP eh_frame_sp = GetEHFrameUnwindPlan(target);385if (!eh_frame_sp)386eh_frame_sp = GetDebugFrameUnwindPlan(target);387if (!eh_frame_sp)388eh_frame_sp = GetObjectFileUnwindPlan(target);389UnwindPlanSP arch_default_at_entry_sp =390GetUnwindPlanArchitectureDefaultAtFunctionEntry(thread);391UnwindPlanSP arch_default_sp = GetUnwindPlanArchitectureDefault(thread);392UnwindPlanSP assembly_sp = GetAssemblyUnwindPlan(target, thread);393394// This point of this code is to detect when a function is using a non-395// standard ABI, and the eh_frame correctly describes that alternate ABI.396// This is addressing a specific situation on x86_64 linux systems where one397// function in a library pushes a value on the stack and jumps to another398// function. So using an assembly instruction based unwind will not work399// when you're in the second function - the stack has been modified in a non-400// ABI way. But we have eh_frame that correctly describes how to unwind from401// this location. So we're looking to see if the initial pc register save402// location from the eh_frame is different from the assembly unwind, the arch403// default unwind, and the arch default at initial function entry.404//405// We may have eh_frame that describes the entire function -- or we may have406// eh_frame that only describes the unwind after the prologue has executed --407// so we need to check both the arch default (once the prologue has executed)408// and the arch default at initial function entry. And we may be running on409// a target where we have only some of the assembly/arch default unwind plans410// available.411412if (CompareUnwindPlansForIdenticalInitialPCLocation(413thread, eh_frame_sp, arch_default_at_entry_sp) == eLazyBoolNo &&414CompareUnwindPlansForIdenticalInitialPCLocation(415thread, eh_frame_sp, arch_default_sp) == eLazyBoolNo &&416CompareUnwindPlansForIdenticalInitialPCLocation(417thread, assembly_sp, arch_default_sp) == eLazyBoolNo) {418return eh_frame_sp;419}420421if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread))422return plan_sp;423if (UnwindPlanSP plan_sp = GetDebugFrameAugmentedUnwindPlan(target, thread))424return plan_sp;425if (UnwindPlanSP plan_sp = GetEHFrameAugmentedUnwindPlan(target, thread))426return plan_sp;427if (UnwindPlanSP plan_sp = GetObjectFileAugmentedUnwindPlan(target, thread))428return plan_sp;429430return assembly_sp;431}432433UnwindPlanSP FuncUnwinders::GetUnwindPlanFastUnwind(Target &target,434Thread &thread) {435std::lock_guard<std::recursive_mutex> guard(m_mutex);436if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast)437return m_unwind_plan_fast_sp;438439m_tried_unwind_fast = true;440441UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));442if (assembly_profiler_sp) {443m_unwind_plan_fast_sp =444std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);445if (!assembly_profiler_sp->GetFastUnwindPlan(m_range, thread,446*m_unwind_plan_fast_sp)) {447m_unwind_plan_fast_sp.reset();448}449}450return m_unwind_plan_fast_sp;451}452453UnwindPlanSP FuncUnwinders::GetUnwindPlanArchitectureDefault(Thread &thread) {454std::lock_guard<std::recursive_mutex> guard(m_mutex);455if (m_unwind_plan_arch_default_sp.get() || m_tried_unwind_arch_default)456return m_unwind_plan_arch_default_sp;457458m_tried_unwind_arch_default = true;459460Address current_pc;461ProcessSP process_sp(thread.CalculateProcess());462if (process_sp) {463ABI *abi = process_sp->GetABI().get();464if (abi) {465m_unwind_plan_arch_default_sp =466std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);467if (!abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp)) {468m_unwind_plan_arch_default_sp.reset();469}470}471}472473return m_unwind_plan_arch_default_sp;474}475476UnwindPlanSP477FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry(Thread &thread) {478std::lock_guard<std::recursive_mutex> guard(m_mutex);479if (m_unwind_plan_arch_default_at_func_entry_sp.get() ||480m_tried_unwind_arch_default_at_func_entry)481return m_unwind_plan_arch_default_at_func_entry_sp;482483m_tried_unwind_arch_default_at_func_entry = true;484485Address current_pc;486ProcessSP process_sp(thread.CalculateProcess());487if (process_sp) {488ABI *abi = process_sp->GetABI().get();489if (abi) {490m_unwind_plan_arch_default_at_func_entry_sp =491std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);492if (!abi->CreateFunctionEntryUnwindPlan(493*m_unwind_plan_arch_default_at_func_entry_sp)) {494m_unwind_plan_arch_default_at_func_entry_sp.reset();495}496}497}498499return m_unwind_plan_arch_default_at_func_entry_sp;500}501502Address &FuncUnwinders::GetFirstNonPrologueInsn(Target &target) {503std::lock_guard<std::recursive_mutex> guard(m_mutex);504if (m_first_non_prologue_insn.IsValid())505return m_first_non_prologue_insn;506507ExecutionContext exe_ctx(target.shared_from_this(), false);508UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));509if (assembly_profiler_sp)510assembly_profiler_sp->FirstNonPrologueInsn(m_range, exe_ctx,511m_first_non_prologue_insn);512return m_first_non_prologue_insn;513}514515const Address &FuncUnwinders::GetFunctionStartAddress() const {516return m_range.GetBaseAddress();517}518519lldb::UnwindAssemblySP520FuncUnwinders::GetUnwindAssemblyProfiler(Target &target) {521UnwindAssemblySP assembly_profiler_sp;522if (ArchSpec arch = m_unwind_table.GetArchitecture()) {523arch.MergeFrom(target.GetArchitecture());524assembly_profiler_sp = UnwindAssembly::FindPlugin(arch);525}526return assembly_profiler_sp;527}528529Address FuncUnwinders::GetLSDAAddress(Target &target) {530Address lsda_addr;531532UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target);533if (unwind_plan_sp.get() == nullptr) {534unwind_plan_sp = GetCompactUnwindUnwindPlan(target);535}536if (unwind_plan_sp.get() == nullptr) {537unwind_plan_sp = GetObjectFileUnwindPlan(target);538}539if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) {540lsda_addr = unwind_plan_sp->GetLSDAAddress();541}542return lsda_addr;543}544545Address FuncUnwinders::GetPersonalityRoutinePtrAddress(Target &target) {546Address personality_addr;547548UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target);549if (unwind_plan_sp.get() == nullptr) {550unwind_plan_sp = GetCompactUnwindUnwindPlan(target);551}552if (unwind_plan_sp.get() == nullptr) {553unwind_plan_sp = GetObjectFileUnwindPlan(target);554}555if (unwind_plan_sp.get() &&556unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) {557personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr();558}559560return personality_addr;561}562563564