[0.1.x] added : typedVarList, typedVarArray, containingRecord for global space

git-svn-id: https://pykd.svn.codeplex.com/svn@75077 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\kernelnet_cp 2012-03-27 07:03:19 +00:00 committed by Mikhail I. Izmestev
parent 2d1d141a4c
commit 064f28eda0
6 changed files with 241 additions and 42 deletions

View File

@ -439,38 +439,68 @@ void terminateProcess()
static const boost::regex moduleSymMatch("^(?:([^!]*)!)?([^!]+)$"); static const boost::regex moduleSymMatch("^(?:([^!]*)!)?([^!]+)$");
TypedVarPtr DebugClient::getTypedVarByName( const std::string &varName ) void DebugClient::splitSymName( const std::string &fullName, std::string &moduleName, std::string &symbolName )
{ {
boost::cmatch matchResult; boost::cmatch matchResult;
if ( !boost::regex_match( varName.c_str(), matchResult, moduleSymMatch ) ) if ( !boost::regex_match( fullName.c_str(), matchResult, moduleSymMatch ) )
{ {
std::stringstream sstr; std::stringstream sstr;
sstr << "invalid symbol name: " << varName; sstr << "invalid symbol name: " << fullName;
throw SymbolException( sstr.str() ); throw SymbolException( sstr.str() );
} }
std::string symName = std::string( matchResult[2].first, matchResult[2].second ); symbolName = std::string( matchResult[2].first, matchResult[2].second );
if ( matchResult[1].matched ) if ( matchResult[1].matched )
{ {
Module module = loadModuleByName( std::string( matchResult[1].first, matchResult[1].second ) ); moduleName = std::string( matchResult[1].first, matchResult[1].second );
return module.getTypedVarByName( symName ); return;
} }
HRESULT hres; HRESULT hres;
ULONG64 base; ULONG64 base;
hres = m_symbols->GetSymbolModule( ( std::string("!") + symName ).c_str(), &base ); hres = m_symbols->GetSymbolModule( ( std::string("!") + symbolName ).c_str(), &base );
if ( FAILED( hres ) ) if ( FAILED( hres ) )
{ {
std::stringstream sstr; std::stringstream sstr;
sstr << "failed to find module for symbol: " << symName; sstr << "failed to find module for symbol: " << symbolName;
throw SymbolException( sstr.str() ); throw SymbolException( sstr.str() );
} }
Module module = loadModuleByOffset( base ); 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 );
}
///////////////////////////////////////////////////////////////////////////////////
TypedVarPtr DebugClient::getTypedVarByName( const std::string &varName )
{
std::string moduleName;
std::string symName;
splitSymName( varName, moduleName, symName );
Module module = loadModuleByName( moduleName );
return module.getTypedVarByName( symName ); return module.getTypedVarByName( symName );
} }
@ -479,39 +509,143 @@ TypedVarPtr DebugClient::getTypedVarByName( const std::string &varName )
TypedVarPtr DebugClient::getTypedVarByTypeName( const std::string &typeName, ULONG64 addr ) TypedVarPtr DebugClient::getTypedVarByTypeName( const std::string &typeName, ULONG64 addr )
{ {
boost::cmatch matchResult; addr = addr64( addr );
if ( !boost::regex_match( typeName.c_str(), matchResult, moduleSymMatch ) ) std::string moduleName;
{ std::string symName;
std::stringstream sstr;
sstr << "invalid symbol name: " << typeName;
throw SymbolException( sstr.str() );
}
std::string symName = std::string( matchResult[2].first, matchResult[2].second ); splitSymName( typeName, moduleName, symName );
if ( matchResult[1].matched ) Module module = loadModuleByName( moduleName );
{
Module module = loadModuleByName( std::string( matchResult[1].first, matchResult[1].second ) );
return module.getTypedVarByTypeName( symName, addr ); return module.getTypedVarByTypeName( symName, addr );
} }
HRESULT hres; ///////////////////////////////////////////////////////////////////////////////////
ULONG64 base;
hres = m_symbols->GetSymbolModule( ( std::string("!") + symName ).c_str(), &base ); TypedVarPtr DebugClient::containingRecordByName( ULONG64 addr, const std::string &typeName, const std::string &fieldName )
if ( FAILED( hres ) )
{ {
std::stringstream sstr; addr = addr64( addr );
sstr << "failed to find module for symbol: " << symName;
throw SymbolException( sstr.str() ); std::string moduleName;
std::string symName;
splitSymName( typeName, moduleName, symName );
Module module = loadModuleByName( moduleName );
return module.containingRecordByName( addr, symName, fieldName );
} }
Module module = loadModuleByOffset( base ); TypedVarPtr containingRecordByName( ULONG64 addr, const std::string &typeName, const std::string &fieldName )
{
return g_dbgClient->containingRecordByName( addr, typeName, fieldName );
}
return module.getTypedVarByTypeName( symName, addr ); ///////////////////////////////////////////////////////////////////////////////////
TypedVarPtr DebugClient::containingRecordByType( ULONG64 addr, const TypeInfoPtr &typeInfo, const std::string &fieldName )
{
addr = addr64(addr);
TypeInfoPtr fieldTypeInfo = typeInfo->getField( fieldName );
VarDataPtr varData = VarDataMemory::factory( m_dataSpaces, addr - fieldTypeInfo->getOffset() );
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 + fieldTypeInfo->getOffset() ) )
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 );
Module 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 );
Module 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 );
} }
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////

