Index: lldb/trunk/include/lldb/Host/linux/Uio.h =================================================================== --- lldb/trunk/include/lldb/Host/linux/Uio.h +++ lldb/trunk/include/lldb/Host/linux/Uio.h @@ -0,0 +1,23 @@ +//===-- Uio.h ---------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Host_linux_Uio_h_ +#define liblldb_Host_linux_Uio_h_ + +#include + +// Android does not define the process_vm_readv wrapper +#ifdef __ANDROID_NDK__ +ssize_t process_vm_readv(::pid_t pid, + const struct iovec *local_iov, unsigned long liovcnt, + const struct iovec *remote_iov, unsigned long riovcnt, + unsigned long flags); +#endif + +#endif // liblldb_Host_linux_Uio_h_ Index: lldb/trunk/source/Host/android/LibcGlue.cpp =================================================================== --- lldb/trunk/source/Host/android/LibcGlue.cpp +++ lldb/trunk/source/Host/android/LibcGlue.cpp @@ -11,12 +11,14 @@ #include +#include +#include + #if __ANDROID_API__ < 21 #include #include #include -#include #include #include "lldb/Host/Time.h" @@ -37,3 +39,11 @@ } #endif + +ssize_t process_vm_readv(::pid_t pid, + const struct iovec *local_iov, unsigned long liovcnt, + const struct iovec *remote_iov, unsigned long riovcnt, + unsigned long flags) +{ + return syscall(__NR_process_vm_readv, pid, local_iov, liovcnt, remote_iov, riovcnt, flags); +} Index: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -18,6 +18,7 @@ // C++ Includes #include +#include #include #include #include @@ -52,14 +53,15 @@ #include #include +#include #include -#include #include #include #include "lldb/Host/linux/Personality.h" #include "lldb/Host/linux/Ptrace.h" #include "lldb/Host/linux/Signalfd.h" +#include "lldb/Host/linux/Uio.h" #include "lldb/Host/android/Android.h" #define LLDB_PERSONALITY_GET_CURRENT_SETTINGS 0xffffffff @@ -75,6 +77,40 @@ using namespace llvm; // Private bits we only need internally. + +static bool ProcessVmReadvSupported() +{ + static bool is_supported; + static std::once_flag flag; + + std::call_once(flag, [] { + Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); + + uint32_t source = 0x47424742; + uint32_t dest = 0; + + struct iovec local, remote; + remote.iov_base = &source; + local.iov_base = &dest; + remote.iov_len = local.iov_len = sizeof source; + + // We shall try if cross-process-memory reads work by attempting to read a value from our own process. + ssize_t res = process_vm_readv(getpid(), &local, 1, &remote, 1, 0); + is_supported = (res == sizeof(source) && source == dest); + if (log) + { + if (is_supported) + log->Printf("%s: Detected kernel support for process_vm_readv syscall. Fast memory reads enabled.", + __FUNCTION__); + else + log->Printf("%s: syscall process_vm_readv failed (error: %s). Fast memory reads disabled.", + __FUNCTION__, strerror(errno)); + } + }); + + return is_supported; +} + namespace { const UnixSignals& @@ -242,7 +278,6 @@ log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, (void*)vm_addr, print_dst, (unsigned long)data); } - vm_addr += word_size; dst += word_size; } @@ -3245,6 +3280,32 @@ Error NativeProcessLinux::ReadMemory (lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) { + 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. + + const ::pid_t pid = GetID(); + + struct iovec local_iov, remote_iov; + local_iov.iov_base = buf; + local_iov.iov_len = size; + 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; + + Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf ("NativeProcessLinux::%s using process_vm_readv to read %zd bytes from inferior address 0x%" PRIx64": %s", + __FUNCTION__, size, addr, success ? "Success" : strerror(errno)); + + if (success) + return Error(); + // else + // the call failed for some reason, let's retry the read using ptrace api. + } + ReadOperation op(addr, buf, size, bytes_read); m_monitor_up->DoOperation(&op); return op.GetError ();