/[pcsx2_0.9.7]/trunk/3rdparty/wxWidgets/src/msw/debughlp.cpp
ViewVC logotype

Annotation of /trunk/3rdparty/wxWidgets/src/msw/debughlp.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (hide annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (9 years, 11 months ago) by william
File size: 22681 byte(s)
Auto Commited Import of: pcsx2-0.9.7-r3738-debug in ./trunk
1 william 31 /////////////////////////////////////////////////////////////////////////////
2     // Name: msw/debughlp.cpp
3     // Purpose: various Win32 debug helpers
4     // Author: Vadim Zeitlin
5     // Modified by:
6     // Created: 2005-01-08 (extracted from crashrpt.cpp)
7     // RCS-ID: $Id: debughlp.cpp 37037 2006-01-21 16:47:30Z JS $
8     // Copyright: (c) 2003-2005 Vadim Zeitlin <vadim@wxwindows.org>
9     // Licence: wxWindows licence
10     /////////////////////////////////////////////////////////////////////////////
11    
12     // ============================================================================
13     // declarations
14     // ============================================================================
15    
16     // ----------------------------------------------------------------------------
17     // headers
18     // ----------------------------------------------------------------------------
19    
20     #include "wx/wxprec.h"
21    
22     #ifdef __BORLANDC__
23     #pragma hdrstop
24     #endif
25    
26     #include "wx/msw/debughlp.h"
27    
28     #if wxUSE_DBGHELP && wxUSE_DYNLIB_CLASS
29    
30     // ----------------------------------------------------------------------------
31     // constants
32     // ----------------------------------------------------------------------------
33    
34     // to prevent recursion which could result from corrupted data we limit
35     // ourselves to that many levels of embedded fields inside structs
36     static const unsigned MAX_DUMP_DEPTH = 20;
37    
38     // ----------------------------------------------------------------------------
39     // globals
40     // ----------------------------------------------------------------------------
41    
42     // error message from Init()
43     static wxString gs_errMsg;
44    
45 william 62 #if wxUSE_THREADS
46     wxMutex s_mtx_DbgHelp;
47     #endif
48    
49 william 31 // ============================================================================
50     // wxDbgHelpDLL implementation
51     // ============================================================================
52    
53     // ----------------------------------------------------------------------------
54     // static members
55     // ----------------------------------------------------------------------------
56    
57     #define DEFINE_SYM_FUNCTION(func) wxDbgHelpDLL::func ## _t wxDbgHelpDLL::func = 0
58    
59     wxDO_FOR_ALL_SYM_FUNCS(DEFINE_SYM_FUNCTION);
60 william 62 DEFINE_SYM_FUNCTION(SymRefreshModuleList);
61 william 31
62     #undef DEFINE_SYM_FUNCTION
63    
64     // ----------------------------------------------------------------------------
65     // initialization methods
66     // ----------------------------------------------------------------------------
67    
68     // load all function we need from the DLL
69    
70 william 62 bool wxDbgHelpDLL::BindFunctions(const wxDynamicLibrary& dllDbgHelp)
71 william 31 {
72     #define LOAD_SYM_FUNCTION(name) \
73 william 62 name = (name ## _t)dllDbgHelp.GetSymbol(_T(#name)); \
74     if ( !name ) \
75 william 31 { \
76     gs_errMsg += _T("Function ") _T(#name) _T("() not found.\n"); \
77     return false; \
78     }
79    
80     wxDO_FOR_ALL_SYM_FUNCS(LOAD_SYM_FUNCTION);
81    
82 william 62 #undef LOAD_SYM_FUNCTION
83 william 31
84 william 62 // SymRefreshModuleList is bound separately since it requires an especially new version
85     // of WinDbgHlp (v6.5 or later). If it binds as NULL, that's ok. Its only needed in
86     // order to reload symbols for apps that dynamically unload/reload plugins.
87    
88     SymRefreshModuleList = (SymRefreshModuleList_t)dllDbgHelp.GetSymbol(_T("SymRefreshModuleList"));
89    
90 william 31 return true;
91     }
92    
93     // called by Init() if we hadn't done this before
94 william 62 bool wxDbgHelpDLL::DoInit()
95 william 31 {
96     wxDynamicLibrary dllDbgHelp(_T("dbghelp.dll"), wxDL_VERBATIM);
97     if ( dllDbgHelp.IsLoaded() )
98     {
99 william 62 if ( BindFunctions(dllDbgHelp) )
100 william 31 {
101     // turn on default options
102 william 62 DWORD options = SymGetOptions();
103 william 31
104     options |= SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_DEBUG;
105    
106 william 62 SymSetOptions(options);
107 william 31
108     dllDbgHelp.Detach();
109     return true;
110     }
111    
112     gs_errMsg += _T("\nPlease update your dbghelp.dll version, ")
113     _T("at least version 5.1 is needed!\n")
114     _T("(if you already have a new version, please ")
115     _T("put it in the same directory where the program is.)\n");
116     }
117     else // failed to load dbghelp.dll
118     {
119     gs_errMsg += _T("Please install dbghelp.dll available free of charge ")
120     _T("from Microsoft to get more detailed crash information!");
121     }
122    
123     gs_errMsg += _T("\nLatest dbghelp.dll is available at ")
124     _T("http://www.microsoft.com/whdc/ddk/debugging/\n");
125    
126     return false;
127     }
128    
129     /* static */
130     bool wxDbgHelpDLL::Init()
131     {
132 william 62 // this flag is -1 until Init() is called for the first time, then it's set
133     // to either false or true depending on whether we could load the functions
134     static int s_loaded = -1;
135 william 31
136 william 62 #if wxUSE_THREADS
137     wxMutexLocker lock(s_mtx_DbgHelp);
138     #endif
139    
140 william 31 if ( s_loaded == -1 )
141     {
142     s_loaded = DoInit();
143     }
144    
145     return s_loaded != 0;
146     }
147    
148 william 62 bool wxDbgHelpDLL::RefreshModuleList( HANDLE hProcess )
149     {
150     static bool s_syms_initialized = false;
151    
152     #if wxUSE_THREADS
153     wxMutexLocker lock(s_mtx_DbgHelp);
154     #endif
155    
156     if ( !s_syms_initialized )
157     {
158     if ( !SymInitialize(
159     hProcess,
160     NULL, // use default symbol search path
161     TRUE // load symbols for all loaded modules
162     ) )
163     {
164     wxDbgHelpDLL::LogError(_T("SymInitialize"));
165     return false;
166     }
167    
168     s_syms_initialized = true;
169     }
170     else if ( SymRefreshModuleList && !SymRefreshModuleList( hProcess ) )
171     {
172     // If winDbgHlp v6.5 or newer, we can use this to reload symbols on-the-fly.
173     // If not, then the app could have outdated or unloaded symbols if it dynamically
174     // loads and unloads modules *and* performs multiple stack traces during the course
175     // of program execution.
176    
177     wxDbgHelpDLL::LogError(_T("SymRefreshModuleList"));
178     return false;
179     }
180    
181     return true;
182     }
183    
184 william 31 // ----------------------------------------------------------------------------
185     // error handling
186     // ----------------------------------------------------------------------------
187    
188     /* static */
189     const wxString& wxDbgHelpDLL::GetErrorMessage()
190     {
191     return gs_errMsg;
192     }
193    
194     /* static */
195     void wxDbgHelpDLL::LogError(const wxChar *func)
196     {
197     ::OutputDebugString(wxString::Format(_T("dbghelp: %s() failed: %s\r\n"),
198     func, wxSysErrorMsg(::GetLastError())));
199     }
200    
201     // ----------------------------------------------------------------------------
202     // data dumping
203     // ----------------------------------------------------------------------------
204    
205     static inline
206     bool
207     DoGetTypeInfo(DWORD64 base, ULONG ti, IMAGEHLP_SYMBOL_TYPE_INFO type, void *rc)
208     {
209     static HANDLE s_hProcess = ::GetCurrentProcess();
210    
211     return wxDbgHelpDLL::SymGetTypeInfo
212     (
213     s_hProcess,
214     base,
215     ti,
216     type,
217     rc
218     ) != 0;
219     }
220    
221     static inline
222     bool
223     DoGetTypeInfo(PSYMBOL_INFO pSym, IMAGEHLP_SYMBOL_TYPE_INFO type, void *rc)
224     {
225     return DoGetTypeInfo(pSym->ModBase, pSym->TypeIndex, type, rc);
226     }
227    
228     static inline
229     wxDbgHelpDLL::BasicType GetBasicType(PSYMBOL_INFO pSym)
230     {
231     wxDbgHelpDLL::BasicType bt;
232     return DoGetTypeInfo(pSym, TI_GET_BASETYPE, &bt)
233     ? bt
234     : wxDbgHelpDLL::BASICTYPE_NOTYPE;
235     }
236    
237     /* static */
238     wxString wxDbgHelpDLL::GetSymbolName(PSYMBOL_INFO pSym)
239     {
240     wxString s;
241    
242     WCHAR *pwszTypeName;
243     if ( SymGetTypeInfo
244     (
245     GetCurrentProcess(),
246     pSym->ModBase,
247     pSym->TypeIndex,
248     TI_GET_SYMNAME,
249     &pwszTypeName
250     ) )
251     {
252     s = wxConvCurrent->cWC2WX(pwszTypeName);
253    
254     ::LocalFree(pwszTypeName);
255     }
256    
257     return s;
258     }
259    
260     /* static */ wxString
261     wxDbgHelpDLL::DumpBaseType(BasicType bt, DWORD64 length, PVOID pAddress)
262     {
263     if ( !pAddress )
264     {
265     return _T("null");
266     }
267    
268     if ( ::IsBadReadPtr(pAddress, length) != 0 )
269     {
270     return _T("BAD");
271     }
272    
273    
274     wxString s;
275     s.reserve(256);
276    
277     if ( length == 1 )
278     {
279     const BYTE b = *(PBYTE)pAddress;
280    
281     if ( bt == BASICTYPE_BOOL )
282     s = b ? _T("true") : _T("false");
283     else
284     s.Printf(_T("%#04x"), b);
285     }
286     else if ( length == 2 )
287     {
288     s.Printf(bt == BASICTYPE_UINT ? _T("%#06x") : _T("%d"),
289     *(PWORD)pAddress);
290     }
291     else if ( length == 4 )
292     {
293     bool handled = false;
294    
295     if ( bt == BASICTYPE_FLOAT )
296     {
297     s.Printf(_T("%f"), *(PFLOAT)pAddress);
298    
299     handled = true;
300     }
301     else if ( bt == BASICTYPE_CHAR )
302     {
303     // don't take more than 32 characters of a string
304     static const size_t NUM_CHARS = 64;
305    
306     const char *pc = *(PSTR *)pAddress;
307     if ( ::IsBadStringPtrA(pc, NUM_CHARS) == 0 )
308     {
309     s += _T('"');
310     for ( size_t n = 0; n < NUM_CHARS && *pc; n++, pc++ )
311     {
312     s += *pc;
313     }
314     s += _T('"');
315    
316     handled = true;
317     }
318     }
319    
320     if ( !handled )
321     {
322     // treat just as an opaque DWORD
323     s.Printf(_T("%#x"), *(PDWORD)pAddress);
324     }
325     }
326     else if ( length == 8 )
327     {
328     if ( bt == BASICTYPE_FLOAT )
329     {
330     s.Printf(_T("%lf"), *(double *)pAddress);
331     }
332     else // opaque 64 bit value
333     {
334     s.Printf(_T("%#" wxLongLongFmtSpec _T("x")), *(PDWORD *)pAddress);
335     }
336     }
337    
338     return s;
339     }
340    
341     wxString
342     wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
343     {
344     wxString s;
345    
346     // avoid infinite recursion
347     if ( level > MAX_DUMP_DEPTH )
348     {
349     return s;
350     }
351    
352     SymbolTag tag = SYMBOL_TAG_NULL;
353     if ( !DoGetTypeInfo(pSym, TI_GET_SYMTAG, &tag) )
354     {
355     return s;
356     }
357    
358     switch ( tag )
359     {
360     case SYMBOL_TAG_UDT:
361     case SYMBOL_TAG_BASE_CLASS:
362     s = DumpUDT(pSym, pVariable, level);
363     break;
364    
365     case SYMBOL_TAG_DATA:
366     if ( !pVariable )
367     {
368     s = _T("NULL");
369     }
370     else // valid location
371     {
372     wxDbgHelpDLL::DataKind kind;
373     if ( !DoGetTypeInfo(pSym, TI_GET_DATAKIND, &kind) ||
374     kind != DATA_MEMBER )
375     {
376     // maybe it's a static member? we're not interested in them...
377     break;
378     }
379    
380     // get the offset of the child member, relative to its parent
381     DWORD ofs = 0;
382     if ( !DoGetTypeInfo(pSym, TI_GET_OFFSET, &ofs) )
383     break;
384    
385     pVariable = (void *)((DWORD_PTR)pVariable + ofs);
386    
387    
388     // now pass to the type representing the type of this member
389     SYMBOL_INFO sym = *pSym;
390     if ( !DoGetTypeInfo(pSym, TI_GET_TYPEID, &sym.TypeIndex) )
391     break;
392    
393     ULONG64 size;
394     DoGetTypeInfo(&sym, TI_GET_LENGTH, &size);
395    
396     switch ( DereferenceSymbol(&sym, &pVariable) )
397     {
398     case SYMBOL_TAG_BASE_TYPE:
399     {
400     BasicType bt = GetBasicType(&sym);
401     if ( bt )
402     {
403     s = DumpBaseType(bt, size, pVariable);
404     }
405     }
406     break;
407    
408     case SYMBOL_TAG_UDT:
409     case SYMBOL_TAG_BASE_CLASS:
410     s = DumpUDT(&sym, pVariable, level);
411     break;
412     }
413     }
414    
415     if ( !s.empty() )
416     {
417     s = GetSymbolName(pSym) + _T(" = ") + s;
418     }
419     break;
420     }
421    
422     if ( !s.empty() )
423     {
424     s = wxString(_T('\t'), level + 1) + s + _T('\n');
425     }
426    
427     return s;
428     }
429    
430     /* static */ wxString
431     wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
432     {
433     wxString s;
434    
435     // we have to limit the depth of UDT dumping as otherwise we get in
436     // infinite loops trying to dump linked lists... 10 levels seems quite
437     // reasonable, full information is in minidump file anyhow
438     if ( level > 10 )
439     return s;
440    
441     s.reserve(512);
442     s = GetSymbolName(pSym);
443    
444     #if !wxUSE_STL
445     // special handling for ubiquitous wxString: although the code below works
446     // for it as well, it shows the wxStringBase class and takes 4 lines
447     // instead of only one as this branch
448     if ( s == _T("wxString") )
449     {
450     wxString *ps = (wxString *)pVariable;
451    
452     // we can't just dump wxString directly as it could be corrupted or
453     // invalid and it could also be locked for writing (i.e. if we're
454     // between GetWriteBuf() and UngetWriteBuf() calls) and assert when we
455     // try to access it contents using public methods, so instead use our
456     // knowledge of its internals
457     const wxChar *p = NULL;
458     if ( !::IsBadReadPtr(ps, sizeof(wxString)) )
459     {
460     p = ps->data();
461     wxStringData *data = (wxStringData *)p - 1;
462     if ( ::IsBadReadPtr(data, sizeof(wxStringData)) ||
463     ::IsBadReadPtr(p, sizeof(wxChar *)*data->nAllocLength) )
464     {
465     p = NULL; // don't touch this pointer with 10 feet pole
466     }
467     }
468    
469     s << _T("(\"") << (p ? p : _T("???")) << _T(")\"");
470     }
471     else // any other UDT
472     #endif // !wxUSE_STL
473     {
474     // Determine how many children this type has.
475     DWORD dwChildrenCount = 0;
476     DoGetTypeInfo(pSym, TI_GET_CHILDRENCOUNT, &dwChildrenCount);
477    
478     // Prepare to get an array of "TypeIds", representing each of the children.
479     TI_FINDCHILDREN_PARAMS *children = (TI_FINDCHILDREN_PARAMS *)
480     malloc(sizeof(TI_FINDCHILDREN_PARAMS) +
481     (dwChildrenCount - 1)*sizeof(ULONG));
482     if ( !children )
483     return s;
484    
485     children->Count = dwChildrenCount;
486     children->Start = 0;
487    
488     // Get the array of TypeIds, one for each child type
489     if ( !DoGetTypeInfo(pSym, TI_FINDCHILDREN, children) )
490     {
491     free(children);
492     return s;
493     }
494    
495     s << _T(" {\n");
496    
497     // Iterate through all children
498     SYMBOL_INFO sym;
499     wxZeroMemory(sym);
500     sym.ModBase = pSym->ModBase;
501     for ( unsigned i = 0; i < dwChildrenCount; i++ )
502     {
503     sym.TypeIndex = children->ChildId[i];
504    
505     // children here are in lexicographic sense, i.e. we get all our nested
506     // classes and not only our member fields, but we can't get the values
507     // for the members of the nested classes, of course!
508     DWORD nested;
509     if ( DoGetTypeInfo(&sym, TI_GET_NESTED, &nested) && nested )
510     continue;
511    
512     // avoid infinite recursion: this does seem to happen sometimes with
513     // complex typedefs...
514     if ( sym.TypeIndex == pSym->TypeIndex )
515     continue;
516    
517     s += DumpField(&sym, pVariable, level + 1);
518     }
519    
520     free(children);
521    
522     s << wxString(_T('\t'), level + 1) << _T('}');
523     }
524    
525     return s;
526     }
527    
528     /* static */
529     wxDbgHelpDLL::SymbolTag
530     wxDbgHelpDLL::DereferenceSymbol(PSYMBOL_INFO pSym, void **ppData)
531     {
532     SymbolTag tag = SYMBOL_TAG_NULL;
533     for ( ;; )
534     {
535     if ( !DoGetTypeInfo(pSym, TI_GET_SYMTAG, &tag) )
536     break;
537    
538     if ( tag != SYMBOL_TAG_POINTER_TYPE )
539     break;
540    
541     ULONG tiNew;
542     if ( !DoGetTypeInfo(pSym, TI_GET_TYPEID, &tiNew) ||
543     tiNew == pSym->TypeIndex )
544     break;
545    
546     pSym->TypeIndex = tiNew;
547    
548     // remove one level of indirection except for the char strings: we want
549     // to dump "char *" and not a single "char" for them
550     if ( ppData && *ppData && GetBasicType(pSym) != BASICTYPE_CHAR )
551     {
552     DWORD_PTR *pData = (DWORD_PTR *)*ppData;
553    
554     if ( ::IsBadReadPtr(pData, sizeof(DWORD_PTR *)) )
555     {
556     break;
557     }
558    
559     *ppData = (void *)*pData;
560     }
561     }
562    
563     return tag;
564     }
565    
566     /* static */ wxString
567     wxDbgHelpDLL::DumpSymbol(PSYMBOL_INFO pSym, void *pVariable)
568     {
569     wxString s;
570     SYMBOL_INFO symDeref = *pSym;
571     switch ( DereferenceSymbol(&symDeref, &pVariable) )
572     {
573     case SYMBOL_TAG_UDT:
574     // show UDT recursively
575     s = DumpUDT(&symDeref, pVariable);
576     break;
577    
578     case SYMBOL_TAG_BASE_TYPE:
579     // variable of simple type, show directly
580     BasicType bt = GetBasicType(&symDeref);
581     if ( bt )
582     {
583     s = DumpBaseType(bt, pSym->Size, pVariable);
584     }
585     break;
586     }
587    
588     return s;
589     }
590    
591     // ----------------------------------------------------------------------------
592     // debugging helpers
593     // ----------------------------------------------------------------------------
594    
595     // this code is very useful when debugging debughlp.dll-related code but
596     // probably not worth having compiled in normally, please do not remove it!
597     #if 0 // ndef NDEBUG
598    
599     static wxString TagString(wxDbgHelpDLL::SymbolTag tag)
600     {
601     static const wxChar *tags[] =
602     {
603     _T("null"),
604     _T("exe"),
605     _T("compiland"),
606     _T("compiland details"),
607     _T("compiland env"),
608     _T("function"),
609     _T("block"),
610     _T("data"),
611     _T("annotation"),
612     _T("label"),
613     _T("public symbol"),
614     _T("udt"),
615     _T("enum"),
616     _T("function type"),
617     _T("pointer type"),
618     _T("array type"),
619     _T("base type"),
620     _T("typedef"),
621     _T("base class"),
622     _T("friend"),
623     _T("function arg type"),
624     _T("func debug start"),
625     _T("func debug end"),
626     _T("using namespace"),
627     _T("vtable shape"),
628     _T("vtable"),
629     _T("custom"),
630     _T("thunk"),
631     _T("custom type"),
632     _T("managed type"),
633     _T("dimension"),
634     };
635    
636     wxCOMPILE_TIME_ASSERT( WXSIZEOF(tags) == wxDbgHelpDLL::SYMBOL_TAG_MAX,
637     SymbolTagStringMismatch );
638    
639     wxString s;
640     if ( tag < WXSIZEOF(tags) )
641     s = tags[tag];
642     else
643     s.Printf(_T("unrecognized tag (%d)"), tag);
644    
645     return s;
646     }
647    
648     static wxString KindString(wxDbgHelpDLL::DataKind kind)
649     {
650     static const wxChar *kinds[] =
651     {
652     _T("unknown"),
653     _T("local"),
654     _T("static local"),
655     _T("param"),
656     _T("object ptr"),
657     _T("file static"),
658     _T("global"),
659     _T("member"),
660     _T("static member"),
661     _T("constant"),
662     };
663    
664     wxCOMPILE_TIME_ASSERT( WXSIZEOF(kinds) == wxDbgHelpDLL::DATA_MAX,
665     DataKindStringMismatch );
666    
667     wxString s;
668     if ( kind < WXSIZEOF(kinds) )
669     s = kinds[kind];
670     else
671     s.Printf(_T("unrecognized kind (%d)"), kind);
672    
673     return s;
674     }
675    
676     static wxString UdtKindString(wxDbgHelpDLL::UdtKind kind)
677     {
678     static const wxChar *kinds[] =
679     {
680     _T("struct"),
681     _T("class"),
682     _T("union"),
683     };
684    
685     wxCOMPILE_TIME_ASSERT( WXSIZEOF(kinds) == wxDbgHelpDLL::UDT_MAX,
686     UDTKindStringMismatch );
687    
688     wxString s;
689     if ( kind < WXSIZEOF(kinds) )
690     s = kinds[kind];
691     else
692     s.Printf(_T("unrecognized UDT (%d)"), kind);
693    
694     return s;
695     }
696    
697     static wxString TypeString(wxDbgHelpDLL::BasicType bt)
698     {
699     static const wxChar *types[] =
700     {
701     _T("no type"),
702     _T("void"),
703     _T("char"),
704     _T("wchar"),
705     _T(""),
706     _T(""),
707     _T("int"),
708     _T("uint"),
709     _T("float"),
710     _T("bcd"),
711     _T("bool"),
712     _T(""),
713     _T(""),
714     _T("long"),
715     _T("ulong"),
716     _T(""),
717     _T(""),
718     _T(""),
719     _T(""),
720     _T(""),
721     _T(""),
722     _T(""),
723     _T(""),
724     _T(""),
725     _T(""),
726     _T("CURRENCY"),
727     _T("DATE"),
728     _T("VARIANT"),
729     _T("complex"),
730     _T("bit"),
731     _T("BSTR"),
732     _T("HRESULT"),
733     };
734    
735     wxCOMPILE_TIME_ASSERT( WXSIZEOF(types) == wxDbgHelpDLL::BASICTYPE_MAX,
736     BasicTypeStringMismatch );
737    
738     wxString s;
739     if ( bt < WXSIZEOF(types) )
740     s = types[bt];
741    
742     if ( s.empty() )
743     s.Printf(_T("unrecognized type (%d)"), bt);
744    
745     return s;
746     }
747    
748     // this function is meant to be called from under debugger to see the
749     // proprieties of the given type id
750     extern "C" void DumpTI(ULONG ti)
751     {
752     SYMBOL_INFO sym = { sizeof(SYMBOL_INFO) };
753     sym.ModBase = 0x400000; // it's a constant under Win32
754     sym.TypeIndex = ti;
755    
756     wxDbgHelpDLL::SymbolTag tag = wxDbgHelpDLL::SYMBOL_TAG_NULL;
757     DoGetTypeInfo(&sym, TI_GET_SYMTAG, &tag);
758     DoGetTypeInfo(&sym, TI_GET_TYPEID, &ti);
759    
760     OutputDebugString(wxString::Format(_T("Type 0x%x: "), sym.TypeIndex));
761     wxString name = wxDbgHelpDLL::GetSymbolName(&sym);
762     if ( !name.empty() )
763     {
764     OutputDebugString(wxString::Format(_T("name=\"%s\", "), name.c_str()));
765     }
766    
767     DWORD nested;
768     if ( !DoGetTypeInfo(&sym, TI_GET_NESTED, &nested) )
769     {
770     nested = FALSE;
771     }
772    
773     OutputDebugString(wxString::Format(_T("tag=%s%s"),
774     nested ? _T("nested ") : wxEmptyString,
775     TagString(tag).c_str()));
776     if ( tag == wxDbgHelpDLL::SYMBOL_TAG_UDT )
777     {
778     wxDbgHelpDLL::UdtKind udtKind;
779     if ( DoGetTypeInfo(&sym, TI_GET_UDTKIND, &udtKind) )
780     {
781     OutputDebugString(_T(" (") + UdtKindString(udtKind) + _T(')'));
782     }
783     }
784    
785     wxDbgHelpDLL::DataKind kind = wxDbgHelpDLL::DATA_UNKNOWN;
786     if ( DoGetTypeInfo(&sym, TI_GET_DATAKIND, &kind) )
787     {
788     OutputDebugString(wxString::Format(
789     _T(", kind=%s"), KindString(kind).c_str()));
790     if ( kind == wxDbgHelpDLL::DATA_MEMBER )
791     {
792     DWORD ofs = 0;
793     if ( DoGetTypeInfo(&sym, TI_GET_OFFSET, &ofs) )
794     {
795     OutputDebugString(wxString::Format(_T(" (ofs=0x%x)"), ofs));
796     }
797     }
798     }
799    
800     wxDbgHelpDLL::BasicType bt = GetBasicType(&sym);
801     if ( bt )
802     {
803     OutputDebugString(wxString::Format(_T(", type=%s"),
804     TypeString(bt).c_str()));
805     }
806    
807     if ( ti != sym.TypeIndex )
808     {
809     OutputDebugString(wxString::Format(_T(", next ti=0x%x"), ti));
810     }
811    
812     OutputDebugString(_T("\r\n"));
813     }
814    
815     #endif // NDEBUG
816    
817     #endif // wxUSE_DBGHELP

  ViewVC Help
Powered by ViewVC 1.1.22