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

📄 stackwalker.cpp

📁 Extended C/C++ Dynamic Memory Control And Debug Library
💻 CPP
📖 第 1 页 / 共 4 页
字号:
  pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
  pSym->MaxNameLength = STACKWALK_MAX_NAMELEN;

#if 1
  memset(&Line, 0, sizeof(Line));
#else
  Line.Key = NULL;
  Line.LineNumber = 0;
  Line.FileName = NULL;
  Line.Address = 0;
#endif
  Line.SizeOfStruct = sizeof(Line);

#if 0
  memset(&Module, 0, sizeof(Module));
#else
  Module.BaseOfImage = 0;
  Module.ImageSize = 0;
  Module.TimeDateStamp = 0;
  Module.CheckSum = 0;
  Module.NumSyms = 0;
  Module.SymType = SymNone;
  *Module.ModuleName = '\0';
  *Module.ImageName = '\0';
  *Module.LoadedImageName = '\0';
#endif
  Module.SizeOfStruct = sizeof(Module);

  for (frameNum = 0; ; ++frameNum )
  {
    // get next stack frame (StackWalk64(), SymFunctionTableAccess64(), SymGetModuleBase64())
    // if this returns ERROR_INVALID_ADDRESS (487) or ERROR_NOACCESS (998), you can
    // assume that either you are done, or that the stack is so hosed that the next
    // deeper frame could not be found.
    // CONTEXT need not to be suplied if imageTyp is IMAGE_FILE_MACHINE_I386!
    if ( ! this->m_sw->pSW(imageType, this->m_hProcess, hThread, &s, &c, myReadProcMem, this->m_sw->pSFTA, this->m_sw->pSGMB, NULL) )
    {
      this->OnDbgHelpErr("StackWalk64", GetLastError(), s.AddrPC.Offset);
      break;
    }

    csEntry.offset = s.AddrPC.Offset;
    csEntry.name[0] = 0;
    csEntry.undName[0] = 0;
    csEntry.undFullName[0] = 0;
    csEntry.offsetFromSmybol = 0;
    csEntry.offsetFromLine = 0;
    csEntry.lineFileName[0] = 0;
    csEntry.lineNumber = 0;
    csEntry.loadedImageName[0] = 0;
    csEntry.moduleName[0] = 0;
    csEntry.symTypeString = NULL;
    if (s.AddrPC.Offset == s.AddrReturn.Offset)
    {
      this->OnDbgHelpErr("StackWalk64-Endless-Callstack!", 0, s.AddrPC.Offset);
      break;
    }
    if ( s.AddrPC.Offset != 0 )
    {
      // we seem to have a valid PC
     if ((m_pentry = search_entry(s.AddrPC.Offset)) == NULL)  /* search if address is already known */
     {// address unknown
      // show procedure info (SymGetSymFromAddr64())
      if (this->m_sw->pSGSFA(this->m_hProcess, s.AddrPC.Offset, &(csEntry.offsetFromSmybol), pSym) != FALSE)
      {
        // TODO: Mache dies sicher...!
        strcpy_s(csEntry.name, pSym->Name);
        // UnDecorateSymbolName()
        this->m_sw->pUDSN( pSym->Name, csEntry.undName, STACKWALK_MAX_NAMELEN, UNDNAME_NAME_ONLY );
        this->m_sw->pUDSN( pSym->Name, csEntry.undFullName, STACKWALK_MAX_NAMELEN, UNDNAME_COMPLETE );
      }
      else
      {
        this->OnDbgHelpErr("SymGetSymFromAddr64", GetLastError(), s.AddrPC.Offset);
      }

      // show line number info, NT5.0-method (SymGetLineFromAddr64())
      if (this->m_sw->pSGLFA != NULL )
      { // yes, we have SymGetLineFromAddr64()
        if (this->m_sw->pSGLFA(this->m_hProcess, s.AddrPC.Offset, &(csEntry.offsetFromLine), &Line) != FALSE)
        {
          csEntry.lineNumber = Line.LineNumber;
          // TODO: Mache dies sicher...!
          strcpy_s(csEntry.lineFileName, Line.FileName);
        }
        else
        {
          this->OnDbgHelpErr("SymGetLineFromAddr64", GetLastError(), s.AddrPC.Offset);
        }
      } // yes, we have SymGetLineFromAddr64()

      // show module info (SymGetModuleInfo64())
      if (this->m_sw->GetModuleInfo(this->m_hProcess, s.AddrPC.Offset, &Module ) != FALSE)
      { // got module info OK
#if 0   // @@@@ XMEM: not necessary for XMEM
        switch ( Module.SymType )
        {
        case SymNone:
          csEntry.symTypeString = "-nosymbols-";
          break;
        case SymCoff:
          csEntry.symTypeString = "COFF";
          break;
        case SymCv:
          csEntry.symTypeString = "CV";
          break;
        case SymPdb:
          csEntry.symTypeString = "PDB";
          break;
        case SymExport:
          csEntry.symTypeString = "-exported-";
          break;
        case SymDeferred:
          csEntry.symTypeString = "-deferred-";
          break;
        case SymSym:
          csEntry.symTypeString = "SYM";
          break;
        case SymVirtual:
          csEntry.symTypeString = "Virtual";
          break;
#if API_VERSION_NUMBER >= 9
        case SymDia:
          csEntry.symTypeString = "DIA";
          break;
#endif
        default:
          //_snprintf( ty, sizeof ty, "symtype=%ld", (long) Module.SymType );
          csEntry.symTypeString = NULL;
          break;
        }
#endif  // /*@@@@ XMEM*/
        // TODO: Mache dies sicher...!
        strcpy_s(csEntry.moduleName, Module.ModuleName);
// /*@@@@ XMEM*/       csEntry.baseOfImage = Module.BaseOfImage;
// /*@@@@ XMEM*/       strcpy_s(csEntry.loadedImageName, Module.LoadedImageName);
      } // got module info OK
      else
      {
        this->OnDbgHelpErr("SymGetModuleInfo64", GetLastError(), s.AddrPC.Offset);
      }
     }
    } // we seem to have a valid PC
    else
    {
      m_pentry = NULL;      /* invalid address */
    }

    CallstackEntryType et = nextEntry;
    if (frameNum == 0)
      et = firstEntry;
    this->OnCallstackEntry(et, csEntry);
    
    if (s.AddrReturn.Offset == 0)
    {
      this->OnCallstackEntry(lastEntry, csEntry);
      SetLastError(ERROR_SUCCESS);
      break;
    }
  } // for ( frameNum )

