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

  ViewVC Help
Powered by ViewVC 1.1.22