Skip to content

Commit 1995fd9

Browse files
authored
[lldb] Extract DW_OP_deref evaluation code (NFC) (#146801)
The DWARF expression evaluator is essentially a large state machine implemented as a switch statement. For anything but trivial operations, having the evaluation logic implemented inline is difficult to follow, especially when there are nested switches. This commit moves evaluation of `DW_OP_deref` out-of-line, similar to `Evaluate_DW_OP_entry_value`.
1 parent 2aa0f0a commit 1995fd9

File tree

2 files changed

+72
-71
lines changed

2 files changed

+72
-71
lines changed

lldb/include/lldb/Expression/DWARFExpression.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ namespace lldb_private {
3535
/// location expression or a location list and interprets it.
3636
class DWARFExpression {
3737
public:
38+
using Stack = std::vector<Value>;
39+
3840
class Delegate {
3941
public:
4042
Delegate() = default;
@@ -53,7 +55,7 @@ class DWARFExpression {
5355
virtual bool ParseVendorDWARFOpcode(uint8_t op,
5456
const DataExtractor &opcodes,
5557
lldb::offset_t &offset,
56-
std::vector<Value> &stack) const = 0;
58+
Stack &stack) const = 0;
5759

5860
Delegate(const Delegate &) = delete;
5961
Delegate &operator=(const Delegate &) = delete;

lldb/source/Expression/DWARFExpression.cpp

Lines changed: 69 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ bool DWARFExpression::LinkThreadLocalStorage(
589589
return true;
590590
}
591591

592-
static llvm::Error Evaluate_DW_OP_entry_value(std::vector<Value> &stack,
592+
static llvm::Error Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack,
593593
ExecutionContext *exe_ctx,
594594
RegisterContext *reg_ctx,
595595
const DataExtractor &opcodes,
@@ -654,7 +654,7 @@ static llvm::Error Evaluate_DW_OP_entry_value(std::vector<Value> &stack,
654654
addr_t return_pc = LLDB_INVALID_ADDRESS;
655655
uint32_t current_frame_idx = current_frame->GetFrameIndex();
656656

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

863+
static llvm::Error Evaluate_DW_OP_deref(DWARFExpression::Stack &stack,
864+
ExecutionContext *exe_ctx,
865+
lldb::ModuleSP module_sp,
866+
Process *process) {
867+
if (stack.empty())
868+
return llvm::createStringError("expression stack empty for DW_OP_deref");
869+
870+
const Value::ValueType value_type = stack.back().GetValueType();
871+
switch (value_type) {
872+
case Value::ValueType::HostAddress: {
873+
void *src = (void *)stack.back().GetScalar().ULongLong();
874+
intptr_t ptr;
875+
::memcpy(&ptr, src, sizeof(void *));
876+
stack.back().GetScalar() = ptr;
877+
stack.back().ClearContext();
878+
} break;
879+
case Value::ValueType::FileAddress: {
880+
auto file_addr = stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
881+
Address so_addr;
882+
auto maybe_load_addr = ResolveLoadAddress(exe_ctx, module_sp, "DW_OP_deref",
883+
file_addr, so_addr);
884+
if (!maybe_load_addr)
885+
return maybe_load_addr.takeError();
886+
stack.back().GetScalar() = *maybe_load_addr;
887+
// Fall through to load address promotion code below.
888+
}
889+
[[fallthrough]];
890+
case Value::ValueType::Scalar:
891+
// Promote Scalar to LoadAddress and fall through.
892+
stack.back().SetValueType(Value::ValueType::LoadAddress);
893+
[[fallthrough]];
894+
case Value::ValueType::LoadAddress: {
895+
if (!exe_ctx)
896+
return llvm::createStringError("NULL execution context for DW_OP_deref");
897+
if (!process)
898+
return llvm::createStringError("NULL process for DW_OP_deref");
899+
lldb::addr_t pointer_addr =
900+
stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
901+
Status error;
902+
lldb::addr_t pointer_value =
903+
process->ReadPointerFromMemory(pointer_addr, error);
904+
if (pointer_value == LLDB_INVALID_ADDRESS)
905+
return llvm::joinErrors(
906+
llvm::createStringError(
907+
"Failed to dereference pointer from 0x%" PRIx64
908+
" for DW_OP_deref",
909+
pointer_addr),
910+
error.takeError());
911+
if (ABISP abi_sp = process->GetABI())
912+
pointer_value = abi_sp->FixCodeAddress(pointer_value);
913+
stack.back().GetScalar() = pointer_value;
914+
stack.back().ClearContext();
915+
} break;
916+
case Value::ValueType::Invalid:
917+
return llvm::createStringError("invalid value type for DW_OP_deref");
918+
}
919+
920+
return llvm::Error::success();
921+
}
922+
863923
/// Helper function to move common code used to load sized data from a uint8_t
864924
/// buffer.
865925
///
@@ -890,7 +950,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
890950
if (opcodes.GetByteSize() == 0)
891951
return llvm::createStringError(
892952
"no location, value may have been optimized out");
893-
std::vector<Value> stack;
953+
954+
Stack stack;
894955

895956
Process *process = nullptr;
896957
StackFrame *frame = nullptr;
@@ -1019,69 +1080,9 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
10191080
// retrieved from the dereferenced address is the size of an address on the
10201081
// target machine.
10211082
case DW_OP_deref: {
1022-
if (stack.empty())
1023-
return llvm::createStringError(
1024-
"expression stack empty for DW_OP_deref");
1025-
Value::ValueType value_type = stack.back().GetValueType();
1026-
switch (value_type) {
1027-
case Value::ValueType::HostAddress: {
1028-
void *src = (void *)stack.back().GetScalar().ULongLong();
1029-
intptr_t ptr;
1030-
::memcpy(&ptr, src, sizeof(void *));
1031-
stack.back().GetScalar() = ptr;
1032-
stack.back().ClearContext();
1033-
} break;
1034-
case Value::ValueType::FileAddress: {
1035-
auto file_addr = stack.back().GetScalar().ULongLong(
1036-
LLDB_INVALID_ADDRESS);
1037-
1038-
Address so_addr;
1039-
auto maybe_load_addr = ResolveLoadAddress(
1040-
exe_ctx, module_sp, "DW_OP_deref", file_addr, so_addr);
1041-
1042-
if (!maybe_load_addr)
1043-
return maybe_load_addr.takeError();
1044-
1045-
stack.back().GetScalar() = *maybe_load_addr;
1046-
// Fall through to load address promotion code below.
1047-
}
1048-
[[fallthrough]];
1049-
case Value::ValueType::Scalar:
1050-
// Promote Scalar to LoadAddress and fall through.
1051-
stack.back().SetValueType(Value::ValueType::LoadAddress);
1052-
[[fallthrough]];
1053-
case Value::ValueType::LoadAddress:
1054-
if (exe_ctx) {
1055-
if (process) {
1056-
lldb::addr_t pointer_addr =
1057-
stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
1058-
Status error;
1059-
lldb::addr_t pointer_value =
1060-
process->ReadPointerFromMemory(pointer_addr, error);
1061-
if (pointer_value != LLDB_INVALID_ADDRESS) {
1062-
if (ABISP abi_sp = process->GetABI())
1063-
pointer_value = abi_sp->FixCodeAddress(pointer_value);
1064-
stack.back().GetScalar() = pointer_value;
1065-
stack.back().ClearContext();
1066-
} else {
1067-
return llvm::createStringError(
1068-
"Failed to dereference pointer from 0x%" PRIx64
1069-
" for DW_OP_deref: %s\n",
1070-
pointer_addr, error.AsCString());
1071-
}
1072-
} else {
1073-
return llvm::createStringError("NULL process for DW_OP_deref");
1074-
}
1075-
} else {
1076-
return llvm::createStringError(
1077-
"NULL execution context for DW_OP_deref");
1078-
}
1079-
break;
1080-
1081-
case Value::ValueType::Invalid:
1082-
return llvm::createStringError("invalid value type for DW_OP_deref");
1083-
}
1084-
1083+
if (llvm::Error err =
1084+
Evaluate_DW_OP_deref(stack, exe_ctx, module_sp, process))
1085+
return err;
10851086
} break;
10861087

10871088
// OPCODE: DW_OP_deref_size
@@ -1966,8 +1967,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
19661967
case Value::ValueType::Scalar: {
19671968
uint32_t bit_size = piece_byte_size * 8;
19681969
uint32_t bit_offset = 0;
1969-
if (!scalar.ExtractBitfield(
1970-
bit_size, bit_offset)) {
1970+
if (!scalar.ExtractBitfield(bit_size, bit_offset)) {
19711971
return llvm::createStringError(
19721972
"unable to extract %" PRIu64 " bytes from a %" PRIu64
19731973
" byte scalar value.",
@@ -2409,8 +2409,7 @@ bool DWARFExpression::MatchesOperand(
24092409
return MatchUnaryOp(
24102410
MatchOpType(Instruction::Operand::Type::Dereference),
24112411
MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum),
2412-
MatchRegOp(*reg),
2413-
MatchImmOp(offset)))(operand);
2412+
MatchRegOp(*reg), MatchImmOp(offset)))(operand);
24142413
} else {
24152414
return MatchRegOp(*reg)(operand);
24162415
}

0 commit comments

Comments
 (0)