@@ -40,6 +40,51 @@ using namespace lldb_private;
4040using namespace llvm ::dwarf;
4141
4242namespace {
43+ // / A mock implementation of DWARFExpression::Delegate for testing.
44+ // / This class provides default implementations of all delegate methods,
45+ // / with the DWARF version being configurable via the constructor.
46+ class MockDwarfDelegate : public DWARFExpression ::Delegate {
47+ public:
48+ static constexpr uint16_t DEFAULT_DWARF_VERSION = 5 ;
49+ static MockDwarfDelegate Dwarf5 () { return MockDwarfDelegate (5 ); }
50+ static MockDwarfDelegate Dwarf2 () { return MockDwarfDelegate (2 ); }
51+
52+ MockDwarfDelegate () : MockDwarfDelegate(DEFAULT_DWARF_VERSION) {}
53+ explicit MockDwarfDelegate (uint16_t version) : m_dwarf_version(version) {}
54+
55+ uint16_t GetVersion () const override { return m_dwarf_version; }
56+
57+ dw_addr_t GetBaseAddress () const override { return 0 ; }
58+
59+ uint8_t GetAddressByteSize () const override { return 4 ; }
60+
61+ llvm::Expected<std::pair<uint64_t , bool >>
62+ GetDIEBitSizeAndSign (uint64_t relative_die_offset) const override {
63+ return llvm::createStringError (llvm::inconvertibleErrorCode (),
64+ " GetDIEBitSizeAndSign not implemented" );
65+ }
66+
67+ dw_addr_t ReadAddressFromDebugAddrSection (uint32_t index) const override {
68+ return 0 ;
69+ }
70+
71+ lldb::offset_t GetVendorDWARFOpcodeSize (const DataExtractor &data,
72+ const lldb::offset_t data_offset,
73+ const uint8_t op) const override {
74+ return LLDB_INVALID_OFFSET;
75+ }
76+
77+ bool ParseVendorDWARFOpcode (uint8_t op, const DataExtractor &opcodes,
78+ lldb::offset_t &offset, RegisterContext *reg_ctx,
79+ lldb::RegisterKind reg_kind,
80+ DWARFExpression::Stack &stack) const override {
81+ return false ;
82+ }
83+
84+ private:
85+ uint16_t m_dwarf_version;
86+ };
87+
4388// / Mock memory implementation for testing.
4489// / Stores predefined memory contents indexed by {address, size} pairs.
4590class MockMemory {
@@ -189,7 +234,7 @@ class MockRegisterContext : public RegisterContext {
189234
190235static llvm::Expected<Value> Evaluate (llvm::ArrayRef<uint8_t > expr,
191236 lldb::ModuleSP module_sp = {},
192- DWARFUnit *unit = nullptr ,
237+ DWARFExpression::Delegate *unit = nullptr ,
193238 ExecutionContext *exe_ctx = nullptr ,
194239 RegisterContext *reg_ctx = nullptr ) {
195240 DataExtractor extractor (expr.data (), expr.size (), lldb::eByteOrderLittle,
@@ -534,6 +579,23 @@ TEST(DWARFExpression, DW_OP_stack_value) {
534579 EXPECT_THAT_EXPECTED (Evaluate ({DW_OP_stack_value}), llvm::Failed ());
535580}
536581
582+ // This test shows that the dwarf version is used by the expression evaluation.
583+ // Note that the different behavior tested here is not meant to imply that this
584+ // is the correct interpretation of dwarf2 vs. dwarf5, but rather it was picked
585+ // as an easy example that evaluates differently based on the dwarf version.
586+ TEST (DWARFExpression, dwarf_version) {
587+ MockDwarfDelegate dwarf2 = MockDwarfDelegate::Dwarf2 ();
588+ MockDwarfDelegate dwarf5 = MockDwarfDelegate::Dwarf5 ();
589+
590+ // In dwarf2 the constant on top of the stack is treated as a value.
591+ EXPECT_THAT_EXPECTED (Evaluate ({DW_OP_lit1}, {}, &dwarf2), ExpectScalar (1 ));
592+
593+ // In dwarf5 the constant on top of the stack is implicitly converted to an
594+ // address.
595+ EXPECT_THAT_EXPECTED (Evaluate ({DW_OP_lit1}, {}, &dwarf5),
596+ ExpectLoadAddress (1 ));
597+ }
598+
537599TEST (DWARFExpression, DW_OP_piece) {
538600 EXPECT_THAT_EXPECTED (Evaluate ({DW_OP_const2u, 0x11 , 0x22 , DW_OP_piece, 2 ,
539601 DW_OP_const2u, 0x33 , 0x44 , DW_OP_piece, 2 }),
0 commit comments