From 3dfd2aea7a28faa5240cb308b9cdcca8b4025f83 Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Fri, 15 Dec 2017 20:00:59 -0800 Subject: Add tool to save information from a process. Also, modify the ProcessVmRead function to allow arbitrarily large reads and add a test for it. Test: Run tool and verify the output can be used to do an offline Test: unwind. Test: Ran unit tests. Change-Id: I0974ddca4f5cf72b4c9fa29b597a0a669e223828 --- libunwindstack/Memory.cpp | 66 ++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 30 deletions(-) (limited to 'libunwindstack/Memory.cpp') diff --git a/libunwindstack/Memory.cpp b/libunwindstack/Memory.cpp index 1f3c6c393..285f8790a 100644 --- a/libunwindstack/Memory.cpp +++ b/libunwindstack/Memory.cpp @@ -35,10 +35,6 @@ namespace unwindstack { static size_t ProcessVmRead(pid_t pid, uint64_t remote_src, void* dst, size_t len) { - struct iovec dst_iov = { - .iov_base = dst, - .iov_len = len, - }; // Split up the remote read across page boundaries. // From the manpage: @@ -49,39 +45,49 @@ static size_t ProcessVmRead(pid_t pid, uint64_t remote_src, void* dst, size_t le // perform a partial transfer that splits a single iovec element. constexpr size_t kMaxIovecs = 64; struct iovec src_iovs[kMaxIovecs]; - size_t iovecs_used = 0; uint64_t cur = remote_src; + size_t total_read = 0; while (len > 0) { - if (iovecs_used == kMaxIovecs) { - errno = EINVAL; - return 0; + struct iovec dst_iov = { + .iov_base = &reinterpret_cast(dst)[total_read], .iov_len = len, + }; + + size_t iovecs_used = 0; + while (len > 0) { + if (iovecs_used == kMaxIovecs) { + break; + } + + // struct iovec uses void* for iov_base. + if (cur >= UINTPTR_MAX) { + errno = EFAULT; + return total_read; + } + + src_iovs[iovecs_used].iov_base = reinterpret_cast(cur); + + uintptr_t misalignment = cur & (getpagesize() - 1); + size_t iov_len = getpagesize() - misalignment; + iov_len = std::min(iov_len, len); + + len -= iov_len; + if (__builtin_add_overflow(cur, iov_len, &cur)) { + errno = EFAULT; + return total_read; + } + + src_iovs[iovecs_used].iov_len = iov_len; + ++iovecs_used; } - // struct iovec uses void* for iov_base. - if (cur >= UINTPTR_MAX) { - errno = EFAULT; - return 0; + ssize_t rc = process_vm_readv(pid, &dst_iov, 1, src_iovs, iovecs_used, 0); + if (rc == -1) { + return total_read; } - - src_iovs[iovecs_used].iov_base = reinterpret_cast(cur); - - uintptr_t misalignment = cur & (getpagesize() - 1); - size_t iov_len = getpagesize() - misalignment; - iov_len = std::min(iov_len, len); - - len -= iov_len; - if (__builtin_add_overflow(cur, iov_len, &cur)) { - errno = EFAULT; - return 0; - } - - src_iovs[iovecs_used].iov_len = iov_len; - ++iovecs_used; + total_read += rc; } - - ssize_t rc = process_vm_readv(pid, &dst_iov, 1, src_iovs, iovecs_used, 0); - return rc == -1 ? 0 : rc; + return total_read; } static bool PtraceReadLong(pid_t pid, uint64_t addr, long* value) { -- cgit v1.2.3