diff --git a/pykd/dbgclient.cpp b/pykd/dbgclient.cpp deleted file mode 100644 index f057c02..0000000 --- a/pykd/dbgclient.cpp +++ /dev/null @@ -1,740 +0,0 @@ -#include "stdafx.h" -#include - -#include "dbgclient.h" -#include "stkframe.h" - -namespace pykd { - -/////////////////////////////////////////////////////////////////////////////////// - -DebugClientPtr g_dbgClient( DebugClient::createDbgClient() ); - -/////////////////////////////////////////////////////////////////////////////////// - -DebugClient::DebugClient( IDebugClient4 *client ) - : DbgObject( client ) - , m_symSymbols( new SyntheticSymbols(*m_symbols, *this) ) - , m_internalDbgEventHandler(client, this, m_symSymbols, m_bpCallbacks) -{ -} - -/////////////////////////////////////////////////////////////////////////////////// - -DebugClientPtr DebugClient::createDbgClient() { - - HRESULT hres; - CComPtr client = NULL; - - hres = DebugCreate( __uuidof(IDebugClient4), (void **)&client ); - if ( FAILED( hres ) ) - throw DbgException("DebugCreate failed"); - - return createDbgClient( client ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -DebugClientPtr DebugClient::createDbgClient( IDebugClient4 *client ) { - - //HRESULT hres; - //CComPtr newClient = NULL; - - //hres = client->CreateClient( &newClient ); - //if ( FAILED( hres ) ) - // throw DbgException("DebugCreate failed"); - - //CComQIPtr client4= newClient; - - //return DebugClientPtr( new DebugClient(client4) ); - - return DebugClientPtr( new DebugClient(client) ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -DebugClientPtr DebugClient::setDbgClientCurrent( DebugClientPtr newDbgClient ) { - DebugClientPtr oldClient = g_dbgClient; - g_dbgClient = newDbgClient; - return oldClient; -} - -/////////////////////////////////////////////////////////////////////////////////// - -python::tuple DebugClient::getDebuggeeType() -{ - HRESULT hres; - ULONG debugClass, debugQualifier; - - hres = m_control->GetDebuggeeType( &debugClass, &debugQualifier ); - - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::GetDebuggeeType failed" ); - - return python::make_tuple( debugClass, debugQualifier ); -} - -python::tuple getDebuggeeType() -{ - return g_dbgClient->getDebuggeeType(); -} - -/////////////////////////////////////////////////////////////////////////////////// - -ULONG DebugClient::getExecutionStatus() -{ - ULONG currentStatus; - HRESULT hres; - - hres = m_control->GetExecutionStatus( ¤tStatus ); - - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::GetExecutionStatus failed" ); - - return currentStatus; -} - -ULONG getExecutionStatus() -{ - return g_dbgClient->getExecutionStatus(); -} - -/////////////////////////////////////////////////////////////////////////////////// - -bool DebugClient::is64bitSystem() -{ - HRESULT hres; - - hres = m_control->IsPointer64Bit(); - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::IsPointer64Bit failed" ); - - return hres == S_OK; -} - -bool -is64bitSystem() -{ - return g_dbgClient->is64bitSystem(); -} - - -/////////////////////////////////////////////////////////////////////////////////// - -bool DebugClient::isDumpAnalyzing() -{ - HRESULT hres; - ULONG debugClass, debugQualifier; - - hres = m_control->GetDebuggeeType( &debugClass, &debugQualifier ); - - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::GetDebuggeeType failed" ); - - return debugQualifier >= DEBUG_DUMP_SMALL; -} - -bool isDumpAnalyzing() -{ - return g_dbgClient->isDumpAnalyzing(); -} - -/////////////////////////////////////////////////////////////////////////////////// - -bool DebugClient::isKernelDebugging() -{ - HRESULT hres; - ULONG debugClass, debugQualifier; - - hres = m_control->GetDebuggeeType( &debugClass, &debugQualifier ); - - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::GetDebuggeeType failed" ); - - return debugClass == DEBUG_CLASS_KERNEL; -} - -bool isKernelDebugging() -{ - return g_dbgClient->isKernelDebugging(); -} - -////////////////////////////////////////////////////////////////////////////////// - -void DebugClient::loadDump( const std::wstring &fileName ) -{ - HRESULT hres; - - hres = m_client->OpenDumpFileWide( fileName.c_str(), NULL ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugClient4::OpenDumpFileWide failed" ); - - hres = safeWaitForEvent(); - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::WaitForEvent failed" ); -} - -void loadDump( const std::wstring &fileName ) { - g_dbgClient->loadDump( fileName ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -void DebugClient::startProcess( const std::wstring &processName ) -{ - HRESULT hres; - - ULONG opt; - hres = m_control->GetEngineOptions( &opt ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::GetEngineOptions failed" ); - - opt |= DEBUG_ENGOPT_INITIAL_BREAK; - hres = m_control->SetEngineOptions( opt ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::SetEngineOptions failed" ); - - std::vector< std::wstring::value_type > cmdLine( processName.size() + 1 ); - wcscpy_s( &cmdLine[0], cmdLine.size(), processName.c_str() ); - - hres = m_client->CreateProcessWide( 0, &cmdLine[0], DEBUG_PROCESS | DETACHED_PROCESS ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugClient4::CreateProcessWide failed" ); - - hres = safeWaitForEvent(); - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::WaitForEvent failed" ); -} - -void startProcess( const std::wstring &processName ) { - g_dbgClient->startProcess( processName ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -void DebugClient::attachProcess( ULONG processId ) -{ - HRESULT hres; - - hres = m_client->AttachProcess( 0, processId, 0 ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugClient::AttachProcess failed" ); -} - -void attachProcess( ULONG processId ) { - g_dbgClient->attachProcess( processId ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -void DebugClient::detachProcess() -{ - HRESULT hres; - - hres = m_client->DetachCurrentProcess(); - if ( FAILED( hres ) ) - throw DbgException( "IDebugClient::DetachCurrentProcess failed" ); -} - -void detachProcess() { - g_dbgClient->detachProcess(); -} - -/////////////////////////////////////////////////////////////////////////////////// - -void DebugClient::attachKernel( const std::wstring ¶m ) -{ - HRESULT hres; - - hres = m_client5->AttachKernelWide( DEBUG_ATTACH_KERNEL_CONNECTION, param.c_str() ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugClient5::AttachKernelWide failed" ); -} - -void attachKernel( const std::wstring ¶m ) { - g_dbgClient->attachKernel( param ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -std::string DebugClient::findSymbol( ULONG64 offset ) -{ - HRESULT hres; - - offset = addr64( offset ); - - char symbolName[0x100]; - ULONG64 displace = 0; - hres = m_symbols->GetNameByOffset( offset, symbolName, sizeof(symbolName), NULL, &displace ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugSymbol::GetNameByOffset failed" ); - - std::stringstream ss; - displace == 0 ? ss << symbolName : ss << symbolName << '+' << std::hex << displace; - - return ss.str(); -} - -std::string findSymbol( ULONG64 offset ) -{ - return g_dbgClient->findSymbol( offset ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -ULONG64 DebugClient::getOffset( const std::wstring symbolname ) -{ - HRESULT hres; - ULONG64 offset; - - hres = m_symbols->GetOffsetByNameWide( symbolname.c_str(), &offset ); - if ( FAILED( hres ) ) - throw DbgException( "failed to find offset for symbol" ); - - return offset; -} - -ULONG64 getOffset( const std::wstring symbolname ) -{ - return g_dbgClient->getOffset( symbolname ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -std::string DebugClient::getPdbFile( ULONG64 moduleBase ) -{ - HRESULT hres; - IMAGEHLP_MODULEW64 imageHelpInfo = { 0 }; - - hres = - m_advanced->GetSymbolInformation( - DEBUG_SYMINFO_IMAGEHLP_MODULEW64, - moduleBase, - 0, - &imageHelpInfo, - sizeof( imageHelpInfo ), - NULL, - NULL, - 0, - NULL ); - - if ( FAILED( hres ) ) - throw DbgException( "IDebugAdvanced2::GetSymbolInformation failed" ); - - char fileName[ 256 ]; - WideCharToMultiByte( CP_ACP, 0, imageHelpInfo.LoadedPdbName, 256, fileName, 256, NULL, NULL ); - - return std::string( fileName ); -} - -std::string getPdbFile( ULONG64 moduleBase ) -{ - return g_dbgClient->getPdbFile( moduleBase ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -std::string DebugClient::dbgSymPath() -{ - HRESULT hres; - std::string pathStr; - - ULONG size; - m_symbols->GetSymbolPath( NULL, 0, &size ); - - std::vector path(size); - hres = m_symbols->GetSymbolPath( &path[0], size, NULL ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugSymbols::GetSymbolPath failed" ); - - return std::string(&path[0],size); -} - -std::string dbgSymPath() -{ - return g_dbgClient->dbgSymPath(); -} - -/////////////////////////////////////////////////////////////////////////////////// - -void DebugClient::setExecutionStatus( ULONG status ) -{ - HRESULT hres; - - hres = m_control->SetExecutionStatus( status ); - - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::SetExecutionStatus failed" ); -} - -void setExecutionStatus( ULONG status ) -{ - g_dbgClient->setExecutionStatus( status ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -HRESULT DebugClient::safeWaitForEvent(ULONG timeout /*= INFINITE*/, ULONG flags /*= DEBUG_WAIT_DEFAULT*/) -{ - PyThread_StateRestore pyThreadRestore( m_pyThreadState ); - return m_control->WaitForEvent( flags, timeout ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -void DebugClient::waitForEvent() -{ - HRESULT hres = safeWaitForEvent(); - - if ( FAILED( hres ) ) - { - if (E_UNEXPECTED == hres) - throw WaitEventException(); - - throw DbgException( "IDebugControl::WaitForEvent failed" ); - } -} - -void waitForEvent() -{ - g_dbgClient->waitForEvent(); -} - -/////////////////////////////////////////////////////////////////////////////////// - -ULONG DebugClient::ptrSize() -{ - HRESULT hres; - - hres = m_control->IsPointer64Bit(); - - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::IsPointer64Bit failed" ); - - return S_OK == hres ? 8 : 4; -} - -/////////////////////////////////////////////////////////////////////////////////// - -ULONG ptrSize() -{ - return g_dbgClient->ptrSize(); -} - -/////////////////////////////////////////////////////////////////////////////////// - -void DebugClient::terminateProcess() -{ - HRESULT hres; - - hres = m_client->TerminateCurrentProcess(); - if ( FAILED( hres ) ) - throw DbgException( "IDebugClient::TerminateCurrentProcess", hres ); -} - -void terminateProcess() -{ - g_dbgClient->terminateProcess(); -} - -/////////////////////////////////////////////////////////////////////////////////// - -static const boost::regex moduleSymMatch("^(?:([^!]*)!)?([^!]+)$"); - -void DebugClient::splitSymName( const std::string &fullName, std::string &moduleName, std::string &symbolName ) -{ - boost::cmatch matchResult; - - OutputReader outputDiscard( m_client ); - - if ( !boost::regex_match( fullName.c_str(), matchResult, moduleSymMatch ) ) - { - std::stringstream sstr; - sstr << "invalid symbol name: " << fullName; - throw SymbolException( sstr.str() ); - } - - symbolName = std::string( matchResult[2].first, matchResult[2].second ); - - if ( matchResult[1].matched ) - { - moduleName = std::string( matchResult[1].first, matchResult[1].second ); - - return; - } - - HRESULT hres; - ULONG64 base; - - hres = m_symbols->GetSymbolModule( ( std::string("!") + symbolName ).c_str(), &base ); - if ( FAILED( hres ) ) - { - std::stringstream sstr; - sstr << "failed to find module for symbol: " << symbolName; - throw SymbolException( sstr.str() ); - } - - char nameBuffer[0x100]; - - hres = - m_symbols->GetModuleNameString( - DEBUG_MODNAME_MODULE, - DEBUG_ANY_ID, - base, - nameBuffer, - sizeof(nameBuffer), - NULL ); - - if ( FAILED( hres ) ) - { - std::stringstream sstr; - sstr << "failed to find module for symbol: " << symbolName; - throw SymbolException( sstr.str() ); - } - - moduleName = std::string( nameBuffer ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -ULONG64 DebugClient::getSymbolSize( const std::string &fullName ) -{ - std::string moduleName; - std::string symName; - - if ( TypeInfo::isBaseType( fullName ) ) - return TypeInfo::getBaseTypeInfo( fullName )->getSize(); - - splitSymName( fullName, moduleName, symName ); - - ModulePtr module = loadModuleByName( moduleName ); - - return module->getSymbolSize(symName); -} - -ULONG64 getSymbolSize( const std::string &symName ) -{ - return g_dbgClient->getSymbolSize(symName); -} - -/////////////////////////////////////////////////////////////////////////////////// - -TypeInfoPtr DebugClient::getTypeInfoByName( const std::string &typeName ) -{ - std::string moduleName; - std::string symName; - - if ( TypeInfo::isBaseType( typeName ) ) - return TypeInfo::getBaseTypeInfo( typeName ); - - splitSymName( typeName, moduleName, symName ); - - ModulePtr module = loadModuleByName( moduleName ); - - return module->getTypeByName( symName ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -TypedVarPtr DebugClient::getTypedVarByName( const std::string &varName ) -{ - std::string moduleName; - std::string symName; - - splitSymName( varName, moduleName, symName ); - - ModulePtr module = loadModuleByName( moduleName ); - - return module->getTypedVarByName( symName ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -TypedVarPtr DebugClient::getTypedVarByTypeName( const std::string &typeName, ULONG64 addr ) -{ - addr = addr64( addr ); - - std::string moduleName; - std::string symName; - - splitSymName( typeName, moduleName, symName ); - - ModulePtr module = loadModuleByName( moduleName ); - - return module->getTypedVarByTypeName( symName, addr ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -TypedVarPtr DebugClient::containingRecordByName( ULONG64 addr, const std::string &typeName, const std::string &fieldName ) -{ - addr = addr64( addr ); - - std::string moduleName; - std::string symName; - - splitSymName( typeName, moduleName, symName ); - - ModulePtr module = loadModuleByName( moduleName ); - - return module->containingRecordByName( addr, symName, fieldName ); -} - -TypedVarPtr containingRecordByName( ULONG64 addr, const std::string &typeName, const std::string &fieldName ) -{ - return g_dbgClient->containingRecordByName( addr, typeName, fieldName ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -TypedVarPtr DebugClient::containingRecordByType( ULONG64 addr, const TypeInfoPtr &typeInfo, const std::string &fieldName ) -{ - addr = addr64(addr); - - VarDataPtr varData = VarDataMemory::factory( m_dataSpaces, addr - typeInfo->getFieldOffsetByNameRecirsive(fieldName) ); - - return TypedVar::getTypedVar( m_client, typeInfo, varData ); -} - -TypedVarPtr containingRecordByType( ULONG64 addr, const TypeInfoPtr &typeInfo, const std::string &fieldName ) -{ - return g_dbgClient->containingRecordByType( addr, typeInfo, fieldName ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -python::list DebugClient::getTypedVarListByType( ULONG64 listHeadAddress, const TypeInfoPtr &typeInfo, const std::string &listEntryName )\ -{ - python::list lst; - - listHeadAddress = addr64( listHeadAddress ); - - ULONG64 entryAddress = 0; - - TypeInfoPtr fieldTypeInfo = typeInfo->getField( listEntryName ); - - if ( fieldTypeInfo->getName() == ( typeInfo->getName() + "*" ) ) - { - for( entryAddress = ptrPtr( listHeadAddress ); addr64(entryAddress) != listHeadAddress && entryAddress != NULL; entryAddress = ptrPtr( entryAddress + typeInfo->getFieldOffsetByNameRecirsive(listEntryName) ) ) - lst.append( getTypedVarByTypeInfo( typeInfo, entryAddress ) ); - } - else - { - for( entryAddress = ptrPtr( listHeadAddress ); addr64(entryAddress) != listHeadAddress && entryAddress != NULL; entryAddress = ptrPtr( entryAddress ) ) - lst.append( containingRecordByType( entryAddress, typeInfo, listEntryName ) ); - } - - return lst; -} - -python::list getTypedVarListByType( ULONG64 listHeadAddress, const TypeInfoPtr &typeInfo, const std::string &listEntryName ) -{ - return g_dbgClient->getTypedVarListByType( listHeadAddress, typeInfo, listEntryName ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -python::list DebugClient::getTypedVarListByTypeName( ULONG64 listHeadAddress, const std::string &typeName, const std::string &listEntryName ) -{ - std::string moduleName; - std::string symName; - - splitSymName( typeName, moduleName, symName ); - - ModulePtr module = loadModuleByName( moduleName ); - - return module->getTypedVarListByTypeName( listHeadAddress, symName, listEntryName ); -} - -python::list getTypedVarListByTypeName( ULONG64 listHeadAddress, const std::string &typeName, const std::string &listEntryName ) -{ - return g_dbgClient->getTypedVarListByTypeName( listHeadAddress, typeName, listEntryName ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -python::list DebugClient::getTypedVarArrayByType( ULONG64 address, const TypeInfoPtr &typeInfo, ULONG number ) -{ - address = addr64(address); - - python::list lst; - - for( ULONG i = 0; i < number; ++i ) - lst.append( getTypedVarByTypeInfo( typeInfo, address + i * typeInfo->getSize() ) ); - - return lst; -} - -python::list getTypedVarArrayByType( ULONG64 address, const TypeInfoPtr &typeInfo, ULONG number ) -{ - return g_dbgClient->getTypedVarArrayByType( address, typeInfo, number ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -python::list DebugClient::getTypedVarArrayByTypeName( ULONG64 addr, const std::string &typeName, ULONG number ) -{ - std::string moduleName; - std::string symName; - - splitSymName( typeName, moduleName, symName ); - - ModulePtr module = loadModuleByName( moduleName ); - - return module->getTypedVarArrayByTypeName( addr, symName, number ); -} - -python::list getTypedVarArrayByTypeName( ULONG64 addr, const std::string &typeName, ULONG number ) -{ - return g_dbgClient->getTypedVarArrayByTypeName( addr, typeName, number ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -python::tuple DebugClient::getSourceLine( ULONG64 offset ) -{ - HRESULT hres; - - if ( offset == 0 ) - { - hres = m_registers->GetInstructionOffset( &offset ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugRegisters::GetInstructionOffset failed" ); - } - - ULONG fileNameLength = 0; - - m_symbols->GetLineByOffset( - offset, - NULL, - NULL, - 0, - &fileNameLength, - NULL ); - - if ( fileNameLength == 0 ) - throw DbgException( "Failed to find source file" ); - - std::vector fileNameBuf( fileNameLength ); - - ULONG lineNo; - ULONG64 displacement; - - hres = - m_symbols->GetLineByOffset( - offset, - &lineNo, - &fileNameBuf[0], - fileNameLength, - NULL, - &displacement ); - - if ( FAILED( hres ) ) - throw DbgException( "IDebugSymbol::GetLineByOffset method failed" ); - - return python::make_tuple( std::string( &fileNameBuf[0] ), lineNo, displacement ); -} - -/////////////////////////////////////////////////////////////////////////////////// - -}; // end of namespace pykd diff --git a/pykd/dbgclient.h b/pykd/dbgclient.h deleted file mode 100644 index 376ee6d..0000000 --- a/pykd/dbgclient.h +++ /dev/null @@ -1,530 +0,0 @@ -#pragma once - -#include -#include - -#include -#include - -///////////////////////////////////////////////////////////////////////////////// - -#include "dbgobj.h" -#include "dbgexcept.h" -#include "module.h" -#include "dbgio.h" -#include "dbgcmd.h" -#include "pyaux.h" -#include "disasm.h" -#include "cpureg.h" -#include "inteventhandler.h" -#include "synsymbol.h" -#include "context.h" - -///////////////////////////////////////////////////////////////////////////////// - -namespace pykd { - -///////////////////////////////////////////////////////////////////////////////// - -class DebugClient; -typedef boost::shared_ptr DebugClientPtr; - -///////////////////////////////////////////////////////////////////////////////// - -typedef ULONG BPOINT_ID; -typedef python::object BpCallback; -typedef std::map BpCallbackMapIml; -struct BpCallbackMap { - boost::shared_ptr m_lock; - BpCallbackMapIml m_map; - - BpCallbackMap() : m_lock(new boost::recursive_mutex) {} -}; - -///////////////////////////////////////////////////////////////////////////////// - -class DebugClient : private DbgObject - , public boost::enable_shared_from_this { - -private: - // simple IDebugControl4 call wrapper - template - T getDbgControlT( - HRESULT (STDMETHODCALLTYPE IDebugControl4::*method)(T *), - const char *methodName - ) - { - T retValue; - HRESULT hres = (m_control->*method)(&retValue); - if (S_OK != hres) - throw DbgException( methodName, hres); - return retValue; - } - #define getDbgControl(method) \ - getDbgControlT( &IDebugControl4::##method, "IDebugControl4::" #method ) - -public: - - virtual ~DebugClient() {} - - static - DebugClientPtr createDbgClient() ; - - static - DebugClientPtr createDbgClient( IDebugClient4 *client ); - - static - DebugClientPtr setDbgClientCurrent( DebugClientPtr newDbgClient ); - -public: - - ULONG64 addr64( ULONG64 addr ); - - void breakin(); - - bool compareMemory( ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr = FALSE ); - - void detachProcess(); - - DbgOut dout() { - return DbgOut( m_client ); - } - - DbgIn din() { - return DbgIn( m_client ); - } - - std::string dbgCommand( const std::wstring &command ); - - void startProcess( const std::wstring &processName ); - - void attachProcess( ULONG processId ); - - void attachKernel( const std::wstring ¶m ); - - Disasm disasm( ULONG offset = 0 ) { - return Disasm( m_client, offset ); - } - - void dprint( const std::wstring &str, bool dml = false ); - - void dprintln( const std::wstring &str, bool dml = false ); - - void eprint( const std::wstring &str ); - - void eprintln( const std::wstring &str ); - - ULONG64 evaluate( const std::wstring &expression ); - - std::string findSymbol( ULONG64 offset ); - - ULONG64 getCurrentProcess(); - - python::list getCurrentStack(); - - python::tuple getDebuggeeType(); - - ULONG64 getImplicitThread(); - - ULONG getExecutionStatus(); - - ULONG64 getOffset( const std::wstring symbolname ); - - std::string getPdbFile( ULONG64 moduleBase ); - - std::string getProcessorMode(); - - std::string getProcessorType(); - - std::string dbgSymPath(); - - python::tuple getSourceLine( ULONG64 offset = 0); - - python::list getThreadList(); - - template - void changeDebuggerStatus(); - - bool is64bitSystem(); - - bool isKernelDebugging(); - - bool isDumpAnalyzing(); - - bool isVaValid( ULONG64 addr ); - - void loadDump( const std::wstring &fileName ); - - ModulePtr loadModuleByName( const std::string &moduleName ) { - return ModulePtr( new Module( m_client, m_symSymbols, moduleName ) ); - } - - ModulePtr loadModuleByOffset( ULONG64 offset ) { - return ModulePtr( new Module( m_client, m_symSymbols, offset ) ); - } - - DbgExtensionPtr loadExtension( const std::wstring &extPath ) { - return DbgExtensionPtr( new DbgExtension( m_client, extPath ) ); - } - - python::list loadBytes( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); - - python::list loadWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); - - python::list loadDWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); - - python::list loadQWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); - - python::list loadSignBytes( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); - - python::list loadSignWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); - - python::list loadSignDWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); - - python::list loadSignQWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); - - std::string loadChars( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); - - std::wstring loadWChars( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); - - std::string loadCStr( ULONG64 offset ); - - std::wstring loadWStr( ULONG64 offset ); - - std::string loadAnsiStr( ULONG64 address ); - - std::wstring loadUnicodeStr( ULONG64 address ); - - python::list loadPtrList( ULONG64 address ); - - python::list loadPtrArray( ULONG64 address, ULONG number ); - - ULONG64 loadMSR( ULONG msr ); - - ULONG ptrSize(); - - ULONG64 ptrByte( ULONG64 offset ); - - ULONG64 ptrWord( ULONG64 offset ); - - ULONG64 ptrDWord( ULONG64 offset ); - - ULONG64 ptrQWord( ULONG64 offset ); - - ULONG64 ptrMWord( ULONG64 offset ); - - LONG64 ptrSignByte( ULONG64 offset ); - - LONG64 ptrSignWord( ULONG64 offset ); - - LONG64 ptrSignDWord( ULONG64 offset ); - - LONG64 ptrSignQWord( ULONG64 offset ); - - LONG64 ptrSignMWord( ULONG64 offset ); - - ULONG64 ptrPtr( ULONG64 offset ); - - void setMSR( ULONG msr, ULONG64 value); - - CpuReg getRegByName( const std::string ®Name ); - - CpuReg getRegByIndex( ULONG index ); - - void setCurrentProcess( ULONG64 addr ); - - void setExecutionStatus( ULONG status ); - - void setImplicitThread( ULONG64 threadAddr ); - - void setProcessorMode( const std::wstring &mode ); - - void terminateProcess(); - - void waitForEvent(); - - ULONG getNumberProcessors() { - return getDbgControl(GetNumberProcessors); - } - - ULONG getPageSize() { - return getDbgControl(GetPageSize); - } - - ContextPtr getThreadContext() { - return ContextPtr( new ThreadContext(m_client) ); - } - ContextPtr getThreadWow64Context() { - return ThreadContext::getWow64Context(m_client); - } - - python::dict getLocals( - ContextPtr ctx = ContextPtr( reinterpret_cast(0) ) - ); -public: - - CComPtr& - client() { - return m_client; - } - - CComPtr& - client5() { - return m_client5; - } - - CComPtr& - control() { - return m_control; - } - - CComPtr< IDebugDataSpaces4>& - dataSpace() { - return m_dataSpaces; - } - - PyThreadStateSaver& - getThreadState() { - return m_pyThreadState; - } - - void addSyntheticSymbol( - ULONG64 addr, - ULONG size, - const std::string &symName - ) - { - return m_symSymbols->add(addr, size, symName); - } - - void delAllSyntheticSymbols() - { - return m_symSymbols->clear(); - } - - ULONG delSyntheticSymbol( - ULONG64 addr - ) - { - return m_symSymbols->remove(addr); - } - - ULONG delSyntheticSymbolsMask( - const std::string &moduleName, - const std::string &symName - ) - { - return m_symSymbols->removeByMask(moduleName, symName); - } - - SynSymbolsPtr getSynSymbols() { - return m_symSymbols; - } - - // breakpoints management - BPOINT_ID setSoftwareBp(ULONG64 addr, BpCallback &callback = BpCallback()); - BPOINT_ID setHardwareBp(ULONG64 addr, ULONG size, ULONG accessType, BpCallback &callback = BpCallback()); - - python::list getAllBp(); - - void removeBp(BPOINT_ID Id); - void removeAllBp(); - - void splitSymName( const std::string &fullName, std::string &moduleName, std::string &symbolName ); - - TypeInfoPtr getTypeInfoByName( const std::string &typeName ); - - TypedVarPtr getTypedVarByName( const std::string &varName ); - - TypedVarPtr getTypedVarByTypeName( const std::string &typeName, ULONG64 addr ); - - TypedVarPtr getTypedVarByTypeInfo( const TypeInfoPtr &typeInfo, ULONG64 addr ) { - return TypedVar::getTypedVar( m_client, typeInfo, VarDataMemory::factory(m_dataSpaces, addr) ); - } - - TypedVarPtr containingRecordByName( ULONG64 addr, const std::string &typeName, const std::string &fieldName ); - - TypedVarPtr containingRecordByType( ULONG64 addr, const TypeInfoPtr &typeInfo, const std::string &fieldName ); - - - python::list getTypedVarListByTypeName( ULONG64 listHeadAddres, const std::string &typeName, const std::string &listEntryName ); - - python::list getTypedVarListByType( ULONG64 listHeadAddres, const TypeInfoPtr &typeInfo, const std::string &listEntryName ); - - python::list getTypedVarArrayByTypeName( ULONG64 addr, const std::string &typeName, ULONG number ); - - python::list getTypedVarArrayByType( ULONG64 addr, const TypeInfoPtr &typeInfo, ULONG number ); - - ULONG64 getSymbolSize( const std::string &symName ); - - -private: - HRESULT safeWaitForEvent(ULONG timeout = INFINITE, ULONG flags = DEBUG_WAIT_DEFAULT); - - template - python::list - loadArray( ULONG64 offset, ULONG count, bool phyAddr ); - - BpCallbackMap m_bpCallbacks; - - SynSymbolsPtr m_symSymbols; // DebugClient is creator - InternalDbgEventHandler m_internalDbgEventHandler; - - DebugClient( IDebugClient4 *client ); - - PyThreadStateSaver m_pyThreadState; -}; - -///////////////////////////////////////////////////////////////////////////////// - -extern DebugClientPtr g_dbgClient; - -void loadDump( const std::wstring &fileName ); - -void startProcess( const std::wstring &processName ); - -void attachProcess( ULONG processId ); - -void attachKernel( const std::wstring ¶m ); - -void detachProcess(); - -std::string findSymbol( ULONG64 offset ); - -python::tuple getDebuggeeType(); - -ULONG getExecutionStatus(); - -ULONG64 getOffset( const std::wstring symbolname ); - -std::string getPdbFile( ULONG64 moduleBase ); - -std::string dbgSymPath(); - -bool is64bitSystem(); - -bool isKernelDebugging(); - -bool isDumpAnalyzing(); - -ULONG ptrSize(); - -void setExecutionStatus( ULONG status ); - -void terminateProcess(); - -void waitForEvent(); - -TypedVarPtr containingRecordByName( ULONG64 addr, const std::string &typeName, const std::string &fieldName ); - -TypedVarPtr containingRecordByType( ULONG64 addr, const TypeInfoPtr &typeInfo, const std::string &fieldName ); - -python::list getTypedVarListByTypeName( ULONG64 listHeadAddres, const std::string &typeName, const std::string &listEntryName ); - -python::list getTypedVarListByType( ULONG64 listHeadAddres, const TypeInfoPtr &typeInfo, const std::string &listEntryName ); - -python::list getTypedVarArrayByTypeName( ULONG64 addr, const std::string &typeName, ULONG number ); - -python::list getTypedVarArrayByType( ULONG64 addr, const TypeInfoPtr &typeInfo, ULONG number ); - -ULONG64 getSymbolSize( const std::string &symName ); - -///////////////////////////////////////////////////////////////////////////////// -// Synthetic symbols global finctions: - -inline void addSyntheticSymbol( - ULONG64 addr, - ULONG size, - const std::string &symName -) -{ - return g_dbgClient->addSyntheticSymbol(addr, size, symName); -} - -inline void delAllSyntheticSymbols() -{ - return g_dbgClient->delAllSyntheticSymbols(); -} - -inline ULONG delSyntheticSymbol( - ULONG64 addr -) -{ - return g_dbgClient->delSyntheticSymbol(addr); -} - -inline ULONG delSyntheticSymbolsMask( - const std::string &moduleName, - const std::string &symName -) -{ - return g_dbgClient->delSyntheticSymbolsMask(moduleName, symName); -} - -///////////////////////////////////////////////////////////////////////////////// - -inline ULONG getNumberProcessors() { - return g_dbgClient->getNumberProcessors(); -} - -inline ULONG getPageSize() { - return g_dbgClient->getPageSize(); -} - -inline ContextPtr getThreadContext() { - return g_dbgClient->getThreadContext(); -} - -inline ContextPtr getThreadWow64Context() { - return g_dbgClient->getThreadWow64Context(); -} - -inline python::dict getLocals( - ContextPtr ctx = ContextPtr() -) -{ - return g_dbgClient->getLocals(ctx); -} - -///////////////////////////////////////////////////////////////////////////////// - -template -void DebugClient::changeDebuggerStatus() -{ - HRESULT hres; - - hres = m_control->SetExecutionStatus( status ); - - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::SetExecutionStatus failed" ); - - ULONG currentStatus; - - do { - - waitForEvent(); - - hres = m_control->GetExecutionStatus( ¤tStatus ); - - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::GetExecutionStatus failed" ); - - } while( currentStatus != DEBUG_STATUS_BREAK && currentStatus != DEBUG_STATUS_NO_DEBUGGEE ); -} - -template -void changeDebuggerStatus() -{ - g_dbgClient->changeDebuggerStatus(); -} - -inline python::tuple getSourceLine( ULONG64 offset = 0 ) -{ - return g_dbgClient->getSourceLine(offset); -} -///////////////////////////////////////////////////////////////////////////////// - - -}; // namespace pykd - - diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h index 99c9db3..5836e42 100644 --- a/pykd/dbgengine.h +++ b/pykd/dbgengine.h @@ -30,6 +30,7 @@ ULONG getModuleCheckSum( ULONG64 baseOffset ); ULONG getRegIndexByName( const std::string ®Name ); std::string getRegNameByIndex( ULONG index ); BaseTypeVariant getRegVariantValue( ULONG index ); +ULONG64 getRegInstructionPointer(); // это нужно сделать по-другому! std::string getSymbolByOffset( ULONG64 offset ); diff --git a/pykd/dbgobj.h b/pykd/dbgobj.h deleted file mode 100644 index 9b3211f..0000000 --- a/pykd/dbgobj.h +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once - -#include "dbgexcept.h" -#include "synsymbol.h" - -namespace pykd { - -/////////////////////////////////////////////////////////////////////////////////// - -class DbgObject { - -protected: - - DbgObject( IDebugClient4 *client ) - { - - m_client = client; - - HRESULT hres; - hres = client->QueryInterface( __uuidof(IDebugClient5), (void **)&m_client5 ); - if ( FAILED( hres ) ) - throw DbgException("QueryInterface IDebugClient5 failed"); - - hres = client->QueryInterface( __uuidof(IDebugControl4), (void**)&m_control ); - if ( FAILED( hres ) ) - throw DbgException("QueryInterface IDebugControl4 failed"); - - hres = client->QueryInterface( __uuidof(IDebugSymbols3), (void**)&m_symbols ); - if ( FAILED( hres ) ) - throw DbgException("QueryInterface IDebugSymbols3 failed"); - - hres = client->QueryInterface( __uuidof(IDebugAdvanced2), (void**)&m_advanced ); - if ( FAILED( hres ) ) - throw DbgException("QueryInterface IDebugAdvanced2 failed"); - - hres = client->QueryInterface( __uuidof(IDebugDataSpaces4), (void**)&m_dataSpaces ); - if ( FAILED( hres ) ) - throw DbgException("QueryInterface IDebugDataSpaces failed"); - - hres = client->QueryInterface( __uuidof(IDebugRegisters2), (void**)&m_registers ); - if ( FAILED( hres ) ) - throw DbgException("QueryInterface IDebugDataSpaces failed"); - - hres = client->QueryInterface( __uuidof(IDebugSystemObjects), (void**)&m_system ); - if ( FAILED( hres ) ) - throw DbgException("QueryInterface IDebugSystem2 failed"); - } - - virtual ~DbgObject() {}; - - CComPtr m_client5; - CComPtr m_client; - CComPtr m_control; - CComPtr m_symbols; - CComPtr m_advanced; - CComPtr m_dataSpaces; - CComPtr m_registers; - CComPtr m_system; -}; - - - -/////////////////////////////////////////////////////////////////////////////////// - -}; // end of namespace pykd \ No newline at end of file diff --git a/pykd/disasm.cpp b/pykd/disasm.cpp index a35c0f3..280e632 100644 --- a/pykd/disasm.cpp +++ b/pykd/disasm.cpp @@ -1,47 +1,20 @@ #include "stdafx.h" +#include "dbgengine.h" +#include "disasmengine.h" #include "disasm.h" #include "dbgexcept.h" -#include "dbgmem.h" -#include "dbgclient.h" + namespace pykd { ///////////////////////////////////////////////////////////////////////////////// -Disasm::Disasm( IDebugClient4 *client, ULONG64 offset ) : - DbgObject( client ) +Disasm::Disasm( ULONG64 offset ) { - HRESULT hres; - m_beginOffset = addr64(offset); if ( m_beginOffset == 0 ) - { - hres = m_registers->GetInstructionOffset( &m_beginOffset ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugRegisters::GetInstructionOffset failed" ); - } - - m_currentOffset = m_beginOffset; - - doDisasm(); -} - -///////////////////////////////////////////////////////////////////////////////// - -Disasm::Disasm( ULONG64 offset ) : - DbgObject( g_dbgClient->client() ) -{ - HRESULT hres; - - m_beginOffset = addr64(offset); - - if ( m_beginOffset == 0 ) - { - hres = m_registers->GetInstructionOffset( &m_beginOffset ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugRegisters::GetInstructionOffset failed" ); - } + m_beginOffset = getRegInstructionPointer(); m_currentOffset = m_beginOffset; @@ -52,30 +25,11 @@ Disasm::Disasm( ULONG64 offset ) : void Disasm::doDisasm() { - HRESULT hres; - char buffer[0x100]; - ULONG disasmSize = 0; ULONG64 endOffset = 0; - - hres = - m_control->Disassemble( - m_currentOffset, - DEBUG_DISASM_EFFECTIVE_ADDRESS, - buffer, - sizeof(buffer), - &disasmSize, - &endOffset ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::Disassemble failed" ); - - hres = m_control->GetDisassembleEffectiveOffset( &m_ea ); - if ( FAILED( hres ) ) - m_ea = 0; + disasmDisassembly( m_currentOffset, m_disasm, endOffset ); m_length = (ULONG)(endOffset - m_currentOffset); - - m_disasm = std::string( buffer, disasmSize - 2); } ///////////////////////////////////////////////////////////////////////////////// @@ -83,17 +37,13 @@ void Disasm::doDisasm() std::string Disasm::assembly( const std::string &instr ) { - HRESULT hres; - ULONG64 endOffset = 0; - hres = m_control->Assemble( m_currentOffset, instr.c_str(), &endOffset ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::Assemble failed" ); + disasmAssemblay( m_currentOffset, instr, endOffset ); m_currentOffset = endOffset; doDisasm(); - + return m_disasm; } diff --git a/pykd/disasm.h b/pykd/disasm.h index 793ad68..2c9fdb3 100644 --- a/pykd/disasm.h +++ b/pykd/disasm.h @@ -1,17 +1,13 @@ #pragma once -#include "dbgobj.h" - namespace pykd { ///////////////////////////////////////////////////////////////////////////////// -class Disasm : private DbgObject { +class Disasm { public: - Disasm( IDebugClient4 *client, ULONG64 offset = 0 ); - Disasm( ULONG64 offset = 0); std::string disassemble() { diff --git a/pykd/disasmengine.h b/pykd/disasmengine.h new file mode 100644 index 0000000..2728b7c --- /dev/null +++ b/pykd/disasmengine.h @@ -0,0 +1,8 @@ +#pragma once + +namespace pykd { + +void disasmAssemblay( ULONG64 offset, const std::string &instruction, ULONG64 &nextOffset ); +void disasmDisassembly( ULONG64 offset, std::string &instruction, ULONG64 &nextOffset ); + +} // end pykd namespace \ No newline at end of file diff --git a/pykd/pykd_2008.vcproj b/pykd/pykd_2008.vcproj index 8417e57..dcff298 100644 --- a/pykd/pykd_2008.vcproj +++ b/pykd/pykd_2008.vcproj @@ -365,6 +365,10 @@ RelativePath=".\dbgmem.cpp" > + + @@ -451,6 +455,14 @@ RelativePath=".\dbgmem.h" > + + + + @@ -505,6 +517,10 @@ + + diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index 5c1d41a..11ecdba 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -16,6 +16,7 @@ #include "typeinfo.h" #include "typedvar.h" #include "cpureg.h" +#include "disasm.h" using namespace pykd; @@ -288,12 +289,24 @@ BOOST_PYTHON_MODULE( pykd ) .def("__getitem__", &TypedVar::getElementByIndex ) .def("__getitem__", &TypedVar::getElementByIndexPtr ); - python::class_ >( "cpuReg", "CPU regsiter class", boost::python::no_init ) .def( "name", &CpuReg::name, "The name of the regsiter" ) .def( "index", &CpuReg::index, "The index of thr register" ); + python::class_("disasm", "Class disassemble a processor instructions" ) + .def( python::init<>( "constructor" ) ) + .def( python::init( boost::python::args("offset"), "constructor" ) ) + .def( "disasm", &Disasm::disassemble, "Disassemble next instruction" ) + .def( "disasm", &Disasm::jump, "Disassemble from the specified offset" ) + .def( "asm", &Disasm::assembly, "Insert assemblied instuction to current offset" ) + .def( "begin", &Disasm::begin, "Return begin offset" ) + .def( "current", &Disasm::current, "Return current offset" ) + .def( "length", &Disasm::length, "Return current instruction length" ) + .def( "instruction", &Disasm::instruction, "Returm current disassembled instruction" ) + .def( "ea", &Disasm::ea, "Return effective address for last disassembled instruction or 0" ) + .def( "reset", &Disasm::reset, "Reset current offset to begin" ); + // wrapper for standart python exceptions python::register_exception_translator( &PyException::exceptionTranslate ); diff --git a/pykd/win/dbgasm.cpp b/pykd/win/dbgasm.cpp new file mode 100644 index 0000000..6410141 --- /dev/null +++ b/pykd/win/dbgasm.cpp @@ -0,0 +1,48 @@ +#include "stdafx.h" + +#include "win/dbgeng.h" + +namespace pykd { + +////////////////////////////////////////////////////////////////////////////// + +void disasmAssemblay( ULONG64 offset, const std::string &instruction, ULONG64 &nextOffset ) +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres; + + hres = g_dbgEng->control->Assemble( offset, instruction.c_str(), &nextOffset ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::Assemble failed" ); +} + +/////////////////////////////////////////////////////////////////////////////// + +void disasmDisassembly( ULONG64 offset, std::string &instruction, ULONG64 &nextOffset ) +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres; + char buffer[0x100]; + ULONG disasmSize = 0; + ULONG64 endOffset = 0; + + hres = + g_dbgEng->control->Disassemble( + offset, + DEBUG_DISASM_EFFECTIVE_ADDRESS, + buffer, + sizeof(buffer), + &disasmSize, + &nextOffset ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::Disassemble failed" ); + + instruction = std::string( buffer, disasmSize - 2); +} + +/////////////////////////////////////////////////////////////////////////////// + +} // end pykd namespace diff --git a/pykd/win/dbgeng.cpp b/pykd/win/dbgeng.cpp index 29640d2..2d8c5f5 100644 --- a/pykd/win/dbgeng.cpp +++ b/pykd/win/dbgeng.cpp @@ -451,7 +451,7 @@ BaseTypeVariant getRegVariantValue( ULONG index ) { PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); - HRESULT hres; + HRESULT hres; DEBUG_VALUE debugValue; hres = g_dbgEng->registers->GetValue( index, &debugValue ); @@ -482,6 +482,22 @@ BaseTypeVariant getRegVariantValue( ULONG index ) /////////////////////////////////////////////////////////////////////////////// +ULONG64 getRegInstructionPointer() +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres; + ULONG64 ip = 0; + + hres = g_dbgEng->registers->GetInstructionOffset( &ip ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugRegisters::GetInstructionOffset failed" ); + + return ip; +} + +/////////////////////////////////////////////////////////////////////////////// + } // end pykd namespace