311 lines
8.1 KiB
C++
311 lines
8.1 KiB
C++
/*++
|
|
|
|
Copyright (c) 1998-1999 Microsoft Corporation
|
|
All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
dbgback.cxx
|
|
|
|
Abstract:
|
|
|
|
Debug Imagehlp
|
|
|
|
Author:
|
|
|
|
Steve Kiraly (SteveKi) 17-May-1998
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "precomp.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include "dbgloadl.hxx"
|
|
#include "dbgimage.hxx"
|
|
#include <wtypes.h>
|
|
//
|
|
// Initialize the imagehlp library.
|
|
//
|
|
TDebugImagehlp::
|
|
TDebugImagehlp(
|
|
VOID
|
|
) : _ImageHlp( TEXT("ImageHlp.dll") ),
|
|
_bValid( FALSE ),
|
|
_pfSymGetModuleInfo( NULL ),
|
|
_pfSymFunctionTableAccess( NULL ),
|
|
_pfSymGetModuleBase( NULL ),
|
|
_pfStackWalk( NULL ),
|
|
_pfSymInitialize( NULL ),
|
|
_pfSymSetOptions( NULL ),
|
|
_pfSymGetSymFromAddr( NULL ),
|
|
_pfSymUnDName( NULL )
|
|
{
|
|
if( _ImageHlp.bValid() )
|
|
{
|
|
_pfSymGetModuleInfo = (pfSymGetModuleInfo) _ImageHlp.pfnGetProc( "SymGetModuleInfo" );
|
|
_pfStackWalk = (pfStackWalk) _ImageHlp.pfnGetProc( "StackWalk" );
|
|
_pfSymSetOptions = (pfSymSetOptions) _ImageHlp.pfnGetProc( "SymSetOptions" );
|
|
_pfSymInitialize = (pfSymInitialize) _ImageHlp.pfnGetProc( "SymInitialize" );
|
|
_pfSymFunctionTableAccess = (pfSymFunctionTableAccess)_ImageHlp.pfnGetProc( "SymFunctionTableAccess" );
|
|
_pfSymGetModuleBase = (pfSymGetModuleBase) _ImageHlp.pfnGetProc( "SymGetModuleBase" );
|
|
_pfSymGetSymFromAddr = (pfSymGetSymFromAddr) _ImageHlp.pfnGetProc( "SymGetSymFromAddr" );
|
|
_pfSymUnDName = (pfSymUnDName) _ImageHlp.pfnGetProc( "SymUnDName" );
|
|
_pfSymGetSearchPath = (pfSymGetSearchPath) _ImageHlp.pfnGetProc( "SymGetSearchPath" );
|
|
_pfSymSetSearchPath = (pfSymSetSearchPath) _ImageHlp.pfnGetProc( "SymSetSearchPath" );
|
|
|
|
if( _pfSymGetModuleInfo &&
|
|
_pfStackWalk &&
|
|
_pfSymSetOptions &&
|
|
_pfSymInitialize &&
|
|
_pfSymFunctionTableAccess &&
|
|
_pfSymGetModuleBase &&
|
|
_pfSymGetSymFromAddr &&
|
|
_pfSymUnDName )
|
|
{
|
|
_pfSymSetOptions( SYMOPT_DEFERRED_LOADS );
|
|
_pfSymInitialize( GetCurrentProcess(), NULL, TRUE );
|
|
_bValid = TRUE;
|
|
|
|
#ifndef UNICODE
|
|
_pszSymbolFormatSpecifier = _T("%08lx %s!%s+0x%x\n");
|
|
#else
|
|
_pszSymbolFormatSpecifier = _T("%08lx %S!%S+0x%x\n");
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Destroy the imagehlp library.
|
|
//
|
|
TDebugImagehlp::
|
|
~TDebugImagehlp(
|
|
VOID
|
|
)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Return the object state.
|
|
//
|
|
BOOL
|
|
TDebugImagehlp::
|
|
bValid(
|
|
VOID
|
|
)
|
|
{
|
|
return _bValid;
|
|
}
|
|
|
|
//
|
|
// Capture the current backtrace.
|
|
//
|
|
BOOL
|
|
TDebugImagehlp::
|
|
bCaptureBacktrace(
|
|
IN UINT nSkip,
|
|
IN ULONG nTotal,
|
|
OUT VOID **apvBacktrace,
|
|
OUT ULONG *puCount
|
|
)
|
|
{
|
|
HANDLE hThread = NULL;
|
|
CONTEXT context = {0};
|
|
|
|
hThread = GetCurrentThread();
|
|
|
|
context.ContextFlags = CONTEXT_FULL;
|
|
|
|
if (GetThreadContext(hThread, &context))
|
|
{
|
|
STACKFRAME stkfrm = {0};
|
|
DWORD dwMachType = 0;
|
|
|
|
stkfrm.AddrPC.Mode = AddrModeFlat;
|
|
|
|
#if defined(_M_IX86)
|
|
dwMachType = IMAGE_FILE_MACHINE_I386;
|
|
stkfrm.AddrPC.Offset = context.Eip; // Program Counter
|
|
stkfrm.AddrStack.Offset = context.Esp; // Stack Pointer
|
|
stkfrm.AddrStack.Mode = AddrModeFlat; // Stack address mode
|
|
stkfrm.AddrFrame.Offset = context.Ebp; // Frame Pointer
|
|
stkfrm.AddrFrame.Mode = AddrModeFlat; // Frame address mode
|
|
#elif defined(_M_MRX000)
|
|
dwMachType = IMAGE_FILE_MACHINE_R4000;
|
|
stkfrm.AddrPC.Offset = context.Fir; // Program Counter
|
|
#elif defined(_M_ALPHA)
|
|
dwMachType = IMAGE_FILE_MACHINE_ALPHA;
|
|
stkfrm.AddrPC.Offset = (ULONG) context.Fir; // Program Counter
|
|
#elif defined(_M_PPC)
|
|
dwMachType = IMAGE_FILE_MACHINE_POWERPC;
|
|
stkfrm.AddrPC.Offset = context.Iar; // Program Counter
|
|
#elif defined(_M_IA64)
|
|
dwMachType = IMAGE_FILE_MACHINE_IA64;
|
|
stkfrm.AddrPC.Offset = context.StIIP;
|
|
#else
|
|
#error("Unknown Target Machine");
|
|
#endif
|
|
|
|
//
|
|
// Clear the valid entry count.
|
|
//
|
|
*puCount = 0;
|
|
|
|
//
|
|
// Walk the stack saving the addresses.
|
|
//
|
|
for( UINT i = 0; i < nSkip + nTotal; i++ )
|
|
{
|
|
if( !_pfStackWalk( dwMachType,
|
|
GetCurrentProcess(),
|
|
GetCurrentProcess(),
|
|
&stkfrm,
|
|
&context,
|
|
NULL,
|
|
_pfSymFunctionTableAccess,
|
|
_pfSymGetModuleBase,
|
|
NULL ))
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (i >= nSkip)
|
|
{
|
|
if( stkfrm.AddrPC.Offset )
|
|
{
|
|
apvBacktrace[(*puCount)++] = (VOID *)stkfrm.AddrPC.Offset;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return *puCount > 0;
|
|
}
|
|
|
|
//
|
|
// Resolve the specified address to a human readable symbol.
|
|
//
|
|
BOOL
|
|
TDebugImagehlp::
|
|
ResolveAddressToSymbol(
|
|
IN PVOID pvAddress,
|
|
IN LPTSTR pszName,
|
|
IN UINT cchNameLength,
|
|
IN EDecoration eDecorateType
|
|
)
|
|
{
|
|
IMAGEHLP_MODULE mod = {0};
|
|
DWORD dwDisplacement = 0;
|
|
INT iLen = 0;
|
|
UINT_PTR Address = (UINT_PTR)pvAddress;
|
|
LPCSTR pszSymbolName = NULL;
|
|
|
|
CHAR szUnDDump[kMaxSymbolNameLength];
|
|
CHAR dump[sizeof(IMAGEHLP_SYMBOL) + kMaxSymbolNameLength];
|
|
PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)&dump;
|
|
|
|
//
|
|
// Fetch the module name
|
|
//
|
|
mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
|
|
_pfSymGetModuleInfo(GetCurrentProcess(), Address, &mod);
|
|
|
|
//
|
|
// Have to do this because size of sym is dynamically determined
|
|
//
|
|
pSym->SizeOfStruct = sizeof(dump);
|
|
pSym->MaxNameLength = kMaxSymbolNameLength;
|
|
|
|
//
|
|
// Fetch the symbol
|
|
//
|
|
if (_pfSymGetSymFromAddr(GetCurrentProcess(),
|
|
Address,
|
|
&dwDisplacement,
|
|
pSym))
|
|
{
|
|
//
|
|
// Assume the caller wants a decorated symbol name.
|
|
//
|
|
pszSymbolName = pSym->Name;
|
|
|
|
if( eDecorateType == kUnDecorateName )
|
|
{
|
|
//
|
|
// Get the undecorated name for this symbol.
|
|
//
|
|
if( _pfSymUnDName( pSym, szUnDDump, sizeof( szUnDDump ) ) )
|
|
{
|
|
pszSymbolName = szUnDDump;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Format the symbol name.
|
|
//
|
|
iLen = _sntprintf( pszName,
|
|
cchNameLength,
|
|
_pszSymbolFormatSpecifier,
|
|
Address,
|
|
mod.ModuleName,
|
|
pszSymbolName,
|
|
dwDisplacement );
|
|
|
|
return iLen > 0;
|
|
}
|
|
|
|
//
|
|
// Get the current symbol search path for this process
|
|
//
|
|
BOOL
|
|
TDebugImagehlp::
|
|
GetSymbolPath(
|
|
IN TDebugString &strSearchPath
|
|
) const
|
|
{
|
|
BOOL bRetval = FALSE;
|
|
CHAR szNarowSearchPath[MAX_PATH];
|
|
LPTSTR pszSearchPath;
|
|
|
|
bRetval = _pfSymGetSearchPath( GetCurrentProcess(), szNarowSearchPath, COUNTOF( szNarowSearchPath ) );
|
|
|
|
if( bRetval )
|
|
{
|
|
bRetval = StringA2T( &pszSearchPath, szNarowSearchPath );
|
|
|
|
if( bRetval )
|
|
{
|
|
bRetval = strSearchPath.bUpdate( pszSearchPath );
|
|
|
|
INTERNAL_DELETE [] pszSearchPath;
|
|
}
|
|
}
|
|
|
|
return bRetval;
|
|
}
|
|
|
|
//
|
|
// Set the current symbol search path for this process
|
|
//
|
|
BOOL
|
|
TDebugImagehlp::
|
|
SetSymbolPath(
|
|
IN LPCTSTR pszSearchPath
|
|
)
|
|
{
|
|
BOOL bRetval = FALSE;
|
|
LPSTR pszNarrowSearchPath = NULL;
|
|
|
|
bRetval = StringT2A( &pszNarrowSearchPath, pszSearchPath );
|
|
|
|
if( bRetval )
|
|
{
|
|
bRetval = _pfSymSetSearchPath( GetCurrentProcess(), pszNarrowSearchPath );
|
|
|
|
INTERNAL_DELETE [] pszNarrowSearchPath;
|
|
}
|
|
|
|
return bRetval;
|
|
}
|