View File

@ -325,6 +325,8 @@ public:
void removeBp(BPOINT_ID Id); void removeBp(BPOINT_ID Id);
void removeAllBp(); void removeAllBp();
void splitSymName( const std::string &fullName, std::string &moduleName, std::string &symbolName );
TypedVarPtr getTypedVarByName( const std::string &varName ); TypedVarPtr getTypedVarByName( const std::string &varName );
TypedVarPtr getTypedVarByTypeName( const std::string &typeName, ULONG64 addr ); TypedVarPtr getTypedVarByTypeName( const std::string &typeName, ULONG64 addr );
@ -333,6 +335,20 @@ public:
return TypedVar::getTypedVar( m_client, typeInfo, VarDataMemory::factory(m_dataSpaces, 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 );
private: private:
template<typename T> template<typename T>
python::list python::list
@ -388,6 +404,18 @@ void terminateProcess();
void waitForEvent(); 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 );
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
// Synthetic symbols global finctions: // Synthetic symbols global finctions:

View File

@ -304,6 +304,20 @@ BOOST_PYTHON_MODULE( pykd )
"Return symbol path" ) "Return symbol path" )
.def( "trace", &DebugClient::changeDebuggerStatus<DEBUG_STATUS_STEP_INTO>, .def( "trace", &DebugClient::changeDebuggerStatus<DEBUG_STATUS_STEP_INTO>,
"Change debugger status to DEBUG_STATUS_STEP_INTO" ) "Change debugger status to DEBUG_STATUS_STEP_INTO" )
.def("typedVarList", &DebugClient::getTypedVarListByTypeName,
"Return a list of the typedVar class instances. Each item represents an item of the linked list in the target memory" )
.def("typedVarList", &DebugClient::getTypedVarListByType,
"Return a list of the typedVar class instances. Each item represents an item of the linked list in the target memory" )
.def("typedVarArray", &DebugClient::getTypedVarArrayByTypeName,
"Return a list of the typedVar class instances. Each item represents an item of the counted array in the target memory" )
.def("typedVarArray", &DebugClient::getTypedVarArrayByType,
"Return a list of the typedVar class instances. Each item represents an item of the counted array in the target memory" )
.def("containingRecord", &DebugClient::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", &DebugClient::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( "waitForEvent", &DebugClient::waitForEvent, .def( "waitForEvent", &DebugClient::waitForEvent,
"Wait for events that breaks into the debugger" ) "Wait for events that breaks into the debugger" )
.def( "wrmsr", &DebugClient::setMSR, .def( "wrmsr", &DebugClient::setMSR,
@ -491,6 +505,20 @@ BOOST_PYTHON_MODULE( pykd )
"Set MSR value" ); "Set MSR value" );
python::def( "trace", &changeDebuggerStatus<DEBUG_STATUS_STEP_INTO>, python::def( "trace", &changeDebuggerStatus<DEBUG_STATUS_STEP_INTO>,
"Change debugger status to DEBUG_STATUS_STEP_INTO" ); "Change debugger status to DEBUG_STATUS_STEP_INTO" );
python::def("typedVarList", &getTypedVarListByTypeName,
"Return a list of the typedVar class instances. Each item represents an item of the linked list in the target memory" );
python::def("typedVarList", &getTypedVarListByType,
"Return a list of the typedVar class instances. Each item represents an item of the linked list in the target memory" );
python::def("typedVarArray", &getTypedVarArrayByTypeName,
"Return a list of the typedVar class instances. Each item represents an item of the counted array in the target memory" );
python::def("typedVarArray", &getTypedVarArrayByType,
"Return a list of the typedVar class instances. Each item represents an item of the counted array in the target memory" );
python::def("containingRecord", &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" );
python::def("containingRecord", &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" );
python::def( "waitForEvent", &waitForEvent, python::def( "waitForEvent", &waitForEvent,
"Wait for events that breaks into the debugger" ); "Wait for events that breaks into the debugger" );
python::def( "getNumberProcessors", &getNumberProcessors, python::def( "getNumberProcessors", &getNumberProcessors,

View File

@ -347,12 +347,12 @@ python::list Module::getTypedVarListByType( ULONG64 listHeadAddress, const TypeI
if ( fieldTypeInfo->getName() == ( typeInfo->getName() + "*" ) ) if ( fieldTypeInfo->getName() == ( typeInfo->getName() + "*" ) )
{ {
for( entryAddress = ptrPtr( listHeadAddress ); addr64(entryAddress) != listHeadAddress && entryAddress != NULL; entryAddress = ptrPtr( entryAddress + fieldTypeInfo->getOffset() ) ) for( entryAddress = ptrPtr( listHeadAddress, m_dataSpaces ); addr64(entryAddress) != listHeadAddress && entryAddress != NULL; entryAddress = ptrPtr( entryAddress + fieldTypeInfo->getOffset() ) )
lst.append( getTypedVarByType( typeInfo, entryAddress ) ); lst.append( getTypedVarByType( typeInfo, entryAddress ) );
} }
else else
{ {
for( entryAddress = ptrPtr( listHeadAddress ); addr64(entryAddress) != listHeadAddress && entryAddress != NULL; entryAddress = ptrPtr( entryAddress ) ) for( entryAddress = ptrPtr( listHeadAddress, m_dataSpaces ); addr64(entryAddress) != listHeadAddress && entryAddress != NULL; entryAddress = ptrPtr( entryAddress ) )
lst.append( containingRecordByType( entryAddress, typeInfo, listEntryName ) ); lst.append( containingRecordByType( entryAddress, typeInfo, listEntryName ) );
} }

View File

@ -17,6 +17,7 @@ class BaseTest( unittest.TestCase ):
self.assertTrue( hasattr(pykd, 'addr64') ) self.assertTrue( hasattr(pykd, 'addr64') )
self.assertTrue( hasattr(pykd, 'breakin') ) self.assertTrue( hasattr(pykd, 'breakin') )
self.assertTrue( hasattr(pykd, 'compareMemory') ) self.assertTrue( hasattr(pykd, 'compareMemory') )
self.assertTrue( hasattr(pykd, 'containingRecord') )
self.assertTrue( hasattr(pykd, 'dbgCommand') ) self.assertTrue( hasattr(pykd, 'dbgCommand') )
self.assertTrue( hasattr(pykd, 'dprint') ) self.assertTrue( hasattr(pykd, 'dprint') )
self.assertTrue( hasattr(pykd, 'dprintln') ) self.assertTrue( hasattr(pykd, 'dprintln') )
@ -76,6 +77,8 @@ class BaseTest( unittest.TestCase ):
self.assertTrue( hasattr(pykd, 'startProcess') ) self.assertTrue( hasattr(pykd, 'startProcess') )
self.assertTrue( hasattr(pykd, 'step') ) self.assertTrue( hasattr(pykd, 'step') )
self.assertTrue( hasattr(pykd, 'symbolsPath') ) self.assertTrue( hasattr(pykd, 'symbolsPath') )
self.assertTrue( hasattr(pykd, 'typedVarArray') )
self.assertTrue( hasattr(pykd, 'typedVarList') )
self.assertTrue( hasattr(pykd, 'trace') ) self.assertTrue( hasattr(pykd, 'trace') )
self.assertTrue( hasattr(pykd, 'wrmsr') ) self.assertTrue( hasattr(pykd, 'wrmsr') )
@ -95,7 +98,6 @@ class BaseTest( unittest.TestCase ):
def testOldRemovedApi( self ): def testOldRemovedApi( self ):
""" Branch test: old API 0.0.x what should be removed """ """ Branch test: old API 0.0.x what should be removed """
self.assertFalse( hasattr(pykd, 'containingRecord') )
self.assertFalse( hasattr(pykd, 'dbgModuleClass') ) self.assertFalse( hasattr(pykd, 'dbgModuleClass') )
self.assertFalse( hasattr(pykd, 'dbgStackFrameClass') ) self.assertFalse( hasattr(pykd, 'dbgStackFrameClass') )
self.assertFalse( hasattr(pykd, 'debugEvent') ) self.assertFalse( hasattr(pykd, 'debugEvent') )
@ -104,8 +106,6 @@ class BaseTest( unittest.TestCase ):
self.assertFalse( hasattr(pykd, 'loadPtrs') ) self.assertFalse( hasattr(pykd, 'loadPtrs') )
self.assertFalse( hasattr(pykd, 'reloadModule') ) self.assertFalse( hasattr(pykd, 'reloadModule') )
self.assertFalse( hasattr(pykd, 'sizeof') ) self.assertFalse( hasattr(pykd, 'sizeof') )
self.assertFalse( hasattr(pykd, 'typedVarArray') )
self.assertFalse( hasattr(pykd, 'typedVarList') )
self.assertFalse( hasattr(pykd, 'windbgIn') ) self.assertFalse( hasattr(pykd, 'windbgIn') )
self.assertFalse( hasattr(pykd, 'windbgOut') ) self.assertFalse( hasattr(pykd, 'windbgOut') )
self.assertFalse( hasattr(pykd, 'bp') ) self.assertFalse( hasattr(pykd, 'bp') )

View File

@ -126,6 +126,11 @@ class TypedVarTest( unittest.TestCase ):
self.assertEqual( [1000,2000,3000], [ tv.m_someBaseFiled2 for tv in 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 ] ) self.assertEqual( [1001,2001,3001], [ tv.m_childFiled1 for tv in tvl ] )
tvl1 = target.module.typedVarList( target.module.g_listHead, "listStruct", "listEntry" )
tvl2 = pykd.typedVarList( target.module.g_listHead, target.moduleName + "!listStruct", "listEntry" )
self.assertEqual( tvl1, tvl2 )
def testTypedVarArray(self): def testTypedVarArray(self):
tvl = target.module.typedVarArray( target.module.g_testArray, "structTest", 2 ) tvl = target.module.typedVarArray( target.module.g_testArray, "structTest", 2 )
self.assertEqual( 2, len( tvl ) ) self.assertEqual( 2, len( tvl ) )
@ -137,6 +142,10 @@ class TypedVarTest( unittest.TestCase ):
self.assertEqual( 1, tvl[0].m_field3 ) self.assertEqual( 1, tvl[0].m_field3 )
self.assertEqual( 0, tvl[1].m_field4 ) self.assertEqual( 0, tvl[1].m_field4 )
tvl1 = target.module.typedVarArray( target.module.g_testArray, "structTest", 2 )
tvl2 = pykd.typedVarArray( target.module.g_testArray, target.moduleName + "!structTest", 2 )
self.assertEqual( tvl1, tvl2 )
def testEqual(self): def testEqual(self):
tv1 = target.module.typedVar("g_structTest") tv1 = target.module.typedVar("g_structTest")
tv2 = target.module.typedVar("intMatrix") tv2 = target.module.typedVar("intMatrix")