debug_stack.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /////////////////////////////////////////////////////////////////////////EA-V1
  19. // $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_stack.h $
  20. // $Author: mhoffe $
  21. // $Revision: #1 $
  22. // $DateTime: 2003/07/03 11:55:26 $
  23. //
  24. // ©2003 Electronic Arts
  25. //
  26. // Stack walker
  27. //////////////////////////////////////////////////////////////////////////////
  28. #ifdef _MSC_VER
  29. # pragma once
  30. #endif
  31. #ifndef DEBUG_STACK_H // Include guard
  32. #define DEBUG_STACK_H
  33. /// \brief stack walker class (singleton)
  34. class DebugStackwalk
  35. {
  36. friend class Debug;
  37. DebugStackwalk(const DebugStackwalk&);
  38. DebugStackwalk& operator=(DebugStackwalk&);
  39. // private so that only Debug can create and destroy us
  40. DebugStackwalk(void);
  41. ~DebugStackwalk();
  42. public:
  43. /// \brief a stack trace signature
  44. class Signature
  45. {
  46. // makes life easier :)
  47. friend class DebugStackwalk;
  48. /// max # of possible addresses
  49. enum { MAX_ADDR = 256 };
  50. /// number of addresses
  51. unsigned m_numAddr;
  52. /// addresses
  53. unsigned m_addr[MAX_ADDR];
  54. public:
  55. explicit Signature(void): m_numAddr(0) {}
  56. Signature(const Signature &src);
  57. Signature& operator=(const Signature& src);
  58. /**
  59. \brief Determine the number of addresses in this signature.
  60. \return number of addresses in this signature
  61. */
  62. unsigned Size(void) const { return m_numAddr; }
  63. /**
  64. \brief Get a single address from the signature.
  65. The address at index 0 is always on top of the stack.
  66. \param n index, 0..Size()-1
  67. \return signature address
  68. */
  69. unsigned GetAddress(int n) const;
  70. /**
  71. \brief Strong ordering operator.
  72. Signatures are ordered by looking at the bottom of the stack
  73. first. Implemented inline so that STL algorithms using this
  74. operator can be compiled more efficiently.
  75. */
  76. bool operator<(const Signature &other) const
  77. {
  78. unsigned m=m_numAddr<other.m_numAddr?m_numAddr:other.m_numAddr;
  79. for (unsigned k=0;k<m;k++)
  80. {
  81. if (m_addr[m_numAddr-k-1]<other.m_addr[other.m_numAddr-k-1])
  82. return true;
  83. if (m_addr[m_numAddr-k-1]>other.m_addr[other.m_numAddr-k-1])
  84. return false;
  85. }
  86. return m_numAddr<other.m_numAddr;
  87. }
  88. /**
  89. \brief Determines symbol for given address.
  90. The data is returned in the form
  91. \<addr\> \<module\>+NN, \<sym\>+NN, \<file\>:\<line\>+NN
  92. \param addr function address
  93. \param buf return buffer
  94. \param bufSize size of return buffer, minimum is 64 bytes (256 recommended)
  95. */
  96. static void GetSymbol(unsigned addr, char *buf, unsigned bufSize);
  97. /**
  98. \brief Determines symbol for given address.
  99. \param addr function address
  100. \param bufMod module buffer, may be NULL
  101. \param sizeMod size of buffer, including NUL, minimum 16 if given
  102. \param relMod relative address within module, may be NULL
  103. \param bufSym symbol buffer, may be NULL
  104. \param sizeSym size of buffer, including NUL
  105. \param relSym relative address within symbol, may be NULL
  106. \param bufFile file name buffer, may be NULL
  107. \param sizeFile size of buffer, including NUL
  108. \param line line number, may be NULL
  109. \param relLine relative address within line, may be NULL
  110. */
  111. static void GetSymbol(unsigned addr,
  112. char *bufMod, unsigned sizeMod, unsigned *relMod,
  113. char *bufSym, unsigned sizeSym, unsigned *relSym,
  114. char *bufFile, unsigned sizeFile, unsigned *line, unsigned *relLine);
  115. };
  116. /** \internal
  117. \brief Returns dbghelp.dll DLL handle.
  118. \return dbghelp.dll DLL handle
  119. */
  120. static void *GetDbghelpHandle(void);
  121. /** \internal
  122. \brief Checks if dbghelp.dll version is old.
  123. \return true if old version, false if not
  124. */
  125. static bool IsOldDbghelp(void);
  126. /**
  127. \brief Walks the stack from the given address.
  128. \param sig stack signature to return
  129. \param ctx processor context, if NULL then use current address
  130. \return number of addresses found
  131. */
  132. static int StackWalk(Signature &sig, struct _CONTEXT *ctx=0);
  133. };
  134. /**
  135. \brief Dumps a complete signature with symbols.
  136. \param dbg debug instance
  137. \param sig signature
  138. \return debug instance
  139. */
  140. Debug& operator<<(Debug &dbg, const DebugStackwalk::Signature &sig);
  141. #endif // DEBUG_STACK_H