From b8122152d5d2aa7727a195074c7893f6ff149f62 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Fri, 25 Jun 2021 16:10:17 +0200 Subject: [PATCH 1/4] fix: Use the correct syscall for process_vm_readv --- Memory.cpp | 37 ++++++++++++++++++------------------- Unwinder.cpp | 4 +++- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/Memory.cpp b/Memory.cpp index 456b9f5..6dfc5cf 100644 --- a/Memory.cpp +++ b/Memory.cpp @@ -14,6 +14,9 @@ * limitations under the License. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif #include #include #include @@ -26,16 +29,6 @@ #include #include "unistdfix.h" #include -#ifndef __NR_process_vm_readv -#ifdef __i386__ -#define __NR_process_vm_readv 347 -#elif defined(__ILP32__) -#define __X32_SYSCALL_BIT 0x40000000 -#define __NR_process_vm_readv (__X32_SYSCALL_BIT + 539) -#else -#define __NR_process_vm_readv 310 -#endif -#endif #include #include @@ -54,6 +47,19 @@ #include "MemoryRange.h" #include "MemoryRemote.h" +#ifdef __ANDROID_API__ +# if __ANDROID_API__ < 23 +static ssize_t +process_vm_readv(pid_t __pid, const struct iovec *__local_iov, + unsigned long __local_iov_count, const struct iovec *__remote_iov, + unsigned long __remote_iov_count, unsigned long __flags) +{ + return syscall(__NR_process_vm_readv, __pid, __local_iov, __local_iov_count, + __remote_iov, __remote_iov_count, __flags); +} +# endif +#endif + namespace unwindstack { static size_t ProcessVmRead(pid_t pid, uint64_t remote_src, void* dst, size_t len) { @@ -103,7 +109,7 @@ static size_t ProcessVmRead(pid_t pid, uint64_t remote_src, void* dst, size_t le ++iovecs_used; } - ssize_t rc = syscall(__NR_process_vm_readv, pid, &dst_iov, 1, src_iovs, iovecs_used, 0); + ssize_t rc = process_vm_readv(pid, &dst_iov, 1, src_iovs, iovecs_used, 0); if (rc == -1) { return total_read; } @@ -344,14 +350,7 @@ size_t MemoryRemote::Read(uint64_t addr, void* dst, size_t size) { } size_t MemoryLocal::Read(uint64_t addr, void* dst, size_t size) { - // Prefer process_vm_read, try it first. If it doesn't work, use direct - // memory read. - size_t result = ProcessVmRead(getpid(), addr, dst, size); - if (!result && size) { - memcpy(dst, (void *)addr, size); - result = size; - } - return result; + return ProcessVmRead(getpid(), addr, dst, size); } MemoryRange::MemoryRange(const std::shared_ptr& memory, uint64_t begin, uint64_t length, diff --git a/Unwinder.cpp b/Unwinder.cpp index 8a5de0b..9c86e8a 100644 --- a/Unwinder.cpp +++ b/Unwinder.cpp @@ -14,7 +14,9 @@ * limitations under the License. */ -#define _GNU_SOURCE 1 +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif #include #include #include From c6c11ba96fb407b56eaec5bd8ca8251fdebaf53e Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Fri, 25 Jun 2021 16:36:51 +0200 Subject: [PATCH 2/4] bump build-time requirement to NDK 20 --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b6c5e6e..735f44e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,12 +12,12 @@ jobs: fail-fast: false matrix: include: - - name: Android (API 16, NDK 19) + - name: Android (API 16, NDK 20) ANDROID_API: 16 - ANDROID_NDK: 19.2.5345600 - - name: Android (API 30 NDK 21) + ANDROID_NDK: 20.1.5948944 + - name: Android (API 30, NDK 22) ANDROID_API: 30 - ANDROID_NDK: 21.3.6528147 + ANDROID_NDK: 22.1.7171670 runs-on: macos-latest From 329250bd68e4bb8f0ffb027171fbd1b8576f8782 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Mon, 28 Jun 2021 12:03:14 +0200 Subject: [PATCH 3/4] fall back to memcpy on old Android --- Memory.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Memory.cpp b/Memory.cpp index 6dfc5cf..6da7818 100644 --- a/Memory.cpp +++ b/Memory.cpp @@ -350,7 +350,17 @@ size_t MemoryRemote::Read(uint64_t addr, void* dst, size_t size) { } size_t MemoryLocal::Read(uint64_t addr, void* dst, size_t size) { - return ProcessVmRead(getpid(), addr, dst, size); + errno = 0; + size_t rv = ProcessVmRead(getpid(), addr, dst, size); + // The syscall is only available in Linux 3.2, meaning Android 17. + // If that is the case, just fall back to an unsafe memcpy. +#if __ANDROID_API__ < 17 + if (rv != size && errno == EINVAL) { + memcpy(dst, (void*)addr, size); + rv = size; + } +#endif + return rv; } MemoryRange::MemoryRange(const std::shared_ptr& memory, uint64_t begin, uint64_t length, From a383f9776c6e103fa59cc44ed38b15eeed096e0f Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Mon, 28 Jun 2021 12:10:02 +0200 Subject: [PATCH 4/4] simplify ifdefs --- Memory.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Memory.cpp b/Memory.cpp index 6da7818..0c9752d 100644 --- a/Memory.cpp +++ b/Memory.cpp @@ -47,8 +47,7 @@ #include "MemoryRange.h" #include "MemoryRemote.h" -#ifdef __ANDROID_API__ -# if __ANDROID_API__ < 23 +#if defined(__ANDROID_API__) && __ANDROID_API__ < 23 static ssize_t process_vm_readv(pid_t __pid, const struct iovec *__local_iov, unsigned long __local_iov_count, const struct iovec *__remote_iov, @@ -57,7 +56,6 @@ process_vm_readv(pid_t __pid, const struct iovec *__local_iov, return syscall(__NR_process_vm_readv, __pid, __local_iov, __local_iov_count, __remote_iov, __remote_iov_count, __flags); } -# endif #endif namespace unwindstack { @@ -354,7 +352,7 @@ size_t MemoryLocal::Read(uint64_t addr, void* dst, size_t size) { size_t rv = ProcessVmRead(getpid(), addr, dst, size); // The syscall is only available in Linux 3.2, meaning Android 17. // If that is the case, just fall back to an unsafe memcpy. -#if __ANDROID_API__ < 17 +#if defined(__ANDROID_API__) && __ANDROID_API__ < 17 if (rv != size && errno == EINVAL) { memcpy(dst, (void*)addr, size); rv = size;