// Copyright 2014 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_MINIDUMP_MINIDUMP_CONTEXT_H_ #define CRASHPAD_MINIDUMP_MINIDUMP_CONTEXT_H_ #include #include "base/compiler_specific.h" #include "snapshot/cpu_context.h" #include "util/numeric/int128.h" namespace crashpad { //! \brief Architecture-independent flags for `context_flags` fields in Minidump //! context structures. // // https://zachsaw.blogspot.com/2010/11/wow64-bug-getthreadcontext-may-return.html#c5639760895973344002 enum MinidumpContextFlags : uint32_t { //! \brief The thread was executing a trap handler in kernel mode //! (`CONTEXT_EXCEPTION_ACTIVE`). //! //! If this bit is set, it indicates that the context is from a thread that //! was executing a trap handler in the kernel. This bit is only valid when //! ::kMinidumpContextExceptionReporting is also set. This bit is only used on //! Windows. kMinidumpContextExceptionActive = 0x08000000, //! \brief The thread was executing a system call in kernel mode //! (`CONTEXT_SERVICE_ACTIVE`). //! //! If this bit is set, it indicates that the context is from a thread that //! was executing a system call in the kernel. This bit is only valid when //! ::kMinidumpContextExceptionReporting is also set. This bit is only used on //! Windows. kMinidumpContextServiceActive = 0x10000000, //! \brief Kernel-mode state reporting is desired //! (`CONTEXT_EXCEPTION_REQUEST`). //! //! This bit is not used in context structures containing snapshots of thread //! CPU context. It used when calling `GetThreadContext()` on Windows to //! specify that kernel-mode state reporting //! (::kMinidumpContextExceptionReporting) is desired in the returned context //! structure. kMinidumpContextExceptionRequest = 0x40000000, //! \brief Kernel-mode state reporting is provided //! (`CONTEXT_EXCEPTION_REPORTING`). //! //! If this bit is set, it indicates that the bits indicating how the thread //! had entered kernel mode (::kMinidumpContextExceptionActive and //! ::kMinidumpContextServiceActive) are valid. This bit is only used on //! Windows. kMinidumpContextExceptionReporting = 0x80000000, }; //! \brief 32-bit x86-specifc flags for MinidumpContextX86::context_flags. enum MinidumpContextX86Flags : uint32_t { //! \brief Identifies the context structure as 32-bit x86. This is the same as //! `CONTEXT_i386` and `CONTEXT_i486` on Windows for this architecture. kMinidumpContextX86 = 0x00010000, //! \brief Indicates the validity of control registers (`CONTEXT_CONTROL`). //! //! The `ebp`, `eip`, `cs`, `eflags`, `esp`, and `ss` fields are valid. kMinidumpContextX86Control = kMinidumpContextX86 | 0x00000001, //! \brief Indicates the validity of non-control integer registers //! (`CONTEXT_INTEGER`). //! //! The `edi`, `esi`, `ebx`, `edx`, `ecx, and `eax` fields are valid. kMinidumpContextX86Integer = kMinidumpContextX86 | 0x00000002, //! \brief Indicates the validity of non-control segment registers //! (`CONTEXT_SEGMENTS`). //! //! The `gs`, `fs`, `es`, and `ds` fields are valid. kMinidumpContextX86Segment = kMinidumpContextX86 | 0x00000004, //! \brief Indicates the validity of floating-point state //! (`CONTEXT_FLOATING_POINT`). //! //! The `fsave` field is valid. The `float_save` field is included in this //! definition, but its members have no practical use asdie from `fsave`. kMinidumpContextX86FloatingPoint = kMinidumpContextX86 | 0x00000008, //! \brief Indicates the validity of debug registers //! (`CONTEXT_DEBUG_REGISTERS`). //! //! The `dr0` through `dr3`, `dr6`, and `dr7` fields are valid. kMinidumpContextX86Debug = kMinidumpContextX86 | 0x00000010, //! \brief Indicates the validity of extended registers in `fxsave` format //! (`CONTEXT_EXTENDED_REGISTERS`). //! //! The `extended_registers` field is valid and contains `fxsave` data. kMinidumpContextX86Extended = kMinidumpContextX86 | 0x00000020, //! \brief Indicates the validity of `xsave` data (`CONTEXT_XSTATE`). //! //! The context contains `xsave` data. This is used with an extended context //! structure not currently defined here. kMinidumpContextX86Xstate = kMinidumpContextX86 | 0x00000040, //! \brief Indicates the validity of control, integer, and segment registers. //! (`CONTEXT_FULL`). kMinidumpContextX86Full = kMinidumpContextX86Control | kMinidumpContextX86Integer | kMinidumpContextX86Segment, //! \brief Indicates the validity of all registers except `xsave` data. //! (`CONTEXT_ALL`). kMinidumpContextX86All = kMinidumpContextX86Full | kMinidumpContextX86FloatingPoint | kMinidumpContextX86Debug | kMinidumpContextX86Extended, }; //! \brief A 32-bit x86 CPU context (register state) carried in a minidump file. //! //! This is analogous to the `CONTEXT` structure on Windows when targeting //! 32-bit x86, and the `WOW64_CONTEXT` structure when targeting an x86-family //! CPU, either 32- or 64-bit. This structure is used instead of `CONTEXT` or //! `WOW64_CONTEXT` to make it available when targeting other architectures. //! //! \note This structure doesn’t carry `dr4` or `dr5`, which are obsolete and //! normally alias `dr6` and `dr7`, respectively. See Intel Software //! Developer’s Manual, Volume 3B: System Programming, Part 2 (253669-052), //! 17.2.2 “Debug Registers DR4 and DR5”. struct MinidumpContextX86 { //! \brief A bitfield composed of values of #MinidumpContextFlags and //! #MinidumpContextX86Flags. //! //! This field identifies the context structure as a 32-bit x86 CPU context, //! and indicates which other fields in the structure are valid. uint32_t context_flags; uint32_t dr0; uint32_t dr1; uint32_t dr2; uint32_t dr3; uint32_t dr6; uint32_t dr7; // CPUContextX86::Fsave has identical layout to what the x86 CONTEXT structure // places here. CPUContextX86::Fsave fsave; union { uint32_t spare_0; // As in the native x86 CONTEXT structure since Windows 8 uint32_t cr0_npx_state; // As in WOW64_CONTEXT and older SDKs’ x86 CONTEXT } float_save; uint32_t gs; uint32_t fs; uint32_t es; uint32_t ds; uint32_t edi; uint32_t esi; uint32_t ebx; uint32_t edx; uint32_t ecx; uint32_t eax; uint32_t ebp; uint32_t eip; uint32_t cs; uint32_t eflags; uint32_t esp; uint32_t ss; // CPUContextX86::Fxsave has identical layout to what the x86 CONTEXT // structure places here. CPUContextX86::Fxsave fxsave; }; //! \brief x86_64-specific flags for MinidumpContextAMD64::context_flags. enum MinidumpContextAMD64Flags : uint32_t { //! \brief Identifies the context structure as x86_64. This is the same as //! `CONTEXT_AMD64` on Windows for this architecture. kMinidumpContextAMD64 = 0x00100000, //! \brief Indicates the validity of control registers (`CONTEXT_CONTROL`). //! //! The `cs`, `ss`, `eflags`, `rsp`, and `rip` fields are valid. kMinidumpContextAMD64Control = kMinidumpContextAMD64 | 0x00000001, //! \brief Indicates the validity of non-control integer registers //! (`CONTEXT_INTEGER`). //! //! The `rax`, `rcx`, `rdx`, `rbx`, `rbp`, `rsi`, `rdi`, and `r8` through //! `r15` fields are valid. kMinidumpContextAMD64Integer = kMinidumpContextAMD64 | 0x00000002, //! \brief Indicates the validity of non-control segment registers //! (`CONTEXT_SEGMENTS`). //! //! The `ds`, `es`, `fs`, and `gs` fields are valid. kMinidumpContextAMD64Segment = kMinidumpContextAMD64 | 0x00000004, //! \brief Indicates the validity of floating-point state //! (`CONTEXT_FLOATING_POINT`). //! //! The `xmm0` through `xmm15` fields are valid. kMinidumpContextAMD64FloatingPoint = kMinidumpContextAMD64 | 0x00000008, //! \brief Indicates the validity of debug registers //! (`CONTEXT_DEBUG_REGISTERS`). //! //! The `dr0` through `dr3`, `dr6`, and `dr7` fields are valid. kMinidumpContextAMD64Debug = kMinidumpContextAMD64 | 0x00000010, //! \brief Indicates the validity of `xsave` data (`CONTEXT_XSTATE`). //! //! The context contains `xsave` data. This is used with an extended context //! structure which is partly implemented for CET state only. kMinidumpContextAMD64Xstate = kMinidumpContextAMD64 | 0x00000040, //! \brief Indicates the validity of control, integer, and floating-point //! registers (`CONTEXT_FULL`). kMinidumpContextAMD64Full = kMinidumpContextAMD64Control | kMinidumpContextAMD64Integer | kMinidumpContextAMD64FloatingPoint, //! \brief Indicates the validity of all registers except `xsave` data //! (`CONTEXT_ALL`). kMinidumpContextAMD64All = kMinidumpContextAMD64Full | kMinidumpContextAMD64Segment | kMinidumpContextAMD64Debug, }; //! \brief An x86_64 (AMD64) CPU context (register state) carried in a minidump //! file. //! //! This is analogous to the `CONTEXT` structure on Windows when targeting //! x86_64. This structure is used instead of `CONTEXT` to make it available //! when targeting other architectures. //! //! \note This structure doesn’t carry `dr4` or `dr5`, which are obsolete and //! normally alias `dr6` and `dr7`, respectively. See Intel Software //! Developer’s Manual, Volume 3B: System Programming, Part 2 (253669-052), //! 17.2.2 “Debug Registers DR4 and DR5”. struct alignas(16) MinidumpContextAMD64 { //! \brief Register parameter home address. //! //! On Windows, this field may contain the “home” address (on-stack, in the //! shadow area) of a parameter passed by register. This field is present for //! convenience but is not necessarily populated, even if a corresponding //! parameter was passed by register. //! //! \{ uint64_t p1_home; uint64_t p2_home; uint64_t p3_home; uint64_t p4_home; uint64_t p5_home; uint64_t p6_home; //! \} //! \brief A bitfield composed of values of #MinidumpContextFlags and //! #MinidumpContextAMD64Flags. //! //! This field identifies the context structure as an x86_64 CPU context, and //! indicates which other fields in the structure are valid. uint32_t context_flags; uint32_t mx_csr; uint16_t cs; uint16_t ds; uint16_t es; uint16_t fs; uint16_t gs; uint16_t ss; uint32_t eflags; uint64_t dr0; uint64_t dr1; uint64_t dr2; uint64_t dr3; uint64_t dr6; uint64_t dr7; uint64_t rax; uint64_t rcx; uint64_t rdx; uint64_t rbx; uint64_t rsp; uint64_t rbp; uint64_t rsi; uint64_t rdi; uint64_t r8; uint64_t r9; uint64_t r10; uint64_t r11; uint64_t r12; uint64_t r13; uint64_t r14; uint64_t r15; uint64_t rip; // CPUContextX86_64::Fxsave has identical layout to what the x86_64 CONTEXT // structure places here. CPUContextX86_64::Fxsave fxsave; uint128_struct vector_register[26]; uint64_t vector_control; //! \brief Model-specific debug extension register. //! //! See Intel Software Developer’s Manual, Volume 3B: System Programming, Part //! 2 (253669-051), 17.4 “Last Branch, Interrupt, and Exception Recording //! Overview”, and AMD Architecture Programmer’s Manual, Volume 2: System //! Programming (24593-3.24), 13.1.6 “Control-Transfer Breakpoint Features”. //! //! \{ uint64_t debug_control; uint64_t last_branch_to_rip; uint64_t last_branch_from_rip; uint64_t last_exception_to_rip; uint64_t last_exception_from_rip; //! \} }; //! \brief 32-bit ARM-specifc flags for MinidumpContextARM::context_flags. enum MinidumpContextARMFlags : uint32_t { //! \brief Identifies the context structure as 32-bit ARM. kMinidumpContextARM = 0x40000000, //! \brief Indicates the validity of integer regsiters. //! //! Regsiters `r0`-`r15` and `cpsr` are valid. kMinidumpContextARMInteger = kMinidumpContextARM | 0x00000002, //! \brief Inidicates the validity of VFP regsiters. //! //! Registers `d0`-`d31` and `fpscr` are valid. kMinidumpContextARMVFP = kMinidumpContextARM | 0x00000004, //! \brief Indicates the validity of all registers. kMinidumpContextARMAll = kMinidumpContextARMInteger | kMinidumpContextARMVFP, }; //! \brief A 32-bit ARM CPU context (register state) carried in a minidump file. struct MinidumpContextARM { //! \brief A bitfield composed of values of #MinidumpContextFlags and //! #MinidumpContextARMFlags. //! //! This field identifies the context structure as a 32-bit ARM CPU context, //! and indicates which other fields in the structure are valid. uint32_t context_flags; //! \brief General-purpose registers `r0`-`r15`. uint32_t regs[11]; uint32_t fp; // r11 uint32_t ip; // r12 uint32_t sp; // r13 uint32_t lr; // r14 uint32_t pc; // r15 //! \brief Current program status register. uint32_t cpsr; //! \brief Floating-point status and control register. uint32_t fpscr; //! \brief VFP registers `d0`-`d31`. uint64_t vfp[32]; //! \brief This space is unused. It is included for compatibility with //! breakpad (which also doesn't use it). uint32_t extra[8]; }; //! \brief CONTEXT_CHUNK struct MinidumpContextChunk { int32_t offset; uint32_t size; }; //! \brief CONTEXT_EX struct MinidumpContextExHeader { MinidumpContextChunk all; MinidumpContextChunk legacy; MinidumpContextChunk xstate; }; //! \brief XSAVE_AREA_HEADER struct MinidumpXSaveAreaHeader { uint64_t mask; uint64_t compaction_mask; uint64_t xsave_header_reserved[6]; }; //! \brief Offset of first xsave feature in the full extended context. //! //! This is used to calculate the final size of the extended context, and //! can be validated by calling InitializeContext2 with one XSTATE feature, //! and LocateXStateFeature to determine the first offset. //! Also see "MANAGING STATE USING THE XSAVE FEATURE SET", Ch. 13, Intel SDM. constexpr uint32_t kMinidumpAMD64XSaveOffset = 0x550; //! \brief Offset of first xsave feature within the extended context area. //! //! 0x240 is the size of the legacy area (512) + the xsave header(64 bytes) //! Intel SDM 13.4.1. This is not where the item is in the extended compacted //! context, but is the offset recorded in the minidump. It needs to be correct //! there. See https://windows-internals.com/cet-on-windows/ for some discussion //! "CONTEXT_XSTATE: Extended processor state chunk. The state is stored in the //! same format the XSAVE operation stores it with exception of the first 512 //! bytes, i.e. starting from XSAVE_AREA_HEADER." This may vary by cpuid. constexpr uint32_t kXSaveAreaFirstOffset = 0x240; //! \brief XSAVE_CET_U_FORMAT struct MinidumpAMD64XSaveFormatCetU { uint64_t cetmsr; uint64_t ssp; }; //! \brief 64-bit ARM-specifc flags for MinidumpContextARM64::context_flags. enum MinidumpContextARM64Flags : uint32_t { //! \brief Identifies the context structure as 64-bit ARM. kMinidumpContextARM64 = 0x00400000, //! \brief Indicates the validity of control registers. //! //! Registers `fp`, `lr`, `sp`, `pc`, and `cpsr`. kMinidumpContextARM64Control = kMinidumpContextARM64 | 0x00000001, //! \brief Indicates the validty of integer registers. //! //! Registers `x0`-`x28`. kMinidumpContextARM64Integer = kMinidumpContextARM64 | 0x00000002, //! \brief Indicates the validity of fpsimd registers. //! //! Registers `v0`-`v31`, `fpsr`, and `fpcr` are valid. kMinidumpContextARM64Fpsimd = kMinidumpContextARM64 | 0x00000004, //! \brief Indicates the validity of debug registers. //! //! `bcr`, `bvr`, `wcr`, and `wvr` are valid. kMinidumpContextARM64Debug = kMinidumpContextARM64 | 0x00000008, //! \brief Indicates the validity of control, integer and floating point //! registers. kMinidumpContextARM64Full = kMinidumpContextARM64Control | kMinidumpContextARM64Integer | kMinidumpContextARM64Fpsimd, //! \brief Indicates the validity of all registers. kMinidumpContextARM64All = kMinidumpContextARM64Full | kMinidumpContextARM64Debug, }; //! \brief A 64-bit ARM CPU context (register state) carried in a minidump file. struct MinidumpContextARM64 { uint32_t context_flags; //! \brief Current program status register. uint32_t cpsr; //! \brief General-purpose registers `x0`-`x28`. uint64_t regs[29]; //! \brief Frame pointer or `x29`. uint64_t fp; //! \brief Link register or `x30`. uint64_t lr; //! \brief Stack pointer or `x31`. uint64_t sp; //! \brief Program counter. uint64_t pc; //! \brief NEON registers `v0`-`v31`. uint128_struct fpsimd[32]; //! \brief Floating-point control register. uint32_t fpcr; //! \brief Floating-point status register. uint32_t fpsr; //! \brief Debug registers. uint32_t bcr[8]; uint64_t bvr[8]; uint32_t wcr[2]; uint64_t wvr[2]; }; //! \brief 32bit MIPS-specifc flags for MinidumpContextMIPS::context_flags. //! Based on minidump_cpu_mips.h from breakpad enum MinidumpContextMIPSFlags : uint32_t { //! \brief Identifies the context structure as MIPSEL. kMinidumpContextMIPS = 0x00040000, //! \brief Indicates the validity of integer registers. //! //! Registers `0`-`31`, `mdhi`, `mdlo`, `epc`, `badvaddr`, `status` and //! `cause` are valid. kMinidumpContextMIPSInteger = kMinidumpContextMIPS | 0x00000002, //! \brief Indicates the validity of floating point registers. //! //! Floating point registers `0`-`31`, `fpcsr` and `fir` are valid kMinidumpContextMIPSFloatingPoint = kMinidumpContextMIPS | 0x00000004, //! \brief Indicates the validity of DSP registers. //! //! Registers `hi0`-`hi2`, `lo0`-`lo2` and `dsp_control` are valid kMinidumpContextMIPSDSP = kMinidumpContextMIPS | 0x00000008, //! \brief Indicates the validity of all registers. kMinidumpContextMIPSAll = kMinidumpContextMIPSInteger | kMinidumpContextMIPSFloatingPoint | kMinidumpContextMIPSDSP, }; //! \brief A 32bit MIPS CPU context (register state) carried in a minidump file. struct MinidumpContextMIPS { uint32_t context_flags; //! \brief This padding field is included for breakpad compatibility. uint32_t _pad0; //! \brief General purpose registers `0`-`31`. uint64_t regs[32]; //! \brief Multiply/divide result. uint64_t mdhi, mdlo; //! \brief DSP registers. uint32_t hi[3]; uint32_t lo[3]; uint32_t dsp_control; //! \brief This padding field is included for breakpad compatibility. uint32_t _pad1; // \brief cp0 registers. uint64_t epc; uint64_t badvaddr; uint32_t status; uint32_t cause; //! \brief FPU registers. union { struct { float _fp_fregs; uint32_t _fp_pad; } fregs[32]; double dregs[32]; } fpregs; //! \brief FPU status register. uint32_t fpcsr; //! \brief FPU implementation register. uint32_t fir; }; //! \brief 64bit MIPS-specifc flags for MinidumpContextMIPS64::context_flags. //! Based on minidump_cpu_mips.h from breakpad enum MinidumpContextMIPS64Flags : uint32_t { //! \brief Identifies the context structure as MIPS64EL. kMinidumpContextMIPS64 = 0x00080000, //! \brief Indicates the validity of integer registers. //! //! Registers `0`-`31`, `mdhi`, `mdlo`, `epc`, `badvaddr`, `status` and //! `cause` are valid. kMinidumpContextMIPS64Integer = kMinidumpContextMIPS64 | 0x00000002, //! \brief Indicates the validity of floating point registers. //! //! Floating point registers `0`-`31`, `fpcsr` and `fir` are valid kMinidumpContextMIPS64FloatingPoint = kMinidumpContextMIPS64 | 0x00000004, //! \brief Indicates the validity of DSP registers. //! //! Registers `hi0`-`hi2`, `lo0`-`lo2` and `dsp_control` are valid. kMinidumpContextMIPS64DSP = kMinidumpContextMIPS64 | 0x00000008, //! \brief Indicates the validity of all registers. kMinidumpContextMIPS64All = kMinidumpContextMIPS64Integer | kMinidumpContextMIPS64FloatingPoint | kMinidumpContextMIPS64DSP, }; //! \brief A 32bit MIPS CPU context (register state) carried in a minidump file. struct MinidumpContextMIPS64 { uint64_t context_flags; //! \brief General purpose registers. uint64_t regs[32]; //! \brief Multiply/divide result. uint64_t mdhi, mdlo; //! \brief DSP registers. uint64_t hi[3]; uint64_t lo[3]; uint64_t dsp_control; //! \brief cp0 registers. uint64_t epc; uint64_t badvaddr; uint64_t status; uint64_t cause; //! \brief FPU registers. union { struct { float _fp_fregs; uint32_t _fp_pad; } fregs[32]; double dregs[32]; } fpregs; //! \brief FPU status register. uint64_t fpcsr; //! \brief FPU implementation register. uint64_t fir; }; //! \brief 64bit RISC-V-specifc flags for MinidumpContextRISCV64::context_flags. //! Based on minidump_cpu_riscv64.h from breakpad enum MinidumpContextRISCV64Flags : uint32_t { //! \brief Identifies the context structure as RISCV64. kMinidumpContextRISCV64 = 0x00080000, //! \brief Indicates the validity of integer registers. //! //! Registers `x1`-`x31` and pc are valid. kMinidumpContextRISCV64Integer = kMinidumpContextRISCV64 | 0x00000002, //! \brief Indicates the validity of floating point registers. //! //! Floating point registers `f0`-`f31`, and `fcsr` are valid kMinidumpContextRISCV64FloatingPoint = kMinidumpContextRISCV64 | 0x00000004, //! \brief Indicates the validity of all registers. kMinidumpContextRISCV64All = kMinidumpContextRISCV64Integer | kMinidumpContextRISCV64FloatingPoint, }; //! \brief A 64bit RISCV CPU context (register state) carried in a minidump file. struct MinidumpContextRISCV64 { uint64_t context_flags; //! \brief General purpose registers. uint64_t regs[32]; //! \brief FPU registers. uint64_t fpregs[32]; //! \brief FPU status register. uint64_t fcsr; }; } // namespace crashpad #endif // CRASHPAD_MINIDUMP_MINIDUMP_CONTEXT_H_