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