Skip to content

Commit b63c1c4

Browse files
authored
[lldb] Disable some unwind plans for discontinuous functions (#140927)
Basically, disable everything except the eh_frame unwind plan, as that's the only one which supports this right now. The other plans are working with now trying the interpret everything in between the function parts as a part of the function, which is more likely to produce wrong results than correct ones. I changed the interface for object file plans, to give the implementations a chance to implement this correctly, but I haven't actually converted PECallFrameInfo (its only implementation) to handle that. (from the looks of things, it should be relatively easy to do, if it becomes necessary) I'm also deleting UnwindPlan::GetFirstNonPrologueInsn, as it's not used, and it doesn't work for discontinuous functions.
1 parent b9a7098 commit b63c1c4

File tree

7 files changed

+100
-117
lines changed

7 files changed

+100
-117
lines changed

lldb/include/lldb/Symbol/CallFrameInfo.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ class CallFrameInfo {
1919

2020
virtual bool GetAddressRange(Address addr, AddressRange &range) = 0;
2121

22-
virtual bool GetUnwindPlan(const Address &addr, UnwindPlan &unwind_plan) = 0;
23-
virtual bool GetUnwindPlan(const AddressRange &range, UnwindPlan &unwind_plan) = 0;
22+
virtual std::unique_ptr<UnwindPlan>
23+
GetUnwindPlan(llvm::ArrayRef<AddressRange> ranges, const Address &addr) = 0;
24+
25+
virtual std::unique_ptr<UnwindPlan> GetUnwindPlan(const Address &addr) = 0;
2426
};
2527

2628
} // namespace lldb_private

