FuncUnwinders.cpp revision 321369
1253208Sandre//===-- FuncUnwinders.cpp ----------------------------------*- C++ -*-===// 2253208Sandre// 3253208Sandre// The LLVM Compiler Infrastructure 4253208Sandre// 5253208Sandre// This file is distributed under the University of Illinois Open Source 6253208Sandre// License. See LICENSE.TXT for details. 7253208Sandre// 8253208Sandre//===----------------------------------------------------------------------===// 9253208Sandre 10253208Sandre#include "lldb/Symbol/FuncUnwinders.h" 11253208Sandre#include "lldb/Core/Address.h" 12253208Sandre#include "lldb/Core/AddressRange.h" 13253208Sandre#include "lldb/Symbol/ArmUnwindInfo.h" 14253208Sandre#include "lldb/Symbol/CompactUnwindInfo.h" 15253208Sandre#include "lldb/Symbol/DWARFCallFrameInfo.h" 16253208Sandre#include "lldb/Symbol/ObjectFile.h" 17253208Sandre#include "lldb/Symbol/UnwindPlan.h" 18253208Sandre#include "lldb/Symbol/UnwindTable.h" 19253208Sandre#include "lldb/Target/ABI.h" 20253208Sandre#include "lldb/Target/ExecutionContext.h" 21253208Sandre#include "lldb/Target/Process.h" 22253208Sandre#include "lldb/Target/RegisterNumber.h" 23253208Sandre#include "lldb/Target/Target.h" 24253208Sandre#include "lldb/Target/Thread.h" 25253208Sandre#include "lldb/Target/UnwindAssembly.h" 26253208Sandre 27253208Sandreusing namespace lldb; 28253208Sandreusing namespace lldb_private; 29253208Sandre 30253208Sandre//------------------------------------------------ 31253208Sandre/// constructor 32253208Sandre//------------------------------------------------ 33253208Sandre 34253208SandreFuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, AddressRange range) 35253208Sandre : m_unwind_table(unwind_table), m_range(range), m_mutex(), 36253208Sandre m_unwind_plan_assembly_sp(), m_unwind_plan_eh_frame_sp(), 37253208Sandre m_unwind_plan_eh_frame_augmented_sp(), m_unwind_plan_compact_unwind(), 38253208Sandre m_unwind_plan_arm_unwind_sp(), m_unwind_plan_fast_sp(), 39253208Sandre m_unwind_plan_arch_default_sp(), 40253208Sandre m_unwind_plan_arch_default_at_func_entry_sp(), 41253208Sandre m_tried_unwind_plan_assembly(false), m_tried_unwind_plan_eh_frame(false), 42253208Sandre m_tried_unwind_plan_debug_frame(false), 43253208Sandre m_tried_unwind_plan_eh_frame_augmented(false), 44253208Sandre m_tried_unwind_plan_debug_frame_augmented(false), 45253208Sandre m_tried_unwind_plan_compact_unwind(false), 46253208Sandre m_tried_unwind_plan_arm_unwind(false), m_tried_unwind_fast(false), 47253208Sandre m_tried_unwind_arch_default(false), 48253208Sandre m_tried_unwind_arch_default_at_func_entry(false), 49253208Sandre m_first_non_prologue_insn() {} 50253208Sandre 51253208Sandre//------------------------------------------------ 52253208Sandre/// destructor 53253208Sandre//------------------------------------------------ 54253208Sandre 55253208SandreFuncUnwinders::~FuncUnwinders() {} 56253208Sandre 57253208SandreUnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite(Target &target, 58253208Sandre int current_offset) { 59253208Sandre std::lock_guard<std::recursive_mutex> guard(m_mutex); 60253208Sandre 61253208Sandre if (UnwindPlanSP plan_sp = GetEHFrameUnwindPlan(target, current_offset)) 62253208Sandre return plan_sp; 63253208Sandre if (UnwindPlanSP plan_sp = GetDebugFrameUnwindPlan(target, current_offset)) 64253208Sandre return plan_sp; 65253208Sandre if (UnwindPlanSP plan_sp = GetCompactUnwindUnwindPlan(target, current_offset)) 66253208Sandre return plan_sp; 67253208Sandre if (UnwindPlanSP plan_sp = GetArmUnwindUnwindPlan(target, current_offset)) 68253208Sandre return plan_sp; 69253208Sandre 70253208Sandre return nullptr; 71253208Sandre} 72253208Sandre 73253208SandreUnwindPlanSP FuncUnwinders::GetCompactUnwindUnwindPlan(Target &target, 74253208Sandre int current_offset) { 75253208Sandre std::lock_guard<std::recursive_mutex> guard(m_mutex); 76253208Sandre if (m_unwind_plan_compact_unwind.size() > 0) 77253208Sandre return m_unwind_plan_compact_unwind[0]; // FIXME support multiple compact 78253208Sandre // unwind plans for one func 79253208Sandre if (m_tried_unwind_plan_compact_unwind) 80253208Sandre return UnwindPlanSP(); 81253208Sandre 82253208Sandre m_tried_unwind_plan_compact_unwind = true; 83253208Sandre if (m_range.GetBaseAddress().IsValid()) { 84253208Sandre Address current_pc(m_range.GetBaseAddress()); 85253208Sandre if (current_offset != -1) 86253208Sandre current_pc.SetOffset(current_pc.GetOffset() + current_offset); 87253208Sandre CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo(); 88253208Sandre if (compact_unwind) { 89253208Sandre UnwindPlanSP unwind_plan_sp(new UnwindPlan(lldb::eRegisterKindGeneric)); 90253208Sandre if (compact_unwind->GetUnwindPlan(target, current_pc, *unwind_plan_sp)) { 91253208Sandre m_unwind_plan_compact_unwind.push_back(unwind_plan_sp); 92253208Sandre return m_unwind_plan_compact_unwind[0]; // FIXME support multiple 93253208Sandre // compact unwind plans for one 94253208Sandre // func 95253208Sandre } 96253208Sandre } 97253208Sandre } 98253208Sandre return UnwindPlanSP(); 99253208Sandre} 100253208Sandre 101253208SandreUnwindPlanSP FuncUnwinders::GetEHFrameUnwindPlan(Target &target, 102253208Sandre int current_offset) { 103253208Sandre std::lock_guard<std::recursive_mutex> guard(m_mutex); 104253208Sandre if (m_unwind_plan_eh_frame_sp.get() || m_tried_unwind_plan_eh_frame) 105253208Sandre return m_unwind_plan_eh_frame_sp; 106253208Sandre 107253208Sandre m_tried_unwind_plan_eh_frame = true; 108253208Sandre if (m_range.GetBaseAddress().IsValid()) { 109253208Sandre Address current_pc(m_range.GetBaseAddress()); 110253208Sandre if (current_offset != -1) 111253208Sandre current_pc.SetOffset(current_pc.GetOffset() + current_offset); 112253208Sandre DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo(); 113253208Sandre if (eh_frame) { 114253208Sandre m_unwind_plan_eh_frame_sp.reset( 115253208Sandre new UnwindPlan(lldb::eRegisterKindGeneric)); 116253208Sandre if (!eh_frame->GetUnwindPlan(current_pc, *m_unwind_plan_eh_frame_sp)) 117253208Sandre m_unwind_plan_eh_frame_sp.reset(); 118253208Sandre } 119253208Sandre } 120253208Sandre return m_unwind_plan_eh_frame_sp; 121253208Sandre} 122253208Sandre 123253208SandreUnwindPlanSP FuncUnwinders::GetDebugFrameUnwindPlan(Target &target, 124253208Sandre int current_offset) { 125253208Sandre std::lock_guard<std::recursive_mutex> guard(m_mutex); 126253208Sandre if (m_unwind_plan_debug_frame_sp || m_tried_unwind_plan_debug_frame) 127253208Sandre return m_unwind_plan_debug_frame_sp; 128253208Sandre 129253208Sandre m_tried_unwind_plan_debug_frame = true; 130253208Sandre if (m_range.GetBaseAddress().IsValid()) { 131253208Sandre Address current_pc(m_range.GetBaseAddress()); 132253208Sandre if (current_offset != -1) 133253208Sandre current_pc.SetOffset(current_pc.GetOffset() + current_offset); 134253208Sandre DWARFCallFrameInfo *debug_frame = m_unwind_table.GetDebugFrameInfo(); 135253208Sandre if (debug_frame) { 136253208Sandre m_unwind_plan_debug_frame_sp.reset( 137253208Sandre new UnwindPlan(lldb::eRegisterKindGeneric)); 138253208Sandre if (!debug_frame->GetUnwindPlan(current_pc, 139253208Sandre *m_unwind_plan_debug_frame_sp)) 140253208Sandre m_unwind_plan_debug_frame_sp.reset(); 141 } 142 } 143 return m_unwind_plan_debug_frame_sp; 144} 145 146UnwindPlanSP FuncUnwinders::GetArmUnwindUnwindPlan(Target &target, 147 int current_offset) { 148 std::lock_guard<std::recursive_mutex> guard(m_mutex); 149 if (m_unwind_plan_arm_unwind_sp.get() || m_tried_unwind_plan_arm_unwind) 150 return m_unwind_plan_arm_unwind_sp; 151 152 m_tried_unwind_plan_arm_unwind = true; 153 if (m_range.GetBaseAddress().IsValid()) { 154 Address current_pc(m_range.GetBaseAddress()); 155 if (current_offset != -1) 156 current_pc.SetOffset(current_pc.GetOffset() + current_offset); 157 ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo(); 158 if (arm_unwind_info) { 159 m_unwind_plan_arm_unwind_sp.reset( 160 new UnwindPlan(lldb::eRegisterKindGeneric)); 161 if (!arm_unwind_info->GetUnwindPlan(target, current_pc, 162 *m_unwind_plan_arm_unwind_sp)) 163 m_unwind_plan_arm_unwind_sp.reset(); 164 } 165 } 166 return m_unwind_plan_arm_unwind_sp; 167} 168 169UnwindPlanSP FuncUnwinders::GetEHFrameAugmentedUnwindPlan(Target &target, 170 Thread &thread, 171 int current_offset) { 172 std::lock_guard<std::recursive_mutex> guard(m_mutex); 173 if (m_unwind_plan_eh_frame_augmented_sp.get() || 174 m_tried_unwind_plan_eh_frame_augmented) 175 return m_unwind_plan_eh_frame_augmented_sp; 176 177 // Only supported on x86 architectures where we get eh_frame from the compiler 178 // that describes 179 // the prologue instructions perfectly, and sometimes the epilogue 180 // instructions too. 181 if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 && 182 target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 && 183 target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) { 184 m_tried_unwind_plan_eh_frame_augmented = true; 185 return m_unwind_plan_eh_frame_augmented_sp; 186 } 187 188 m_tried_unwind_plan_eh_frame_augmented = true; 189 190 UnwindPlanSP eh_frame_plan = GetEHFrameUnwindPlan(target, current_offset); 191 if (!eh_frame_plan) 192 return m_unwind_plan_eh_frame_augmented_sp; 193 194 m_unwind_plan_eh_frame_augmented_sp.reset(new UnwindPlan(*eh_frame_plan)); 195 196 // Augment the eh_frame instructions with epilogue descriptions if necessary 197 // so the 198 // UnwindPlan can be used at any instruction in the function. 199 200 UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); 201 if (assembly_profiler_sp) { 202 if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite( 203 m_range, thread, *m_unwind_plan_eh_frame_augmented_sp)) { 204 m_unwind_plan_eh_frame_augmented_sp.reset(); 205 } 206 } else { 207 m_unwind_plan_eh_frame_augmented_sp.reset(); 208 } 209 return m_unwind_plan_eh_frame_augmented_sp; 210} 211 212UnwindPlanSP 213FuncUnwinders::GetDebugFrameAugmentedUnwindPlan(Target &target, Thread &thread, 214 int current_offset) { 215 std::lock_guard<std::recursive_mutex> guard(m_mutex); 216 if (m_unwind_plan_debug_frame_augmented_sp.get() || 217 m_tried_unwind_plan_debug_frame_augmented) 218 return m_unwind_plan_debug_frame_augmented_sp; 219 220 // Only supported on x86 architectures where we get debug_frame from the 221 // compiler that describes the prologue instructions perfectly, and sometimes 222 // the epilogue instructions too. 223 if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 && 224 target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 && 225 target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) { 226 m_tried_unwind_plan_debug_frame_augmented = true; 227 return m_unwind_plan_debug_frame_augmented_sp; 228 } 229 230 m_tried_unwind_plan_debug_frame_augmented = true; 231 232 UnwindPlanSP debug_frame_plan = 233 GetDebugFrameUnwindPlan(target, current_offset); 234 if (!debug_frame_plan) 235 return m_unwind_plan_debug_frame_augmented_sp; 236 237 m_unwind_plan_debug_frame_augmented_sp.reset( 238 new UnwindPlan(*debug_frame_plan)); 239 240 // Augment the debug_frame instructions with epilogue descriptions if 241 // necessary so the UnwindPlan can be used at any instruction in the function. 242 243 UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); 244 if (assembly_profiler_sp) { 245 if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite( 246 m_range, thread, *m_unwind_plan_debug_frame_augmented_sp)) { 247 m_unwind_plan_debug_frame_augmented_sp.reset(); 248 } 249 } else 250 m_unwind_plan_debug_frame_augmented_sp.reset(); 251 return m_unwind_plan_debug_frame_augmented_sp; 252} 253 254UnwindPlanSP FuncUnwinders::GetAssemblyUnwindPlan(Target &target, 255 Thread &thread, 256 int current_offset) { 257 std::lock_guard<std::recursive_mutex> guard(m_mutex); 258 if (m_unwind_plan_assembly_sp.get() || m_tried_unwind_plan_assembly || 259 m_unwind_table.GetAllowAssemblyEmulationUnwindPlans() == false) { 260 return m_unwind_plan_assembly_sp; 261 } 262 263 m_tried_unwind_plan_assembly = true; 264 265 UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); 266 if (assembly_profiler_sp) { 267 m_unwind_plan_assembly_sp.reset(new UnwindPlan(lldb::eRegisterKindGeneric)); 268 if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly( 269 m_range, thread, *m_unwind_plan_assembly_sp)) { 270 m_unwind_plan_assembly_sp.reset(); 271 } 272 } 273 return m_unwind_plan_assembly_sp; 274} 275 276// This method compares the pc unwind rule in the first row of two UnwindPlans. 277// If they have the same way of getting the pc value (e.g. "CFA - 8" + "CFA is 278// sp"), 279// then it will return LazyBoolTrue. 280LazyBool FuncUnwinders::CompareUnwindPlansForIdenticalInitialPCLocation( 281 Thread &thread, const UnwindPlanSP &a, const UnwindPlanSP &b) { 282 LazyBool plans_are_identical = eLazyBoolCalculate; 283 284 RegisterNumber pc_reg(thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 285 uint32_t pc_reg_lldb_regnum = pc_reg.GetAsKind(eRegisterKindLLDB); 286 287 if (a.get() && b.get()) { 288 UnwindPlan::RowSP a_first_row = a->GetRowAtIndex(0); 289 UnwindPlan::RowSP b_first_row = b->GetRowAtIndex(0); 290 291 if (a_first_row.get() && b_first_row.get()) { 292 UnwindPlan::Row::RegisterLocation a_pc_regloc; 293 UnwindPlan::Row::RegisterLocation b_pc_regloc; 294 295 a_first_row->GetRegisterInfo(pc_reg_lldb_regnum, a_pc_regloc); 296 b_first_row->GetRegisterInfo(pc_reg_lldb_regnum, b_pc_regloc); 297 298 plans_are_identical = eLazyBoolYes; 299 300 if (a_first_row->GetCFAValue() != b_first_row->GetCFAValue()) { 301 plans_are_identical = eLazyBoolNo; 302 } 303 if (a_pc_regloc != b_pc_regloc) { 304 plans_are_identical = eLazyBoolNo; 305 } 306 } 307 } 308 return plans_are_identical; 309} 310 311UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target, 312 Thread &thread, 313 int current_offset) { 314 UnwindPlanSP eh_frame_sp = GetEHFrameUnwindPlan(target, current_offset); 315 if (!eh_frame_sp) 316 eh_frame_sp = GetDebugFrameUnwindPlan(target, current_offset); 317 UnwindPlanSP arch_default_at_entry_sp = 318 GetUnwindPlanArchitectureDefaultAtFunctionEntry(thread); 319 UnwindPlanSP arch_default_sp = GetUnwindPlanArchitectureDefault(thread); 320 UnwindPlanSP assembly_sp = 321 GetAssemblyUnwindPlan(target, thread, current_offset); 322 323 // This point of this code is to detect when a function is using a 324 // non-standard ABI, and the eh_frame correctly describes that alternate ABI. 325 // This is addressing a specific situation on x86_64 linux systems where one 326 // function in a library pushes a value on the stack and jumps to another 327 // function. So using an assembly instruction based unwind will not work when 328 // you're in the second function - the stack has been modified in a non-ABI 329 // way. But we have eh_frame that correctly describes how to unwind from this 330 // location. So we're looking to see if the initial pc register save location 331 // from the eh_frame is different from the assembly unwind, the arch default 332 // unwind, and the arch default at initial function entry. 333 // 334 // We may have eh_frame that describes the entire function -- or we may have 335 // eh_frame that only describes the unwind after the prologue has executed -- 336 // so we need to check both the arch default (once the prologue has executed) 337 // and the arch default at initial function entry. And we may be running on a 338 // target where we have only some of the assembly/arch default unwind plans 339 // available. 340 341 if (CompareUnwindPlansForIdenticalInitialPCLocation( 342 thread, eh_frame_sp, arch_default_at_entry_sp) == eLazyBoolNo && 343 CompareUnwindPlansForIdenticalInitialPCLocation( 344 thread, eh_frame_sp, arch_default_sp) == eLazyBoolNo && 345 CompareUnwindPlansForIdenticalInitialPCLocation( 346 thread, assembly_sp, arch_default_sp) == eLazyBoolNo) { 347 return eh_frame_sp; 348 } 349 350 if (UnwindPlanSP plan_sp = 351 GetEHFrameAugmentedUnwindPlan(target, thread, current_offset)) 352 return plan_sp; 353 if (UnwindPlanSP plan_sp = 354 GetDebugFrameAugmentedUnwindPlan(target, thread, current_offset)) 355 return plan_sp; 356 357 return assembly_sp; 358} 359 360UnwindPlanSP FuncUnwinders::GetUnwindPlanFastUnwind(Target &target, 361 Thread &thread) { 362 std::lock_guard<std::recursive_mutex> guard(m_mutex); 363 if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast) 364 return m_unwind_plan_fast_sp; 365 366 m_tried_unwind_fast = true; 367 368 UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); 369 if (assembly_profiler_sp) { 370 m_unwind_plan_fast_sp.reset(new UnwindPlan(lldb::eRegisterKindGeneric)); 371 if (!assembly_profiler_sp->GetFastUnwindPlan(m_range, thread, 372 *m_unwind_plan_fast_sp)) { 373 m_unwind_plan_fast_sp.reset(); 374 } 375 } 376 return m_unwind_plan_fast_sp; 377} 378 379UnwindPlanSP FuncUnwinders::GetUnwindPlanArchitectureDefault(Thread &thread) { 380 std::lock_guard<std::recursive_mutex> guard(m_mutex); 381 if (m_unwind_plan_arch_default_sp.get() || m_tried_unwind_arch_default) 382 return m_unwind_plan_arch_default_sp; 383 384 m_tried_unwind_arch_default = true; 385 386 Address current_pc; 387 ProcessSP process_sp(thread.CalculateProcess()); 388 if (process_sp) { 389 ABI *abi = process_sp->GetABI().get(); 390 if (abi) { 391 m_unwind_plan_arch_default_sp.reset( 392 new UnwindPlan(lldb::eRegisterKindGeneric)); 393 if (!abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp)) { 394 m_unwind_plan_arch_default_sp.reset(); 395 } 396 } 397 } 398 399 return m_unwind_plan_arch_default_sp; 400} 401 402UnwindPlanSP 403FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry(Thread &thread) { 404 std::lock_guard<std::recursive_mutex> guard(m_mutex); 405 if (m_unwind_plan_arch_default_at_func_entry_sp.get() || 406 m_tried_unwind_arch_default_at_func_entry) 407 return m_unwind_plan_arch_default_at_func_entry_sp; 408 409 m_tried_unwind_arch_default_at_func_entry = true; 410 411 Address current_pc; 412 ProcessSP process_sp(thread.CalculateProcess()); 413 if (process_sp) { 414 ABI *abi = process_sp->GetABI().get(); 415 if (abi) { 416 m_unwind_plan_arch_default_at_func_entry_sp.reset( 417 new UnwindPlan(lldb::eRegisterKindGeneric)); 418 if (!abi->CreateFunctionEntryUnwindPlan( 419 *m_unwind_plan_arch_default_at_func_entry_sp)) { 420 m_unwind_plan_arch_default_at_func_entry_sp.reset(); 421 } 422 } 423 } 424 425 return m_unwind_plan_arch_default_at_func_entry_sp; 426} 427 428Address &FuncUnwinders::GetFirstNonPrologueInsn(Target &target) { 429 std::lock_guard<std::recursive_mutex> guard(m_mutex); 430 if (m_first_non_prologue_insn.IsValid()) 431 return m_first_non_prologue_insn; 432 433 ExecutionContext exe_ctx(target.shared_from_this(), false); 434 UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); 435 if (assembly_profiler_sp) 436 assembly_profiler_sp->FirstNonPrologueInsn(m_range, exe_ctx, 437 m_first_non_prologue_insn); 438 return m_first_non_prologue_insn; 439} 440 441const Address &FuncUnwinders::GetFunctionStartAddress() const { 442 return m_range.GetBaseAddress(); 443} 444 445lldb::UnwindAssemblySP 446FuncUnwinders::GetUnwindAssemblyProfiler(Target &target) { 447 UnwindAssemblySP assembly_profiler_sp; 448 ArchSpec arch; 449 if (m_unwind_table.GetArchitecture(arch)) { 450 arch.MergeFrom(target.GetArchitecture()); 451 assembly_profiler_sp = UnwindAssembly::FindPlugin(arch); 452 } 453 return assembly_profiler_sp; 454} 455 456Address FuncUnwinders::GetLSDAAddress(Target &target) { 457 Address lsda_addr; 458 459 UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target, -1); 460 if (unwind_plan_sp.get() == nullptr) { 461 unwind_plan_sp = GetCompactUnwindUnwindPlan(target, -1); 462 } 463 if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) { 464 lsda_addr = unwind_plan_sp->GetLSDAAddress(); 465 } 466 return lsda_addr; 467} 468 469Address FuncUnwinders::GetPersonalityRoutinePtrAddress(Target &target) { 470 Address personality_addr; 471 472 UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target, -1); 473 if (unwind_plan_sp.get() == nullptr) { 474 unwind_plan_sp = GetCompactUnwindUnwindPlan(target, -1); 475 } 476 if (unwind_plan_sp.get() && 477 unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) { 478 personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr(); 479 } 480 481 return personality_addr; 482} 483