X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/737c443bd16aa48366e941b886e6a3e8630bab85..0d1903dbda864780eec30efdc4e91776bdbfd21b:/src/msw/debughlp.cpp diff --git a/src/msw/debughlp.cpp b/src/msw/debughlp.cpp index 3752aa10b2..161a532933 100644 --- a/src/msw/debughlp.cpp +++ b/src/msw/debughlp.cpp @@ -1,10 +1,9 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: msw/debughlp.cpp +// Name: src/msw/debughlp.cpp // Purpose: various Win32 debug helpers // Author: Vadim Zeitlin // Modified by: // Created: 2005-01-08 (extracted from crashrpt.cpp) -// RCS-ID: $Id$ // Copyright: (c) 2003-2005 Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -25,7 +24,15 @@ #include "wx/msw/debughlp.h" -#if wxUSE_DBGHELP +#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 @@ -42,7 +49,8 @@ static wxString gs_errMsg; // static members // ---------------------------------------------------------------------------- -#define DEFINE_SYM_FUNCTION(func) wxDbgHelpDLL::func ## _t wxDbgHelpDLL::func = 0 +#define DEFINE_SYM_FUNCTION(func, name) \ + wxDbgHelpDLL::func ## _t wxDbgHelpDLL::func = 0 wxDO_FOR_ALL_SYM_FUNCS(DEFINE_SYM_FUNCTION); @@ -56,12 +64,12 @@ wxDO_FOR_ALL_SYM_FUNCS(DEFINE_SYM_FUNCTION); static bool BindDbgHelpFunctions(const wxDynamicLibrary& dllDbgHelp) { - #define LOAD_SYM_FUNCTION(name) \ - wxDbgHelpDLL::name = (wxDbgHelpDLL::name ## _t) \ - dllDbgHelp.GetSymbol(_T(#name)); \ - if ( !wxDbgHelpDLL::name ) \ + #define LOAD_SYM_FUNCTION(func, name) \ + wxDbgHelpDLL::func = (wxDbgHelpDLL::func ## _t) \ + dllDbgHelp.GetSymbol(wxT(#name)); \ + if ( !wxDbgHelpDLL::func ) \ { \ - gs_errMsg += _T("Function ") _T(#name) _T("() not found.\n"); \ + gs_errMsg += wxT("Function ") wxT(#name) wxT("() not found.\n"); \ return false; \ } @@ -75,7 +83,7 @@ static bool BindDbgHelpFunctions(const wxDynamicLibrary& dllDbgHelp) // called by Init() if we hadn't done this before static bool DoInit() { - wxDynamicLibrary dllDbgHelp(_T("dbghelp.dll"), wxDL_VERBATIM); + wxDynamicLibrary dllDbgHelp(wxT("dbghelp.dll"), wxDL_VERBATIM); if ( dllDbgHelp.IsLoaded() ) { if ( BindDbgHelpFunctions(dllDbgHelp) ) @@ -91,19 +99,19 @@ static bool DoInit() 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"); + gs_errMsg += wxT("\nPlease update your dbghelp.dll version, ") + wxT("at least version 5.1 is needed!\n") + wxT("(if you already have a new version, please ") + wxT("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 += wxT("Please install dbghelp.dll available free of charge ") + wxT("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"); + gs_errMsg += wxT("\nLatest dbghelp.dll is available at ") + wxT("http://www.microsoft.com/whdc/ddk/debugging/\n"); return false; } @@ -136,8 +144,8 @@ const wxString& wxDbgHelpDLL::GetErrorMessage() /* static */ void wxDbgHelpDLL::LogError(const wxChar *func) { - ::OutputDebugString(wxString::Format(_T("dbghelp: %s() failed: %s\r\n"), - func, wxSysErrorMsg(::GetLastError()))); + ::OutputDebugString(wxString::Format(wxT("dbghelp: %s() failed: %s\r\n"), + func, wxSysErrorMsg(::GetLastError())).t_str()); } // ---------------------------------------------------------------------------- @@ -204,12 +212,12 @@ wxDbgHelpDLL::DumpBaseType(BasicType bt, DWORD64 length, PVOID pAddress) { if ( !pAddress ) { - return _T("null"); + return wxT("null"); } if ( ::IsBadReadPtr(pAddress, length) != 0 ) { - return _T("BAD"); + return wxT("BAD"); } @@ -221,13 +229,13 @@ wxDbgHelpDLL::DumpBaseType(BasicType bt, DWORD64 length, PVOID pAddress) const BYTE b = *(PBYTE)pAddress; if ( bt == BASICTYPE_BOOL ) - s = b ? _T("true") : _T("false"); + s = b ? wxT("true") : wxT("false"); else - s.Printf(_T("%#04x"), b); + s.Printf(wxT("%#04x"), b); } else if ( length == 2 ) { - s.Printf(bt == BASICTYPE_UINT ? _T("%#06x") : _T("%d"), + s.Printf(bt == BASICTYPE_UINT ? wxT("%#06x") : wxT("%d"), *(PWORD)pAddress); } else if ( length == 4 ) @@ -236,7 +244,7 @@ wxDbgHelpDLL::DumpBaseType(BasicType bt, DWORD64 length, PVOID pAddress) if ( bt == BASICTYPE_FLOAT ) { - s.Printf(_T("%f"), *(PFLOAT)pAddress); + s.Printf(wxT("%f"), *(PFLOAT)pAddress); handled = true; } @@ -248,12 +256,12 @@ wxDbgHelpDLL::DumpBaseType(BasicType bt, DWORD64 length, PVOID pAddress) const char *pc = *(PSTR *)pAddress; if ( ::IsBadStringPtrA(pc, NUM_CHARS) == 0 ) { - s += _T('"'); + s += wxT('"'); for ( size_t n = 0; n < NUM_CHARS && *pc; n++, pc++ ) { s += *pc; } - s += _T('"'); + s += wxT('"'); handled = true; } @@ -262,18 +270,18 @@ wxDbgHelpDLL::DumpBaseType(BasicType bt, DWORD64 length, PVOID pAddress) if ( !handled ) { // treat just as an opaque DWORD - s.Printf(_T("%#x"), *(PDWORD)pAddress); + s.Printf(wxT("%#x"), *(PDWORD)pAddress); } } else if ( length == 8 ) { if ( bt == BASICTYPE_FLOAT ) { - s.Printf(_T("%lf"), *(double *)pAddress); + s.Printf(wxT("%lf"), *(double *)pAddress); } else // opaque 64 bit value { - s.Printf(_T("%#" wxLongLongFmtSpec _T("x")), *(PDWORD *)pAddress); + s.Printf("%#" wxLongLongFmtSpec "x", *(wxLongLong_t *)pAddress); } } @@ -286,7 +294,7 @@ wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level) wxString s; // avoid infinite recursion - if ( level > 100 ) + if ( level > MAX_DUMP_DEPTH ) { return s; } @@ -307,7 +315,7 @@ wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level) case SYMBOL_TAG_DATA: if ( !pVariable ) { - s = _T("NULL"); + s = wxT("NULL"); } else // valid location { @@ -351,19 +359,28 @@ wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level) case SYMBOL_TAG_BASE_CLASS: s = DumpUDT(&sym, pVariable, level); break; + + default: + // Suppress gcc warnings about unhandled enum values. + break; } } if ( !s.empty() ) { - s = GetSymbolName(pSym) + _T(" = ") + s; + s = GetSymbolName(pSym) + wxT(" = ") + s; } break; + + default: + // Suppress gcc warnings about unhandled enum values, don't assert + // to avoid problems during fatal crash generation. + break; } if ( !s.empty() ) { - s = wxString(_T('\t'), level + 1) + s + _T('\n'); + s = wxString(wxT('\t'), level + 1) + s + wxT('\n'); } return s; @@ -383,17 +400,35 @@ wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level) s.reserve(512); s = GetSymbolName(pSym); -#if !wxUSE_STL +#if !wxUSE_STD_STRING // special handling for ubiquitous wxString: although the code below works // for it as well, it shows the wxStringBase class and takes 4 lines // instead of only one as this branch - if ( s == _T("wxString") ) + if ( s == wxT("wxString") ) { wxString *ps = (wxString *)pVariable; - s << _T("(\"") << *ps << _T(")\""); + + // we can't just dump wxString directly as it could be corrupted or + // invalid and it could also be locked for writing (i.e. if we're + // between GetWriteBuf() and UngetWriteBuf() calls) and assert when we + // try to access it contents using public methods, so instead use our + // knowledge of its internals + const wxChar *p = NULL; + if ( !::IsBadReadPtr(ps, sizeof(wxString)) ) + { + p = ps->data(); + wxStringData *data = (wxStringData *)p - 1; + if ( ::IsBadReadPtr(data, sizeof(wxStringData)) || + ::IsBadReadPtr(p, sizeof(wxChar *)*data->nAllocLength) ) + { + p = NULL; // don't touch this pointer with 10 feet pole + } + } + + s << wxT("(\"") << (p ? p : wxT("???")) << wxT(")\""); } else // any other UDT -#endif // !wxUSE_STL +#endif // !wxUSE_STD_STRING { // Determine how many children this type has. DWORD dwChildrenCount = 0; @@ -416,7 +451,7 @@ wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level) return s; } - s << _T(" {\n"); + s << wxT(" {\n"); // Iterate through all children SYMBOL_INFO sym; @@ -443,7 +478,7 @@ wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level) free(children); - s << wxString(_T('\t'), level + 1) << _T('}'); + s << wxString(wxT('\t'), level + 1) << wxT('}'); } return s; @@ -494,6 +529,11 @@ wxDbgHelpDLL::DumpSymbol(PSYMBOL_INFO pSym, void *pVariable) SYMBOL_INFO symDeref = *pSym; switch ( DereferenceSymbol(&symDeref, &pVariable) ) { + default: + // Suppress gcc warnings about unhandled enum values, don't assert + // to avoid problems during fatal crash generation. + break; + case SYMBOL_TAG_UDT: // show UDT recursively s = DumpUDT(&symDeref, pVariable); @@ -524,37 +564,37 @@ static wxString TagString(wxDbgHelpDLL::SymbolTag tag) { static const wxChar *tags[] = { - _T("null"), - _T("exe"), - _T("compiland"), - _T("compiland details"), - _T("compiland env"), - _T("function"), - _T("block"), - _T("data"), - _T("annotation"), - _T("label"), - _T("public symbol"), - _T("udt"), - _T("enum"), - _T("function type"), - _T("pointer type"), - _T("array type"), - _T("base type"), - _T("typedef"), - _T("base class"), - _T("friend"), - _T("function arg type"), - _T("func debug start"), - _T("func debug end"), - _T("using namespace"), - _T("vtable shape"), - _T("vtable"), - _T("custom"), - _T("thunk"), - _T("custom type"), - _T("managed type"), - _T("dimension"), + wxT("null"), + wxT("exe"), + wxT("compiland"), + wxT("compiland details"), + wxT("compiland env"), + wxT("function"), + wxT("block"), + wxT("data"), + wxT("annotation"), + wxT("label"), + wxT("public symbol"), + wxT("udt"), + wxT("enum"), + wxT("function type"), + wxT("pointer type"), + wxT("array type"), + wxT("base type"), + wxT("typedef"), + wxT("base class"), + wxT("friend"), + wxT("function arg type"), + wxT("func debug start"), + wxT("func debug end"), + wxT("using namespace"), + wxT("vtable shape"), + wxT("vtable"), + wxT("custom"), + wxT("thunk"), + wxT("custom type"), + wxT("managed type"), + wxT("dimension"), }; wxCOMPILE_TIME_ASSERT( WXSIZEOF(tags) == wxDbgHelpDLL::SYMBOL_TAG_MAX, @@ -564,7 +604,7 @@ static wxString TagString(wxDbgHelpDLL::SymbolTag tag) if ( tag < WXSIZEOF(tags) ) s = tags[tag]; else - s.Printf(_T("unrecognized tag (%d)"), tag); + s.Printf(wxT("unrecognized tag (%d)"), tag); return s; } @@ -573,16 +613,16 @@ static wxString KindString(wxDbgHelpDLL::DataKind kind) { static const wxChar *kinds[] = { - _T("unknown"), - _T("local"), - _T("static local"), - _T("param"), - _T("object ptr"), - _T("file static"), - _T("global"), - _T("member"), - _T("static member"), - _T("constant"), + wxT("unknown"), + wxT("local"), + wxT("static local"), + wxT("param"), + wxT("object ptr"), + wxT("file static"), + wxT("global"), + wxT("member"), + wxT("static member"), + wxT("constant"), }; wxCOMPILE_TIME_ASSERT( WXSIZEOF(kinds) == wxDbgHelpDLL::DATA_MAX, @@ -592,7 +632,7 @@ static wxString KindString(wxDbgHelpDLL::DataKind kind) if ( kind < WXSIZEOF(kinds) ) s = kinds[kind]; else - s.Printf(_T("unrecognized kind (%d)"), kind); + s.Printf(wxT("unrecognized kind (%d)"), kind); return s; } @@ -601,9 +641,9 @@ static wxString UdtKindString(wxDbgHelpDLL::UdtKind kind) { static const wxChar *kinds[] = { - _T("struct"), - _T("class"), - _T("union"), + wxT("struct"), + wxT("class"), + wxT("union"), }; wxCOMPILE_TIME_ASSERT( WXSIZEOF(kinds) == wxDbgHelpDLL::UDT_MAX, @@ -613,7 +653,7 @@ static wxString UdtKindString(wxDbgHelpDLL::UdtKind kind) if ( kind < WXSIZEOF(kinds) ) s = kinds[kind]; else - s.Printf(_T("unrecognized UDT (%d)"), kind); + s.Printf(wxT("unrecognized UDT (%d)"), kind); return s; } @@ -622,38 +662,38 @@ static wxString TypeString(wxDbgHelpDLL::BasicType bt) { static const wxChar *types[] = { - _T("no type"), - _T("void"), - _T("char"), - _T("wchar"), - _T(""), - _T(""), - _T("int"), - _T("uint"), - _T("float"), - _T("bcd"), - _T("bool"), - _T(""), - _T(""), - _T("long"), - _T("ulong"), - _T(""), - _T(""), - _T(""), - _T(""), - _T(""), - _T(""), - _T(""), - _T(""), - _T(""), - _T(""), - _T("CURRENCY"), - _T("DATE"), - _T("VARIANT"), - _T("complex"), - _T("bit"), - _T("BSTR"), - _T("HRESULT"), + wxT("no type"), + wxT("void"), + wxT("char"), + wxT("wchar"), + wxT(""), + wxT(""), + wxT("int"), + wxT("uint"), + wxT("float"), + wxT("bcd"), + wxT("bool"), + wxT(""), + wxT(""), + wxT("long"), + wxT("ulong"), + wxT(""), + wxT(""), + wxT(""), + wxT(""), + wxT(""), + wxT(""), + wxT(""), + wxT(""), + wxT(""), + wxT(""), + wxT("CURRENCY"), + wxT("DATE"), + wxT("VARIANT"), + wxT("complex"), + wxT("bit"), + wxT("BSTR"), + wxT("HRESULT"), }; wxCOMPILE_TIME_ASSERT( WXSIZEOF(types) == wxDbgHelpDLL::BASICTYPE_MAX, @@ -664,7 +704,7 @@ static wxString TypeString(wxDbgHelpDLL::BasicType bt) s = types[bt]; if ( s.empty() ) - s.Printf(_T("unrecognized type (%d)"), bt); + s.Printf(wxT("unrecognized type (%d)"), bt); return s; } @@ -681,11 +721,11 @@ extern "C" void DumpTI(ULONG ti) DoGetTypeInfo(&sym, TI_GET_SYMTAG, &tag); DoGetTypeInfo(&sym, TI_GET_TYPEID, &ti); - OutputDebugString(wxString::Format(_T("Type 0x%x: "), sym.TypeIndex)); + OutputDebugString(wxString::Format(wxT("Type 0x%x: "), sym.TypeIndex)); wxString name = wxDbgHelpDLL::GetSymbolName(&sym); if ( !name.empty() ) { - OutputDebugString(wxString::Format(_T("name=\"%s\", "), name.c_str())); + OutputDebugString(wxString::Format(wxT("name=\"%s\", "), name.c_str())); } DWORD nested; @@ -694,15 +734,15 @@ extern "C" void DumpTI(ULONG ti) nested = FALSE; } - OutputDebugString(wxString::Format(_T("tag=%s%s"), - nested ? _T("nested ") : wxEmptyString, + OutputDebugString(wxString::Format(wxT("tag=%s%s"), + nested ? wxT("nested ") : wxEmptyString, TagString(tag).c_str())); if ( tag == wxDbgHelpDLL::SYMBOL_TAG_UDT ) { wxDbgHelpDLL::UdtKind udtKind; if ( DoGetTypeInfo(&sym, TI_GET_UDTKIND, &udtKind) ) { - OutputDebugString(_T(" (") + UdtKindString(udtKind) + _T(')')); + OutputDebugString(wxT(" (") + UdtKindString(udtKind) + wxT(')')); } } @@ -710,13 +750,13 @@ extern "C" void DumpTI(ULONG ti) if ( DoGetTypeInfo(&sym, TI_GET_DATAKIND, &kind) ) { OutputDebugString(wxString::Format( - _T(", kind=%s"), KindString(kind).c_str())); + wxT(", kind=%s"), KindString(kind).c_str())); if ( kind == wxDbgHelpDLL::DATA_MEMBER ) { DWORD ofs = 0; if ( DoGetTypeInfo(&sym, TI_GET_OFFSET, &ofs) ) { - OutputDebugString(wxString::Format(_T(" (ofs=0x%x)"), ofs)); + OutputDebugString(wxString::Format(wxT(" (ofs=0x%x)"), ofs)); } } } @@ -724,16 +764,16 @@ extern "C" void DumpTI(ULONG ti) wxDbgHelpDLL::BasicType bt = GetBasicType(&sym); if ( bt ) { - OutputDebugString(wxString::Format(_T(", type=%s"), + OutputDebugString(wxString::Format(wxT(", type=%s"), TypeString(bt).c_str())); } if ( ti != sym.TypeIndex ) { - OutputDebugString(wxString::Format(_T(", next ti=0x%x"), ti)); + OutputDebugString(wxString::Format(wxT(", next ti=0x%x"), ti)); } - OutputDebugString(_T("\r\n")); + OutputDebugString(wxT("\r\n")); } #endif // NDEBUG