summaryrefslogtreecommitdiff
path: root/lldb/source
diff options
context:
space:
mode:
authorPavel Labath <pavel@labath.sk>2018-09-26 07:31:41 +0000
committerPavel Labath <pavel@labath.sk>2018-09-26 07:31:41 +0000
commita053a48c5551a8b9454cb54832b9136f60232996 (patch)
tree2c249d2285e182f582ae226b63a214c2395481a2 /lldb/source
parent912c4c9012c5c3a0b478e29fe4f66295db61107c (diff)
Fix a memory read bug in lldb-server
NativeProcessProtocol::ReadMemoryWithoutTrap had a bug, where it failed to properly remove inserted breakpoint opcodes if the memory read partially overlapped the trap opcode. This could not happen on x86 because it has a one-byte breakpoint instruction, but it could happen on arm, which has a 4-byte breakpoint instruction (in arm mode). Since triggerring this condition would only be possible on an arm machine (and even then it would be a bit tricky). I test this using a NativeProcessProtocol unit test.
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/Host/common/NativeBreakpointList.cpp25
1 files changed, 18 insertions, 7 deletions
diff --git a/lldb/source/Host/common/NativeBreakpointList.cpp b/lldb/source/Host/common/NativeBreakpointList.cpp
index cfcbe083106..b1a42d7583c 100644
--- a/lldb/source/Host/common/NativeBreakpointList.cpp
+++ b/lldb/source/Host/common/NativeBreakpointList.cpp
@@ -210,20 +210,31 @@ Status NativeBreakpointList::GetBreakpoint(lldb::addr_t addr,
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();
}