Status NativeBreakpointList::RemoveTrapsFromBuffer(lldb::addr_t addr, void *buf,
size_t size) const {
+ auto data = llvm::makeMutableArrayRef(static_cast<uint8_t *>(buf), size);
for (const auto &map : m_breakpoints) {
- lldb::addr_t bp_addr = map.first;
- // Breapoint not in range, ignore
- if (bp_addr < addr || addr + size <= bp_addr)
- continue;
const auto &bp_sp = map.second;
// Not software breakpoint, ignore
if (!bp_sp->IsSoftwareBreakpoint())
continue;
auto software_bp_sp = std::static_pointer_cast<SoftwareBreakpoint>(bp_sp);
- auto opcode_addr = static_cast<char *>(buf) + bp_addr - addr;
- auto saved_opcodes = software_bp_sp->m_saved_opcodes;
+
+ lldb::addr_t bp_addr = map.first;
auto opcode_size = software_bp_sp->m_opcode_size;
- ::memcpy(opcode_addr, saved_opcodes, opcode_size);
+
+ // Breapoint not in range, ignore
+ if (bp_addr + opcode_size < addr || addr + size <= bp_addr)
+ continue;
+
+ auto saved_opcodes =
+ llvm::makeArrayRef(software_bp_sp->m_saved_opcodes, opcode_size);
+ if (bp_addr < addr) {
+ saved_opcodes = saved_opcodes.drop_front(addr - bp_addr);
+ bp_addr = addr;
+ }
+ auto bp_data = data.drop_front(bp_addr - addr);
+ std::copy_n(saved_opcodes.begin(),
+ std::min(saved_opcodes.size(), bp_data.size()),
+ bp_data.begin());
}
return Status();
}
llvm::ArrayRef<uint8_t> Data));
using NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode;
+ llvm::Expected<std::vector<uint8_t>> ReadMemoryWithoutTrap(addr_t Addr,
+ size_t Size);
private:
ArchSpec Arch;
};
+
+class FakeMemory {
+public:
+ FakeMemory(llvm::ArrayRef<uint8_t> Data) : Data(Data) {}
+ llvm::Expected<std::vector<uint8_t>> Read(addr_t Addr, size_t Size);
+ llvm::Expected<size_t> Write(addr_t Addr, llvm::ArrayRef<uint8_t> Chunk);
+
+private:
+ std::vector<uint8_t> Data;
+};
} // namespace
Status MockProcess::ReadMemory(addr_t Addr, void *Buf, size_t Size,
return Status();
}
+llvm::Expected<std::vector<uint8_t>>
+MockProcess::ReadMemoryWithoutTrap(addr_t Addr, size_t Size) {
+ std::vector<uint8_t> Data(Size, 0);
+ size_t BytesRead;
+ Status ST = NativeProcessProtocol::ReadMemoryWithoutTrap(
+ Addr, Data.data(), Data.size(), BytesRead);
+ if (ST.Fail())
+ return ST.ToError();
+ Data.resize(BytesRead);
+ return std::move(Data);
+}
+
+llvm::Expected<std::vector<uint8_t>> FakeMemory::Read(addr_t Addr,
+ size_t Size) {
+ if (Addr >= Data.size())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Address out of range.");
+ Size = std::min(Size, Data.size() - Addr);
+ return std::vector<uint8_t>(&Data[Addr], &Data[Addr + Size]);
+}
+
+llvm::Expected<size_t> FakeMemory::Write(addr_t Addr,
+ llvm::ArrayRef<uint8_t> Chunk) {
+ if (Addr >= Data.size())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Address out of range.");
+ size_t Size = std::min(Chunk.size(), Data.size() - Addr);
+ std::copy_n(Chunk.begin(), Size, &Data[Addr]);
+ return Size;
+}
+
TEST(NativeProcessProtocolTest, SetBreakpoint) {
NiceMock<MockDelegate> DummyDelegate;
MockProcess Process(DummyDelegate, ArchSpec("x86_64-pc-linux"));
EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(),
llvm::Failed());
}
+
+TEST(NativeProcessProtocolTest, ReadMemoryWithoutTrap) {
+ NiceMock<MockDelegate> DummyDelegate;
+ MockProcess Process(DummyDelegate, ArchSpec("aarch64-pc-linux"));
+ FakeMemory M{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}};
+ EXPECT_CALL(Process, ReadMemory(_, _))
+ .WillRepeatedly(Invoke(&M, &FakeMemory::Read));
+ EXPECT_CALL(Process, WriteMemory(_, _))
+ .WillRepeatedly(Invoke(&M, &FakeMemory::Write));
+
+ EXPECT_THAT_ERROR(Process.SetBreakpoint(0x4, 0, false).ToError(),
+ llvm::Succeeded());
+ EXPECT_THAT_EXPECTED(
+ Process.ReadMemoryWithoutTrap(0, 10),
+ llvm::HasValue(std::vector<uint8_t>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}));
+ EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(0, 6),
+ llvm::HasValue(std::vector<uint8_t>{0, 1, 2, 3, 4, 5}));
+ EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(6, 4),
+ llvm::HasValue(std::vector<uint8_t>{6, 7, 8, 9}));
+ EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(6, 2),
+ llvm::HasValue(std::vector<uint8_t>{6, 7}));
+ EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(4, 2),
+ llvm::HasValue(std::vector<uint8_t>{4, 5}));
+}