home *** CD-ROM | disk | FTP | other *** search
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- #include "stdafx.h"
-
- #include <imagehlp.h>
- #pragma comment(lib, "imagehlp.lib")
-
- #ifdef AFX_AUX_SEG
- #pragma code_seg(AFX_AUX_SEG)
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
- // Routine to produce stack dump
-
- static LPVOID __stdcall FunctionTableAccess(HANDLE hProcess, DWORD dwPCAddress);
- static DWORD __stdcall GetModuleBase(HANDLE hProcess, DWORD dwReturnAddress);
-
- #define MODULE_NAME_LEN 64
- #define SYMBOL_NAME_LEN 128
-
- struct SYMBOL_INFO
- {
- DWORD dwAddress;
- DWORD dwOffset;
- CHAR szModule[MODULE_NAME_LEN];
- CHAR szSymbol[SYMBOL_NAME_LEN];
- };
-
- static LPVOID __stdcall FunctionTableAccess(HANDLE hProcess, DWORD dwPCAddress)
- {
- return SymFunctionTableAccess(hProcess, dwPCAddress);
- }
-
- static DWORD __stdcall GetModuleBase(HANDLE hProcess, DWORD dwReturnAddress)
- {
- IMAGEHLP_MODULE moduleInfo;
-
- if (SymGetModuleInfo(hProcess, dwReturnAddress, &moduleInfo))
- return moduleInfo.BaseOfImage;
- else
- {
- MEMORY_BASIC_INFORMATION memoryBasicInfo;
-
- if (::VirtualQueryEx(hProcess, (LPVOID) dwReturnAddress,
- &memoryBasicInfo, sizeof(memoryBasicInfo)))
- {
- DWORD cch = 0;
- char szFile[MAX_PATH] = { 0 };
-
- cch = GetModuleFileNameA((HINSTANCE)memoryBasicInfo.AllocationBase,
- szFile, MAX_PATH);
-
- // Ignore the return code since we can't do anything with it.
- if (!SymLoadModule(hProcess,
- NULL, ((cch) ? szFile : NULL),
- NULL, (DWORD) memoryBasicInfo.AllocationBase, 0))
- {
- DWORD dwError = GetLastError();
- TRACE1("Error: %d\n", dwError);
- }
- return (DWORD) memoryBasicInfo.AllocationBase;
- }
- else
- TRACE1("Error is %d\n", GetLastError());
- }
-
- return 0;
- }
-
- static BOOL ResolveSymbol(HANDLE hProcess, DWORD dwAddress,
- SYMBOL_INFO &siSymbol)
- {
- BOOL fRetval = TRUE;
-
- siSymbol.dwAddress = dwAddress;
-
- union {
- CHAR rgchSymbol[sizeof(IMAGEHLP_SYMBOL) + 255];
- IMAGEHLP_SYMBOL sym;
- };
-
- CHAR szUndec[256];
- CHAR szWithOffset[256];
- LPSTR pszSymbol = NULL;
- IMAGEHLP_MODULE mi;
-
- memset(&siSymbol, 0, sizeof(SYMBOL_INFO));
- mi.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
-
- if (!SymGetModuleInfo(hProcess, dwAddress, &mi))
- lstrcpyA(siSymbol.szModule, "<no module>");
- else
- {
- LPSTR pszModule = strchr(mi.ImageName, '\\');
- if (pszModule == NULL)
- pszModule = mi.ImageName;
- else
- pszModule++;
-
- lstrcpynA(siSymbol.szModule, pszModule, _countof(siSymbol.szModule));
- lstrcatA(siSymbol.szModule, "! ");
- }
-
- __try
- {
- sym.SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
- sym.Address = dwAddress;
- sym.MaxNameLength = 255;
-
- if (SymGetSymFromAddr(hProcess, dwAddress, &(siSymbol.dwOffset), &sym))
- {
- pszSymbol = sym.Name;
-
- if (UnDecorateSymbolName(sym.Name, szUndec, _countof(szUndec),
- UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ACCESS_SPECIFIERS))
- {
- pszSymbol = szUndec;
- }
- else if (SymUnDName(&sym, szUndec, _countof(szUndec)))
- {
- pszSymbol = szUndec;
- }
-
- if (siSymbol.dwOffset != 0)
- {
- wsprintfA(szWithOffset, "%s + %d bytes", pszSymbol, siSymbol.dwOffset);
- pszSymbol = szWithOffset;
- }
- }
- else
- pszSymbol = "<no symbol>";
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- pszSymbol = "<EX: no symbol>";
- siSymbol.dwOffset = dwAddress - mi.BaseOfImage;
- }
-
- lstrcpynA(siSymbol.szSymbol, pszSymbol, _countof(siSymbol.szSymbol));
- return fRetval;
- }
-
- class CTraceClipboardData
- {
- HGLOBAL m_hMemory;
- DWORD m_dwSize;
- DWORD m_dwUsed;
- DWORD m_dwTarget;
-
- public:
- void SendOut(LPCSTR pszData);
- CTraceClipboardData(DWORD dwTarget);
- ~CTraceClipboardData();
- };
-
- CTraceClipboardData::CTraceClipboardData(DWORD dwTarget)
- : m_dwTarget(dwTarget), m_dwSize(0), m_dwUsed(0), m_hMemory(NULL)
- {
- }
-
- CTraceClipboardData::~CTraceClipboardData()
- {
- if (m_hMemory != NULL)
- {
- // chuck it onto the clipboard
- // don't free it unless there's an error
-
- if (!OpenClipboard(NULL))
- GlobalFree(m_hMemory);
- else if (!EmptyClipboard() ||
- SetClipboardData(CF_TEXT, m_hMemory) == NULL)
- {
- GlobalFree(m_hMemory);
- }
- else
- CloseClipboard();
- }
- }
-
- void CTraceClipboardData::SendOut(LPCSTR pszData)
- {
- int nLength;
- if (pszData == NULL || (nLength = lstrlenA(pszData)) == 0)
- return;
-
- // send it to TRACE (can be redirected)
- if (m_dwTarget & AFX_STACK_DUMP_TARGET_TRACE)
- TRACE1("%hs", pszData);
-
- // send it to OutputDebugString() (can't redirect)
- if (m_dwTarget & AFX_STACK_DUMP_TARGET_ODS)
- OutputDebugStringA(pszData);
-
- // build a buffer for the clipboard
- if (m_dwTarget & AFX_STACK_DUMP_TARGET_CLIPBOARD)
- {
- if (m_hMemory == NULL)
- {
- m_hMemory = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, 1024);
- if (m_hMemory == NULL)
- {
- TRACE0("AfxDumpStack Error: No memory available for clipboard.\n");
- m_dwTarget &= ~AFX_STACK_DUMP_TARGET_CLIPBOARD;
- }
- else
- {
- m_dwUsed = nLength;
- m_dwSize = 1024;
- LPSTR pstr = (LPSTR) GlobalLock(m_hMemory);
- if (pstr != NULL)
- {
- lstrcpyA(pstr, pszData);
- GlobalUnlock(m_hMemory);
- }
- else
- {
- TRACE0("AfxDumpStack Error: Couldn't lock memory!\n");
- GlobalFree(m_hMemory);
- m_hMemory = NULL;
- m_dwTarget &= ~AFX_STACK_DUMP_TARGET_CLIPBOARD;
- }
- }
- }
- else
- {
- if ((m_dwUsed + nLength + 1) >= m_dwSize)
- {
- // grow by leaps and bounds
- m_dwSize *= 2;
- if (m_dwSize > (1024L*1024L))
- {
- TRACE0("AfxDumpStack Error: more than one megabyte on clipboard.\n");
- m_dwTarget &= ~AFX_STACK_DUMP_TARGET_CLIPBOARD;
- }
-
- HGLOBAL hMemory = GlobalReAlloc(m_hMemory, m_dwSize, GMEM_MOVEABLE);
- if (hMemory == NULL)
- {
- TRACE1("AfxDumpStack Error: Couldn't get %d bytes!\n", m_dwSize);
- m_dwTarget &= ~AFX_STACK_DUMP_TARGET_CLIPBOARD;
- }
- else
- m_hMemory = hMemory;
- }
-
- LPSTR pstr = (LPSTR) GlobalLock(m_hMemory);
- if (pstr != NULL)
- {
- lstrcpyA(pstr + m_dwUsed, pszData);
- m_dwUsed += nLength;
- GlobalUnlock(m_hMemory);
- }
- else
- {
- TRACE0("AfxDumpStack Error: Couldn't lock memory!\n");
- m_dwTarget &= ~AFX_STACK_DUMP_TARGET_CLIPBOARD;
- }
- }
- }
-
- return;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // AfxDumpStack API
-
- void AFXAPI AfxDumpStack(DWORD dwTarget /* = AFX_STACK_DUMP_TARGET_DEFAULT */)
- {
- CTraceClipboardData clipboardData(dwTarget);
-
- clipboardData.SendOut("=== begin AfxDumpStack output ===\r\n");
-
- CDWordArray adwAddress;
- HANDLE hProcess = ::GetCurrentProcess();
- if (SymInitialize(hProcess, NULL, FALSE))
- {
- // force undecorated names to get params
- DWORD dw = SymGetOptions();
- dw &= ~SYMOPT_UNDNAME;
- SymSetOptions(dw);
-
- HANDLE hThread = ::GetCurrentThread();
- CONTEXT threadContext;
-
- threadContext.ContextFlags = CONTEXT_FULL;
-
- if (::GetThreadContext(hThread, &threadContext))
- {
- STACKFRAME stackFrame;
- memset(&stackFrame, 0, sizeof(stackFrame));
- stackFrame.AddrPC.Mode = AddrModeFlat;
-
- DWORD dwMachType;
-
- #if defined(_M_IX86)
- dwMachType = IMAGE_FILE_MACHINE_I386;
-
- // program counter, stack pointer, and frame pointer
- stackFrame.AddrPC.Offset = threadContext.Eip;
- stackFrame.AddrStack.Offset = threadContext.Esp;
- stackFrame.AddrStack.Mode = AddrModeFlat;
- stackFrame.AddrFrame.Offset = threadContext.Ebp;
- stackFrame.AddrFrame.Mode = AddrModeFlat;
- #elif defined(_M_MRX000)
- // only program counter
- dwMachType = IMAGE_FILE_MACHINE_R4000;
- stackFrame.AddrPC. Offset = treadContext.Fir;
- #elif defined(_M_ALPHA)
- // only program counter
- dwMachType = IMAGE_FILE_MACHINE_ALPHA;
- stackFrame.AddrPC.Offset = (unsigned long) threadContext.Fir;
- #elif defined(_M_PPC)
- // only program counter
- dwMachType = IMAGE_FILE_MACHINE_POWERPC;
- stackFrame.AddrPC.Offset = threadContext.Iar;
- #elif
- #error("Unknown Target Machine");
- #endif
-
- adwAddress.SetSize(0, 16);
-
- int nFrame;
- for (nFrame = 0; nFrame < 1024; nFrame++)
- {
- if (!StackWalk(dwMachType, hProcess, hProcess,
- &stackFrame, &threadContext, NULL,
- FunctionTableAccess, GetModuleBase, NULL))
- {
- break;
- }
-
- adwAddress.SetAtGrow(nFrame, stackFrame.AddrPC.Offset);
- }
- }
- }
- else
- {
- DWORD dw = GetLastError();
- char sz[100];
- wsprintfA(sz,
- "AfxDumpStack Error: IMAGEHLP.DLL wasn't found. "
- "GetLastError() returned 0x%8.8X\r\n", dw);
- clipboardData.SendOut(sz);
- }
-
- // dump it out now
- int nAddress;
- int cAddresses = adwAddress.GetSize();
- for (nAddress = 0; nAddress < cAddresses; nAddress++)
- {
- SYMBOL_INFO info;
- DWORD dwAddress = adwAddress[nAddress];
-
- char sz[20];
- wsprintfA(sz, "%8.8X: ", dwAddress);
- clipboardData.SendOut(sz);
-
- if (ResolveSymbol(hProcess, dwAddress, info))
- {
- clipboardData.SendOut(info.szModule);
- clipboardData.SendOut(info.szSymbol);
- }
- else
- clipboardData.SendOut("symbol not found");
- clipboardData.SendOut("\r\n");
- }
-
- clipboardData.SendOut("=== end AfxDumpStack() output ===\r\n");
- }
-