aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
diff options
context:
space:
mode:
authorPavel Labath <pavel@labath.sk>2024-09-02 14:44:18 +0200
committerGitHub <noreply@github.com>2024-09-02 14:44:18 +0200
commit181cc75ea8be70e3fa7145456e1bf2331e0bc5e4 (patch)
tree75793108d142e5e484515987d5218ae9ab025e07 /lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
parent0c0bac94c08e73d4c35b454ba02317f2db313f93 (diff)
downloadllvm-181cc75ea8be70e3fa7145456e1bf2331e0bc5e4.zip
llvm-181cc75ea8be70e3fa7145456e1bf2331e0bc5e4.tar.gz
llvm-181cc75ea8be70e3fa7145456e1bf2331e0bc5e4.tar.bz2
[lldb/linux] Make truncated reads work (#106532)
Previously, we were returning an error if we couldn't read the whole region. This doesn't matter most of the time, because lldb caches memory reads, and in that process it aligns them to cache line boundaries. As (LLDB) cache lines are smaller than pages, the reads are unlikely to cross page boundaries. Nonetheless, this can cause a problem for large reads (which bypass the cache), where we're unable to read anything even if just a single byte of the memory is unreadable. This patch fixes the lldb-server to do that, and also changes the linux implementation, to reuse any partial results it got from the process_vm_readv call (to avoid having to re-read everything again using ptrace, only to find that it stopped at the same place). This matches debugserver behavior. It is also consistent with the gdb remote protocol documentation, but -- notably -- not with actual gdbserver behavior (which returns errors instead of partial results). We filed a [clarification bug](https://sourceware.org/bugzilla/show_bug.cgi?id=24751) several years ago. Though we did not really reach a conclusion there, I think this is the most logical behavior. The associated test does not currently pass on windows, because the windows memory read APIs don't support partial reads (I have a WIP patch to work around that).
Diffstat (limited to 'lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp')
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp41
1 files changed, 19 insertions, 22 deletions
diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index cb95da9..1e2e3a8 100644
--- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -1641,6 +1641,10 @@ NativeProcessLinux::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
Status NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
size_t &bytes_read) {
+ Log *log = GetLog(POSIXLog::Memory);
+ LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
+
+ bytes_read = 0;
if (ProcessVmReadvSupported()) {
// The process_vm_readv path is about 50 times faster than ptrace api. We
// want to use this syscall if it is supported.
@@ -1651,32 +1655,29 @@ Status NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
remote_iov.iov_base = reinterpret_cast<void *>(addr);
remote_iov.iov_len = size;
- bytes_read = process_vm_readv(GetCurrentThreadID(), &local_iov, 1,
- &remote_iov, 1, 0);
- const bool success = bytes_read == size;
+ ssize_t read_result = process_vm_readv(GetCurrentThreadID(), &local_iov, 1,
+ &remote_iov, 1, 0);
+ int error = 0;
+ if (read_result < 0)
+ error = errno;
+ else
+ bytes_read = read_result;
- Log *log = GetLog(POSIXLog::Process);
LLDB_LOG(log,
- "using process_vm_readv to read {0} bytes from inferior "
- "address {1:x}: {2}",
- size, addr, success ? "Success" : llvm::sys::StrError(errno));
-
- if (success)
- return Status();
- // else the call failed for some reason, let's retry the read using ptrace
- // api.
+ "process_vm_readv({0}, [iovec({1}, {2})], [iovec({3:x}, {2})], 1, "
+ "0) => {4} ({5})",
+ GetCurrentThreadID(), buf, size, addr, read_result,
+ error > 0 ? llvm::sys::StrError(errno) : "sucesss");
}
unsigned char *dst = static_cast<unsigned char *>(buf);
size_t remainder;
long data;
- Log *log = GetLog(POSIXLog::Memory);
- LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
-
- for (bytes_read = 0; bytes_read < size; bytes_read += remainder) {
+ for (; bytes_read < size; bytes_read += remainder) {
Status error = NativeProcessLinux::PtraceWrapper(
- PTRACE_PEEKDATA, GetCurrentThreadID(), (void *)addr, nullptr, 0, &data);
+ PTRACE_PEEKDATA, GetCurrentThreadID(),
+ reinterpret_cast<void *>(addr + bytes_read), nullptr, 0, &data);
if (error.Fail())
return error;
@@ -1684,11 +1685,7 @@ Status NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder;
// Copy the data into our buffer
- memcpy(dst, &data, remainder);
-
- LLDB_LOG(log, "[{0:x}]:{1:x}", addr, data);
- addr += k_ptrace_word_size;
- dst += k_ptrace_word_size;
+ memcpy(dst + bytes_read, &data, remainder);
}
return Status();
}