⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stackwalker.cpp

📁 奇迹世界公用文件源代码,研究网络游戏的朋友可以研究下
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        if ( (pHashEntry->cRemovedFlag <= 0) || (pHashEntry->cRemovedFlag > 1) ) {
          ulCount++;
          if (g_CallstackOutputType == ACOutput_XML)
            _ftprintf(fFile, _T("<LEAK requestID=\"%u\" size=\"%u\">\n"), pHashEntry->lRequestID, pHashEntry->nDataSize);
          else
            _ftprintf(fFile, _T("RequestID: %12i, Removed: %i, Size: %12i\n"), pHashEntry->lRequestID, pHashEntry->cRemovedFlag, pHashEntry->nDataSize);
          CONTEXT c;
          memset( &c, '\0', sizeof c );
          c.Eip = pHashEntry->dwEIPOffset;
          c.Ebp = pHashEntry->dwESPOffset;
          ShowStackRM( NULL, c, fFile, &ReadProcMemoryFromHash, (HANDLE) pHashEntry->lRequestID);
          // Count the number of leaky bytes
          if (pHashEntry->nDataSize > 0)
            ulLeaksByte += pHashEntry->nDataSize;
          else
            ulLeaksByte++;  // If memory was allocated with zero bytes, then just increase the counter 1

          if (g_CallstackOutputType == ACOutput_XML)
            _ftprintf(fFile, _T("</LEAK>\n"));  // terminate the xml-node
        }
        pHashEntry = pHashEntry->Next;
      }
    }
  }
  if (g_CallstackOutputType != ACOutput_XML)
    _ftprintf(fFile, _T("\n**** Number of leaks: %i\n"), ulCount);
  return ulLeaksByte;
}  // AllocHashOutLeaks

// Write all used memory to a file
void AllocHashOut(FILE *fFile) {
  ULONG ulTemp;
  AllocHashEntryType *pHashEntry;

  for(ulTemp = 0; ulTemp < ALLOC_HASH_ENTRIES; ulTemp++) {
    pHashEntry = &AllocHashTable[ulTemp];
    if (pHashEntry->lRequestID != 0) {
      while(pHashEntry != NULL) {
        if (g_CallstackOutputType == ACOutput_XML)
          _ftprintf(fFile, _T("<MEMUSED requestID=\"%u\" size=\"%u\"\n"), pHashEntry->lRequestID, pHashEntry->nDataSize);
        else
          _ftprintf(fFile, _T("RequestID: %12i, Removed: %i, Size: %12i\n"), pHashEntry->lRequestID, pHashEntry->cRemovedFlag, pHashEntry->nDataSize);
        pHashEntry = pHashEntry->Next;
      }
    }
  }
}  // AllocHashOut

/*******************************************************************************
 * Ende der Hash-Tabelle
 *******************************************************************************/


// The follwoing is copied from dbgint.h:
// <CRT_INTERNALS>
/*
 * For diagnostic purpose, blocks are allocated with extra information and
 * stored in a doubly-linked list.  This makes all blocks registered with
 * how big they are, when they were allocated, and what they are used for.
 */

#define nNoMansLandSize 4

typedef struct _CrtMemBlockHeader
{
        struct _CrtMemBlockHeader * pBlockHeaderNext;
        struct _CrtMemBlockHeader * pBlockHeaderPrev;
        char *                      szFileName;
        int                         nLine;
#ifdef _WIN64
        /* These items are reversed on Win64 to eliminate gaps in the struct
         * and ensure that sizeof(struct)%16 == 0, so 16-byte alignment is
         * maintained in the debug heap.
         */
        int                         nBlockUse;
        size_t                      nDataSize;
#else  /* _WIN64 */
        size_t                      nDataSize;
        int                         nBlockUse;
#endif  /* _WIN64 */
        long                        lRequest;
        unsigned char               gap[nNoMansLandSize];
        /* followed by:
         *  unsigned char           data[nDataSize];
         *  unsigned char           anotherGap[nNoMansLandSize];
         */
} _CrtMemBlockHeader;
#define pbData(pblock) ((unsigned char *)((_CrtMemBlockHeader *)pblock + 1))
#define pHdr(pbData) (((_CrtMemBlockHeader *)pbData)-1)
 
