1 //===-- FuncUnwinders.cpp -------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Symbol/FuncUnwinders.h" 10 #include "lldb/Core/Address.h" 11 #include "lldb/Core/AddressRange.h" 12 #include "lldb/Symbol/ArmUnwindInfo.h" 13 #include "lldb/Symbol/CallFrameInfo.h" 14 #include "lldb/Symbol/CompactUnwindInfo.h" 15 #include "lldb/Symbol/DWARFCallFrameInfo.h" 16 #include "lldb/Symbol/ObjectFile.h" 17 #include "lldb/Symbol/SymbolFile.h" 18 #include "lldb/Symbol/UnwindPlan.h" 19 #include "lldb/Symbol/UnwindTable.h" 20 #include "lldb/Target/ABI.h" 21 #include "lldb/Target/ExecutionContext.h" 22 #include "lldb/Target/Process.h" 23 #include "lldb/Target/RegisterContext.h" 24 #include "lldb/Target/RegisterNumber.h" 25 #include "lldb/Target/Target.h" 26 #include "lldb/Target/Thread.h" 27 #include "lldb/Target/UnwindAssembly.h" 28 29 #include <memory> 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 /// constructor 35 36 FuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, AddressRange range) 37 : m_unwind_table(unwind_table), m_range(range), m_mutex(), 38 m_unwind_plan_assembly_sp(), m_unwind_plan_eh_frame_sp(), 39 m_unwind_plan_eh_frame_augmented_sp(), m_unwind_plan_compact_unwind(), 40 m_unwind_plan_arm_unwind_sp(), m_unwind_plan_fast_sp(), 41 m_unwind_plan_arch_default_sp(), 42 m_unwind_plan_arch_default_at_func_entry_sp(), 43 m_tried_unwind_plan_assembly(false), m_tried_unwind_plan_eh_frame(false), 44 m_tried_unwind_plan_object_file(false), 45 m_tried_unwind_plan_debug_frame(false), 46 m_tried_unwind_plan_object_file_augmented(false), 47 m_tried_unwind_plan_eh_frame_augmented(false), 48 m_tried_unwind_plan_debug_frame_augmented(false), 49 m_tried_unwind_plan_compact_unwind(false), 50 m_tried_unwind_plan_arm_unwind(false), 51 m_tried_unwind_plan_symbol_file(false), m_tried_unwind_fast(false), 52 m_tried_unwind_arch_default(false), 53 m_tried_unwind_arch_default_at_func_entry(false), 54 m_first_non_prologue_insn() {} 55 56 /// destructor 57 58 FuncUnwinders::~FuncUnwinders() = default; 59 60 UnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite(Target &target, 61 Thread &thread) { 62 std::lock_guard<std::recursive_mutex> guard(m_mutex); 63 64 if (UnwindPlanSP plan_sp = GetObjectFileUnwindPlan(target)) 65 return plan_sp; 66 if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread)) 67 return plan_sp; 68 if (UnwindPlanSP plan_sp = GetDebugFrameUnwindPlan(target)) 69 return plan_sp; 70 if (UnwindPlanSP plan_sp = GetEHFrameUnwindPlan(target)) 71 return plan_sp; 72 if (UnwindPlanSP plan_sp = GetCompactUnwindUnwindPlan(target)) 73 return plan_sp; 74 if (UnwindPlanSP plan_sp = GetArmUnwindUnwindPlan(target)) 75 return plan_sp; 76 77 return nullptr; 78 } 79 80 UnwindPlanSP FuncUnwinders::GetCompactUnwindUnwindPlan(Target &target) { 81 std::lock_guard<std::recursive_mutex> guard(m_mutex); 82 if (m_unwind_plan_compact_unwind.size() > 0) 83 return m_unwind_plan_compact_unwind[0]; // FIXME support multiple compact 84 // unwind plans for one func 85 if (m_tried_unwind_plan_compact_unwind) 86 return UnwindPlanSP(); 87 88 m_tried_unwind_plan_compact_unwind = true; 89 if (m_range.GetBaseAddress().IsValid()) { 90 Address current_pc(m_range.GetBaseAddress()); 91 CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo(); 92 if (compact_unwind) { 93 UnwindPlanSP unwind_plan_sp(new UnwindPlan(lldb::eRegisterKindGeneric)); 94 if (compact_unwind->GetUnwindPlan(target, current_pc, *unwind_plan_sp)) { 95 m_unwind_plan_compact_unwind.push_back(unwind_plan_sp); 96 return m_unwind_plan_compact_unwind[0]; // FIXME support multiple 97 // compact unwind plans for one 98 // func 99 } 100 } 101 } 102 return UnwindPlanSP(); 103 } 104 105 lldb::UnwindPlanSP FuncUnwinders::GetObjectFileUnwindPlan(Target &target) { 106 std::lock_guard<std::recursive_mutex> guard(m_mutex); 107 if (m_unwind_plan_object_file_sp.get() || 108 m_tried_unwind_plan_object_file) 109 return m_unwind_plan_object_file_sp; 110 111 m_tried_unwind_plan_object_file = true; 112 if (m_range.GetBaseAddress().IsValid()) { 113 CallFrameInfo *object_file_frame = m_unwind_table.GetObjectFileUnwindInfo(); 114 if (object_file_frame) { 115 m_unwind_plan_object_file_sp = 116 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 117 if (!object_file_frame->GetUnwindPlan(m_range, 118 *m_unwind_plan_object_file_sp)) 119 m_unwind_plan_object_file_sp.reset(); 120 } 121 } 122 return m_unwind_plan_object_file_sp; 123 } 124 125 UnwindPlanSP FuncUnwinders::GetEHFrameUnwindPlan(Target &target) { 126 std::lock_guard<std::recursive_mutex> guard(m_mutex); 127 if (m_unwind_plan_eh_frame_sp.get() || m_tried_unwind_plan_eh_frame) 128 return m_unwind_plan_eh_frame_sp; 129 130 m_tried_unwind_plan_eh_frame = true; 131 if (m_range.GetBaseAddress().IsValid()) { 132 DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo(); 133 if (eh_frame) { 134 m_unwind_plan_eh_frame_sp = 135 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 136 if (!eh_frame->GetUnwindPlan(m_range, *m_unwind_plan_eh_frame_sp)) 137 m_unwind_plan_eh_frame_sp.reset(); 138 } 139 } 140 return m_unwind_plan_eh_frame_sp; 141 } 142 143 UnwindPlanSP FuncUnwinders::GetDebugFrameUnwindPlan(Target &target) { 144 std::lock_guard<std::recursive_mutex> guard(m_mutex); 145 if (m_unwind_plan_debug_frame_sp || m_tried_unwind_plan_debug_frame) 146 return m_unwind_plan_debug_frame_sp; 147 148 m_tried_unwind_plan_debug_frame = true; 149 if (m_range.GetBaseAddress().IsValid()) { 150 DWARFCallFrameInfo *debug_frame = m_unwind_table.GetDebugFrameInfo(); 151 if (debug_frame) { 152 m_unwind_plan_debug_frame_sp = 153 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 154 if (!debug_frame->GetUnwindPlan(m_range, *m_unwind_plan_debug_frame_sp)) 155 m_unwind_plan_debug_frame_sp.reset(); 156 } 157 } 158 return m_unwind_plan_debug_frame_sp; 159 } 160 161 UnwindPlanSP FuncUnwinders::GetArmUnwindUnwindPlan(Target &target) { 162 std::lock_guard<std::recursive_mutex> guard(m_mutex); 163 if (m_unwind_plan_arm_unwind_sp.get() || m_tried_unwind_plan_arm_unwind) 164 return m_unwind_plan_arm_unwind_sp; 165 166 m_tried_unwind_plan_arm_unwind = true; 167 if (m_range.GetBaseAddress().IsValid()) { 168 Address current_pc(m_range.GetBaseAddress()); 169 ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo(); 170 if (arm_unwind_info) { 171 m_unwind_plan_arm_unwind_sp = 172 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 173 if (!arm_unwind_info->GetUnwindPlan(target, current_pc, 174 *m_unwind_plan_arm_unwind_sp)) 175 m_unwind_plan_arm_unwind_sp.reset(); 176 } 177 } 178 return m_unwind_plan_arm_unwind_sp; 179 } 180 181 namespace { 182 class RegisterContextToInfo: public SymbolFile::RegisterInfoResolver { 183 public: 184 RegisterContextToInfo(RegisterContext &ctx) : m_ctx(ctx) {} 185 186 const RegisterInfo *ResolveName(llvm::StringRef name) const override { 187 return m_ctx.GetRegisterInfoByName(name); 188 } 189 const RegisterInfo *ResolveNumber(lldb::RegisterKind kind, 190 uint32_t number) const override { 191 return m_ctx.GetRegisterInfo(kind, number); 192 } 193 194 private: 195 RegisterContext &m_ctx; 196 }; 197 } // namespace 198 199 UnwindPlanSP FuncUnwinders::GetSymbolFileUnwindPlan(Thread &thread) { 200 std::lock_guard<std::recursive_mutex> guard(m_mutex); 201 if (m_unwind_plan_symbol_file_sp.get() || m_tried_unwind_plan_symbol_file) 202 return m_unwind_plan_symbol_file_sp; 203 204 m_tried_unwind_plan_symbol_file = true; 205 if (SymbolFile *symfile = m_unwind_table.GetSymbolFile()) { 206 m_unwind_plan_symbol_file_sp = symfile->GetUnwindPlan( 207 m_range.GetBaseAddress(), 208 RegisterContextToInfo(*thread.GetRegisterContext())); 209 } 210 return m_unwind_plan_symbol_file_sp; 211 } 212 213 UnwindPlanSP 214 FuncUnwinders::GetObjectFileAugmentedUnwindPlan(Target &target, 215 Thread &thread) { 216 std::lock_guard<std::recursive_mutex> guard(m_mutex); 217 if (m_unwind_plan_object_file_augmented_sp.get() || 218 m_tried_unwind_plan_object_file_augmented) 219 return m_unwind_plan_object_file_augmented_sp; 220 221 m_tried_unwind_plan_object_file_augmented = true; 222 223 UnwindPlanSP object_file_unwind_plan = GetObjectFileUnwindPlan(target); 224 if (!object_file_unwind_plan) 225 return m_unwind_plan_object_file_augmented_sp; 226 227 m_unwind_plan_object_file_augmented_sp = 228 std::make_shared<UnwindPlan>(*object_file_unwind_plan); 229 230 // Augment the instructions with epilogue descriptions if necessary 231 // so the UnwindPlan can be used at any instruction in the function. 232 233 UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); 234 if (assembly_profiler_sp) { 235 if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite( 236 m_range, thread, *m_unwind_plan_object_file_augmented_sp)) { 237 m_unwind_plan_object_file_augmented_sp.reset(); 238 } 239 } else { 240 m_unwind_plan_object_file_augmented_sp.reset(); 241 } 242 return m_unwind_plan_object_file_augmented_sp; 243 } 244 245 UnwindPlanSP FuncUnwinders::GetEHFrameAugmentedUnwindPlan(Target &target, 246 Thread &thread) { 247 std::lock_guard<std::recursive_mutex> guard(m_mutex); 248 if (m_unwind_plan_eh_frame_augmented_sp.get() || 249 m_tried_unwind_plan_eh_frame_augmented) 250 return m_unwind_plan_eh_frame_augmented_sp; 251 252 // Only supported on x86 architectures where we get eh_frame from the 253 // compiler that describes the prologue instructions perfectly, and sometimes 254 // the epilogue instructions too. 255 if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 && 256 target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 && 257 target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) { 258 m_tried_unwind_plan_eh_frame_augmented = true; 259 return m_unwind_plan_eh_frame_augmented_sp; 260 } 261 262 m_tried_unwind_plan_eh_frame_augmented = true; 263 264 UnwindPlanSP eh_frame_plan = GetEHFrameUnwindPlan(target); 265 if (!eh_frame_plan) 266 return m_unwind_plan_eh_frame_augmented_sp; 267 268 m_unwind_plan_eh_frame_augmented_sp = 269 std::make_shared<UnwindPlan>(*eh_frame_plan); 270 271 // Augment the eh_frame instructions with epilogue descriptions if necessary 272 // so the UnwindPlan can be used at any instruction in the function. 273 274 UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); 275 if (assembly_profiler_sp) { 276 if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite( 277 m_range, thread, *m_unwind_plan_eh_frame_augmented_sp)) { 278 m_unwind_plan_eh_frame_augmented_sp.reset(); 279 } 280 } else { 281 m_unwind_plan_eh_frame_augmented_sp.reset(); 282 } 283 return m_unwind_plan_eh_frame_augmented_sp; 284 } 285 286 UnwindPlanSP FuncUnwinders::GetDebugFrameAugmentedUnwindPlan(Target &target, 287 Thread &thread) { 288 std::lock_guard<std::recursive_mutex> guard(m_mutex); 289 if (m_unwind_plan_debug_frame_augmented_sp.get() || 290 m_tried_unwind_plan_debug_frame_augmented) 291 return m_unwind_plan_debug_frame_augmented_sp; 292 293 // Only supported on x86 architectures where we get debug_frame from the 294 // compiler that describes the prologue instructions perfectly, and sometimes 295 // the epilogue instructions too. 296 if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 && 297 target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 && 298 target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) { 299 m_tried_unwind_plan_debug_frame_augmented = true; 300 return m_unwind_plan_debug_frame_augmented_sp; 301 } 302 303 m_tried_unwind_plan_debug_frame_augmented = true; 304 305 UnwindPlanSP debug_frame_plan = GetDebugFrameUnwindPlan(target); 306 if (!debug_frame_plan) 307 return m_unwind_plan_debug_frame_augmented_sp; 308 309 m_unwind_plan_debug_frame_augmented_sp = 310 std::make_shared<UnwindPlan>(*debug_frame_plan); 311 312 // Augment the debug_frame instructions with epilogue descriptions if 313 // necessary so the UnwindPlan can be used at any instruction in the 314 // function. 315 316 UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); 317 if (assembly_profiler_sp) { 318 if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite( 319 m_range, thread, *m_unwind_plan_debug_frame_augmented_sp)) { 320 m_unwind_plan_debug_frame_augmented_sp.reset(); 321 } 322 } else 323 m_unwind_plan_debug_frame_augmented_sp.reset(); 324 return m_unwind_plan_debug_frame_augmented_sp; 325 } 326 327 UnwindPlanSP FuncUnwinders::GetAssemblyUnwindPlan(Target &target, 328 Thread &thread) { 329 std::lock_guard<std::recursive_mutex> guard(m_mutex); 330 if (m_unwind_plan_assembly_sp.get() || m_tried_unwind_plan_assembly || 331 !m_unwind_table.GetAllowAssemblyEmulationUnwindPlans()) { 332 return m_unwind_plan_assembly_sp; 333 } 334 335 m_tried_unwind_plan_assembly = true; 336 337 UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); 338 if (assembly_profiler_sp) { 339 m_unwind_plan_assembly_sp = 340 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 341 if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly( 342 m_range, thread, *m_unwind_plan_assembly_sp)) { 343 m_unwind_plan_assembly_sp.reset(); 344 } 345 } 346 return m_unwind_plan_assembly_sp; 347 } 348 349 // This method compares the pc unwind rule in the first row of two UnwindPlans. 350 // If they have the same way of getting the pc value (e.g. "CFA - 8" + "CFA is 351 // sp"), then it will return LazyBoolTrue. 352 LazyBool FuncUnwinders::CompareUnwindPlansForIdenticalInitialPCLocation( 353 Thread &thread, const UnwindPlanSP &a, const UnwindPlanSP &b) { 354 LazyBool plans_are_identical = eLazyBoolCalculate; 355 356 RegisterNumber pc_reg(thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 357 uint32_t pc_reg_lldb_regnum = pc_reg.GetAsKind(eRegisterKindLLDB); 358 359 if (a.get() && b.get()) { 360 UnwindPlan::RowSP a_first_row = a->GetRowAtIndex(0); 361 UnwindPlan::RowSP b_first_row = b->GetRowAtIndex(0); 362 363 if (a_first_row.get() && b_first_row.get()) { 364 UnwindPlan::Row::RegisterLocation a_pc_regloc; 365 UnwindPlan::Row::RegisterLocation b_pc_regloc; 366 367 a_first_row->GetRegisterInfo(pc_reg_lldb_regnum, a_pc_regloc); 368 b_first_row->GetRegisterInfo(pc_reg_lldb_regnum, b_pc_regloc); 369 370 plans_are_identical = eLazyBoolYes; 371 372 if (a_first_row->GetCFAValue() != b_first_row->GetCFAValue()) { 373 plans_are_identical = eLazyBoolNo; 374 } 375 if (a_pc_regloc != b_pc_regloc) { 376 plans_are_identical = eLazyBoolNo; 377 } 378 } 379 } 380 return plans_are_identical; 381 } 382 383 UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target, 384 Thread &thread) { 385 UnwindPlanSP eh_frame_sp = GetEHFrameUnwindPlan(target); 386 if (!eh_frame_sp) 387 eh_frame_sp = GetDebugFrameUnwindPlan(target); 388 if (!eh_frame_sp) 389 eh_frame_sp = GetObjectFileUnwindPlan(target); 390 UnwindPlanSP arch_default_at_entry_sp = 391 GetUnwindPlanArchitectureDefaultAtFunctionEntry(thread); 392 UnwindPlanSP arch_default_sp = GetUnwindPlanArchitectureDefault(thread); 393 UnwindPlanSP assembly_sp = GetAssemblyUnwindPlan(target, thread); 394 395 // This point of this code is to detect when a function is using a non- 396 // standard ABI, and the eh_frame correctly describes that alternate ABI. 397 // This is addressing a specific situation on x86_64 linux systems where one 398 // function in a library pushes a value on the stack and jumps to another 399 // function. So using an assembly instruction based unwind will not work 400 // when you're in the second function - the stack has been modified in a non- 401 // ABI way. But we have eh_frame that correctly describes how to unwind from 402 // this location. So we're looking to see if the initial pc register save 403 // location from the eh_frame is different from the assembly unwind, the arch 404 // default unwind, and the arch default at initial function entry. 405 // 406 // We may have eh_frame that describes the entire function -- or we may have 407 // eh_frame that only describes the unwind after the prologue has executed -- 408 // so we need to check both the arch default (once the prologue has executed) 409 // and the arch default at initial function entry. And we may be running on 410 // a target where we have only some of the assembly/arch default unwind plans 411 // available. 412 413 if (CompareUnwindPlansForIdenticalInitialPCLocation( 414 thread, eh_frame_sp, arch_default_at_entry_sp) == eLazyBoolNo && 415 CompareUnwindPlansForIdenticalInitialPCLocation( 416 thread, eh_frame_sp, arch_default_sp) == eLazyBoolNo && 417 CompareUnwindPlansForIdenticalInitialPCLocation( 418 thread, assembly_sp, arch_default_sp) == eLazyBoolNo) { 419 return eh_frame_sp; 420 } 421 422 if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread)) 423 return plan_sp; 424 if (UnwindPlanSP plan_sp = GetDebugFrameAugmentedUnwindPlan(target, thread)) 425 return plan_sp; 426 if (UnwindPlanSP plan_sp = GetEHFrameAugmentedUnwindPlan(target, thread)) 427 return plan_sp; 428 if (UnwindPlanSP plan_sp = GetObjectFileAugmentedUnwindPlan(target, thread)) 429 return plan_sp; 430 431 return assembly_sp; 432 } 433 434 UnwindPlanSP FuncUnwinders::GetUnwindPlanFastUnwind(Target &target, 435 Thread &thread) { 436 std::lock_guard<std::recursive_mutex> guard(m_mutex); 437 if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast) 438 return m_unwind_plan_fast_sp; 439 440 m_tried_unwind_fast = true; 441 442 UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); 443 if (assembly_profiler_sp) { 444 m_unwind_plan_fast_sp = 445 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 446 if (!assembly_profiler_sp->GetFastUnwindPlan(m_range, thread, 447 *m_unwind_plan_fast_sp)) { 448 m_unwind_plan_fast_sp.reset(); 449 } 450 } 451 return m_unwind_plan_fast_sp; 452 } 453 454 UnwindPlanSP FuncUnwinders::GetUnwindPlanArchitectureDefault(Thread &thread) { 455 std::lock_guard<std::recursive_mutex> guard(m_mutex); 456 if (m_unwind_plan_arch_default_sp.get() || m_tried_unwind_arch_default) 457 return m_unwind_plan_arch_default_sp; 458 459 m_tried_unwind_arch_default = true; 460 461 Address current_pc; 462 ProcessSP process_sp(thread.CalculateProcess()); 463 if (process_sp) { 464 ABI *abi = process_sp->GetABI().get(); 465 if (abi) { 466 m_unwind_plan_arch_default_sp = 467 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 468 if (!abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp)) { 469 m_unwind_plan_arch_default_sp.reset(); 470 } 471 } 472 } 473 474 return m_unwind_plan_arch_default_sp; 475 } 476 477 UnwindPlanSP 478 FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry(Thread &thread) { 479 std::lock_guard<std::recursive_mutex> guard(m_mutex); 480 if (m_unwind_plan_arch_default_at_func_entry_sp.get() || 481 m_tried_unwind_arch_default_at_func_entry) 482 return m_unwind_plan_arch_default_at_func_entry_sp; 483 484 m_tried_unwind_arch_default_at_func_entry = true; 485 486 Address current_pc; 487 ProcessSP process_sp(thread.CalculateProcess()); 488 if (process_sp) { 489 ABI *abi = process_sp->GetABI().get(); 490 if (abi) { 491 m_unwind_plan_arch_default_at_func_entry_sp = 492 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 493 if (!abi->CreateFunctionEntryUnwindPlan( 494 *m_unwind_plan_arch_default_at_func_entry_sp)) { 495 m_unwind_plan_arch_default_at_func_entry_sp.reset(); 496 } 497 } 498 } 499 500 return m_unwind_plan_arch_default_at_func_entry_sp; 501 } 502 503 Address &FuncUnwinders::GetFirstNonPrologueInsn(Target &target) { 504 std::lock_guard<std::recursive_mutex> guard(m_mutex); 505 if (m_first_non_prologue_insn.IsValid()) 506 return m_first_non_prologue_insn; 507 508 ExecutionContext exe_ctx(target.shared_from_this(), false); 509 UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); 510 if (assembly_profiler_sp) 511 assembly_profiler_sp->FirstNonPrologueInsn(m_range, exe_ctx, 512 m_first_non_prologue_insn); 513 return m_first_non_prologue_insn; 514 } 515 516 const Address &FuncUnwinders::GetFunctionStartAddress() const { 517 return m_range.GetBaseAddress(); 518 } 519 520 lldb::UnwindAssemblySP 521 FuncUnwinders::GetUnwindAssemblyProfiler(Target &target) { 522 UnwindAssemblySP assembly_profiler_sp; 523 if (ArchSpec arch = m_unwind_table.GetArchitecture()) { 524 arch.MergeFrom(target.GetArchitecture()); 525 assembly_profiler_sp = UnwindAssembly::FindPlugin(arch); 526 } 527 return assembly_profiler_sp; 528 } 529 530 Address FuncUnwinders::GetLSDAAddress(Target &target) { 531 Address lsda_addr; 532 533 UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target); 534 if (unwind_plan_sp.get() == nullptr) { 535 unwind_plan_sp = GetCompactUnwindUnwindPlan(target); 536 } 537 if (unwind_plan_sp.get() == nullptr) { 538 unwind_plan_sp = GetObjectFileUnwindPlan(target); 539 } 540 if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) { 541 lsda_addr = unwind_plan_sp->GetLSDAAddress(); 542 } 543 return lsda_addr; 544 } 545 546 Address FuncUnwinders::GetPersonalityRoutinePtrAddress(Target &target) { 547 Address personality_addr; 548 549 UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target); 550 if (unwind_plan_sp.get() == nullptr) { 551 unwind_plan_sp = GetCompactUnwindUnwindPlan(target); 552 } 553 if (unwind_plan_sp.get() == nullptr) { 554 unwind_plan_sp = GetObjectFileUnwindPlan(target); 555 } 556 if (unwind_plan_sp.get() && 557 unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) { 558 personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr(); 559 } 560 561 return personality_addr; 562 } 563