debughlp.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 768 行 · 第 1/2 页
CPP
768 行
/////////////////////////////////////////////////////////////////////////////
// Name: msw/debughlp.cpp
// Purpose: various Win32 debug helpers
// Author: Vadim Zeitlin
// Modified by:
// Created: 2005-01-08 (extracted from crashrpt.cpp)
// RCS-ID: $Id: debughlp.cpp,v 1.9.2.1 2006/01/21 16:46:44 JS Exp $
// Copyright: (c) 2003-2005 Vadim Zeitlin <vadim@wxwindows.org>
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "wx/msw/debughlp.h"
#if wxUSE_DBGHELP && wxUSE_DYNLIB_CLASS
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// to prevent recursion which could result from corrupted data we limit
// ourselves to that many levels of embedded fields inside structs
static const unsigned MAX_DUMP_DEPTH = 20;
// ----------------------------------------------------------------------------
// globals
// ----------------------------------------------------------------------------
// error message from Init()
static wxString gs_errMsg;
// ============================================================================
// wxDbgHelpDLL implementation
// ============================================================================
// ----------------------------------------------------------------------------
// static members
// ----------------------------------------------------------------------------
#define DEFINE_SYM_FUNCTION(func) wxDbgHelpDLL::func ## _t wxDbgHelpDLL::func = 0
wxDO_FOR_ALL_SYM_FUNCS(DEFINE_SYM_FUNCTION);
#undef DEFINE_SYM_FUNCTION
// ----------------------------------------------------------------------------
// initialization methods
// ----------------------------------------------------------------------------
// load all function we need from the DLL
static bool BindDbgHelpFunctions(const wxDynamicLibrary& dllDbgHelp)
{
#define LOAD_SYM_FUNCTION(name) \
wxDbgHelpDLL::name = (wxDbgHelpDLL::name ## _t) \
dllDbgHelp.GetSymbol(_T(#name)); \
if ( !wxDbgHelpDLL::name ) \
{ \
gs_errMsg += _T("Function ") _T(#name) _T("() not found.\n"); \
return false; \
}
wxDO_FOR_ALL_SYM_FUNCS(LOAD_SYM_FUNCTION);
#undef LOAD_SYM_FUNCTION
return true;
}
// called by Init() if we hadn't done this before
static bool DoInit()
{
wxDynamicLibrary dllDbgHelp(_T("dbghelp.dll"), wxDL_VERBATIM);
if ( dllDbgHelp.IsLoaded() )
{
if ( BindDbgHelpFunctions(dllDbgHelp) )
{
// turn on default options
DWORD options = wxDbgHelpDLL::SymGetOptions();
options |= SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_DEBUG;
wxDbgHelpDLL::SymSetOptions(options);
dllDbgHelp.Detach();
return true;
}
gs_errMsg += _T("\nPlease update your dbghelp.dll version, ")
_T("at least version 5.1 is needed!\n")
_T("(if you already have a new version, please ")
_T("put it in the same directory where the program is.)\n");
}
else // failed to load dbghelp.dll
{
gs_errMsg += _T("Please install dbghelp.dll available free of charge ")
_T("from Microsoft to get more detailed crash information!");
}
gs_errMsg += _T("\nLatest dbghelp.dll is available at ")
_T("http://www.microsoft.com/whdc/ddk/debugging/\n");
return false;
}
/* static */
bool wxDbgHelpDLL::Init()
{
// this flag is -1 until Init() is called for the first time, then it's set
// to either false or true depending on whether we could load the functions
static int s_loaded = -1;
if ( s_loaded == -1 )
{
s_loaded = DoInit();
}
return s_loaded != 0;
}
// ----------------------------------------------------------------------------
// error handling
// ----------------------------------------------------------------------------
/* static */
const wxString& wxDbgHelpDLL::GetErrorMessage()
{
return gs_errMsg;
}
/* static */
void wxDbgHelpDLL::LogError(const wxChar *func)
{
::OutputDebugString(wxString::Format(_T("dbghelp: %s() failed: %s\r\n"),
func, wxSysErrorMsg(::GetLastError())));
}
// ----------------------------------------------------------------------------
// data dumping
// ----------------------------------------------------------------------------
static inline
bool
DoGetTypeInfo(DWORD64 base, ULONG ti, IMAGEHLP_SYMBOL_TYPE_INFO type, void *rc)
{
static HANDLE s_hProcess = ::GetCurrentProcess();
return wxDbgHelpDLL::SymGetTypeInfo
(
s_hProcess,
base,
ti,
type,
rc
) != 0;
}
static inline
bool
DoGetTypeInfo(PSYMBOL_INFO pSym, IMAGEHLP_SYMBOL_TYPE_INFO type, void *rc)
{
return DoGetTypeInfo(pSym->ModBase, pSym->TypeIndex, type, rc);
}
static inline
wxDbgHelpDLL::BasicType GetBasicType(PSYMBOL_INFO pSym)
{
wxDbgHelpDLL::BasicType bt;
return DoGetTypeInfo(pSym, TI_GET_BASETYPE, &bt)
? bt
: wxDbgHelpDLL::BASICTYPE_NOTYPE;
}
/* static */
wxString wxDbgHelpDLL::GetSymbolName(PSYMBOL_INFO pSym)
{
wxString s;
WCHAR *pwszTypeName;
if ( SymGetTypeInfo
(
GetCurrentProcess(),
pSym->ModBase,
pSym->TypeIndex,
TI_GET_SYMNAME,
&pwszTypeName
) )
{
s = wxConvCurrent->cWC2WX(pwszTypeName);
::LocalFree(pwszTypeName);
}
return s;
}
/* static */ wxString
wxDbgHelpDLL::DumpBaseType(BasicType bt, DWORD64 length, PVOID pAddress)
{
if ( !pAddress )
{
return _T("null");
}
if ( ::IsBadReadPtr(pAddress, length) != 0 )
{
return _T("BAD");
}
wxString s;
s.reserve(256);
if ( length == 1 )
{
const BYTE b = *(PBYTE)pAddress;
if ( bt == BASICTYPE_BOOL )
s = b ? _T("true") : _T("false");
else
s.Printf(_T("%#04x"), b);
}
else if ( length == 2 )
{
s.Printf(bt == BASICTYPE_UINT ? _T("%#06x") : _T("%d"),
*(PWORD)pAddress);
}
else if ( length == 4 )
{
bool handled = false;
if ( bt == BASICTYPE_FLOAT )
{
s.Printf(_T("%f"), *(PFLOAT)pAddress);
handled = true;
}
else if ( bt == BASICTYPE_CHAR )
{
// don't take more than 32 characters of a string
static const size_t NUM_CHARS = 64;
const char *pc = *(PSTR *)pAddress;
if ( ::IsBadStringPtrA(pc, NUM_CHARS) == 0 )
{
s += _T('"');
for ( size_t n = 0; n < NUM_CHARS && *pc; n++, pc++ )
{
s += *pc;
}
s += _T('"');
handled = true;
}
}
if ( !handled )
{
// treat just as an opaque DWORD
s.Printf(_T("%#x"), *(PDWORD)pAddress);
}
}
else if ( length == 8 )
{
if ( bt == BASICTYPE_FLOAT )
{
s.Printf(_T("%lf"), *(double *)pAddress);
}
else // opaque 64 bit value
{
s.Printf(_T("%#" wxLongLongFmtSpec _T("x")), *(PDWORD *)pAddress);
}
}
return s;
}
wxString
wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
{
wxString s;
// avoid infinite recursion
if ( level > MAX_DUMP_DEPTH )
{
return s;
}
SymbolTag tag = SYMBOL_TAG_NULL;
if ( !DoGetTypeInfo(pSym, TI_GET_SYMTAG, &tag) )
{
return s;
}
switch ( tag )
{
case SYMBOL_TAG_UDT:
case SYMBOL_TAG_BASE_CLASS:
s = DumpUDT(pSym, pVariable, level);
break;
case SYMBOL_TAG_DATA:
if ( !pVariable )
{
s = _T("NULL");
}
else // valid location
{
wxDbgHelpDLL::DataKind kind;
if ( !DoGetTypeInfo(pSym, TI_GET_DATAKIND, &kind) ||
kind != DATA_MEMBER )
{
// maybe it's a static member? we're not interested in them...
break;
}
// get the offset of the child member, relative to its parent
DWORD ofs = 0;
if ( !DoGetTypeInfo(pSym, TI_GET_OFFSET, &ofs) )
break;
pVariable = (void *)((DWORD_PTR)pVariable + ofs);
// now pass to the type representing the type of this member
SYMBOL_INFO sym = *pSym;
if ( !DoGetTypeInfo(pSym, TI_GET_TYPEID, &sym.TypeIndex) )
break;
ULONG64 size;
DoGetTypeInfo(&sym, TI_GET_LENGTH, &size);
switch ( DereferenceSymbol(&sym, &pVariable) )
{
case SYMBOL_TAG_BASE_TYPE:
{
BasicType bt = GetBasicType(&sym);
if ( bt )
{
s = DumpBaseType(bt, size, pVariable);
}
}
break;
case SYMBOL_TAG_UDT:
case SYMBOL_TAG_BASE_CLASS:
s = DumpUDT(&sym, pVariable, level);
break;
}
}
if ( !s.empty() )
{
s = GetSymbolName(pSym) + _T(" = ") + s;
}
break;
}
if ( !s.empty() )
{
s = wxString(_T('\t'), level + 1) + s + _T('\n');
}
return s;
}
/* static */ wxString
wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
{
wxString s;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?