mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-20 10:43:46 +00:00
linux, x86: Read floating point state via mcontext.fpptr
Floating-point content may not begin at the start of __fpregs_mem and should be located via mcontext.fpptr, which may be `nullptr`. Bug: crashpad:30 Change-Id: Ie3116339d79f6669d757618e9e592f8480dcdcba Reviewed-on: https://chromium-review.googlesource.com/1001332 Reviewed-by: Scott Graham <scottmg@chromium.org> Commit-Queue: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
a3ba96c0d4
commit
914e7f76dd
@ -77,6 +77,8 @@ void InitializeCPUContextX86_NoFloatingPoint(
|
|||||||
CPUContextX86* context) {
|
CPUContextX86* context) {
|
||||||
SET_GPRS32();
|
SET_GPRS32();
|
||||||
|
|
||||||
|
memset(&context->fxsave, 0, sizeof(context->fxsave));
|
||||||
|
|
||||||
context->dr0 = 0;
|
context->dr0 = 0;
|
||||||
context->dr1 = 0;
|
context->dr1 = 0;
|
||||||
context->dr2 = 0;
|
context->dr2 = 0;
|
||||||
@ -152,6 +154,23 @@ void InitializeCPUContextX86_64(const SignalThreadContext64& thread_context,
|
|||||||
context->dr7 = 0;
|
context->dr7 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InitializeCPUContextX86_64_NoFloatingPoint(
|
||||||
|
const SignalThreadContext64& thread_context,
|
||||||
|
CPUContextX86_64* context) {
|
||||||
|
SET_GPRS64();
|
||||||
|
|
||||||
|
memset(&context->fxsave, 0, sizeof(context->fxsave));
|
||||||
|
|
||||||
|
context->dr0 = 0;
|
||||||
|
context->dr1 = 0;
|
||||||
|
context->dr2 = 0;
|
||||||
|
context->dr3 = 0;
|
||||||
|
context->dr4 = 0;
|
||||||
|
context->dr5 = 0;
|
||||||
|
context->dr6 = 0;
|
||||||
|
context->dr7 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined(ARCH_CPU_ARM_FAMILY)
|
#elif defined(ARCH_CPU_ARM_FAMILY)
|
||||||
|
|
||||||
void InitializeCPUContextARM(const ThreadContext::t32_t& thread_context,
|
void InitializeCPUContextARM(const ThreadContext::t32_t& thread_context,
|
||||||
@ -195,6 +214,11 @@ void InitializeCPUContextARM_NoFloatingPoint(
|
|||||||
context->lr = thread_context.lr;
|
context->lr = thread_context.lr;
|
||||||
context->pc = thread_context.pc;
|
context->pc = thread_context.pc;
|
||||||
context->cpsr = thread_context.cpsr;
|
context->cpsr = thread_context.cpsr;
|
||||||
|
|
||||||
|
memset(&context->fpa_regs, 0, sizeof(context->fpa_regs));
|
||||||
|
memset(&context->vfp_regs, 0, sizeof(context->vfp_regs));
|
||||||
|
context->have_fpa_regs = false;
|
||||||
|
context->have_vfp_regs = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeCPUContextARM64(const ThreadContext::t64_t& thread_context,
|
void InitializeCPUContextARM64(const ThreadContext::t64_t& thread_context,
|
||||||
@ -218,6 +242,10 @@ void InitializeCPUContextARM64_NoFloatingPoint(
|
|||||||
context->sp = thread_context.sp;
|
context->sp = thread_context.sp;
|
||||||
context->pc = thread_context.pc;
|
context->pc = thread_context.pc;
|
||||||
context->pstate = thread_context.pstate;
|
context->pstate = thread_context.pstate;
|
||||||
|
|
||||||
|
memset(&context->fpsimd, 0, sizeof(context->fpsimd));
|
||||||
|
context->fpsr = 0;
|
||||||
|
context->fpcr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeCPUContextARM64_OnlyFPSIMD(
|
void InitializeCPUContextARM64_OnlyFPSIMD(
|
||||||
@ -230,12 +258,6 @@ void InitializeCPUContextARM64_OnlyFPSIMD(
|
|||||||
context->fpcr = float_context.fpcr;
|
context->fpcr = float_context.fpcr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeCPUContextARM64_ClearFPSIMD(CPUContextARM64* context) {
|
|
||||||
memset(context->fpsimd, 0, sizeof(context->fpsimd));
|
|
||||||
context->fpsr = 0;
|
|
||||||
context->fpcr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // ARCH_CPU_X86_FAMILY
|
#endif // ARCH_CPU_X86_FAMILY
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
@ -44,8 +44,7 @@ void InitializeCPUContextX86(const SignalThreadContext32& thread_context,
|
|||||||
//! \brief Initializes GPR and debug state in a CPUContextX86 from a native
|
//! \brief Initializes GPR and debug state in a CPUContextX86 from a native
|
||||||
//! signal context structure on Linux.
|
//! signal context structure on Linux.
|
||||||
//!
|
//!
|
||||||
//! Floating point state is not initialized. Debug registers are initialized to
|
//! Floating point state and debug registers are initialized to zero.
|
||||||
//! zero.
|
|
||||||
//!
|
//!
|
||||||
//! \param[in] thread_context The native thread context.
|
//! \param[in] thread_context The native thread context.
|
||||||
//! \param[out] context The CPUContextX86 structure to initialize.
|
//! \param[out] context The CPUContextX86 structure to initialize.
|
||||||
@ -69,6 +68,17 @@ void InitializeCPUContextX86_64(const SignalThreadContext64& thread_context,
|
|||||||
CPUContextX86_64* context);
|
CPUContextX86_64* context);
|
||||||
//! \}
|
//! \}
|
||||||
|
|
||||||
|
//! \brief Initializes GPR and debug state in a CPUContextX86_64 from a native
|
||||||
|
//! signal context structure on Linux.
|
||||||
|
//!
|
||||||
|
//! Floating point state and debug registers are initialized to zero.
|
||||||
|
//!
|
||||||
|
//! \param[in] thread_context The native thread context.
|
||||||
|
//! \param[out] context The CPUContextX86_64 structure to initialize.
|
||||||
|
void InitializeCPUContextX86_64_NoFloatingPoint(
|
||||||
|
const SignalThreadContext64& thread_context,
|
||||||
|
CPUContextX86_64* context);
|
||||||
|
|
||||||
#endif // ARCH_CPU_X86_FAMILY || DOXYGEN
|
#endif // ARCH_CPU_X86_FAMILY || DOXYGEN
|
||||||
|
|
||||||
#if defined(ARCH_CPU_ARM_FAMILY) || DOXYGEN
|
#if defined(ARCH_CPU_ARM_FAMILY) || DOXYGEN
|
||||||
@ -86,7 +96,7 @@ void InitializeCPUContextARM(const ThreadContext::t32_t& thread_context,
|
|||||||
//! \brief Initializes GPR state in a CPUContextARM from a native signal context
|
//! \brief Initializes GPR state in a CPUContextARM from a native signal context
|
||||||
//! structure on Linux.
|
//! structure on Linux.
|
||||||
//!
|
//!
|
||||||
//! Floating point state is not initialized.
|
//! Floating point state is initialized to zero.
|
||||||
//!
|
//!
|
||||||
//! \param[in] thread_context The native thread context.
|
//! \param[in] thread_context The native thread context.
|
||||||
//! \param[out] context The CPUContextARM structure to initialize.
|
//! \param[out] context The CPUContextARM structure to initialize.
|
||||||
@ -107,7 +117,7 @@ void InitializeCPUContextARM64(const ThreadContext::t64_t& thread_context,
|
|||||||
//! \brief Initializes GPR state in a CPUContextARM64 from a native context
|
//! \brief Initializes GPR state in a CPUContextARM64 from a native context
|
||||||
//! structure on Linux.
|
//! structure on Linux.
|
||||||
//!
|
//!
|
||||||
//! Floating point state is not initialized.
|
//! Floating point state is initialized to zero.
|
||||||
//!
|
//!
|
||||||
//! \param[in] thread_context The native thread context.
|
//! \param[in] thread_context The native thread context.
|
||||||
//! \param[out] context The CPUContextARM64 structure to initialize.
|
//! \param[out] context The CPUContextARM64 structure to initialize.
|
||||||
@ -126,13 +136,6 @@ void InitializeCPUContextARM64_OnlyFPSIMD(
|
|||||||
const SignalFPSIMDContext& float_context,
|
const SignalFPSIMDContext& float_context,
|
||||||
CPUContextARM64* context);
|
CPUContextARM64* context);
|
||||||
|
|
||||||
//! \brief Initializes FPSIMD state in a CPUContextARM64 to zero.
|
|
||||||
//!
|
|
||||||
//! General purpose registers are not initialized.
|
|
||||||
//!
|
|
||||||
//! \param[out] context The CPUContextARM64 structure to initialize.
|
|
||||||
void InitializeCPUContextARM64_ClearFPSIMD(CPUContextARM64* context);
|
|
||||||
|
|
||||||
#endif // ARCH_CPU_ARM_FAMILY || DOXYGEN
|
#endif // ARCH_CPU_ARM_FAMILY || DOXYGEN
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
@ -41,6 +41,7 @@ ExceptionSnapshotLinux::ExceptionSnapshotLinux()
|
|||||||
ExceptionSnapshotLinux::~ExceptionSnapshotLinux() {}
|
ExceptionSnapshotLinux::~ExceptionSnapshotLinux() {}
|
||||||
|
|
||||||
#if defined(ARCH_CPU_X86_FAMILY)
|
#if defined(ARCH_CPU_X86_FAMILY)
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
bool ExceptionSnapshotLinux::ReadContext<ContextTraits32>(
|
bool ExceptionSnapshotLinux::ReadContext<ContextTraits32>(
|
||||||
ProcessReaderLinux* reader,
|
ProcessReaderLinux* reader,
|
||||||
@ -54,26 +55,35 @@ bool ExceptionSnapshotLinux::ReadContext<ContextTraits32>(
|
|||||||
context_.architecture = kCPUArchitectureX86;
|
context_.architecture = kCPUArchitectureX86;
|
||||||
context_.x86 = &context_union_.x86;
|
context_.x86 = &context_union_.x86;
|
||||||
|
|
||||||
if (ucontext.fprs.magic == X86_FXSR_MAGIC) {
|
if (!ucontext.mcontext.fpptr) {
|
||||||
if (!reader->Memory()->Read(context_address +
|
InitializeCPUContextX86_NoFloatingPoint(ucontext.mcontext.gprs,
|
||||||
offsetof(UContext<ContextTraits32>, fprs) +
|
context_.x86);
|
||||||
offsetof(SignalFloatContext32, fxsave),
|
return true;
|
||||||
sizeof(CPUContextX86::Fxsave),
|
}
|
||||||
&context_.x86->fxsave)) {
|
|
||||||
|
SignalFloatContext32 fprs;
|
||||||
|
if (!reader->Memory()->Read(ucontext.mcontext.fpptr, sizeof(fprs), &fprs)) {
|
||||||
|
LOG(ERROR) << "Couldn't read float context";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fprs.magic == X86_FXSR_MAGIC) {
|
||||||
|
InitializeCPUContextX86_NoFloatingPoint(ucontext.mcontext.gprs,
|
||||||
|
context_.x86);
|
||||||
|
if (!reader->Memory()->Read(
|
||||||
|
ucontext.mcontext.fpptr + offsetof(SignalFloatContext32, fxsave),
|
||||||
|
sizeof(CPUContextX86::Fxsave),
|
||||||
|
&context_.x86->fxsave)) {
|
||||||
LOG(ERROR) << "Couldn't read fxsave";
|
LOG(ERROR) << "Couldn't read fxsave";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
InitializeCPUContextX86_NoFloatingPoint(ucontext.mcontext.gprs,
|
} else if (fprs.magic == 0xffff) {
|
||||||
context_.x86);
|
InitializeCPUContextX86(ucontext.mcontext.gprs, fprs, context_.x86);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (ucontext.fprs.magic != 0xffff) {
|
LOG(ERROR) << "unexpected magic 0x" << std::hex << fprs.magic;
|
||||||
LOG(ERROR) << "unexpected magic 0x" << std::hex << ucontext.fprs.magic;
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
InitializeCPUContextX86(
|
|
||||||
ucontext.mcontext.gprs, ucontext.fprs, context_.x86);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,8 +100,19 @@ bool ExceptionSnapshotLinux::ReadContext<ContextTraits64>(
|
|||||||
context_.architecture = kCPUArchitectureX86_64;
|
context_.architecture = kCPUArchitectureX86_64;
|
||||||
context_.x86_64 = &context_union_.x86_64;
|
context_.x86_64 = &context_union_.x86_64;
|
||||||
|
|
||||||
InitializeCPUContextX86_64(
|
if (!ucontext.mcontext.fpptr) {
|
||||||
ucontext.mcontext.gprs, ucontext.fprs, context_.x86_64);
|
InitializeCPUContextX86_64_NoFloatingPoint(ucontext.mcontext.gprs,
|
||||||
|
context_.x86_64);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SignalFloatContext64 fprs;
|
||||||
|
if (!reader->Memory()->Read(ucontext.mcontext.fpptr, sizeof(fprs), &fprs)) {
|
||||||
|
LOG(ERROR) << "Couldn't read float context";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitializeCPUContextX86_64(ucontext.mcontext.gprs, fprs, context_.x86_64);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,8 +139,6 @@ bool ExceptionSnapshotLinux::ReadContext<ContextTraits32>(
|
|||||||
}
|
}
|
||||||
InitializeCPUContextARM_NoFloatingPoint(thread_context, dest_context);
|
InitializeCPUContextARM_NoFloatingPoint(thread_context, dest_context);
|
||||||
|
|
||||||
dest_context->have_fpa_regs = false;
|
|
||||||
|
|
||||||
LinuxVMAddress reserved_address =
|
LinuxVMAddress reserved_address =
|
||||||
context_address + offsetof(UContext<ContextTraits32>, reserved);
|
context_address + offsetof(UContext<ContextTraits32>, reserved);
|
||||||
if ((reserved_address & 7) != 0) {
|
if ((reserved_address & 7) != 0) {
|
||||||
@ -134,7 +153,6 @@ bool ExceptionSnapshotLinux::ReadContext<ContextTraits32>(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dest_context->have_vfp_regs = false;
|
|
||||||
do {
|
do {
|
||||||
CoprocessorContextHead head;
|
CoprocessorContextHead head;
|
||||||
if (!range.Read(reserved_address, sizeof(head), &head)) {
|
if (!range.Read(reserved_address, sizeof(head), &head)) {
|
||||||
@ -241,7 +259,6 @@ bool ExceptionSnapshotLinux::ReadContext<ContextTraits64>(
|
|||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
LOG(WARNING) << "fpsimd not found";
|
LOG(WARNING) << "fpsimd not found";
|
||||||
InitializeCPUContextARM64_ClearFPSIMD(dest_context);
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -54,6 +54,7 @@ using NativeCPUContext = FxsaveUContext;
|
|||||||
|
|
||||||
void InitializeContext(NativeCPUContext* context) {
|
void InitializeContext(NativeCPUContext* context) {
|
||||||
context->ucontext.uc_mcontext.gregs[REG_EAX] = 0xabcd1234;
|
context->ucontext.uc_mcontext.gregs[REG_EAX] = 0xabcd1234;
|
||||||
|
context->ucontext.uc_mcontext.fpregs = &context->ucontext.__fpregs_mem;
|
||||||
// glibc and bionic use an unsigned long for status, but the kernel treats
|
// glibc and bionic use an unsigned long for status, but the kernel treats
|
||||||
// status as two uint16_t, with the upper 16 bits called "magic" which, if set
|
// status as two uint16_t, with the upper 16 bits called "magic" which, if set
|
||||||
// to X86_FXSR_MAGIC, indicate that an fxsave follows.
|
// to X86_FXSR_MAGIC, indicate that an fxsave follows.
|
||||||
@ -78,6 +79,7 @@ using NativeCPUContext = ucontext_t;
|
|||||||
|
|
||||||
void InitializeContext(NativeCPUContext* context) {
|
void InitializeContext(NativeCPUContext* context) {
|
||||||
context->uc_mcontext.gregs[REG_RAX] = 0xabcd1234abcd1234;
|
context->uc_mcontext.gregs[REG_RAX] = 0xabcd1234abcd1234;
|
||||||
|
context->uc_mcontext.fpregs = &context->__fpregs_mem;
|
||||||
memset(&context->__fpregs_mem, 44, sizeof(context->__fpregs_mem));
|
memset(&context->__fpregs_mem, 44, sizeof(context->__fpregs_mem));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ struct UContext {
|
|||||||
SignalStack<Traits> stack;
|
SignalStack<Traits> stack;
|
||||||
MContext<Traits> mcontext;
|
MContext<Traits> mcontext;
|
||||||
Sigset<Traits> sigmask;
|
Sigset<Traits> sigmask;
|
||||||
typename Traits::FloatContext fprs;
|
char fpregs_mem[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif defined(ARCH_CPU_ARM_FAMILY)
|
#elif defined(ARCH_CPU_ARM_FAMILY)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user