180814287SRaphael Isemann //===-- DWARFExpressionTest.cpp -------------------------------------------===// 2b07a7997SPavel Labath // 3b07a7997SPavel Labath // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4b07a7997SPavel Labath // See https://llvm.org/LICENSE.txt for license information. 5b07a7997SPavel Labath // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6b07a7997SPavel Labath // 7b07a7997SPavel Labath //===----------------------------------------------------------------------===// 8b07a7997SPavel Labath 9b07a7997SPavel Labath #include "lldb/Expression/DWARFExpression.h" 10188b0747SAdrian Prantl #include "Plugins/Platform/Linux/PlatformLinux.h" 11d839f654SPhilip Pfaffe #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h" 12c08d3b08SPhilip Pfaffe #include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h" 13c21b71c1SJonas Devlieghere #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 14f37b62ecSJonas Devlieghere #include "TestingSupport/Symbol/YAMLModuleTester.h" 15188b0747SAdrian Prantl #include "lldb/Core/Debugger.h" 16c08d3b08SPhilip Pfaffe #include "lldb/Core/PluginManager.h" 1770599d70SJonas Devlieghere #include "lldb/Core/Value.h" 18b07a7997SPavel Labath #include "lldb/Core/dwarf.h" 19188b0747SAdrian Prantl #include "lldb/Host/HostInfo.h" 209b23df63SAdrian Prantl #include "lldb/Symbol/ObjectFile.h" 21b07a7997SPavel Labath #include "lldb/Utility/StreamString.h" 22b07a7997SPavel Labath #include "llvm/ADT/StringExtras.h" 23b07a7997SPavel Labath #include "llvm/Testing/Support/Error.h" 24b07a7997SPavel Labath #include "gtest/gtest.h" 25b07a7997SPavel Labath 26b07a7997SPavel Labath using namespace lldb_private; 27ae869d44SShafik Yaghmour using namespace lldb_private::dwarf; 28a669a237Swalter erquinigo using namespace lldb_private::plugin::dwarf; 29b07a7997SPavel Labath 30667c2eb0SAdrian Prantl static llvm::Expected<Scalar> Evaluate(llvm::ArrayRef<uint8_t> expr, 31667c2eb0SAdrian Prantl lldb::ModuleSP module_sp = {}, 32188b0747SAdrian Prantl DWARFUnit *unit = nullptr, 33188b0747SAdrian Prantl ExecutionContext *exe_ctx = nullptr) { 34667c2eb0SAdrian Prantl DataExtractor extractor(expr.data(), expr.size(), lldb::eByteOrderLittle, 35667c2eb0SAdrian Prantl /*addr_size*/ 4); 36539b72f2SJonas Devlieghere 37539b72f2SJonas Devlieghere llvm::Expected<Value> result = 38539b72f2SJonas Devlieghere DWARFExpression::Evaluate(exe_ctx, /*reg_ctx*/ nullptr, module_sp, 39188b0747SAdrian Prantl extractor, unit, lldb::eRegisterKindLLDB, 40667c2eb0SAdrian Prantl /*initial_value_ptr*/ nullptr, 41539b72f2SJonas Devlieghere /*object_address_ptr*/ nullptr); 42539b72f2SJonas Devlieghere if (!result) 43539b72f2SJonas Devlieghere return result.takeError(); 44667c2eb0SAdrian Prantl 45539b72f2SJonas Devlieghere switch (result->GetValueType()) { 46057efa99SAdrian Prantl case Value::ValueType::Scalar: 47539b72f2SJonas Devlieghere return result->GetScalar(); 4814ccba26SAdrian Prantl case Value::ValueType::LoadAddress: 4914ccba26SAdrian Prantl return LLDB_INVALID_ADDRESS; 50057efa99SAdrian Prantl case Value::ValueType::HostAddress: { 517b0d58e3SAdrian Prantl // Convert small buffers to scalars to simplify the tests. 52539b72f2SJonas Devlieghere DataBufferHeap &buf = result->GetBuffer(); 537b0d58e3SAdrian Prantl if (buf.GetByteSize() <= 8) { 547b0d58e3SAdrian Prantl uint64_t val = 0; 557b0d58e3SAdrian Prantl memcpy(&val, buf.GetBytes(), buf.GetByteSize()); 567b0d58e3SAdrian Prantl return Scalar(llvm::APInt(buf.GetByteSize()*8, val, false)); 577b0d58e3SAdrian Prantl } 587b0d58e3SAdrian Prantl } 5959d2495fSFangrui Song [[fallthrough]]; 607b0d58e3SAdrian Prantl default: 61539b72f2SJonas Devlieghere break; 627b0d58e3SAdrian Prantl } 63539b72f2SJonas Devlieghere return llvm::createStringError("unsupported value type"); 64667c2eb0SAdrian Prantl } 65667c2eb0SAdrian Prantl 66f37b62ecSJonas Devlieghere class DWARFExpressionTester : public YAMLModuleTester { 679b23df63SAdrian Prantl public: 68376c7bd9SGreg Clayton DWARFExpressionTester(llvm::StringRef yaml_data, size_t cu_index) : 69376c7bd9SGreg Clayton YAMLModuleTester(yaml_data, cu_index) {} 70376c7bd9SGreg Clayton 71f37b62ecSJonas Devlieghere using YAMLModuleTester::YAMLModuleTester; 72667c2eb0SAdrian Prantl llvm::Expected<Scalar> Eval(llvm::ArrayRef<uint8_t> expr) { 73a895a446SPavel Labath return ::Evaluate(expr, m_module_sp, m_dwarf_unit); 74667c2eb0SAdrian Prantl } 75667c2eb0SAdrian Prantl }; 76b07a7997SPavel Labath 779b23df63SAdrian Prantl /// Unfortunately Scalar's operator==() is really picky. 789b23df63SAdrian Prantl static Scalar GetScalar(unsigned bits, uint64_t value, bool sign) { 7916e17ca1SPavel Labath Scalar scalar(value); 8016e17ca1SPavel Labath scalar.TruncOrExtendTo(bits, sign); 819b23df63SAdrian Prantl return scalar; 829b23df63SAdrian Prantl } 839b23df63SAdrian Prantl 84188b0747SAdrian Prantl /// This is needed for the tests that use a mock process. 85188b0747SAdrian Prantl class DWARFExpressionMockProcessTest : public ::testing::Test { 86188b0747SAdrian Prantl public: 87188b0747SAdrian Prantl void SetUp() override { 88188b0747SAdrian Prantl FileSystem::Initialize(); 89188b0747SAdrian Prantl HostInfo::Initialize(); 90188b0747SAdrian Prantl platform_linux::PlatformLinux::Initialize(); 91188b0747SAdrian Prantl } 92188b0747SAdrian Prantl void TearDown() override { 93188b0747SAdrian Prantl platform_linux::PlatformLinux::Terminate(); 94188b0747SAdrian Prantl HostInfo::Terminate(); 95188b0747SAdrian Prantl FileSystem::Terminate(); 96188b0747SAdrian Prantl } 97188b0747SAdrian Prantl }; 98188b0747SAdrian Prantl 997dc84e22SJonas Devlieghere // NB: This class doesn't use the override keyword to avoid 1007dc84e22SJonas Devlieghere // -Winconsistent-missing-override warnings from the compiler. The 1017dc84e22SJonas Devlieghere // inconsistency comes from the overriding definitions in the MOCK_*** macros. 1027dc84e22SJonas Devlieghere class MockTarget : public Target { 1037dc84e22SJonas Devlieghere public: 1047dc84e22SJonas Devlieghere MockTarget(Debugger &debugger, const ArchSpec &target_arch, 1057dc84e22SJonas Devlieghere const lldb::PlatformSP &platform_sp) 1067dc84e22SJonas Devlieghere : Target(debugger, target_arch, platform_sp, true) {} 1077dc84e22SJonas Devlieghere 1087dc84e22SJonas Devlieghere MOCK_METHOD2(ReadMemory, 1097dc84e22SJonas Devlieghere llvm::Expected<std::vector<uint8_t>>(lldb::addr_t addr, 1107dc84e22SJonas Devlieghere size_t size)); 1117dc84e22SJonas Devlieghere 1127dc84e22SJonas Devlieghere size_t ReadMemory(const Address &addr, void *dst, size_t dst_len, 1137dc84e22SJonas Devlieghere Status &error, bool force_live_memory = false, 1147dc84e22SJonas Devlieghere lldb::addr_t *load_addr_ptr = nullptr) /*override*/ { 1157dc84e22SJonas Devlieghere auto expected_memory = this->ReadMemory(addr.GetOffset(), dst_len); 1167dc84e22SJonas Devlieghere if (!expected_memory) { 1177dc84e22SJonas Devlieghere llvm::consumeError(expected_memory.takeError()); 1187dc84e22SJonas Devlieghere return 0; 1197dc84e22SJonas Devlieghere } 1207dc84e22SJonas Devlieghere const size_t bytes_read = expected_memory->size(); 1217dc84e22SJonas Devlieghere assert(bytes_read <= dst_len); 1227dc84e22SJonas Devlieghere std::memcpy(dst, expected_memory->data(), bytes_read); 1237dc84e22SJonas Devlieghere return bytes_read; 1247dc84e22SJonas Devlieghere } 1257dc84e22SJonas Devlieghere }; 1267dc84e22SJonas Devlieghere 127b07a7997SPavel Labath TEST(DWARFExpression, DW_OP_pick) { 128b07a7997SPavel Labath EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit1, DW_OP_lit0, DW_OP_pick, 0}), 129b07a7997SPavel Labath llvm::HasValue(0)); 130b07a7997SPavel Labath EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit1, DW_OP_lit0, DW_OP_pick, 1}), 131b07a7997SPavel Labath llvm::HasValue(1)); 132b07a7997SPavel Labath EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit1, DW_OP_lit0, DW_OP_pick, 2}), 133b07a7997SPavel Labath llvm::Failed()); 134b07a7997SPavel Labath } 1359b23df63SAdrian Prantl 1364edb7e34SPavel Labath TEST(DWARFExpression, DW_OP_const) { 1374edb7e34SPavel Labath // Extend to address size. 1384edb7e34SPavel Labath EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const1u, 0x88}), llvm::HasValue(0x88)); 1394edb7e34SPavel Labath EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const1s, 0x88}), 1404edb7e34SPavel Labath llvm::HasValue(0xffffff88)); 1414edb7e34SPavel Labath EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const2u, 0x47, 0x88}), 1424edb7e34SPavel Labath llvm::HasValue(0x8847)); 1434edb7e34SPavel Labath EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const2s, 0x47, 0x88}), 1444edb7e34SPavel Labath llvm::HasValue(0xffff8847)); 1454edb7e34SPavel Labath EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const4u, 0x44, 0x42, 0x47, 0x88}), 1464edb7e34SPavel Labath llvm::HasValue(0x88474244)); 1474edb7e34SPavel Labath EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const4s, 0x44, 0x42, 0x47, 0x88}), 1484edb7e34SPavel Labath llvm::HasValue(0x88474244)); 1494edb7e34SPavel Labath 1504edb7e34SPavel Labath // Truncate to address size. 1514edb7e34SPavel Labath EXPECT_THAT_EXPECTED( 1524edb7e34SPavel Labath Evaluate({DW_OP_const8u, 0x00, 0x11, 0x22, 0x33, 0x44, 0x42, 0x47, 0x88}), 1534edb7e34SPavel Labath llvm::HasValue(0x33221100)); 1544edb7e34SPavel Labath EXPECT_THAT_EXPECTED( 1554edb7e34SPavel Labath Evaluate({DW_OP_const8s, 0x00, 0x11, 0x22, 0x33, 0x44, 0x42, 0x47, 0x88}), 1564edb7e34SPavel Labath llvm::HasValue(0x33221100)); 1574edb7e34SPavel Labath 1584edb7e34SPavel Labath // Don't truncate to address size for compatibility with clang (pr48087). 1594edb7e34SPavel Labath EXPECT_THAT_EXPECTED( 1604edb7e34SPavel Labath Evaluate({DW_OP_constu, 0x81, 0x82, 0x84, 0x88, 0x90, 0xa0, 0x40}), 1614edb7e34SPavel Labath llvm::HasValue(0x01010101010101)); 1624edb7e34SPavel Labath EXPECT_THAT_EXPECTED( 1634edb7e34SPavel Labath Evaluate({DW_OP_consts, 0x81, 0x82, 0x84, 0x88, 0x90, 0xa0, 0x40}), 1644edb7e34SPavel Labath llvm::HasValue(0xffff010101010101)); 1654edb7e34SPavel Labath } 1664edb7e34SPavel Labath 1675c39c31aSAndy Yankovsky TEST(DWARFExpression, DW_OP_skip) { 1685c39c31aSAndy Yankovsky EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const1u, 0x42, DW_OP_skip, 0x02, 0x00, 1695c39c31aSAndy Yankovsky DW_OP_const1u, 0xff}), 1705c39c31aSAndy Yankovsky llvm::HasValue(0x42)); 1715c39c31aSAndy Yankovsky } 1725c39c31aSAndy Yankovsky 1735c39c31aSAndy Yankovsky TEST(DWARFExpression, DW_OP_bra) { 1745c39c31aSAndy Yankovsky EXPECT_THAT_EXPECTED( 1755c39c31aSAndy Yankovsky // clang-format off 1765c39c31aSAndy Yankovsky Evaluate({ 1775c39c31aSAndy Yankovsky DW_OP_const1u, 0x42, // push 0x42 1785c39c31aSAndy Yankovsky DW_OP_const1u, 0x1, // push 0x1 1795c39c31aSAndy Yankovsky DW_OP_bra, 0x02, 0x00, // if 0x1 > 0, then skip 0x0002 opcodes 1805c39c31aSAndy Yankovsky DW_OP_const1u, 0xff, // push 0xff 1815c39c31aSAndy Yankovsky }), 1825c39c31aSAndy Yankovsky // clang-format on 1835c39c31aSAndy Yankovsky llvm::HasValue(0x42)); 184*75b37c31SJonas Devlieghere 185*75b37c31SJonas Devlieghere EXPECT_THAT_ERROR(Evaluate({DW_OP_bra, 0x01, 0x00}).takeError(), 186*75b37c31SJonas Devlieghere llvm::Failed()); 1875c39c31aSAndy Yankovsky } 1885c39c31aSAndy Yankovsky 1899b23df63SAdrian Prantl TEST(DWARFExpression, DW_OP_convert) { 1909b23df63SAdrian Prantl /// Auxiliary debug info. 191a895a446SPavel Labath const char *yamldata = R"( 192a895a446SPavel Labath --- !ELF 193a895a446SPavel Labath FileHeader: 194a895a446SPavel Labath Class: ELFCLASS64 195a895a446SPavel Labath Data: ELFDATA2LSB 196a895a446SPavel Labath Type: ET_EXEC 197a895a446SPavel Labath Machine: EM_386 198a895a446SPavel Labath DWARF: 199a895a446SPavel Labath debug_abbrev: 200a895a446SPavel Labath - Table: 201a895a446SPavel Labath - Code: 0x00000001 202a895a446SPavel Labath Tag: DW_TAG_compile_unit 203a895a446SPavel Labath Children: DW_CHILDREN_yes 204a895a446SPavel Labath Attributes: 205a895a446SPavel Labath - Attribute: DW_AT_language 206a895a446SPavel Labath Form: DW_FORM_data2 207a895a446SPavel Labath - Code: 0x00000002 208a895a446SPavel Labath Tag: DW_TAG_base_type 209a895a446SPavel Labath Children: DW_CHILDREN_no 210a895a446SPavel Labath Attributes: 211a895a446SPavel Labath - Attribute: DW_AT_encoding 212a895a446SPavel Labath Form: DW_FORM_data1 213a895a446SPavel Labath - Attribute: DW_AT_byte_size 214a895a446SPavel Labath Form: DW_FORM_data1 215a895a446SPavel Labath debug_info: 216a895a446SPavel Labath - Version: 4 217a895a446SPavel Labath AddrSize: 8 218376c7bd9SGreg Clayton AbbrevTableID: 0 219376c7bd9SGreg Clayton AbbrOffset: 0x0 220376c7bd9SGreg Clayton Entries: 221376c7bd9SGreg Clayton - AbbrCode: 0x00000001 222376c7bd9SGreg Clayton Values: 223376c7bd9SGreg Clayton - Value: 0x000000000000000C 224376c7bd9SGreg Clayton - AbbrCode: 0x00000000 225376c7bd9SGreg Clayton - Version: 4 226376c7bd9SGreg Clayton AddrSize: 8 227376c7bd9SGreg Clayton AbbrevTableID: 0 228376c7bd9SGreg Clayton AbbrOffset: 0x0 229a895a446SPavel Labath Entries: 230a895a446SPavel Labath - AbbrCode: 0x00000001 231a895a446SPavel Labath Values: 232a895a446SPavel Labath - Value: 0x000000000000000C 233a895a446SPavel Labath # 0x0000000e: 234a895a446SPavel Labath - AbbrCode: 0x00000002 235a895a446SPavel Labath Values: 236a895a446SPavel Labath - Value: 0x0000000000000007 # DW_ATE_unsigned 237a895a446SPavel Labath - Value: 0x0000000000000004 238a895a446SPavel Labath # 0x00000011: 239a895a446SPavel Labath - AbbrCode: 0x00000002 240a895a446SPavel Labath Values: 241a895a446SPavel Labath - Value: 0x0000000000000007 # DW_ATE_unsigned 242a895a446SPavel Labath - Value: 0x0000000000000008 243a895a446SPavel Labath # 0x00000014: 244a895a446SPavel Labath - AbbrCode: 0x00000002 245a895a446SPavel Labath Values: 246a895a446SPavel Labath - Value: 0x0000000000000005 # DW_ATE_signed 247a895a446SPavel Labath - Value: 0x0000000000000008 248a895a446SPavel Labath # 0x00000017: 249a895a446SPavel Labath - AbbrCode: 0x00000002 250a895a446SPavel Labath Values: 251a895a446SPavel Labath - Value: 0x0000000000000008 # DW_ATE_unsigned_char 252a895a446SPavel Labath - Value: 0x0000000000000001 253a895a446SPavel Labath # 0x0000001a: 254a895a446SPavel Labath - AbbrCode: 0x00000002 255a895a446SPavel Labath Values: 256a895a446SPavel Labath - Value: 0x0000000000000006 # DW_ATE_signed_char 257a895a446SPavel Labath - Value: 0x0000000000000001 258a895a446SPavel Labath # 0x0000001d: 259a895a446SPavel Labath - AbbrCode: 0x00000002 260a895a446SPavel Labath Values: 261a895a446SPavel Labath - Value: 0x000000000000000b # DW_ATE_numeric_string 262a895a446SPavel Labath - Value: 0x0000000000000001 263a895a446SPavel Labath - AbbrCode: 0x00000000 264376c7bd9SGreg Clayton 265a895a446SPavel Labath )"; 266376c7bd9SGreg Clayton // Compile unit relative offsets to each DW_TAG_base_type 2679b23df63SAdrian Prantl uint8_t offs_uint32_t = 0x0000000e; 2689b23df63SAdrian Prantl uint8_t offs_uint64_t = 0x00000011; 2699b23df63SAdrian Prantl uint8_t offs_sint64_t = 0x00000014; 2709b23df63SAdrian Prantl uint8_t offs_uchar = 0x00000017; 2719b23df63SAdrian Prantl uint8_t offs_schar = 0x0000001a; 2729b23df63SAdrian Prantl 273376c7bd9SGreg Clayton DWARFExpressionTester t(yamldata, /*cu_index=*/1); 274667c2eb0SAdrian Prantl ASSERT_TRUE((bool)t.GetDwarfUnit()); 2759b23df63SAdrian Prantl 2769b23df63SAdrian Prantl // Constant is given as little-endian. 2779b23df63SAdrian Prantl bool is_signed = true; 2789b23df63SAdrian Prantl bool not_signed = false; 2799b23df63SAdrian Prantl 280667c2eb0SAdrian Prantl // 281667c2eb0SAdrian Prantl // Positive tests. 282667c2eb0SAdrian Prantl // 283667c2eb0SAdrian Prantl 2849b23df63SAdrian Prantl // Leave as is. 2852c6710a5SAdrian Prantl EXPECT_THAT_EXPECTED( 2862c6710a5SAdrian Prantl t.Eval({DW_OP_const4u, 0x11, 0x22, 0x33, 0x44, // 2872c6710a5SAdrian Prantl DW_OP_convert, offs_uint32_t, DW_OP_stack_value}), 2884edb7e34SPavel Labath llvm::HasValue(GetScalar(64, 0x44332211, not_signed))); 2894edb7e34SPavel Labath 2904edb7e34SPavel Labath // Zero-extend to 64 bits. 2912c6710a5SAdrian Prantl EXPECT_THAT_EXPECTED( 2922c6710a5SAdrian Prantl t.Eval({DW_OP_const4u, 0x11, 0x22, 0x33, 0x44, // 2932c6710a5SAdrian Prantl DW_OP_convert, offs_uint64_t, DW_OP_stack_value}), 2944edb7e34SPavel Labath llvm::HasValue(GetScalar(64, 0x44332211, not_signed))); 2959b23df63SAdrian Prantl 2969b23df63SAdrian Prantl // Sign-extend to 64 bits. 2979b23df63SAdrian Prantl EXPECT_THAT_EXPECTED( 298667c2eb0SAdrian Prantl t.Eval({DW_OP_const4s, 0xcc, 0xdd, 0xee, 0xff, // 2992c6710a5SAdrian Prantl DW_OP_convert, offs_sint64_t, DW_OP_stack_value}), 3009b23df63SAdrian Prantl llvm::HasValue(GetScalar(64, 0xffffffffffeeddcc, is_signed))); 3019b23df63SAdrian Prantl 3024edb7e34SPavel Labath // Sign-extend, then truncate. 3032c6710a5SAdrian Prantl EXPECT_THAT_EXPECTED( 3042c6710a5SAdrian Prantl t.Eval({DW_OP_const4s, 0xcc, 0xdd, 0xee, 0xff, // 3054edb7e34SPavel Labath DW_OP_convert, offs_sint64_t, // 3062c6710a5SAdrian Prantl DW_OP_convert, offs_uint32_t, DW_OP_stack_value}), 3074edb7e34SPavel Labath llvm::HasValue(GetScalar(32, 0xffeeddcc, not_signed))); 3084edb7e34SPavel Labath 3094edb7e34SPavel Labath // Truncate to default unspecified (pointer-sized) type. 3104edb7e34SPavel Labath EXPECT_THAT_EXPECTED(t.Eval({DW_OP_const4s, 0xcc, 0xdd, 0xee, 0xff, // 3114edb7e34SPavel Labath DW_OP_convert, offs_sint64_t, // 3122c6710a5SAdrian Prantl DW_OP_convert, 0x00, DW_OP_stack_value}), 3134edb7e34SPavel Labath llvm::HasValue(GetScalar(32, 0xffeeddcc, not_signed))); 3144edb7e34SPavel Labath 3159b23df63SAdrian Prantl // Truncate to 8 bits. 3162c6710a5SAdrian Prantl EXPECT_THAT_EXPECTED(t.Eval({DW_OP_const4s, 'A', 'B', 'C', 'D', DW_OP_convert, 3172c6710a5SAdrian Prantl offs_uchar, DW_OP_stack_value}), 3189b23df63SAdrian Prantl llvm::HasValue(GetScalar(8, 'A', not_signed))); 3199b23df63SAdrian Prantl 3209b23df63SAdrian Prantl // Also truncate to 8 bits. 3212c6710a5SAdrian Prantl EXPECT_THAT_EXPECTED(t.Eval({DW_OP_const4s, 'A', 'B', 'C', 'D', DW_OP_convert, 3222c6710a5SAdrian Prantl offs_schar, DW_OP_stack_value}), 3239b23df63SAdrian Prantl llvm::HasValue(GetScalar(8, 'A', is_signed))); 3249b23df63SAdrian Prantl 3259b23df63SAdrian Prantl // 3269b23df63SAdrian Prantl // Errors. 3279b23df63SAdrian Prantl // 3289b23df63SAdrian Prantl 3299b23df63SAdrian Prantl // No Module. 3309b23df63SAdrian Prantl EXPECT_THAT_ERROR(Evaluate({DW_OP_const1s, 'X', DW_OP_convert, 0x00}, nullptr, 331a895a446SPavel Labath t.GetDwarfUnit()) 3329b23df63SAdrian Prantl .takeError(), 3339b23df63SAdrian Prantl llvm::Failed()); 3349b23df63SAdrian Prantl 3359b23df63SAdrian Prantl // No DIE. 336667c2eb0SAdrian Prantl EXPECT_THAT_ERROR( 337667c2eb0SAdrian Prantl t.Eval({DW_OP_const1s, 'X', DW_OP_convert, 0x01}).takeError(), 3389b23df63SAdrian Prantl llvm::Failed()); 3399b23df63SAdrian Prantl 3409b23df63SAdrian Prantl // Unsupported. 341667c2eb0SAdrian Prantl EXPECT_THAT_ERROR( 342667c2eb0SAdrian Prantl t.Eval({DW_OP_const1s, 'X', DW_OP_convert, 0x1d}).takeError(), 3439b23df63SAdrian Prantl llvm::Failed()); 3449b23df63SAdrian Prantl } 3457b0d58e3SAdrian Prantl 346f3a7d790SMed Ismail Bennani TEST(DWARFExpression, DW_OP_stack_value) { 347f3a7d790SMed Ismail Bennani EXPECT_THAT_EXPECTED(Evaluate({DW_OP_stack_value}), llvm::Failed()); 348f3a7d790SMed Ismail Bennani } 349f3a7d790SMed Ismail Bennani 3507b0d58e3SAdrian Prantl TEST(DWARFExpression, DW_OP_piece) { 3517b0d58e3SAdrian Prantl EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const2u, 0x11, 0x22, DW_OP_piece, 2, 3527b0d58e3SAdrian Prantl DW_OP_const2u, 0x33, 0x44, DW_OP_piece, 2}), 3537b0d58e3SAdrian Prantl llvm::HasValue(GetScalar(32, 0x44332211, true))); 354f55ab6f9SAdrian Prantl EXPECT_THAT_EXPECTED( 355f55ab6f9SAdrian Prantl Evaluate({DW_OP_piece, 1, DW_OP_const1u, 0xff, DW_OP_piece, 1}), 356f55ab6f9SAdrian Prantl // Note that the "00" should really be "undef", but we can't 357f55ab6f9SAdrian Prantl // represent that yet. 358f55ab6f9SAdrian Prantl llvm::HasValue(GetScalar(16, 0xff00, true))); 3597b0d58e3SAdrian Prantl } 360731fee8bSPavel Labath 361efe62b63SMed Ismail Bennani TEST(DWARFExpression, DW_OP_implicit_value) { 362efe62b63SMed Ismail Bennani unsigned char bytes = 4; 363efe62b63SMed Ismail Bennani 364efe62b63SMed Ismail Bennani EXPECT_THAT_EXPECTED( 365efe62b63SMed Ismail Bennani Evaluate({DW_OP_implicit_value, bytes, 0x11, 0x22, 0x33, 0x44}), 366efe62b63SMed Ismail Bennani llvm::HasValue(GetScalar(8 * bytes, 0x44332211, true))); 367efe62b63SMed Ismail Bennani } 368efe62b63SMed Ismail Bennani 369731fee8bSPavel Labath TEST(DWARFExpression, DW_OP_unknown) { 370731fee8bSPavel Labath EXPECT_THAT_EXPECTED( 371731fee8bSPavel Labath Evaluate({0xff}), 372731fee8bSPavel Labath llvm::FailedWithMessage( 373731fee8bSPavel Labath "Unhandled opcode DW_OP_unknown_ff in DWARFExpression")); 374731fee8bSPavel Labath } 375585e7a35SAdrian Prantl 376188b0747SAdrian Prantl TEST_F(DWARFExpressionMockProcessTest, DW_OP_deref) { 377585e7a35SAdrian Prantl EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit0, DW_OP_deref}), llvm::Failed()); 378188b0747SAdrian Prantl 379188b0747SAdrian Prantl struct MockProcess : Process { 3809b031d5eSMichał Górny MockProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp) 3819b031d5eSMichał Górny : Process(target_sp, listener_sp) {} 3829b031d5eSMichał Górny 383a3939e15SPavel Labath llvm::StringRef GetPluginName() override { return "mock process"; } 384188b0747SAdrian Prantl bool CanDebug(lldb::TargetSP target, 385188b0747SAdrian Prantl bool plugin_specified_by_name) override { 386188b0747SAdrian Prantl return false; 387188b0747SAdrian Prantl }; 388188b0747SAdrian Prantl Status DoDestroy() override { return {}; } 389188b0747SAdrian Prantl void RefreshStateAfterStop() override {} 390188b0747SAdrian Prantl bool DoUpdateThreadList(ThreadList &old_thread_list, 391188b0747SAdrian Prantl ThreadList &new_thread_list) override { 392188b0747SAdrian Prantl return false; 393188b0747SAdrian Prantl }; 394188b0747SAdrian Prantl size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, 395188b0747SAdrian Prantl Status &error) override { 396188b0747SAdrian Prantl for (size_t i = 0; i < size; ++i) 397188b0747SAdrian Prantl ((char *)buf)[i] = (vm_addr + i) & 0xff; 398188b0747SAdrian Prantl error.Clear(); 399188b0747SAdrian Prantl return size; 400188b0747SAdrian Prantl } 401188b0747SAdrian Prantl }; 402188b0747SAdrian Prantl 403188b0747SAdrian Prantl // Set up a mock process. 404188b0747SAdrian Prantl ArchSpec arch("i386-pc-linux"); 405d6678404SMed Ismail Bennani Platform::SetHostPlatform( 406d6678404SMed Ismail Bennani platform_linux::PlatformLinux::CreateInstance(true, &arch)); 407188b0747SAdrian Prantl lldb::DebuggerSP debugger_sp = Debugger::CreateInstance(); 408188b0747SAdrian Prantl ASSERT_TRUE(debugger_sp); 409188b0747SAdrian Prantl lldb::TargetSP target_sp; 410188b0747SAdrian Prantl lldb::PlatformSP platform_sp; 411188b0747SAdrian Prantl debugger_sp->GetTargetList().CreateTarget( 412188b0747SAdrian Prantl *debugger_sp, "", arch, eLoadDependentsNo, platform_sp, target_sp); 413188b0747SAdrian Prantl ASSERT_TRUE(target_sp); 414188b0747SAdrian Prantl ASSERT_TRUE(target_sp->GetArchitecture().IsValid()); 415188b0747SAdrian Prantl ASSERT_TRUE(platform_sp); 416188b0747SAdrian Prantl lldb::ListenerSP listener_sp(Listener::MakeListener("dummy")); 417188b0747SAdrian Prantl lldb::ProcessSP process_sp = 418188b0747SAdrian Prantl std::make_shared<MockProcess>(target_sp, listener_sp); 419188b0747SAdrian Prantl ASSERT_TRUE(process_sp); 420188b0747SAdrian Prantl 421188b0747SAdrian Prantl ExecutionContext exe_ctx(process_sp); 42214ccba26SAdrian Prantl // Implicit location: *0x4. 42314ccba26SAdrian Prantl EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit4, DW_OP_deref, DW_OP_stack_value}, 42414ccba26SAdrian Prantl {}, {}, &exe_ctx), 425188b0747SAdrian Prantl llvm::HasValue(GetScalar(32, 0x07060504, false))); 42614ccba26SAdrian Prantl // Memory location: *(*0x4). 42714ccba26SAdrian Prantl // Evaluate returns LLDB_INVALID_ADDRESS for all load addresses. 42814ccba26SAdrian Prantl EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit4, DW_OP_deref}, {}, {}, &exe_ctx), 42914ccba26SAdrian Prantl llvm::HasValue(Scalar(LLDB_INVALID_ADDRESS))); 4302c6710a5SAdrian Prantl // Memory location: *0x4. 4312c6710a5SAdrian Prantl // Evaluate returns LLDB_INVALID_ADDRESS for all load addresses. 4322c6710a5SAdrian Prantl EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit4}, {}, {}, &exe_ctx), 4332c6710a5SAdrian Prantl llvm::HasValue(Scalar(4))); 4342c6710a5SAdrian Prantl // Implicit location: *0x4. 4352c6710a5SAdrian Prantl // Evaluate returns LLDB_INVALID_ADDRESS for all load addresses. 4362c6710a5SAdrian Prantl EXPECT_THAT_EXPECTED( 4372c6710a5SAdrian Prantl Evaluate({DW_OP_lit4, DW_OP_deref, DW_OP_stack_value}, {}, {}, &exe_ctx), 4382c6710a5SAdrian Prantl llvm::HasValue(GetScalar(32, 0x07060504, false))); 439585e7a35SAdrian Prantl } 440d839f654SPhilip Pfaffe 441d839f654SPhilip Pfaffe TEST_F(DWARFExpressionMockProcessTest, WASM_DW_OP_addr) { 442d839f654SPhilip Pfaffe // Set up a wasm target 443d839f654SPhilip Pfaffe ArchSpec arch("wasm32-unknown-unknown-wasm"); 444d839f654SPhilip Pfaffe lldb::PlatformSP host_platform_sp = 445d6678404SMed Ismail Bennani platform_linux::PlatformLinux::CreateInstance(true, &arch); 446d839f654SPhilip Pfaffe ASSERT_TRUE(host_platform_sp); 447d839f654SPhilip Pfaffe Platform::SetHostPlatform(host_platform_sp); 448d839f654SPhilip Pfaffe lldb::DebuggerSP debugger_sp = Debugger::CreateInstance(); 449d839f654SPhilip Pfaffe ASSERT_TRUE(debugger_sp); 450d839f654SPhilip Pfaffe lldb::TargetSP target_sp; 451d839f654SPhilip Pfaffe lldb::PlatformSP platform_sp; 452d839f654SPhilip Pfaffe debugger_sp->GetTargetList().CreateTarget(*debugger_sp, "", arch, 453d839f654SPhilip Pfaffe lldb_private::eLoadDependentsNo, 454d839f654SPhilip Pfaffe platform_sp, target_sp); 455d839f654SPhilip Pfaffe 456d839f654SPhilip Pfaffe ExecutionContext exe_ctx(target_sp, false); 457d839f654SPhilip Pfaffe // DW_OP_addr takes a single operand of address size width: 458d839f654SPhilip Pfaffe uint8_t expr[] = {DW_OP_addr, 0x40, 0x0, 0x0, 0x0}; 459d839f654SPhilip Pfaffe DataExtractor extractor(expr, sizeof(expr), lldb::eByteOrderLittle, 460d839f654SPhilip Pfaffe /*addr_size*/ 4); 461539b72f2SJonas Devlieghere 462539b72f2SJonas Devlieghere llvm::Expected<Value> result = DWARFExpression::Evaluate( 463d839f654SPhilip Pfaffe &exe_ctx, /*reg_ctx*/ nullptr, /*module_sp*/ {}, extractor, 464d839f654SPhilip Pfaffe /*unit*/ nullptr, lldb::eRegisterKindLLDB, 465d839f654SPhilip Pfaffe /*initial_value_ptr*/ nullptr, 466539b72f2SJonas Devlieghere /*object_address_ptr*/ nullptr); 467d839f654SPhilip Pfaffe 468539b72f2SJonas Devlieghere ASSERT_THAT_EXPECTED(result, llvm::Succeeded()); 469539b72f2SJonas Devlieghere ASSERT_EQ(result->GetValueType(), Value::ValueType::LoadAddress); 470d839f654SPhilip Pfaffe } 471d839f654SPhilip Pfaffe 472d839f654SPhilip Pfaffe TEST_F(DWARFExpressionMockProcessTest, WASM_DW_OP_addr_index) { 473d839f654SPhilip Pfaffe const char *yamldata = R"( 474d839f654SPhilip Pfaffe --- !ELF 475d839f654SPhilip Pfaffe FileHeader: 476d839f654SPhilip Pfaffe Class: ELFCLASS64 477d839f654SPhilip Pfaffe Data: ELFDATA2LSB 478d839f654SPhilip Pfaffe Type: ET_EXEC 479d839f654SPhilip Pfaffe Machine: EM_386 480d839f654SPhilip Pfaffe DWARF: 481d839f654SPhilip Pfaffe debug_abbrev: 482d839f654SPhilip Pfaffe - Table: 483d839f654SPhilip Pfaffe - Code: 0x00000001 484d839f654SPhilip Pfaffe Tag: DW_TAG_compile_unit 485d839f654SPhilip Pfaffe Children: DW_CHILDREN_no 486d839f654SPhilip Pfaffe Attributes: 487d839f654SPhilip Pfaffe - Attribute: DW_AT_addr_base 488d839f654SPhilip Pfaffe Form: DW_FORM_sec_offset 489d839f654SPhilip Pfaffe 490d839f654SPhilip Pfaffe debug_info: 491d839f654SPhilip Pfaffe - Version: 5 492d839f654SPhilip Pfaffe AddrSize: 4 493d839f654SPhilip Pfaffe UnitType: DW_UT_compile 494d839f654SPhilip Pfaffe Entries: 495d839f654SPhilip Pfaffe - AbbrCode: 0x00000001 496d839f654SPhilip Pfaffe Values: 497d839f654SPhilip Pfaffe - Value: 0x8 # Offset of the first Address past the header 498d839f654SPhilip Pfaffe - AbbrCode: 0x0 499d839f654SPhilip Pfaffe 500d839f654SPhilip Pfaffe debug_addr: 501d839f654SPhilip Pfaffe - Version: 5 502d839f654SPhilip Pfaffe AddressSize: 4 503d839f654SPhilip Pfaffe Entries: 504d839f654SPhilip Pfaffe - Address: 0x1234 505d839f654SPhilip Pfaffe - Address: 0x5678 506d839f654SPhilip Pfaffe )"; 507d839f654SPhilip Pfaffe 508d839f654SPhilip Pfaffe // Can't use DWARFExpressionTester from above because subsystems overlap with 509d839f654SPhilip Pfaffe // the fixture. 510d839f654SPhilip Pfaffe SubsystemRAII<ObjectFileELF, SymbolFileDWARF> subsystems; 511d839f654SPhilip Pfaffe llvm::Expected<TestFile> file = TestFile::fromYaml(yamldata); 512d839f654SPhilip Pfaffe EXPECT_THAT_EXPECTED(file, llvm::Succeeded()); 513d839f654SPhilip Pfaffe auto module_sp = std::make_shared<Module>(file->moduleSpec()); 514d839f654SPhilip Pfaffe auto *dwarf_cu = llvm::cast<SymbolFileDWARF>(module_sp->GetSymbolFile()) 515d839f654SPhilip Pfaffe ->DebugInfo() 516d839f654SPhilip Pfaffe .GetUnitAtIndex(0); 517d839f654SPhilip Pfaffe ASSERT_TRUE(dwarf_cu); 518d839f654SPhilip Pfaffe dwarf_cu->ExtractDIEsIfNeeded(); 519d839f654SPhilip Pfaffe 520d839f654SPhilip Pfaffe // Set up a wasm target 521d839f654SPhilip Pfaffe ArchSpec arch("wasm32-unknown-unknown-wasm"); 522d839f654SPhilip Pfaffe lldb::PlatformSP host_platform_sp = 523d6678404SMed Ismail Bennani platform_linux::PlatformLinux::CreateInstance(true, &arch); 524d839f654SPhilip Pfaffe ASSERT_TRUE(host_platform_sp); 525d839f654SPhilip Pfaffe Platform::SetHostPlatform(host_platform_sp); 526d839f654SPhilip Pfaffe lldb::DebuggerSP debugger_sp = Debugger::CreateInstance(); 527d839f654SPhilip Pfaffe ASSERT_TRUE(debugger_sp); 528d839f654SPhilip Pfaffe lldb::TargetSP target_sp; 529d839f654SPhilip Pfaffe lldb::PlatformSP platform_sp; 530d839f654SPhilip Pfaffe debugger_sp->GetTargetList().CreateTarget(*debugger_sp, "", arch, 531d839f654SPhilip Pfaffe lldb_private::eLoadDependentsNo, 532d839f654SPhilip Pfaffe platform_sp, target_sp); 533d839f654SPhilip Pfaffe 534d839f654SPhilip Pfaffe ExecutionContext exe_ctx(target_sp, false); 53500c60496SFelipe de Azevedo Piovezan 536539b72f2SJonas Devlieghere auto evaluate = [&](DWARFExpression &expr) -> llvm::Expected<Value> { 53700c60496SFelipe de Azevedo Piovezan DataExtractor extractor; 53800c60496SFelipe de Azevedo Piovezan expr.GetExpressionData(extractor); 539539b72f2SJonas Devlieghere return DWARFExpression::Evaluate(&exe_ctx, /*reg_ctx*/ nullptr, 540539b72f2SJonas Devlieghere /*module_sp*/ {}, extractor, dwarf_cu, 541d839f654SPhilip Pfaffe lldb::eRegisterKindLLDB, 542d839f654SPhilip Pfaffe /*initial_value_ptr*/ nullptr, 543539b72f2SJonas Devlieghere /*object_address_ptr*/ nullptr); 54400c60496SFelipe de Azevedo Piovezan }; 545d839f654SPhilip Pfaffe 54600c60496SFelipe de Azevedo Piovezan // DW_OP_addrx takes a single leb128 operand, the index in the addr table: 54700c60496SFelipe de Azevedo Piovezan uint8_t expr_data[] = {DW_OP_addrx, 0x01}; 54800c60496SFelipe de Azevedo Piovezan DataExtractor extractor(expr_data, sizeof(expr_data), lldb::eByteOrderLittle, 54900c60496SFelipe de Azevedo Piovezan /*addr_size*/ 4); 55000c60496SFelipe de Azevedo Piovezan DWARFExpression expr(extractor); 55100c60496SFelipe de Azevedo Piovezan 552539b72f2SJonas Devlieghere llvm::Expected<Value> result = evaluate(expr); 553539b72f2SJonas Devlieghere ASSERT_THAT_EXPECTED(result, llvm::Succeeded()); 554539b72f2SJonas Devlieghere ASSERT_EQ(result->GetValueType(), Value::ValueType::LoadAddress); 555539b72f2SJonas Devlieghere ASSERT_EQ(result->GetScalar().UInt(), 0x5678u); 556f09f0a6bSFelipe de Azevedo Piovezan 557f09f0a6bSFelipe de Azevedo Piovezan ASSERT_TRUE(expr.Update_DW_OP_addr(dwarf_cu, 0xdeadbeef)); 558539b72f2SJonas Devlieghere result = evaluate(expr); 559539b72f2SJonas Devlieghere ASSERT_THAT_EXPECTED(result, llvm::Succeeded()); 560539b72f2SJonas Devlieghere ASSERT_EQ(result->GetValueType(), Value::ValueType::LoadAddress); 561539b72f2SJonas Devlieghere ASSERT_EQ(result->GetScalar().UInt(), 0xdeadbeefu); 562d839f654SPhilip Pfaffe } 563c08d3b08SPhilip Pfaffe 564c08d3b08SPhilip Pfaffe class CustomSymbolFileDWARF : public SymbolFileDWARF { 565c08d3b08SPhilip Pfaffe static char ID; 566c08d3b08SPhilip Pfaffe 567c08d3b08SPhilip Pfaffe public: 568c08d3b08SPhilip Pfaffe using SymbolFileDWARF::SymbolFileDWARF; 569c08d3b08SPhilip Pfaffe 570c08d3b08SPhilip Pfaffe bool isA(const void *ClassID) const override { 571c08d3b08SPhilip Pfaffe return ClassID == &ID || SymbolFile::isA(ClassID); 572c08d3b08SPhilip Pfaffe } 573c08d3b08SPhilip Pfaffe static bool classof(const SymbolFile *obj) { return obj->isA(&ID); } 574c08d3b08SPhilip Pfaffe 575c08d3b08SPhilip Pfaffe static llvm::StringRef GetPluginNameStatic() { return "custom_dwarf"; } 576c08d3b08SPhilip Pfaffe 577c08d3b08SPhilip Pfaffe static llvm::StringRef GetPluginDescriptionStatic() { 578c08d3b08SPhilip Pfaffe return "Symbol file reader with expression extensions."; 579c08d3b08SPhilip Pfaffe } 580c08d3b08SPhilip Pfaffe 581c08d3b08SPhilip Pfaffe static void Initialize() { 582c08d3b08SPhilip Pfaffe PluginManager::RegisterPlugin(GetPluginNameStatic(), 583c08d3b08SPhilip Pfaffe GetPluginDescriptionStatic(), CreateInstance, 584c08d3b08SPhilip Pfaffe SymbolFileDWARF::DebuggerInitialize); 585c08d3b08SPhilip Pfaffe } 586c08d3b08SPhilip Pfaffe 587c08d3b08SPhilip Pfaffe static void Terminate() { PluginManager::UnregisterPlugin(CreateInstance); } 588c08d3b08SPhilip Pfaffe 589c08d3b08SPhilip Pfaffe static lldb_private::SymbolFile * 590c08d3b08SPhilip Pfaffe CreateInstance(lldb::ObjectFileSP objfile_sp) { 591c08d3b08SPhilip Pfaffe return new CustomSymbolFileDWARF(std::move(objfile_sp), 592c08d3b08SPhilip Pfaffe /*dwo_section_list*/ nullptr); 593c08d3b08SPhilip Pfaffe } 594c08d3b08SPhilip Pfaffe 595c08d3b08SPhilip Pfaffe lldb::offset_t 596c08d3b08SPhilip Pfaffe GetVendorDWARFOpcodeSize(const lldb_private::DataExtractor &data, 597c08d3b08SPhilip Pfaffe const lldb::offset_t data_offset, 598c08d3b08SPhilip Pfaffe const uint8_t op) const final { 599c08d3b08SPhilip Pfaffe auto offset = data_offset; 600c08d3b08SPhilip Pfaffe if (op != DW_OP_WASM_location) { 601c08d3b08SPhilip Pfaffe return LLDB_INVALID_OFFSET; 602c08d3b08SPhilip Pfaffe } 603c08d3b08SPhilip Pfaffe 604c08d3b08SPhilip Pfaffe // DW_OP_WASM_location WASM_GLOBAL:0x03 index:u32 605c08d3b08SPhilip Pfaffe // Called with "arguments" 0x03 and 0x04 606c08d3b08SPhilip Pfaffe // Location type: 607c08d3b08SPhilip Pfaffe if (data.GetU8(&offset) != /* global */ 0x03) { 608c08d3b08SPhilip Pfaffe return LLDB_INVALID_OFFSET; 609c08d3b08SPhilip Pfaffe } 610c08d3b08SPhilip Pfaffe 611c08d3b08SPhilip Pfaffe // Index 612c08d3b08SPhilip Pfaffe if (data.GetU32(&offset) != 0x04) { 613c08d3b08SPhilip Pfaffe return LLDB_INVALID_OFFSET; 614c08d3b08SPhilip Pfaffe } 615c08d3b08SPhilip Pfaffe 616c08d3b08SPhilip Pfaffe // Report the skipped distance: 617c08d3b08SPhilip Pfaffe return offset - data_offset; 618c08d3b08SPhilip Pfaffe } 619c08d3b08SPhilip Pfaffe 620c08d3b08SPhilip Pfaffe bool 621c08d3b08SPhilip Pfaffe ParseVendorDWARFOpcode(uint8_t op, const lldb_private::DataExtractor &opcodes, 622c08d3b08SPhilip Pfaffe lldb::offset_t &offset, 623c08d3b08SPhilip Pfaffe std::vector<lldb_private::Value> &stack) const final { 624c08d3b08SPhilip Pfaffe if (op != DW_OP_WASM_location) { 625c08d3b08SPhilip Pfaffe return false; 626c08d3b08SPhilip Pfaffe } 627c08d3b08SPhilip Pfaffe 628c08d3b08SPhilip Pfaffe // DW_OP_WASM_location WASM_GLOBAL:0x03 index:u32 629c08d3b08SPhilip Pfaffe // Called with "arguments" 0x03 and 0x04 630c08d3b08SPhilip Pfaffe // Location type: 631c08d3b08SPhilip Pfaffe if (opcodes.GetU8(&offset) != /* global */ 0x03) { 632c08d3b08SPhilip Pfaffe return false; 633c08d3b08SPhilip Pfaffe } 634c08d3b08SPhilip Pfaffe 635c08d3b08SPhilip Pfaffe // Index: 636c08d3b08SPhilip Pfaffe if (opcodes.GetU32(&offset) != 0x04) { 637c08d3b08SPhilip Pfaffe return false; 638c08d3b08SPhilip Pfaffe } 639c08d3b08SPhilip Pfaffe 640c08d3b08SPhilip Pfaffe // Return some value: 641c08d3b08SPhilip Pfaffe stack.push_back({GetScalar(32, 42, false)}); 642c08d3b08SPhilip Pfaffe return true; 643c08d3b08SPhilip Pfaffe } 644c08d3b08SPhilip Pfaffe }; 645c08d3b08SPhilip Pfaffe 646c08d3b08SPhilip Pfaffe char CustomSymbolFileDWARF::ID; 647c08d3b08SPhilip Pfaffe 648c08d3b08SPhilip Pfaffe static auto testExpressionVendorExtensions(lldb::ModuleSP module_sp, 649c08d3b08SPhilip Pfaffe DWARFUnit &dwarf_unit) { 650c08d3b08SPhilip Pfaffe // Test that expression extensions can be evaluated, for example 651c08d3b08SPhilip Pfaffe // DW_OP_WASM_location which is not currently handled by DWARFExpression: 652c08d3b08SPhilip Pfaffe EXPECT_THAT_EXPECTED(Evaluate({DW_OP_WASM_location, 0x03, // WASM_GLOBAL:0x03 653c08d3b08SPhilip Pfaffe 0x04, 0x00, 0x00, // index:u32 654c08d3b08SPhilip Pfaffe 0x00, DW_OP_stack_value}, 655c08d3b08SPhilip Pfaffe module_sp, &dwarf_unit), 656c08d3b08SPhilip Pfaffe llvm::HasValue(GetScalar(32, 42, false))); 657c08d3b08SPhilip Pfaffe 658c08d3b08SPhilip Pfaffe // Test that searches for opcodes work in the presence of extensions: 659c08d3b08SPhilip Pfaffe uint8_t expr[] = {DW_OP_WASM_location, 0x03, 0x04, 0x00, 0x00, 0x00, 660c08d3b08SPhilip Pfaffe DW_OP_form_tls_address}; 661c08d3b08SPhilip Pfaffe DataExtractor extractor(expr, sizeof(expr), lldb::eByteOrderLittle, 662c08d3b08SPhilip Pfaffe /*addr_size*/ 4); 663c08d3b08SPhilip Pfaffe DWARFExpression dwarf_expr(extractor); 664c08d3b08SPhilip Pfaffe ASSERT_TRUE(dwarf_expr.ContainsThreadLocalStorage(&dwarf_unit)); 665c08d3b08SPhilip Pfaffe } 666c08d3b08SPhilip Pfaffe 667c08d3b08SPhilip Pfaffe TEST(DWARFExpression, Extensions) { 668c08d3b08SPhilip Pfaffe const char *yamldata = R"( 669c08d3b08SPhilip Pfaffe --- !ELF 670c08d3b08SPhilip Pfaffe FileHeader: 671c08d3b08SPhilip Pfaffe Class: ELFCLASS64 672c08d3b08SPhilip Pfaffe Data: ELFDATA2LSB 673c08d3b08SPhilip Pfaffe Type: ET_EXEC 674c08d3b08SPhilip Pfaffe Machine: EM_386 675c08d3b08SPhilip Pfaffe DWARF: 676c08d3b08SPhilip Pfaffe debug_abbrev: 677c08d3b08SPhilip Pfaffe - Table: 678c08d3b08SPhilip Pfaffe - Code: 0x00000001 679c08d3b08SPhilip Pfaffe Tag: DW_TAG_compile_unit 680c08d3b08SPhilip Pfaffe Children: DW_CHILDREN_no 681c08d3b08SPhilip Pfaffe debug_info: 682c08d3b08SPhilip Pfaffe - Version: 4 683c08d3b08SPhilip Pfaffe AddrSize: 4 684c08d3b08SPhilip Pfaffe Entries: 685c08d3b08SPhilip Pfaffe - AbbrCode: 0x1 686c08d3b08SPhilip Pfaffe - AbbrCode: 0x0 687c08d3b08SPhilip Pfaffe )"; 688c08d3b08SPhilip Pfaffe 689c08d3b08SPhilip Pfaffe SubsystemRAII<FileSystem, HostInfo, TypeSystemClang, ObjectFileELF, 690c08d3b08SPhilip Pfaffe CustomSymbolFileDWARF> 691c08d3b08SPhilip Pfaffe subsystems; 692c08d3b08SPhilip Pfaffe 693c08d3b08SPhilip Pfaffe llvm::Expected<TestFile> file = TestFile::fromYaml(yamldata); 694c08d3b08SPhilip Pfaffe EXPECT_THAT_EXPECTED(file, llvm::Succeeded()); 695c08d3b08SPhilip Pfaffe 696c08d3b08SPhilip Pfaffe auto module_sp = std::make_shared<Module>(file->moduleSpec()); 697c08d3b08SPhilip Pfaffe auto &symfile = 698c08d3b08SPhilip Pfaffe *llvm::cast<CustomSymbolFileDWARF>(module_sp->GetSymbolFile()); 699c08d3b08SPhilip Pfaffe auto *dwarf_unit = symfile.DebugInfo().GetUnitAtIndex(0); 700c08d3b08SPhilip Pfaffe 701c08d3b08SPhilip Pfaffe testExpressionVendorExtensions(module_sp, *dwarf_unit); 702c08d3b08SPhilip Pfaffe } 703c08d3b08SPhilip Pfaffe 704c08d3b08SPhilip Pfaffe TEST(DWARFExpression, ExtensionsDWO) { 705c08d3b08SPhilip Pfaffe const char *skeleton_yamldata = R"( 706c08d3b08SPhilip Pfaffe --- !ELF 707c08d3b08SPhilip Pfaffe FileHeader: 708c08d3b08SPhilip Pfaffe Class: ELFCLASS64 709c08d3b08SPhilip Pfaffe Data: ELFDATA2LSB 710c08d3b08SPhilip Pfaffe Type: ET_EXEC 711c08d3b08SPhilip Pfaffe Machine: EM_386 712c08d3b08SPhilip Pfaffe DWARF: 713c08d3b08SPhilip Pfaffe debug_abbrev: 714c08d3b08SPhilip Pfaffe - Table: 715c08d3b08SPhilip Pfaffe - Code: 0x00000001 716c08d3b08SPhilip Pfaffe Tag: DW_TAG_skeleton_unit 717c08d3b08SPhilip Pfaffe Children: DW_CHILDREN_no 718c08d3b08SPhilip Pfaffe Attributes: 719c08d3b08SPhilip Pfaffe - Attribute: DW_AT_dwo_name 720c08d3b08SPhilip Pfaffe Form: DW_FORM_string 721c08d3b08SPhilip Pfaffe - Attribute: DW_AT_dwo_id 722c08d3b08SPhilip Pfaffe Form: DW_FORM_data4 723c08d3b08SPhilip Pfaffe debug_info: 724c08d3b08SPhilip Pfaffe - Version: 4 725c08d3b08SPhilip Pfaffe AddrSize: 4 726c08d3b08SPhilip Pfaffe Entries: 727c08d3b08SPhilip Pfaffe - AbbrCode: 0x1 728c08d3b08SPhilip Pfaffe Values: 729c08d3b08SPhilip Pfaffe - CStr: "dwo_unit" 730c08d3b08SPhilip Pfaffe - Value: 0x01020304 731c08d3b08SPhilip Pfaffe - AbbrCode: 0x0 732c08d3b08SPhilip Pfaffe )"; 733c08d3b08SPhilip Pfaffe 734c08d3b08SPhilip Pfaffe // .dwo sections aren't currently supported by dwarfyaml. The dwo_yamldata 735c08d3b08SPhilip Pfaffe // contents where generated by roundtripping the following yaml through 736c08d3b08SPhilip Pfaffe // yaml2obj | obj2yaml and renaming the sections. This works because the 737c08d3b08SPhilip Pfaffe // structure of the .dwo and non-.dwo sections is identical. 738c08d3b08SPhilip Pfaffe // 739c08d3b08SPhilip Pfaffe // --- !ELF 740c08d3b08SPhilip Pfaffe // FileHeader: 741c08d3b08SPhilip Pfaffe // Class: ELFCLASS64 742c08d3b08SPhilip Pfaffe // Data: ELFDATA2LSB 743c08d3b08SPhilip Pfaffe // Type: ET_EXEC 744c08d3b08SPhilip Pfaffe // Machine: EM_386 745c08d3b08SPhilip Pfaffe // DWARF: 746c08d3b08SPhilip Pfaffe // debug_abbrev: #.dwo 747c08d3b08SPhilip Pfaffe // - Table: 748c08d3b08SPhilip Pfaffe // - Code: 0x00000001 749c08d3b08SPhilip Pfaffe // Tag: DW_TAG_compile_unit 750c08d3b08SPhilip Pfaffe // Children: DW_CHILDREN_no 751c08d3b08SPhilip Pfaffe // Attributes: 752c08d3b08SPhilip Pfaffe // - Attribute: DW_AT_dwo_id 753c08d3b08SPhilip Pfaffe // Form: DW_FORM_data4 754c08d3b08SPhilip Pfaffe // debug_info: #.dwo 755c08d3b08SPhilip Pfaffe // - Version: 4 756c08d3b08SPhilip Pfaffe // AddrSize: 4 757c08d3b08SPhilip Pfaffe // Entries: 758c08d3b08SPhilip Pfaffe // - AbbrCode: 0x1 759c08d3b08SPhilip Pfaffe // Values: 76034a8e6eeSAlexander Yermolovich // - Value: 0x0120304 761c08d3b08SPhilip Pfaffe // - AbbrCode: 0x0 762c08d3b08SPhilip Pfaffe const char *dwo_yamldata = R"( 763c08d3b08SPhilip Pfaffe --- !ELF 764c08d3b08SPhilip Pfaffe FileHeader: 765c08d3b08SPhilip Pfaffe Class: ELFCLASS64 766c08d3b08SPhilip Pfaffe Data: ELFDATA2LSB 767c08d3b08SPhilip Pfaffe Type: ET_EXEC 768c08d3b08SPhilip Pfaffe Machine: EM_386 769c08d3b08SPhilip Pfaffe Sections: 770c08d3b08SPhilip Pfaffe - Name: .debug_abbrev.dwo 771c08d3b08SPhilip Pfaffe Type: SHT_PROGBITS 772c08d3b08SPhilip Pfaffe AddressAlign: 0x1 773c08d3b08SPhilip Pfaffe Content: '0111007506000000' 774c08d3b08SPhilip Pfaffe - Name: .debug_info.dwo 775c08d3b08SPhilip Pfaffe Type: SHT_PROGBITS 776c08d3b08SPhilip Pfaffe AddressAlign: 0x1 777c08d3b08SPhilip Pfaffe Content: 0D00000004000000000004010403020100 778c08d3b08SPhilip Pfaffe )"; 779c08d3b08SPhilip Pfaffe 780c08d3b08SPhilip Pfaffe SubsystemRAII<FileSystem, HostInfo, ObjectFileELF, CustomSymbolFileDWARF> 781c08d3b08SPhilip Pfaffe subsystems; 782c08d3b08SPhilip Pfaffe 783c08d3b08SPhilip Pfaffe llvm::Expected<TestFile> skeleton_file = 784c08d3b08SPhilip Pfaffe TestFile::fromYaml(skeleton_yamldata); 785c08d3b08SPhilip Pfaffe EXPECT_THAT_EXPECTED(skeleton_file, llvm::Succeeded()); 786c08d3b08SPhilip Pfaffe llvm::Expected<TestFile> dwo_file = TestFile::fromYaml(dwo_yamldata); 787c08d3b08SPhilip Pfaffe EXPECT_THAT_EXPECTED(dwo_file, llvm::Succeeded()); 788c08d3b08SPhilip Pfaffe 789c08d3b08SPhilip Pfaffe auto skeleton_module_sp = 790c08d3b08SPhilip Pfaffe std::make_shared<Module>(skeleton_file->moduleSpec()); 791c08d3b08SPhilip Pfaffe auto &skeleton_symfile = 792c08d3b08SPhilip Pfaffe *llvm::cast<CustomSymbolFileDWARF>(skeleton_module_sp->GetSymbolFile()); 793c08d3b08SPhilip Pfaffe 794c08d3b08SPhilip Pfaffe auto dwo_module_sp = std::make_shared<Module>(dwo_file->moduleSpec()); 795c08d3b08SPhilip Pfaffe SymbolFileDWARFDwo dwo_symfile( 796c08d3b08SPhilip Pfaffe skeleton_symfile, dwo_module_sp->GetObjectFile()->shared_from_this(), 79734a8e6eeSAlexander Yermolovich 0x0120304); 798c08d3b08SPhilip Pfaffe auto *dwo_dwarf_unit = dwo_symfile.DebugInfo().GetUnitAtIndex(0); 799c08d3b08SPhilip Pfaffe 800c08d3b08SPhilip Pfaffe testExpressionVendorExtensions(dwo_module_sp, *dwo_dwarf_unit); 801c08d3b08SPhilip Pfaffe } 8027dc84e22SJonas Devlieghere 8037dc84e22SJonas Devlieghere TEST_F(DWARFExpressionMockProcessTest, DW_OP_piece_file_addr) { 8047dc84e22SJonas Devlieghere using ::testing::ByMove; 8057dc84e22SJonas Devlieghere using ::testing::ElementsAre; 8067dc84e22SJonas Devlieghere using ::testing::Return; 8077dc84e22SJonas Devlieghere 8087dc84e22SJonas Devlieghere // Set up a mock process. 8097dc84e22SJonas Devlieghere ArchSpec arch("i386-pc-linux"); 8107dc84e22SJonas Devlieghere Platform::SetHostPlatform( 8117dc84e22SJonas Devlieghere platform_linux::PlatformLinux::CreateInstance(true, &arch)); 8127dc84e22SJonas Devlieghere lldb::DebuggerSP debugger_sp = Debugger::CreateInstance(); 8137dc84e22SJonas Devlieghere ASSERT_TRUE(debugger_sp); 8147dc84e22SJonas Devlieghere lldb::PlatformSP platform_sp; 8157dc84e22SJonas Devlieghere auto target_sp = 8167dc84e22SJonas Devlieghere std::make_shared<MockTarget>(*debugger_sp, arch, platform_sp); 8177dc84e22SJonas Devlieghere ASSERT_TRUE(target_sp); 8187dc84e22SJonas Devlieghere ASSERT_TRUE(target_sp->GetArchitecture().IsValid()); 8197dc84e22SJonas Devlieghere 8207dc84e22SJonas Devlieghere EXPECT_CALL(*target_sp, ReadMemory(0x40, 1)) 8217dc84e22SJonas Devlieghere .WillOnce(Return(ByMove(std::vector<uint8_t>{0x11}))); 8227dc84e22SJonas Devlieghere EXPECT_CALL(*target_sp, ReadMemory(0x50, 1)) 8237dc84e22SJonas Devlieghere .WillOnce(Return(ByMove(std::vector<uint8_t>{0x22}))); 8247dc84e22SJonas Devlieghere 8257dc84e22SJonas Devlieghere ExecutionContext exe_ctx(static_cast<lldb::TargetSP>(target_sp), false); 8267dc84e22SJonas Devlieghere 8277dc84e22SJonas Devlieghere uint8_t expr[] = {DW_OP_addr, 0x40, 0x0, 0x0, 0x0, DW_OP_piece, 1, 8287dc84e22SJonas Devlieghere DW_OP_addr, 0x50, 0x0, 0x0, 0x0, DW_OP_piece, 1}; 8297dc84e22SJonas Devlieghere DataExtractor extractor(expr, sizeof(expr), lldb::eByteOrderLittle, 8307dc84e22SJonas Devlieghere /*addr_size*/ 4); 831539b72f2SJonas Devlieghere llvm::Expected<Value> result = DWARFExpression::Evaluate( 8327dc84e22SJonas Devlieghere &exe_ctx, /*reg_ctx*/ nullptr, /*module_sp*/ {}, extractor, 8337dc84e22SJonas Devlieghere /*unit*/ nullptr, lldb::eRegisterKindLLDB, 8347dc84e22SJonas Devlieghere /*initial_value_ptr*/ nullptr, 835539b72f2SJonas Devlieghere /*object_address_ptr*/ nullptr); 8367dc84e22SJonas Devlieghere 837539b72f2SJonas Devlieghere ASSERT_THAT_EXPECTED(result, llvm::Succeeded()); 838539b72f2SJonas Devlieghere ASSERT_EQ(result->GetValueType(), Value::ValueType::HostAddress); 839539b72f2SJonas Devlieghere ASSERT_THAT(result->GetBuffer().GetData(), ElementsAre(0x11, 0x22)); 8407dc84e22SJonas Devlieghere } 841