// </CRT_INTERNALS>




// Global data:
static BOOL g_bInitialized = FALSE;
static HINSTANCE g_hImagehlpDll = NULL;

static DWORD g_dwShowCount = 0;  // increase at every ShowStack-Call
static CRITICAL_SECTION g_csFileOpenClose = {0};

// Is used for syncronising call to MyAllocHook (to prevent reentrant calls)
static LONG g_lMallocCalled = 0;

static _CRT_ALLOC_HOOK pfnOldCrtAllocHook = NULL;

// Deaktivate AllocHook, by increasing the Syncronisation-Counter
/*
static void DeactivateMallocStackwalker(void) {
  InterlockedIncrement(&g_lMallocCalled);
}
*/


// MyAllocHook is Single-Threaded, that means the the calls are serialized in the calling function!
// Special case for VC 5
#if _MSC_VER <= 1100 
static int MyAllocHook(int nAllocType, void *pvData, 
      size_t nSize, int nBlockUse, long lRequest, 
      const char * szFileName, int nLine ) {
#else
static int MyAllocHook(int nAllocType, void *pvData, 
      size_t nSize, int nBlockUse, long lRequest, 
      const unsigned char * szFileName, int nLine ) {
#endif
  static TCHAR *operation[] = { _T(""), _T("ALLOCATIONG"), _T("RE-ALLOCATING"), _T("FREEING") };
  static TCHAR *blockType[] = { _T("Free"), _T("Normal"), _T("CRT"), _T("Ignore"), _T("Client") };

#ifdef IGNORE_CRT_ALLOC
  if (_BLOCK_TYPE(nBlockUse) == _CRT_BLOCK)  // Ignore internal C runtime library allocations
    return TRUE;
#endif
  extern int _crtDbgFlag;
  if  ( ((_CRTDBG_ALLOC_MEM_DF & _crtDbgFlag) == 0) && ( (nAllocType == _HOOK_ALLOC) || (nAllocType == _HOOK_REALLOC) ) )
  {
    // Someone has disabled that the runtime should log this allocation
    // so we do not log this allocation
    if (pfnOldCrtAllocHook != NULL)
      pfnOldCrtAllocHook(nAllocType, pvData, nSize, nBlockUse, lRequest, szFileName, nLine);
    return TRUE;
  }

  // Prevent from reentrat calls
  if (InterlockedIncrement(&g_lMallocCalled) > 1) { // I was already called
    InterlockedDecrement(&g_lMallocCalled);
    // call the previous alloc hook
    if (pfnOldCrtAllocHook != NULL)
      pfnOldCrtAllocHook(nAllocType, pvData, nSize, nBlockUse, lRequest, szFileName, nLine);
    return TRUE;
  }

  if (g_ulShowStackAtAlloc > 0) {
    AllocCheckFileOpen();  // Open logfile
  }

   _ASSERT( (nAllocType == _HOOK_ALLOC) || (nAllocType == _HOOK_REALLOC) || (nAllocType == _HOOK_FREE) );
   _ASSERT( ( _BLOCK_TYPE(nBlockUse) >= 0 ) && ( _BLOCK_TYPE(nBlockUse) < 5 ) );

  if (nAllocType == _HOOK_FREE) { // freeing
    // Try to get the header information
    if (_CrtIsValidHeapPointer(pvData)) {  // it is a valid Heap-Pointer
      // get the ID
      _CrtMemBlockHeader *pHead;
      // get a pointer to memory block header
      pHead = pHdr(pvData);
      nSize = pHead->nDataSize;
      lRequest = pHead->lRequest; // This is the ID!

      if (pHead->nBlockUse == _IGNORE_BLOCK)
      {
        InterlockedDecrement(&g_lMallocCalled);
        if (pfnOldCrtAllocHook != NULL)
          pfnOldCrtAllocHook(nAllocType, pvData, nSize, nBlockUse, lRequest, szFileName, nLine);
        return TRUE;
      }
    }
  }

  if (g_ulShowStackAtAlloc > 0) {
    _ftprintf( g_fFile, _T("##### Memory operation: %s a %d-byte '%s' block (# %ld)"),
      operation[nAllocType], nSize, blockType[_BLOCK_TYPE(nBlockUse)], lRequest );
    if ( pvData != NULL )
      _ftprintf( g_fFile, _T(" at 0x%X"), pvData );
    _ftprintf(g_fFile, _T("\n"));
  }

  if (nAllocType == _HOOK_FREE) { // freeing:
    if (lRequest != 0) {  // RequestID was found
      BOOL bRet;
      // Try to find the RequestID in the Hash-Table, mark it that it was freed
      bRet = AllocHashRemove(lRequest);
      if(g_ulShowStackAtAlloc > 0) {
        if (bRet == FALSE) {
          // RequestID not found!
          _ftprintf(g_fFile, _T("###### RequestID not found in hash table for FREEING (%i)!\n"), lRequest);
        }
      } // g_ulShowStackAtAlloc > 0
    }
    else {
      if(g_ulShowStackAtAlloc > 0) {
      // No valid RequestID found, display error
      _ftprintf(g_fFile, _T("###### No valid RequestID for FREEING! (0x%X)\n"), pvData);
 
      }
    }
  }  // freeing

  if (nAllocType == _HOOK_REALLOC) { // re-allocating
    // Try to get the header information
    if (_CrtIsValidHeapPointer(pvData)) {  // it is a valid Heap-Pointer
      BOOL bRet;
      LONG lReallocRequest;
      // get the ID
      _CrtMemBlockHeader *pHead;
      // get a pointer to memory block header
      pHead = pHdr(pvData);
      // Try to find the RequestID in the Hash-Table, mark it that it was freed
      lReallocRequest = pHead->lRequest;
      bRet = AllocHashRemove(lReallocRequest);
      if (g_ulShowStackAtAlloc > 0) {
        if (bRet == FALSE) {
          // RequestID not found!
          _ftprintf(g_fFile, _T("###### RequestID not found in hash table for RE-ALLOCATING (%i)!\n"), lReallocRequest);
        }
        else {
          _ftprintf(g_fFile, _T("##### Implicit freeing because of re-allocation (# old: %ld, new: %ld)\n"), lReallocRequest, lRequest);
        }
      }  // g_ulShowStackAtAlloc > 0
    }  // ValidHeapPointer
  }  // re-allocating

  if ( (g_ulShowStackAtAlloc < 3) && (nAllocType == _HOOK_FREE) ) {
    InterlockedDecrement(&g_lMallocCalled);
    // call the previous alloc hook
    if (pfnOldCrtAllocHook != NULL)
      pfnOldCrtAllocHook(nAllocType, pvData, nSize, nBlockUse, lRequest, szFileName, nLine);
    return TRUE;
  }

  // Get the context DIESES of this Thread
  HANDLE hThread;
  if (DuplicateHandle( GetCurrentProcess(), GetCurrentThread(),
    GetCurrentProcess(), &hThread, 0, false, DUPLICATE_SAME_ACCESS ) == 0) {
      // Something was wrong...
      _ftprintf(g_fFile, _T("###### Could not call 'DuplicateHandle' successfully\n"));
      InterlockedDecrement(&g_lMallocCalled);
      // call the previous alloc hook
      if (pfnOldCrtAllocHook != NULL)
        pfnOldCrtAllocHook(nAllocType, pvData, nSize, nBlockUse, lRequest, szFileName, nLine);
      return TRUE;
  }

  CONTEXT c;
  memset( &c, '\0', sizeof c );
  c.ContextFlags = CONTEXT_FULL;

  // init CONTEXT record so we know where to start the stackwalk
  if ( GetThreadContext( hThread, &c )  == 0) {
    if(g_ulShowStackAtAlloc > 1) {
      _ftprintf(g_fFile, _T("###### Could not call 'GetThreadContext' successfully\n"));
    }
    InterlockedDecrement(&g_lMallocCalled);
    // call the previous alloc hook
    if (pfnOldCrtAllocHook != NULL)
      pfnOldCrtAllocHook(nAllocType, pvData, nSize, nBlockUse, lRequest, szFileName, nLine);
    CloseHandle(hThread);
    return TRUE; // could not get context
  }

  if(g_ulShowStackAtAlloc > 1) {
    if(g_ulShowStackAtAlloc > 2) {
      // output the callstack
      ShowStack( hThread, c, g_fFile);
    }
    else {
      // Output only (re)allocs
      if (nAllocType != _HOOK_FREE) {
        ShowStack( hThread, c, g_fFile);
      }
    }
  }  // g_ulShowStackAtAlloc > 1
  CloseHandle( hThread );

  // Only isert in the Hash-Table if it is not a "freeing"
  if (nAllocType != _HOOK_FREE) {
    if(lRequest != 0) // Always a valid RequestID should be provided (see comments in the header)
      AllocHashInsert(lRequest, c, nSize);
  }

  InterlockedDecrement(&g_lMallocCalled);
  // call the previous alloc hook
  if (pfnOldCrtAllocHook != NULL)
    pfnOldCrtAllocHook(nAllocType, pvData, nSize, nBlockUse, lRequest, szFileName, nLine);
  return TRUE; // allow the memory operation to proceed
}




// ##########################################################################################
// ##########################################################################################
// ##########################################################################################
// ##########################################################################################

#define gle (GetLastError())
#define lenof(a) (sizeof(a) / sizeof((a)[0]))
#define MAXNAMELEN 1024 // max name length for found symbols
#define IMGSYMLEN ( sizeof IMAGEHLP_SYMBOL64 )
#define TTBUFLEN 8096 // for a temp buffer (2^13)



// SymCleanup()
typedef BOOL (__stdcall *tSC)( IN HANDLE hProcess );
tSC pSC = NULL;

// SymFunctionTableAccess64()
typedef PVOID (__stdcall *tSFTA)( HANDLE hProcess, DWORD64 AddrBase );
tSFTA pSFTA = NULL;

// SymGetLineFromAddr64()
typedef BOOL (__stdcall *tSGLFA)( IN HANDLE hProcess, IN DWORD64 dwAddr,
  OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Line );
tSGLFA pSGLFA = NULL;

// SymGetModuleBase64()
typedef DWORD64 (__stdcall *tSGMB)( IN HANDLE hProcess, IN DWORD64 dwAddr );
tSGMB pSGMB = NULL;

// SymGetModuleInfo64()
typedef BOOL (__stdcall *tSGMI)( IN HANDLE hProcess, IN DWORD64 dwAddr, OUT PIMAGEHLP_MODULE64 ModuleInfo );
tSGMI pSGMI = NULL;

// SymGetOptions()
typedef DWORD (__stdcall *tSGO)( VOID );
tSGO pSGO = NULL;

// SymGetSymFromAddr64()
typedef BOOL (__stdcall *tSGSFA)( IN HANDLE hProcess, IN DWORD64 dwAddr,
  OUT PDWORD64 pdwDisplacement, OUT PIMAGEHLP_SYMBOL64 Symbol );
tSGSFA pSGSFA = NULL;

// SymInitialize()
typedef BOOL (__stdcall *tSI)( IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess );
tSI pSI = NULL;

// SymLoadModule64()
typedef DWORD (__stdcall *tSLM)( IN HANDLE hProcess, IN HANDLE hFile,
  IN PSTR ImageName, IN PSTR ModuleName, IN DWORD64 BaseOfDll, IN DWORD SizeOfDll );
tSLM pSLM = NULL;

// SymSetOptions()
typedef DWORD (__stdcall *tSSO)( IN DWORD SymOptions );
tSSO pSSO = NULL;

// StackWalk64()
typedef BOOL (__stdcall *tSW)( 
  DWORD MachineType, 
  HANDLE hProcess,
  HANDLE hThread, 
  LPSTACKFRAME64 StackFrame, 
  PVOID ContextRecord,
  PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
  PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
  PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
  PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress );
tSW pSW = NULL;

// UnDecorateSymbolName()
typedef DWORD (__stdcall WINAPI *tUDSN)( PCSTR DecoratedName, PSTR UnDecoratedName,
  DWORD UndecoratedLength, DWORD Flags );
tUDSN pUDSN = NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -