Skip to content

Commit 78645f8

Browse files
dmpotsgithub-actions[bot]
authored andcommitted
Automerge: [lldb] Add helper to create mock objects for dwarf expression tests (#167956)
This commit adds a new helper function that creates various mock objects that can be used in dwarf expression testing. The optional register value and memory contents are used to create MockProcessWithMemRead and MockRegisterContext that can return expected memory contents and register values. This simplifies some tests by removing redundant code that creates these objects in individual tests and consolidates the logic into one place.
2 parents 68ad559 + 3bec613 commit 78645f8

File tree

1 file changed

+89
-132
lines changed

1 file changed

+89
-132
lines changed

lldb/unittests/Expression/DWARFExpressionTest.cpp

Lines changed: 89 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,33 @@ struct MockProcess : Process {
6767
}
6868
};
6969

70+
/// A Process whose `ReadMemory` override queries a DenseMap.
71+
struct MockProcessWithMemRead : Process {
72+
using addr_t = lldb::addr_t;
73+
74+
llvm::DenseMap<addr_t, addr_t> memory_map;
75+
76+
MockProcessWithMemRead(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
77+
llvm::DenseMap<addr_t, addr_t> &&memory_map)
78+
: Process(target_sp, listener_sp), memory_map(memory_map) {}
79+
size_t DoReadMemory(addr_t vm_addr, void *buf, size_t size,
80+
Status &error) override {
81+
assert(memory_map.contains(vm_addr));
82+
assert(size == sizeof(addr_t));
83+
*reinterpret_cast<addr_t *>(buf) = memory_map[vm_addr];
84+
return sizeof(addr_t);
85+
}
86+
size_t ReadMemory(addr_t addr, void *buf, size_t size,
87+
Status &status) override {
88+
return DoReadMemory(addr, buf, size, status);
89+
}
90+
bool CanDebug(lldb::TargetSP, bool) override { return true; }
91+
Status DoDestroy() override { return Status(); }
92+
llvm::StringRef GetPluginName() override { return ""; }
93+
void RefreshStateAfterStop() override {}
94+
bool DoUpdateThreadList(ThreadList &, ThreadList &) override { return false; }
95+
};
96+
7097
class MockThread : public Thread {
7198
public:
7299
MockThread(Process &process) : Thread(process, /*tid=*/1), m_reg_ctx_sp() {}
@@ -175,24 +202,55 @@ class DWARFExpressionMockProcessTest : public ::testing::Test {
175202
}
176203
};
177204

