linux: Use user_regs instead of pt_regs for 32-bit ARM in ProcessInfo

Not all libc implementations reliably expose pt_regs from
<sys/ptrace.h>. glibc-2.25/sysdeps/generic/sys/ptrace.h, for example,
does not #include <asm/ptrace.h> (which defines the structure) or
anything else that would #include that file such as <linux/ptrace.h>. On
the other hand, Android 7.1.1 bionic/libc/include/sys/ptrace.h does
#include <linux/ptrace.h>.

It is not viable to #include <asm/ptrace.h> or <linux/ptrace.h>
directly: it would be natural to #include them, sorted, before
<sys/ptrace.h> but this causes problems for glibc’s <sys/ptrace.h>.
Constants like PTRACE_GETREGS and PTRACE_TRACEME are simple macros in
<asm/ptrace.h> and <linux/ptrace.h>, respectively, but are defined in
enums in glibc’s <sys/ptrace.h>, and this doesn’t mix well. It is
possible to #include <asm/ptrace.h> (but not <linux/ptrace.h>) after
<sys/ptrace.h>, but because this involves same-value macro redefinitions
and because it reaches into internal headers, it’s not preferred.

The alternative approach taken here is to use the user_regs structure
from <sys/user.h>, which is reliably defined by both Bionic and glibc,
and has the same layout as the kernel’s pt_regs structure. (All that
matters in this code is the size of the structure.) See Android 7.1.1
bionic/libc/include/sys/user.h,
glibc-2.25/sysdeps/unix/sysv/linux/arm/sys/user.h, and
linux-4.9.15/arch/arm/include/asm/ptrace.h for the various equivalent
definitions.

Take the same approach for 64-bit ARM: use user_regs_struct from
<sys/user.h> in preference to hoping for a C library’s <sys/ptrace.h> to
somehow provide the kernel’s user_pt_regs.

This mirrors the approach already being used for x86 and x86_64, which
use the C library’s <sys/user.h> user_regs_struct.

Bug: crashpad:30
Test: crashpad_util_test ProcessInfo.*
Change-Id: I3067e32c7fa4d6c8f4f2d5b63df141a0f490cd13
Reviewed-on: https://chromium-review.googlesource.com/455558
Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
Mark Mentovai 2017-03-15 12:05:02 -04:00
parent 9be4745be0
commit d7467ba7e4

View File

@ -342,12 +342,10 @@ bool ProcessInfo::Is64Bit(bool* is_64_bit) const {
// more/larger registers than this process. If the kernel fills less space // more/larger registers than this process. If the kernel fills less space
// than sizeof(regs) then the target process uses smaller/fewer registers. // than sizeof(regs) then the target process uses smaller/fewer registers.
struct { struct {
#if defined(ARCH_CPU_X86_FAMILY) #if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM64)
using PrStatusType = user_regs_struct; using PrStatusType = user_regs_struct;
#elif defined(ARCH_CPU_ARMEL) #elif defined(ARCH_CPU_ARMEL)
using PrStatusType = pt_regs; using PrStatusType = user_regs;
#elif defined(ARCH_CPU_ARM64)
using PrStatusType = user_pt_regs;
#endif #endif
PrStatusType regs; PrStatusType regs;
char extra; char extra;