Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
137 changes: 67 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,64 @@ 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::createStringError(
"Failed to dereference pointer from 0x%" PRIx64
" for DW_OP_deref: %s\n",
pointer_addr, error.AsCString());
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 +948,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 +1078,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 +1965,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 +2407,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