eathread_callstack.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  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_H
  8. #define EATHREAD_EATHREAD_CALLSTACK_H
  9. #include <EABase/eabase.h>
  10. #include <eathread/eathread.h>
  11. #include <stddef.h>
  12. namespace EA
  13. {
  14. namespace Thread
  15. {
  16. /// CallstackContext
  17. ///
  18. /// This is forward-declared here and fully declared at the bottom of this file.
  19. ///
  20. struct CallstackContext;
  21. struct Context;
  22. /// InitCallstack
  23. ///
  24. /// Allows the user to explicitly initialize the callstack mechanism.
  25. /// Only the first call to InitCallstack will have effect. Calls to
  26. /// InitCallstack must be matched by calls to ShutdownCallstack.
  27. ///
  28. EATHREADLIB_API void InitCallstack();
  29. /// ShutdownCallstack
  30. ///
  31. /// Allows the user to explicitly shutdown the callstack mechanism.
  32. /// Calls to InitCallstack must be matched by calls to ShutdownCallstack.
  33. /// The last call to ShutdownCallstack will shutdown and free the callstack mechanism.
  34. ///
  35. EATHREADLIB_API void ShutdownCallstack();
  36. /// GetCallstack
  37. ///
  38. /// Gets the addresses of the calling instructions of a call stack.
  39. /// If the CallstackContext parameter is used, then that execution context is used;
  40. /// otherwise the current execution context is used.
  41. /// The return value is the number of entries written to the callstack array.
  42. /// The item at callstack[0] is from the function calling the GetCallstack function.
  43. /// For most platforms the addresses reported are the addresses of the instruction
  44. /// that will next be executed upon returning from the function it is calling.
  45. /// The maxDepth parameter must be at least one and callstack must be able to hold
  46. /// at least one entry (a terminating 0 NULL entry).
  47. ///
  48. EATHREADLIB_API size_t GetCallstack(void* callstack[], size_t maxDepth, const CallstackContext* pContext = NULL);
  49. /// GetCallstack
  50. ///
  51. /// Gets the callstack based on the thread id as opposed to register context.
  52. ///
  53. #if defined(EA_PLATFORM_SONY)
  54. EATHREADLIB_API size_t GetCallstack(void* pReturnAddressArray[], size_t nReturnAddressArrayCapacity, EA::Thread::ThreadId& pthread);
  55. #endif
  56. #if defined(EA_PLATFORM_MICROSOFT)
  57. /// Microsoft thread handles are opaque types which are non-unique per thread.
  58. /// That is, two different thread handles might refer to the same thread.
  59. /// threadId is the same as EA::Thread::ThreadId and is a Microsoft thread HANDLE.
  60. /// This is not the same as a Microsoft DWORD thread id which is the same as EA::Thread::SysThreadId.
  61. EATHREADLIB_API bool ThreadHandlesAreEqual(intptr_t threadId1, intptr_t threadId2);
  62. /// This function is the same as EA::Thread::GetSysThreadId(ThreadId id).
  63. /// This function converts from one type of Microsoft thread identifier to another.
  64. /// threadId is the same as EA::Thread::ThreadId and is a Microsoft thread HANDLE.
  65. /// The return value is a Microsoft DWORD thread id which is the same as EA::Thread::SysThreadId.
  66. /// Upon failure, the return value will be zero.
  67. EATHREADLIB_API uint32_t GetThreadIdFromThreadHandle(intptr_t threadId);
  68. #endif
  69. /// GetCallstackContext
  70. ///
  71. /// Gets the CallstackContext associated with the given thread.
  72. /// The thread must be in a non-running state.
  73. /// If the threadID is EAThread::kThreadIdInvalid, the current thread context is retrieved.
  74. /// However, it's of little use to get the context of the current thread, since upon return
  75. /// from the GetCallstackContext the data will not apply to the current thread any more;
  76. /// thus this information is probably useful only for diagnostic purposes.
  77. /// The threadId parameter is the same type as an EAThread ThreadId. It is important to
  78. /// note that an EAThread ThreadId under Microsoft platforms is a thread handle and not what
  79. /// Microsoft calls a thread id. This is by design as Microsoft thread ids are second class
  80. /// citizens and likely wouldn't exist if it not were for quirks in the Windows API evolution.
  81. ///
  82. /// Note that threadId is the same as EA::Thread::ThreadId and is a Microsoft thread HANDLE.
  83. /// This is not the same as a Microsoft DWORD thread id which is the same as EA::Thread::SysThreadId.
  84. ///
  85. /// EACallstack has a general struct for each CPU type called Context, defined in EACallstack/Context.h.
  86. /// The Context struct contains the entire CPU register context information. In order to walk a thread's
  87. /// callstack, you really need only two or three of the register values from the Context. So there is a
  88. /// mini struct called CallstackContext which is just those registers needed to read a thread's callstack.
  89. ///
  90. // ThreadId constants
  91. #if EA_USE_CPP11_CONCURRENCY
  92. EATHREADLIB_API bool GetCallstackContext(CallstackContext& context, EA::Thread::ThreadId threadId);
  93. #else
  94. EATHREADLIB_API bool GetCallstackContext(CallstackContext& context, intptr_t threadId = 0);
  95. #endif
  96. /// GetCallstackContextSysThreadId
  97. ///
  98. /// This is the same as GetCallstackContext, except it uses what EAThread calls SysThreadId.
  99. /// On Microsoft platforms a SysThreadId is a "thread id" whereas ThreadId is "thread handle."
  100. /// On non-Microsoft platforms a SysThreadId is defined to be the same as ThreadId and is often
  101. /// just an integer or opaque identifier (e.g. pthread).
  102. /// This function exists because it may be more convenient to work with SysThreadIds in some cases.
  103. /// You can convert from a ThreadId (Microsoft thread handle) to a SysThreadId (Microsoft thread id)
  104. /// with the GetThreadIdFromThreadHandle function.
  105. EATHREADLIB_API bool GetCallstackContextSysThreadId(CallstackContext& context, intptr_t sysThreadId = 0);
  106. /// GetCallstackContext
  107. ///
  108. /// Gets the CallstackContext from a full Context struct. Note that the Context struct
  109. /// defines the entire machine context, whereas the CallstackContext is a tiny struct
  110. /// with just a couple integer members and is all that's needed to describe a callstack.
  111. ///
  112. EATHREADLIB_API void GetCallstackContext(CallstackContext& context, const Context* pContext = NULL);
  113. /// GetModuleFromAddress
  114. ///
  115. /// Given an address, this function tells what module it comes from.
  116. /// The primary use of this is to tell what DLL an instruction pointer comes from.
  117. /// Returns the required strlen of the pModuleFileName. If the return value is >= moduleNameCapacity,
  118. /// there wasn't enough space. pModuleFileName is written with as many characters as possible
  119. /// and will always be zero terminated. moduleNameCapacity must be at least one.
  120. ///
  121. EATHREADLIB_API size_t GetModuleFromAddress(const void* pAddress, char* pModuleFileName, size_t moduleNameCapacity);
  122. /// ModuleHandle
  123. /// This is a runtime module identifier. For Microsoft Windows-like platforms
  124. /// this is the same thing as HMODULE. For other platforms it is a shared library
  125. /// runtime library pointer, id, or handle. For Microsoft platforms, each running
  126. /// DLL has a module handle.
  127. #if defined(EA_PLATFORM_MICROSOFT)
  128. typedef void* ModuleHandle; // HMODULE, from LoadLibrary()
  129. #elif defined(EA_PLATFORM_UNIX) || defined(EA_PLATFORM_APPLE)
  130. typedef void* ModuleHandle; // void*, from dlopen()
  131. #else
  132. typedef uintptr_t ModuleHandle;
  133. #endif
  134. /// GetModuleHandleFromAddress
  135. ///
  136. /// Returns the module handle from a code address.
  137. /// Returns 0/NULL if no associated module could be found.
  138. ///
  139. EATHREADLIB_API ModuleHandle GetModuleHandleFromAddress(const void* pAddress);
  140. /// EAGetInstructionPointer
  141. ///
  142. /// Returns the current instruction pointer (a.k.a. program counter).
  143. /// This function is implemented as a macro, it acts as if its declaration
  144. /// were like so:
  145. /// void EAGetInstructionPointer(void*& p);
  146. ///
  147. /// For portability, this function should only be used as a standalone
  148. /// statement on its own line.
  149. ///
  150. /// Example usage:
  151. /// void* pInstruction;
  152. /// EAGetInstructionPointer(pInstruction);
  153. ///
  154. #if defined(EA_COMPILER_MSVC) && defined(EA_PROCESSOR_X86)
  155. // We implement this via calling the next line of code as a function.
  156. // Then we continue as if we were exiting that function but with no
  157. // return statement. The result is that the instruction pointer will
  158. // be placed on the stack and we merely pop it off the stack and
  159. // into a local variable.
  160. #define EAGetInstructionPointer(p) \
  161. { \
  162. uintptr_t eip; \
  163. __asm { \
  164. __asm call GetEIP \
  165. __asm GetEIP: \
  166. __asm pop eip \
  167. } \
  168. p = (void*)eip; \
  169. }
  170. EA_DISABLE_VC_WARNING(4740)
  171. inline void GetInstructionPointer(void*& p)
  172. {EAGetInstructionPointer(p);}
  173. EA_RESTORE_VC_WARNING()
  174. #elif defined(EA_COMPILER_MSVC) && (defined(EA_PROCESSOR_X86_64) || defined(EA_PROCESSOR_ARM))
  175. EATHREADLIB_API EA_NO_INLINE void GetInstructionPointer(void*& p);
  176. #define EAGetInstructionPointer(p) EA::Thread::GetInstructionPointer(p)
  177. #elif defined(EA_COMPILER_ARM) // ARM compiler
  178. // Even if there are compiler intrinsics that let you get the instruction pointer,
  179. // this function can still be useful. For example, on ARM platforms this function
  180. // returns the address with the 'thumb bit' set if it's thumb code. We need this info sometimes.
  181. EATHREADLIB_API void GetInstructionPointer(void*& p);
  182. // The ARM compiler provides a __current_pc() instrinsic, which returns an unsigned integer type.
  183. #define EAGetInstructionPointer(p) { uintptr_t pc = (uintptr_t)__current_pc(); p = reinterpret_cast<void*>(pc); }
  184. //#elif defined(EA_COMPILER_CLANG) // Disabled until implemented. The GCC code below works under clang, though it wouldn't if compiler extensions were disabled.
  185. // EATHREADLIB_API void GetInstructionPointer(void*& p);
  186. //
  187. // // To do: implement this directly instead of via a call to GetInstructionPointer.
  188. // #define EAGetInstructionPointer(p) EA::Thread::GetInstructionPointer(p)
  189. #elif defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG) // This covers EA_PLATFORM_UNIX, EA_PLATFORM_OSX
  190. // Even if there are compiler intrinsics that let you get the instruction pointer,
  191. // this function can still be useful. For example, on ARM platforms this function
  192. // returns the address with the 'thumb bit' set if it's thumb code. We need this info sometimes.
  193. EATHREADLIB_API void GetInstructionPointer(void*& p) __attribute__((noinline));
  194. // It turns out that GCC has an extension that allows you to take the address
  195. // of a label. The code here looks a little wacky, but that's how it's done.
  196. // Basically, this generates a global variable called 'label' and the assignment
  197. // to 'p' reads that variable into p. One possible downside to this technique is
  198. // that it relies on registers and global memory not being corrupted, yet one of
  199. // reasons why we might want to be getting the instruction pointer is in dealing
  200. // with some sort or processor exception which may be due to memory corruption.
  201. // To consider: Make a version of this which calculates the value dynamically via asm.
  202. #define EAGetInstructionPointer(p) EA::Thread::GetInstructionPointer(p)
  203. #else
  204. #error
  205. #endif
  206. /// EASetStackBase / SetStackBase / GetStackBase / GetStackLimit
  207. ///
  208. /// EASetStackBase as a macro and acts as if its declaration were like so:
  209. /// void EASetStackBase();
  210. ///
  211. /// EASetStackBase sets the current stack pointer as the bottom (beginning)
  212. /// of the stack. Depending on the platform, the "bottom" may be up or down
  213. /// depending on whether the stack grows upward or downward (usually it grows
  214. /// downward and so "bottom" actually refers to an address that is above child
  215. /// stack frames in memory.
  216. /// This function is intended to be called on application startup as early as
  217. /// possible, and in each created thread, as early as possible. Its purpose
  218. /// is to record the beginning stack pointer because the platform doesn't provide
  219. /// APIs to tell what it is, and we need to know it (e.g. so we don't overrun
  220. /// it during stack unwinds).
  221. ///
  222. /// For portability, EASetStackBase should be used only as a standalone
  223. /// statement on its own line, as it may include statements that can't work otherwise.
  224. ///
  225. /// Example usage:
  226. /// int main(int argc, char** argv) {
  227. /// EASetStackBase();
  228. /// . . .
  229. /// }
  230. ///
  231. /// SetStackBase is a function which lets you explicitly set a stack bottom instead
  232. /// of doing it automatically with EASetStackBase. If you pass NULL for pStackBase
  233. /// then the function uses its stack location during its execution, which will be
  234. /// a little less optimal than calling EASetStackBase.
  235. ///
  236. /// GetStackBase returns the stack bottom set by EASetStackBase or SetStackBase.
  237. /// It returns NULL if no stack bottom was set or could be set.
  238. ///
  239. /// GetStackLimit returns the current stack "top", which will be lower than the stack
  240. /// bottom in memory if the platform grows its stack downward.
  241. EATHREADLIB_API void SetStackBase(void* pStackBase);
  242. inline void SetStackBase(uintptr_t pStackBase){ SetStackBase((void*)pStackBase); }
  243. EATHREADLIB_API void* GetStackBase();
  244. EATHREADLIB_API void* GetStackLimit();
  245. #if defined(EA_COMPILER_MSVC) && defined(EA_PROCESSOR_X86)
  246. #define EASetStackBase() \
  247. { \
  248. void* esp; \
  249. __asm { mov esp, ESP } \
  250. ::EA::Thread::SetStackBase(esp); \
  251. }
  252. #elif defined(EA_COMPILER_MSVC) && (defined(EA_PROCESSOR_X86_64) || defined(EA_PROCESSOR_ARM))
  253. // This implementation uses SetStackBase(NULL), which internally retrieves the stack pointer.
  254. #define EASetStackBase() \
  255. { \
  256. ::EA::Thread::SetStackBase((void*)NULL); \
  257. } \
  258. #elif defined(EA_COMPILER_ARM) // ARM compiler
  259. #define EASetStackBase() \
  260. ::EA::Thread::SetStackBase((void*)__current_sp())
  261. #elif defined(EA_COMPILER_GNUC) // This covers EA_PLATFORM_UNIX, EA_PLATFORM_OSX
  262. #define EASetStackBase() \
  263. ::EA::Thread::SetStackBase((void*)__builtin_frame_address(0));
  264. #else
  265. // This implementation uses SetStackBase(NULL), which internally retrieves the stack pointer.
  266. #define EASetStackBase() \
  267. { \
  268. ::EA::Thread::SetStackBase((void*)NULL); \
  269. } \
  270. #endif
  271. #if defined(EA_PLATFORM_UNIX) || defined(EA_PLATFORM_APPLE) || defined(EA_PLATFORM_SONY)
  272. // GetPthreadStackInfo
  273. //
  274. // With some implementations of pthread, the stack base is returned by pthread as NULL if it's the main thread,
  275. // or possibly if it's a thread you created but didn't call pthread_attr_setstack manually to provide your
  276. // own stack. It's impossible for us to tell here whether will be such a NULL return value, so we just do what
  277. // we can and the user nees to beware that a NULL return value means that the system doesn't provide the
  278. // given information for the current thread. This function returns false and sets pBase and pLimit to NULL in
  279. // the case that the thread base and limit weren't returned by the system or were returned as NULL.
  280. bool GetPthreadStackInfo(void** pBase, void** pLimit);
  281. #endif
  282. } // namespace Thread
  283. } // namespace EA
  284. #endif // Header include guard.