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/CompactUnwindInfo.h" 14 #include "lldb/Symbol/DWARFCallFrameInfo.h" 15 #include "lldb/Symbol/ObjectFile.h" 16 #include "lldb/Symbol/UnwindPlan.h" 17 #include "lldb/Symbol/UnwindTable.h" 18 #include "lldb/Target/ABI.h" 19 #include "lldb/Target/ExecutionContext.h" 20 #include "lldb/Target/Process.h" 21 #include "lldb/Target/RegisterNumber.h" 22 #include "lldb/Target/Target.h" 23 #include "lldb/Target/Thread.h" 24 #include "lldb/Target/UnwindAssembly.h" 25 26 #include <memory> 27 28 using namespace lldb; 29 using namespace lldb_private; 30 31 //------------------------------------------------ 32 /// constructor 33 //------------------------------------------------ 34 35 FuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, AddressRange range) 36 : m_unwind_table(unwind_table), m_range(range), m_mutex(), 37 m_unwind_plan_assembly_sp(), m_unwind_plan_eh_frame_sp(), 38 m_unwind_plan_eh_frame_augmented_sp(), m_unwind_plan_compact_unwind(), 39 m_unwind_plan_arm_unwind_sp(), m_unwind_plan_fast_sp(), 40 m_unwind_plan_arch_default_sp(), 41 m_unwind_plan_arch_default_at_func_entry_sp(), 42 m_tried_unwind_plan_assembly(false), m_tried_unwind_plan_eh_frame(false), 43 m_tried_unwind_plan_debug_frame(false), 44 m_tried_unwind_plan_eh_frame_augmented(false), 45 m_tried_unwind_plan_debug_frame_augmented(false), 46 m_tried_unwind_plan_compact_unwind(false), 47 m_tried_unwind_plan_arm_unwind(false), m_tried_unwind_fast(false), 48 m_tried_unwind_arch_default(false), 49 m_tried_unwind_arch_default_at_func_entry(false), 50 m_first_non_prologue_insn() {} 51 52 //------------------------------------------------ 53 /// destructor 54 //------------------------------------------------ 55 56 FuncUnwinders::~FuncUnwinders() {} 57 58 UnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite(Target &target, 59 int current_offset) { 60 std::lock_guard<std::recursive_mutex> guard(m_mutex); 61 62 if (UnwindPlanSP plan_sp = GetEHFrameUnwindPlan(target, current_offset)) 63 return plan_sp; 64 if (UnwindPlanSP plan_sp = GetDebugFrameUnwindPlan(target, current_offset)) 65 return plan_sp; 66 if (UnwindPlanSP plan_sp = GetCompactUnwindUnwindPlan(target, current_offset)) 67 return plan_sp; 68 if (UnwindPlanSP plan_sp = GetArmUnwindUnwindPlan(target, current_offset)) 69 return plan_sp; 70 71 return nullptr; 72 } 73 74 UnwindPlanSP FuncUnwinders::GetCompactUnwindUnwindPlan(Target &target, 75 int current_offset) { 76 std::lock_guard<std::recursive_mutex> guard(m_mutex); 77 if (m_unwind_plan_compact_unwind.size() > 0) 78 return m_unwind_plan_compact_unwind[0]; // FIXME support multiple compact 79 // unwind plans for one func 80 if (m_tried_unwind_plan_compact_unwind) 81 return UnwindPlanSP(); 82 83 m_tried_unwind_plan_compact_unwind = true; 84 if (m_range.GetBaseAddress().IsValid()) { 85 Address current_pc(m_range.GetBaseAddress()); 86 if (current_offset != -1) 87 current_pc.SetOffset(current_pc.GetOffset() + current_offset); 88 CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo(); 89 if (compact_unwind) { 90 UnwindPlanSP unwind_plan_sp(new UnwindPlan(lldb::eRegisterKindGeneric)); 91 if (compact_unwind->GetUnwindPlan(target, current_pc, *unwind_plan_sp)) { 92 m_unwind_plan_compact_unwind.push_back(unwind_plan_sp); 93 return m_unwind_plan_compact_unwind[0]; // FIXME support multiple 94 // compact unwind plans for one 95 // func 96 } 97 } 98 } 99 return UnwindPlanSP(); 100 } 101 102 UnwindPlanSP FuncUnwinders::GetEHFrameUnwindPlan(Target &target, 103 int current_offset) { 104 std::lock_guard<std::recursive_mutex> guard(m_mutex); 105 if (m_unwind_plan_eh_frame_sp.get() || m_tried_unwind_plan_eh_frame) 106 return m_unwind_plan_eh_frame_sp; 107 108 m_tried_unwind_plan_eh_frame = true; 109 if (m_range.GetBaseAddress().IsValid()) { 110 Address current_pc(m_range.GetBaseAddress()); 111 if (current_offset != -1) 112 current_pc.SetOffset(current_pc.GetOffset() + current_offset); 113 DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo(); 114 if (eh_frame) { 115 m_unwind_plan_eh_frame_sp = 116 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 117 if (!eh_frame->GetUnwindPlan(current_pc, *m_unwind_plan_eh_frame_sp)) 118 m_unwind_plan_eh_frame_sp.reset(); 119 } 120 } 121 return m_unwind_plan_eh_frame_sp; 122 } 123 124 UnwindPlanSP FuncUnwinders::GetDebugFrameUnwindPlan(Target &target, 125 int current_offset) { 126 std::lock_guard<std::recursive_mutex> guard(m_mutex); 127 if (m_unwind_plan_debug_frame_sp || m_tried_unwind_plan_debug_frame) 128 return m_unwind_plan_debug_frame_sp; 129 130 m_tried_unwind_plan_debug_frame = true; 131 if (m_range.GetBaseAddress().IsValid()) { 132 Address current_pc(m_range.GetBaseAddress()); 133 if (current_offset != -1) 134 current_pc.SetOffset(current_pc.GetOffset() + current_offset); 135 DWARFCallFrameInfo *debug_frame = m_unwind_table.GetDebugFrameInfo(); 136 if (debug_frame) { 137 m_unwind_plan_debug_frame_sp = 138 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 139 if (!debug_frame->GetUnwindPlan(current_pc, 140 *m_unwind_plan_debug_frame_sp)) 141 m_unwind_plan_debug_frame_sp.reset(); 142 } 143 } 144 return m_unwind_plan_debug_frame_sp; 145 } 146 147 UnwindPlanSP FuncUnwinders::GetArmUnwindUnwindPlan(Target &target, 148 int current_offset) { 149 std::lock_guard<std::recursive_mutex> guard(m_mutex); 150 if (m_unwind_plan_arm_unwind_sp.get() || m_tried_unwind_plan_arm_unwind) 151 return m_unwind_plan_arm_unwind_sp; 152 153 m_tried_unwind_plan_arm_unwind = true; 154 if (m_range.GetBaseAddress().IsValid()) { 155 Address current_pc(m_range.GetBaseAddress()); 156 if (current_offset != -1) 157 current_pc.SetOffset(current_pc.GetOffset() + current_offset); 158 ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo(); 159 if (arm_unwind_info) { 160 m_unwind_plan_arm_unwind_sp = 161 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 162 if (!arm_unwind_info->GetUnwindPlan(target, current_pc, 163 *m_unwind_plan_arm_unwind_sp)) 164 m_unwind_plan_arm_unwind_sp.reset(); 165 } 166 } 167 return m_unwind_plan_arm_unwind_sp; 168 } 169 170 UnwindPlanSP FuncUnwinders::GetEHFrameAugmentedUnwindPlan(Target &target, 171 Thread &thread, 172 int current_offset) { 173 std::lock_guard<std::recursive_mutex> guard(m_mutex); 174 if (m_unwind_plan_eh_frame_augmented_sp.get() || 175 m_tried_unwind_plan_eh_frame_augmented) 176 return m_unwind_plan_eh_frame_augmented_sp; 177 178 // Only supported on x86 architectures where we get eh_frame from the 179 // compiler that describes the prologue instructions perfectly, and sometimes 180 // the epilogue 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 = 195 std::make_shared<UnwindPlan>(*eh_frame_plan); 196 197 // Augment the eh_frame instructions with epilogue descriptions if necessary 198 // so the 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 212 UnwindPlanSP 213 FuncUnwinders::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 = 238 std::make_shared<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 242 // function. 243 244 UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); 245 if (assembly_profiler_sp) { 246 if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite( 247 m_range, thread, *m_unwind_plan_debug_frame_augmented_sp)) { 248 m_unwind_plan_debug_frame_augmented_sp.reset(); 249 } 250 } else 251 m_unwind_plan_debug_frame_augmented_sp.reset(); 252 return m_unwind_plan_debug_frame_augmented_sp; 253 } 254 255 UnwindPlanSP FuncUnwinders::GetAssemblyUnwindPlan(Target &target, 256 Thread &thread, 257 int current_offset) { 258 std::lock_guard<std::recursive_mutex> guard(m_mutex); 259 if (m_unwind_plan_assembly_sp.get() || m_tried_unwind_plan_assembly || 260 !m_unwind_table.GetAllowAssemblyEmulationUnwindPlans()) { 261 return m_unwind_plan_assembly_sp; 262 } 263 264 m_tried_unwind_plan_assembly = true; 265 266 UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); 267 if (assembly_profiler_sp) { 268 m_unwind_plan_assembly_sp = 269 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 270 if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly( 271 m_range, thread, *m_unwind_plan_assembly_sp)) { 272 m_unwind_plan_assembly_sp.reset(); 273 } 274 } 275 return m_unwind_plan_assembly_sp; 276 } 277 278 // This method compares the pc unwind rule in the first row of two UnwindPlans. 279 // If they have the same way of getting the pc value (e.g. "CFA - 8" + "CFA is 280 // sp"), then it will return LazyBoolTrue. 281 LazyBool FuncUnwinders::CompareUnwindPlansForIdenticalInitialPCLocation( 282 Thread &thread, const UnwindPlanSP &a, const UnwindPlanSP &b) { 283 LazyBool plans_are_identical = eLazyBoolCalculate; 284 285 RegisterNumber pc_reg(thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 286 uint32_t pc_reg_lldb_regnum = pc_reg.GetAsKind(eRegisterKindLLDB); 287 288 if (a.get() && b.get()) { 289 UnwindPlan::RowSP a_first_row = a->GetRowAtIndex(0); 290 UnwindPlan::RowSP b_first_row = b->GetRowAtIndex(0); 291 292 if (a_first_row.get() && b_first_row.get()) { 293 UnwindPlan::Row::RegisterLocation a_pc_regloc; 294 UnwindPlan::Row::RegisterLocation b_pc_regloc; 295 296 a_first_row->GetRegisterInfo(pc_reg_lldb_regnum, a_pc_regloc); 297 b_first_row->GetRegisterInfo(pc_reg_lldb_regnum, b_pc_regloc); 298 299 plans_are_identical = eLazyBoolYes; 300 301 if (a_first_row->GetCFAValue() != b_first_row->GetCFAValue()) { 302 plans_are_identical = eLazyBoolNo; 303 } 304 if (a_pc_regloc != b_pc_regloc) { 305 plans_are_identical = eLazyBoolNo; 306 } 307 } 308 } 309 return plans_are_identical; 310 } 311 312 UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target, 313 Thread &thread, 314 int current_offset) { 315 UnwindPlanSP eh_frame_sp = GetEHFrameUnwindPlan(target, current_offset); 316 if (!eh_frame_sp) 317 eh_frame_sp = GetDebugFrameUnwindPlan(target, current_offset); 318 UnwindPlanSP arch_default_at_entry_sp = 319 GetUnwindPlanArchitectureDefaultAtFunctionEntry(thread); 320 UnwindPlanSP arch_default_sp = GetUnwindPlanArchitectureDefault(thread); 321 UnwindPlanSP assembly_sp = 322 GetAssemblyUnwindPlan(target, thread, current_offset); 323 324 // This point of this code is to detect when a function is using a non- 325 // standard ABI, and the eh_frame correctly describes that alternate ABI. 326 // This is addressing a specific situation on x86_64 linux systems where one 327 // function in a library pushes a value on the stack and jumps to another 328 // function. So using an assembly instruction based unwind will not work 329 // when you're in the second function - the stack has been modified in a non- 330 // ABI way. But we have eh_frame that correctly describes how to unwind from 331 // this location. So we're looking to see if the initial pc register save 332 // location from the eh_frame is different from the assembly unwind, the arch 333 // default unwind, and the arch default at initial function entry. 334 // 335 // We may have eh_frame that describes the entire function -- or we may have 336 // eh_frame that only describes the unwind after the prologue has executed -- 337 // so we need to check both the arch default (once the prologue has executed) 338 // and the arch default at initial function entry. And we may be running on 339 // a target where we have only some of the assembly/arch default unwind plans 340 // available. 341 342 if (CompareUnwindPlansForIdenticalInitialPCLocation( 343 thread, eh_frame_sp, arch_default_at_entry_sp) == eLazyBoolNo && 344 CompareUnwindPlansForIdenticalInitialPCLocation( 345 thread, eh_frame_sp, arch_default_sp) == eLazyBoolNo && 346 CompareUnwindPlansForIdenticalInitialPCLocation( 347 thread, assembly_sp, arch_default_sp) == eLazyBoolNo) { 348 return eh_frame_sp; 349 } 350 351 if (UnwindPlanSP plan_sp = 352 GetEHFrameAugmentedUnwindPlan(target, thread, current_offset)) 353 return plan_sp; 354 if (UnwindPlanSP plan_sp = 355 GetDebugFrameAugmentedUnwindPlan(target, thread, current_offset)) 356 return plan_sp; 357 358 return assembly_sp; 359 } 360 361 UnwindPlanSP FuncUnwinders::GetUnwindPlanFastUnwind(Target &target, 362 Thread &thread) { 363 std::lock_guard<std::recursive_mutex> guard(m_mutex); 364 if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast) 365 return m_unwind_plan_fast_sp; 366 367 m_tried_unwind_fast = true; 368 369 UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); 370 if (assembly_profiler_sp) { 371 m_unwind_plan_fast_sp = 372 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 373 if (!assembly_profiler_sp->GetFastUnwindPlan(m_range, thread, 374 *m_unwind_plan_fast_sp)) { 375 m_unwind_plan_fast_sp.reset(); 376 } 377 } 378 return m_unwind_plan_fast_sp; 379 } 380 381 UnwindPlanSP FuncUnwinders::GetUnwindPlanArchitectureDefault(Thread &thread) { 382 std::lock_guard<std::recursive_mutex> guard(m_mutex); 383 if (m_unwind_plan_arch_default_sp.get() || m_tried_unwind_arch_default) 384 return m_unwind_plan_arch_default_sp; 385 386 m_tried_unwind_arch_default = true; 387 388 Address current_pc; 389 ProcessSP process_sp(thread.CalculateProcess()); 390 if (process_sp) { 391 ABI *abi = process_sp->GetABI().get(); 392 if (abi) { 393 m_unwind_plan_arch_default_sp = 394 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 395 if (!abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp)) { 396 m_unwind_plan_arch_default_sp.reset(); 397 } 398 } 399 } 400 401 return m_unwind_plan_arch_default_sp; 402 } 403 404 UnwindPlanSP 405 FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry(Thread &thread) { 406 std::lock_guard<std::recursive_mutex> guard(m_mutex); 407 if (m_unwind_plan_arch_default_at_func_entry_sp.get() || 408 m_tried_unwind_arch_default_at_func_entry) 409 return m_unwind_plan_arch_default_at_func_entry_sp; 410 411 m_tried_unwind_arch_default_at_func_entry = true; 412 413 Address current_pc; 414 ProcessSP process_sp(thread.CalculateProcess()); 415 if (process_sp) { 416 ABI *abi = process_sp->GetABI().get(); 417 if (abi) { 418 m_unwind_plan_arch_default_at_func_entry_sp = 419 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 420 if (!abi->CreateFunctionEntryUnwindPlan( 421 *m_unwind_plan_arch_default_at_func_entry_sp)) { 422 m_unwind_plan_arch_default_at_func_entry_sp.reset(); 423 } 424 } 425 } 426 427 return m_unwind_plan_arch_default_at_func_entry_sp; 428 } 429 430 Address &FuncUnwinders::GetFirstNonPrologueInsn(Target &target) { 431 std::lock_guard<std::recursive_mutex> guard(m_mutex); 432 if (m_first_non_prologue_insn.IsValid()) 433 return m_first_non_prologue_insn; 434 435 ExecutionContext exe_ctx(target.shared_from_this(), false); 436 UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); 437 if (assembly_profiler_sp) 438 assembly_profiler_sp->FirstNonPrologueInsn(m_range, exe_ctx, 439 m_first_non_prologue_insn); 440 return m_first_non_prologue_insn; 441 } 442 443 const Address &FuncUnwinders::GetFunctionStartAddress() const { 444 return m_range.GetBaseAddress(); 445 } 446 447 lldb::UnwindAssemblySP 448 FuncUnwinders::GetUnwindAssemblyProfiler(Target &target) { 449 UnwindAssemblySP assembly_profiler_sp; 450 if (ArchSpec arch = m_unwind_table.GetArchitecture()) { 451 arch.MergeFrom(target.GetArchitecture()); 452 assembly_profiler_sp = UnwindAssembly::FindPlugin(arch); 453 } 454 return assembly_profiler_sp; 455 } 456 457 Address FuncUnwinders::GetLSDAAddress(Target &target) { 458 Address lsda_addr; 459 460 UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target, -1); 461 if (unwind_plan_sp.get() == nullptr) { 462 unwind_plan_sp = GetCompactUnwindUnwindPlan(target, -1); 463 } 464 if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) { 465 lsda_addr = unwind_plan_sp->GetLSDAAddress(); 466 } 467 return lsda_addr; 468 } 469 470 Address FuncUnwinders::GetPersonalityRoutinePtrAddress(Target &target) { 471 Address personality_addr; 472 473 UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target, -1); 474 if (unwind_plan_sp.get() == nullptr) { 475 unwind_plan_sp = GetCompactUnwindUnwindPlan(target, -1); 476 } 477 if (unwind_plan_sp.get() && 478 unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) { 479 personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr(); 480 } 481 482 return personality_addr; 483 } 484