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
2 changes: 0 additions & 2 deletions lldb/source/Expression/DWARFExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -909,8 +909,6 @@ static llvm::Error Evaluate_DW_OP_deref(DWARFExpression::Stack &stack,
" 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;
Expand Down
4 changes: 4 additions & 0 deletions lldb/unittests/Expression/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@ add_lldb_unittest(ExpressionTests
CppModuleConfigurationTest.cpp
ExpressionTest.cpp

LINK_COMPONENTS
AArch64
Support
LINK_LIBS
lldbCore
lldbPluginObjectFileELF
lldbPluginObjectFileWasm
lldbPluginSymbolVendorWasm
lldbPluginPlatformLinux
lldbPluginABIAArch64
lldbPluginExpressionParserClang
lldbPluginTypeSystemClang
lldbUtility
Expand Down
100 changes: 100 additions & 0 deletions lldb/unittests/Expression/DWARFExpressionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "lldb/Expression/DWARFExpression.h"
#include "Plugins/ABI/AArch64/ABISysV_arm64.h"
#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h"
#include "Plugins/Platform/Linux/PlatformLinux.h"
#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
Expand All @@ -21,10 +22,12 @@
#include "lldb/Core/dwarf.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"

Expand Down Expand Up @@ -190,15 +193,39 @@ class DWARFExpressionMockProcessTest : public ::testing::Test {
void SetUp() override {
FileSystem::Initialize();
HostInfo::Initialize();
LLVMInitializeAArch64TargetInfo();
LLVMInitializeAArch64TargetMC();
platform_linux::PlatformLinux::Initialize();
ABISysV_arm64::Initialize();
}
void TearDown() override {
platform_linux::PlatformLinux::Terminate();
HostInfo::Terminate();
FileSystem::Terminate();
ABISysV_arm64::Terminate();
}
};

struct PlatformTargetDebugger {
lldb::PlatformSP platform_sp;
lldb::TargetSP target_sp;
lldb::DebuggerSP debugger_sp;
};

/// A helper function to create <Platform, Target, Debugger> objects with the
/// "aarch64-pc-linux" ArchSpec.
static PlatformTargetDebugger CreateTarget() {
ArchSpec arch("aarch64-pc-linux");
Platform::SetHostPlatform(
platform_linux::PlatformLinux::CreateInstance(true, &arch));
lldb::PlatformSP platform_sp;
lldb::TargetSP target_sp;
lldb::DebuggerSP debugger_sp = Debugger::CreateInstance();
debugger_sp->GetTargetList().CreateTarget(
*debugger_sp, "", arch, eLoadDependentsNo, platform_sp, target_sp);
return PlatformTargetDebugger{platform_sp, target_sp, debugger_sp};
}

// NB: This class doesn't use the override keyword to avoid
// -Winconsistent-missing-override warnings from the compiler. The
// inconsistency comes from the overriding definitions in the MOCK_*** macros.
Expand Down Expand Up @@ -1135,3 +1162,76 @@ TEST_F(DWARFExpressionMockProcessTest, DW_OP_piece_file_addr) {
ASSERT_EQ(result->GetValueType(), Value::ValueType::HostAddress);
ASSERT_THAT(result->GetBuffer().GetData(), ElementsAre(0x11, 0x22));
}

/// A Process whose `ReadMemory` override queries a DenseMap.
struct MockProcessWithMemRead : Process {
using addr_t = lldb::addr_t;

llvm::DenseMap<addr_t, addr_t> memory_map;

MockProcessWithMemRead(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
llvm::DenseMap<addr_t, addr_t> &&memory_map)
: Process(target_sp, listener_sp), memory_map(memory_map) {}
size_t DoReadMemory(addr_t vm_addr, void *buf, size_t size,
Status &error) override {
assert(memory_map.contains(vm_addr));
assert(size == sizeof(addr_t));
*reinterpret_cast<addr_t *>(buf) = memory_map[vm_addr];
return sizeof(addr_t);
}
size_t ReadMemory(addr_t addr, void *buf, size_t size,
Status &status) override {
return DoReadMemory(addr, buf, size, status);
}
bool CanDebug(lldb::TargetSP, bool) override { return true; }
Status DoDestroy() override { return Status(); }
llvm::StringRef GetPluginName() override { return ""; }
void RefreshStateAfterStop() override {}
bool DoUpdateThreadList(ThreadList &, ThreadList &) override { return false; }
};

/// Sets the value of register x22 to "42".
/// Creates a process whose memory address 42 contains the value
/// memory[42] = ((0xffULL) << 56) | 0xabcdef;
/// The expression DW_OP_breg22, 0, DW_OP_deref should produce that same value,
/// without clearing the top byte 0xff.
TEST_F(DWARFExpressionMockProcessTest, DW_op_deref_no_ptr_fixing) {
llvm::DenseMap<lldb::addr_t, lldb::addr_t> memory;
constexpr lldb::addr_t expected_value = ((0xffULL) << 56) | 0xabcdefULL;
memory[42] = expected_value;

PlatformTargetDebugger test_setup = CreateTarget();
lldb::ProcessSP process_sp = std::make_shared<MockProcessWithMemRead>(
test_setup.target_sp, Listener::MakeListener("dummy"), std::move(memory));
auto thread = std::make_shared<MockThread>(*process_sp);
lldb::RegisterContextSP reg_ctx_sp =
std::make_shared<MockRegisterContext>(*thread, RegisterValue(42ull));
thread->SetRegisterContext(reg_ctx_sp);
process_sp->GetThreadList().AddThread(thread);

auto evaluate_expr = [&](auto &expr_data) {
DataExtractor extractor(expr_data, sizeof(expr_data),
lldb::eByteOrderLittle,
/*addr_size*/ 8);
DWARFExpression expr(extractor);

ExecutionContext exe_ctx(process_sp);
llvm::Expected<Value> result = DWARFExpression::Evaluate(
&exe_ctx, reg_ctx_sp.get(), /*module_sp*/ nullptr, extractor,
/*unit*/ nullptr, lldb::eRegisterKindLLDB,
/*initial_value_ptr=*/nullptr,
/*object_address_ptr=*/nullptr);
return result;
};

uint8_t expr_reg[] = {DW_OP_breg22, 0};
llvm::Expected<Value> result_reg = evaluate_expr(expr_reg);
ASSERT_THAT_EXPECTED(result_reg, llvm::Succeeded());
ASSERT_EQ(result_reg->GetValueType(), Value::ValueType::LoadAddress);
ASSERT_EQ(result_reg->GetScalar().ULongLong(), 42ull);

uint8_t expr_deref[] = {DW_OP_breg22, 0, DW_OP_deref};
llvm::Expected<Value> result_deref = evaluate_expr(expr_deref);
ASSERT_THAT_EXPECTED(result_deref, llvm::Succeeded());
ASSERT_EQ(result_deref->GetScalar().ULongLong(), expected_value);
}
Loading