Index: lldb/source/Expression/DWARFExpression.cpp =================================================================== --- lldb/source/Expression/DWARFExpression.cpp +++ lldb/source/Expression/DWARFExpression.cpp @@ -1067,6 +1067,7 @@ stack.back().SetValueType(Value::ValueType::LoadAddress); // Fall through to load address code below... } LLVM_FALLTHROUGH; + case Value::ValueType::Scalar: case Value::ValueType::LoadAddress: if (exe_ctx) { if (process) { @@ -1099,7 +1100,6 @@ } break; - case Value::ValueType::Scalar: case Value::ValueType::Invalid: if (error_ptr) error_ptr->SetErrorString("Invalid value type for DW_OP_deref.\n"); Index: lldb/unittests/Expression/CMakeLists.txt =================================================================== --- lldb/unittests/Expression/CMakeLists.txt +++ lldb/unittests/Expression/CMakeLists.txt @@ -7,6 +7,8 @@ LINK_LIBS lldbCore + lldbPluginObjectFileELF + lldbPluginPlatformLinux lldbPluginExpressionParserClang lldbPluginTypeSystemClang lldbUtility Index: lldb/unittests/Expression/DWARFExpressionTest.cpp =================================================================== --- lldb/unittests/Expression/DWARFExpressionTest.cpp +++ lldb/unittests/Expression/DWARFExpressionTest.cpp @@ -7,11 +7,15 @@ //===----------------------------------------------------------------------===// #include "lldb/Expression/DWARFExpression.h" +#include "Plugins/Platform/Linux/PlatformLinux.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "TestingSupport/Symbol/YAMLModuleTester.h" #include "lldb/Core/Value.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/dwarf.h" +#include "lldb/Host/HostInfo.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/Reproducer.h" #include "lldb/Utility/StreamString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Testing/Support/Error.h" @@ -21,16 +25,17 @@ static llvm::Expected Evaluate(llvm::ArrayRef expr, lldb::ModuleSP module_sp = {}, - DWARFUnit *unit = nullptr) { + DWARFUnit *unit = nullptr, + ExecutionContext *exe_ctx = nullptr) { DataExtractor extractor(expr.data(), expr.size(), lldb::eByteOrderLittle, /*addr_size*/ 4); Value result; Status status; - if (!DWARFExpression::Evaluate( - /*exe_ctx*/ nullptr, /*reg_ctx*/ nullptr, module_sp, extractor, unit, - lldb::eRegisterKindLLDB, - /*initial_value_ptr*/ nullptr, - /*object_address_ptr*/ nullptr, result, &status)) + if (!DWARFExpression::Evaluate(exe_ctx, /*reg_ctx*/ nullptr, module_sp, + extractor, unit, lldb::eRegisterKindLLDB, + /*initial_value_ptr*/ nullptr, + /*object_address_ptr*/ nullptr, result, + &status)) return status.ToError(); switch (result.GetValueType()) { @@ -66,6 +71,23 @@ return scalar; } +/// This is needed for the tests that use a mock process. +class DWARFExpressionMockProcessTest : public ::testing::Test { +public: + void SetUp() override { + llvm::cantFail(repro::Reproducer::Initialize(repro::ReproducerMode::Off, {})); + FileSystem::Initialize(); + HostInfo::Initialize(); + platform_linux::PlatformLinux::Initialize(); + } + void TearDown() override { + platform_linux::PlatformLinux::Terminate(); + HostInfo::Terminate(); + FileSystem::Terminate(); + repro::Reproducer::Terminate(); + } +}; + TEST(DWARFExpression, DW_OP_pick) { EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit1, DW_OP_lit0, DW_OP_pick, 0}), llvm::HasValue(0)); @@ -277,6 +299,51 @@ "Unhandled opcode DW_OP_unknown_ff in DWARFExpression")); } -TEST(DWARFExpression, DW_OP_deref) { +TEST_F(DWARFExpressionMockProcessTest, DW_OP_deref) { EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit0, DW_OP_deref}), llvm::Failed()); + + struct MockProcess : Process { + using Process::Process; + ConstString GetPluginName() override { return ConstString("mock process"); } + uint32_t GetPluginVersion() override { return 0; } + bool CanDebug(lldb::TargetSP target, + bool plugin_specified_by_name) override { + return false; + }; + Status DoDestroy() override { return {}; } + void RefreshStateAfterStop() override {} + bool DoUpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) override { + return false; + }; + size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, + Status &error) override { + for (size_t i = 0; i < size; ++i) + ((char *)buf)[i] = (vm_addr + i) & 0xff; + error.Clear(); + return size; + } + }; + + // Set up a mock process. + ArchSpec arch("i386-pc-linux"); + Platform::SetHostPlatform( + platform_linux::PlatformLinux::CreateInstance(true, &arch)); + lldb::DebuggerSP debugger_sp = Debugger::CreateInstance(); + ASSERT_TRUE(debugger_sp); + lldb::TargetSP target_sp; + lldb::PlatformSP platform_sp; + debugger_sp->GetTargetList().CreateTarget( + *debugger_sp, "", arch, eLoadDependentsNo, platform_sp, target_sp); + ASSERT_TRUE(target_sp); + ASSERT_TRUE(target_sp->GetArchitecture().IsValid()); + ASSERT_TRUE(platform_sp); + lldb::ListenerSP listener_sp(Listener::MakeListener("dummy")); + lldb::ProcessSP process_sp = + std::make_shared(target_sp, listener_sp); + ASSERT_TRUE(process_sp); + + ExecutionContext exe_ctx(process_sp); + EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit4, DW_OP_deref}, {}, {}, &exe_ctx), + llvm::HasValue(GetScalar(32, 0x07060504, false))); }