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