Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

362 lines
7.8 KiB

/*++
Copyright (c) 1998-1999 Microsoft Corporation
All rights reserved.
Module Name:
dbgback.cxx
Abstract:
Debug Backtrace Device
Author:
Steve Kiraly (SteveKi) 16-May-1998
Revision History:
--*/
#include "precomp.hxx"
#pragma hdrstop
#include "dbgloadl.hxx"
#include "dbgimage.hxx"
#include "dbgback.hxx"
#include "dbgreg.hxx"
//
// Construct the backtrace device.
//
TDebugDeviceBacktrace::
TDebugDeviceBacktrace(
IN LPCTSTR pszConfiguration,
IN EDebugType eDebugType
) : TDebugDevice( pszConfiguration, eDebugType ),
_pDbgImagehlp( NULL ),
_bValid( FALSE ),
_pDbgDevice( NULL ),
_bDisplaySymbols( FALSE )
{
//
// Collect andy device arguments.
//
CollectDeviceArguments();
//
// Create the debug imagehlp object.
//
_pDbgImagehlp = INTERNAL_NEW TDebugImagehlp;
//
// Set the valid flag.
//
_bValid = _pDbgImagehlp && _pDbgImagehlp->bValid();
}
//
// Close the backtrace device.
//
TDebugDeviceBacktrace::
~TDebugDeviceBacktrace(
)
{
INTERNAL_DELETE _pDbgImagehlp;
INTERNAL_DELETE _pDbgDevice;
}
//
// Indicates the deveice object is valid.
//
BOOL
TDebugDeviceBacktrace::
bValid(
VOID
)
{
return _bValid;
}
//
// Output the string to the backtrace device
//
BOOL
TDebugDeviceBacktrace::
bOutput(
IN UINT uSize,
IN LPBYTE pBuffer
)
{
//
// Is the class in a good state and we have an output device.
//
BOOL bRetval = bValid() && _pDbgDevice;
if( bRetval )
{
//
// Send the string to the output device.
//
bRetval = _pDbgDevice->bOutput( uSize, pBuffer );
if( bRetval )
{
PVOID apvBacktrace[kMaxDepth];
ULONG uCount = 0;
memset( apvBacktrace, 0, sizeof( apvBacktrace ) );
//
// Capture the current backtrace skiping the call stack of this class
//
bRetval = _pDbgImagehlp->bCaptureBacktrace( 3, kMaxDepth, apvBacktrace, &uCount );
if( bRetval )
{
//
// Send the backtrace to the output device.
//
bRetval = OutputBacktrace( uCount, apvBacktrace );
}
}
}
return bRetval;
}
//
// Send the backtrace to the output device.
//
BOOL
TDebugDeviceBacktrace::
OutputBacktrace(
IN UINT uCount,
IN PVOID *apvBacktrace
)
{
TCHAR szBuffer [kMaxSymbolName];
BOOL bRetval = FALSE;
LPCTSTR pszFmt = NULL;
for( UINT i = 0; i < uCount && apvBacktrace[i]; i++ )
{
if( _bDisplaySymbols )
{
bRetval = _pDbgImagehlp->ResolveAddressToSymbol( apvBacktrace[i],
szBuffer,
COUNTOF( szBuffer ),
TDebugImagehlp::kUnDecorateName );
}
else
{
if( i == 0 )
{
pszFmt = kstrBacktraceStart;
}
else if( !apvBacktrace[i+1] )
{
pszFmt = kstrBacktraceEnd;
}
else
{
pszFmt = kstrBacktraceMiddle;
}
bRetval = _sntprintf( szBuffer, COUNTOF(szBuffer), pszFmt, apvBacktrace[i] ) > 0;
}
if( bRetval )
{
bRetval = _pDbgDevice->bOutput( _tcslen( szBuffer ) * sizeof(TCHAR),
reinterpret_cast<LPBYTE>( szBuffer ) );
}
}
return bRetval;
}
//
// Initialize the specified symbol path.
//
VOID
TDebugDeviceBacktrace::
InitSympath(
VOID
)
{
if( _bDisplaySymbols )
{
TDebugString strRegistryPath;
//
// Get the base registry path.
//
BOOL bRetval = strRegistryPath.bUpdate( kstrSympathRegistryPath );
if( bRetval )
{
TDebugString strProcessName;
//
// Get this processes short name.
//
bRetval = GetProcessName( strProcessName );
if( bRetval )
{
//
// Build the registry path Path\processname
//
bRetval = strRegistryPath.bCat( kstrSlash ) && strRegistryPath.bCat( strProcessName );
if( bRetval )
{
//
// Open the registry key.
//
TDebugRegistry Registry( strRegistryPath, TDebugRegistry::kOpen|TDebugRegistry::kRead, HKEY_LOCAL_MACHINE );
bRetval = Registry.bValid();
if( bRetval )
{
//
// Read the symbol path if there.
//
bRetval = Registry.bRead( kstrSympathRegistryKey, _strSympath );
}
}
}
}
//
// If the registry did not specifiy a symbol path then use the
// default symbol path that imagehlp has.
//
if( !bRetval )
{
_pDbgImagehlp->GetSymbolPath( _strSympath );
}
else
{
//
// Set the symbol path
//
_pDbgImagehlp->SetSymbolPath( _strSympath );
}
}
}
//
// If we are displaying symbols then as the first line in the output
// device indicate the symbol path.
//
VOID
TDebugDeviceBacktrace::
WriteSympathToOutputDevice(
VOID
)
{
if( _bDisplaySymbols )
{
TDebugString strSympath;
strSympath.bFormat(kstrSympathFormat, _strSympath);
_pDbgDevice->bOutput(strSympath.uLen() * sizeof(TCHAR),
reinterpret_cast<LPBYTE>(
const_cast<LPTSTR>(
static_cast<LPCTSTR>(
strSympath))));
}
}
//
// Create and the set the output device type.
//
BOOL
TDebugDeviceBacktrace::
InitializeOutputDevice(
IN UINT uDevice,
IN LPCTSTR pszConfiguration,
IN UINT uCharacterType
)
{
if( bValid() )
{
//
// Get access to the debug factory.
//
TDebugFactory DebugFactory;
//
// If we failed to create the debug factory then exit.
//
if (DebugFactory.bValid())
{
//
// Release the existing debug device.
//
delete _pDbgDevice;
//
// Create the specified debug device using the factory.
//
_pDbgDevice = DebugFactory.Produce( uDevice, pszConfiguration, uCharacterType );
//
// If the debug device was created successfully.
//
if( _pDbgDevice )
{
//
// Initialize the sympath
//
InitSympath();
//
// Write sympath to output device.
//
WriteSympathToOutputDevice();
}
}
}
//
// Indicate the debug device was created.
//
return _pDbgDevice != NULL;
}
//
// Get the device arguments from the configuration string.
//
BOOL
TDebugDeviceBacktrace::
CollectDeviceArguments(
VOID
)
{
TDebugDevice::TIterator i( this );
for( i.First(); !i.IsDone(); i.Next() )
{
switch( i.Index() )
{
//
// Ignore the character type.
//
case 1:
break;
//
// The second aregument is the symbol specifier.
//
case 2:
_bDisplaySymbols = !_tcsicmp( kstrSymbols, i.Current() );
break;
}
}
return FALSE;
}