178-
struct PlatformTargetDebugger {
205+
struct TestContext {
179206
lldb::PlatformSP platform_sp;
180207
lldb::TargetSP target_sp;
181208
lldb::DebuggerSP debugger_sp;
209+
lldb::ProcessSP process_sp;
210+
lldb::ThreadSP thread_sp;
211+
lldb::RegisterContextSP reg_ctx_sp;
182212
};
183213

184-
/// A helper function to create <Platform, Target, Debugger> objects with the
185-
/// "aarch64-pc-linux" ArchSpec.
186-
static PlatformTargetDebugger CreateTarget() {
187-
ArchSpec arch("aarch64-pc-linux");
214+
/// A helper function to create TestContext objects with the
215+
/// given triple, memory, and register contents.
216+
static bool CreateTestContext(
217+
TestContext *ctx, llvm::StringRef triple,
218+
std::optional<RegisterValue> reg_value = {},
219+
std::optional<llvm::DenseMap<lldb::addr_t, lldb::addr_t>> memory = {}) {
220+
ArchSpec arch(triple);
188221
Platform::SetHostPlatform(
189222
platform_linux::PlatformLinux::CreateInstance(true, &arch));
190223
lldb::PlatformSP platform_sp;
191224
lldb::TargetSP target_sp;
192225
lldb::DebuggerSP debugger_sp = Debugger::CreateInstance();
193-
debugger_sp->GetTargetList().CreateTarget(
226+
Status status = debugger_sp->GetTargetList().CreateTarget(
194227
*debugger_sp, "", arch, eLoadDependentsNo, platform_sp, target_sp);
195-
return PlatformTargetDebugger{platform_sp, target_sp, debugger_sp};
228+
229+
EXPECT_TRUE(status.Success());
230+
if (!status.Success())
231+
return false;
232+
233+
lldb::ProcessSP process_sp;
234+
if (memory)
235+
process_sp = std::make_shared<MockProcessWithMemRead>(
236+
target_sp, Listener::MakeListener("dummy"), std::move(*memory));
237+
else
238+
process_sp = std::make_shared<MockProcess>(target_sp,
239+
Listener::MakeListener("dummy"));
240+
241+
auto thread_sp = std::make_shared<MockThread>(*process_sp);
242+
243+
process_sp->GetThreadList().AddThread(thread_sp);
244+
245+
lldb::RegisterContextSP reg_ctx_sp;
246+
if (reg_value) {
247+
reg_ctx_sp = std::make_shared<MockRegisterContext>(*thread_sp, *reg_value);
248+
thread_sp->SetRegisterContext(reg_ctx_sp);
249+
}
250+
251+
*ctx = TestContext{platform_sp, target_sp, debugger_sp,
252+
process_sp, thread_sp, reg_ctx_sp};
253+
return true;
196254
}
197255

198256
// NB: This class doesn't use the override keyword to avoid
@@ -486,24 +544,10 @@ TEST_F(DWARFExpressionMockProcessTest, DW_OP_deref) {
486544
EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit0, DW_OP_deref}), llvm::Failed());
487545

488546
// Set up a mock process.
489-
ArchSpec arch("i386-pc-linux");
490-
Platform::SetHostPlatform(
491-
platform_linux::PlatformLinux::CreateInstance(true, &arch));
492-
lldb::DebuggerSP debugger_sp = Debugger::CreateInstance();
493-
ASSERT_TRUE(debugger_sp);
494-
lldb::TargetSP target_sp;
495-
lldb::PlatformSP platform_sp;
496-
debugger_sp->GetTargetList().CreateTarget(
497-
*debugger_sp, "", arch, eLoadDependentsNo, platform_sp, target_sp);
498-
ASSERT_TRUE(target_sp);
499-
ASSERT_TRUE(target_sp->GetArchitecture().IsValid());
500-
ASSERT_TRUE(platform_sp);
501-
lldb::ListenerSP listener_sp(Listener::MakeListener("dummy"));
502-
lldb::ProcessSP process_sp =
503-
std::make_shared<MockProcess>(target_sp, listener_sp);
504-
ASSERT_TRUE(process_sp);
547+
TestContext test_ctx;
548+
ASSERT_TRUE(CreateTestContext(&test_ctx, "i386-pc-linux"));
505549

506-
ExecutionContext exe_ctx(process_sp);
550+
ExecutionContext exe_ctx(test_ctx.process_sp);
507551
// Implicit location: *0x4.
508552
EXPECT_THAT_EXPECTED(
509553
Evaluate({DW_OP_lit4, DW_OP_deref, DW_OP_stack_value}, {}, {}, &exe_ctx),
@@ -518,20 +562,10 @@ TEST_F(DWARFExpressionMockProcessTest, DW_OP_deref) {
518562

519563
TEST_F(DWARFExpressionMockProcessTest, WASM_DW_OP_addr) {
520564
// Set up a wasm target
521-
ArchSpec arch("wasm32-unknown-unknown-wasm");
522-
lldb::PlatformSP host_platform_sp =
523-
platform_linux::PlatformLinux::CreateInstance(true, &arch);
524-
ASSERT_TRUE(host_platform_sp);
525-
Platform::SetHostPlatform(host_platform_sp);
526-
lldb::DebuggerSP debugger_sp = Debugger::CreateInstance();
527-
ASSERT_TRUE(debugger_sp);
528-
lldb::TargetSP target_sp;
529-
lldb::PlatformSP platform_sp;
530-
debugger_sp->GetTargetList().CreateTarget(*debugger_sp, "", arch,
531-
lldb_private::eLoadDependentsNo,
532-
platform_sp, target_sp);
565+
TestContext test_ctx;
566+
ASSERT_TRUE(CreateTestContext(&test_ctx, "wasm32-unknown-unknown-wasm"));
533567

534-
ExecutionContext exe_ctx(target_sp, false);
568+
ExecutionContext exe_ctx(test_ctx.target_sp, false);
535569
// DW_OP_addr takes a single operand of address size width:
536570
EXPECT_THAT_EXPECTED(
537571
Evaluate({DW_OP_addr, 0x40, 0x0, 0x0, 0x0}, {}, {}, &exe_ctx),
@@ -587,20 +621,9 @@ TEST_F(DWARFExpressionMockProcessTest, WASM_DW_OP_addr_index) {
587621
dwarf_cu->ExtractDIEsIfNeeded();
588622

589623
// Set up a wasm target
590-
ArchSpec arch("wasm32-unknown-unknown-wasm");
591-
lldb::PlatformSP host_platform_sp =
592-
platform_linux::PlatformLinux::CreateInstance(true, &arch);
593-
ASSERT_TRUE(host_platform_sp);
594-
Platform::SetHostPlatform(host_platform_sp);
595-
lldb::DebuggerSP debugger_sp = Debugger::CreateInstance();
596-
ASSERT_TRUE(debugger_sp);
597-
lldb::TargetSP target_sp;
598-
lldb::PlatformSP platform_sp;
599-
debugger_sp->GetTargetList().CreateTarget(*debugger_sp, "", arch,
600-
lldb_private::eLoadDependentsNo,
601-
platform_sp, target_sp);
602-
603-
ExecutionContext exe_ctx(target_sp, false);
624+
TestContext test_ctx;
625+
ASSERT_TRUE(CreateTestContext(&test_ctx, "wasm32-unknown-unknown-wasm"));
626+
ExecutionContext exe_ctx(test_ctx.target_sp, false);
604627

605628
auto evaluate = [&](DWARFExpression &expr) -> llvm::Expected<Value> {
606629
DataExtractor extractor;
@@ -823,28 +846,10 @@ TEST(DWARFExpression, Extensions) {
823846
subsystems;
824847

825848
// Set up a wasm target.
826-
ArchSpec arch("wasm32-unknown-unknown-wasm");
827-
lldb::PlatformSP host_platform_sp =
828-
platform_linux::PlatformLinux::CreateInstance(true, &arch);
829-
ASSERT_TRUE(host_platform_sp);
830-
Platform::SetHostPlatform(host_platform_sp);
831-
lldb::DebuggerSP debugger_sp = Debugger::CreateInstance();
832-
ASSERT_TRUE(debugger_sp);
833-
lldb::TargetSP target_sp;
834-
lldb::PlatformSP platform_sp;
835-
debugger_sp->GetTargetList().CreateTarget(*debugger_sp, "", arch,
836-
lldb_private::eLoadDependentsNo,
837-
platform_sp, target_sp);
838-
// Set up a mock process and thread.
839-
lldb::ListenerSP listener_sp(Listener::MakeListener("dummy"));
840-
lldb::ProcessSP process_sp =
841-
std::make_shared<MockProcess>(target_sp, listener_sp);
842-
ASSERT_TRUE(process_sp);
843-
MockThread thread(*process_sp);
849+
TestContext test_ctx;
844850
const uint32_t kExpectedValue = 42;
845-
lldb::RegisterContextSP reg_ctx_sp = std::make_shared<MockRegisterContext>(
846-
thread, RegisterValue(kExpectedValue));
847-
thread.SetRegisterContext(reg_ctx_sp);
851+
ASSERT_TRUE(CreateTestContext(&test_ctx, "wasm32-unknown-unknown-wasm",
852+
RegisterValue(kExpectedValue)));
848853

849854
llvm::Expected<TestFile> file = TestFile::fromYaml(yamldata);
850855
EXPECT_THAT_EXPECTED(file, llvm::Succeeded());
@@ -853,7 +858,8 @@ TEST(DWARFExpression, Extensions) {
853858
SymbolFileWasm sym_file_wasm(obj_file_sp, nullptr);
854859
auto *dwarf_unit = sym_file_wasm.DebugInfo().GetUnitAtIndex(0);
855860

856-
testExpressionVendorExtensions(module_sp, *dwarf_unit, reg_ctx_sp.get());
861+
testExpressionVendorExtensions(module_sp, *dwarf_unit,
862+
test_ctx.reg_ctx_sp.get());
857863
}
858864

859865
TEST(DWARFExpression, ExtensionsSplitSymbols) {
@@ -1022,28 +1028,10 @@ TEST(DWARFExpression, ExtensionsSplitSymbols) {
10221028
subsystems;
10231029

10241030
// Set up a wasm target.
1025-
ArchSpec arch("wasm32-unknown-unknown-wasm");
1026-
lldb::PlatformSP host_platform_sp =
1027-
platform_linux::PlatformLinux::CreateInstance(true, &arch);
1028-
ASSERT_TRUE(host_platform_sp);
1029-
Platform::SetHostPlatform(host_platform_sp);
1030-
lldb::DebuggerSP debugger_sp = Debugger::CreateInstance();
1031-
ASSERT_TRUE(debugger_sp);
1032-
lldb::TargetSP target_sp;
1033-
lldb::PlatformSP platform_sp;
1034-
debugger_sp->GetTargetList().CreateTarget(*debugger_sp, "", arch,
1035-
lldb_private::eLoadDependentsNo,
1036-
platform_sp, target_sp);
1037-
// Set up a mock process and thread.
1038-
lldb::ListenerSP listener_sp(Listener::MakeListener("dummy"));
1039-
lldb::ProcessSP process_sp =
1040-
std::make_shared<MockProcess>(target_sp, listener_sp);
1041-
ASSERT_TRUE(process_sp);
1042-
MockThread thread(*process_sp);
1031+
TestContext test_ctx;
10431032
const uint32_t kExpectedValue = 42;
1044-
lldb::RegisterContextSP reg_ctx_sp = std::make_shared<MockRegisterContext>(
1045-
thread, RegisterValue(kExpectedValue));
1046-
thread.SetRegisterContext(reg_ctx_sp);
1033+
ASSERT_TRUE(CreateTestContext(&test_ctx, "wasm32-unknown-unknown-wasm",
1034+
RegisterValue(kExpectedValue)));
10471035

10481036
llvm::Expected<TestFile> skeleton_file =
10491037
TestFile::fromYaml(skeleton_yamldata);
@@ -1059,7 +1047,8 @@ TEST(DWARFExpression, ExtensionsSplitSymbols) {
10591047
SymbolFileWasm sym_file_wasm(obj_file_sp, nullptr);
10601048
auto *dwarf_unit = sym_file_wasm.DebugInfo().GetUnitAtIndex(0);
10611049

1062-
testExpressionVendorExtensions(sym_module_sp, *dwarf_unit, reg_ctx_sp.get());
1050+
testExpressionVendorExtensions(sym_module_sp, *dwarf_unit,
1051+
test_ctx.reg_ctx_sp.get());
10631052
}
10641053

10651054
TEST_F(DWARFExpressionMockProcessTest, DW_OP_piece_file_addr) {
@@ -1092,33 +1081,6 @@ TEST_F(DWARFExpressionMockProcessTest, DW_OP_piece_file_addr) {
10921081
ExpectHostAddress({0x11, 0x22}));
10931082
}
10941083

1095-
/// A Process whose `ReadMemory` override queries a DenseMap.
1096-
struct MockProcessWithMemRead : Process {
1097-
using addr_t = lldb::addr_t;
1098-
1099-
llvm::DenseMap<addr_t, addr_t> memory_map;
1100-
1101-
MockProcessWithMemRead(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
1102-
llvm::DenseMap<addr_t, addr_t> &&memory_map)
1103-
: Process(target_sp, listener_sp), memory_map(memory_map) {}
1104-
size_t DoReadMemory(addr_t vm_addr, void *buf, size_t size,
1105-
Status &error) override {
1106-
assert(memory_map.contains(vm_addr));
1107-
assert(size == sizeof(addr_t));
1108-
*reinterpret_cast<addr_t *>(buf) = memory_map[vm_addr];
1109-
return sizeof(addr_t);
1110-
}
1111-
size_t ReadMemory(addr_t addr, void *buf, size_t size,
1112-
Status &status) override {
1113-
return DoReadMemory(addr, buf, size, status);
1114-
}
1115-
bool CanDebug(lldb::TargetSP, bool) override { return true; }
1116-
Status DoDestroy() override { return Status(); }
1117-
llvm::StringRef GetPluginName() override { return ""; }
1118-
void RefreshStateAfterStop() override {}
1119-
bool DoUpdateThreadList(ThreadList &, ThreadList &) override { return false; }
1120-
};
1121-
11221084
class DWARFExpressionMockProcessTestWithAArch
11231085
: public DWARFExpressionMockProcessTest {
11241086
public:
@@ -1149,18 +1111,13 @@ TEST_F(DWARFExpressionMockProcessTestWithAArch, DW_op_deref_no_ptr_fixing) {
11491111
constexpr lldb::addr_t addr = 42;
11501112
memory[addr] = expected_value;
11511113

1152-
PlatformTargetDebugger test_setup = CreateTarget();
1153-
lldb::ProcessSP process_sp = std::make_shared<MockProcessWithMemRead>(
1154-
test_setup.target_sp, Listener::MakeListener("dummy"), std::move(memory));
1155-
auto thread = std::make_shared<MockThread>(*process_sp);
1156-
lldb::RegisterContextSP reg_ctx_sp =
1157-
std::make_shared<MockRegisterContext>(*thread, RegisterValue(addr));
1158-
thread->SetRegisterContext(reg_ctx_sp);
1159-
process_sp->GetThreadList().AddThread(thread);
1114+
TestContext test_ctx;
1115+
ASSERT_TRUE(CreateTestContext(&test_ctx, "aarch64-pc-linux",
1116+
RegisterValue(addr), std::move(memory)));
11601117

11611118
auto evaluate_expr = [&](auto &expr_data) {
1162-
ExecutionContext exe_ctx(process_sp);
1163-
return Evaluate(expr_data, {}, {}, &exe_ctx, reg_ctx_sp.get());
1119+
ExecutionContext exe_ctx(test_ctx.process_sp);
1120+
return Evaluate(expr_data, {}, {}, &exe_ctx, test_ctx.reg_ctx_sp.get());
11641121
};
11651122

11661123
uint8_t expr_reg[] = {DW_OP_breg22, 0};

0 commit comments

Comments
 (0)