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_TESTINGSUPPORT_HOST_NATIVEPROCESSTESTUTILS_H 10 #define LLDB_UNITTESTS_TESTINGSUPPORT_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_METHOD0(GetSharedLibraryInfoAddress, addr_t()); 45 MOCK_METHOD0(UpdateThreads, size_t()); 46 MOCK_CONST_METHOD0(GetAuxvData, 47 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>()); 48 MOCK_METHOD2(GetLoadedModuleFileSpec, 49 Status(const char *ModulePath, FileSpec &Spec)); 50 MOCK_METHOD2(GetFileLoadAddress, 51 Status(const llvm::StringRef &FileName, addr_t &Addr)); 52 GetArchitecture()53 const ArchSpec &GetArchitecture() const /*override*/ { return Arch; } SetBreakpoint(lldb::addr_t Addr,uint32_t Size,bool Hardware)54 Status SetBreakpoint(lldb::addr_t Addr, uint32_t Size, 55 bool Hardware) /*override*/ { 56 if (Hardware) 57 return this->SetHardwareBreakpoint(Addr, Size); 58 else 59 return this->SetSoftwareBreakpoint(Addr, Size); 60 } 61 62 // Redirect base class Read/Write Memory methods to functions whose signatures 63 // are more mock-friendly. ReadMemory(addr_t Addr,void * Buf,size_t Size,size_t & BytesRead)64 Status ReadMemory(addr_t Addr, void *Buf, size_t Size, 65 size_t &BytesRead) /*override*/ { 66 auto ExpectedMemory = this->ReadMemory(Addr, Size); 67 if (!ExpectedMemory) { 68 BytesRead = 0; 69 return Status(ExpectedMemory.takeError()); 70 } 71 BytesRead = ExpectedMemory->size(); 72 assert(BytesRead <= Size); 73 std::memcpy(Buf, ExpectedMemory->data(), BytesRead); 74 return Status(); 75 } 76 WriteMemory(addr_t Addr,const void * Buf,size_t Size,size_t & BytesWritten)77 Status WriteMemory(addr_t Addr, const void *Buf, size_t Size, 78 size_t &BytesWritten) /*override*/ { 79 auto ExpectedBytes = this->WriteMemory( 80 Addr, llvm::makeArrayRef(static_cast<const uint8_t *>(Buf), Size)); 81 if (!ExpectedBytes) { 82 BytesWritten = 0; 83 return Status(ExpectedBytes.takeError()); 84 } 85 BytesWritten = *ExpectedBytes; 86 return Status(); 87 } 88 89 MOCK_METHOD2(ReadMemory, 90 llvm::Expected<std::vector<uint8_t>>(addr_t Addr, size_t Size)); 91 MOCK_METHOD2(WriteMemory, 92 llvm::Expected<size_t>(addr_t Addr, 93 llvm::ArrayRef<uint8_t> Data)); 94 95 using T::GetSoftwareBreakpointTrapOpcode; ReadMemoryWithoutTrap(addr_t Addr,size_t Size)96 llvm::Expected<std::vector<uint8_t>> ReadMemoryWithoutTrap(addr_t Addr, 97 size_t Size) { 98 std::vector<uint8_t> Data(Size, 0); 99 size_t BytesRead; 100 Status ST = 101 T::ReadMemoryWithoutTrap(Addr, Data.data(), Data.size(), BytesRead); 102 if (ST.Fail()) 103 return ST.ToError(); 104 Data.resize(BytesRead); 105 return std::move(Data); 106 } 107 108 private: 109 ArchSpec Arch; 110 }; 111 112 class FakeMemory { 113 public: 114 FakeMemory(llvm::ArrayRef<uint8_t> Data, addr_t start_addr = 0) Data(Data)115 : Data(Data), m_start_addr(start_addr) {} 116 117 FakeMemory(const void *Data, size_t data_size, addr_t start_addr = 0) 118 : Data((const uint8_t *)Data, ((const uint8_t *)Data) + data_size), 119 m_start_addr(start_addr) {} 120 Read(addr_t Addr,size_t Size)121 llvm::Expected<std::vector<uint8_t>> Read(addr_t Addr, size_t Size) { 122 Addr -= m_start_addr; 123 if (Addr >= Data.size()) 124 return llvm::createStringError(llvm::inconvertibleErrorCode(), 125 "Address out of range."); 126 Size = std::min(Size, Data.size() - (size_t)Addr); 127 auto Begin = std::next(Data.begin(), Addr); 128 return std::vector<uint8_t>(Begin, std::next(Begin, Size)); 129 } 130 Write(addr_t Addr,llvm::ArrayRef<uint8_t> Chunk)131 llvm::Expected<size_t> Write(addr_t Addr, llvm::ArrayRef<uint8_t> Chunk) { 132 Addr -= m_start_addr; 133 if (Addr >= Data.size()) 134 return llvm::createStringError(llvm::inconvertibleErrorCode(), 135 "Address out of range."); 136 size_t Size = std::min(Chunk.size(), Data.size() - (size_t)Addr); 137 std::copy_n(Chunk.begin(), Size, &Data[Addr]); 138 return Size; 139 } 140 141 private: 142 std::vector<uint8_t> Data; 143 addr_t m_start_addr; 144 }; 145 } // namespace lldb_private 146 147 #endif 148