mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-27 15:32:10 +08: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) {
|
||||
SET_GPRS32();
|
||||
|
||||
memset(&context->fxsave, 0, sizeof(context->fxsave));
|
||||
|
||||
context->dr0 = 0;
|
||||
context->dr1 = 0;
|
||||
context->dr2 = 0;
|
||||
@ -152,6 +154,23 @@ void InitializeCPUContextX86_64(const SignalThreadContext64& thread_context,
|
||||
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)
|
||||
|
||||
void InitializeCPUContextARM(const ThreadContext::t32_t& thread_context,
|
||||
@ -195,6 +214,11 @@ void InitializeCPUContextARM_NoFloatingPoint(
|
||||
context->lr = thread_context.lr;
|
||||
context->pc = thread_context.pc;
|
||||
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,
|
||||
@ -218,6 +242,10 @@ void InitializeCPUContextARM64_NoFloatingPoint(
|
||||
context->sp = thread_context.sp;
|
||||
context->pc = thread_context.pc;
|
||||
context->pstate = thread_context.pstate;
|
||||
|
||||
memset(&context->fpsimd, 0, sizeof(context->fpsimd));
|
||||
context->fpsr = 0;
|
||||
context->fpcr = 0;
|
||||
}
|
||||
|
||||
void InitializeCPUContextARM64_OnlyFPSIMD(
|
||||
@ -230,12 +258,6 @@ void InitializeCPUContextARM64_OnlyFPSIMD(
|
||||
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
|
||||
|
||||
} // namespace internal
|
||||
|
@ -44,8 +44,7 @@ void InitializeCPUContextX86(const SignalThreadContext32& thread_context,
|
||||
//! \brief Initializes GPR and debug state in a CPUContextX86 from a native
|
||||
//! signal context structure on Linux.
|
||||
//!
|
||||
//! Floating point state is not initialized. Debug registers are initialized to
|
||||
//! zero.
|
||||
//! Floating point state and debug registers are initialized to zero.
|
||||
//!
|
||||
//! \param[in] thread_context The native thread context.
|
||||
//! \param[out] context The CPUContextX86 structure to initialize.
|
||||
@ -69,6 +68,17 @@ void InitializeCPUContextX86_64(const SignalThreadContext64& thread_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
|
||||
|
||||
#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
|
||||
//! 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[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
|
||||
//! 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[out] context The CPUContextARM64 structure to initialize.
|
||||
@ -126,13 +136,6 @@ void InitializeCPUContextARM64_OnlyFPSIMD(
|
||||
const SignalFPSIMDContext& float_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
|
||||
|
||||
} // namespace internal
|
||||
|
@ -41,6 +41,7 @@ ExceptionSnapshotLinux::ExceptionSnapshotLinux()
|
||||
ExceptionSnapshotLinux::~ExceptionSnapshotLinux() {}
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
|
||||
template <>
|
||||
bool ExceptionSnapshotLinux::ReadContext<ContextTraits32>(
|
||||
ProcessReaderLinux* reader,
|
||||
@ -54,26 +55,35 @@ bool ExceptionSnapshotLinux::ReadContext<ContextTraits32>(
|
||||
context_.architecture = kCPUArchitectureX86;
|
||||
context_.x86 = &context_union_.x86;
|
||||
|
||||
if (ucontext.fprs.magic == X86_FXSR_MAGIC) {
|
||||
if (!reader->Memory()->Read(context_address +
|
||||
offsetof(UContext<ContextTraits32>, fprs) +
|
||||
offsetof(SignalFloatContext32, fxsave),
|
||||
sizeof(CPUContextX86::Fxsave),
|
||||
&context_.x86->fxsave)) {
|
||||
if (!ucontext.mcontext.fpptr) {
|
||||
InitializeCPUContextX86_NoFloatingPoint(ucontext.mcontext.gprs,
|
||||
context_.x86);
|
||||
return true;
|
||||
}
|
||||
|
||||
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";
|
||||
return false;
|
||||
}
|
||||
InitializeCPUContextX86_NoFloatingPoint(ucontext.mcontext.gprs,
|
||||
context_.x86);
|
||||
|
||||
} else if (fprs.magic == 0xffff) {
|
||||
InitializeCPUContextX86(ucontext.mcontext.gprs, fprs, context_.x86);
|
||||
} else {
|
||||
if (ucontext.fprs.magic != 0xffff) {
|
||||
LOG(ERROR) << "unexpected magic 0x" << std::hex << ucontext.fprs.magic;
|
||||
return false;
|
||||
}
|
||||
InitializeCPUContextX86(
|
||||
ucontext.mcontext.gprs, ucontext.fprs, context_.x86);
|
||||
LOG(ERROR) << "unexpected magic 0x" << std::hex << fprs.magic;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -90,8 +100,19 @@ bool ExceptionSnapshotLinux::ReadContext<ContextTraits64>(
|
||||
context_.architecture = kCPUArchitectureX86_64;
|
||||
context_.x86_64 = &context_union_.x86_64;
|
||||
|
||||
InitializeCPUContextX86_64(
|
||||
ucontext.mcontext.gprs, ucontext.fprs, context_.x86_64);
|
||||
if (!ucontext.mcontext.fpptr) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -118,8 +139,6 @@ bool ExceptionSnapshotLinux::ReadContext<ContextTraits32>(
|
||||
}
|
||||
InitializeCPUContextARM_NoFloatingPoint(thread_context, dest_context);
|
||||
|
||||
dest_context->have_fpa_regs = false;
|
||||
|
||||
LinuxVMAddress reserved_address =
|
||||
context_address + offsetof(UContext<ContextTraits32>, reserved);
|
||||
if ((reserved_address & 7) != 0) {
|
||||
@ -134,7 +153,6 @@ bool ExceptionSnapshotLinux::ReadContext<ContextTraits32>(
|
||||
return false;
|
||||
}
|
||||
|
||||
dest_context->have_vfp_regs = false;
|
||||
do {
|
||||
CoprocessorContextHead head;
|
||||
if (!range.Read(reserved_address, sizeof(head), &head)) {
|
||||
@ -241,7 +259,6 @@ bool ExceptionSnapshotLinux::ReadContext<ContextTraits64>(
|
||||
|
||||
case 0:
|
||||
LOG(WARNING) << "fpsimd not found";
|
||||
InitializeCPUContextARM64_ClearFPSIMD(dest_context);
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
@ -54,6 +54,7 @@ using NativeCPUContext = FxsaveUContext;
|
||||
|
||||
void InitializeContext(NativeCPUContext* context) {
|
||||
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
|
||||
// status as two uint16_t, with the upper 16 bits called "magic" which, if set
|
||||
// to X86_FXSR_MAGIC, indicate that an fxsave follows.
|
||||
@ -78,6 +79,7 @@ using NativeCPUContext = ucontext_t;
|
||||
|
||||
void InitializeContext(NativeCPUContext* context) {
|
||||
context->uc_mcontext.gregs[REG_RAX] = 0xabcd1234abcd1234;
|
||||
context->uc_mcontext.fpregs = &context->__fpregs_mem;
|
||||
memset(&context->__fpregs_mem, 44, sizeof(context->__fpregs_mem));
|
||||
}
|
||||
|
||||
|
@ -206,7 +206,7 @@ struct UContext {
|
||||
SignalStack<Traits> stack;
|
||||
MContext<Traits> mcontext;
|
||||
Sigset<Traits> sigmask;
|
||||
typename Traits::FloatContext fprs;
|
||||
char fpregs_mem[0];
|
||||
};
|
||||
|
||||
#elif defined(ARCH_CPU_ARM_FAMILY)
|
||||
|
Loading…
x
Reference in New Issue
Block a user