lldb/include/lldb/Symbol/FuncUnwinders.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ class FuncUnwinders {
5151
std::shared_ptr<const UnwindPlan>
5252
GetUnwindPlanArchitectureDefaultAtFunctionEntry(lldb_private::Thread &thread);
5353

54-
Address &GetFirstNonPrologueInsn(Target &target);
55-
5654
const Address &GetFunctionStartAddress() const;
5755

5856
bool ContainsAddress(const Address &addr) const {
@@ -114,10 +112,6 @@ class FuncUnwinders {
114112
/// The address ranges of the function.
115113
AddressRanges m_ranges;
116114

117-
/// The smallest address range covering the entire function.
118-
/// DEPRECATED: Use m_ranges instead.
119-
AddressRange m_range;
120-
121115
std::recursive_mutex m_mutex;
122116

123117
std::shared_ptr<const UnwindPlan> m_unwind_plan_assembly_sp;

lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.cpp

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -455,27 +455,26 @@ bool PECallFrameInfo::GetAddressRange(Address addr, AddressRange &range) {
455455
return true;
456456
}
457457

458-
bool PECallFrameInfo::GetUnwindPlan(const Address &addr,
459-
UnwindPlan &unwind_plan) {
460-
return GetUnwindPlan(AddressRange(addr, 1), unwind_plan);
461-
}
462-
463-
bool PECallFrameInfo::GetUnwindPlan(const AddressRange &range,
464-
UnwindPlan &unwind_plan) {
465-
unwind_plan.Clear();
466-
467-
unwind_plan.SetSourceName("PE EH info");
468-
unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
469-
unwind_plan.SetRegisterKind(eRegisterKindLLDB);
458+
std::unique_ptr<UnwindPlan> PECallFrameInfo::GetUnwindPlan(
459+
llvm::ArrayRef<lldb_private::AddressRange> ranges,
460+
const lldb_private::Address &addr) {
461+
// Only continuous functions are supported.
462+
if (ranges.size() != 1)
463+
return nullptr;
464+
const AddressRange &range = ranges[0];
470465

471466
const RuntimeFunction *runtime_function =
472467
FindRuntimeFunctionIntersectsWithRange(range);
473468
if (!runtime_function)
474-
return false;
469+
return nullptr;
470+
471+
auto plan_up = std::make_unique<UnwindPlan>(eRegisterKindLLDB);
472+
plan_up->SetSourceName("PE EH info");
473+
plan_up->SetSourcedFromCompiler(eLazyBoolYes);
475474

476475
EHProgramBuilder builder(m_object_file, runtime_function->UnwindInfoOffset);
477476
if (!builder.Build())
478-
return false;
477+
return nullptr;
479478

480479
std::vector<UnwindPlan::Row> rows;
481480

@@ -493,14 +492,14 @@ bool PECallFrameInfo::GetUnwindPlan(const AddressRange &range,
493492
}
494493

495494
for (auto it = rows.rbegin(); it != rows.rend(); ++it)
496-
unwind_plan.AppendRow(std::move(*it));
495+
plan_up->AppendRow(std::move(*it));
497496

498-
unwind_plan.SetPlanValidAddressRanges({AddressRange(
497+
plan_up->SetPlanValidAddressRanges({AddressRange(
499498
m_object_file.GetAddress(runtime_function->StartAddress),
500499
runtime_function->EndAddress - runtime_function->StartAddress)});
501-
unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
500+
plan_up->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
502501

503-
return true;
502+
return plan_up;
504503
}
505504

506505
const RuntimeFunction *PECallFrameInfo::FindRuntimeFunctionIntersectsWithRange(

lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
#ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_PECOFF_PECALLFRAMEINFO_H
1010
#define LLDB_SOURCE_PLUGINS_OBJECTFILE_PECOFF_PECALLFRAMEINFO_H
1111

12+
#include "lldb/Core/AddressRange.h"
1213
#include "lldb/Symbol/CallFrameInfo.h"
14+
#include "lldb/Symbol/UnwindPlan.h"
1315
#include "lldb/Utility/DataExtractor.h"
1416

1517
class ObjectFilePECOFF;
@@ -31,10 +33,14 @@ class PECallFrameInfo : public virtual lldb_private::CallFrameInfo {
3133
bool GetAddressRange(lldb_private::Address addr,
3234
lldb_private::AddressRange &range) override;
3335

34-
bool GetUnwindPlan(const lldb_private::Address &addr,
35-
lldb_private::UnwindPlan &unwind_plan) override;
36-
bool GetUnwindPlan(const lldb_private::AddressRange &range,
37-
lldb_private::UnwindPlan &unwind_plan) override;
36+
std::unique_ptr<lldb_private::UnwindPlan>
37+
GetUnwindPlan(const lldb_private::Address &addr) override {
38+
return GetUnwindPlan({lldb_private::AddressRange(addr, 1)}, addr);
39+
}
40+
41+
std::unique_ptr<lldb_private::UnwindPlan>
42+
GetUnwindPlan(llvm::ArrayRef<lldb_private::AddressRange> ranges,
43+
const lldb_private::Address &addr) override;
3844

3945
private:
4046
const llvm::Win64EH::RuntimeFunction *FindRuntimeFunctionIntersectsWithRange(

lldb/source/Symbol/FuncUnwinders.cpp

Lines changed: 38 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -31,30 +31,11 @@
3131
using namespace lldb;
3232
using namespace lldb_private;
3333

34-
static AddressRange CollapseRanges(llvm::ArrayRef<AddressRange> ranges) {
35-
if (ranges.empty())
36-
return AddressRange();
37-
if (ranges.size() == 1)
38-
return ranges[0];
39-
40-
Address lowest_addr = ranges[0].GetBaseAddress();
41-
addr_t highest_addr = lowest_addr.GetFileAddress() + ranges[0].GetByteSize();
42-
for (const AddressRange &range : ranges.drop_front()) {
43-
Address range_begin = range.GetBaseAddress();
44-
addr_t range_end = range_begin.GetFileAddress() + range.GetByteSize();
45-
if (range_begin.GetFileAddress() < lowest_addr.GetFileAddress())
46-
lowest_addr = range_begin;
47-
if (range_end > highest_addr)
48-
highest_addr = range_end;
49-
}
50-
return AddressRange(lowest_addr, highest_addr - lowest_addr.GetFileAddress());
51-
}
52-
5334
FuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, Address addr,
5435
AddressRanges ranges)
5536
: m_unwind_table(unwind_table), m_addr(std::move(addr)),
56-
m_ranges(std::move(ranges)), m_range(CollapseRanges(m_ranges)),
57-
m_tried_unwind_plan_assembly(false), m_tried_unwind_plan_eh_frame(false),
37+
m_ranges(std::move(ranges)), m_tried_unwind_plan_assembly(false),
38+
m_tried_unwind_plan_eh_frame(false),
5839
m_tried_unwind_plan_object_file(false),
5940
m_tried_unwind_plan_debug_frame(false),
6041
m_tried_unwind_plan_object_file_augmented(false),
@@ -106,8 +87,9 @@ FuncUnwinders::GetCompactUnwindUnwindPlan(Target &target) {
10687
return nullptr;
10788

10889
m_tried_unwind_plan_compact_unwind = true;
109-
if (m_range.GetBaseAddress().IsValid()) {
110-
Address current_pc(m_range.GetBaseAddress());
90+
// Only continuous functions are supported.
91+
if (m_ranges.size() == 1) {
92+
Address current_pc(m_ranges[0].GetBaseAddress());
11193
CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo();
11294
if (compact_unwind) {
11395
auto unwind_plan_sp =
@@ -131,14 +113,10 @@ FuncUnwinders::GetObjectFileUnwindPlan(Target &target) {
131113
return m_unwind_plan_object_file_sp;
132114

133115
m_tried_unwind_plan_object_file = true;
134-
if (m_range.GetBaseAddress().IsValid()) {
135-
CallFrameInfo *object_file_frame = m_unwind_table.GetObjectFileUnwindInfo();
136-
if (object_file_frame) {
137-
auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
138-
if (object_file_frame->GetUnwindPlan(m_range, *plan_sp))
139-
m_unwind_plan_object_file_sp = std::move(plan_sp);
140-
}
141-
}
116+
if (CallFrameInfo *object_file_frame =
117+
m_unwind_table.GetObjectFileUnwindInfo())
118+
m_unwind_plan_object_file_sp =
119+
object_file_frame->GetUnwindPlan(m_ranges, m_addr);
142120
return m_unwind_plan_object_file_sp;
143121
}
144122

@@ -178,8 +156,9 @@ FuncUnwinders::GetArmUnwindUnwindPlan(Target &target) {
178156
return m_unwind_plan_arm_unwind_sp;
179157

180158
m_tried_unwind_plan_arm_unwind = true;
181-
if (m_range.GetBaseAddress().IsValid()) {
182-
Address current_pc(m_range.GetBaseAddress());
159+
// Only continuous functions are supported.
160+
if (m_ranges.size() == 1) {
161+
Address current_pc = m_ranges[0].GetBaseAddress();
183162
ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo();
184163
if (arm_unwind_info) {
185164
auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
@@ -215,9 +194,10 @@ FuncUnwinders::GetSymbolFileUnwindPlan(Thread &thread) {
215194
return m_unwind_plan_symbol_file_sp;
216195

217196
m_tried_unwind_plan_symbol_file = true;
218-
if (SymbolFile *symfile = m_unwind_table.GetSymbolFile()) {
197+
if (SymbolFile *symfile = m_unwind_table.GetSymbolFile();
198+
symfile && m_ranges.size() == 1) {
219199
m_unwind_plan_symbol_file_sp = symfile->GetUnwindPlan(
220-
m_range.GetBaseAddress(),
200+
m_ranges[0].GetBaseAddress(),
221201
RegisterContextToInfo(*thread.GetRegisterContext()));
222202
}
223203
return m_unwind_plan_symbol_file_sp;
@@ -242,10 +222,11 @@ FuncUnwinders::GetObjectFileAugmentedUnwindPlan(Target &target,
242222
// so the UnwindPlan can be used at any instruction in the function.
243223

244224
UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
245-
if (assembly_profiler_sp) {
225+
// Only continuous functions are supported.
226+
if (assembly_profiler_sp && m_ranges.size() == 1) {
246227
auto plan_sp = std::make_shared<UnwindPlan>(*object_file_unwind_plan);
247228

248-
if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite(m_range, thread,
229+
if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite(m_ranges[0], thread,
249230
*plan_sp))
250231
m_unwind_plan_object_file_augmented_sp = std::move(plan_sp);
251232
}
@@ -280,9 +261,10 @@ FuncUnwinders::GetEHFrameAugmentedUnwindPlan(Target &target, Thread &thread) {
280261
// so the UnwindPlan can be used at any instruction in the function.
281262

282263
UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
283-
if (assembly_profiler_sp) {
264+
// Only continuous functions are supported.
265+
if (assembly_profiler_sp && m_ranges.size() == 1) {
284266
auto plan_sp = std::make_shared<UnwindPlan>(*eh_frame_plan);
285-
if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite(m_range, thread,
267+
if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite(m_ranges[0], thread,
286268
*plan_sp))
287269
m_unwind_plan_eh_frame_augmented_sp = std::move(plan_sp);
288270
}
@@ -319,10 +301,11 @@ FuncUnwinders::GetDebugFrameAugmentedUnwindPlan(Target &target,
319301
// function.
320302

321303
UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
322-
if (assembly_profiler_sp) {
304+
// Only continuous functions are supported.
305+
if (assembly_profiler_sp && m_ranges.size() == 1) {
323306
auto plan_sp = std::make_shared<UnwindPlan>(*debug_frame_plan);
324307

325-
if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite(m_range, thread,
308+
if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite(m_ranges[0], thread,
326309
*plan_sp))
327310
m_unwind_plan_debug_frame_augmented_sp = std::move(plan_sp);
328311
}
@@ -339,18 +322,19 @@ FuncUnwinders::GetAssemblyUnwindPlan(Target &target, Thread &thread) {
339322

340323
m_tried_unwind_plan_assembly = true;
341324

342-
// Don't analyze more than 10 megabytes of instructions,
343-
// if a function is legitimately larger than that, we'll
344-
// miss the epilogue instructions, but guard against a
345-
// bogusly large function and analyzing large amounts of
346-
// non-instruction data.
347-
AddressRange range = m_range;
348-
const addr_t func_size =
349-
std::min(range.GetByteSize(), (addr_t)1024 * 10 * 10);
350-
range.SetByteSize(func_size);
351-
352325
UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
353-
if (assembly_profiler_sp) {
326+
// Only continuous functions are supported.
327+
if (assembly_profiler_sp && m_ranges.size() == 1) {
328+
// Don't analyze more than 10 megabytes of instructions,
329+
// if a function is legitimately larger than that, we'll
330+
// miss the epilogue instructions, but guard against a
331+
// bogusly large function and analyzing large amounts of
332+
// non-instruction data.
333+
AddressRange range = m_ranges[0];
334+
const addr_t func_size =
335+
std::min(range.GetByteSize(), (addr_t)1024 * 10 * 10);
336+
range.SetByteSize(func_size);
337+
354338
auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
355339
if (assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly(
356340
range, thread, *plan_sp))
@@ -457,9 +441,9 @@ FuncUnwinders::GetUnwindPlanFastUnwind(Target &target, Thread &thread) {
457441
m_tried_unwind_fast = true;
458442

459443
UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
460-
if (assembly_profiler_sp) {
444+
if (assembly_profiler_sp && m_ranges.size() == 1) {
461445
auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
462-
if (assembly_profiler_sp->GetFastUnwindPlan(m_range, thread, *plan_sp))
446+
if (assembly_profiler_sp->GetFastUnwindPlan(m_ranges[0], thread, *plan_sp))
463447
m_unwind_plan_fast_sp = std::move(plan_sp);
464448
}
465449
return m_unwind_plan_fast_sp;
@@ -503,19 +487,6 @@ FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry(Thread &thread) {
503487
return m_unwind_plan_arch_default_at_func_entry_sp;
504488
}
505489

506-
Address &FuncUnwinders::GetFirstNonPrologueInsn(Target &target) {
507-
std::lock_guard<std::recursive_mutex> guard(m_mutex);
508-
if (m_first_non_prologue_insn.IsValid())
509-
return m_first_non_prologue_insn;
510-
511-
ExecutionContext exe_ctx(target.shared_from_this(), false);
512-
UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
513-
if (assembly_profiler_sp)
514-
assembly_profiler_sp->FirstNonPrologueInsn(m_range, exe_ctx,
515-
m_first_non_prologue_insn);
516-
return m_first_non_prologue_insn;
517-
}
518-
519490
const Address &FuncUnwinders::GetFunctionStartAddress() const { return m_addr; }
520491

521492
lldb::UnwindAssemblySP

lldb/source/Target/RegisterContextUnwind.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -880,10 +880,9 @@ RegisterContextUnwind::GetFullUnwindPlanForFrame() {
880880
CallFrameInfo *object_file_unwind =
881881
pc_module_sp->GetUnwindTable().GetObjectFileUnwindInfo();
882882
if (object_file_unwind) {
883-
auto unwind_plan_sp =
884-
std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
885-
if (object_file_unwind->GetUnwindPlan(m_current_pc, *unwind_plan_sp))
886-
return unwind_plan_sp;
883+
if (std::unique_ptr<UnwindPlan> plan_up =
884+
object_file_unwind->GetUnwindPlan(m_current_pc))
885+
return plan_up;
887886
}
888887

889888
return arch_default_unwind_plan_sp;

0 commit comments

Comments
 (0)