[Lldb-commits] [lldb] [lldb] Support DW_OP_WASM_location in DWARFExpression (PR #78977)
Paolo Severini via lldb-commits
lldb-commits at lists.llvm.org
Mon Jan 29 06:26:38 PST 2024
https://github.com/paolosevMSFT updated https://github.com/llvm/llvm-project/pull/78977
>From 4bcf2b50123b18752108aad163a059577e360aa6 Mon Sep 17 00:00:00 2001
From: Paolo Severini <paolosev at microsoft.com>
Date: Mon, 22 Jan 2024 06:06:56 -0800
Subject: [PATCH 1/2] Add support for DW_OP_WASM_location to DWARFExpression
---
lldb/source/Expression/DWARFExpression.cpp | 41 ++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index fe4928d4f43a434..95033db5ed8f5a1 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -346,6 +346,16 @@ static offset_t GetOpcodeDataSize(const DataExtractor &data,
return (offset - data_offset) + subexpr_len;
}
+ case DW_OP_WASM_location: {
+ uint8_t wasm_op = data.GetU8(&offset);
+ if (wasm_op == 3) {
+ data.GetU32(&offset);
+ } else {
+ data.GetULEB128(&offset);
+ }
+ return offset - data_offset;
+ }
+
default:
if (!dwarf_cu) {
return LLDB_INVALID_OFFSET;
@@ -2595,6 +2605,37 @@ bool DWARFExpression::Evaluate(
break;
}
+ case DW_OP_WASM_location: {
+ uint8_t wasm_op = opcodes.GetU8(&offset);
+ uint32_t index;
+
+ /* LLDB doesn't have an address space to represents WebAssembly locals,
+ * globals and operand stacks.
+ * We encode these elements into virtual registers:
+ * | tag: 2 bits | index: 30 bits |
+ * where tag is:
+ * 0: Not a WebAssembly location
+ * 1: Local
+ * 2: Global
+ * 3: Operand stack value
+ */
+ if (wasm_op == 3) {
+ index = opcodes.GetU32(&offset);
+ wasm_op = 2; // Global
+ } else {
+ index = opcodes.GetULEB128(&offset);
+ }
+
+ reg_num = (((wasm_op + 1) & 0x03) << 30) | (index & 0x3fffffff);
+
+ if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, tmp))
+ stack.push_back(tmp);
+ else
+ return false;
+
+ break;
+ }
+
default:
if (dwarf_cu) {
if (dwarf_cu->GetSymbolFileDWARF().ParseVendorDWARFOpcode(
>From 639295de7bdd4a2e710b62337a511ded92eb702a Mon Sep 17 00:00:00 2001
From: Paolo Severini <paolosev at microsoft.com>
Date: Mon, 29 Jan 2024 06:25:58 -0800
Subject: [PATCH 2/2] Add unite tests
---
.../include/lldb/Expression/DWARFExpression.h | 5 +
lldb/source/Expression/DWARFExpression.cpp | 53 +-
.../ObjectFile/wasm/ObjectFileWasm.cpp | 6 +-
.../SymbolFile/DWARF/SymbolFileDWARF.cpp | 66 ++
.../SymbolFile/DWARF/SymbolFileDWARF.h | 27 +-
.../SymbolFile/DWARF/SymbolFileDWARFDwo.cpp | 8 +-
.../SymbolFile/DWARF/SymbolFileDWARFDwo.h | 8 +-
lldb/unittests/Expression/CMakeLists.txt | 2 +
.../Expression/DWARFExpressionTest.cpp | 562 ++++++++++++++----
9 files changed, 580 insertions(+), 157 deletions(-)
diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h
index 1d85308d1caa735..73143399ff147f4 100644
--- a/lldb/include/lldb/Expression/DWARFExpression.h
+++ b/lldb/include/lldb/Expression/DWARFExpression.h
@@ -153,6 +153,11 @@ class DWARFExpression {
bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op) const;
+ static bool ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
+ lldb::RegisterKind reg_kind,
+ uint32_t reg_num, Status *error_ptr,
+ Value &value);
+
private:
/// A data extractor capable of reading opcode bytes
DataExtractor m_data;
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 95033db5ed8f5a1..7298ccbf998d4d9 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -95,10 +95,12 @@ void DWARFExpression::SetRegisterKind(RegisterKind reg_kind) {
}
-static bool ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
- lldb::RegisterKind reg_kind,
- uint32_t reg_num, Status *error_ptr,
- Value &value) {
+// static
+bool DWARFExpression::ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
+ lldb::RegisterKind reg_kind,
+ uint32_t reg_num,
+ Status *error_ptr,
+ Value &value) {
if (reg_ctx == nullptr) {
if (error_ptr)
error_ptr->SetErrorString("No register context in frame.\n");
@@ -346,16 +348,6 @@ static offset_t GetOpcodeDataSize(const DataExtractor &data,
return (offset - data_offset) + subexpr_len;
}
- case DW_OP_WASM_location: {
- uint8_t wasm_op = data.GetU8(&offset);
- if (wasm_op == 3) {
- data.GetU32(&offset);
- } else {
- data.GetULEB128(&offset);
- }
- return offset - data_offset;
- }
-
default:
if (!dwarf_cu) {
return LLDB_INVALID_OFFSET;
@@ -2605,41 +2597,10 @@ bool DWARFExpression::Evaluate(
break;
}
- case DW_OP_WASM_location: {
- uint8_t wasm_op = opcodes.GetU8(&offset);
- uint32_t index;
-
- /* LLDB doesn't have an address space to represents WebAssembly locals,
- * globals and operand stacks.
- * We encode these elements into virtual registers:
- * | tag: 2 bits | index: 30 bits |
- * where tag is:
- * 0: Not a WebAssembly location
- * 1: Local
- * 2: Global
- * 3: Operand stack value
- */
- if (wasm_op == 3) {
- index = opcodes.GetU32(&offset);
- wasm_op = 2; // Global
- } else {
- index = opcodes.GetULEB128(&offset);
- }
-
- reg_num = (((wasm_op + 1) & 0x03) << 30) | (index & 0x3fffffff);
-
- if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, tmp))
- stack.push_back(tmp);
- else
- return false;
-
- break;
- }
-
default:
if (dwarf_cu) {
if (dwarf_cu->GetSymbolFileDWARF().ParseVendorDWARFOpcode(
- op, opcodes, offset, stack)) {
+ op, reg_ctx, opcodes, reg_kind, offset, stack, error_ptr)) {
break;
}
}
diff --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
index 06eb6ff9cafb5d5..cf643ba51280d21 100644
--- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
+++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
@@ -406,9 +406,13 @@ DataExtractor ObjectFileWasm::ReadImageData(offset_t offset, uint32_t size) {
DataBufferSP buffer_sp(data_up.release());
data.SetData(buffer_sp, 0, buffer_sp->GetByteSize());
}
+ } else if (offset < m_data.GetByteSize()) {
+ size =
+ std::min(static_cast<uint64_t>(size), m_data.GetByteSize() - offset);
+ return DataExtractor(m_data.GetDataStart() + offset, size, GetByteOrder(),
+ GetAddressByteSize());
}
}
-
data.SetByteOrder(GetByteOrder());
return data;
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index fed97858c83f8e2..72a831a8ab411fe 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -31,6 +31,7 @@
#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
+#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
@@ -327,6 +328,9 @@ llvm::StringRef SymbolFileDWARF::GetPluginDescriptionStatic() {
}
SymbolFile *SymbolFileDWARF::CreateInstance(ObjectFileSP objfile_sp) {
+ if (llvm::isa<lldb_private::wasm::ObjectFileWasm>(*objfile_sp))
+ return new wasm::SymbolFileWasm(std::move(objfile_sp),
+ /*dwo_section_list*/ nullptr);
return new SymbolFileDWARF(std::move(objfile_sp),
/*dwo_section_list*/ nullptr);
}
@@ -4476,3 +4480,65 @@ void SymbolFileDWARF::GetCompileOptions(
args.insert({comp_unit, Args(flags)});
}
}
+
+using namespace lldb_private::plugin::dwarf::wasm;
+
+SymbolFileWasm::SymbolFileWasm(ObjectFileSP objfile_sp,
+ SectionList *dwo_section_list)
+ : SymbolFileDWARF(objfile_sp, dwo_section_list) {}
+
+SymbolFileWasm::~SymbolFileWasm() = default;
+
+lldb::offset_t
+SymbolFileWasm::GetVendorDWARFOpcodeSize(const DataExtractor &data,
+ const lldb::offset_t data_offset,
+ const uint8_t op) const {
+ if (op != DW_OP_WASM_location) {
+ return LLDB_INVALID_OFFSET;
+ }
+
+ lldb::offset_t offset = data_offset;
+ uint8_t wasm_op = data.GetU8(&offset);
+ if (wasm_op == 3) {
+ data.GetU32(&offset);
+ } else {
+ data.GetULEB128(&offset);
+ }
+ return offset - data_offset;
+}
+
+bool SymbolFileWasm::ParseVendorDWARFOpcode(
+ uint8_t op, RegisterContext *reg_ctx, const DataExtractor &opcodes,
+ const lldb::RegisterKind reg_kind, lldb::offset_t &offset,
+ std::vector<Value> &stack, Status *error_ptr) const {
+ uint8_t wasm_op = opcodes.GetU8(&offset);
+
+ /* LLDB doesn't have an address space to represents WebAssembly locals,
+ * globals and operand stacks.
+ * We encode these elements into virtual registers:
+ * | tag: 2 bits | index: 30 bits |
+ * where tag is:
+ * 0: Not a WebAssembly location
+ * 1: Local
+ * 2: Global
+ * 3: Operand stack value
+ */
+ uint32_t index;
+ if (wasm_op == 3) {
+ index = opcodes.GetU32(&offset);
+ wasm_op = 2; // Global
+ } else {
+ index = opcodes.GetULEB128(&offset);
+ }
+
+ uint32_t reg_num = (((wasm_op + 1) & 0x03) << 30) | (index & 0x3fffffff);
+
+ Value tmp;
+ if (DWARFExpression::ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num,
+ error_ptr, tmp)) {
+ stack.push_back(tmp);
+ return true;
+ }
+ else
+ return false;
+}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 26a9502f90aa006..daacad8af46d527 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -305,9 +305,12 @@ class SymbolFileDWARF : public SymbolFileCommon {
return LLDB_INVALID_OFFSET;
}
- virtual bool ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes,
+ virtual bool ParseVendorDWARFOpcode(uint8_t op, RegisterContext *reg_ctx,
+ const DataExtractor &opcodes,
+ const lldb::RegisterKind reg_kind,
lldb::offset_t &offset,
- std::vector<Value> &stack) const {
+ std::vector<Value> &stack,
+ Status *error_ptr) const {
return false;
}
@@ -547,6 +550,26 @@ class SymbolFileDWARF : public SymbolFileCommon {
/// an index that identifies the .DWO or .o file.
std::optional<uint64_t> m_file_index;
};
+
+namespace wasm {
+class SymbolFileWasm : public SymbolFileDWARF {
+public:
+ SymbolFileWasm(lldb::ObjectFileSP objfile_sp, SectionList *dwo_section_list);
+
+ ~SymbolFileWasm() override;
+
+ lldb::offset_t GetVendorDWARFOpcodeSize(const DataExtractor &data,
+ const lldb::offset_t data_offset,
+ const uint8_t op) const override;
+
+ bool ParseVendorDWARFOpcode(uint8_t op, RegisterContext *reg_ctx,
+ const DataExtractor &opcodes,
+ const lldb::RegisterKind reg_kind,
+ lldb::offset_t &offset, std::vector<Value> &stack,
+ Status *error_ptr) const override;
+};
+} // namespace wasm
+
} // namespace dwarf
} // namespace lldb_private::plugin
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
index ca698a84a9146da..379b98ff9b561b5 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -86,9 +86,11 @@ lldb::offset_t SymbolFileDWARFDwo::GetVendorDWARFOpcodeSize(
}
bool SymbolFileDWARFDwo::ParseVendorDWARFOpcode(
- uint8_t op, const lldb_private::DataExtractor &opcodes,
- lldb::offset_t &offset, std::vector<lldb_private::Value> &stack) const {
- return GetBaseSymbolFile().ParseVendorDWARFOpcode(op, opcodes, offset, stack);
+ uint8_t op, RegisterContext *reg_ctx, const DataExtractor &opcodes,
+ const lldb::RegisterKind reg_kind, lldb::offset_t &offset,
+ std::vector<Value> &stack, Status *error_ptr) const {
+ return GetBaseSymbolFile().ParseVendorDWARFOpcode(
+ op, reg_ctx, opcodes, reg_kind, offset, stack, error_ptr);
}
SymbolFileDWARF::DIEToTypePtr &SymbolFileDWARFDwo::GetDIEToType() {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
index 9f5950e51b0c180..1025fc47c28fffb 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -47,9 +47,11 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF {
const lldb::offset_t data_offset,
const uint8_t op) const override;
- bool ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes,
- lldb::offset_t &offset,
- std::vector<Value> &stack) const override;
+ bool ParseVendorDWARFOpcode(uint8_t op, RegisterContext *reg_ctx,
+ const DataExtractor &opcodes,
+ const lldb::RegisterKind reg_kind,
+ lldb::offset_t &offset, std::vector<Value> &stack,
+ Status *error_ptr) const override;
void FindGlobalVariables(ConstString name,
const CompilerDeclContext &parent_decl_ctx,
diff --git a/lldb/unittests/Expression/CMakeLists.txt b/lldb/unittests/Expression/CMakeLists.txt
index 185b19f84cae79a..533cdc673e6d196 100644
--- a/lldb/unittests/Expression/CMakeLists.txt
+++ b/lldb/unittests/Expression/CMakeLists.txt
@@ -8,6 +8,8 @@ add_lldb_unittest(ExpressionTests
LINK_LIBS
lldbCore
lldbPluginObjectFileELF
+ lldbPluginObjectFileWasm
+ lldbPluginSymbolVendorWasm
lldbPluginPlatformLinux
lldbPluginExpressionParserClang
lldbPluginTypeSystemClang
diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index 8d77d6b2585f146..82bcf9695a17623 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -7,9 +7,11 @@
//===----------------------------------------------------------------------===//
#include "lldb/Expression/DWARFExpression.h"
+#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h"
#include "Plugins/Platform/Linux/PlatformLinux.h"
#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
+#include "Plugins/SymbolVendor/wasm/SymbolVendorWasm.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "TestingSupport/Symbol/YAMLModuleTester.h"
#include "lldb/Core/Debugger.h"
@@ -18,6 +20,8 @@
#include "lldb/Core/dwarf.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Testing/Support/Error.h"
@@ -26,20 +30,22 @@
using namespace lldb_private;
using namespace lldb_private::dwarf;
using namespace lldb_private::plugin::dwarf;
+using namespace lldb_private::plugin::dwarf::wasm;
+using namespace lldb_private::wasm;
static llvm::Expected<Scalar> Evaluate(llvm::ArrayRef<uint8_t> expr,
lldb::ModuleSP module_sp = {},
DWARFUnit *unit = nullptr,
- ExecutionContext *exe_ctx = nullptr) {
+ ExecutionContext *exe_ctx = nullptr,
+ RegisterContext *reg_ctx = nullptr) {
DataExtractor extractor(expr.data(), expr.size(), lldb::eByteOrderLittle,
/*addr_size*/ 4);
Value result;
Status status;
- if (!DWARFExpression::Evaluate(exe_ctx, /*reg_ctx*/ nullptr, module_sp,
- extractor, unit, lldb::eRegisterKindLLDB,
- /*initial_value_ptr*/ nullptr,
- /*object_address_ptr*/ nullptr, result,
- &status))
+ if (!DWARFExpression::Evaluate(
+ exe_ctx, reg_ctx, module_sp, extractor, unit, lldb::eRegisterKindLLDB,
+ /*initial_value_ptr*/ nullptr,
+ /*object_address_ptr*/ nullptr, result, &status))
return status.ToError();
switch (result.GetValueType()) {
@@ -341,32 +347,33 @@ TEST(DWARFExpression, DW_OP_unknown) {
"Unhandled opcode DW_OP_unknown_ff in DWARFExpression"));
}
-TEST_F(DWARFExpressionMockProcessTest, DW_OP_deref) {
- EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit0, DW_OP_deref}), llvm::Failed());
+namespace {
+struct MockProcess : Process {
+ MockProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp)
+ : Process(target_sp, listener_sp) {}
- struct MockProcess : Process {
- MockProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp)
- : Process(target_sp, listener_sp) {}
-
- llvm::StringRef GetPluginName() override { return "mock process"; }
- bool CanDebug(lldb::TargetSP target,
- bool plugin_specified_by_name) override {
- return false;
- };
- Status DoDestroy() override { return {}; }
- void RefreshStateAfterStop() override {}
- bool DoUpdateThreadList(ThreadList &old_thread_list,
- ThreadList &new_thread_list) override {
- return false;
- };
- size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
- Status &error) override {
- for (size_t i = 0; i < size; ++i)
- ((char *)buf)[i] = (vm_addr + i) & 0xff;
- error.Clear();
- return size;
- }
+ llvm::StringRef GetPluginName() override { return "mock process"; }
+ bool CanDebug(lldb::TargetSP target, bool plugin_specified_by_name) override {
+ return false;
+ };
+ Status DoDestroy() override { return {}; }
+ void RefreshStateAfterStop() override {}
+ bool DoUpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list) override {
+ return false;
};
+ size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
+ Status &error) override {
+ for (size_t i = 0; i < size; ++i)
+ ((char *)buf)[i] = (vm_addr + i) & 0xff;
+ error.Clear();
+ return size;
+ }
+};
+} // namespace
+
+TEST_F(DWARFExpressionMockProcessTest, DW_OP_deref) {
+ EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit0, DW_OP_deref}), llvm::Failed());
// Set up a mock process.
ArchSpec arch("i386-pc-linux");
@@ -529,7 +536,7 @@ TEST_F(DWARFExpressionMockProcessTest, WASM_DW_OP_addr_index) {
ASSERT_EQ(result.GetValueType(), Value::ValueType::LoadAddress);
ASSERT_EQ(result.GetScalar().UInt(), 0xdeadbeefu);
}
-
+/*
class CustomSymbolFileDWARF : public SymbolFileDWARF {
static char ID;
@@ -557,82 +564,12 @@ class CustomSymbolFileDWARF : public SymbolFileDWARF {
static lldb_private::SymbolFile *
CreateInstance(lldb::ObjectFileSP objfile_sp) {
- return new CustomSymbolFileDWARF(std::move(objfile_sp),
- /*dwo_section_list*/ nullptr);
- }
-
- lldb::offset_t
- GetVendorDWARFOpcodeSize(const lldb_private::DataExtractor &data,
- const lldb::offset_t data_offset,
- const uint8_t op) const final {
- auto offset = data_offset;
- if (op != DW_OP_WASM_location) {
- return LLDB_INVALID_OFFSET;
- }
-
- // DW_OP_WASM_location WASM_GLOBAL:0x03 index:u32
- // Called with "arguments" 0x03 and 0x04
- // Location type:
- if (data.GetU8(&offset) != /* global */ 0x03) {
- return LLDB_INVALID_OFFSET;
- }
-
- // Index
- if (data.GetU32(&offset) != 0x04) {
- return LLDB_INVALID_OFFSET;
- }
-
- // Report the skipped distance:
- return offset - data_offset;
- }
-
- bool
- ParseVendorDWARFOpcode(uint8_t op, const lldb_private::DataExtractor &opcodes,
- lldb::offset_t &offset,
- std::vector<lldb_private::Value> &stack) const final {
- if (op != DW_OP_WASM_location) {
- return false;
- }
-
- // DW_OP_WASM_location WASM_GLOBAL:0x03 index:u32
- // Called with "arguments" 0x03 and 0x04
- // Location type:
- if (opcodes.GetU8(&offset) != /* global */ 0x03) {
- return false;
- }
-
- // Index:
- if (opcodes.GetU32(&offset) != 0x04) {
- return false;
- }
-
- // Return some value:
- stack.push_back({GetScalar(32, 42, false)});
- return true;
+ return new CustomSymbolFileDWARF(std::move(objfile_sp), nullptr);
}
};
char CustomSymbolFileDWARF::ID;
-static auto testExpressionVendorExtensions(lldb::ModuleSP module_sp,
- DWARFUnit &dwarf_unit) {
- // Test that expression extensions can be evaluated, for example
- // DW_OP_WASM_location which is not currently handled by DWARFExpression:
- EXPECT_THAT_EXPECTED(Evaluate({DW_OP_WASM_location, 0x03, // WASM_GLOBAL:0x03
- 0x04, 0x00, 0x00, // index:u32
- 0x00, DW_OP_stack_value},
- module_sp, &dwarf_unit),
- llvm::HasValue(GetScalar(32, 42, false)));
-
- // Test that searches for opcodes work in the presence of extensions:
- uint8_t expr[] = {DW_OP_WASM_location, 0x03, 0x04, 0x00, 0x00, 0x00,
- DW_OP_form_tls_address};
- DataExtractor extractor(expr, sizeof(expr), lldb::eByteOrderLittle,
- /*addr_size*/ 4);
- DWARFExpression dwarf_expr(extractor);
- ASSERT_TRUE(dwarf_expr.ContainsThreadLocalStorage(&dwarf_unit));
-}
-
TEST(DWARFExpression, Extensions) {
const char *yamldata = R"(
--- !ELF
@@ -768,3 +705,424 @@ TEST(DWARFExpression, ExtensionsDWO) {
testExpressionVendorExtensions(dwo_module_sp, *dwo_dwarf_unit);
}
+*/
+namespace {
+class MockThread : public Thread {
+public:
+ MockThread(Process &process) : Thread(process, 1 /* tid */), m_reg_ctx_sp() {}
+ ~MockThread() override { DestroyThread(); }
+
+ void RefreshStateAfterStop() override {}
+ lldb::RegisterContextSP GetRegisterContext() override { return m_reg_ctx_sp; }
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame(StackFrame *frame) override {
+ return m_reg_ctx_sp;
+ }
+ bool CalculateStopInfo() override { return false; }
+
+ void SetRegisterContext(lldb::RegisterContextSP reg_ctx_sp) {
+ m_reg_ctx_sp = reg_ctx_sp;
+ }
+
+private:
+ lldb::RegisterContextSP m_reg_ctx_sp;
+};
+
+class MockRegisterContext : public RegisterContext {
+public:
+ MockRegisterContext(Thread &thread, const RegisterValue ®_value)
+ : RegisterContext(thread, 0 /*concrete_frame_idx*/),
+ m_reg_value(reg_value) {}
+
+ void InvalidateAllRegisters() override {}
+ size_t GetRegisterCount() override { return 0; }
+ const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override {
+ if (reg == 0x4000002a) {
+ return &m_reg_info;
+ }
+ return &m_reg_info; /* nullptr; */
+ }
+ size_t GetRegisterSetCount() override { return 0; }
+ const RegisterSet *GetRegisterSet(size_t reg_set) override { return nullptr; }
+ lldb::ByteOrder GetByteOrder() override {
+ return lldb::ByteOrder::eByteOrderLittle;
+ }
+ bool ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue ®_value) override {
+ reg_value = m_reg_value;
+ return true;
+ }
+ bool WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue ®_value) override {
+ return false;
+ }
+ uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
+ uint32_t num) override {
+ return num;
+ }
+
+private:
+ RegisterInfo m_reg_info;
+ RegisterValue m_reg_value;
+};
+
+static auto testExpressionVendorExtensions(lldb::ModuleSP module_sp,
+ DWARFUnit &dwarf_unit,
+ RegisterContext *reg_ctx) {
+ // Test that expression extensions can be evaluated, for example
+ // DW_OP_WASM_location which is not currently handled by DWARFExpression:
+ EXPECT_THAT_EXPECTED(Evaluate({DW_OP_WASM_location, 0x03, // WASM_GLOBAL:0x03
+ 0x04, 0x00, 0x00, // index:u32
+ 0x00, DW_OP_stack_value},
+ module_sp, &dwarf_unit, nullptr, reg_ctx),
+ llvm::HasValue(GetScalar(32, 42, false)));
+
+ // Test that searches for opcodes work in the presence of extensions:
+ uint8_t expr[] = {DW_OP_WASM_location, 0x03, 0x04, 0x00, 0x00, 0x00,
+ DW_OP_form_tls_address};
+ DataExtractor extractor(expr, sizeof(expr), lldb::eByteOrderLittle,
+ /*addr_size*/ 4);
+ DWARFExpression dwarf_expr(extractor);
+ ASSERT_TRUE(dwarf_expr.ContainsThreadLocalStorage(&dwarf_unit));
+}
+} // namespace;
+
+TEST(DWARFExpression, Extensions) {
+ const char *yamldata = R"(
+--- !WASM
+FileHeader:
+ Version: 0x1
+Sections:
+ - Type: TYPE
+ Signatures:
+ - Index: 0
+ ParamTypes:
+ - I32
+ ReturnTypes:
+ - I32
+ - Type: FUNCTION
+ FunctionTypes: [ 0 ]
+ - Type: TABLE
+ Tables:
+ - Index: 0
+ ElemType: FUNCREF
+ Limits:
+ Flags: [ HAS_MAX ]
+ Minimum: 0x1
+ Maximum: 0x1
+ - Type: MEMORY
+ Memories:
+ - Flags: [ HAS_MAX ]
+ Minimum: 0x100
+ Maximum: 0x100
+ - Type: GLOBAL
+ Globals:
+ - Index: 0
+ Type: I32
+ Mutable: true
+ InitExpr:
+ Opcode: I32_CONST
+ Value: 65536
+ - Type: EXPORT
+ Exports:
+ - Name: memory
+ Kind: MEMORY
+ Index: 0
+ - Name: square
+ Kind: FUNCTION
+ Index: 0
+ - Name: __indirect_function_table
+ Kind: TABLE
+ Index: 0
+ - Type: CODE
+ Functions:
+ - Index: 0
+ Locals:
+ - Type: I32
+ Count: 1
+ - Type: I32
+ Count: 1
+ - Type: I32
+ Count: 1
+ - Type: I32
+ Count: 1
+ - Type: I32
+ Count: 1
+ - Type: I32
+ Count: 1
+ Body: 2300210141102102200120026B21032003200036020C200328020C2104200328020C2105200420056C210620060F0B
+ - Type: CUSTOM
+ Name: name
+ FunctionNames:
+ - Index: 0
+ Name: square
+ GlobalNames:
+ - Index: 0
+ Name: __stack_pointer
+ - Type: CUSTOM
+ Name: .debug_abbrev
+ Payload: 011101250E1305030E10171B0E110112060000022E01110112064018030E3A0B3B0B271949133F1900000305000218030E3A0B3B0B49130000042400030E3E0B0B0B000000
+ - Type: CUSTOM
+ Name: .debug_info
+ Payload: 510000000400000000000401670000001D005E000000000000000A000000020000003C00000002020000003C00000004ED00039F5700000001014D0000000302910C0400000001014D000000000400000000050400
+ - Type: CUSTOM
+ Name: .debug_str
+ Payload: 696E740076616C756500513A5C70616F6C6F7365764D5346545C6C6C766D2D70726F6A6563745C6C6C64625C746573745C4150495C66756E6374696F6E616C69746965735C6764625F72656D6F74655F636C69656E745C737175617265007371756172652E6300636C616E672076657273696F6E2031382E302E30202868747470733A2F2F6769746875622E636F6D2F6C6C766D2F6C6C766D2D70726F6A65637420373535303166353336323464653932616166636532663164613639386232343961373239336463372900
+ - Type: CUSTOM
+ Name: .debug_line
+ Payload: 64000000040020000000010101FB0E0D000101010100000001000001007371756172652E6300000000000005020200000001000502250000000301050A0A010005022C00000005120601000502330000000510010005023A0000000503010005023E000000000101
+)";
+
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> mem_fs =
+ new llvm::vfs::InMemoryFileSystem();
+ FileSystem::Initialize(mem_fs);
+ {
+ SubsystemRAII<HostInfo, ObjectFileWasm, SymbolVendorWasm> subsystems;
+
+ // Set up a wasm target
+ ArchSpec arch("wasm32-unknown-unknown-wasm");
+ lldb::PlatformSP host_platform_sp =
+ platform_linux::PlatformLinux::CreateInstance(true, &arch);
+ ASSERT_TRUE(host_platform_sp);
+ Platform::SetHostPlatform(host_platform_sp);
+ lldb::DebuggerSP debugger_sp = Debugger::CreateInstance();
+ ASSERT_TRUE(debugger_sp);
+ lldb::TargetSP target_sp;
+ lldb::PlatformSP platform_sp;
+ debugger_sp->GetTargetList().CreateTarget(*debugger_sp, "", arch,
+ lldb_private::eLoadDependentsNo,
+ platform_sp, target_sp);
+ // Set up a mock process and thread.
+ lldb::ListenerSP listener_sp(Listener::MakeListener("dummy"));
+ lldb::ProcessSP process_sp =
+ std::make_shared<MockProcess>(target_sp, listener_sp);
+ ASSERT_TRUE(process_sp);
+ MockThread thread(*process_sp);
+ const uint32_t kExpectedValue = 42;
+ lldb::RegisterContextSP reg_ctx_sp = std::make_shared<MockRegisterContext>(
+ thread, RegisterValue(kExpectedValue));
+ thread.SetRegisterContext(reg_ctx_sp);
+
+ llvm::Expected<TestFile> file = TestFile::fromYaml(yamldata);
+ EXPECT_THAT_EXPECTED(file, llvm::Succeeded());
+ auto module_sp = std::make_shared<Module>(file->moduleSpec());
+ auto obj_file_sp = module_sp->GetObjectFile()->shared_from_this();
+ SymbolFileWasm sym_file_wasm(obj_file_sp, nullptr);
+ auto *dwarf_unit = sym_file_wasm.DebugInfo().GetUnitAtIndex(0);
+
+ testExpressionVendorExtensions(module_sp, *dwarf_unit, reg_ctx_sp.get());
+ }
+ FileSystem::Terminate();
+}
+
+TEST(DWARFExpression, ExtensionsSplitSymbols) {
+ const char *skeleton_yamldata = R"(
+--- !WASM
+FileHeader:
+ Version: 0x1
+Sections:
+ - Type: TYPE
+ Signatures:
+ - Index: 0
+ ParamTypes:
+ - I32
+ ReturnTypes:
+ - I32
+ - Type: FUNCTION
+ FunctionTypes: [ 0 ]
+ - Type: TABLE
+ Tables:
+ - Index: 0
+ ElemType: FUNCREF
+ Limits:
+ Flags: [ HAS_MAX ]
+ Minimum: 0x1
+ Maximum: 0x1
+ - Type: MEMORY
+ Memories:
+ - Flags: [ HAS_MAX ]
+ Minimum: 0x100
+ Maximum: 0x100
+ - Type: GLOBAL
+ Globals:
+ - Index: 0
+ Type: I32
+ Mutable: true
+ InitExpr:
+ Opcode: I32_CONST
+ Value: 65536
+ - Type: EXPORT
+ Exports:
+ - Name: memory
+ Kind: MEMORY
+ Index: 0
+ - Name: square
+ Kind: FUNCTION
+ Index: 0
+ - Name: __indirect_function_table
+ Kind: TABLE
+ Index: 0
+ - Type: CODE
+ Functions:
+ - Index: 0
+ Locals:
+ - Type: I32
+ Count: 1
+ - Type: I32
+ Count: 1
+ - Type: I32
+ Count: 1
+ - Type: I32
+ Count: 1
+ - Type: I32
+ Count: 1
+ - Type: I32
+ Count: 1
+ Body: 2300210141102102200120026B21032003200036020C200328020C2104200328020C2105200420056C210620060F0B
+ - Type: CUSTOM
+ Name: name
+ FunctionNames:
+ - Index: 0
+ Name: square
+ GlobalNames:
+ - Index: 0
+ Name: __stack_pointer
+ - Type: CUSTOM
+ Name: external_debug_info
+ Payload: 167371756172652E7761736D2E64656275672E7761736D
+)";
+
+ const char *sym_yamldata = R"(
+--- !WASM
+FileHeader:
+ Version: 0x1
+Sections:
+ - Type: TYPE
+ Signatures:
+ - Index: 0
+ ParamTypes:
+ - I32
+ ReturnTypes:
+ - I32
+ - Type: FUNCTION
+ FunctionTypes: [ 0 ]
+ - Type: TABLE
+ Tables:
+ - Index: 0
+ ElemType: FUNCREF
+ Limits:
+ Flags: [ HAS_MAX ]
+ Minimum: 0x1
+ Maximum: 0x1
+ - Type: MEMORY
+ Memories:
+ - Flags: [ HAS_MAX ]
+ Minimum: 0x100
+ Maximum: 0x100
+ - Type: GLOBAL
+ Globals:
+ - Index: 0
+ Type: I32
+ Mutable: true
+ InitExpr:
+ Opcode: I32_CONST
+ Value: 65536
+ - Type: EXPORT
+ Exports:
+ - Name: memory
+ Kind: MEMORY
+ Index: 0
+ - Name: square
+ Kind: FUNCTION
+ Index: 0
+ - Name: __indirect_function_table
+ Kind: TABLE
+ Index: 0
+ - Type: CODE
+ Functions:
+ - Index: 0
+ Locals:
+ - Type: I32
+ Count: 1
+ - Type: I32
+ Count: 1
+ - Type: I32
+ Count: 1
+ - Type: I32
+ Count: 1
+ - Type: I32
+ Count: 1
+ - Type: I32
+ Count: 1
+ Body: 2300210141102102200120026B21032003200036020C200328020C2104200328020C2105200420056C210620060F0B
+ - Type: CUSTOM
+ Name: name
+ FunctionNames:
+ - Index: 0
+ Name: square
+ GlobalNames:
+ - Index: 0
+ Name: __stack_pointer
+ - Type: CUSTOM
+ Name: .debug_abbrev
+ Payload: 011101250E1305030E10171B0E110112060000022E01110112064018030E3A0B3B0B271949133F1900000305000218030E3A0B3B0B49130000042400030E3E0B0B0B000000
+ - Type: CUSTOM
+ Name: .debug_info
+ Payload: 510000000400000000000401670000001D005E0000000000000004000000020000003C00000002020000003C00000004ED00039F5700000001014D0000000302910C5100000001014D000000000400000000050400
+ - Type: CUSTOM
+ Name: .debug_str
+ Payload: 696E7400513A5C70616F6C6F7365764D5346545C6C6C766D2D70726F6A6563745C6C6C64625C746573745C4150495C66756E6374696F6E616C69746965735C6764625F72656D6F74655F636C69656E740076616C756500737175617265007371756172652E6300636C616E672076657273696F6E2031382E302E30202868747470733A2F2F6769746875622E636F6D2F6C6C766D2F6C6C766D2D70726F6A65637420373535303166353336323464653932616166636532663164613639386232343961373239336463372900
+ - Type: CUSTOM
+ Name: .debug_line
+ Payload: 64000000040020000000010101FB0E0D000101010100000001000001007371756172652E6300000000000005020200000001000502250000000301050A0A010005022C00000005120601000502330000000510010005023A0000000503010005023E000000000101
+)";
+
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> mem_fs =
+ new llvm::vfs::InMemoryFileSystem();
+ FileSystem::Initialize(mem_fs);
+ {
+ SubsystemRAII<HostInfo, ObjectFileWasm, SymbolVendorWasm> subsystems;
+
+ // Set up a wasm target
+ ArchSpec arch("wasm32-unknown-unknown-wasm");
+ lldb::PlatformSP host_platform_sp =
+ platform_linux::PlatformLinux::CreateInstance(true, &arch);
+ ASSERT_TRUE(host_platform_sp);
+ Platform::SetHostPlatform(host_platform_sp);
+ lldb::DebuggerSP debugger_sp = Debugger::CreateInstance();
+ ASSERT_TRUE(debugger_sp);
+ lldb::TargetSP target_sp;
+ lldb::PlatformSP platform_sp;
+ debugger_sp->GetTargetList().CreateTarget(*debugger_sp, "", arch,
+ lldb_private::eLoadDependentsNo,
+ platform_sp, target_sp);
+ // Set up a mock process and thread.
+ lldb::ListenerSP listener_sp(Listener::MakeListener("dummy"));
+ lldb::ProcessSP process_sp =
+ std::make_shared<MockProcess>(target_sp, listener_sp);
+ ASSERT_TRUE(process_sp);
+ MockThread thread(*process_sp);
+ const uint32_t kExpectedValue = 42;
+ lldb::RegisterContextSP reg_ctx_sp = std::make_shared<MockRegisterContext>(
+ thread, RegisterValue(kExpectedValue));
+ thread.SetRegisterContext(reg_ctx_sp);
+
+ llvm::Expected<TestFile> skeleton_file =
+ TestFile::fromYaml(skeleton_yamldata);
+ EXPECT_THAT_EXPECTED(skeleton_file, llvm::Succeeded());
+ auto skeleton_module_sp =
+ std::make_shared<Module>(skeleton_file->moduleSpec());
+
+ llvm::Expected<TestFile> sym_file = TestFile::fromYaml(sym_yamldata);
+ EXPECT_THAT_EXPECTED(sym_file, llvm::Succeeded());
+ auto sym_module_sp = std::make_shared<Module>(sym_file->moduleSpec());
+
+ auto obj_file_sp = sym_module_sp->GetObjectFile()->shared_from_this();
+ SymbolFileWasm sym_file_wasm(obj_file_sp, nullptr);
+ auto *dwarf_unit = sym_file_wasm.DebugInfo().GetUnitAtIndex(0);
+
+ testExpressionVendorExtensions(sym_module_sp, *dwarf_unit,
+ reg_ctx_sp.get());
+ }
+ FileSystem::Terminate();
+}
More information about the lldb-commits
mailing list