OWLNext    7.0
Borland's Object Windows Library for the modern age
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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);
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);
91 static DWORD SymGetOptions();
92 static DWORD SymSetOptions(DWORD SymOptions);
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{
114 symFunctionTableAccess(GetModule(), SymFunctionTableAccessStr);
116}
117//-----------------------------------------------------------------------------
118BOOL TImageHelp::SymGetModuleInfo(HANDLE p1, DWORD p2, PIMAGEHLP_MODULE p3)
119{
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{
129 symLoadModule(GetModule(), SymLoadModuleStr);
130 return symLoadModule(p1,p2,p3,p4,p5,p6);
131}
132//-----------------------------------------------------------------------------
133BOOL TImageHelp::SymGetSymFromAddr(HANDLE p1, DWORD p2, PDWORD p3,
135{
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{
144 unDecorateSymbolName(GetModule(), UnDecorateSymbolNameStr);
146}
147//-----------------------------------------------------------------------------
148BOOL TImageHelp::SymUnDName(PIMAGEHLP_SYMBOL p1, LPSTR p2, DWORD p3)
149{
151 symUnDName(GetModule(), SymUnDNameStr);
152 return symUnDName(p1,p2,p3);
153}
154//-----------------------------------------------------------------------------
155BOOL TImageHelp::SymInitialize(HANDLE p1, LPSTR p2, BOOL p3)
156{
158 symInitialize(GetModule(), SymInitializeStr);
159 return symInitialize(p1,p2,p3);
160}
161//-----------------------------------------------------------------------------
162DWORD TImageHelp::SymGetOptions()
163{
165 symGetOptions(GetModule(), SymGetOptionsStr);
166 return symGetOptions();
167}
168//-----------------------------------------------------------------------------
169DWORD TImageHelp::SymSetOptions(DWORD p1)
170{
172 symSetOptions(GetModule(), SymSetOptionsStr);
173 return symSetOptions(p1);
174}
175//-----------------------------------------------------------------------------
176BOOL TImageHelp::StackWalk(DWORD p1, HANDLE p2, HANDLE p3, LPSTACKFRAME p4,
181{
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{
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{
235
236 if (TImageHelp::SymGetModuleInfo(hProcess, dwReturnAddress, &moduleInfo))
237 return moduleInfo.BaseOfImage;
238 else{
240
243
244 char szFile[MAX_PATH] = { 0 };
247
248 // Ignore the return code since we can't do anything with it.
249 if(!TImageHelp::SymLoadModule(hProcess,NULL, ((cch) ? szFile : NULL),
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
263{
264 BOOL fRetval = TRUE;
265
266 siSymbol.dwAddress = dwAddress;
267
268 union __SYMB{
269 CHAR rgchSymbol[sizeof(IMAGEHLP_SYMBOL) + 255];
271 } u;
272
273 CHAR szUndec[256];
274 CHAR szWithOffset[256];
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),
306 }
307 else if (TImageHelp::SymUnDName(&u.sym, szUndec, COUNTOF(szUndec))){
309 }
310
311 if(siSymbol.dwOffset != 0){
312 wsprintfA(szWithOffset, "%s + %d bytes", pszSymbol, siSymbol.dwOffset);
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
333 public:
336 void SendOut(LPCSTR pszData);
337 private:
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))
363 else if (!EmptyClipboard() || SetClipboardData(CF_TEXT, Memory) == NULL){
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){
380 }
381
382 // send it to OutputDebugString() (can't redirect)
383 if (Target & OWL_STACK_DUMP_TARGET_ODS)
385
386 // build a buffer for the clipboard
388 if(!Memory){
390 if(!Memory){
391 //TRACE("OwlDumpStack Error: No memory available for clipboard");
392 Target &= ~OWL_STACK_DUMP_TARGET_CLIPBOARD;
393 }
394 else{
395 Used = nLength;
396 Size = 1024;
398 if (pstr){
401 }
402 else{
403 //TRACE("OwlDumpStack Error: Couldn't lock memory!");
405 Memory = 0;
406 Target &= ~OWL_STACK_DUMP_TARGET_CLIPBOARD;
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.");
416 Target &= ~OWL_STACK_DUMP_TARGET_CLIPBOARD;
417 }
418
420 if (!hMemory){
421 //TRACE(_T("OwlDumpStack Error: Couldn't get ") << Size << _T("bytes!"));
422 Target &= ~OWL_STACK_DUMP_TARGET_CLIPBOARD;
423 }
424 else
425 Memory = hMemory;
426 }
427
429 if (pstr){
431 Used += nLength;
433 }
434 else{
435 //TRACE("OwlDumpStack Error: Couldn't lock memory!");
436 Target &= ~OWL_STACK_DUMP_TARGET_CLIPBOARD;
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
451
452 clipboardData.SendOut("=== begin OwlDumpStack output ===\r\n");
453
456 if (TImageHelp::SymInitialize(hProcess, NULL, FALSE)){
457 // force undecorated names to get params
458 DWORD dw = TImageHelp::SymGetOptions();
460 TImageHelp::SymSetOptions(dw);
461
464
465 threadContext.ContextFlags = CONTEXT_FULL;
466
468 {
470 memset(&stackFrame, 0, sizeof(stackFrame));
471 stackFrame.AddrPC.Mode = AddrModeFlat;
472
474
475#if defined(_M_IX86)
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
487 stackFrame.AddrPC. Offset = treadContext.Fir;
488#elif defined(_M_ALPHA)
489 // only program counter
491 stackFrame.AddrPC.Offset = (unsigned long) threadContext.Fir;
492#elif defined(_M_PPC)
493 // only program counter
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];
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++){
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
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
char tchar
Definition defs.h:77
#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