241 lines · cpp
1//===-- NativeProcessProtocolTest.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 "TestingSupport/Host/NativeProcessTestUtils.h"10 11#include "lldb/Host/common/NativeProcessProtocol.h"12#include "llvm/Support/Process.h"13#include "llvm/Testing/Support/Error.h"14#include "gmock/gmock.h"15 16using namespace lldb_private;17using namespace lldb;18using namespace testing;19 20TEST(NativeProcessProtocolTest, SetBreakpoint) {21 NiceMock<MockDelegate> DummyDelegate;22 MockProcess<NativeProcessProtocol> Process(DummyDelegate,23 ArchSpec("x86_64-pc-linux"));24 auto Trap = cantFail(Process.GetSoftwareBreakpointTrapOpcode(1));25 InSequence S;26 EXPECT_CALL(Process, ReadMemory(0x47, 1))27 .WillOnce(Return(ByMove(std::vector<uint8_t>{0xbb})));28 EXPECT_CALL(Process, WriteMemory(0x47, Trap)).WillOnce(Return(ByMove(1)));29 EXPECT_CALL(Process, ReadMemory(0x47, 1)).WillOnce(Return(ByMove(Trap)));30 EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(),31 llvm::Succeeded());32}33 34TEST(NativeProcessProtocolTest, SetBreakpointFailRead) {35 NiceMock<MockDelegate> DummyDelegate;36 MockProcess<NativeProcessProtocol> Process(DummyDelegate,37 ArchSpec("x86_64-pc-linux"));38 EXPECT_CALL(Process, ReadMemory(0x47, 1))39 .WillOnce(Return(ByMove(40 llvm::createStringError(llvm::inconvertibleErrorCode(), "Foo"))));41 EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(),42 llvm::Failed());43}44 45TEST(NativeProcessProtocolTest, SetBreakpointFailWrite) {46 NiceMock<MockDelegate> DummyDelegate;47 MockProcess<NativeProcessProtocol> Process(DummyDelegate,48 ArchSpec("x86_64-pc-linux"));49 auto Trap = cantFail(Process.GetSoftwareBreakpointTrapOpcode(1));50 InSequence S;51 EXPECT_CALL(Process, ReadMemory(0x47, 1))52 .WillOnce(Return(ByMove(std::vector<uint8_t>{0xbb})));53 EXPECT_CALL(Process, WriteMemory(0x47, Trap))54 .WillOnce(Return(ByMove(55 llvm::createStringError(llvm::inconvertibleErrorCode(), "Foo"))));56 EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(),57 llvm::Failed());58}59 60TEST(NativeProcessProtocolTest, SetBreakpointFailVerify) {61 NiceMock<MockDelegate> DummyDelegate;62 MockProcess<NativeProcessProtocol> Process(DummyDelegate,63 ArchSpec("x86_64-pc-linux"));64 auto Trap = cantFail(Process.GetSoftwareBreakpointTrapOpcode(1));65 InSequence S;66 EXPECT_CALL(Process, ReadMemory(0x47, 1))67 .WillOnce(Return(ByMove(std::vector<uint8_t>{0xbb})));68 EXPECT_CALL(Process, WriteMemory(0x47, Trap)).WillOnce(Return(ByMove(1)));69 EXPECT_CALL(Process, ReadMemory(0x47, 1))70 .WillOnce(Return(ByMove(71 llvm::createStringError(llvm::inconvertibleErrorCode(), "Foo"))));72 EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(),73 llvm::Failed());74}75 76TEST(NativeProcessProtocolTest, RemoveSoftwareBreakpoint) {77 NiceMock<MockDelegate> DummyDelegate;78 MockProcess<NativeProcessProtocol> Process(DummyDelegate,79 ArchSpec("x86_64-pc-linux"));80 auto Trap = cantFail(Process.GetSoftwareBreakpointTrapOpcode(1));81 auto Original = std::vector<uint8_t>{0xbb};82 83 // Set up a breakpoint.84 {85 InSequence S;86 EXPECT_CALL(Process, ReadMemory(0x47, 1))87 .WillOnce(Return(ByMove(Original)));88 EXPECT_CALL(Process, WriteMemory(0x47, Trap)).WillOnce(Return(ByMove(1)));89 EXPECT_CALL(Process, ReadMemory(0x47, 1)).WillOnce(Return(ByMove(Trap)));90 EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(),91 llvm::Succeeded());92 }93 94 // Remove the breakpoint for the first time. This should remove the breakpoint95 // from m_software_breakpoints.96 //97 // Should succeed.98 {99 InSequence S;100 EXPECT_CALL(Process, ReadMemory(0x47, 1)).WillOnce(Return(ByMove(Trap)));101 EXPECT_CALL(Process, WriteMemory(0x47, llvm::ArrayRef(Original)))102 .WillOnce(Return(ByMove(1)));103 EXPECT_CALL(Process, ReadMemory(0x47, 1))104 .WillOnce(Return(ByMove(Original)));105 EXPECT_THAT_ERROR(Process.RemoveBreakpoint(0x47, false).ToError(),106 llvm::Succeeded());107 }108 109 // Remove the breakpoint for the second time.110 //111 // Should fail. None of the ReadMemory() or WriteMemory() should be called,112 // because the function should early return when seeing that the breakpoint113 // isn't in m_software_breakpoints.114 {115 EXPECT_CALL(Process, ReadMemory(_, _)).Times(0);116 EXPECT_CALL(Process, WriteMemory(_, _)).Times(0);117 EXPECT_THAT_ERROR(Process.RemoveBreakpoint(0x47, false).ToError(),118 llvm::Failed());119 }120}121 122TEST(NativeProcessProtocolTest, RemoveSoftwareBreakpointMemoryError) {123 NiceMock<MockDelegate> DummyDelegate;124 MockProcess<NativeProcessProtocol> Process(DummyDelegate,125 ArchSpec("x86_64-pc-linux"));126 auto Trap = cantFail(Process.GetSoftwareBreakpointTrapOpcode(1));127 auto Original = std::vector<uint8_t>{0xbb};128 auto SomethingElse = std::vector<uint8_t>{0xaa};129 130 // Set up a breakpoint.131 {132 InSequence S;133 EXPECT_CALL(Process, ReadMemory(0x47, 1))134 .WillOnce(Return(ByMove(Original)));135 EXPECT_CALL(Process, WriteMemory(0x47, Trap)).WillOnce(Return(ByMove(1)));136 EXPECT_CALL(Process, ReadMemory(0x47, 1)).WillOnce(Return(ByMove(Trap)));137 EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(),138 llvm::Succeeded());139 }140 141 // Remove the breakpoint for the first time, with an unexpected value read by142 // the first ReadMemory(). This should cause an early return, with the143 // breakpoint removed from m_software_breakpoints.144 //145 // Should fail.146 {147 InSequence S;148 EXPECT_CALL(Process, ReadMemory(0x47, 1))149 .WillOnce(Return(ByMove(SomethingElse)));150 EXPECT_THAT_ERROR(Process.RemoveBreakpoint(0x47, false).ToError(),151 llvm::Failed());152 }153 154 // Remove the breakpoint for the second time.155 //156 // Should fail. None of the ReadMemory() or WriteMemory() should be called,157 // because the function should early return when seeing that the breakpoint158 // isn't in m_software_breakpoints.159 {160 EXPECT_CALL(Process, ReadMemory(_, _)).Times(0);161 EXPECT_CALL(Process, WriteMemory(_, _)).Times(0);162 EXPECT_THAT_ERROR(Process.RemoveBreakpoint(0x47, false).ToError(),163 llvm::Failed());164 }165}166 167TEST(NativeProcessProtocolTest, ReadMemoryWithoutTrap) {168 NiceMock<MockDelegate> DummyDelegate;169 MockProcess<NativeProcessProtocol> Process(DummyDelegate,170 ArchSpec("aarch64-pc-linux"));171 FakeMemory M{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}};172 EXPECT_CALL(Process, ReadMemory(_, _))173 .WillRepeatedly(Invoke(&M, &FakeMemory::Read));174 EXPECT_CALL(Process, WriteMemory(_, _))175 .WillRepeatedly(Invoke(&M, &FakeMemory::Write));176 177 EXPECT_THAT_ERROR(Process.SetBreakpoint(0x4, 0, false).ToError(),178 llvm::Succeeded());179 EXPECT_THAT_EXPECTED(180 Process.ReadMemoryWithoutTrap(0, 10),181 llvm::HasValue(std::vector<uint8_t>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}));182 EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(0, 6),183 llvm::HasValue(std::vector<uint8_t>{0, 1, 2, 3, 4, 5}));184 EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(6, 4),185 llvm::HasValue(std::vector<uint8_t>{6, 7, 8, 9}));186 EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(6, 2),187 llvm::HasValue(std::vector<uint8_t>{6, 7}));188 EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(4, 2),189 llvm::HasValue(std::vector<uint8_t>{4, 5}));190}191 192TEST(NativeProcessProtocolTest, ReadCStringFromMemory) {193 NiceMock<MockDelegate> DummyDelegate;194 MockProcess<NativeProcessProtocol> Process(DummyDelegate,195 ArchSpec("aarch64-pc-linux"));196 FakeMemory M({'h', 'e', 'l', 'l', 'o', 0, 'w', 'o'});197 EXPECT_CALL(Process, ReadMemory(_, _))198 .WillRepeatedly(Invoke(&M, &FakeMemory::Read));199 200 char string[1024];201 size_t bytes_read;202 EXPECT_THAT_EXPECTED(Process.ReadCStringFromMemory(203 0x0, &string[0], sizeof(string), bytes_read),204 llvm::HasValue(llvm::StringRef("hello")));205 EXPECT_EQ(bytes_read, 6UL);206}207 208TEST(NativeProcessProtocolTest, ReadCStringFromMemory_MaxSize) {209 NiceMock<MockDelegate> DummyDelegate;210 MockProcess<NativeProcessProtocol> Process(DummyDelegate,211 ArchSpec("aarch64-pc-linux"));212 FakeMemory M({'h', 'e', 'l', 'l', 'o', 0, 'w', 'o'});213 EXPECT_CALL(Process, ReadMemory(_, _))214 .WillRepeatedly(Invoke(&M, &FakeMemory::Read));215 216 char string[4];217 size_t bytes_read;218 EXPECT_THAT_EXPECTED(Process.ReadCStringFromMemory(219 0x0, &string[0], sizeof(string), bytes_read),220 llvm::HasValue(llvm::StringRef("hel")));221 EXPECT_EQ(bytes_read, 3UL);222}223 224TEST(NativeProcessProtocolTest, ReadCStringFromMemory_CrossPageBoundary) {225 NiceMock<MockDelegate> DummyDelegate;226 MockProcess<NativeProcessProtocol> Process(DummyDelegate,227 ArchSpec("aarch64-pc-linux"));228 unsigned string_start = llvm::sys::Process::getPageSizeEstimate() - 3;229 FakeMemory M({'h', 'e', 'l', 'l', 'o', 0, 'w', 'o'}, string_start);230 EXPECT_CALL(Process, ReadMemory(_, _))231 .WillRepeatedly(Invoke(&M, &FakeMemory::Read));232 233 char string[1024];234 size_t bytes_read;235 EXPECT_THAT_EXPECTED(Process.ReadCStringFromMemory(string_start, &string[0],236 sizeof(string),237 bytes_read),238 llvm::HasValue(llvm::StringRef("hello")));239 EXPECT_EQ(bytes_read, 6UL);240}241