1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/debughlp.cpp
3 // Purpose: various Win32 debug helpers
4 // Author: Vadim Zeitlin
5 // Modified by: Suzumizaki-kimitaka 2013-04-10
6 // Created: 2005-01-08 (extracted from crashrpt.cpp)
7 // Copyright: (c) 2003-2005 Vadim Zeitlin <vadim@wxwindows.org>
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 #include "wx/wxprec.h"
25 #include "wx/msw/debughlp.h"
27 #if wxUSE_DBGHELP && wxUSE_DYNLIB_CLASS
29 // ----------------------------------------------------------------------------
31 // ----------------------------------------------------------------------------
33 // to prevent recursion which could result from corrupted data we limit
34 // ourselves to that many levels of embedded fields inside structs
35 static const unsigned MAX_DUMP_DEPTH
= 20;
37 // ----------------------------------------------------------------------------
39 // ----------------------------------------------------------------------------
41 // error message from Init()
42 static wxString gs_errMsg
;
44 // ============================================================================
45 // wxDbgHelpDLL implementation
46 // ============================================================================
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 #define DEFINE_SYM_FUNCTION(func, name) \
53 wxDbgHelpDLL::func ## _t wxDbgHelpDLL::func = 0
55 wxDO_FOR_ALL_SYM_FUNCS(DEFINE_SYM_FUNCTION
);
57 #undef DEFINE_SYM_FUNCTION
59 // ----------------------------------------------------------------------------
60 // initialization methods
61 // ----------------------------------------------------------------------------
63 // load all function we need from the DLL
66 bool wxDbgHelpDLL::BindDbgHelpFunctions(const wxDynamicLibrary
& dllDbgHelp
)
68 #define LOAD_SYM_FUNCTION(func, name) \
69 wxDbgHelpDLL::func = (wxDbgHelpDLL::func ## _t) \
70 dllDbgHelp.GetSymbol(wxT(#name)); \
71 if ( !wxDbgHelpDLL::func ) \
73 gs_errMsg += wxT("Function ") wxT(#name) wxT("() not found.\n"); \
77 wxDO_FOR_ALL_SYM_FUNCS_REQUIRED(LOAD_SYM_FUNCTION
);
79 #undef LOAD_SYM_FUNCTION
81 #define LOAD_SYM_FUNCTION_OPTIONAL(func, name) \
82 if ( dllDbgHelp.HasSymbol(wxT(#name)) ) \
84 wxDbgHelpDLL::func = (wxDbgHelpDLL::func ## _t) \
85 dllDbgHelp.GetSymbol(wxT(#name)); \
88 wxDO_FOR_ALL_SYM_FUNCS_OPTIONAL(LOAD_SYM_FUNCTION_OPTIONAL
);
90 #undef LOAD_SYM_FUNCTION_CAN_FAIL
95 // called by Init() if we hadn't done this before
97 bool wxDbgHelpDLL::DoInit()
99 wxDynamicLibrary
dllDbgHelp(wxT("dbghelp.dll"), wxDL_VERBATIM
);
100 if ( dllDbgHelp
.IsLoaded() )
102 if ( BindDbgHelpFunctions(dllDbgHelp
) )
104 // turn on default options
105 DWORD options
= wxDbgHelpDLL::SymGetOptions();
107 options
|= SYMOPT_DEFERRED_LOADS
| SYMOPT_UNDNAME
| SYMOPT_DEBUG
;
109 wxDbgHelpDLL::SymSetOptions(options
);
115 gs_errMsg
+= wxT("\nPlease update your dbghelp.dll version, ")
116 wxT("at least version 5.1 is needed!\n")
117 wxT("(if you already have a new version, please ")
118 wxT("put it in the same directory where the program is.)\n");
120 else // failed to load dbghelp.dll
122 gs_errMsg
+= wxT("Please install dbghelp.dll available free of charge ")
123 wxT("from Microsoft to get more detailed crash information!");
126 gs_errMsg
+= wxT("\nLatest dbghelp.dll is available at ")
127 wxT("http://www.microsoft.com/whdc/ddk/debugging/\n");
133 bool wxDbgHelpDLL::Init()
135 // this flag is -1 until Init() is called for the first time, then it's set
136 // to either false or true depending on whether we could load the functions
137 static int s_loaded
= -1;
139 if ( s_loaded
== -1 )
144 return s_loaded
!= 0;
147 // ----------------------------------------------------------------------------
149 // ----------------------------------------------------------------------------
152 const wxString
& wxDbgHelpDLL::GetErrorMessage()
158 void wxDbgHelpDLL::LogError(const wxChar
*func
)
160 ::OutputDebugString(wxString::Format(wxT("dbghelp: %s() failed: %s\r\n"),
161 func
, wxSysErrorMsg(::GetLastError())).t_str());
164 // ----------------------------------------------------------------------------
166 // ----------------------------------------------------------------------------
170 DoGetTypeInfo(DWORD64 base
, ULONG ti
, IMAGEHLP_SYMBOL_TYPE_INFO type
, void *rc
)
172 static HANDLE s_hProcess
= ::GetCurrentProcess();
174 return wxDbgHelpDLL::SymGetTypeInfo
186 DoGetTypeInfo(wxPSYMBOL_INFO pSym
, IMAGEHLP_SYMBOL_TYPE_INFO type
, void *rc
)
188 return DoGetTypeInfo(pSym
->ModBase
, pSym
->TypeIndex
, type
, rc
);
192 wxDbgHelpDLL::BasicType
GetBasicType(wxPSYMBOL_INFO pSym
)
194 wxDbgHelpDLL::BasicType bt
;
195 return DoGetTypeInfo(pSym
, TI_GET_BASETYPE
, &bt
)
197 : wxDbgHelpDLL::BASICTYPE_NOTYPE
;
201 wxString
wxDbgHelpDLL::GetSymbolName(wxPSYMBOL_INFO pSym
)
215 s
= wxConvCurrent
->cWC2WX(pwszTypeName
);
217 ::LocalFree(pwszTypeName
);
223 /* static */ wxString
224 wxDbgHelpDLL::DumpBaseType(BasicType bt
, DWORD64 length
, PVOID pAddress
)
231 if ( ::IsBadReadPtr(pAddress
, length
) != 0 )
242 const BYTE b
= *(PBYTE
)pAddress
;
244 if ( bt
== BASICTYPE_BOOL
)
245 s
= b
? wxT("true") : wxT("false");
247 s
.Printf(wxT("%#04x"), b
);
249 else if ( length
== 2 )
251 s
.Printf(bt
== BASICTYPE_UINT
? wxT("%#06x") : wxT("%d"),
254 else if ( length
== 4 )
256 bool handled
= false;
258 if ( bt
== BASICTYPE_FLOAT
)
260 s
.Printf(wxT("%f"), *(PFLOAT
)pAddress
);
264 else if ( bt
== BASICTYPE_CHAR
)
266 // don't take more than 32 characters of a string
267 static const size_t NUM_CHARS
= 64;
269 const char *pc
= *(PSTR
*)pAddress
;
270 if ( ::IsBadStringPtrA(pc
, NUM_CHARS
) == 0 )
273 for ( size_t n
= 0; n
< NUM_CHARS
&& *pc
; n
++, pc
++ )
285 // treat just as an opaque DWORD
286 s
.Printf(wxT("%#x"), *(PDWORD
)pAddress
);
289 else if ( length
== 8 )
291 if ( bt
== BASICTYPE_FLOAT
)
293 s
.Printf(wxT("%lf"), *(double *)pAddress
);
295 else // opaque 64 bit value
297 s
.Printf("%#" wxLongLongFmtSpec
"x", *(wxLongLong_t
*)pAddress
);
305 wxDbgHelpDLL::DumpField(wxPSYMBOL_INFO pSym
, void *pVariable
, unsigned level
)
309 // avoid infinite recursion
310 if ( level
> MAX_DUMP_DEPTH
)
315 SymbolTag tag
= SYMBOL_TAG_NULL
;
316 if ( !DoGetTypeInfo(pSym
, TI_GET_SYMTAG
, &tag
) )
324 case SYMBOL_TAG_BASE_CLASS
:
325 s
= DumpUDT(pSym
, pVariable
, level
);
328 case SYMBOL_TAG_DATA
:
333 else // valid location
335 wxDbgHelpDLL::DataKind kind
;
336 if ( !DoGetTypeInfo(pSym
, TI_GET_DATAKIND
, &kind
) ||
337 kind
!= DATA_MEMBER
)
339 // maybe it's a static member? we're not interested in them...
343 // get the offset of the child member, relative to its parent
345 if ( !DoGetTypeInfo(pSym
, TI_GET_OFFSET
, &ofs
) )
348 pVariable
= (void *)((DWORD_PTR
)pVariable
+ ofs
);
351 // now pass to the type representing the type of this member
352 wxSYMBOL_INFO sym
= *pSym
;
353 if ( !DoGetTypeInfo(pSym
, TI_GET_TYPEID
, &sym
.TypeIndex
) )
357 DoGetTypeInfo(&sym
, TI_GET_LENGTH
, &size
);
359 switch ( DereferenceSymbol(&sym
, &pVariable
) )
361 case SYMBOL_TAG_BASE_TYPE
:
363 BasicType bt
= GetBasicType(&sym
);
366 s
= DumpBaseType(bt
, size
, pVariable
);
372 case SYMBOL_TAG_BASE_CLASS
:
373 s
= DumpUDT(&sym
, pVariable
, level
);
377 // Suppress gcc warnings about unhandled enum values.
384 s
= GetSymbolName(pSym
) + wxT(" = ") + s
;
389 // Suppress gcc warnings about unhandled enum values, don't assert
390 // to avoid problems during fatal crash generation.
396 s
= wxString(wxT('\t'), level
+ 1) + s
+ wxT('\n');
402 /* static */ wxString
403 wxDbgHelpDLL::DumpUDT(wxPSYMBOL_INFO pSym
, void *pVariable
, unsigned level
)
407 // we have to limit the depth of UDT dumping as otherwise we get in
408 // infinite loops trying to dump linked lists... 10 levels seems quite
409 // reasonable, full information is in minidump file anyhow
414 s
= GetSymbolName(pSym
);
416 #if !wxUSE_STD_STRING
417 // special handling for ubiquitous wxString: although the code below works
418 // for it as well, it shows the wxStringBase class and takes 4 lines
419 // instead of only one as this branch
420 if ( s
== wxT("wxString") )
422 wxString
*ps
= (wxString
*)pVariable
;
424 // we can't just dump wxString directly as it could be corrupted or
425 // invalid and it could also be locked for writing (i.e. if we're
426 // between GetWriteBuf() and UngetWriteBuf() calls) and assert when we
427 // try to access it contents using public methods, so instead use our
428 // knowledge of its internals
429 const wxChar
*p
= NULL
;
430 if ( !::IsBadReadPtr(ps
, sizeof(wxString
)) )
433 wxStringData
*data
= (wxStringData
*)p
- 1;
434 if ( ::IsBadReadPtr(data
, sizeof(wxStringData
)) ||
435 ::IsBadReadPtr(p
, sizeof(wxChar
*)*data
->nAllocLength
) )
437 p
= NULL
; // don't touch this pointer with 10 feet pole
441 s
<< wxT("(\"") << (p
? p
: wxT("???")) << wxT(")\"");
443 else // any other UDT
444 #endif // !wxUSE_STD_STRING
446 // Determine how many children this type has.
447 DWORD dwChildrenCount
= 0;
448 DoGetTypeInfo(pSym
, TI_GET_CHILDRENCOUNT
, &dwChildrenCount
);
450 // Prepare to get an array of "TypeIds", representing each of the children.
451 TI_FINDCHILDREN_PARAMS
*children
= (TI_FINDCHILDREN_PARAMS
*)
452 malloc(sizeof(TI_FINDCHILDREN_PARAMS
) +
453 (dwChildrenCount
- 1)*sizeof(ULONG
));
457 children
->Count
= dwChildrenCount
;
460 // Get the array of TypeIds, one for each child type
461 if ( !DoGetTypeInfo(pSym
, TI_FINDCHILDREN
, children
) )
469 // Iterate through all children
472 sym
.ModBase
= pSym
->ModBase
;
473 for ( unsigned i
= 0; i
< dwChildrenCount
; i
++ )
475 sym
.TypeIndex
= children
->ChildId
[i
];
477 // children here are in lexicographic sense, i.e. we get all our nested
478 // classes and not only our member fields, but we can't get the values
479 // for the members of the nested classes, of course!
481 if ( DoGetTypeInfo(&sym
, TI_GET_NESTED
, &nested
) && nested
)
484 // avoid infinite recursion: this does seem to happen sometimes with
485 // complex typedefs...
486 if ( sym
.TypeIndex
== pSym
->TypeIndex
)
489 s
+= DumpField(&sym
, pVariable
, level
+ 1);
494 s
<< wxString(wxT('\t'), level
+ 1) << wxT('}');
501 wxDbgHelpDLL::SymbolTag
502 wxDbgHelpDLL::DereferenceSymbol(wxPSYMBOL_INFO pSym
, void **ppData
)
504 SymbolTag tag
= SYMBOL_TAG_NULL
;
507 if ( !DoGetTypeInfo(pSym
, TI_GET_SYMTAG
, &tag
) )
510 if ( tag
!= SYMBOL_TAG_POINTER_TYPE
)
514 if ( !DoGetTypeInfo(pSym
, TI_GET_TYPEID
, &tiNew
) ||
515 tiNew
== pSym
->TypeIndex
)
518 pSym
->TypeIndex
= tiNew
;
520 // remove one level of indirection except for the char strings: we want
521 // to dump "char *" and not a single "char" for them
522 if ( ppData
&& *ppData
&& GetBasicType(pSym
) != BASICTYPE_CHAR
)
524 DWORD_PTR
*pData
= (DWORD_PTR
*)*ppData
;
526 if ( ::IsBadReadPtr(pData
, sizeof(DWORD_PTR
*)) )
531 *ppData
= (void *)*pData
;
538 /* static */ wxString
539 wxDbgHelpDLL::DumpSymbol(wxPSYMBOL_INFO pSym
, void *pVariable
)
542 wxSYMBOL_INFO symDeref
= *pSym
;
543 switch ( DereferenceSymbol(&symDeref
, &pVariable
) )
546 // Suppress gcc warnings about unhandled enum values, don't assert
547 // to avoid problems during fatal crash generation.
551 // show UDT recursively
552 s
= DumpUDT(&symDeref
, pVariable
);
555 case SYMBOL_TAG_BASE_TYPE
:
556 // variable of simple type, show directly
557 BasicType bt
= GetBasicType(&symDeref
);
560 s
= DumpBaseType(bt
, pSym
->Size
, pVariable
);
568 // ----------------------------------------------------------------------------
569 // do the best functions and structures
570 // ----------------------------------------------------------------------------
572 struct wxMswEnmLddMdlsHelperStruct
575 wxMswEnmLddMdlsHelperStruct(wxPENUMLOADED_MODULES_CALLBACK64 ptr
, PVOID content
)
576 : m_pointer_to_callback(ptr
), m_user_content(content
)
578 wxPENUMLOADED_MODULES_CALLBACK64 m_pointer_to_callback
;
579 PVOID m_user_content
;
584 static BOOL CALLBACK
wxMswEnmLddMdlsCallback1(
585 PCSTR ModuleName
, DWORD64 ModuleBase
, ULONG ModuleSize
, PVOID UserContext
)
587 wxMswEnmLddMdlsHelperStruct
& alternate
=
588 *(wxMswEnmLddMdlsHelperStruct
*)(UserContext
);
590 const wxWCharBuffer buf
= wxConvLocal
.cMB2WC(ModuleName
, wxNO_LEN
, NULL
);
591 return (*alternate
.m_pointer_to_callback
)
592 (buf
.data(), ModuleBase
, ModuleSize
, alternate
.m_user_content
);
595 static BOOL CALLBACK
wxMswEnmLddMdlsCallback2(
596 PCSTR ModuleName
, DWORD_PTR ModuleBase
, ULONG ModuleSize
, PVOID UserContext
)
598 wxMswEnmLddMdlsHelperStruct
& alternate
=
599 *(wxMswEnmLddMdlsHelperStruct
*)(UserContext
);
601 const wxWCharBuffer buf
= wxConvLocal
.cMB2WC(ModuleName
, wxNO_LEN
, NULL
);
602 return (*alternate
.m_pointer_to_callback
)
603 (buf
.data(), ModuleBase
, ModuleSize
, alternate
.m_user_content
);
608 static BOOL CALLBACK
wxMswEnmLddMdlsCallback(
609 PCSTR ModuleName
, DWORD_PTR ModuleBase
, ULONG ModuleSize
, PVOID UserContext
)
611 wxMswEnmLddMdlsHelperStruct
& alternate
=
612 *(wxMswEnmLddMdlsHelperStruct
*)(UserContext
);
614 return (*alternate
.m_pointer_to_callback
)
615 (ModuleName
, ModuleBase
, ModuleSize
, alternate
.m_user_content
);
621 BOOL
wxDbgHelpDLL::EnumerateLoadedModulesT(
622 HANDLE handle
, wxPENUMLOADED_MODULES_CALLBACK64 callback
, PVOID pvoid
)
625 if (EnumerateLoadedModulesW64
)
627 const BOOL retVal
= (*EnumerateLoadedModulesW64
)(handle
, callback
, pvoid
);
631 if (EnumerateLoadedModules64
)
633 wxMswEnmLddMdlsHelperStruct
p(callback
, pvoid
);
635 (*EnumerateLoadedModules64
)
636 (handle
, &wxMswEnmLddMdlsCallback1
, (PVOID
)(&p
));
640 if (EnumerateLoadedModules
)
642 wxMswEnmLddMdlsHelperStruct
p(callback
, pvoid
);
644 (*EnumerateLoadedModules
)
645 (handle
, &wxMswEnmLddMdlsCallback2
, (PVOID
)(&p
));
651 if (EnumerateLoadedModules64
)
653 const BOOL retVal
= (*EnumerateLoadedModules64
)(handle
, callback
, pvoid
);
657 if (EnumerateLoadedModules
)
659 wxMswEnmLddMdlsHelperStruct
p(callback
, pvoid
);
661 (*EnumerateLoadedModules
)
662 (handle
, &wxMswEnmLddMdlsCallback
, (PVOID
)(&p
));
671 BOOL
wxDbgHelpDLL::SymInitializeT(HANDLE hProcess
, LPCTSTR UserSearchPath
, BOOL fInvadeProcess
)
676 const BOOL retVal
= (*SymInitializeW
)(hProcess
, UserSearchPath
, fInvadeProcess
);
685 const wxCharBuffer buf
= wxConvLocal
.cWC2MB(UserSearchPath
, wxNO_LEN
, NULL
);
686 retVal
= (*SymInitialize
)(hProcess
, buf
.data(), fInvadeProcess
);
690 retVal
= (*SymInitialize
)(hProcess
, NULL
, fInvadeProcess
);
698 return (*SymInitialize
)(hProcess
, UserSearchPath
, fInvadeProcess
);
705 BOOL
wxDbgHelpDLL::SymFromAddrT(HANDLE hProcess
, DWORD64 Address
, PDWORD64 Displacement
, wxPSYMBOL_INFO Symbol
)
710 const BOOL retVal
= (*SymFromAddrW
)(hProcess
, Address
, Displacement
, Symbol
);
716 BYTE
* symbolBuffer
= new BYTE
[sizeof(SYMBOL_INFO
) + Symbol
->MaxNameLen
*sizeof(CHAR
)];
717 PSYMBOL_INFO data
= (SYMBOL_INFO
*)(symbolBuffer
);
719 data
->SizeOfStruct
= sizeof(SYMBOL_INFO
);
720 data
->MaxNameLen
= Symbol
->MaxNameLen
;
721 if (! (*SymFromAddr
)(hProcess
, Address
, Displacement
, data
))
723 delete [] symbolBuffer
;
727 // We can't refer data->NameLen. It seems to be unmodified.
728 const wxWCharBuffer buf
= wxConvLocal
.cMB2WC(data
->Name
, wxNO_LEN
, NULL
);
730 // FIXME: I know too brute but some header names SYMBOL_INFO::Index
731 // and the other one defines it as SYMBOL_INFO::info.
732 const ULONG dstSize
= Symbol
->SizeOfStruct
;
733 CopyMemory(Symbol
, data
, sizeof(SYMBOL_INFO
)-sizeof(CHAR
));
734 Symbol
->SizeOfStruct
= dstSize
;
735 Symbol
->NameLen
= buf
.length();
736 wxStrncpy(Symbol
->Name
, buf
.data(), Symbol
->MaxNameLen
);
737 delete [] symbolBuffer
;
744 return (*SymFromAddr
)(hProcess
, Address
, Displacement
, Symbol
);
751 BOOL
wxDbgHelpDLL::SymGetLineFromAddrT(HANDLE hProcess
, DWORD64 dwAddr
, PDWORD pdrDisplacement
, wxPIMAGEHLP_LINE Line
)
754 if (SymGetLineFromAddrW64
)
756 const BOOL retVal
= (*SymGetLineFromAddrW64
)(hProcess
, dwAddr
, pdrDisplacement
, Line
);
759 // TODO: seems always fail with GetLastError() returns 487 with 32bit binary on 64 bit Windows.
761 static WCHAR staticBuf
[MAX_PATH
];
762 if (SymGetLineFromAddr64
)
764 IMAGEHLP_LINE64 LineAlternate
;
765 LineAlternate
.SizeOfStruct
= sizeof(IMAGEHLP_LINE64
);
766 if ((*SymGetLineFromAddr64
)(hProcess
, dwAddr
, pdrDisplacement
, &LineAlternate
))
768 const wxWCharBuffer ConvBuf
=
769 wxConvLocal
.cMB2WC(LineAlternate
.FileName
, wxNO_LEN
, NULL
);
770 wxStrncpy(staticBuf
, ConvBuf
.data(), MAX_PATH
);
771 Line
->Key
= LineAlternate
.Key
;
772 Line
->LineNumber
= LineAlternate
.LineNumber
;
773 Line
->FileName
= staticBuf
;
774 Line
->Address
= LineAlternate
.Address
;
778 if (SymGetLineFromAddr
)
780 IMAGEHLP_LINE LineAlternate
;
781 LineAlternate
.SizeOfStruct
= sizeof(IMAGEHLP_LINE
);
782 if ((*SymGetLineFromAddr
)(hProcess
, dwAddr
, pdrDisplacement
, &LineAlternate
))
784 const wxWCharBuffer ConvBuf
=
785 wxConvLocal
.cMB2WC(LineAlternate
.FileName
, wxNO_LEN
, NULL
);
786 wxStrncpy(staticBuf
, ConvBuf
.data(), MAX_PATH
);
787 Line
->Key
= LineAlternate
.Key
;
788 Line
->LineNumber
= LineAlternate
.LineNumber
;
789 Line
->FileName
= staticBuf
;
790 Line
->Address
= LineAlternate
.Address
;
796 if (SymGetLineFromAddr64
)
798 return (*SymGetLineFromAddr64
)(hProcess
, dwAddr
, pdrDisplacement
, Line
);
800 if (SymGetLineFromAddr
)
802 IMAGEHLP_LINE LineAlternate
;
803 LineAlternate
.SizeOfStruct
= sizeof(IMAGEHLP_LINE
);
804 if ((*SymGetLineFromAddr
)(hProcess
, dwAddr
, pdrDisplacement
, &LineAlternate
))
806 Line
->Key
= LineAlternate
.Key
;
807 Line
->LineNumber
= LineAlternate
.LineNumber
;
808 Line
->FileName
= LineAlternate
.FileName
;
809 Line
->Address
= LineAlternate
.Address
;
817 struct wxMswSymEnumSymbolsHelperStruct
820 wxMswSymEnumSymbolsHelperStruct(PSYM_ENUMERATESYMBOLS_CALLBACKW ptr
, PVOID content
)
821 : m_pointer_to_callback(ptr
), m_user_content(content
)
823 PSYM_ENUMERATESYMBOLS_CALLBACKW m_pointer_to_callback
;
824 PVOID m_user_content
;
829 static BOOL CALLBACK
wxMswSymEnumSymbolsHelperCallback(
830 PSYMBOL_INFO pSymInfo
, ULONG SymbolSize
, PVOID UserContext
)
832 wxMswSymEnumSymbolsHelperStruct
& alternate
=
833 *(wxMswSymEnumSymbolsHelperStruct
*)(UserContext
);
834 const wxWCharBuffer buf
= wxConvLocal
.cMB2WC(pSymInfo
->Name
, pSymInfo
->MaxNameLen
, NULL
);
835 BYTE
* symbolBuffer
= new BYTE
[sizeof(SYMBOL_INFOW
) + buf
.length()*sizeof(WCHAR
)];
836 SYMBOL_INFOW
* data
= (SYMBOL_INFOW
*)(symbolBuffer
);
838 // FIXME: I know too brute but some header names SYMBOL_INFO::Index
839 // and the other one defines it as SYMBOL_INFO::info.
840 CopyMemory(data
, pSymInfo
, sizeof(SYMBOL_INFO
)-sizeof(CHAR
));
841 data
->SizeOfStruct
= sizeof(SYMBOL_INFOW
);
842 wxStrncpy(data
->Name
, buf
.data(), buf
.length());
843 BOOL retVal
= (*alternate
.m_pointer_to_callback
)(data
, SymbolSize
, alternate
.m_user_content
);
844 delete [] symbolBuffer
;
851 BOOL
wxDbgHelpDLL::SymEnumSymbolsT(HANDLE hProcess
, ULONG64 baseOfDll
, PCTSTR Mask
,
852 wxPSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback
, const PVOID UserContext
)
857 const BOOL retVal
= (*SymEnumSymbolsW
)(hProcess
, baseOfDll
, Mask
, EnumSymbolsCallback
, UserContext
);
863 wxMswSymEnumSymbolsHelperStruct
p(EnumSymbolsCallback
, UserContext
);
864 const wxCharBuffer buf
= wxConvLocal
.cWC2MB(Mask
? Mask
: L
"", wxNO_LEN
, NULL
);
865 return (*SymEnumSymbols
)(hProcess
, baseOfDll
, buf
.data(),
866 wxMswSymEnumSymbolsHelperCallback
, (PVOID
)(&p
));
872 return (*SymEnumSymbols
)(hProcess
, baseOfDll
, Mask
, EnumSymbolsCallback
, UserContext
);
878 // ----------------------------------------------------------------------------
880 // ----------------------------------------------------------------------------
882 // this code is very useful when debugging debughlp.dll-related code but
883 // probably not worth having compiled in normally, please do not remove it!
886 static wxString
TagString(wxDbgHelpDLL::SymbolTag tag
)
888 static const wxChar
*tags
[] =
893 wxT("compiland details"),
894 wxT("compiland env"),
900 wxT("public symbol"),
903 wxT("function type"),
910 wxT("function arg type"),
911 wxT("func debug start"),
912 wxT("func debug end"),
913 wxT("using namespace"),
923 wxCOMPILE_TIME_ASSERT( WXSIZEOF(tags
) == wxDbgHelpDLL::SYMBOL_TAG_MAX
,
924 SymbolTagStringMismatch
);
927 if ( tag
< WXSIZEOF(tags
) )
930 s
.Printf(wxT("unrecognized tag (%d)"), tag
);
935 static wxString
KindString(wxDbgHelpDLL::DataKind kind
)
937 static const wxChar
*kinds
[] =
947 wxT("static member"),
951 wxCOMPILE_TIME_ASSERT( WXSIZEOF(kinds
) == wxDbgHelpDLL::DATA_MAX
,
952 DataKindStringMismatch
);
955 if ( kind
< WXSIZEOF(kinds
) )
958 s
.Printf(wxT("unrecognized kind (%d)"), kind
);
963 static wxString
UdtKindString(wxDbgHelpDLL::UdtKind kind
)
965 static const wxChar
*kinds
[] =
972 wxCOMPILE_TIME_ASSERT( WXSIZEOF(kinds
) == wxDbgHelpDLL::UDT_MAX
,
973 UDTKindStringMismatch
);
976 if ( kind
< WXSIZEOF(kinds
) )
979 s
.Printf(wxT("unrecognized UDT (%d)"), kind
);
984 static wxString
TypeString(wxDbgHelpDLL::BasicType bt
)
986 static const wxChar
*types
[] =
1022 wxCOMPILE_TIME_ASSERT( WXSIZEOF(types
) == wxDbgHelpDLL::BASICTYPE_MAX
,
1023 BasicTypeStringMismatch
);
1026 if ( bt
< WXSIZEOF(types
) )
1030 s
.Printf(wxT("unrecognized type (%d)"), bt
);
1035 // this function is meant to be called from under debugger to see the
1036 // proprieties of the given type id
1037 extern "C" void DumpTI(ULONG ti
)
1039 SYMBOL_INFO sym
= { sizeof(SYMBOL_INFO
) };
1040 sym
.ModBase
= 0x400000; // it's a constant under Win32
1043 wxDbgHelpDLL::SymbolTag tag
= wxDbgHelpDLL::SYMBOL_TAG_NULL
;
1044 DoGetTypeInfo(&sym
, TI_GET_SYMTAG
, &tag
);
1045 DoGetTypeInfo(&sym
, TI_GET_TYPEID
, &ti
);
1047 OutputDebugString(wxString::Format(wxT("Type 0x%x: "), sym
.TypeIndex
));
1048 wxString name
= wxDbgHelpDLL::GetSymbolName(&sym
);
1049 if ( !name
.empty() )
1051 OutputDebugString(wxString::Format(wxT("name=\"%s\", "), name
.c_str()));
1055 if ( !DoGetTypeInfo(&sym
, TI_GET_NESTED
, &nested
) )
1060 OutputDebugString(wxString::Format(wxT("tag=%s%s"),
1061 nested
? wxT("nested ") : wxEmptyString
,
1062 TagString(tag
).c_str()));
1063 if ( tag
== wxDbgHelpDLL::SYMBOL_TAG_UDT
)
1065 wxDbgHelpDLL::UdtKind udtKind
;
1066 if ( DoGetTypeInfo(&sym
, TI_GET_UDTKIND
, &udtKind
) )
1068 OutputDebugString(wxT(" (") + UdtKindString(udtKind
) + wxT(')'));
1072 wxDbgHelpDLL::DataKind kind
= wxDbgHelpDLL::DATA_UNKNOWN
;
1073 if ( DoGetTypeInfo(&sym
, TI_GET_DATAKIND
, &kind
) )
1075 OutputDebugString(wxString::Format(
1076 wxT(", kind=%s"), KindString(kind
).c_str()));
1077 if ( kind
== wxDbgHelpDLL::DATA_MEMBER
)
1080 if ( DoGetTypeInfo(&sym
, TI_GET_OFFSET
, &ofs
) )
1082 OutputDebugString(wxString::Format(wxT(" (ofs=0x%x)"), ofs
));
1087 wxDbgHelpDLL::BasicType bt
= GetBasicType(&sym
);
1090 OutputDebugString(wxString::Format(wxT(", type=%s"),
1091 TypeString(bt
).c_str()));
1094 if ( ti
!= sym
.TypeIndex
)
1096 OutputDebugString(wxString::Format(wxT(", next ti=0x%x"), ti
));
1099 OutputDebugString(wxT("\r\n"));
1104 #endif // wxUSE_DBGHELP