1 //===-- NativeProcessProtocolTest.cpp ---------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Host/common/NativeProcessProtocol.h" 11 #include "llvm/Testing/Support/Error.h" 12 #include "gmock/gmock.h" 13 14 using namespace lldb_private; 15 using namespace lldb; 16 using namespace testing; 17 18 namespace { 19 class MockDelegate : public NativeProcessProtocol::NativeDelegate { 20 public: 21 MOCK_METHOD1(InitializeDelegate, void(NativeProcessProtocol *Process)); 22 MOCK_METHOD2(ProcessStateChanged, 23 void(NativeProcessProtocol *Process, StateType State)); 24 MOCK_METHOD1(DidExec, void(NativeProcessProtocol *Process)); 25 }; 26 27 // NB: This class doesn't use the override keyword to avoid 28 // -Winconsistent-missing-override warnings from the compiler. The 29 // inconsistency comes from the overriding definitions in the MOCK_*** macros. 30 class MockProcess : public NativeProcessProtocol { 31 public: 32 MockProcess(NativeDelegate &Delegate, const ArchSpec &Arch, 33 lldb::pid_t Pid = 1) 34 : NativeProcessProtocol(Pid, -1, Delegate), Arch(Arch) {} 35 36 MOCK_METHOD1(Resume, Status(const ResumeActionList &ResumeActions)); 37 MOCK_METHOD0(Halt, Status()); 38 MOCK_METHOD0(Detach, Status()); 39 MOCK_METHOD1(Signal, Status(int Signo)); 40 MOCK_METHOD0(Kill, Status()); 41 MOCK_METHOD3(AllocateMemory, 42 Status(size_t Size, uint32_t Permissions, addr_t &Addr)); 43 MOCK_METHOD1(DeallocateMemory, Status(addr_t Addr)); 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 53 const ArchSpec &GetArchitecture() const /*override*/ { return Arch; } 54 Status SetBreakpoint(lldb::addr_t Addr, uint32_t Size, 55 bool Hardware) /*override*/ { 56 if (Hardware) 57 return SetHardwareBreakpoint(Addr, Size); 58 else 59 return SetSoftwareBreakpoint(Addr, Size); 60 } 61 62 // Redirect base class Read/Write Memory methods to functions whose signatures 63 // are more mock-friendly. 64 Status ReadMemory(addr_t Addr, void *Buf, size_t Size, 65 size_t &BytesRead) /*override*/; 66 Status WriteMemory(addr_t Addr, const void *Buf, size_t Size, 67 size_t &BytesWritten) /*override*/; 68 69 MOCK_METHOD2(ReadMemory, 70 llvm::Expected<std::vector<uint8_t>>(addr_t Addr, size_t Size)); 71 MOCK_METHOD2(WriteMemory, 72 llvm::Expected<size_t>(addr_t Addr, 73 llvm::ArrayRef<uint8_t> Data)); 74 75 using NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode; 76 llvm::Expected<std::vector<uint8_t>> ReadMemoryWithoutTrap(addr_t Addr, 77 size_t Size); 78 79 private: 80 ArchSpec Arch; 81 }; 82 83 class FakeMemory { 84 public: 85 FakeMemory(llvm::ArrayRef<uint8_t> Data) : Data(Data) {} 86 llvm::Expected<std::vector<uint8_t>> Read(addr_t Addr, size_t Size); 87 llvm::Expected<size_t> Write(addr_t Addr, llvm::ArrayRef<uint8_t> Chunk); 88 89 private: 90 std::vector<uint8_t> Data; 91 }; 92 } // namespace 93 94 Status MockProcess::ReadMemory(addr_t Addr, void *Buf, size_t Size, 95 size_t &BytesRead) { 96 auto ExpectedMemory = ReadMemory(Addr, Size); 97 if (!ExpectedMemory) { 98 BytesRead = 0; 99 return Status(ExpectedMemory.takeError()); 100 } 101 BytesRead = ExpectedMemory->size(); 102 assert(BytesRead <= Size); 103 std::memcpy(Buf, ExpectedMemory->data(), BytesRead); 104 return Status(); 105 } 106 107 Status MockProcess::WriteMemory(addr_t Addr, const void *Buf, size_t Size, 108 size_t &BytesWritten) { 109 auto ExpectedBytes = WriteMemory( 110 Addr, llvm::makeArrayRef(static_cast<const uint8_t *>(Buf), Size)); 111 if (!ExpectedBytes) { 112 BytesWritten = 0; 113 return Status(ExpectedBytes.takeError()); 114 } 115 BytesWritten = *ExpectedBytes; 116 return Status(); 117 } 118 119 llvm::Expected<std::vector<uint8_t>> 120 MockProcess::ReadMemoryWithoutTrap(addr_t Addr, size_t Size) { 121 std::vector<uint8_t> Data(Size, 0); 122 size_t BytesRead; 123 Status ST = NativeProcessProtocol::ReadMemoryWithoutTrap( 124 Addr, Data.data(), Data.size(), BytesRead); 125 if (ST.Fail()) 126 return ST.ToError(); 127 Data.resize(BytesRead); 128 return std::move(Data); 129 } 130 131 llvm::Expected<std::vector<uint8_t>> FakeMemory::Read(addr_t Addr, 132 size_t Size) { 133 if (Addr >= Data.size()) 134 return llvm::createStringError(llvm::inconvertibleErrorCode(), 135 "Address out of range."); 136 Size = std::min(Size, Data.size() - (size_t)Addr); 137 auto Begin = std::next(Data.begin(), Addr); 138 return std::vector<uint8_t>(Begin, std::next(Begin, Size)); 139 } 140 141 llvm::Expected<size_t> FakeMemory::Write(addr_t Addr, 142 llvm::ArrayRef<uint8_t> Chunk) { 143 if (Addr >= Data.size()) 144 return llvm::createStringError(llvm::inconvertibleErrorCode(), 145 "Address out of range."); 146 size_t Size = std::min(Chunk.size(), Data.size() - (size_t)Addr); 147 std::copy_n(Chunk.begin(), Size, &Data[Addr]); 148 return Size; 149 } 150 151 TEST(NativeProcessProtocolTest, SetBreakpoint) { 152 NiceMock<MockDelegate> DummyDelegate; 153 MockProcess Process(DummyDelegate, ArchSpec("x86_64-pc-linux")); 154 auto Trap = cantFail(Process.GetSoftwareBreakpointTrapOpcode(1)); 155 InSequence S; 156 EXPECT_CALL(Process, ReadMemory(0x47, 1)) 157 .WillOnce(Return(ByMove(std::vector<uint8_t>{0xbb}))); 158 EXPECT_CALL(Process, WriteMemory(0x47, Trap)).WillOnce(Return(ByMove(1))); 159 EXPECT_CALL(Process, ReadMemory(0x47, 1)).WillOnce(Return(ByMove(Trap))); 160 EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(), 161 llvm::Succeeded()); 162 } 163 164 TEST(NativeProcessProtocolTest, SetBreakpointFailRead) { 165 NiceMock<MockDelegate> DummyDelegate; 166 MockProcess Process(DummyDelegate, ArchSpec("x86_64-pc-linux")); 167 EXPECT_CALL(Process, ReadMemory(0x47, 1)) 168 .WillOnce(Return(ByMove( 169 llvm::createStringError(llvm::inconvertibleErrorCode(), "Foo")))); 170 EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(), 171 llvm::Failed()); 172 } 173 174 TEST(NativeProcessProtocolTest, SetBreakpointFailWrite) { 175 NiceMock<MockDelegate> DummyDelegate; 176 MockProcess Process(DummyDelegate, ArchSpec("x86_64-pc-linux")); 177 auto Trap = cantFail(Process.GetSoftwareBreakpointTrapOpcode(1)); 178 InSequence S; 179 EXPECT_CALL(Process, ReadMemory(0x47, 1)) 180 .WillOnce(Return(ByMove(std::vector<uint8_t>{0xbb}))); 181 EXPECT_CALL(Process, WriteMemory(0x47, Trap)) 182 .WillOnce(Return(ByMove( 183 llvm::createStringError(llvm::inconvertibleErrorCode(), "Foo")))); 184 EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(), 185 llvm::Failed()); 186 } 187 188 TEST(NativeProcessProtocolTest, SetBreakpointFailVerify) { 189 NiceMock<MockDelegate> DummyDelegate; 190 MockProcess Process(DummyDelegate, ArchSpec("x86_64-pc-linux")); 191 auto Trap = cantFail(Process.GetSoftwareBreakpointTrapOpcode(1)); 192 InSequence S; 193 EXPECT_CALL(Process, ReadMemory(0x47, 1)) 194 .WillOnce(Return(ByMove(std::vector<uint8_t>{0xbb}))); 195 EXPECT_CALL(Process, WriteMemory(0x47, Trap)).WillOnce(Return(ByMove(1))); 196 EXPECT_CALL(Process, ReadMemory(0x47, 1)) 197 .WillOnce(Return(ByMove( 198 llvm::createStringError(llvm::inconvertibleErrorCode(), "Foo")))); 199 EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(), 200 llvm::Failed()); 201 } 202 203 TEST(NativeProcessProtocolTest, ReadMemoryWithoutTrap) { 204 NiceMock<MockDelegate> DummyDelegate; 205 MockProcess Process(DummyDelegate, ArchSpec("aarch64-pc-linux")); 206 FakeMemory M{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}}; 207 EXPECT_CALL(Process, ReadMemory(_, _)) 208 .WillRepeatedly(Invoke(&M, &FakeMemory::Read)); 209 EXPECT_CALL(Process, WriteMemory(_, _)) 210 .WillRepeatedly(Invoke(&M, &FakeMemory::Write)); 211 212 EXPECT_THAT_ERROR(Process.SetBreakpoint(0x4, 0, false).ToError(), 213 llvm::Succeeded()); 214 EXPECT_THAT_EXPECTED( 215 Process.ReadMemoryWithoutTrap(0, 10), 216 llvm::HasValue(std::vector<uint8_t>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); 217 EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(0, 6), 218 llvm::HasValue(std::vector<uint8_t>{0, 1, 2, 3, 4, 5})); 219 EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(6, 4), 220 llvm::HasValue(std::vector<uint8_t>{6, 7, 8, 9})); 221 EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(6, 2), 222 llvm::HasValue(std::vector<uint8_t>{6, 7})); 223 EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(4, 2), 224 llvm::HasValue(std::vector<uint8_t>{4, 5})); 225 } 226