|
|
/*++
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; }
|