Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
7.3 KiB

  1. //========= Copyright � 1996-2008, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Tools for grabbing/dumping the stack at runtime
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifndef TIER0_STACKTOOLS_H
  8. #define TIER0_STACKTOOLS_H
  9. #ifdef _WIN32
  10. #pragma once
  11. #endif
  12. #include "tier0/platform.h"
  13. #if (defined( PLATFORM_WINDOWS ) || defined( PLATFORM_X360 )) && !defined( STEAM ) && !defined( _CERT ) && defined( TCHAR_IS_CHAR ) //designed for windows/x360, not built/tested with wide characters, not intended for release builds (but probably wouldn't damage anything)
  14. # define ENABLE_RUNTIME_STACK_TRANSLATION //uncomment to enable runtime stack translation tools. All of which use on-demand loading of necessary dll's and pdb's
  15. #endif
  16. #if defined( ENABLE_RUNTIME_STACK_TRANSLATION )
  17. //#define ENABLE_THREAD_PARENT_STACK_TRACING 1 //uncomment to actually enable tracking stack traces from threads and jobs to their parent thread. Must also define THREAD_PARENT_STACK_TRACE_SUPPORTED in threadtools.h
  18. # if defined( ENABLE_THREAD_PARENT_STACK_TRACING )
  19. # define THREAD_PARENT_STACK_TRACE_LENGTH 32
  20. # endif
  21. #endif
  22. PLATFORM_INTERFACE int GetCallStack( void **pReturnAddressesOut, int iArrayCount, int iSkipCount );
  23. //ONLY WORKS IF THE CRAWLED PORTION OF THE STACK DISABLES FRAME POINTER OMISSION (/Oy-) "vpc /nofpo"
  24. PLATFORM_INTERFACE int GetCallStack_Fast( void **pReturnAddressesOut, int iArrayCount, int iSkipCount );
  25. typedef int (*FN_GetCallStack)( void **pReturnAddressesOut, int iArrayCount, int iSkipCount );
  26. //where we'll find our PDB's for win32.
  27. PLATFORM_INTERFACE void SetStackTranslationSymbolSearchPath( const char *szSemicolonSeparatedList = NULL );
  28. PLATFORM_INTERFACE void StackToolsNotify_LoadedLibrary( const char *szLibName );
  29. //maximum output sample "tier0.dll!TranslateStackInfo - u:\Dev\L4D\src\tier0\stacktools.cpp(162) + 4 bytes"
  30. enum TranslateStackInfo_StyleFlags_t
  31. {
  32. TSISTYLEFLAG_NONE = 0,
  33. TSISTYLEFLAG_MODULENAME = (1<<0), //start with module Sample: "tier0.dll!"
  34. TSISTYLEFLAG_SYMBOLNAME = (1<<1), //include the symbol name Sample: "TranslateStackInfo"
  35. TSISTYLEFLAG_FULLPATH = (1<<2), //include full path Sample: "u:\Dev\L4D\src\tier0\stacktools.cpp"
  36. TSISTYLEFLAG_SHORTPATH = (1<<3), //only include 2 directories Sample: "\src\tier0\stacktools.cpp"
  37. TSISTYLEFLAG_LINE = (1<<4), //file line number Sample: "(162)"
  38. TSISTYLEFLAG_LINEANDOFFSET = (1<<5), //file line + offset Sample: "(162) + 4 bytes"
  39. TSISTYLEFLAG_LAST = TSISTYLEFLAG_LINEANDOFFSET,
  40. TSISTYLEFLAG_DEFAULT = (TSISTYLEFLAG_MODULENAME | TSISTYLEFLAG_SYMBOLNAME | TSISTYLEFLAG_FULLPATH | TSISTYLEFLAG_LINEANDOFFSET), //produces sample above
  41. };
  42. //Generates a formatted list of function information, returns number of translated entries
  43. //On 360 this generates a string that can be decoded by VXConsole in print functions. Optimal path for translation because it's one way. Other paths require multiple transactions.
  44. PLATFORM_INTERFACE int TranslateStackInfo( const void * const *pCallStack, int iCallStackCount, tchar *szOutput, int iOutBufferSize, const tchar *szEntrySeparator, TranslateStackInfo_StyleFlags_t style = TSISTYLEFLAG_DEFAULT );
  45. PLATFORM_INTERFACE void PreloadStackInformation( void * const *pAddresses, int iAddressCount ); //caches data and reduces communication with VXConsole to speed up 360 decoding when using any of the Get***FromAddress() functions. Nop on PC.
  46. PLATFORM_INTERFACE bool GetFileAndLineFromAddress( const void *pAddress, tchar *pFileNameOut, int iMaxFileNameLength, uint32 &iLineNumberOut, uint32 *pDisplacementOut = NULL );
  47. PLATFORM_INTERFACE bool GetSymbolNameFromAddress( const void *pAddress, tchar *pSymbolNameOut, int iMaxSymbolNameLength, uint64 *pDisplacementOut = NULL );
  48. PLATFORM_INTERFACE bool GetModuleNameFromAddress( const void *pAddress, tchar *pModuleNameOut, int iMaxModuleNameLength );
  49. class PLATFORM_CLASS CCallStackStorage //a helper class to grab a stack trace as close to the leaf code surface as possible, then pass it on to deeper functions intact with less unpredictable inlining pollution
  50. {
  51. public:
  52. CCallStackStorage( FN_GetCallStack GetStackFunction = GetCallStack, uint32 iSkipCalls = 0 );
  53. CCallStackStorage( const CCallStackStorage &copyFrom )
  54. {
  55. iValidEntries = copyFrom.iValidEntries;
  56. // warning C6204: Possible buffer overrun in call to 'memcpy': use of unchecked parameter 'src'
  57. ANALYZE_SUPPRESS( 6204 )
  58. memcpy( pStack, copyFrom.pStack, sizeof( void * ) * copyFrom.iValidEntries );
  59. }
  60. void *pStack[128]; //probably too big, possibly too small for some applications. Don't want to spend the time figuring out how to generalize this without templatizing pollution or mallocs
  61. uint32 iValidEntries;
  62. };
  63. //Hold onto one of these to denote the top of a functional stack trace. Also allows us to string together threads to their parents
  64. class PLATFORM_CLASS CStackTop_Base
  65. {
  66. protected:
  67. #if defined( ENABLE_RUNTIME_STACK_TRANSLATION )
  68. CStackTop_Base *m_pPrevTop;
  69. void *m_pStackBase;
  70. void *m_pReplaceAddress;
  71. void * const *m_pParentStackTrace;
  72. int m_iParentStackTraceLength;
  73. #endif
  74. };
  75. //makes a copy of the parent stack
  76. class PLATFORM_CLASS CStackTop_CopyParentStack : public CStackTop_Base
  77. {
  78. public:
  79. CStackTop_CopyParentStack( void * const * pParentStackTrace, int iParentStackTraceLength );
  80. ~CStackTop_CopyParentStack( void );
  81. };
  82. //just references the parent stack. Assuming that you'll keep that memory around as long as you're keeping this Stack Top marker.
  83. class PLATFORM_CLASS CStackTop_ReferenceParentStack : public CStackTop_Base
  84. {
  85. public:
  86. CStackTop_ReferenceParentStack( void * const * pParentStackTrace = NULL, int iParentStackTraceLength = 0 );
  87. ~CStackTop_ReferenceParentStack( void );
  88. void ReleaseParentStackReferences( void ); //in case you need to delete the parent stack trace before this class goes out of scope
  89. };
  90. //Encodes data so that every byte's most significant bit is a 1. Ensuring no null terminators.
  91. //This puts the encoded data in the 128-255 value range. Leaving all standard ascii characters for control.
  92. //Returns string length (not including the written null terminator as is standard).
  93. //Or if the buffer is too small. Returns negative of necessary buffer size (including room needed for null terminator)
  94. PLATFORM_INTERFACE int EncodeBinaryToString( const void *pToEncode, int iDataLength, char *pEncodeOut, int iEncodeBufferSize );
  95. //Decodes a string produced by EncodeBinaryToString(). Safe to decode in place if you don't mind trashing your string, binary byte count always less than string byte count.
  96. //Returns:
  97. // >= 0 is the decoded data size
  98. // INT_MIN (most negative value possible) indicates an improperly formatted string (not our data)
  99. // all other negative values are the negative of how much dest buffer size is necessary.
  100. PLATFORM_INTERFACE int DecodeBinaryFromString( const char *pString, void *pDestBuffer, int iDestBufferSize, char **ppParseFinishOut = NULL );
  101. // 360<->VXConsole specific communication definitions
  102. #define XBX_CALLSTACKDECODEPREFIX ":CSDECODE["
  103. enum StackTranslation_BinaryHandler_Command_t
  104. {
  105. ST_BHC_LOADEDLIBARY,
  106. ST_BHC_GETTRANSLATIONINFO,
  107. };
  108. #pragma pack(push)
  109. #pragma pack(1)
  110. struct FullStackInfo_t
  111. {
  112. const void *pAddress;
  113. char szModuleName[24];
  114. char szFileName[MAX_PATH/2];
  115. char szSymbol[64];
  116. uint32 iLine;
  117. uint32 iSymbolOffset;
  118. };
  119. #pragma pack(pop)
  120. #endif //#ifndef TIER0_STACKTOOLS_H