Skip to content

Commit 1d2007b

Browse files
[lldb] Fix OP_deref evaluation for large integer results (#159460)
When evaluating any DWARF expression that ended in OP_deref and whose previous value on the dwarf stack -- the pointer address for the deref -- was a load address, we were treating the result itself as a pointer, calling Process:FixCodeAddress(result). This is wrong: there's no guarantee that the result is a pointer itself.
1 parent d57aa48 commit 1d2007b

File tree

3 files changed

+105
-2
lines changed

3 files changed

+105
-2
lines changed

lldb/source/Expression/DWARFExpression.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -909,8 +909,6 @@ static llvm::Error Evaluate_DW_OP_deref(DWARFExpression::Stack &stack,
909909
" for DW_OP_deref",
910910
pointer_addr),
911911
error.takeError());
912-
if (ABISP abi_sp = process->GetABI())
913-
pointer_value = abi_sp->FixCodeAddress(pointer_value);
914912
stack.back().GetScalar() = pointer_value;
915913
stack.back().ClearContext();
916914
} break;

lldb/unittests/Expression/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,16 @@ add_lldb_unittest(ExpressionTests
66
CppModuleConfigurationTest.cpp
77
ExpressionTest.cpp
88

9+
LINK_COMPONENTS
10+
AArch64
11+
Support
912
LINK_LIBS
1013
lldbCore
1114
lldbPluginObjectFileELF
1215
lldbPluginObjectFileWasm
1316
lldbPluginSymbolVendorWasm
1417
lldbPluginPlatformLinux
18+
lldbPluginABIAArch64
1519
lldbPluginExpressionParserClang
1620
lldbPluginTypeSystemClang
1721
lldbUtility

lldb/unittests/Expression/DWARFExpressionTest.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "lldb/Expression/DWARFExpression.h"
10+
#include "Plugins/ABI/AArch64/ABISysV_arm64.h"
1011
#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h"
1112
#include "Plugins/Platform/Linux/PlatformLinux.h"
1213
#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
@@ -21,10 +22,12 @@
2122
#include "lldb/Core/dwarf.h"
2223
#include "lldb/Host/HostInfo.h"
2324
#include "lldb/Symbol/ObjectFile.h"
25+
#include "lldb/Target/ABI.h"
2426
#include "lldb/Target/RegisterContext.h"
2527
#include "lldb/Utility/RegisterValue.h"
2628
#include "lldb/Utility/StreamString.h"
2729
#include "llvm/ADT/StringExtras.h"
30+
#include "llvm/Support/TargetSelect.h"
2831
#include "llvm/Testing/Support/Error.h"
2932
#include "gtest/gtest.h"
3033

@@ -190,15 +193,39 @@ class DWARFExpressionMockProcessTest : public ::testing::Test {
190193
void SetUp() override {
191194
FileSystem::Initialize();
192195
HostInfo::Initialize();
196+
LLVMInitializeAArch64TargetInfo();
197+
LLVMInitializeAArch64TargetMC();
193198
platform_linux::PlatformLinux::Initialize();
199+
ABISysV_arm64::Initialize();
194200
}
195201
void TearDown() override {
196202
platform_linux::PlatformLinux::Terminate();
197203
HostInfo::Terminate();
198204
FileSystem::Terminate();
205+
ABISysV_arm64::Terminate();
199206
}
200207
};
201208

209+
struct PlatformTargetDebugger {
210+
lldb::PlatformSP platform_sp;
211+
lldb::TargetSP target_sp;
212+
lldb::DebuggerSP debugger_sp;
213+
};
214+
215+
/// A helper function to create <Platform, Target, Debugger> objects with the
216+
/// "aarch64-pc-linux" ArchSpec.
217+
static PlatformTargetDebugger CreateTarget() {
218+
ArchSpec arch("aarch64-pc-linux");
219+
Platform::SetHostPlatform(
220+
platform_linux::PlatformLinux::CreateInstance(true, &arch));
221+
lldb::PlatformSP platform_sp;
222+
lldb::TargetSP target_sp;
223+
lldb::DebuggerSP debugger_sp = Debugger::CreateInstance();
224+
debugger_sp->GetTargetList().CreateTarget(
225+
*debugger_sp, "", arch, eLoadDependentsNo, platform_sp, target_sp);
226+
return PlatformTargetDebugger{platform_sp, target_sp, debugger_sp};
227+
}
228+
202229
// NB: This class doesn't use the override keyword to avoid
203230
// -Winconsistent-missing-override warnings from the compiler. The
204231
// inconsistency comes from the overriding definitions in the MOCK_*** macros.
@@ -1135,3 +1162,77 @@ TEST_F(DWARFExpressionMockProcessTest, DW_OP_piece_file_addr) {
11351162
ASSERT_EQ(result->GetValueType(), Value::ValueType::HostAddress);
11361163
ASSERT_THAT(result->GetBuffer().GetData(), ElementsAre(0x11, 0x22));
11371164
}
1165+
1166+
/// A Process whose `ReadMemory` override queries a DenseMap.
1167+
struct MockProcessWithMemRead : Process {
1168+
using addr_t = lldb::addr_t;
1169+
1170+
llvm::DenseMap<addr_t, addr_t> memory_map;
1171+
1172+
MockProcessWithMemRead(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
1173+
llvm::DenseMap<addr_t, addr_t> &&memory_map)
1174+
: Process(target_sp, listener_sp), memory_map(memory_map) {}
1175+
size_t DoReadMemory(addr_t vm_addr, void *buf, size_t size,
1176+
Status &error) override {
1177+
assert(memory_map.contains(vm_addr));
1178+
assert(size == sizeof(addr_t));
1179+
*reinterpret_cast<addr_t *>(buf) = memory_map[vm_addr];
1180+
return sizeof(addr_t);
1181+
}
1182+
size_t ReadMemory(addr_t addr, void *buf, size_t size,
1183+
Status &status) override {
1184+
return DoReadMemory(addr, buf, size, status);
1185+
}
1186+
bool CanDebug(lldb::TargetSP, bool) override { return true; }
1187+
Status DoDestroy() override { return Status(); }
1188+
llvm::StringRef GetPluginName() override { return ""; }
1189+
void RefreshStateAfterStop() override {}
1190+
bool DoUpdateThreadList(ThreadList &, ThreadList &) override { return false; }
1191+
};
1192+
1193+
/// Sets the value of register x22 to "42".
1194+
/// Creates a process whose memory address 42 contains the value
1195+
/// memory[42] = ((0xffULL) << 56) | 0xabcdef;
1196+
/// The expression DW_OP_breg22, 0, DW_OP_deref should produce that same value,
1197+
/// without clearing the top byte 0xff.
1198+
TEST_F(DWARFExpressionMockProcessTest, DW_op_deref_no_ptr_fixing) {
1199+
llvm::DenseMap<lldb::addr_t, lldb::addr_t> memory;
1200+
constexpr lldb::addr_t expected_value = ((0xffULL) << 56) | 0xabcdefULL;
1201+
constexpr lldb::addr_t addr = 42;
1202+
memory[addr] = expected_value;
1203+
1204+
PlatformTargetDebugger test_setup = CreateTarget();
1205+
lldb::ProcessSP process_sp = std::make_shared<MockProcessWithMemRead>(
1206+
test_setup.target_sp, Listener::MakeListener("dummy"), std::move(memory));
1207+
auto thread = std::make_shared<MockThread>(*process_sp);
1208+
lldb::RegisterContextSP reg_ctx_sp =
1209+
std::make_shared<MockRegisterContext>(*thread, RegisterValue(addr));
1210+
thread->SetRegisterContext(reg_ctx_sp);
1211+
process_sp->GetThreadList().AddThread(thread);
1212+
1213+
auto evaluate_expr = [&](auto &expr_data) {
1214+
DataExtractor extractor(expr_data, sizeof(expr_data),
1215+
lldb::eByteOrderLittle,
1216+
/*addr_size*/ 8);
1217+
DWARFExpression expr(extractor);
1218+
1219+
ExecutionContext exe_ctx(process_sp);
1220+
llvm::Expected<Value> result = DWARFExpression::Evaluate(
1221+
&exe_ctx, reg_ctx_sp.get(), /*module_sp*/ nullptr, extractor,
1222+
/*unit*/ nullptr, lldb::eRegisterKindLLDB,
1223+
/*initial_value_ptr=*/nullptr,
1224+
/*object_address_ptr=*/nullptr);
1225+
return result;
1226+
};
1227+
1228+
uint8_t expr_reg[] = {DW_OP_breg22, 0};
1229+
llvm::Expected<Value> result_reg = evaluate_expr(expr_reg);
1230+
ASSERT_THAT_EXPECTED(result_reg, llvm::Succeeded());
1231+
ASSERT_EQ(result_reg->GetValueType(), Value::ValueType::LoadAddress);
1232+
ASSERT_EQ(result_reg->GetScalar().ULongLong(), addr);
1233+
1234+
uint8_t expr_deref[] = {DW_OP_breg22, 0, DW_OP_deref};
1235+
llvm::Expected<Value> result_deref = evaluate_expr(expr_deref);
1236+
ASSERT_THAT_EXPECTED(result_deref, llvm::Succeeded());
1237+
ASSERT_EQ(result_deref->GetScalar().ULongLong(), expected_value);
1238+
}

0 commit comments

Comments
 (0)