diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -1441,6 +1441,7 @@ Status NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) { + 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. @@ -1453,8 +1454,21 @@ remote_iov.iov_base = reinterpret_cast(addr); remote_iov.iov_len = size; - bytes_read = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0); - const bool success = bytes_read == size; + auto vm_bytes_read = + process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0); + const bool success = vm_bytes_read == size; + if (vm_bytes_read > 0) { + bytes_read = vm_bytes_read; + // When process_vm_readv is not able to read all the data we fallback to + // ptrace. However, if process_vm_readv didn't fail (vm_bytes_read != -1) + // and was able to some bytes avoid re-reading them with ptrace by + // updating the addr and size to point to the rest of the data. + if (!success) { + addr = reinterpret_cast(reinterpret_cast(addr) + + vm_bytes_read); + size -= vm_bytes_read; + } + } Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, @@ -1468,14 +1482,14 @@ // api. } - unsigned char *dst = static_cast(buf); + unsigned char *dst = static_cast(buf) + bytes_read; size_t remainder; long data; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_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, GetID(), (void *)addr, nullptr, 0, &data); if (error.Fail())