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