1 //===-- NativeProcessTestUtils.cpp ------------------------------*- C++ -*-===// 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef lldb_unittests_Host_NativeProcessTestUtils_h_ 10 #define lldb_unittests_Host_NativeProcessTestUtils_h_ 11 12 #include "lldb/Host/common/NativeProcessProtocol.h" 13 #include "llvm/Testing/Support/Error.h" 14 #include "gmock/gmock.h" 15 16 using namespace lldb_private; 17 using namespace lldb; 18 using namespace testing; 19 20 namespace lldb_private { 21 22 class MockDelegate : public NativeProcessProtocol::NativeDelegate { 23 public: 24 MOCK_METHOD1(InitializeDelegate, void(NativeProcessProtocol *Process)); 25 MOCK_METHOD2(ProcessStateChanged, 26 void(NativeProcessProtocol *Process, StateType State)); 27 MOCK_METHOD1(DidExec, void(NativeProcessProtocol *Process)); 28 }; 29 30 // NB: This class doesn't use the override keyword to avoid 31 // -Winconsistent-missing-override warnings from the compiler. The 32 // inconsistency comes from the overriding definitions in the MOCK_*** macros. 33 template <typename T> class MockProcess : public T { 34 public: 35 MockProcess(NativeProcessProtocol::NativeDelegate &Delegate, 36 const ArchSpec &Arch, lldb::pid_t Pid = 1) 37 : T(Pid, -1, Delegate), Arch(Arch) {} 38 39 MOCK_METHOD1(Resume, Status(const ResumeActionList &ResumeActions)); 40 MOCK_METHOD0(Halt, Status()); 41 MOCK_METHOD0(Detach, Status()); 42 MOCK_METHOD1(Signal, Status(int Signo)); 43 MOCK_METHOD0(Kill, Status()); 44 MOCK_METHOD3(AllocateMemory, 45 Status(size_t Size, uint32_t Permissions, addr_t &Addr)); 46 MOCK_METHOD1(DeallocateMemory, Status(addr_t Addr)); 47 MOCK_METHOD0(GetSharedLibraryInfoAddress, addr_t()); 48 MOCK_METHOD0(UpdateThreads, size_t()); 49 MOCK_CONST_METHOD0(GetAuxvData, 50 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>()); 51 MOCK_METHOD2(GetLoadedModuleFileSpec, 52 Status(const char *ModulePath, FileSpec &Spec)); 53 MOCK_METHOD2(GetFileLoadAddress, 54 Status(const llvm::StringRef &FileName, addr_t &Addr)); 55 56 const ArchSpec &GetArchitecture() const /*override*/ { return Arch; } 57 Status SetBreakpoint(lldb::addr_t Addr, uint32_t Size, 58 bool Hardware) /*override*/ { 59 if (Hardware) 60 return this->SetHardwareBreakpoint(Addr, Size); 61 else 62 return this->SetSoftwareBreakpoint(Addr, Size); 63 } 64 65 // Redirect base class Read/Write Memory methods to functions whose signatures 66 // are more mock-friendly. 67 Status ReadMemory(addr_t Addr, void *Buf, size_t Size, 68 size_t &BytesRead) /*override*/ { 69 auto ExpectedMemory = this->ReadMemory(Addr, Size); 70 if (!ExpectedMemory) { 71 BytesRead = 0; 72 return Status(ExpectedMemory.takeError()); 73 } 74 BytesRead = ExpectedMemory->size(); 75 assert(BytesRead <= Size); 76 std::memcpy(Buf, ExpectedMemory->data(), BytesRead); 77 return Status(); 78 } 79 80 Status WriteMemory(addr_t Addr, const void *Buf, size_t Size, 81 size_t &BytesWritten) /*override*/ { 82 auto ExpectedBytes = this->WriteMemory( 83 Addr, llvm::makeArrayRef(static_cast<const uint8_t *>(Buf), Size)); 84 if (!ExpectedBytes) { 85 BytesWritten = 0; 86 return Status(ExpectedBytes.takeError()); 87 } 88 BytesWritten = *ExpectedBytes; 89 return Status(); 90 } 91 92 MOCK_METHOD2(ReadMemory, 93 llvm::Expected<std::vector<uint8_t>>(addr_t Addr, size_t Size)); 94 MOCK_METHOD2(WriteMemory, 95 llvm::Expected<size_t>(addr_t Addr, 96 llvm::ArrayRef<uint8_t> Data)); 97 98 using T::GetSoftwareBreakpointTrapOpcode; 99 llvm::Expected<std::vector<uint8_t>> ReadMemoryWithoutTrap(addr_t Addr, 100 size_t Size) { 101 std::vector<uint8_t> Data(Size, 0); 102 size_t BytesRead; 103 Status ST = 104 T::ReadMemoryWithoutTrap(Addr, Data.data(), Data.size(), BytesRead); 105 if (ST.Fail()) 106 return ST.ToError(); 107 Data.resize(BytesRead); 108 return std::move(Data); 109 } 110 111 private: 112 ArchSpec Arch; 113 }; 114 115 class FakeMemory { 116 public: 117 FakeMemory(llvm::ArrayRef<uint8_t> Data, addr_t start_addr = 0) 118 : Data(Data), m_start_addr(start_addr) {} 119 120 FakeMemory(const void *Data, size_t data_size, addr_t start_addr = 0) 121 : Data((const uint8_t *)Data, ((const uint8_t *)Data) + data_size), 122 m_start_addr(start_addr) {} 123 124 llvm::Expected<std::vector<uint8_t>> Read(addr_t Addr, size_t Size) { 125 Addr -= m_start_addr; 126 if (Addr >= Data.size()) 127 return llvm::createStringError(llvm::inconvertibleErrorCode(), 128 "Address out of range."); 129 Size = std::min(Size, Data.size() - (size_t)Addr); 130 auto Begin = std::next(Data.begin(), Addr); 131 return std::vector<uint8_t>(Begin, std::next(Begin, Size)); 132 } 133 134 llvm::Expected<size_t> Write(addr_t Addr, llvm::ArrayRef<uint8_t> Chunk) { 135 Addr -= m_start_addr; 136 if (Addr >= Data.size()) 137 return llvm::createStringError(llvm::inconvertibleErrorCode(), 138 "Address out of range."); 139 size_t Size = std::min(Chunk.size(), Data.size() - (size_t)Addr); 140 std::copy_n(Chunk.begin(), Size, &Data[Addr]); 141 return Size; 142 } 143 144 private: 145 std::vector<uint8_t> Data; 146 addr_t m_start_addr; 147 }; 148 } // namespace lldb_private 149 150 #endif