blob: 5b55c24a76d5213ae8fa1edb527c987155bc8371 [file] [log] [blame]
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_UTIL_LINUX_THREAD_INFO_H_
#define CRASHPAD_UTIL_LINUX_THREAD_INFO_H_
#include <stdint.h>
#include <sys/user.h>
#include <type_traits>
#include "build/build_config.h"
#include "util/linux/address_types.h"
#include "util/numeric/int128.h"
#if defined(OS_ANDROID)
#include <android/api-level.h>
#endif
namespace crashpad {
//! \brief The set of general purpose registers for an architecture family.
union ThreadContext {
ThreadContext();
~ThreadContext();
//! \brief The general purpose registers used by the 32-bit variant of the
//! architecture.
struct t32_t {
#if defined(ARCH_CPU_X86_FAMILY)
// Reflects user_regs_struct in sys/user.h.
uint32_t ebx;
uint32_t ecx;
uint32_t edx;
uint32_t esi;
uint32_t edi;
uint32_t ebp;
uint32_t eax;
uint32_t xds;
uint32_t xes;
uint32_t xfs;
uint32_t xgs;
uint32_t orig_eax;
uint32_t eip;
uint32_t xcs;
uint32_t eflags;
uint32_t esp;
uint32_t xss;
#elif defined(ARCH_CPU_ARM_FAMILY)
// Reflects user_regs in sys/user.h.
uint32_t regs[11];
uint32_t fp;
uint32_t ip;
uint32_t sp;
uint32_t lr;
uint32_t pc;
uint32_t cpsr;
uint32_t orig_r0;
#elif defined(ARCH_CPU_MIPS_FAMILY)
// Reflects output format of static int gpr32_get(), defined in
// arch/mips/kernel/ptrace.c in kernel source
uint32_t padding0_[6];
uint32_t regs[32];
uint32_t lo;
uint32_t hi;
uint32_t cp0_epc;
uint32_t cp0_badvaddr;
uint32_t cp0_status;
uint32_t cp0_cause;
uint32_t padding1_;
#else
#error Port.
#endif // ARCH_CPU_X86_FAMILY
} t32;
//! \brief The general purpose registers used by the 64-bit variant of the
//! architecture.
struct t64_t {
#if defined(ARCH_CPU_X86_FAMILY)
// Reflects user_regs_struct in sys/user.h.
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
uint64_t rbp;
uint64_t rbx;
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
uint64_t rax;
uint64_t rcx;
uint64_t rdx;
uint64_t rsi;
uint64_t rdi;
uint64_t orig_rax;
uint64_t rip;
uint64_t cs;
uint64_t eflags;
uint64_t rsp;
uint64_t ss;
uint64_t fs_base;
uint64_t gs_base;
uint64_t ds;
uint64_t es;
uint64_t fs;
uint64_t gs;
#elif defined(ARCH_CPU_ARM_FAMILY)
// Reflects user_regs_struct in sys/user.h.
uint64_t regs[31];
uint64_t sp;
uint64_t pc;
uint64_t pstate;
#elif defined(ARCH_CPU_MIPS_FAMILY)
// Reflects output format of static int gpr64_get(), defined in
// arch/mips/kernel/ptrace.c in kernel source
uint64_t regs[32];
uint64_t lo;
uint64_t hi;
uint64_t cp0_epc;
uint64_t cp0_badvaddr;
uint64_t cp0_status;
uint64_t cp0_cause;
#else
#error Port.
#endif // ARCH_CPU_X86_FAMILY
} t64;
#if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM64)
using NativeThreadContext = user_regs_struct;
#elif defined(ARCH_CPU_ARMEL)
using NativeThreadContext = user_regs;
#elif defined(ARCH_CPU_MIPS_FAMILY)
// No appropriate NativeThreadsContext type available for MIPS
#else
#error Port.
#endif // ARCH_CPU_X86_FAMILY || ARCH_CPU_ARM64
#if !defined(ARCH_CPU_MIPS_FAMILY)
#if defined(ARCH_CPU_32_BITS)
static_assert(sizeof(t32_t) == sizeof(NativeThreadContext), "Size mismatch");
#else // ARCH_CPU_64_BITS
static_assert(sizeof(t64_t) == sizeof(NativeThreadContext), "Size mismatch");
#endif // ARCH_CPU_32_BITS
#endif // !ARCH_CPU_MIPS_FAMILY
};
static_assert(std::is_standard_layout<ThreadContext>::value,
"Not standard layout");
//! \brief The floating point registers used for an architecture family.
union FloatContext {
FloatContext();
~FloatContext();
//! \brief The floating point registers used by the 32-bit variant of the
//! architecture.
struct f32_t {
#if defined(ARCH_CPU_X86_FAMILY)
// Reflects user_fpxregs_struct in sys/user.h
struct fxsave {
uint16_t cwd;
uint16_t swd;
uint16_t twd;
uint16_t fop;
uint32_t fip;
uint32_t fcs;
uint32_t foo;
uint32_t fos;
uint32_t mxcsr;
uint32_t reserved;
uint32_t st_space[32];
uint32_t xmm_space[32];
uint32_t padding[56];
} fxsave;
#elif defined(ARCH_CPU_ARM_FAMILY)
// Reflects user_fpregs in sys/user.h.
struct fpregs {
struct fp_reg {
uint32_t sign1 : 1;
uint32_t unused : 15;
uint32_t sign2 : 1;
uint32_t exponent : 14;
uint32_t j : 1;
uint32_t mantissa1 : 31;
uint32_t mantisss0 : 32;
} fpregs[8];
uint32_t fpsr : 32;
uint32_t fpcr : 32;
uint8_t type[8];
uint32_t init_flag;
} fpregs;
// Reflects user_vfp in sys/user.h.
struct vfp_t {
uint64_t fpregs[32];
uint32_t fpscr;
} vfp;
bool have_fpregs;
bool have_vfp;
#elif defined(ARCH_CPU_MIPS_FAMILY)
// Reflects data format filled by ptrace_getfpregs() in
// arch/mips/kernel/ptrace.c
struct {
float _fp_fregs;
unsigned int _fp_pad;
} fpregs[32];
uint32_t fpcsr;
uint32_t fpu_id;
#else
#error Port.
#endif // ARCH_CPU_X86_FAMILY
} f32;
//! \brief The floating point registers used by the 64-bit variant of the
//! architecture.
struct f64_t {
#if defined(ARCH_CPU_X86_FAMILY)
// Refelects user_fpregs_struct in sys/user.h
struct fxsave {
uint16_t cwd;
uint16_t swd;
uint16_t ftw;
uint16_t fop;
uint64_t rip;
uint64_t rdp;
uint32_t mxcsr;
uint32_t mxcr_mask;
uint32_t st_space[32];
uint32_t xmm_space[64];
uint32_t padding[24];
} fxsave;
#elif defined(ARCH_CPU_ARM_FAMILY)
uint128_struct vregs[32];
uint32_t fpsr;
uint32_t fpcr;
uint8_t padding[8];
#elif defined(ARCH_CPU_MIPS_FAMILY)
// Reflects data format filled by ptrace_getfpregs() in
// arch/mips/kernel/ptrace.c
double fpregs[32];
uint32_t fpcsr;
uint32_t fpu_id;
#else
#error Port.
#endif // ARCH_CPU_X86_FAMILY
} f64;
#if defined(ARCH_CPU_X86)
// __ANDROID_API_N__ is a proxy for determining whether unified headers are in
// use. It’s only defined by unified headers. Unified headers call this
// structure user_fpxregs_struct regardless of API level.
#if defined(OS_ANDROID) && __ANDROID_API__ <= 19 && !defined(__ANDROID_API_N__)
using NativeFpxregs = user_fxsr_struct;
#else
using NativeFpxregs = user_fpxregs_struct;
#endif // OS_ANDROID
static_assert(sizeof(f32_t::fxsave) == sizeof(NativeFpxregs),
"Size mismatch");
#elif defined(ARCH_CPU_X86_64)
static_assert(sizeof(f64_t::fxsave) == sizeof(user_fpregs_struct),
"Size mismatch");
#elif defined(ARCH_CPU_ARMEL)
static_assert(sizeof(f32_t::fpregs) == sizeof(user_fpregs), "Size mismatch");
#if !defined(__GLIBC__)
static_assert(sizeof(f32_t::vfp) == sizeof(user_vfp), "Size mismatch");
#endif
#elif defined(ARCH_CPU_ARM64)
static_assert(sizeof(f64) == sizeof(user_fpsimd_struct), "Size mismatch");
#elif defined(ARCH_CPU_MIPS_FAMILY)
// No appropriate floating point context native type for available MIPS.
#else
#error Port.
#endif // ARCH_CPU_X86
};
static_assert(std::is_standard_layout<FloatContext>::value,
"Not standard layout");
//! \brief A collection of `ptrace`-able information about a thread.
struct ThreadInfo {
ThreadInfo();
~ThreadInfo();
//! \brief The general purpose registers for the thread.
ThreadContext thread_context;
//! \brief The floating point registers for the thread.
FloatContext float_context;
//! \brief The thread-local storage address for the thread.
LinuxVMAddress thread_specific_data_address;
};
} // namespace crashpad
#endif // CRASHPAD_UTIL_LINUX_THREAD_INFO_H_