Author: labath Date: Wed Jun 17 13:38:49 2015 New Revision: 239924 URL: http://llvm.org/viewvc/llvm-project?rev=239924&view=rev Log: [NativeProcessLinux] Use fast memory reads, if the system supports it
Summary: Memory reads using the ptrace API need to be executed on a designated thread and in 4-byte increments. The process_vm_read syscall has no such requirements and it is about 50 times faster. This patch makes lldb-server use the faster API if the target kernel supports it. Kernel support for this feature is determined at runtime. Using process_vm_writev in the same manner is more complicated since this syscall (unlike ptrace) respects page protection settings and so it cannot be used to set a breakpoint, since code pages are typically read-only. However, memory writes are not currently a performance bottleneck as they happen much more rarely. Test Plan: all tests continue to pass Reviewers: ovyalov, vharron Subscribers: tberghammer, lldb-commits Differential Revision: http://reviews.llvm.org/D10488 Added: lldb/trunk/include/lldb/Host/linux/Uio.h Modified: lldb/trunk/source/Host/android/LibcGlue.cpp lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp Added: lldb/trunk/include/lldb/Host/linux/Uio.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/linux/Uio.h?rev=239924&view=auto ============================================================================== --- lldb/trunk/include/lldb/Host/linux/Uio.h (added) +++ lldb/trunk/include/lldb/Host/linux/Uio.h Wed Jun 17 13:38:49 2015 @@ -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 <sys/uio.h> + +// 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_ Modified: lldb/trunk/source/Host/android/LibcGlue.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/android/LibcGlue.cpp?rev=239924&r1=239923&r2=239924&view=diff ============================================================================== --- lldb/trunk/source/Host/android/LibcGlue.cpp (original) +++ lldb/trunk/source/Host/android/LibcGlue.cpp Wed Jun 17 13:38:49 2015 @@ -11,12 +11,14 @@ #include <android/api-level.h> +#include <sys/syscall.h> +#include <lldb/Host/linux/Uio.h> + #if __ANDROID_API__ < 21 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> -#include <sys/syscall.h> #include <signal.h> #include "lldb/Host/Time.h" @@ -37,3 +39,11 @@ int posix_openpt(int flags) } #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); +} Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp?rev=239924&r1=239923&r2=239924&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp (original) +++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp Wed Jun 17 13:38:49 2015 @@ -18,6 +18,7 @@ // C++ Includes #include <fstream> +#include <mutex> #include <sstream> #include <string> #include <unordered_map> @@ -52,14 +53,15 @@ #include <linux/unistd.h> #include <sys/socket.h> +#include <sys/syscall.h> #include <sys/types.h> -#include <sys/uio.h> #include <sys/user.h> #include <sys/wait.h> #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 lldb_private::process_li 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 @@ namespace 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 @@ NativeProcessLinux::RemoveWatchpoint (ll 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<void *>(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 (); _______________________________________________ lldb-commits mailing list lldb-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits