brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.1 KiB · 0f3d2d2 Raw
239 lines · cpp
1//===---DynamicValueObjectLocalBuffer.cpp-----------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "Plugins/Platform/Linux/PlatformLinux.h"10#include "Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h"11#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"12#include "TestingSupport/SubsystemRAII.h"13#include "TestingSupport/Symbol/ClangTestUtils.h"14#include "lldb/Core/Debugger.h"15#include "lldb/Core/PluginManager.h"16#include "lldb/Target/Language.h"17#include "lldb/Target/LanguageRuntime.h"18#include "lldb/ValueObject/ValueObject.h"19#include "lldb/ValueObject/ValueObjectConstResult.h"20 21#include "gtest/gtest.h"22 23using namespace lldb;24using namespace lldb_private;25using namespace lldb_private::clang_utils;26 27// This entire class is boilerplate.28struct MockLanguage : public Language {29 30  llvm::StringRef GetPluginName() override { return "MockLanguage"; }31  lldb::LanguageType GetLanguageType() const override {32    return lldb::eLanguageTypeC_plus_plus;33  };34 35  static Language *CreateInstance(lldb::LanguageType language) {36    return new MockLanguage();37  }38  static void Initialize() {39    PluginManager::RegisterPlugin("MockLanguage", "Mock Language",40                                  CreateInstance);41  };42 43  static void Terminate() { PluginManager::UnregisterPlugin(CreateInstance); }44  bool IsSourceFile(llvm::StringRef file_path) const override { return true; }45};46LLDB_PLUGIN_DEFINE(MockLanguage)47 48struct MockLanguageRuntime : public LanguageRuntime {49  // This is the only method in this class that matters for this test.50  // This will unconditionally succeed and return a type with size 4,51  // a value_type of HostAddress, and a local buffer that points to the parent's52  // local buffer.53  // The tests will set that buffer to be either be larger or smaller than the54  // type we're returning.55  bool56  GetDynamicTypeAndAddress(ValueObject &in_value,57                           lldb::DynamicValueType use_dynamic,58                           TypeAndOrName &class_type_or_name, Address &address,59                           Value::ValueType &value_type,60                           llvm::ArrayRef<uint8_t> &local_buffer) override {61    auto ast = in_value.GetCompilerType().GetTypeSystem<TypeSystemClang>();62 63    auto int_type = createRecordWithField(64        *ast, "TypeWitInt", ast->GetBasicType(lldb::BasicType::eBasicTypeInt),65        "theIntField", LanguageType::eLanguageTypeC_plus_plus);66    class_type_or_name.SetCompilerType(int_type);67    local_buffer = in_value.GetLocalBuffer();68    value_type = Value::ValueType::HostAddress;69    return true;70  }71 72  // All of this is boilerplate.73  MockLanguageRuntime(Process *process) : LanguageRuntime(process) {}74  llvm::StringRef GetPluginName() override { return "MockLanguageRuntime"; }75  lldb::LanguageType GetLanguageType() const override {76    return lldb::eLanguageTypeC_plus_plus;77  }78 79  llvm::Error GetObjectDescription(Stream &str, ValueObject &object) override {80    return llvm::Error::success();81  }82 83  llvm::Error GetObjectDescription(Stream &str, Value &value,84                                   ExecutionContextScope *exe_scope) override {85    return llvm::Error::success();86  }87 88  bool CouldHaveDynamicValue(ValueObject &in_value) override { return true; }89 90  TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name,91                                 ValueObject &static_value) override {92    return type_and_or_name;93  }94 95  lldb::BreakpointResolverSP96  CreateExceptionResolver(const lldb::BreakpointSP &bkpt, bool catch_bp,97                          bool throw_bp) override {98    return lldb::BreakpointResolverSP();99  }100 101  lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread,102                                                  bool stop_others) override {103    return {};104  }105 106  static LanguageRuntime *CreateInstance(Process *process,107                                         LanguageType language) {108    return new MockLanguageRuntime(process);109  }110 111  static void Initialize() {112    PluginManager::RegisterPlugin(113        "MockLanguageRuntime", "MockLanguageRuntime", CreateInstance,114        [](CommandInterpreter &interpreter) -> lldb::CommandObjectSP {115          return {};116        },117        [](lldb::LanguageType language,118           bool throw_bp) -> BreakpointPreconditionSP { return {}; });119  }120 121  static void Terminate() { PluginManager::UnregisterPlugin(CreateInstance); }122};123LLDB_PLUGIN_DEFINE(MockLanguageRuntime)124 125// This entire class is boilerplate.126struct MockProcess : Process {127  MockProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp)128      : Process(target_sp, listener_sp) {}129 130  llvm::StringRef GetPluginName() override { return "mock process"; }131 132  bool CanDebug(lldb::TargetSP target, bool plugin_specified_by_name) override {133    return false;134  };135 136  Status DoDestroy() override { return {}; }137 138  void RefreshStateAfterStop() override {}139 140  bool DoUpdateThreadList(ThreadList &old_thread_list,141                          ThreadList &new_thread_list) override {142    return false;143  };144 145  size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,146                      Status &error) override {147    // No need to read memory in these tests.148    return size;149  }150};151 152class DynamicValueObjectLocalBufferTest : public ::testing::Test {153public:154  void SetUp() override {155    ArchSpec arch("i386-pc-linux");156    Platform::SetHostPlatform(157        platform_linux::PlatformLinux::CreateInstance(true, &arch));158    // std::call_once(TestUtilities::g_debugger_initialize_flag,159    //                []() { Debugger::Initialize(nullptr); });160    m_debugger_sp = Debugger::CreateInstance();161    ASSERT_TRUE(m_debugger_sp);162    m_debugger_sp->GetTargetList().CreateTarget(*m_debugger_sp, "", arch,163                                                eLoadDependentsNo,164                                                m_platform_sp, m_target_sp);165    ASSERT_TRUE(m_target_sp);166    ASSERT_TRUE(m_target_sp->GetArchitecture().IsValid());167    ASSERT_TRUE(m_platform_sp);168    m_listener_sp = Listener::MakeListener("dummy");169    m_process_sp = std::make_shared<MockProcess>(m_target_sp, m_listener_sp);170    ASSERT_TRUE(m_process_sp);171    m_exe_ctx = ExecutionContext(m_process_sp);172 173    m_holder = std::make_unique<clang_utils::TypeSystemClangHolder>("test");174    m_type_system = m_holder->GetAST();175    LLDB_PLUGIN_INITIALIZE(MockLanguage);176    LLDB_PLUGIN_INITIALIZE(MockLanguageRuntime);177  }178  void TearDown() override {179    LLDB_PLUGIN_TERMINATE(MockLanguage);180    LLDB_PLUGIN_TERMINATE(MockLanguageRuntime);181  }182 183  void TestValueObjectWithLocalBuffer(DataExtractor &data_extractor,184                                      bool should_succeed) {185    std::unique_ptr<TypeSystemClangHolder> holder =186        std::make_unique<TypeSystemClangHolder>("test ASTContext");187    TypeSystemClang *ast = holder->GetAST();188    auto char_type = createRecordWithField(189        *ast, "TypeWithChar",190        ast->GetBasicType(lldb::BasicType::eBasicTypeChar), "theField");191 192    ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();193    ConstString var_name("test_var");194    auto valobj_sp = ValueObjectConstResult::Create(exe_scope, char_type,195                                                    var_name, data_extractor);196    auto dyn_valobj = valobj_sp->GetDynamicValue(lldb::eDynamicCanRunTarget);197    ASSERT_TRUE(dyn_valobj->GetValueIsValid() == should_succeed);198  }199 200  SubsystemRAII<FileSystem, HostInfo, platform_linux::PlatformLinux,201                ScriptInterpreterNone>202      m_subsystems;203  std::unique_ptr<clang_utils::TypeSystemClangHolder> m_holder;204  lldb::DebuggerSP m_debugger_sp;205  lldb::TargetSP m_target_sp;206  lldb::PlatformSP m_platform_sp;207  lldb::ListenerSP m_listener_sp;208  lldb::ProcessSP m_process_sp;209  ExecutionContext m_exe_ctx;210  TypeSystemClang *m_type_system;211};212 213TEST_F(DynamicValueObjectLocalBufferTest, BufferTooSmall) {214  /// Test that a value object with a buffer to small to fit the215  /// "dynamic" type will return an invalid dynamic value object.216  uint8_t value = 1;217  ByteOrder endian = endian::InlHostByteOrder();218  DataExtractor data_extractor{&value, sizeof(value), endian, 4};219  TestValueObjectWithLocalBuffer(data_extractor, false);220}221 222TEST_F(DynamicValueObjectLocalBufferTest, BufferTooBig) {223  /// Test that a value object with a buffer big enough fit the224  /// "dynamic" type will return a valid dynamic value object.225  uint64_t value = 1;226  ByteOrder endian = endian::InlHostByteOrder();227  DataExtractor data_extractor{&value, sizeof(value), endian, 4};228  TestValueObjectWithLocalBuffer(data_extractor, true);229}230 231TEST_F(DynamicValueObjectLocalBufferTest, BufferExactlyRight) {232  /// Test that a value object with a buffer exactly the size of the233  /// "dynamic" type will return a valid dynamic value object.234  uint32_t value = 1;235  ByteOrder endian = endian::InlHostByteOrder();236  DataExtractor data_extractor{&value, sizeof(value), endian, 4};237  TestValueObjectWithLocalBuffer(data_extractor, true);238}239