From c8d99b55658890b2bde2c21e0af14f47c8453a3c Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Mon, 6 Aug 2012 16:14:56 +0000 Subject: [PATCH] [0.2.x] added : typedVar class git-svn-id: https://pykd.svn.codeplex.com/svn@78536 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgengine.h | 8 +- pykd/dbgmem.cpp | 3 +- pykd/dbgmem.h | 2 + pykd/dia/diawrapper.cpp | 7 +- pykd/dia/diawrapper.h | 2 + pykd/module.cpp | 537 +++++++-------------------------------- pykd/module.h | 166 +----------- pykd/pykd_2008.vcproj | 16 ++ pykd/pymod.cpp | 82 ++++-- pykd/symengine.h | 3 +- pykd/typedvar.cpp | 171 ++++++++++--- pykd/typedvar.h | 57 ++--- pykd/typeinfo.h | 4 + pykd/vardata.cpp | 29 +-- pykd/vardata.h | 57 ++--- pykd/win/dbgeng.cpp | 28 ++ test/scripts/pykdtest.py | 5 +- test/scripts/typedvar.py | 8 +- 18 files changed, 449 insertions(+), 736 deletions(-) diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h index bea4307..038c79d 100644 --- a/pykd/dbgengine.h +++ b/pykd/dbgengine.h @@ -1,5 +1,7 @@ #pragma once +#include "dbgmem.h" + namespace pykd { // manage debug target @@ -22,10 +24,8 @@ std::string getModuleSymbolFileName( ULONG64 baseOffset ); ULONG getModuleTimeStamp( ULONG64 baseOffset ); ULONG getModuleCheckSum( ULONG64 baseOffset ); -//manage access to target memory -ULONG64 addr64( ULONG64 offset ); - -void readMemory( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr = FALSE ); +// это нужно сделать по-другому! +std::string getSymbolByOffset( ULONG64 offset ); }; diff --git a/pykd/dbgmem.cpp b/pykd/dbgmem.cpp index b253639..22f13c9 100644 --- a/pykd/dbgmem.cpp +++ b/pykd/dbgmem.cpp @@ -1,11 +1,12 @@ #include "stdafx.h" #include "dbgengine.h" + namespace pykd { ///////////////////////////////////////////////////////////////////////////////////// -bool compareMemory( ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr = FALSE ) +bool compareMemory( ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr ) { bool result = false; diff --git a/pykd/dbgmem.h b/pykd/dbgmem.h index 868bbaf..46c8e76 100644 --- a/pykd/dbgmem.h +++ b/pykd/dbgmem.h @@ -4,6 +4,8 @@ namespace pykd { /////////////////////////////////////////////////////////////////////////////////// +ULONG64 addr64( ULONG64 offset ); +void readMemory( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr = FALSE ); bool isVaValid( ULONG64 addr ); bool compareMemory( ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr = FALSE ); diff --git a/pykd/dia/diawrapper.cpp b/pykd/dia/diawrapper.cpp index 20ea6bf..80e6052 100644 --- a/pykd/dia/diawrapper.cpp +++ b/pykd/dia/diawrapper.cpp @@ -45,7 +45,7 @@ std::string DiaException::makeFullDesc(const std::string &desc, HRESULT hres) //////////////////////////////////////////////////////////////////////////////// -SymbolPtr loadSymbolFile(const std::string &filePath) +SymbolPtr loadSymbolFile(const std::string &filePath, ULONGLONG loadBase ) { HRESULT hres; DiaDataSourcePtr dataSource; @@ -64,6 +64,10 @@ SymbolPtr loadSymbolFile(const std::string &filePath) if ( S_OK != hres ) throw DiaException("Call IDiaDataSource::openSession", hres); + hres = _session->put_loadAddress(loadBase); + if (S_OK != hres) + throw DiaException("Call IDiaSession::put_loadAddress", hres); + DiaSymbolPtr _globalScope; hres = _session->get_globalScope(&_globalScope); if ( S_OK != hres ) @@ -368,7 +372,6 @@ bool DiaSymbol::isVirtualBaseClass() // return !!callSymbol(get_indirectVirtualBaseClass); //} -////////////////////////////////////////////////////////////////////////////// }; // pykd nemaspace end diff --git a/pykd/dia/diawrapper.h b/pykd/dia/diawrapper.h index aaac6a5..210e7f9 100644 --- a/pykd/dia/diawrapper.h +++ b/pykd/dia/diawrapper.h @@ -154,6 +154,8 @@ public: //ULONG getSection(); + void setLoadAddress( ULONGLONG baseAddress ); + public: typedef std::pair ValueNameEntry; diff --git a/pykd/module.cpp b/pykd/module.cpp index 7d51f90..aa81f15 100644 --- a/pykd/module.cpp +++ b/pykd/module.cpp @@ -2,6 +2,7 @@ #include "dbgengine.h" #include "module.h" #include "dbgexcept.h" +#include "vardata.h" namespace pykd { @@ -51,7 +52,7 @@ SymbolPtr& Module::getSymScope() if ( m_symfile.empty() ) break; - m_symScope = loadSymbolFile( m_symfile ); + m_symScope = loadSymbolFile( m_symfile, m_base ); } while( false ); @@ -109,450 +110,106 @@ std::string Module::print() sstr << "Start: " << std::hex << m_base << " End: " << getEnd() << " Size: " << m_size << std::endl; sstr << "Image: " << m_imageName << std::endl; sstr << "Symnol: " << m_symfile << std::endl; - //sstr << "Timestamp: " << m_timeDataStamp << std::endl; - //sstr << "Check Sum: " << m_checkSum << std::endl; + sstr << "Timestamp: " << m_timeDataStamp << std::endl; + sstr << "Check Sum: " << m_checkSum << std::endl; return sstr.str(); } -///////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +TypedVarPtr +Module::getTypedVarByAddr( ULONG64 offset ) +{ + offset = addr64(offset); + + if ( offset < m_base || offset > getEnd() ) + throw DbgException( "address is out of the module space" ); + + std::string symName = getSymbolByOffset( offset ); + + return getTypedVarByName( symName ); +} + +/////////////////////////////////////////////////////////////////////////////// + +TypedVarPtr +Module::getTypedVarByName( const std::string &symName ) +{ + SymbolPtr symVar = getSymScope()->getChildByName( symName ); + + TypeInfoPtr typeInfo = TypeInfo::getTypeInfo( symVar->getType() ); + + if ( LocIsConstant != symVar->getLocType() ) + { + ULONG64 offset = getSymbol( symName ); + return TypedVar::getTypedVar(typeInfo, VarDataMemory::factory(offset) ); + } + + return TypedVar::getTypedVar( typeInfo, VarDataConst::factory(symVar) ); + + + + + //HRESULT hres; + + //pyDia::SymbolPtr symVar = getSymScope()->getChildByName( symName ); + + //std::string fullName = m_name; + //fullName += '!'; + //fullName += symName; + + //ULONG64 offset; + + //hres = m_symbols->GetOffsetByName( fullName.c_str(), &offset ); + + //TypeInfoPtr typeInfo = TypeInfo::getTypeInfo( symVar->getType() ); + + //if ( FAILED( hres ) ) + //{ + // if ( LocIsConstant == symVar->getLocType() ) + // return TypedVar::getTypedVar( m_client, typeInfo, VarDataConst::factory(m_control, symVar) ); + // throw DbgException("IDebugSymbols::GetOffsetByName failed" ); + //} + + //return TypedVar::getTypedVar( m_client, typeInfo, VarDataMemory::factory(m_dataSpaces, offset) ); +} + +/////////////////////////////////////////////////////////////////////////////// + +TypedVarPtr +Module::getTypedVarByTypeName( const std::string &typeName, ULONG64 offset ) +{ + TypeInfoPtr typeInfo = getTypeByName( typeName ); + + return TypedVar::getTypedVar(typeInfo, VarDataMemory::factory(offset) ); +} + +/////////////////////////////////////////////////////////////////////////////// + +TypedVarPtr Module::containingRecordByName( ULONG64 offset, const std::string &typeName, const std::string &fieldName ) +{ + TypeInfoPtr typeInfo = getTypeByName( typeName ); + + return containingRecordByType( offset, typeInfo, fieldName ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +python::list Module::getTypedVarArrayByTypeName( ULONG64 offset, const std::string &typeName, ULONG number ) +{ + return getTypedVarArrayByType( offset, getTypeByName( typeName ), number ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +python::list Module::getTypedVarListByTypeName( ULONG64 listHeadAddress, const std::string &typeName, const std::string &listEntryName ) +{ + return getTypedVarListByType( listHeadAddress, getTypeByName( typeName ), listEntryName ); +} + +/////////////////////////////////////////////////////////////////////////////////// }; // end of namespace pykd - - - - - - - - - - - - - - - -//#include "module.h" -//#include "dbgclient.h" -//#include "dbgmem.h" -// -//namespace pykd { -// -///////////////////////////////////////////////////////////////////////////////////// -// -//ModulePtr Module::loadModuleByName( const std::string &moduleName ) { -// return g_dbgClient->loadModuleByName( moduleName ); -//}; -// -//ModulePtr Module::loadModuleByOffset( ULONG64 offset ) { -// return g_dbgClient->loadModuleByOffset( offset ); -//} -// -///////////////////////////////////////////////////////////////////////////////////// -// -//Module::Module( IDebugClient4 *client, SynSymbolsPtr synSymbols, const std::string& moduleName ) -// : DbgObject( client ) -// , m_synSymbols(synSymbols) -//{ -// HRESULT hres; -// -// m_name = moduleName; -// -// hres = m_symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &m_base ); -// if ( FAILED( hres ) ) -// throw DbgException( "IDebugSymbol::GetModuleByModuleName failed" ); -// -// DEBUG_MODULE_PARAMETERS moduleParam = { 0 }; -// hres = m_symbols->GetModuleParameters( 1, &m_base, 0, &moduleParam ); -// if ( FAILED( hres ) ) -// throw DbgException( "IDebugSymbol::GetModuleParameters failed" ); -// -// m_size = moduleParam.Size; -// m_timeDataStamp = moduleParam.TimeDateStamp; -// m_checkSum = moduleParam.Checksum; -// -// char imageName[0x100]; -// -// hres = m_symbols->GetModuleNameString( -// DEBUG_MODNAME_IMAGE, -// DEBUG_ANY_ID, -// m_base, -// imageName, -// sizeof( imageName ), -// NULL ); -// -// if ( FAILED( hres ) ) -// throw DbgException( "IDebugSymbol::GetModuleNameString failed" ); -// -// m_imageName = std::string( imageName ); -//} -// -///////////////////////////////////////////////////////////////////////////////////// -// -//Module::Module( IDebugClient4 *client, SynSymbolsPtr synSymbols, ULONG64 offset ) -// : DbgObject( client ) -// , m_synSymbols(synSymbols) -//{ -// HRESULT hres; -// -// offset = addr64( offset ); -// -// ULONG moduleIndex; -// hres = m_symbols->GetModuleByOffset( offset, 0, &moduleIndex, &m_base ); -// if ( FAILED( hres ) ) -// throw DbgException( "IDebugSymbol::GetModuleByOffset failed" ); -// -// char moduleName[0x100]; -// -// hres = m_symbols->GetModuleNameString( -// DEBUG_MODNAME_MODULE, -// moduleIndex, -// 0, -// moduleName, -// sizeof( moduleName ), -// NULL ); -// -// if ( FAILED( hres ) ) -// throw DbgException( "IDebugSymbol::GetModuleNameString failed" ); -// -// m_name = std::string( moduleName ); -// -// char imageName[0x100]; -// -// hres = m_symbols->GetModuleNameString( -// DEBUG_MODNAME_IMAGE, -// DEBUG_ANY_ID, -// m_base, -// imageName, -// sizeof( imageName ), -// NULL ); -// -// if ( FAILED( hres ) ) -// throw DbgException( "IDebugSymbol::GetModuleNameString failed" ); -// -// m_imageName = std::string( imageName ); -// -// DEBUG_MODULE_PARAMETERS moduleParam = { 0 }; -// hres = m_symbols->GetModuleParameters( 1, &m_base, 0, &moduleParam ); -// if ( FAILED( hres ) ) -// throw DbgException( "IDebugSymbol::GetModuleParameters failed" ); -// -// m_size = moduleParam.Size; -// m_timeDataStamp = moduleParam.TimeDateStamp; -// m_checkSum = moduleParam.Checksum; -//} -// -///////////////////////////////////////////////////////////////////////////////////// -// -//std::string -//Module::getPdbName() -//{ -// HRESULT hres; -// -// IMAGEHLP_MODULEW64 moduleInfo = {}; -// -// hres = m_advanced->GetSymbolInformation( -// DEBUG_SYMINFO_IMAGEHLP_MODULEW64, -// m_base, -// 0, -// &moduleInfo, -// sizeof(moduleInfo), -// NULL, -// NULL, -// 0, -// NULL ); -// -// if ( FAILED( hres ) ) -// throw DbgException( "IDebugAdvanced2::GetSymbolInformation failed" ); -// -// if (!*moduleInfo.LoadedPdbName) -// { -// reloadSymbolsImpl(); -// -// hres = m_advanced->GetSymbolInformation( -// DEBUG_SYMINFO_IMAGEHLP_MODULEW64, -// m_base, -// 0, -// &moduleInfo, -// sizeof(moduleInfo), -// NULL, -// NULL, -// 0, -// NULL ); -// -// if ( FAILED( hres ) ) -// throw DbgException( "IDebugAdvanced2::GetSymbolInformation failed" ); -// } -// -// char pdbName[ 256 ]; -// WideCharToMultiByte( CP_ACP, 0, moduleInfo.LoadedPdbName, 256, pdbName, 256, NULL, NULL ); -// -// return std::string( pdbName ); -//} -// -///////////////////////////////////////////////////////////////////////////////////// -// -//void -//Module::reloadSymbolsImpl() -//{ -// HRESULT hres; -// -// std::string param = "/f "; -// param += m_imageName; -// -// hres = m_symbols->Reload( param.c_str() ); -// if ( FAILED( hres ) ) -// throw DbgException("IDebugSymbols::Reload failed" ); -//} -// -// -///////////////////////////////////////////////////////////////////////////////////// -// -//void -//Module::reloadSymbols() -//{ -// reloadSymbolsImpl(); -// -// m_dia.reset(); -// m_dia = pyDia::GlobalScope::loadPdb( getPdbName() ); -//} -// -///////////////////////////////////////////////////////////////////////////////////// -// -//TypedVarPtr -//Module::getTypedVarByTypeName( const std::string &typeName, ULONG64 addr ) -//{ -// return TypedVar::getTypedVar( m_client, getTypeByName(typeName), VarDataMemory::factory(m_dataSpaces, addr) ); -//} -// -///////////////////////////////////////////////////////////////////////////////////// -// -//TypedVarPtr -//Module::getTypedVarByType( const TypeInfoPtr &typeInfo, ULONG64 addr ) -//{ -// return TypedVar::getTypedVar( m_client, typeInfo, VarDataMemory::factory(m_dataSpaces, addr) ); -//} -// -///////////////////////////////////////////////////////////////////////////////////// -// -//ULONG64 -//Module::getSymbolSize( const std::string &symName ) -//{ -// try { -// -// pyDia::SymbolPtr symVar = getDia()->getChildByName( symName ); -// -// if ( symVar->getSymTag() == SymTagData ) -// return symVar->getSize(); -// -// } catch( const SymbolException& ) -// { -// } -// -// return getTypeByName(symName)->getSize(); -//} -// -///////////////////////////////////////////////////////////////////////////////////// -// -//TypedVarPtr -//Module::getTypedVarByName( const std::string &symName ) -//{ -// HRESULT hres; -// -// pyDia::SymbolPtr symVar = getDia()->getChildByName( symName ); -// -// std::string fullName = m_name; -// fullName += '!'; -// fullName += symName; -// -// ULONG64 offset; -// -// hres = m_symbols->GetOffsetByName( fullName.c_str(), &offset ); -// -// TypeInfoPtr typeInfo = TypeInfo::getTypeInfo( symVar->getType() ); -// -// if ( FAILED( hres ) ) -// { -// if ( LocIsConstant == symVar->getLocType() ) -// return TypedVar::getTypedVar( m_client, typeInfo, VarDataConst::factory(m_control, symVar) ); -// throw DbgException("IDebugSymbols::GetOffsetByName failed" ); -// } -// -// return TypedVar::getTypedVar( m_client, typeInfo, VarDataMemory::factory(m_dataSpaces, offset) ); -//} -// -///////////////////////////////////////////////////////////////////////////////////// -// -//TypedVarPtr -//Module::getTypedVarByAddr( ULONG64 addr ) -//{ -// HRESULT hres; -// -// addr = addr64(addr); -// -// if ( addr < m_base || addr > getEnd() ) -// throw DbgException( "address is out of the module space" ); -// -// char nameBuf[0x100]; -// -// hres = -// m_symbols->GetNameByOffset( -// addr, -// nameBuf, -// sizeof(nameBuf), -// NULL, -// NULL ); -// -// std::string fullName( nameBuf ); -// -// size_t symPos = fullName.find ( '!' ) + 1; -// -// std::string symbolName; -// symbolName.assign( fullName, symPos, fullName.length() - symPos ); -// -// if ( FAILED(hres) ) -// throw DbgException( "failed IDebugSymbols::GetNameByOffset" ); -// -// return getTypedVarByName( symbolName ); -// -// //LONG displacement; -// //pyDia::SymbolPtr diaSym = -// // getDia()->findByRvaImpl((ULONG)(addr - m_base), SymTagData, displacement); -// //if (displacement) -// // throw DbgException( "not exactly match by RVA" ); -// -// //return TypedVar::getTypedVar( m_client, TypeInfo::getTypeInfo( diaSym->getType() ), addr ); -//} -// -///////////////////////////////////////////////////////////////////////////////////// -// -//ULONG Module::getRvaByName(const std::string &symName) -//{ -// HRESULT hres; -// ULONG64 offset; -// -// hres = m_symbols->GetOffsetByName( symName.c_str(), &offset ); -// if ( SUCCEEDED(hres) ) -// return (ULONG)(offset - m_base); -// -// return (ULONG)m_synSymbols->getRvaByName(m_timeDataStamp, m_checkSum, symName); -// -// //try { -// // pyDia::SymbolPtr sym = getDia()->getChildByName( symName ); -// // return sym->getRva(); -// //} -// //catch (const pyDia::Exception &) { -// //} -// //return (ULONG)m_synSymbols->getRvaByName(m_timeDataStamp, m_checkSumm, symName); -//} -// -///////////////////////////////////////////////////////////////////////////////////// -// -//TypedVarPtr Module::containingRecordByName( ULONG64 address, const std::string &typeName, const std::string &fieldName ) -//{ -// address = addr64(address); -// -// TypeInfoPtr typeInfo = getTypeByName( typeName ); -// -// VarDataPtr varData = -// VarDataMemory::factory( -// m_dataSpaces, -// address - typeInfo->getFieldOffsetByNameRecirsive( fieldName ) -// ); -// -// return TypedVar::getTypedVar( m_client, typeInfo, varData ); -//} -// -///////////////////////////////////////////////////////////////////////////////////// -// -//TypedVarPtr Module::containingRecordByType( ULONG64 address, const TypeInfoPtr &typeInfo, const std::string &fieldName ) -//{ -// address = addr64(address); -// -// VarDataPtr varData = -// VarDataMemory::factory( -// m_dataSpaces, -// address - typeInfo->getFieldOffsetByNameRecirsive( fieldName ) -// ); -// -// return TypedVar::getTypedVar( m_client, typeInfo, varData ); -//} -// -// -///////////////////////////////////////////////////////////////////////////////////// -// -//python::list Module::getTypedVarListByTypeName( ULONG64 listHeadAddress, const std::string &typeName, const std::string &listEntryName ) -//{ -// return getTypedVarListByType( listHeadAddress, getTypeByName( typeName ), listEntryName ); -//} -// -///////////////////////////////////////////////////////////////////////////////////// -// -//python::list Module::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, m_dataSpaces ); addr64(entryAddress) != listHeadAddress && entryAddress != NULL; entryAddress = ptrPtr( entryAddress + typeInfo->getFieldOffsetByNameRecirsive(listEntryName) ) ) -// lst.append( getTypedVarByType( typeInfo, entryAddress ) ); -// } -// else -// { -// for( entryAddress = ptrPtr( listHeadAddress, m_dataSpaces ); addr64(entryAddress) != listHeadAddress && entryAddress != NULL; entryAddress = ptrPtr( entryAddress ) ) -// lst.append( containingRecordByType( entryAddress, typeInfo, listEntryName ) ); -// } -// -// return lst; -//} -// -///////////////////////////////////////////////////////////////////////////////////// -// -//python::list Module::getTypedVarArrayByTypeName( ULONG64 addr, const std::string &typeName, ULONG number ) -//{ -// return getTypedVarArrayByType( addr, getTypeByName( typeName ), number ); -//} -// -///////////////////////////////////////////////////////////////////////////////////// -// -//python::list Module::getTypedVarArrayByType( ULONG64 address, const TypeInfoPtr &typeInfo, ULONG number ) -//{ -// address = addr64(address); -// -// python::list lst; -// -// for( ULONG i = 0; i < number; ++i ) -// lst.append( getTypedVarByType( typeInfo, address + i * typeInfo->getSize() ) ); -// -// return lst; -//} -// -///////////////////////////////////////////////////////////////////////////////////// -// -//std::string Module::print() -//{ -// std::stringstream sstr; -// -// sstr << "Module: " << m_name << std::endl; -// sstr << "Start: " << std::hex << m_base << " End: " << getEnd() << " Size: " << m_size << std::endl; -// sstr << "Image: " << m_imageName << std::endl; -// sstr << "Pdb: " << getPdbName() << std::endl; -// sstr << "Timestamp: " << m_timeDataStamp << std::endl; -// sstr << "Check Sum: " << m_checkSum << std::endl; -// -// return sstr.str(); -//} -// -///////////////////////////////////////////////////////////////////////////////////// -// -//}; // end of namespace pykd -// diff --git a/pykd/module.h b/pykd/module.h index c7d91d0..8cf5167 100644 --- a/pykd/module.h +++ b/pykd/module.h @@ -3,6 +3,7 @@ #include "intbase.h" #include "symengine.h" #include "typeinfo.h" +#include "typedvar.h" namespace pykd { @@ -78,6 +79,18 @@ public: return TypeInfo::getTypeInfo( boost::static_pointer_cast( getSymScope() ), typeName); } + TypedVarPtr getTypedVarByAddr( ULONG64 addr ); + + TypedVarPtr getTypedVarByName( const std::string &symName ); + + TypedVarPtr getTypedVarByTypeName( const std::string &typeName, ULONG64 addr ); + + python::list getTypedVarListByTypeName( ULONG64 listHeadAddres, const std::string &typeName, const std::string &listEntryName ); + + python::list getTypedVarArrayByTypeName( ULONG64 offset, const std::string &typeName, ULONG number ); + + TypedVarPtr containingRecordByName( ULONG64 offset, const std::string &typeName, const std::string &fieldName ); + ULONG64 getSymbolSize( const std::string &symName ); std::string print(); @@ -107,156 +120,3 @@ private: }; // end pykd namespace - - - - - -//#include -// -//#include "dbgobj.h" -//#include "diawrapper.h" -//#include "typeinfo.h" -//#include "typedvar.h" -//#include "synsymbol.h" -// -//namespace pykd { -// -///////////////////////////////////////////////////////////////////////////////////// -// -//class Module; -//typedef boost::shared_ptr ModulePtr; -// -///////////////////////////////////////////////////////////////////////////////////// -// -//class Module : public intBase, private DbgObject { -// -//public: -// -// static -// ModulePtr loadModuleByName( const std::string &name ); -// -// static -// ModulePtr loadModuleByOffset( ULONG64 offset ); -// -//public: -// -// Module( IDebugClient4 *client, SynSymbolsPtr synSymbols, const std::string& moduleName ); -// -// Module( IDebugClient4 *client, SynSymbolsPtr synSymbols, ULONG64 offset ); -// -// std::string getName() { -// return m_name; -// } -// -// std::string getImageName() { -// return m_imageName; -// } -// -// ULONG64 getBase() const { -// return m_base; -// } -// -// ULONG64 getEnd() const { -// return m_base + m_size; -// } -// -// ULONG getSize() const { -// return m_size; -// } -// -// std::string -// getPdbName(); -// -// void -// reloadSymbols(); -// -// ULONG64 -// getSymbol( const std::string &symbolname ) { -// return m_base + getRvaByName(symbolname); -// } -// -// ULONG -// getSymbolRva( const std::string &symbolname ) { -// return getRvaByName(symbolname); -// } -// -// TypeInfoPtr getTypeByName( const std::string &typeName ) { -// return TypeInfo::getTypeInfo( boost::static_pointer_cast( getDia() ), typeName); -// } -// -// TypedVarPtr getTypedVarByTypeName( const std::string &typeName, ULONG64 addr ); -// -// TypedVarPtr getTypedVarByType( const TypeInfoPtr &typeInfo, ULONG64 addr ); -// -// TypedVarPtr getTypedVarByAddr( ULONG64 addr ); -// -// TypedVarPtr getTypedVarByName( const std::string &symName ); -// -// 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 ); -// -// pyDia::GlobalScopePtr& getDia() { -// if (!m_dia) -// { -// m_dia = pyDia::GlobalScope::loadPdb( getPdbName() ); -// if ( m_dia ) -// { -// m_dia->setLoadAddress( m_base ); -// } -// } -// -// return m_dia; -// } -// -// ULONG getCheckSum() const { -// return m_checkSum; -// } -// -// ULONG getTimeDataStamp() const { -// return m_timeDataStamp; -// } -// -// std::string print(); -// -//private: -// -// void -// reloadSymbolsImpl(); -// -// -// ULONG getRvaByName(const std::string &symName); -// -// BaseTypeVariant getValue() { -// return BaseTypeVariant(m_base); -// } -// -// -// std::string m_name; -// std::string m_imageName; -// ULONG64 m_base; -// ULONG m_size; -// -// pyDia::GlobalScopePtr m_dia; -// -// ULONG m_timeDataStamp; -// ULONG m_checkSum; -// SynSymbolsPtr m_synSymbols; -//}; -// -///////////////////////////////////////////////////////////////////////////////////// -// -//}; // end pykd namespace - - diff --git a/pykd/pykd_2008.vcproj b/pykd/pykd_2008.vcproj index 89d0f05..275d415 100644 --- a/pykd/pykd_2008.vcproj +++ b/pykd/pykd_2008.vcproj @@ -409,6 +409,10 @@ /> + + @@ -417,6 +421,10 @@ RelativePath=".\udtutils.cpp" > + + + + @@ -467,6 +479,10 @@ RelativePath=".\udtutils.h" > + + ( "intBase", "intBase", python::no_init ) .def( python::init() ) @@ -193,32 +208,23 @@ BOOST_PYTHON_MODULE( pykd ) "Return offset of the symbol" ) .def("rva", &Module::getSymbolRva, "Return rva of the symbol" ) - //.def( "sizeof", &Module::getSymbolSize, - // "Return a size of the type or variable" ) + .def( "sizeof", &Module::getSymbolSize, + "Return a size of the type or variable" ) .def("type", &Module::getTypeByName, "Return typeInfo class by type name" ) - //.def("typedVar", &Module::getTypedVarByAddr, - // "Return a typedVar class instance" ) - //.def("typedVar",&Module::getTypedVarByName, - // "Return a typedVar class instance" ) - //.def("typedVar",&Module::getTypedVarByType, - // "Return a typedVar class instance" ) - //.def("typedVar",&Module::getTypedVarByTypeName, - // "Return a typedVar class instance" ) - //.def("typedVarList", &Module::getTypedVarListByTypeName, - // "Return a list of the typedVar class instances. Each item represents an item of the linked list in the target memory" ) - //.def("typedVarList", &Module::getTypedVarListByType, - // "Return a list of the typedVar class instances. Each item represents an item of the linked list in the target memory" ) - //.def("typedVarArray", &Module::getTypedVarArrayByTypeName, - // "Return a list of the typedVar class instances. Each item represents an item of the counted array in the target memory" ) - //.def("typedVarArray", &Module::getTypedVarArrayByType, - // "Return a list of the typedVar class instances. Each item represents an item of the counted array in the target memory" ) - //.def("containingRecord", &Module::containingRecordByName, - // "Return instance of the typedVar class. It's value are loaded from the target memory." - // "The start address is calculated by the same method as the standard macro CONTAINING_RECORD does" ) - //.def("containingRecord", &Module::containingRecordByType, - // "Return instance of the typedVar class. It's value are loaded from the target memory." - // "The start address is calculated by the same method as the standard macro CONTAINING_RECORD does" ) + .def("typedVar", &Module::getTypedVarByAddr, + "Return a typedVar class instance" ) + .def("typedVar",&Module::getTypedVarByName, + "Return a typedVar class instance" ) + .def("typedVar",&Module::getTypedVarByTypeName, + "Return a typedVar class instance" ) + .def("typedVarList", &Module::getTypedVarListByTypeName, + "Return a list of the typedVar class instances. Each item represents an item of the linked list in the target memory" ) + .def("typedVarArray", &Module::getTypedVarArrayByTypeName, + "Return a list of the typedVar class instances. Each item represents an item of the counted array in the target memory" ) + .def("containingRecord", &Module::containingRecordByName, + "Return instance of the typedVar class. It's value are loaded from the target memory." + "The start address is calculated by the same method as the standard macro CONTAINING_RECORD does" ) .def("checksum",&Module::getCheckSum, "Return a image file checksum: IMAGE_OPTIONAL_HEADER.CheckSum" ) .def("timestamp",&Module::getTimeDataStamp, @@ -243,6 +249,34 @@ BOOST_PYTHON_MODULE( pykd ) .def("__len__", &TypeInfo::getElementCount ) .def("__getitem__", &TypeInfo::getElementByIndex ); + python::class_, boost::noncopyable >("typedVar", + "Class of non-primitive type object, child class of typeClass. Data from target is copied into object instance", python::no_init ) + .def("__init__", python::make_constructor(TypedVar::getTypedVarByName) ) + .def("__init__", python::make_constructor(TypedVar::getTypedVarByTypeName) ) + .def("__init__", python::make_constructor(TypedVar::getTypedVarByTypeInfo) ) + .def("getAddress", &TypedVar::getAddress, + "Return virtual address" ) + .def("sizeof", &TypedVar::getSize, + "Return size of a variable in the target memory" ) + .def("fieldOffset", &TypedVar::getFieldOffsetByNameRecirsive, + "Return target field offset" ) + .def("field", &TypedVar::getField, + "Return field of structure as an object attribute" ) + .def( "dataKind", &TypedVar::getDataKind, + "Retrieves the variable classification of a data: DataIsXxx") + .def("deref", &TypedVar::deref, + "Return value by pointer" ) + .def("type", &TypedVar::getType, + "Return typeInfo instance" ) + .def("__getattr__", &TypedVar::getField, + "Return field of structure as an object attribute" ) + .def( "__str__", &TypedVar::print ) + .def("__len__", &TypedVar::getElementCount ) + .def("__getitem__", &TypedVar::getElementByIndex ) + .def("__getitem__", &TypedVar::getElementByIndexPtr ); + + // wrapper for standart python exceptions + python::register_exception_translator( &PyException::exceptionTranslate ); pykd::exception( "BaseException", "Pykd base exception class" ); pykd::exception( "MemoryException", "Target memory access exception class" ); diff --git a/pykd/symengine.h b/pykd/symengine.h index f7642a9..544ae1f 100644 --- a/pykd/symengine.h +++ b/pykd/symengine.h @@ -110,7 +110,6 @@ class Symbol { public: - virtual SymbolPtrList findChildren( ULONG symTag, const std::string &name = "", bool caseSensitive = FALSE ) = 0; virtual ULONG getBaseType() = 0; virtual ULONG getBitPosition() = 0; @@ -140,7 +139,7 @@ public: std::string getBasicTypeName( ULONG basicType ); -SymbolPtr loadSymbolFile(const std::string &filePath); +SymbolPtr loadSymbolFile(const std::string &filePath, ULONGLONG loadBase = 0); //////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/typedvar.cpp b/pykd/typedvar.cpp index ffea67b..02f6699 100644 --- a/pykd/typedvar.cpp +++ b/pykd/typedvar.cpp @@ -3,50 +3,50 @@ #include #include "typedvar.h" -#include "dbgclient.h" +#include "module.h" #include "dbgmem.h" namespace pykd { /////////////////////////////////////////////////////////////////////////////////// -TypedVarPtr TypedVar::getTypedVar( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ) +TypedVarPtr TypedVar::getTypedVar( const TypeInfoPtr& typeInfo, VarDataPtr varData ) { TypedVarPtr tv; if ( typeInfo->isBasicType() ) { - tv.reset( new BasicTypedVar( client, typeInfo, varData) ); + tv.reset( new BasicTypedVar( typeInfo, varData) ); return tv; } if ( typeInfo->isPointer() ) { - tv.reset( new PtrTypedVar( client, typeInfo, varData ) ); + tv.reset( new PtrTypedVar( typeInfo, varData ) ); return tv; } if ( typeInfo->isArray() ) { - tv.reset( new ArrayTypedVar( client, typeInfo, varData ) ); + tv.reset( new ArrayTypedVar( typeInfo, varData ) ); return tv; } if ( typeInfo->isUserDefined() ) { - tv.reset( new UdtTypedVar( client, typeInfo, varData ) ); + tv.reset( new UdtTypedVar( typeInfo, varData ) ); return tv; } if ( typeInfo->isBitField() ) { - tv.reset( new BitFieldVar( client, typeInfo, varData ) ); + tv.reset( new BitFieldVar( typeInfo, varData ) ); return tv; } if ( typeInfo->isEnum() ) { - tv.reset( new EnumTypedVar( client, typeInfo, varData ) ); + tv.reset( new EnumTypedVar( typeInfo, varData ) ); return tv; } @@ -59,23 +59,42 @@ TypedVarPtr TypedVar::getTypedVar( IDebugClient4 *client, const TypeInfoPtr& t TypedVarPtr TypedVar::getTypedVarByName( const std::string &varName ) { - return g_dbgClient->getTypedVarByName( varName ); -} + std::string moduleName; + std::string symName; -TypedVarPtr TypedVar::getTypedVarByTypeName( const std::string &typeName, ULONG64 addr ) -{ - return g_dbgClient->getTypedVarByTypeName( typeName, addr ); -} + splitSymName( varName, moduleName, symName ); -TypedVarPtr TypedVar::getTypedVarByTypeInfo( const TypeInfoPtr &typeInfo, ULONG64 addr ) -{ - return g_dbgClient->getTypedVarByTypeInfo( typeInfo, addr ); + ModulePtr module = Module::loadModuleByName( moduleName ); + + return module->getTypedVarByName( symName ); } /////////////////////////////////////////////////////////////////////////////////// -TypedVar::TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ) : - DbgObject( client ), +TypedVarPtr TypedVar::getTypedVarByTypeName( const std::string &typeName, ULONG64 addr ) +{ + addr = addr64( addr ); + + std::string moduleName; + std::string symName; + + splitSymName( typeName, moduleName, symName ); + + ModulePtr module = Module::loadModuleByName( moduleName ); + + return module->getTypedVarByTypeName( symName, addr ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +TypedVarPtr TypedVar::getTypedVarByTypeInfo( const TypeInfoPtr &typeInfo, ULONG64 addr ) +{ + return getTypedVar( typeInfo, VarDataMemory::factory(addr) ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +TypedVar::TypedVar ( const TypeInfoPtr& typeInfo, VarDataPtr varData ) : m_typeInfo( typeInfo ), m_varData( varData ), m_dataKind( DataIsGlobal ) @@ -166,8 +185,8 @@ BaseTypeVariant PtrTypedVar::getValue() TypedVarPtr PtrTypedVar::deref() { - VarDataPtr varData = VarDataMemory::factory( m_dataSpaces, m_varData->readPtr() ); - return TypedVar::getTypedVar( m_client, m_typeInfo->deref(), varData ); + VarDataPtr varData = VarDataMemory::factory( m_varData->readPtr() ); + return TypedVar::getTypedVar( m_typeInfo->deref(), varData ); } /////////////////////////////////////////////////////////////////////////////////// @@ -220,7 +239,7 @@ python::object ArrayTypedVar::getElementByIndex( ULONG index ) TypeInfoPtr elementType = m_typeInfo->getElementType(); - return python::object( TypedVar::getTypedVar( m_client, elementType, m_varData->fork(elementType->getSize()*index) ) ); + return python::object( TypedVar::getTypedVar( elementType, m_varData->fork(elementType->getSize()*index) ) ); } /////////////////////////////////////////////////////////////////////////////////// @@ -235,7 +254,7 @@ UdtTypedVar::getField( const std::string &fieldName ) if ( fieldType->getStaticOffset() == 0 ) throw ImplementException( __FILE__, __LINE__, "Fix ME"); - return TypedVar::getTypedVar( m_client, fieldType, VarDataMemory::factory(m_dataSpaces, fieldType->getStaticOffset() ) ); + return TypedVar::getTypedVar( fieldType, VarDataMemory::factory(fieldType->getStaticOffset() ) ); } ULONG fieldOffset = 0; @@ -247,7 +266,7 @@ UdtTypedVar::getField( const std::string &fieldName ) fieldOffset += getVirtualBaseDisplacement( fieldType ); } - return TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldOffset) ); + return TypedVar::getTypedVar( fieldType, m_varData->fork(fieldOffset) ); } /////////////////////////////////////////////////////////////////////////////////// @@ -264,7 +283,7 @@ UdtTypedVar::getElementByIndex( ULONG index ) return python::make_tuple( m_typeInfo->getFieldNameByIndex(index), - TypedVar::getTypedVar( m_client, fieldType, VarDataMemory::factory(m_dataSpaces, fieldType->getStaticOffset() ) ) ); + TypedVar::getTypedVar(fieldType, VarDataMemory::factory(fieldType->getStaticOffset() ) ) ); } ULONG fieldOffset = m_typeInfo->getFieldOffsetByIndex(index); @@ -276,7 +295,7 @@ UdtTypedVar::getElementByIndex( ULONG index ) return python::make_tuple( m_typeInfo->getFieldNameByIndex(index), - TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldOffset) ) ); + TypedVar::getTypedVar( fieldType, m_varData->fork(fieldOffset) ) ); } /////////////////////////////////////////////////////////////////////////////////// @@ -288,7 +307,7 @@ LONG UdtTypedVar::getVirtualBaseDisplacement( TypeInfoPtr& typeInfo ) ULONG64 vbtableOffset = m_varData->fork( virtualBasePtr )->readPtr(); - VarDataPtr vbtable = VarDataMemory::factory(m_dataSpaces, vbtableOffset); + VarDataPtr vbtable = VarDataMemory::factory(vbtableOffset); LONG displacement = 0; @@ -313,7 +332,7 @@ std::string UdtTypedVar::print() if ( fieldType->isStaticMember() ) { if ( fieldType->getStaticOffset() != 0 ) - fieldVar = TypedVar::getTypedVar( m_client, fieldType, VarDataMemory::factory(m_dataSpaces, fieldType->getStaticOffset() ) ); + fieldVar = TypedVar::getTypedVar( fieldType, VarDataMemory::factory( fieldType->getStaticOffset() ) ); sstr << " =" << std::right << std::setw(10) << std::setfill('0') << std::hex << fieldType->getStaticOffset(); sstr << " " << std::left << std::setw(18) << std::setfill(' ') << m_typeInfo->getFieldNameByIndex(i) << ':'; @@ -327,7 +346,7 @@ std::string UdtTypedVar::print() fieldOffset += getVirtualBaseDisplacement( fieldType ); } - fieldVar = TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldOffset) ); + fieldVar = TypedVar::getTypedVar( fieldType, m_varData->fork(fieldOffset) ); sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << fieldOffset; sstr << " " << std::left << std::setw(24) << std::setfill(' ') << m_typeInfo->getFieldNameByIndex(i) << ':'; } @@ -446,4 +465,98 @@ std::string EnumTypedVar::printValue() /////////////////////////////////////////////////////////////////////////////////// +TypedVarPtr containingRecordByName( ULONG64 offset, const std::string &typeName, const std::string &fieldName ) +{ + std::string moduleName; + std::string symName; + + splitSymName( typeName, moduleName, symName ); + + ModulePtr module = Module::loadModuleByName( moduleName ); + + return module->containingRecordByName( offset, symName, fieldName ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +TypedVarPtr containingRecordByType( ULONG64 addr, const TypeInfoPtr &typeInfo, const std::string &fieldName ) +{ + addr = addr64(addr); + + VarDataPtr varData = VarDataMemory::factory( addr - typeInfo->getFieldOffsetByNameRecirsive(fieldName) ); + + return TypedVar::getTypedVar( typeInfo, varData ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +python::list getTypedVarListByTypeName( ULONG64 listHeadAddress, const std::string &typeName, const std::string &listEntryName ) +{ + std::string moduleName; + std::string symName; + + splitSymName( typeName, moduleName, symName ); + + ModulePtr module = Module::loadModuleByName( moduleName ); + + return module->getTypedVarListByTypeName( listHeadAddress, symName, listEntryName ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +python::list 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( TypedVar::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 getTypedVarArrayByTypeName( ULONG64 addr, const std::string &typeName, ULONG number ) +{ + std::string moduleName; + std::string symName; + + splitSymName( typeName, moduleName, symName ); + + ModulePtr module = Module::loadModuleByName( moduleName ); + + return module->getTypedVarArrayByTypeName( addr, symName, number ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +python::list getTypedVarArrayByType( ULONG64 offset, const TypeInfoPtr &typeInfo, ULONG number ) +{ + offset = addr64(offset); + + python::list lst; + + for( ULONG i = 0; i < number; ++i ) + lst.append( TypedVar::getTypedVarByTypeInfo( typeInfo, offset + i * typeInfo->getSize() ) ); + + return lst; +} + +/////////////////////////////////////////////////////////////////////////////////// + + } // end pykd namespace \ No newline at end of file diff --git a/pykd/typedvar.h b/pykd/typedvar.h index 4350af6..79dd8a4 100644 --- a/pykd/typedvar.h +++ b/pykd/typedvar.h @@ -2,7 +2,6 @@ #include "typeinfo.h" #include "intbase.h" -#include "dbgobj.h" #include "dbgexcept.h" #include "vardata.h" @@ -15,11 +14,11 @@ typedef boost::shared_ptr TypedVarPtr; /////////////////////////////////////////////////////////////////////////////////// -class TypedVar : public intBase, protected DbgObject { +class TypedVar : public intBase { public: - static TypedVarPtr getTypedVar( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ); + static TypedVarPtr getTypedVar( const TypeInfoPtr& typeInfo, VarDataPtr varData ); static TypedVarPtr getTypedVarByName( const std::string &varName ); @@ -86,7 +85,7 @@ public: protected: - TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ); + TypedVar ( const TypeInfoPtr& typeInfo, VarDataPtr varData ); TypeInfoPtr m_typeInfo; @@ -104,11 +103,8 @@ class BasicTypedVar : public TypedVar { public: - BasicTypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ) - : TypedVar(client, typeInfo, varData) - { - } - + BasicTypedVar ( const TypeInfoPtr& typeInfo, VarDataPtr varData ) : TypedVar(typeInfo, varData) + {} virtual std::string print(); @@ -124,10 +120,8 @@ class PtrTypedVar : public TypedVar { public: - PtrTypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ) - : TypedVar(client, typeInfo, varData) - { - } + PtrTypedVar ( const TypeInfoPtr& typeInfo, VarDataPtr varData ) : TypedVar(typeInfo, varData) + {} virtual std::string print(); @@ -145,10 +139,8 @@ class ArrayTypedVar: public TypedVar { public: - ArrayTypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ) - : TypedVar(client, typeInfo, varData) - { - } + ArrayTypedVar ( const TypeInfoPtr& typeInfo, VarDataPtr varData ) : TypedVar(typeInfo, varData) + {} virtual ULONG getElementCount() { return m_typeInfo->getCount(); @@ -167,10 +159,8 @@ class UdtTypedVar : public TypedVar { public: - UdtTypedVar( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ) - : TypedVar(client, typeInfo, varData) - { - } + UdtTypedVar( const TypeInfoPtr& typeInfo, VarDataPtr varData ) : TypedVar(typeInfo, varData) + {} protected: @@ -195,10 +185,8 @@ class BitFieldVar: public TypedVar { public: - BitFieldVar( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ) - : TypedVar(client, typeInfo, varData) - { - } + BitFieldVar( const TypeInfoPtr& typeInfo, VarDataPtr varData ) : TypedVar( typeInfo, varData) + {} virtual std::string printValue(); @@ -210,10 +198,8 @@ public: class EnumTypedVar : public TypedVar { public: - EnumTypedVar( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ) - : TypedVar(client, typeInfo, varData) - { - } + EnumTypedVar( const TypeInfoPtr& typeInfo, VarDataPtr varData ) : TypedVar( typeInfo, varData) + {} virtual std::string print(); @@ -224,5 +210,18 @@ public: /////////////////////////////////////////////////////////////////////////////////// +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 ); + +/////////////////////////////////////////////////////////////////////////////////// } // namespace pykd diff --git a/pykd/typeinfo.h b/pykd/typeinfo.h index e700bc6..e485a0f 100644 --- a/pykd/typeinfo.h +++ b/pykd/typeinfo.h @@ -515,4 +515,8 @@ private: /////////////////////////////////////////////////////////////////////////////////// +void splitSymName( const std::string &fullName, std::string &moduleName, std::string &symbolName ); + +/////////////////////////////////////////////////////////////////////////////////// + }; // namespace pykd diff --git a/pykd/vardata.cpp b/pykd/vardata.cpp index 2feb02c..a9d8503 100644 --- a/pykd/vardata.cpp +++ b/pykd/vardata.cpp @@ -5,7 +5,7 @@ #include "stdafx.h" #include "vardata.h" -#include "dbgmem.h" +#include "dbgengine.h" #include "dbgexcept.h" //////////////////////////////////////////////////////////////////////////////// @@ -14,9 +14,8 @@ namespace pykd { //////////////////////////////////////////////////////////////////////////////// -VarDataMemory::VarDataMemory(CComPtr< IDebugDataSpaces4 > dataSpaces, ULONG64 addr) - : m_dataSpaces(dataSpaces) - , m_addr(addr) +VarDataMemory::VarDataMemory(ULONG64 addr) : + m_addr(addr) { } @@ -40,30 +39,27 @@ ULONG64 VarDataMemory::getAddr() const VarDataPtr VarDataMemory::fork(ULONG offset) const { - return VarDataPtr( new VarDataMemory(m_dataSpaces, m_addr + offset) ); + return VarDataPtr( new VarDataMemory(m_addr + offset) ); } //////////////////////////////////////////////////////////////////////////////// void VarDataMemory::read(PVOID buffer, ULONG length, ULONG offset /*= 0*/) const { - readMemory(m_dataSpaces, m_addr + offset, buffer, length); + readMemory( m_addr + offset, buffer, length); } //////////////////////////////////////////////////////////////////////////////// ULONG64 VarDataMemory::readPtr() const { - ULONG64 ptrValue = 0; - readMemoryPtr(m_dataSpaces, m_addr, &ptrValue); - return ptrValue; + return ptrPtr( m_addr ); } -//////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// -VarDataConst::VarDataConst(CComPtr< IDebugControl4 > control, pyDia::SymbolPtr symData) - : m_control(control) - , m_fieldOffset(0) +VarDataConst::VarDataConst( SymbolPtr &symData) : + m_fieldOffset(0) , m_dataBuff( new std::vector< UCHAR >((size_t)symData->getType()->getSize(), 0) ) { VARIANT vtValue = {0}; @@ -147,7 +143,7 @@ void VarDataConst::read(PVOID buffer, ULONG length, ULONG offset /*= 0*/) const ULONG64 VarDataConst::readPtr() const { ULONG64 val = 0; - const ULONG length = (S_OK == m_control->IsPointer64Bit()) ? 8 : 4; + const ULONG length = ptrSize(); if (length > m_dataBuff->size()) throw DbgException("Internal error in " __FUNCTION__); RtlCopyMemory(&val, &m_dataBuff->at(0), length); @@ -156,9 +152,8 @@ ULONG64 VarDataConst::readPtr() const //////////////////////////////////////////////////////////////////////////////// -VarDataConst::VarDataConst(const VarDataConst &from, ULONG fieldOffset) - : m_control(from.m_control) - , m_fieldOffset(from.m_fieldOffset + fieldOffset) +VarDataConst::VarDataConst(const VarDataConst &from, ULONG fieldOffset) : + m_fieldOffset(from.m_fieldOffset + fieldOffset) , m_dataBuff(from.m_dataBuff) { } diff --git a/pykd/vardata.h b/pykd/vardata.h index b1f27bf..b7548a0 100644 --- a/pykd/vardata.h +++ b/pykd/vardata.h @@ -6,75 +6,73 @@ //////////////////////////////////////////////////////////////////////////////// -#include -#include - -#include "diawrapper.h" +//#include +#include "symengine.h" //////////////////////////////////////////////////////////////////////////////// namespace pykd { -// pointer to variable data access interface -interface IVarData; -typedef boost::shared_ptr< IVarData > VarDataPtr; +class VarData; +typedef boost::shared_ptr< VarData > VarDataPtr; // access to variable data interface -interface IVarData +class VarData { - virtual ~IVarData() {} +public: + virtual ~VarData() {} virtual std::string asString() const = 0; virtual ULONG64 getAddr() const = 0; virtual VarDataPtr fork(ULONG offset) const = 0; - virtual void read(PVOID buffer, ULONG length, ULONG offset = 0) const = 0; virtual ULONG64 readPtr() const = 0; }; // variable in memory -class VarDataMemory : public IVarData +class VarDataMemory : public VarData { public: // IVarData implementation - virtual std::string asString() const override; - virtual ULONG64 getAddr() const override; - virtual VarDataPtr fork(ULONG offset) const override; + virtual std::string asString() const; + virtual ULONG64 getAddr() const; + virtual VarDataPtr fork(ULONG offset) const; - virtual void read(PVOID buffer, ULONG length, ULONG offset = 0) const override; - virtual ULONG64 readPtr() const override; + virtual void read(PVOID buffer, ULONG length, ULONG offset = 0) const; + virtual ULONG64 readPtr() const; - static VarDataPtr factory(CComPtr< IDebugDataSpaces4 > dataSpaces, ULONG64 addr) { - return VarDataPtr( new VarDataMemory(dataSpaces, addr) ); + static VarDataPtr factory(ULONG64 addr) { + return VarDataPtr( new VarDataMemory(addr) ); } protected: - VarDataMemory(CComPtr< IDebugDataSpaces4 > dataSpaces, ULONG64 addr); + VarDataMemory(ULONG64 addr); private: - CComPtr< IDebugDataSpaces4 > m_dataSpaces; ULONG64 m_addr; }; + + // constant variable -class VarDataConst : public IVarData +class VarDataConst : public VarData { public: // IVarData implementation - virtual std::string asString() const override; - virtual ULONG64 getAddr() const override; - virtual VarDataPtr fork(ULONG offset) const override; + virtual std::string asString() const; + virtual ULONG64 getAddr() const; + virtual VarDataPtr fork(ULONG offset) const; - virtual void read(PVOID buffer, ULONG length, ULONG offset = 0) const override; - virtual ULONG64 readPtr() const override; + virtual void read(PVOID buffer, ULONG length, ULONG offset = 0) const; + virtual ULONG64 readPtr() const; - static VarDataPtr factory(CComPtr< IDebugControl4 > control, pyDia::SymbolPtr symData) { - return VarDataPtr( new VarDataConst(control, symData) ); + static VarDataPtr factory(SymbolPtr &symData) { + return VarDataPtr( new VarDataConst(symData) ); } protected: - VarDataConst(CComPtr< IDebugControl4 > control, pyDia::SymbolPtr symData); + VarDataConst(SymbolPtr &symData); VarDataConst(const VarDataConst &from, ULONG fieldOffset); template @@ -84,7 +82,6 @@ protected: } private: - CComPtr< IDebugControl4 > m_control; ULONG m_fieldOffset; boost::shared_ptr< std::vector > m_dataBuff; diff --git a/pykd/win/dbgeng.cpp b/pykd/win/dbgeng.cpp index 49b9f91..e97901a 100644 --- a/pykd/win/dbgeng.cpp +++ b/pykd/win/dbgeng.cpp @@ -318,6 +318,34 @@ ULONG ptrSize() /////////////////////////////////////////////////////////////////////////////////// +std::string getSymbolByOffset( ULONG64 offset ) +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres; + + char nameBuf[0x100]; + + hres = + g_dbgEng->symbols->GetNameByOffset( + offset, + nameBuf, + sizeof(nameBuf), + NULL, + NULL ); + + std::string fullName( nameBuf ); + + size_t symPos = fullName.find ( '!' ) + 1; + + std::string symbolName; + symbolName.assign( fullName, symPos, fullName.length() - symPos ); + + return symbolName; +} + +/////////////////////////////////////////////////////////////////////////////////// + }; diff --git a/test/scripts/pykdtest.py b/test/scripts/pykdtest.py index 34dff38..9bd99dd 100644 --- a/test/scripts/pykdtest.py +++ b/test/scripts/pykdtest.py @@ -17,7 +17,7 @@ import intbase import memtest import moduletest import typeinfo - +import typedvar def getTestSuite( singleName = "" ): if singleName == "": @@ -28,6 +28,7 @@ def getTestSuite( singleName = "" ): unittest.TestLoader().loadTestsFromTestCase( moduletest.ModuleTest ), unittest.TestLoader().loadTestsFromTestCase( memtest.MemoryTest ), unittest.TestLoader().loadTestsFromTestCase( typeinfo.TypeInfoTest ), + unittest.TestLoader().loadTestsFromTestCase( typedvar.TypedVarTest ), ] ) else: return unittest.TestSuite( unittest.TestLoader().loadTestsFromName( singleName ) ) @@ -46,6 +47,8 @@ if __name__ == "__main__": pykd.go() + unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run(getTestSuite( "typedvar.TypedVarTest.testPrint" ) ) + unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( getTestSuite() ) pykd.killProcess( processId ) diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index 2bedc33..073afc8 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -120,7 +120,7 @@ class TypedVarTest( unittest.TestCase ): self.assertEqual( 3, len( tvl ) ) self.assertEqual( [1,2,3], [ tv.num for tv in tvl ] ) - tvl = target.module.typedVarList( target.module.g_listHead, target.module.type("listStruct"), "listEntry" ) + tvl = pykd.typedVarList( target.module.g_listHead, target.module.type("listStruct"), "listEntry" ) self.assertEqual( 3, len( tvl ) ) self.assertEqual( [1,2,3], [ tv.num for tv in tvl ] ) @@ -128,11 +128,11 @@ class TypedVarTest( unittest.TestCase ): self.assertEqual( 3, len( tvl ) ) self.assertEqual( [100,200,300], [ tv.num for tv in tvl ] ) - tvl = target.module.typedVarList( target.module.g_listHead1, target.module.type("listStruct1"), "next" ) + tvl = pykd.typedVarList( target.module.g_listHead1, target.module.type("listStruct1"), "next" ) self.assertEqual( 3, len( tvl ) ) self.assertEqual( [100,200,300], [ tv.num for tv in tvl ] ) - tvl = target.module.typedVarList( target.module.g_childListHead, target.module.type("ChildEntryTest"), "m_next" ) + tvl = pykd.typedVarList( target.module.g_childListHead, target.module.type("ChildEntryTest"), "m_next" ) self.assertEqual( 3, len( tvl ) ) self.assertEqual( [1000,2000,3000], [ tv.m_someBaseFiled2 for tv in tvl ] ) self.assertEqual( [1001,2001,3001], [ tv.m_childFiled1 for tv in tvl ] ) @@ -147,7 +147,7 @@ class TypedVarTest( unittest.TestCase ): self.assertEqual( 500, tvl[0].m_field1 ) self.assertEqual( False, tvl[1].m_field2 ) - tvl = target.module.typedVarArray( target.module.g_testArray, target.module.type("structTest"), 2 ) + tvl = pykd.typedVarArray( target.module.g_testArray, target.module.type("structTest"), 2 ) self.assertEqual( 2, len( tvl ) ) self.assertEqual( 1, tvl[0].m_field3 ) self.assertEqual( 0, tvl[1].m_field4 )