// /*@@@@ XMEM*/ cleanup:
// /*@@@@ XMEM*/   if (pSym) 
// /*@@@@ XMEM*/     free( pSym );

  if (context == NULL)
    ResumeThread(hThread);

  return TRUE;
}

BOOL __stdcall StackWalker::myReadProcMem(
    HANDLE      hProcess,
    DWORD64     qwBaseAddress,
    PVOID       lpBuffer,
    DWORD       nSize,
    LPDWORD     lpNumberOfBytesRead
    )
{
  if (s_readMemoryFunction == NULL)
  {
    SIZE_T st;
    BOOL bRet = ReadProcessMemory(hProcess, (LPVOID) qwBaseAddress, lpBuffer, nSize, &st);
    *lpNumberOfBytesRead = (DWORD) st;
    //printf("ReadMemory: hProcess: %p, baseAddr: %p, buffer: %p, size: %d, read: %d, result: %d\n", hProcess, (LPVOID) qwBaseAddress, lpBuffer, nSize, (DWORD) st, (DWORD) bRet);
    return bRet;
  }
  else
  {
    return s_readMemoryFunction(hProcess, qwBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead, s_readMemoryFunction_UserData);
  }
}

void StackWalker::OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion)
{
  CHAR buffer[STACKWALK_MAX_NAMELEN];
  if (fileVersion == 0)
    _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "%s:%s (%p), size: %d (result: %d), SymType: '%s', PDB: '%s'\n", img, mod, (LPVOID) baseAddr, size, result, symType, pdbName);
  else
  {
    DWORD v4 = (DWORD) fileVersion & 0xFFFF;
    DWORD v3 = (DWORD) (fileVersion>>16) & 0xFFFF;
    DWORD v2 = (DWORD) (fileVersion>>32) & 0xFFFF;
    DWORD v1 = (DWORD) (fileVersion>>48) & 0xFFFF;
    _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "%s:%s (%p), size: %d (result: %d), SymType: '%s', PDB: '%s', fileVersion: %d.%d.%d.%d\n", img, mod, (LPVOID) baseAddr, size, result, symType, pdbName, v1, v2, v3, v4);
  }
  OnOutput(buffer);
}

