OWLNext    7.0
Borland's Object Windows Library for the modern age
Loading...
Searching...
No Matches
dumpstack.cpp
Go to the documentation of this file.
1//--------------------------------------------------------------------------
2// ObjectWindows //
3// Copyright (c) 1993, 1996 by Borland International
4// All Rights Reserved.
5// Copyright (c) 1998 by Yura Bidus //
6// //
7//------------------------------------------------------------------------//
8
9#include <owl/pch.h>
10
11#if defined(BI_COMP_BORLANDC)
12# pragma hdrstop
13#endif
14
15#if __DEBUG == 2
16# define USE_MEMCHECK
17#endif
18#ifdef _DEBUG
19# if !defined(USE_MEMCHECK)
20# define USE_MEMCHECK
21# endif
22#endif
23
24
26
27#include <owl/module.h>
28#include <owl/template.h>
29#include <owl/contain.h>
30
31namespace owl {
32
33using namespace std;
34
35//-----------------------------------------------------------------------------
36
37# if ((__GNUC__ != 3) || ((__GNUC_MINOR__ != 3) && (__GNUC_MINOR__ != 2)))
38#if !defined(_WINTRUST_) && !defined(WINTRUST_H)
39# include <wintrust.h>
40# endif // !defined(_WINTRUST_) && !defined(WINTRUST_H)
41# endif // ((__GNUC__ != 3) || ((__GNUC_MINOR__ != 3) && (__GNUC_MINOR__ != 2)))
42
43//
44// Disable warnings in header "imagehlp.h".
45//
46#if defined(BI_COMP_MSC)
47#pragma warning(push)
48#pragma warning(disable:4091) // warning C4091: 'typedef ': ignored on left of '' when no variable is declared
49#endif
50
51#include <imagehlp.h>
52
53#if defined(BI_COMP_MSC)
54#pragma warning(pop)
55#endif
56
57//#pragma comment(lib, "imagehlp.lib")
58
59static const tchar imgHlpStr[] = _T("imagehlp.dll");
60static const char SymFunctionTableAccessStr[] = "SymFunctionTableAccess";
61static const char SymGetModuleInfoStr[] = "SymGetModuleInfo";
62static const char SymLoadModuleStr[] = "SymLoadModule";
63static const char SymGetSymFromAddrStr[] = "SymGetSymFromAddr";
64static const char UnDecorateSymbolNameStr[] = "UnDecorateSymbolName";
65static const char SymUnDNameStr[] = "SymUnDName";
66static const char SymInitializeStr[] = "SymInitialize";
67static const char SymGetOptionsStr[] = "SymGetOptions";
68static const char SymSetOptionsStr[] = "SymSetOptions";
69static const char StackWalkStr[] = "StackWalk";
70//static const char Str[] = "";
71//static const char Str[] = "";
72//static const char Str[] = "";
73
74//-----------------------------------------------------------------------------
75// class IMAGEHLP
76// ~~~~~ ~~~~~~~~
77//
78// delay loading IMAGEHLP.DLL
79class TImageHelp {
80 public:
81 static TModule& GetModule();
82
83 // Environmental
84 static LPVOID SymFunctionTableAccess(HANDLE hProcess, DWORD AddrBase);
85 static BOOL SymGetModuleInfo(HANDLE hProcess, DWORD dwAddr, PIMAGEHLP_MODULE ModuleInfo);
86 static BOOL SymLoadModule(HANDLE hProcess, HANDLE hFile, PSTR ImageName, PSTR ModuleName, DWORD BaseOfDll, DWORD SizeOfDll);
87 static BOOL SymGetSymFromAddr(HANDLE hProcess, DWORD dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_SYMBOL Symbol);
88 static DWORD UnDecorateSymbolName(LPCSTR DecoratedName, LPSTR UnDecoratedName, DWORD UndecoratedLength, DWORD Flags);
89 static BOOL SymUnDName(PIMAGEHLP_SYMBOL sym, LPSTR UnDecName, DWORD UnDecNameLength);
90 static BOOL SymInitialize(HANDLE hProcess, LPSTR UserSearchPath, BOOL fInvadeProcess);
91 static DWORD SymGetOptions();
92 static DWORD SymSetOptions(DWORD SymOptions);
93 static BOOL StackWalk(DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME StackFrame,
94 LPVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
95 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
96 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
97 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress);
98
99};
100//-----------------------------------------------------------------------------
101TModule&
102TImageHelp::GetModule()
103{
104 static TModule imgModule(imgHlpStr, true, true, false);
105 return imgModule;
106}
107//-----------------------------------------------------------------------------
108# if defined(BI_COMP_BORLANDC)
109# pragma warn -inl
110# endif
111LPVOID TImageHelp::SymFunctionTableAccess(HANDLE p1, DWORD p2)
112{
113 static TModuleProc2<LPVOID, HANDLE, DWORD>
114 symFunctionTableAccess(GetModule(), SymFunctionTableAccessStr);
115 return symFunctionTableAccess(p1,p2);
116}
117//-----------------------------------------------------------------------------
118BOOL TImageHelp::SymGetModuleInfo(HANDLE p1, DWORD p2, PIMAGEHLP_MODULE p3)
119{
120 static TModuleProc3<BOOL, HANDLE,DWORD,PIMAGEHLP_MODULE>
121 symGetModuleInfo(GetModule(), SymGetModuleInfoStr);
122 return symGetModuleInfo(p1,p2,p3);
123}
124//-----------------------------------------------------------------------------
125BOOL TImageHelp::SymLoadModule(HANDLE p1, HANDLE p2, PSTR p3,PSTR p4, DWORD p5,
126 DWORD p6)
127{
128 static TModuleProc6<BOOL,HANDLE,HANDLE,PSTR,PSTR,DWORD, DWORD>
129 symLoadModule(GetModule(), SymLoadModuleStr);
130 return symLoadModule(p1,p2,p3,p4,p5,p6);
131}
132//-----------------------------------------------------------------------------
133BOOL TImageHelp::SymGetSymFromAddr(HANDLE p1, DWORD p2, PDWORD p3,
134 PIMAGEHLP_SYMBOL p4)
135{
136 static TModuleProc4<BOOL,HANDLE,DWORD,PDWORD, PIMAGEHLP_SYMBOL>
137 symGetSymFromAddr(GetModule(), SymGetSymFromAddrStr);
138 return symGetSymFromAddr(p1,p2,p3,p4);
139}
140//-----------------------------------------------------------------------------
141DWORD TImageHelp::UnDecorateSymbolName(LPCSTR p1, LPSTR p2, DWORD p3, DWORD p4)
142{
143 static TModuleProc4<DWORD,LPCSTR,LPSTR,DWORD,DWORD>
144 unDecorateSymbolName(GetModule(), UnDecorateSymbolNameStr);
145 return unDecorateSymbolName(p1,p2,p3,p4);
146}
147//-----------------------------------------------------------------------------
148BOOL TImageHelp::SymUnDName(PIMAGEHLP_SYMBOL p1, LPSTR p2, DWORD p3)
149{
150 static TModuleProc3<BOOL,PIMAGEHLP_SYMBOL,LPSTR,DWORD>
151 symUnDName(GetModule(), SymUnDNameStr);
152 return symUnDName(p1,p2,p3);
153}
154//-----------------------------------------------------------------------------
155BOOL TImageHelp::SymInitialize(HANDLE p1, LPSTR p2, BOOL p3)
156{
157 static TModuleProc3<BOOL,HANDLE,LPSTR,BOOL>
158 symInitialize(GetModule(), SymInitializeStr);
159 return symInitialize(p1,p2,p3);
160}
161//-----------------------------------------------------------------------------
162DWORD TImageHelp::SymGetOptions()
163{
164 static TModuleProc0<DWORD>
165 symGetOptions(GetModule(), SymGetOptionsStr);
166 return symGetOptions();
167}
168//-----------------------------------------------------------------------------
169DWORD TImageHelp::SymSetOptions(DWORD p1)
170{
171 static TModuleProc1<DWORD,DWORD>
172 symSetOptions(GetModule(), SymSetOptionsStr);
173 return symSetOptions(p1);
174}
175//-----------------------------------------------------------------------------
176BOOL TImageHelp::StackWalk(DWORD p1, HANDLE p2, HANDLE p3, LPSTACKFRAME p4,
177 LPVOID p5, PREAD_PROCESS_MEMORY_ROUTINE p6,
178 PFUNCTION_TABLE_ACCESS_ROUTINE p7,
179 PGET_MODULE_BASE_ROUTINE p8,
180 PTRANSLATE_ADDRESS_ROUTINE p9)
181{
182 static TModuleProc9<BOOL,DWORD,HANDLE,HANDLE,LPSTACKFRAME,LPVOID,
183 PREAD_PROCESS_MEMORY_ROUTINE,PFUNCTION_TABLE_ACCESS_ROUTINE,
184 PGET_MODULE_BASE_ROUTINE, PTRANSLATE_ADDRESS_ROUTINE>
185 stackWalk(GetModule(), StackWalkStr);
186 return stackWalk(p1,p2,p3,p4,p5,p6,p7,p8,p9);
187}
188//-----------------------------------------------------------------------------
189//-----------------------------------------------------------------------------
190//-----------------------------------------------------------------------------
191//-----------------------------------------------------------------------------
192//-----------------------------------------------------------------------------
193/////////////////////////////////////////////////////////////////////////////
194// Routine to produce stack dump
195#if !defined(UNIX) //JJH we do not need this stuff in unix
196static LPVOID __stdcall FunctionTableAccess(HANDLE hProcess, DWORD dwPCAddress);
197static DWORD __stdcall GetModuleBase(HANDLE hProcess, DWORD dwReturnAddress);
198#endif ///defined(UNIX)
199
200#define MODULE_NAME_LEN 64
201#define SYMBOL_NAME_LEN 128
202
203#if defined(_DEF_DECLARED)
204
205#define TRACE_STACK(m)\
206 do{\
207 if(__OwlDiagGroupDef.IsEnabled()){\
208 tostringstream out; out << m;\
209 __OwlDiagGroupDef.Trace(out.str().c_str(), 0, __FILE__, __LINE__);\
210 }\
211 }while(0)
212
213#else //no _DEF_DECLARED
214 #define TRACE_STACK(m)
215#endif //_DEF_DECLARED
216
217/// \cond
218struct OWL_SYMBOL_INFO{
219 DWORD dwAddress;
220 DWORD dwOffset;
221 CHAR szModule[MODULE_NAME_LEN];
222 CHAR szSymbol[SYMBOL_NAME_LEN];
223};
224/// \endcond
225
226#if !defined(UNIX) //JJH see OwlDumpStack below...
227static LPVOID __stdcall FunctionTableAccess(HANDLE hProcess, DWORD dwPCAddress)
228{
229 return TImageHelp::SymFunctionTableAccess(hProcess, dwPCAddress);
230}
231
232static DWORD __stdcall GetModuleBase(HANDLE hProcess, DWORD dwReturnAddress)
233{
234 IMAGEHLP_MODULE moduleInfo;
235
236 if (TImageHelp::SymGetModuleInfo(hProcess, dwReturnAddress, &moduleInfo))
237 return moduleInfo.BaseOfImage;
238 else{
239 MEMORY_BASIC_INFORMATION memoryBasicInfo;
240
241 if (::VirtualQueryEx(hProcess, (LPVOID) dwReturnAddress,
242 &memoryBasicInfo, sizeof(memoryBasicInfo))){
243
244 char szFile[MAX_PATH] = { 0 };
245 DWORD cch = GetModuleFileNameA((HINSTANCE)memoryBasicInfo.AllocationBase,
246 szFile, MAX_PATH);
247
248 // Ignore the return code since we can't do anything with it.
249 if(!TImageHelp::SymLoadModule(hProcess,NULL, ((cch) ? szFile : NULL),
250 NULL, (DWORD) memoryBasicInfo.AllocationBase, 0)){
251 TRACE_STACK(_T("Error: ") << GetLastError());
252 }
253 return (DWORD) memoryBasicInfo.AllocationBase;
254 }
255 else{
256 TRACE_STACK(_T("Error is ") << GetLastError());
257 }
258 }
259 return 0;
260}
261
262static BOOL ResolveSymbol(HANDLE hProcess, DWORD dwAddress, OWL_SYMBOL_INFO& siSymbol)
263{
264 BOOL fRetval = TRUE;
265
266 siSymbol.dwAddress = dwAddress;
267
268 union __SYMB{
269 CHAR rgchSymbol[sizeof(IMAGEHLP_SYMBOL) + 255];
270 IMAGEHLP_SYMBOL sym;
271 } u;
272
273 CHAR szUndec[256];
274 CHAR szWithOffset[256];
275 LPCSTR pszSymbol;
276 IMAGEHLP_MODULE mi;
277
278 memset(&siSymbol, 0, sizeof(OWL_SYMBOL_INFO));
279 mi.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
280
281 if (!TImageHelp::SymGetModuleInfo(hProcess, dwAddress, &mi))
282 lstrcpyA(siSymbol.szModule, "<no module>");
283 else{
284 LPSTR pszModule = strchr(mi.ImageName, '\\');
285 if (pszModule == NULL)
286 pszModule = mi.ImageName;
287 else
288 pszModule++;
289
290 lstrcpynA(siSymbol.szModule, pszModule, COUNTOF(siSymbol.szModule));
291 lstrcatA(siSymbol.szModule, "! ");
292 }
293
294 __try
295 {
296 u.sym.SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
297 u.sym.Address = dwAddress;
298 u.sym.MaxNameLength = 255;
299
300 if (TImageHelp::SymGetSymFromAddr(hProcess, dwAddress,
301 &(siSymbol.dwOffset), &u.sym)){
302 pszSymbol = u.sym.Name;
303 if (TImageHelp::UnDecorateSymbolName(u.sym.Name, szUndec, COUNTOF(szUndec),
304 UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ACCESS_SPECIFIERS)){
305 pszSymbol = szUndec;
306 }
307 else if (TImageHelp::SymUnDName(&u.sym, szUndec, COUNTOF(szUndec))){
308 pszSymbol = szUndec;
309 }
310
311 if(siSymbol.dwOffset != 0){
312 wsprintfA(szWithOffset, "%s + %d bytes", pszSymbol, siSymbol.dwOffset);
313 pszSymbol = szWithOffset;
314 }
315 }
316 else
317 pszSymbol = "<no symbol>";
318 }
319 __except(true)
320 {
321 pszSymbol = "<EX: no symbol>";
322 siSymbol.dwOffset = dwAddress - mi.BaseOfImage;
323 }
324
325 lstrcpynA(siSymbol.szSymbol, pszSymbol, COUNTOF(siSymbol.szSymbol));
326 return fRetval;
327}
328
329#endif //if !defined(UNIX)
330
331/// \cond
332class __TTraceClipboardData{
333 public:
334 __TTraceClipboardData(uint32 target);
335 ~__TTraceClipboardData();
336 void SendOut(LPCSTR pszData);
337 private:
338 HGLOBAL Memory;
339 uint32 Size;
340 uint32 Used;
341 uint32 Target;
342
343};
344/// \endcond
345
346__TTraceClipboardData::__TTraceClipboardData(uint32 target)
347:
348 Memory(0)
349 ,Size(0)
350 ,Used(0)
351 ,Target(target)
352{
353}
354
355__TTraceClipboardData::~__TTraceClipboardData()
356{
357 if (Memory){
358 // chuck it onto the clipboard
359 // don't free it unless there's an error
360
361 if(!OpenClipboard(NULL))
362 GlobalFree(Memory);
363 else if (!EmptyClipboard() || SetClipboardData(CF_TEXT, Memory) == NULL){
364 GlobalFree(Memory);
365 }
366 else
367 CloseClipboard();
368 }
369}
370
371void __TTraceClipboardData::SendOut(LPCSTR pszData)
372{
373 int nLength;
374 if (pszData == NULL || (nLength = lstrlenA(pszData)) == 0)
375 return;
376
377 // send it to TRACE (can be redirected)
378 if (Target & OWL_STACK_DUMP_TARGET_TRACE){
379 TRACE_STACK(pszData);
380 }
381
382 // send it to OutputDebugString() (can't redirect)
383 if (Target & OWL_STACK_DUMP_TARGET_ODS)
384 OutputDebugStringA(pszData);
385
386 // build a buffer for the clipboard
388 if(!Memory){
389 Memory = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, 1024);
390 if(!Memory){
391 //TRACE("OwlDumpStack Error: No memory available for clipboard");
393 }
394 else{
395 Used = nLength;
396 Size = 1024;
397 LPSTR pstr = (LPSTR)GlobalLock(Memory);
398 if (pstr){
399 lstrcpyA(pstr, pszData);
400 GlobalUnlock(Memory);
401 }
402 else{
403 //TRACE("OwlDumpStack Error: Couldn't lock memory!");
404 GlobalFree(Memory);
405 Memory = 0;
407 }
408 }
409 }
410 else{
411 if ((Used + nLength + 1) >= Size){
412 // grow by leaps and bounds
413 Size *= 2;
414 if(Size > (1024L*1024L)){
415 //TRACE("OwlDumpStack Error: more than one megabyte on clipboard.");
417 }
418
419 HGLOBAL hMemory = GlobalReAlloc(Memory, Size, GMEM_MOVEABLE);
420 if (!hMemory){
421 //TRACE(_T("OwlDumpStack Error: Couldn't get ") << Size << _T("bytes!"));
423 }
424 else
425 Memory = hMemory;
426 }
427
428 LPSTR pstr = (LPSTR) GlobalLock(Memory);
429 if (pstr){
430 lstrcpyA(pstr + Used, pszData);
431 Used += nLength;
432 GlobalUnlock(Memory);
433 }
434 else{
435 //TRACE("OwlDumpStack Error: Couldn't lock memory!");
437 }
438 }
439 }
440 return;
441}
442
443/////////////////////////////////////////////////////////////////////////////
444// OwlDumpStack API
445_OWLFUNC(void)
446OwlDumpStack(uint32 target /* = OWL_STACK_DUMP_TARGET_DEFAULT */)
447{
448#if !defined(UNIX)
449
450 __TTraceClipboardData clipboardData(target);
451
452 clipboardData.SendOut("=== begin OwlDumpStack output ===\r\n");
453
454 TUint32Array adwAddress;
455 HANDLE hProcess = ::GetCurrentProcess();
456 if (TImageHelp::SymInitialize(hProcess, NULL, FALSE)){
457 // force undecorated names to get params
458 DWORD dw = TImageHelp::SymGetOptions();
459 dw &= ~SYMOPT_UNDNAME;
460 TImageHelp::SymSetOptions(dw);
461
462 HANDLE hThread = ::GetCurrentThread();
463 CONTEXT threadContext;
464
465 threadContext.ContextFlags = CONTEXT_FULL;
466
467 if (::GetThreadContext(hThread, &threadContext))
468 {
469 STACKFRAME stackFrame;
470 memset(&stackFrame, 0, sizeof(stackFrame));
471 stackFrame.AddrPC.Mode = AddrModeFlat;
472
473 DWORD dwMachType;
474
475#if defined(_M_IX86)
476 dwMachType = IMAGE_FILE_MACHINE_I386;
477
478 // program counter, stack pointer, and frame pointer
479 stackFrame.AddrPC.Offset = threadContext.Eip;
480 stackFrame.AddrStack.Offset = threadContext.Esp;
481 stackFrame.AddrStack.Mode = AddrModeFlat;
482 stackFrame.AddrFrame.Offset = threadContext.Ebp;
483 stackFrame.AddrFrame.Mode = AddrModeFlat;
484#elif defined(_M_MRX000)
485 // only program counter
486 dwMachType = IMAGE_FILE_MACHINE_R4000;
487 stackFrame.AddrPC. Offset = treadContext.Fir;
488#elif defined(_M_ALPHA)
489 // only program counter
490 dwMachType = IMAGE_FILE_MACHINE_ALPHA;
491 stackFrame.AddrPC.Offset = (unsigned long) threadContext.Fir;
492#elif defined(_M_PPC)
493 // only program counter
494 dwMachType = IMAGE_FILE_MACHINE_POWERPC;
495 stackFrame.AddrPC.Offset = threadContext.Iar;
496#else
497#error Unknown Target Machine
498#endif
499
500 for (int nFrame = 0; nFrame < 1024; nFrame++){
501 if (!TImageHelp::StackWalk(dwMachType, hProcess, hProcess,&stackFrame,
502 &threadContext, NULL,FunctionTableAccess, GetModuleBase, NULL)){
503 break;
504 }
505 adwAddress.AddAt(stackFrame.AddrPC.Offset, nFrame);
506 }
507 }
508 }
509 else{
510 DWORD dw = GetLastError();
511 char sz[100];
512 wsprintfA(sz,
513 "OwlDumpStack Error: IMAGEHLP.DLL wasn't found. "
514 "GetLastError() returned 0x%8.8X\r\n", dw);
515 clipboardData.SendOut(sz);
516 }
517
518 // dump it out now
519 int nAddress;
520 int cAddresses = adwAddress.Size();
521 for (nAddress = 0; nAddress < cAddresses; nAddress++){
522 OWL_SYMBOL_INFO info;
523 DWORD dwAddress = adwAddress[nAddress];
524
525 char sz[20];
526 wsprintfA(sz, "%8.8X: ", dwAddress);
527 clipboardData.SendOut(sz);
528
529 if (ResolveSymbol(hProcess, dwAddress, info)){
530 clipboardData.SendOut(info.szModule);
531 clipboardData.SendOut(info.szSymbol);
532 }
533 else
534 clipboardData.SendOut("symbol not found");
535 clipboardData.SendOut("\r\n");
536 }
537
538 clipboardData.SendOut("=== end OwlDumpStack() output ===\r\n");
539#endif //(ifdef UNIX)
540}
541# if defined(BI_COMP_BORLANDC)
542# pragma warn .inl
543# endif
544
545
546} // OWL namespace
547/* ========================================================================== */
548
uint Size() const
Definition template.h:672
ObjectWindows dynamic-link libraries (DLLs) construct an instance of TModule, which acts as an object...
Definition module.h:78
void AddAt(R t, uint index)
Definition template.h:1543
Definition of container classes used and made available by OWL.
#define MAX_PATH
Definition cygwin.h:98
#define _T(x)
Definition cygwin.h:51
#define SYMBOL_NAME_LEN
#define TRACE_STACK(m)
#define MODULE_NAME_LEN
defined(UNIX)
#define OWL_STACK_DUMP_TARGET_CLIPBOARD
Definition dumpstack.h:20
#define OWL_STACK_DUMP_TARGET_TRACE
Definition dumpstack.h:19
#define OWL_STACK_DUMP_TARGET_ODS
Definition dumpstack.h:22
Definition of class TModule.
Object Windows Library (OWLNext Core).
Definition animctrl.h:22
unsigned long uint32
Definition number.h:34
void OwlDumpStack(uint32 target=OWL_STACK_DUMP_TARGET_DEFAULT)
char tchar
Definition defs.h:77
TTypedArray< uint32, uint32, TStandardAllocator > TUint32Array
Definition contain.h:35
#define _OWLFUNC(p)
Definition defs.h:341
#define COUNTOF(s)
Array element count Important: Only use this with an argument of array type.
Definition defs.h:376
Definition of container classes used and made available by OWL.
#define __try
Definition unixxcpt.cpp:142
#define __except
Definition unixxcpt.cpp:144