eathread_callstack_context.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Electronic Arts Inc. All rights reserved.
  3. ///////////////////////////////////////////////////////////////////////////////
  4. #if defined(EA_PRAGMA_ONCE_SUPPORTED)
  5. #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.
  6. #endif
  7. #ifndef EATHREAD_EATHREAD_CALLSTACK_CONTEXT_H
  8. #define EATHREAD_EATHREAD_CALLSTACK_CONTEXT_H
  9. #include <EABase/eabase.h>
  10. #include <eathread/internal/config.h>
  11. #include <stddef.h>
  12. EA_DISABLE_VC_WARNING(4201)
  13. namespace EA
  14. {
  15. namespace Thread
  16. {
  17. /// CallstackContext
  18. ///
  19. /// Processor-specific information that's needed to walk a call stack.
  20. ///
  21. enum CallstackContextType
  22. {
  23. CALLSTACK_CONTEXT_UNKNOWN = 0,
  24. CALLSTACK_CONTEXT_POWERPC,
  25. CALLSTACK_CONTEXT_X86,
  26. CALLSTACK_CONTEXT_X86_64,
  27. CALLSTACK_CONTEXT_ARM,
  28. CALLSTACK_CONTEXT_ARM64,
  29. CALLSTACK_CONTEXT_MIPS,
  30. CALLSTACK_CONTEXT_SPU,
  31. NUMBER_OF_CALLSTACK_CONTEXT_TYPES
  32. };
  33. // NOTE: These context structures were moved to this header as of EAThread version 1.17.02
  34. // TODO: We should evaluate if these really do belong here.
  35. // The following are base values required for processor-agnostic offline stack dumping.
  36. // Not all implementations will fill them in, and most times only the base and pointer
  37. // will be filled. Also, most of the specific contexts' will have a member with the
  38. // same value as the stack pointer, i.e. mESP on the x86
  39. struct CallstackContextBase
  40. {
  41. uintptr_t mStackBase; /// Used to help tell what the valid stack ranges is. 0 if not used.
  42. uintptr_t mStackLimit; /// "
  43. uintptr_t mStackPointer; /// "
  44. CallstackContextBase() : mStackBase(0), mStackLimit(0), mStackPointer(0) {}
  45. };
  46. struct CallstackContextPowerPC : public CallstackContextBase
  47. {
  48. uintptr_t mGPR1; /// General purpose register 1.
  49. uintptr_t mIAR; /// Instruction address pseudo-register.
  50. CallstackContextPowerPC() : mGPR1(0), mIAR(0) {}
  51. };
  52. struct CallstackContextX86 : public CallstackContextBase
  53. {
  54. uint32_t mEIP; /// Instruction pointer.
  55. uint32_t mESP; /// Stack pointer.
  56. uint32_t mEBP; /// Base pointer.
  57. CallstackContextX86() : mEIP(0), mESP(0), mEBP(0) {}
  58. };
  59. #if defined(EA_PROCESSOR_X86)
  60. struct CallstackContext : public CallstackContextX86
  61. {
  62. static const CallstackContextType kType = CALLSTACK_CONTEXT_X86;
  63. };
  64. #endif
  65. struct CallstackContextX86_64 : public CallstackContextBase
  66. {
  67. uint64_t mRIP; /// Instruction pointer.
  68. uint64_t mRSP; /// Stack pointer.
  69. uint64_t mRBP; /// Base pointer.
  70. CallstackContextX86_64() : mRIP(0), mRSP(0), mRBP(0) {}
  71. };
  72. #if defined(EA_PROCESSOR_X86_64)
  73. struct CallstackContext : public CallstackContextX86_64
  74. {
  75. static const CallstackContextType kType = CALLSTACK_CONTEXT_X86_64;
  76. };
  77. #endif
  78. struct CallstackContextARM : public CallstackContextBase
  79. {
  80. uint32_t mFP; /// Frame pointer; register 11 for ARM instructions, register 7 for Thumb instructions.
  81. uint32_t mSP; /// Stack pointer; register 13
  82. uint32_t mLR; /// Link register; register 14
  83. uint32_t mPC; /// Program counter; register 15
  84. CallstackContextARM() : mFP(0), mSP(0), mLR(0), mPC(0) {}
  85. };
  86. #if defined(EA_PROCESSOR_ARM32)
  87. struct CallstackContext : public CallstackContextARM
  88. {
  89. static const CallstackContextType kType = CALLSTACK_CONTEXT_ARM;
  90. };
  91. #endif
  92. struct CallstackContextARM64 : public CallstackContextBase
  93. {
  94. uint64_t mFP; /// Frame pointer; register 29
  95. uint64_t mSP; /// Stack pointer; register SP
  96. uint64_t mLR; /// Link register; register 30
  97. uint64_t mPC; /// Program counter; register PC
  98. CallstackContextARM64() : mFP(0), mSP(0), mLR(0), mPC(0) {}
  99. };
  100. #if defined(EA_PROCESSOR_ARM64)
  101. struct CallstackContext : public CallstackContextARM64
  102. {
  103. static const CallstackContextType kType = CALLSTACK_CONTEXT_ARM64;
  104. };
  105. #endif
  106. struct CallstackContextMIPS : public CallstackContextBase
  107. {
  108. uintptr_t mPC; /// Program counter.
  109. uintptr_t mSP; /// Stack pointer.
  110. uintptr_t mFP; /// Frame pointer.
  111. uintptr_t mRA; /// Return address.
  112. CallstackContextMIPS() : mPC(0), mSP(0), mFP(0), mRA(0) {}
  113. };
  114. struct CallstackContextSPU : public CallstackContextBase
  115. {
  116. 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.
  117. 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.
  118. CallstackContextSPU() : mGPR0(0), mGPR1(0) {}
  119. };
  120. union VMXRegister
  121. {
  122. uint8_t mByte [16 / sizeof(uint8_t )];
  123. uint16_t mHalfword[16 / sizeof(uint16_t)];
  124. uint32_t mWord [16 / sizeof(uint32_t)];
  125. uint64_t mDword [16 / sizeof(uint64_t)]; // Some VMX implementations don't support 64 bit integers.
  126. float mFloat [16 / sizeof(float)];
  127. double mDouble [16 / sizeof(double)]; // Some VMX implementations don't support 64 bit doubles.
  128. };
  129. /// ContextPowerPC32
  130. ///
  131. /// This is a generic 32 bit PowerPC with VMX context.
  132. ///
  133. struct ContextPowerPC32
  134. {
  135. uint32_t mGpr[32]; // General registers 0..31
  136. uint32_t mCr; // Condition register
  137. uint32_t mXer; // Fixed point exception register
  138. uint32_t mLr; // Link register
  139. uint32_t mCtr; // Count register low
  140. uint32_t mCtrHigh; // Count register high
  141. uint32_t mIar; // Instruction address register
  142. uint32_t mMsr; // Machine status register
  143. double mFpr[32]; // Floating registers 0..31
  144. double mFpscr; // Floating point status/control reg
  145. VMXRegister mVr[32]; // Vector registers 0..127
  146. VMXRegister mVscr; // Vector status/control register
  147. }; // ContextPowerPC32
  148. /// ContextPowerPC64
  149. ///
  150. /// This is a generic 64 bit PowerPC with VMX context.
  151. ///
  152. struct ContextPowerPC64
  153. {
  154. uint64_t mGpr[32]; // General registers 0..31
  155. uint64_t mCr; // Condition register
  156. uint64_t mXer; // Fixed point exception register
  157. uint64_t mLr; // Link register
  158. uint64_t mCtr; // Count register
  159. uint64_t mIar; // Instruction address register
  160. uint64_t mMsr; // Machine status register
  161. double mFpr[32]; // Floating registers 0..31
  162. double mFpscr; // Floating point status/control reg
  163. VMXRegister mVr[32]; // Vector registers 0..127
  164. VMXRegister mVscr; // Vector status/control register
  165. }; // ContextPowerPC64
  166. /// ContextX86
  167. ///
  168. /// Generic Intel x86 context.
  169. /// This is a duplicate of the CONTEXT structure defined by Microsoft in WinNT.h.
  170. ///
  171. struct ContextX86
  172. {
  173. uint32_t ContextFlags;
  174. uint32_t Dr0;
  175. uint32_t Dr1;
  176. uint32_t Dr2;
  177. uint32_t Dr3;
  178. uint32_t Dr6;
  179. uint32_t Dr7;
  180. // FLOATING_SAVE_AREA
  181. uint32_t Controluint32_t;
  182. uint32_t Statusuint32_t;
  183. uint32_t Taguint32_t;
  184. uint32_t ErrorOffset;
  185. uint32_t ErrorSelector;
  186. uint32_t DataOffset;
  187. uint32_t DataSelector;
  188. uint8_t RegisterArea[80];
  189. uint32_t Cr0NpxState;
  190. uint32_t SegGs;
  191. uint32_t SegFs;
  192. uint32_t SegEs;
  193. uint32_t SegDs;
  194. uint32_t Edi;
  195. uint32_t Esi;
  196. uint32_t Ebx;
  197. uint32_t Edx;
  198. uint32_t Ecx;
  199. uint32_t Eax;
  200. uint32_t Ebp;
  201. uint32_t Eip;
  202. uint32_t SegCs;
  203. uint32_t EFlags;
  204. uint32_t Esp;
  205. uint32_t SegSs;
  206. uint8_t ExtendedRegisters[512];
  207. }; // ContextX86
  208. #ifdef EA_PROCESSOR_X86 // Win32, Linux, OSX.
  209. struct Context : public ContextX86
  210. {
  211. // Empty
  212. };
  213. #endif
  214. /// ContextX86_64
  215. ///
  216. /// Generic Intel x86-64 context.
  217. /// This is a duplicate of the CONTEXT structure defined
  218. /// by Microsoft in WinNT.h in VC8 and later.
  219. ///
  220. EA_PREFIX_ALIGN(16)
  221. struct M128A_
  222. {
  223. uint64_t Low;
  224. int64_t High;
  225. }EA_POSTFIX_ALIGN(16);
  226. struct XMM_SAVE_AREA32_
  227. {
  228. uint16_t ControlWord;
  229. uint16_t StatusWord;
  230. uint8_t TagWord;
  231. uint8_t Reserved1;
  232. uint16_t ErrorOpcode;
  233. uint32_t ErrorOffset;
  234. uint16_t ErrorSelector;
  235. uint16_t Reserved2;
  236. uint32_t DataOffset;
  237. uint16_t DataSelector;
  238. uint16_t Reserved3;
  239. uint32_t MxCsr;
  240. uint32_t MxCsr_Mask;
  241. M128A_ FloatRegisters[8];
  242. M128A_ XmmRegisters[16];
  243. uint8_t Reserved4[96];
  244. };
  245. EA_PREFIX_ALIGN(16) struct ContextX86_64
  246. {
  247. uint64_t P1Home;
  248. uint64_t P2Home;
  249. uint64_t P3Home;
  250. uint64_t P4Home;
  251. uint64_t P5Home;
  252. uint64_t P6Home;
  253. uint32_t ContextFlags;
  254. uint32_t MxCsr;
  255. uint16_t SegCs;
  256. uint16_t SegDs;
  257. uint16_t SegEs;
  258. uint16_t SegFs;
  259. uint16_t SegGs;
  260. uint16_t SegSs;
  261. uint32_t EFlags;
  262. uint64_t Dr0;
  263. uint64_t Dr1;
  264. uint64_t Dr2;
  265. uint64_t Dr3;
  266. uint64_t Dr6;
  267. uint64_t Dr7;
  268. uint64_t Rax;
  269. uint64_t Rcx;
  270. uint64_t Rdx;
  271. uint64_t Rbx;
  272. uint64_t Rsp;
  273. uint64_t Rbp;
  274. uint64_t Rsi;
  275. uint64_t Rdi;
  276. uint64_t R8;
  277. uint64_t R9;
  278. uint64_t R10;
  279. uint64_t R11;
  280. uint64_t R12;
  281. uint64_t R13;
  282. uint64_t R14;
  283. uint64_t R15;
  284. uint64_t Rip;
  285. union {
  286. XMM_SAVE_AREA32_ FltSave;
  287. struct {
  288. M128A_ Header[2];
  289. M128A_ Legacy[8];
  290. M128A_ Xmm0;
  291. M128A_ Xmm1;
  292. M128A_ Xmm2;
  293. M128A_ Xmm3;
  294. M128A_ Xmm4;
  295. M128A_ Xmm5;
  296. M128A_ Xmm6;
  297. M128A_ Xmm7;
  298. M128A_ Xmm8;
  299. M128A_ Xmm9;
  300. M128A_ Xmm10;
  301. M128A_ Xmm11;
  302. M128A_ Xmm12;
  303. M128A_ Xmm13;
  304. M128A_ Xmm14;
  305. M128A_ Xmm15;
  306. } DUMMYSTRUCTNAME;
  307. } DUMMYUNIONNAME;
  308. M128A_ VectorRegister[26];
  309. uint64_t VectorControl;
  310. uint64_t DebugControl;
  311. uint64_t LastBranchToRip;
  312. uint64_t LastBranchFromRip;
  313. uint64_t LastExceptionToRip;
  314. uint64_t LastExceptionFromRip;
  315. }; // ContextX86_64
  316. #ifdef EA_PROCESSOR_X86_64
  317. struct Context : public ContextX86_64
  318. {
  319. // Empty
  320. };
  321. #endif
  322. union DoubleFloat
  323. {
  324. double d64;
  325. float f32[2];
  326. uint64_t u64;
  327. uint32_t u32[2];
  328. };
  329. /// ContextARM
  330. ///
  331. /// Generic ARM processor context.
  332. /// There are many variations of ARM processors, so one context can't
  333. /// address them all. We assume an ARM 7 with VFPv3 here, which is the
  334. /// latest we use as of 2010.
  335. /// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0041c/ch09s02s02.html
  336. /// http://www.arm.com/products/processors/technologies/vector-floating-point.php
  337. ///
  338. /// mGpr[0] Volatile register. Argument1, return value.
  339. /// mGpr[1] Volatile register. Argument2, Second 32-bits if double/int Return Value
  340. /// mGpr[2] Volatile register. Argument3.
  341. /// mGpr[3] Volatile register. Argument4. Further arguments are put on the stack.
  342. /// mGpr[4] Permanent register.
  343. /// mGpr[5] Permanent register.
  344. /// mGpr[6] Permanent register.
  345. /// mGpr[7] Permanent register. Thumb instruction set frame pointer.
  346. /// mGpr[8] Permanent register.
  347. /// mGpr[9] Permanent register. Has platform-specific uses. On iOS it's reserved for the OS.
  348. /// mGpr[10] Permanent register. SL (Stack limit, in some uses)
  349. /// mGpr[11] Permanent register. ARM instruction set frame pointer, except for Apple/iOS where it's general purpose.
  350. /// mGpr[12] Permanent register. IP (scratch register/new-sb in inter-link-unit calls)
  351. /// mGpr[13] Permanent register. SP (Stack pointer)
  352. /// mGpr[14] Permanent register. LR (Link register)
  353. /// mGpr[15] Permanent register. PC (Program Counter)
  354. struct ContextARM
  355. {
  356. uint32_t mGpr[16]; // General registers.
  357. uint32_t mCpsr; // Current program status register.
  358. uint32_t mSpsr; // Saved program status register.
  359. uint32_t mFpscr; // Floating point status condition register.
  360. DoubleFloat mDoubleFloat[32]; // If these are present, the device will have either 16 (VFPv3-D16) or 32 (VFPv3-D32) registers.
  361. }; // ContextARM
  362. #ifdef EA_PROCESSOR_ARM32
  363. struct Context : public ContextARM
  364. {
  365. // Empty
  366. };
  367. #endif
  368. /// ContextARM64
  369. ///
  370. /// Generic ARM64 processor context.
  371. /// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf (page 14)
  372. /// https://en.wikipedia.org/wiki/Aarch64#AArch64 (optional reading)
  373. /// http://lxr.free-electrons.com/source/arch/arm64/include/uapi/asm/sigcontext.h
  374. ///
  375. /// mGpr[0] Volatile register. Argument1, return value.
  376. /// mGpr[1] Volatile register. Argument2, Second 32-bits if double/int Return Value (update)
  377. /// mGpr[2] Volatile register. Argument3.
  378. /// mGpr[3] Volatile register. Argument4.
  379. /// mGpr[4] Volatile register. Argument5.
  380. /// mGpr[5] Volatile register. Argument6.
  381. /// mGpr[6] Volatile register. Argument7.
  382. /// mGpr[7] Volatile register. Argument8.
  383. /// mGpr[8] Permanent register. syscall number is in r8.
  384. /// mGpr[9] Volatile register. Temporary data.
  385. /// mGpr[10] Volatile register. Temporary data.
  386. /// mGpr[11] Volatile register. Temporary data.
  387. /// mGpr[12] Volatile register. Temporary data.
  388. /// mGpr[13] Volatile register. Temporary data.
  389. /// mGpr[14] Volatile register. Temporary data.
  390. /// mGpr[15] Volatile register. Temporary data.
  391. /// mGpr[16] Permanent register. IP0 (scratch register/new-sb in inter-link-unit calls)
  392. /// mGpr[17] Permanent register. IP1 (scratch register/new-sb in inter-link-unit calls)
  393. /// mGpr[18] Permanent register. Has platform-specific uses. On iOS it's reserved for the OS.
  394. /// mGpr[19] Callee-saved register.
  395. /// mGpr[20] Callee-saved register.
  396. /// mGpr[21] Callee-saved register.
  397. /// mGpr[22] Callee-saved register.
  398. /// mGpr[23] Callee-saved register.
  399. /// mGpr[24] Callee-saved register.
  400. /// mGpr[25] Callee-saved register.
  401. /// mGpr[26] Callee-saved register.
  402. /// mGpr[27] Callee-saved register.
  403. /// mGpr[28] Callee-saved register.
  404. /// mGpr[29] Permanent register. FP (Frame pointer)
  405. /// mGpr[30] Permanent register. LR (Link register)
  406. /// mGpr[31] Permanent register. SP (Stack pointer)
  407. ///
  408. /// Program Counter is not a General Purpose Register
  409. /// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0801a/BABGHBJC.html
  410. EA_PREFIX_ALIGN(16)
  411. struct ContextARM64
  412. {
  413. uint64_t mGpr[32]; // General registers.
  414. uint64_t mPC; // Program counter.
  415. uint64_t mNzcv; // Global condition register.
  416. uint32_t mFpsr; // Floating point status register.
  417. uint32_t mFpcr; // Floating point condition register.
  418. union
  419. {
  420. uint8_t mByteArray [512]; // Access Neon registers as raw bytes.
  421. double mDoubleArray[512/sizeof(double)]; // Access Neon registers as doubles
  422. float mFloatArray [512/sizeof(float)]; // Access Neon registers as floats
  423. uint16_t mUInt16Array[512/sizeof(uint16_t)]; // Access Neon registers as uint16_t's
  424. uint32_t mUInt32Array[512/sizeof(uint32_t)]; // Access Neon registers as uint32_t's
  425. uint64_t mUInt64Array[512/sizeof(uint64_t)]; // Access Neon registers as uint64_t's
  426. } mNeon;
  427. uint32_t mPadding[2]; // required to avoid warning 4324 on vc
  428. }EA_POSTFIX_ALIGN(16);// ContextARM64
  429. #ifdef EA_PROCESSOR_ARM64
  430. struct Context : public ContextARM64
  431. {
  432. // Empty
  433. };
  434. #endif
  435. } // namespace Thread
  436. } // namespace EA
  437. EA_RESTORE_VC_WARNING()
  438. #endif // Header include guard.