void StackWalker::OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry)
{
  CHAR buffer[STACKWALK_MAX_NAMELEN];
  if ( (eType != lastEntry) && (entry.offset != 0) )
  {
    if (entry.name[0] == 0)
      strcpy_s(entry.name, "(function-name not available)");
    if (entry.undName[0] != 0)
      strcpy_s(entry.name, entry.undName);
    if (entry.undFullName[0] != 0)
      strcpy_s(entry.name, entry.undFullName);
    if (entry.lineFileName[0] == 0)
    {
      strcpy_s(entry.lineFileName, "(filename not available)");
      if (entry.moduleName[0] == 0)
        strcpy_s(entry.moduleName, "(module-name not available)");
      _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "%p (%s): %s: %s\n", (LPVOID) entry.offset, entry.moduleName, entry.lineFileName, entry.name);
    }
    else
      _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "%s (%d): %s\n", entry.lineFileName, entry.lineNumber, entry.name);
    OnOutput(buffer);
  }
}

void StackWalker::OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr)
{
  CHAR buffer[STACKWALK_MAX_NAMELEN];
  _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "ERROR: %s, GetLastError: %d (Address: %p)\n", szFuncName, gle, (LPVOID) addr);
  OnOutput(buffer);
}

void StackWalker::OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName)
{
  CHAR buffer[STACKWALK_MAX_NAMELEN];
  _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "SymInit: Symbol-SearchPath: '%s', symOptions: %d, UserName: '%s'\n", szSearchPath, symOptions, szUserName);
  OnOutput(buffer);
  // Also display the OS-version
#if _MSC_VER <= 1200
  OSVERSIONINFOA ver;
  ZeroMemory(&ver, sizeof(OSVERSIONINFOA));
  ver.dwOSVersionInfoSize = sizeof(ver);
  if (GetVersionExA(&ver) != FALSE)
  {
    _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "OS-Version: %d.%d.%d (%s)\n",
    ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber,
    ver.szCSDVersion);
    OnOutput(buffer);
  }
#else
  OSVERSIONINFOEXA ver;
  ZeroMemory(&ver, sizeof(OSVERSIONINFOEXA));
  ver.dwOSVersionInfoSize = sizeof(ver);
  if (GetVersionExA( (OSVERSIONINFOA*) &ver) != FALSE)
  {
    _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "OS-Version: %d.%d.%d (%s) 0x%x-0x%x\n", 
      ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber,
      ver.szCSDVersion, ver.wSuiteMask, ver.wProductType);
    OnOutput(buffer);
  }
#endif
}

void StackWalker::OnOutput(LPCSTR buffer)
{
  if (m_pos) 
  {
    // Write to output stream
    *m_pos << buffer;
  } 
  else if (m_pwos) 
  {
    // Unicode output stream is ready. Use the output stream.
    // Convert ASCII stream to UNICODE stream.
    size_t iLen = strlen(buffer) + 1; // Including NULL termination
    wchar_t *pBufferW = (wchar_t*)malloc(sizeof(wchar_t)*iLen);
    if (pBufferW)
    {
      for (u32 i = 0; i < iLen; i++) 
      {
        pBufferW[i] = (wchar_t)buffer[i];
      }
      // Write to output stream
      *m_pwos << pBufferW;
      // Delete pBufferW
      free(pBufferW);
    }
  } 
  else 
  {
    // Write to console.
    OutputDebugStringA(buffer);
  }
}

void StackWalker::OnOutput(LPCWSTR buffer)
{
  if (m_pos) 
  {
    // ASCII output stream is ready. Use the output stream.
    // Convert UNICODE stream to ASCII stream.
#if UNICODE
    u32 iLen = lstrlen(buffer) + 1; // Including NULL termination
#else
    u32 iLen = lstrlen((LPCSTR)buffer) + 1; // Including NULL termination
#endif
    char *pBufferA = (char*)malloc(sizeof(char)*iLen);
    if (pBufferA)
    {
      for (u32 i = 0; i < iLen; i++) 
      {
        pBufferA[i] = (char)buffer[i];
      }
      // Write to output stream
      *m_pos << pBufferA;
      // Delete pBufferA
      free(pBufferA);
    }
  } 
  else if (m_pwos) 
  {
    // Write to output stream
    *m_pwos << buffer;
  } 
  else 
  {
    // Write to console.
    OutputDebugStringW(buffer);
  }
}

⌨️ 快捷键说明

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