https://github.com/Rajveer100 updated https://github.com/llvm/llvm-project/pull/205532
>From a7a0a38ac15ac798a80002276a1ed671bf079513 Mon Sep 17 00:00:00 2001 From: Rajveer <[email protected]> Date: Wed, 24 Jun 2026 16:56:42 +0530 Subject: [PATCH] [lldb] DWARF expression evaluator to test unified stack semantics Part of #181509 This evaluator uses a unified stack for expressions as a DWARF6Value/DWARF6Location and appropriately pushes/pops from stacks depending on the context of the stack frame for various operations like `DW_OP_deref`, `DW_OP_plus` and more. --- lldb/source/Commands/CMakeLists.txt | 1 + .../Commands/CommandObjectDWARFExpression.cpp | 130 ++++++++++++++++++ .../Commands/CommandObjectDWARFExpression.h | 8 ++ 3 files changed, 139 insertions(+) create mode 100644 lldb/source/Commands/CommandObjectDWARFExpression.cpp create mode 100644 lldb/source/Commands/CommandObjectDWARFExpression.h diff --git a/lldb/source/Commands/CMakeLists.txt b/lldb/source/Commands/CMakeLists.txt index f2e62243e999e..c4f2a842a0fda 100644 --- a/lldb/source/Commands/CMakeLists.txt +++ b/lldb/source/Commands/CMakeLists.txt @@ -10,6 +10,7 @@ add_lldb_library(lldbCommands NO_PLUGIN_DEPENDENCIES CommandObjectCommands.cpp CommandObjectDiagnostics.cpp CommandObjectDisassemble.cpp + CommandobjectDWARFExpression.cpp CommandObjectDWIMPrint.cpp CommandObjectExpression.cpp CommandObjectFrame.cpp diff --git a/lldb/source/Commands/CommandObjectDWARFExpression.cpp b/lldb/source/Commands/CommandObjectDWARFExpression.cpp new file mode 100644 index 0000000000000..46a0229e9201a --- /dev/null +++ b/lldb/source/Commands/CommandObjectDWARFExpression.cpp @@ -0,0 +1,130 @@ +//===-- CommandObjectDWARFExpression.cpp +//-----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/Status.h" +#include "lldb/lldb-private-types.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include <variant> + +namespace lldb_private { + +struct DWARF6Value { + uint64_t IntegerLiteral; +}; + +struct DWARF6Location { + enum Kind { MemoryAddress, Register } Type; + uint64_t Payload; +}; + +using StackItem = std::variant<DWARF6Value, DWARF6Location>; + +class DWARF6Evaluator { +public: + std::vector<StackItem> Stack; + + Status Run(const std::vector<uint8_t> &opcodes, ExecutionContext &exe_ctx) { + size_t pc = 0; + RegisterContext *reg_ctx = exe_ctx.GetRegisterContext(); + + while (pc < opcodes.size()) { + uint8_t op = opcodes[pc++]; + switch (op) { + case llvm::dwarf::DW_OP_lit0: + case llvm::dwarf::DW_OP_lit1: + case llvm::dwarf::DW_OP_lit2: + case llvm::dwarf::DW_OP_lit3: + case llvm::dwarf::DW_OP_lit4: { + Stack.push_back( + DWARF6Value{static_cast<uint64_t>(op - llvm::dwarf::DW_OP_lit0)}); + break; + } + + case llvm::dwarf::DW_OP_reg0: { + Stack.push_back(DWARF6Location{DWARF6Location::Register, 0}); + break; + } + + case llvm::dwarf::DW_OP_deref: { + if (Stack.empty()) + return Status::FromErrorString("Stack underflow on DW_OP_deref"); + + StackItem top = Stack.back(); + Stack.pop_back(); + + if (std::holds_alternative<DWARF6Location>(top)) { + DWARF6Location loc = std::get<DWARF6Location>(top); + if (loc.Type == DWARF6Location::Register) { + if (!reg_ctx) + return Status::FromErrorString("Missing Register Context"); + + const RegisterInfo *reg_info = + reg_ctx->GetRegisterInfoAtIndex(loc.Payload); + if (!reg_info) + return Status::FromErrorString("Failed to get Register Info"); + + RegisterValue reg_val; + if (!reg_ctx->ReadRegister(reg_info, reg_val)) + return Status::FromErrorString( + "Failed to read register value from frame"); + + Stack.push_back(DWARF6Value{reg_val.GetAsUInt64()}); + } else if (loc.Type == DWARF6Location::MemoryAddress) { + Process *process = exe_ctx.GetProcessPtr(); + if (!process) + return Status::FromErrorString( + "No active target process context available"); + + uint64_t mem_val = 0; + Status error; + process->ReadMemory(loc.Payload, &mem_val, sizeof(mem_val), error); + + Stack.push_back(DWARF6Value{mem_val}); + } + } else { + return Status::FromErrorString( + "DWARF 6 Type Mismatch: Cannot dereference"); + } + break; + } + + case llvm::dwarf::DW_OP_plus: { + if (Stack.size() < 2) + return Status::FromErrorString("Stack underflow on DW_OP_plus"); + + if (!std::holds_alternative<DWARF6Value>(Stack.back())) + return Status::FromErrorString( + "Right-hand operand must be a Value type"); + auto right = std::get<DWARF6Value>(Stack.back()); + Stack.pop_back(); + + if (!std::holds_alternative<DWARF6Value>(Stack.back())) + return Status::FromErrorString( + "Left-hand operand must be a Value type"); + auto left = std::get<DWARF6Value>(Stack.back()); + Stack.pop_back(); + + Stack.push_back( + DWARF6Value{left.IntegerLiteral + right.IntegerLiteral}); + break; + } + + default: + return Status::FromErrorStringWithFormat( + "Opcode 0x%02X is currently unimplemented", op); + } + } + return Status(); + } +}; +} // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectDWARFExpression.h b/lldb/source/Commands/CommandObjectDWARFExpression.h new file mode 100644 index 0000000000000..d4a348bcda32e --- /dev/null +++ b/lldb/source/Commands/CommandObjectDWARFExpression.h @@ -0,0 +1,8 @@ +//===-- CommandObjectDWARFExpression.h ---------------------------*- C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
