This commit is contained in:
jeanlemotan
2024-07-02 18:10:39 +02:00
commit 48ab06b1d9
733 changed files with 321088 additions and 0 deletions
@@ -0,0 +1,524 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright (c) Electronic Arts Inc. All rights reserved.
///////////////////////////////////////////////////////////////////////////////
#if defined(EA_PRAGMA_ONCE_SUPPORTED)
#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.
#endif
#ifndef EATHREAD_EATHREAD_CALLSTACK_CONTEXT_H
#define EATHREAD_EATHREAD_CALLSTACK_CONTEXT_H
#include <EABase/eabase.h>
#include <eathread/internal/config.h>
#include <stddef.h>
EA_DISABLE_VC_WARNING(4201)
namespace EA
{
namespace Thread
{
/// CallstackContext
///
/// Processor-specific information that's needed to walk a call stack.
///
enum CallstackContextType
{
CALLSTACK_CONTEXT_UNKNOWN = 0,
CALLSTACK_CONTEXT_POWERPC,
CALLSTACK_CONTEXT_X86,
CALLSTACK_CONTEXT_X86_64,
CALLSTACK_CONTEXT_ARM,
CALLSTACK_CONTEXT_ARM64,
CALLSTACK_CONTEXT_MIPS,
CALLSTACK_CONTEXT_SPU,
NUMBER_OF_CALLSTACK_CONTEXT_TYPES
};
// NOTE: These context structures were moved to this header as of EAThread version 1.17.02
// TODO: We should evaluate if these really do belong here.
// The following are base values required for processor-agnostic offline stack dumping.
// Not all implementations will fill them in, and most times only the base and pointer
// will be filled. Also, most of the specific contexts' will have a member with the
// same value as the stack pointer, i.e. mESP on the x86
struct CallstackContextBase
{
uintptr_t mStackBase; /// Used to help tell what the valid stack ranges is. 0 if not used.
uintptr_t mStackLimit; /// "
uintptr_t mStackPointer; /// "
CallstackContextBase() : mStackBase(0), mStackLimit(0), mStackPointer(0) {}
};
struct CallstackContextPowerPC : public CallstackContextBase
{
uintptr_t mGPR1; /// General purpose register 1.
uintptr_t mIAR; /// Instruction address pseudo-register.
CallstackContextPowerPC() : mGPR1(0), mIAR(0) {}
};
struct CallstackContextX86 : public CallstackContextBase
{
uint32_t mEIP; /// Instruction pointer.
uint32_t mESP; /// Stack pointer.
uint32_t mEBP; /// Base pointer.
CallstackContextX86() : mEIP(0), mESP(0), mEBP(0) {}
};
#if defined(EA_PROCESSOR_X86)
struct CallstackContext : public CallstackContextX86
{
static const CallstackContextType kType = CALLSTACK_CONTEXT_X86;
};
#endif
struct CallstackContextX86_64 : public CallstackContextBase
{
uint64_t mRIP; /// Instruction pointer.
uint64_t mRSP; /// Stack pointer.
uint64_t mRBP; /// Base pointer.
CallstackContextX86_64() : mRIP(0), mRSP(0), mRBP(0) {}
};
#if defined(EA_PROCESSOR_X86_64)
struct CallstackContext : public CallstackContextX86_64
{
static const CallstackContextType kType = CALLSTACK_CONTEXT_X86_64;
};
#endif
struct CallstackContextARM : public CallstackContextBase
{
uint32_t mFP; /// Frame pointer; register 11 for ARM instructions, register 7 for Thumb instructions.
uint32_t mSP; /// Stack pointer; register 13
uint32_t mLR; /// Link register; register 14
uint32_t mPC; /// Program counter; register 15
CallstackContextARM() : mFP(0), mSP(0), mLR(0), mPC(0) {}
};
#if defined(EA_PROCESSOR_ARM32)
struct CallstackContext : public CallstackContextARM
{
static const CallstackContextType kType = CALLSTACK_CONTEXT_ARM;
};
#endif
struct CallstackContextARM64 : public CallstackContextBase
{
uint64_t mFP; /// Frame pointer; register 29
uint64_t mSP; /// Stack pointer; register SP
uint64_t mLR; /// Link register; register 30
uint64_t mPC; /// Program counter; register PC
CallstackContextARM64() : mFP(0), mSP(0), mLR(0), mPC(0) {}
};
#if defined(EA_PROCESSOR_ARM64)
struct CallstackContext : public CallstackContextARM64
{
static const CallstackContextType kType = CALLSTACK_CONTEXT_ARM64;
};
#endif
struct CallstackContextMIPS : public CallstackContextBase
{
uintptr_t mPC; /// Program counter.
uintptr_t mSP; /// Stack pointer.
uintptr_t mFP; /// Frame pointer.
uintptr_t mRA; /// Return address.
CallstackContextMIPS() : mPC(0), mSP(0), mFP(0), mRA(0) {}
};
struct CallstackContextSPU : public CallstackContextBase
{
uint32_t mGPR0; /// General purpose register 0, word 0: return address. If this is zero then we can still read a call stack, but simply lose the first entry.
uint32_t mGPR1; /// General purpose register 1, word 0: caller stack frame address. This is required to be set in order to read the call stack properly.
CallstackContextSPU() : mGPR0(0), mGPR1(0) {}
};
union VMXRegister
{
uint8_t mByte [16 / sizeof(uint8_t )];
uint16_t mHalfword[16 / sizeof(uint16_t)];
uint32_t mWord [16 / sizeof(uint32_t)];
uint64_t mDword [16 / sizeof(uint64_t)]; // Some VMX implementations don't support 64 bit integers.
float mFloat [16 / sizeof(float)];
double mDouble [16 / sizeof(double)]; // Some VMX implementations don't support 64 bit doubles.
};
/// ContextPowerPC32
///
/// This is a generic 32 bit PowerPC with VMX context.
///
struct ContextPowerPC32
{
uint32_t mGpr[32]; // General registers 0..31
uint32_t mCr; // Condition register
uint32_t mXer; // Fixed point exception register
uint32_t mLr; // Link register
uint32_t mCtr; // Count register low
uint32_t mCtrHigh; // Count register high
uint32_t mIar; // Instruction address register
uint32_t mMsr; // Machine status register
double mFpr[32]; // Floating registers 0..31
double mFpscr; // Floating point status/control reg
VMXRegister mVr[32]; // Vector registers 0..127
VMXRegister mVscr; // Vector status/control register
}; // ContextPowerPC32
/// ContextPowerPC64
///
/// This is a generic 64 bit PowerPC with VMX context.
///
struct ContextPowerPC64
{
uint64_t mGpr[32]; // General registers 0..31
uint64_t mCr; // Condition register
uint64_t mXer; // Fixed point exception register
uint64_t mLr; // Link register
uint64_t mCtr; // Count register
uint64_t mIar; // Instruction address register
uint64_t mMsr; // Machine status register
double mFpr[32]; // Floating registers 0..31
double mFpscr; // Floating point status/control reg
VMXRegister mVr[32]; // Vector registers 0..127
VMXRegister mVscr; // Vector status/control register
}; // ContextPowerPC64
/// ContextX86
///
/// Generic Intel x86 context.
/// This is a duplicate of the CONTEXT structure defined by Microsoft in WinNT.h.
///
struct ContextX86
{
uint32_t ContextFlags;
uint32_t Dr0;
uint32_t Dr1;
uint32_t Dr2;
uint32_t Dr3;
uint32_t Dr6;
uint32_t Dr7;
// FLOATING_SAVE_AREA
uint32_t Controluint32_t;
uint32_t Statusuint32_t;
uint32_t Taguint32_t;
uint32_t ErrorOffset;
uint32_t ErrorSelector;
uint32_t DataOffset;
uint32_t DataSelector;
uint8_t RegisterArea[80];
uint32_t Cr0NpxState;
uint32_t SegGs;
uint32_t SegFs;
uint32_t SegEs;
uint32_t SegDs;
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 SegCs;
uint32_t EFlags;
uint32_t Esp;
uint32_t SegSs;
uint8_t ExtendedRegisters[512];
}; // ContextX86
#ifdef EA_PROCESSOR_X86 // Win32, Linux, OSX.
struct Context : public ContextX86
{
// Empty
};
#endif
/// ContextX86_64
///
/// Generic Intel x86-64 context.
/// This is a duplicate of the CONTEXT structure defined
/// by Microsoft in WinNT.h in VC8 and later.
///
EA_PREFIX_ALIGN(16)
struct M128A_
{
uint64_t Low;
int64_t High;
}EA_POSTFIX_ALIGN(16);
struct XMM_SAVE_AREA32_
{
uint16_t ControlWord;
uint16_t StatusWord;
uint8_t TagWord;
uint8_t Reserved1;
uint16_t ErrorOpcode;
uint32_t ErrorOffset;
uint16_t ErrorSelector;
uint16_t Reserved2;
uint32_t DataOffset;
uint16_t DataSelector;
uint16_t Reserved3;
uint32_t MxCsr;
uint32_t MxCsr_Mask;
M128A_ FloatRegisters[8];
M128A_ XmmRegisters[16];
uint8_t Reserved4[96];
};
EA_PREFIX_ALIGN(16) struct ContextX86_64
{
uint64_t P1Home;
uint64_t P2Home;
uint64_t P3Home;
uint64_t P4Home;
uint64_t P5Home;
uint64_t P6Home;
uint32_t ContextFlags;
uint32_t MxCsr;
uint16_t SegCs;
uint16_t SegDs;
uint16_t SegEs;
uint16_t SegFs;
uint16_t SegGs;
uint16_t SegSs;
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;
union {
XMM_SAVE_AREA32_ FltSave;
struct {
M128A_ Header[2];
M128A_ Legacy[8];
M128A_ Xmm0;
M128A_ Xmm1;
M128A_ Xmm2;
M128A_ Xmm3;
M128A_ Xmm4;
M128A_ Xmm5;
M128A_ Xmm6;
M128A_ Xmm7;
M128A_ Xmm8;
M128A_ Xmm9;
M128A_ Xmm10;
M128A_ Xmm11;
M128A_ Xmm12;
M128A_ Xmm13;
M128A_ Xmm14;
M128A_ Xmm15;
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME;
M128A_ VectorRegister[26];
uint64_t VectorControl;
uint64_t DebugControl;
uint64_t LastBranchToRip;
uint64_t LastBranchFromRip;
uint64_t LastExceptionToRip;
uint64_t LastExceptionFromRip;
}; // ContextX86_64
#ifdef EA_PROCESSOR_X86_64
struct Context : public ContextX86_64
{
// Empty
};
#endif
union DoubleFloat
{
double d64;
float f32[2];
uint64_t u64;
uint32_t u32[2];
};
/// ContextARM
///
/// Generic ARM processor context.
/// There are many variations of ARM processors, so one context can't
/// address them all. We assume an ARM 7 with VFPv3 here, which is the
/// latest we use as of 2010.
/// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0041c/ch09s02s02.html
/// http://www.arm.com/products/processors/technologies/vector-floating-point.php
///
/// mGpr[0] Volatile register. Argument1, return value.
/// mGpr[1] Volatile register. Argument2, Second 32-bits if double/int Return Value
/// mGpr[2] Volatile register. Argument3.
/// mGpr[3] Volatile register. Argument4. Further arguments are put on the stack.
/// mGpr[4] Permanent register.
/// mGpr[5] Permanent register.
/// mGpr[6] Permanent register.
/// mGpr[7] Permanent register. Thumb instruction set frame pointer.
/// mGpr[8] Permanent register.
/// mGpr[9] Permanent register. Has platform-specific uses. On iOS it's reserved for the OS.
/// mGpr[10] Permanent register. SL (Stack limit, in some uses)
/// mGpr[11] Permanent register. ARM instruction set frame pointer, except for Apple/iOS where it's general purpose.
/// mGpr[12] Permanent register. IP (scratch register/new-sb in inter-link-unit calls)
/// mGpr[13] Permanent register. SP (Stack pointer)
/// mGpr[14] Permanent register. LR (Link register)
/// mGpr[15] Permanent register. PC (Program Counter)
struct ContextARM
{
uint32_t mGpr[16]; // General registers.
uint32_t mCpsr; // Current program status register.
uint32_t mSpsr; // Saved program status register.
uint32_t mFpscr; // Floating point status condition register.
DoubleFloat mDoubleFloat[32]; // If these are present, the device will have either 16 (VFPv3-D16) or 32 (VFPv3-D32) registers.
}; // ContextARM
#ifdef EA_PROCESSOR_ARM32
struct Context : public ContextARM
{
// Empty
};
#endif
/// ContextARM64
///
/// Generic ARM64 processor context.
/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf (page 14)
/// https://en.wikipedia.org/wiki/Aarch64#AArch64 (optional reading)
/// http://lxr.free-electrons.com/source/arch/arm64/include/uapi/asm/sigcontext.h
///
/// mGpr[0] Volatile register. Argument1, return value.
/// mGpr[1] Volatile register. Argument2, Second 32-bits if double/int Return Value (update)
/// mGpr[2] Volatile register. Argument3.
/// mGpr[3] Volatile register. Argument4.
/// mGpr[4] Volatile register. Argument5.
/// mGpr[5] Volatile register. Argument6.
/// mGpr[6] Volatile register. Argument7.
/// mGpr[7] Volatile register. Argument8.
/// mGpr[8] Permanent register. syscall number is in r8.
/// mGpr[9] Volatile register. Temporary data.
/// mGpr[10] Volatile register. Temporary data.
/// mGpr[11] Volatile register. Temporary data.
/// mGpr[12] Volatile register. Temporary data.
/// mGpr[13] Volatile register. Temporary data.
/// mGpr[14] Volatile register. Temporary data.
/// mGpr[15] Volatile register. Temporary data.
/// mGpr[16] Permanent register. IP0 (scratch register/new-sb in inter-link-unit calls)
/// mGpr[17] Permanent register. IP1 (scratch register/new-sb in inter-link-unit calls)
/// mGpr[18] Permanent register. Has platform-specific uses. On iOS it's reserved for the OS.
/// mGpr[19] Callee-saved register.
/// mGpr[20] Callee-saved register.
/// mGpr[21] Callee-saved register.
/// mGpr[22] Callee-saved register.
/// mGpr[23] Callee-saved register.
/// mGpr[24] Callee-saved register.
/// mGpr[25] Callee-saved register.
/// mGpr[26] Callee-saved register.
/// mGpr[27] Callee-saved register.
/// mGpr[28] Callee-saved register.
/// mGpr[29] Permanent register. FP (Frame pointer)
/// mGpr[30] Permanent register. LR (Link register)
/// mGpr[31] Permanent register. SP (Stack pointer)
///
/// Program Counter is not a General Purpose Register
/// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0801a/BABGHBJC.html
EA_PREFIX_ALIGN(16)
struct ContextARM64
{
uint64_t mGpr[32]; // General registers.
uint64_t mPC; // Program counter.
uint64_t mNzcv; // Global condition register.
uint32_t mFpsr; // Floating point status register.
uint32_t mFpcr; // Floating point condition register.
union
{
uint8_t mByteArray [512]; // Access Neon registers as raw bytes.
double mDoubleArray[512/sizeof(double)]; // Access Neon registers as doubles
float mFloatArray [512/sizeof(float)]; // Access Neon registers as floats
uint16_t mUInt16Array[512/sizeof(uint16_t)]; // Access Neon registers as uint16_t's
uint32_t mUInt32Array[512/sizeof(uint32_t)]; // Access Neon registers as uint32_t's
uint64_t mUInt64Array[512/sizeof(uint64_t)]; // Access Neon registers as uint64_t's
} mNeon;
uint32_t mPadding[2]; // required to avoid warning 4324 on vc
}EA_POSTFIX_ALIGN(16);// ContextARM64
#ifdef EA_PROCESSOR_ARM64
struct Context : public ContextARM64
{
// Empty
};
#endif
} // namespace Thread
} // namespace EA
EA_RESTORE_VC_WARNING()
#endif // Header include guard.