Skip to content

[lldb] Extract DW_OP_deref evaluation code (NFC) #146801

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

Merged
merged 2 commits into from
Jul 3, 2025
Merged
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: 3 additions & 1 deletion lldb/include/lldb/Expression/DWARFExpression.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ namespace lldb_private {
/// location expression or a location list and interprets it.
class DWARFExpression {
public:
using Stack = std::vector<Value>;

class Delegate {
public:
Delegate() = default;
Expand All @@ -53,7 +55,7 @@ class DWARFExpression {
virtual bool ParseVendorDWARFOpcode(uint8_t op,
const DataExtractor &opcodes,
lldb::offset_t &offset,
std::vector<Value> &stack) const = 0;
Stack &stack) const = 0;

Delegate(const Delegate &) = delete;
Delegate &operator=(const Delegate &) = delete;
Expand Down
139 changes: 69 additions & 70 deletions lldb/source/Expression/DWARFExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ bool DWARFExpression::LinkThreadLocalStorage(
return true;
}

static llvm::Error Evaluate_DW_OP_entry_value(std::vector<Value> &stack,
static llvm::Error Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack,
ExecutionContext *exe_ctx,
RegisterContext *reg_ctx,
const DataExtractor &opcodes,
Expand Down Expand Up @@ -654,7 +654,7 @@ static llvm::Error Evaluate_DW_OP_entry_value(std::vector<Value> &stack,
addr_t return_pc = LLDB_INVALID_ADDRESS;
uint32_t current_frame_idx = current_frame->GetFrameIndex();

for (uint32_t parent_frame_idx = current_frame_idx + 1;;parent_frame_idx++) {
for (uint32_t parent_frame_idx = current_frame_idx + 1;; parent_frame_idx++) {
parent_frame = thread->GetStackFrameAtIndex(parent_frame_idx);
// If this is null, we're at the end of the stack.
if (!parent_frame)
Expand Down Expand Up @@ -860,6 +860,66 @@ ResolveLoadAddress(ExecutionContext *exe_ctx, lldb::ModuleSP &module_sp,
return load_addr;
}

static llvm::Error Evaluate_DW_OP_deref(DWARFExpression::Stack &stack,
ExecutionContext *exe_ctx,
lldb::ModuleSP module_sp,
Process *process) {
if (stack.empty())
return llvm::createStringError("expression stack empty for DW_OP_deref");

const Value::ValueType value_type = stack.back().GetValueType();
switch (value_type) {
case Value::ValueType::HostAddress: {
void *src = (void *)stack.back().GetScalar().ULongLong();
intptr_t ptr;
::memcpy(&ptr, src, sizeof(void *));
stack.back().GetScalar() = ptr;
stack.back().ClearContext();
} break;
case Value::ValueType::FileAddress: {
auto file_addr = stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
Address so_addr;
auto maybe_load_addr = ResolveLoadAddress(exe_ctx, module_sp, "DW_OP_deref",
file_addr, so_addr);
if (!maybe_load_addr)
return maybe_load_addr.takeError();
stack.back().GetScalar() = *maybe_load_addr;
// Fall through to load address promotion code below.
}
[[fallthrough]];
case Value::ValueType::Scalar:
// Promote Scalar to LoadAddress and fall through.
stack.back().SetValueType(Value::ValueType::LoadAddress);
[[fallthrough]];
case Value::ValueType::LoadAddress: {
if (!exe_ctx)
return llvm::createStringError("NULL execution context for DW_OP_deref");
if (!process)
return llvm::createStringError("NULL process for DW_OP_deref");
lldb::addr_t pointer_addr =
stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
Status error;
lldb::addr_t pointer_value =
process->ReadPointerFromMemory(pointer_addr, error);
if (pointer_value == LLDB_INVALID_ADDRESS)
return llvm::joinErrors(
llvm::createStringError(
"Failed to dereference pointer from 0x%" PRIx64
" for DW_OP_deref",
pointer_addr),
error.takeError());
if (ABISP abi_sp = process->GetABI())
pointer_value = abi_sp->FixCodeAddress(pointer_value);
stack.back().GetScalar() = pointer_value;
stack.back().ClearContext();
} break;
case Value::ValueType::Invalid:
return llvm::createStringError("invalid value type for DW_OP_deref");
}

return llvm::Error::success();
}

/// Helper function to move common code used to load sized data from a uint8_t
/// buffer.
///
Expand Down Expand Up @@ -890,7 +950,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
if (opcodes.GetByteSize() == 0)
return llvm::createStringError(
"no location, value may have been optimized out");
std::vector<Value> stack;

Stack stack;

Process *process = nullptr;
StackFrame *frame = nullptr;
Expand Down Expand Up @@ -1019,69 +1080,9 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// retrieved from the dereferenced address is the size of an address on the
// target machine.
case DW_OP_deref: {
if (stack.empty())
return llvm::createStringError(
"expression stack empty for DW_OP_deref");
Value::ValueType value_type = stack.back().GetValueType();
switch (value_type) {
case Value::ValueType::HostAddress: {
void *src = (void *)stack.back().GetScalar().ULongLong();
intptr_t ptr;
::memcpy(&ptr, src, sizeof(void *));
stack.back().GetScalar() = ptr;
stack.back().ClearContext();
} break;
case Value::ValueType::FileAddress: {
auto file_addr = stack.back().GetScalar().ULongLong(
LLDB_INVALID_ADDRESS);

Address so_addr;
auto maybe_load_addr = ResolveLoadAddress(
exe_ctx, module_sp, "DW_OP_deref", file_addr, so_addr);

if (!maybe_load_addr)
return maybe_load_addr.takeError();

stack.back().GetScalar() = *maybe_load_addr;
// Fall through to load address promotion code below.
}
[[fallthrough]];
case Value::ValueType::Scalar:
// Promote Scalar to LoadAddress and fall through.
stack.back().SetValueType(Value::ValueType::LoadAddress);
[[fallthrough]];
case Value::ValueType::LoadAddress:
if (exe_ctx) {
if (process) {
lldb::addr_t pointer_addr =
stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
Status error;
lldb::addr_t pointer_value =
process->ReadPointerFromMemory(pointer_addr, error);
if (pointer_value != LLDB_INVALID_ADDRESS) {
if (ABISP abi_sp = process->GetABI())
pointer_value = abi_sp->FixCodeAddress(pointer_value);
stack.back().GetScalar() = pointer_value;
stack.back().ClearContext();
} else {
return llvm::createStringError(
"Failed to dereference pointer from 0x%" PRIx64
" for DW_OP_deref: %s\n",
pointer_addr, error.AsCString());
}
} else {
return llvm::createStringError("NULL process for DW_OP_deref");
}
} else {
return llvm::createStringError(
"NULL execution context for DW_OP_deref");
}
break;

case Value::ValueType::Invalid:
return llvm::createStringError("invalid value type for DW_OP_deref");
}

if (llvm::Error err =
Evaluate_DW_OP_deref(stack, exe_ctx, module_sp, process))
return err;
} break;

// OPCODE: DW_OP_deref_size
Expand Down Expand Up @@ -1966,8 +1967,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
case Value::ValueType::Scalar: {
uint32_t bit_size = piece_byte_size * 8;
uint32_t bit_offset = 0;
if (!scalar.ExtractBitfield(
bit_size, bit_offset)) {
if (!scalar.ExtractBitfield(bit_size, bit_offset)) {
return llvm::createStringError(
"unable to extract %" PRIu64 " bytes from a %" PRIu64
" byte scalar value.",
Expand Down Expand Up @@ -2409,8 +2409,7 @@ bool DWARFExpression::MatchesOperand(
return MatchUnaryOp(
MatchOpType(Instruction::Operand::Type::Dereference),
MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum),
MatchRegOp(*reg),
MatchImmOp(offset)))(operand);
MatchRegOp(*reg), MatchImmOp(offset)))(operand);
} else {
return MatchRegOp(*reg)(operand);
}
Expand Down
Loading