Skip to content

[lldb] Support DW_OP_WASM_location in DWARFExpression #78977

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lldb/include/lldb/Expression/DWARFExpression.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ class DWARFExpression {

bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op) const;

static llvm::Error ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
lldb::RegisterKind reg_kind,
uint32_t reg_num, Value &value);

private:
/// A data extractor capable of reading opcode bytes
DataExtractor m_data;
Expand Down
13 changes: 8 additions & 5 deletions lldb/source/Expression/DWARFExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,15 @@ void DWARFExpression::SetRegisterKind(RegisterKind reg_kind) {
m_reg_kind = reg_kind;
}

static llvm::Error ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
lldb::RegisterKind reg_kind,
uint32_t reg_num, Value &value) {
// static
llvm::Error
DWARFExpression::ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
lldb::RegisterKind reg_kind,
uint32_t reg_num, Value &value) {
if (reg_ctx == nullptr)
return llvm::createStringError("no register context in frame");

const uint32_t native_reg =
uint32_t native_reg =
reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
if (native_reg == LLDB_INVALID_REGNUM)
return llvm::createStringError(
Expand Down Expand Up @@ -2250,8 +2252,9 @@ llvm::Expected<Value> DWARFExpression::Evaluate(

default:
if (dwarf_cu) {
Status error_ptr;
if (dwarf_cu->GetSymbolFileDWARF().ParseVendorDWARFOpcode(
op, opcodes, offset, stack)) {
op, reg_ctx, opcodes, reg_kind, offset, stack, &error_ptr)) {
break;
}
}
Expand Down
6 changes: 5 additions & 1 deletion lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
70 changes: 70 additions & 0 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -4446,3 +4450,69 @@ 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 {
if (op != DW_OP_WASM_location) {
return false;
}

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;
llvm::Error error = DWARFExpression::ReadRegisterValueAsScalar(
reg_ctx, reg_kind, reg_num, tmp);
if (error)
return false;

stack.push_back(tmp);
return true;
}
27 changes: 25 additions & 2 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,9 +316,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;
}

Expand Down Expand Up @@ -550,6 +553,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

Expand Down
8 changes: 5 additions & 3 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,11 @@ uint64_t SymbolFileDWARFDwo::GetDebugInfoSize(bool load_all_debug_info) {
}

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() {
Expand Down
8 changes: 5 additions & 3 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF {

uint64_t GetDebugInfoSize(bool load_all_debug_info = false) 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,
Expand Down
2 changes: 2 additions & 0 deletions lldb/unittests/Expression/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ add_lldb_unittest(ExpressionTests
LINK_LIBS
lldbCore
lldbPluginObjectFileELF
lldbPluginObjectFileWasm
lldbPluginSymbolVendorWasm
lldbPluginPlatformLinux
lldbPluginExpressionParserClang
lldbPluginTypeSystemClang
Expand Down
Loading