[0.1.x] added : getCurrentStack routine

[0.1.x] added : getOffset routine
[0.1.x] added : support for working with bit fields


git-svn-id: https://pykd.svn.codeplex.com/svn@72292 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\kernelnet_cp 2011-12-13 07:52:04 +00:00 committed by Mikhail I. Izmestev
parent c8aa7b6112
commit ef857b33d8
12 changed files with 214 additions and 60 deletions

View File

@ -266,6 +266,25 @@ std::string findSymbol( ULONG64 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 );
}
///////////////////////////////////////////////////////////////////////////////////
void DebugClient::setExecutionStatus( ULONG status ) void DebugClient::setExecutionStatus( ULONG status )
{ {
HRESULT hres; HRESULT hres;

View File

@ -85,12 +85,16 @@ public:
ULONG64 getCurrentProcess(); ULONG64 getCurrentProcess();
python::list getCurrentStack();
python::tuple getDebuggeeType(); python::tuple getDebuggeeType();
ULONG64 getImplicitThread(); ULONG64 getImplicitThread();
ULONG getExecutionStatus(); ULONG getExecutionStatus();
ULONG64 getOffset( const std::wstring symbolname );
template<ULONG status> template<ULONG status>
void changeDebuggerStatus(); void changeDebuggerStatus();
@ -265,6 +269,8 @@ python::tuple getDebuggeeType();
ULONG getExecutionStatus(); ULONG getExecutionStatus();
ULONG64 getOffset( const std::wstring symbolname );
bool is64bitSystem(); bool is64bitSystem();
bool isKernelDebugging(); bool isKernelDebugging();

View File

@ -154,12 +154,16 @@ BOOST_PYTHON_MODULE( pykd )
"Find symbol by the target virtual memory offset" ) "Find symbol by the target virtual memory offset" )
.def( "getCurrentProcess", &DebugClient::getCurrentProcess, .def( "getCurrentProcess", &DebugClient::getCurrentProcess,
"Return pointer to current process's block" ) "Return pointer to current process's block" )
.def( "getCurrentStack", &DebugClient::getCurrentStack,
"Return a current stack as a list of stackFrame objects" )
.def( "getDebuggeeType", &DebugClient::getDebuggeeType, .def( "getDebuggeeType", &DebugClient::getDebuggeeType,
"Return type of the debuggee" ) "Return type of the debuggee" )
.def( "getImplicitThread", &getImplicitThread, .def( "getImplicitThread", &getImplicitThread,
"Return implicit thread for current process" ) "Return implicit thread for current process" )
.def( "getExecutionStatus", &DebugClient::getExecutionStatus, .def( "getExecutionStatus", &DebugClient::getExecutionStatus,
"Return information about the execution status of the debugger" ) "Return information about the execution status of the debugger" )
.def( "getOffset", &DebugClient::getOffset,
"Return traget virtual address for specified symbol" )
.def( "go", &DebugClient::changeDebuggerStatus<DEBUG_STATUS_GO>, .def( "go", &DebugClient::changeDebuggerStatus<DEBUG_STATUS_GO>,
"Change debugger status to DEBUG_STATUS_GO" ) "Change debugger status to DEBUG_STATUS_GO" )
.def( "is64bitSystem", &DebugClient::is64bitSystem, .def( "is64bitSystem", &DebugClient::is64bitSystem,
@ -271,6 +275,8 @@ BOOST_PYTHON_MODULE( pykd )
"Find symbol by the target virtual memory offset" ); "Find symbol by the target virtual memory offset" );
python::def( "getCurrentProcess", &getCurrentProcess, python::def( "getCurrentProcess", &getCurrentProcess,
"Return pointer to current process's block" ); "Return pointer to current process's block" );
python::def( "getCurrentStack", &getCurrentStack,
"Return a current stack as a list of stackFrame objects" );
python::def( "getDebuggeeType", &getDebuggeeType, python::def( "getDebuggeeType", &getDebuggeeType,
"Return type of the debuggee" ); "Return type of the debuggee" );
python::def( "getImplicitThread", &getImplicitThread, python::def( "getImplicitThread", &getImplicitThread,
@ -279,6 +285,8 @@ BOOST_PYTHON_MODULE( pykd )
"Return full path to the process image that uses pykd" ); "Return full path to the process image that uses pykd" );
python::def( "getExecutionStatus", &getExecutionStatus, python::def( "getExecutionStatus", &getExecutionStatus,
"Return information about the execution status of the debugger" ); "Return information about the execution status of the debugger" );
python::def( "getOffset", &getOffset,
"Return traget virtual address for specified symbol" );
python::def( "go", &changeDebuggerStatus<DEBUG_STATUS_GO>, python::def( "go", &changeDebuggerStatus<DEBUG_STATUS_GO>,
"Change debugger status to DEBUG_STATUS_GO" ); "Change debugger status to DEBUG_STATUS_GO" );
python::def( "is64bitSystem", &is64bitSystem, python::def( "is64bitSystem", &is64bitSystem,
@ -376,13 +384,14 @@ BOOST_PYTHON_MODULE( pykd )
.def( "name", &TypeInfo::getName ) .def( "name", &TypeInfo::getName )
.def( "size", &TypeInfo::getSize ) .def( "size", &TypeInfo::getSize )
.def( "offset", &TypeInfo::getOffset ) .def( "offset", &TypeInfo::getOffset )
.def( "bitOffset", &TypeInfo::getBitOffset )
.def( "bitWidth", &TypeInfo::getBitWidth )
.def( "field", &TypeInfo::getField ) .def( "field", &TypeInfo::getField )
.def( "__getattr__", &TypeInfo::getField ); .def( "__getattr__", &TypeInfo::getField );
python::class_<TypedVar, TypedVarPtr, python::bases<intBase>, boost::noncopyable >("typedVar", python::class_<TypedVar, TypedVarPtr, python::bases<intBase>, boost::noncopyable >("typedVar",
"Class of non-primitive type object, child class of typeClass. Data from target is copied into object instance", "Class of non-primitive type object, child class of typeClass. Data from target is copied into object instance",
python::no_init ) python::no_init )
//.def( python::init<const TypeInfoPtr&, ULONG64>() )
.def("getAddress", &TypedVar::getAddress, .def("getAddress", &TypedVar::getAddress,
"Return virtual address" ) "Return virtual address" )
.def("sizeof", &TypedVar::getSize, .def("sizeof", &TypedVar::getSize,

View File

@ -46,4 +46,36 @@ getImplicitThread() {
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
python::list
DebugClient::getCurrentStack()
{
HRESULT hres;
ULONG filledFrames;
std::vector<DEBUG_STACK_FRAME> frames(1000);
hres = m_control->GetStackTrace( 0, 0, 0, &frames[0], 1000, &filledFrames );
if ( FAILED( hres ) )
throw DbgException( "IDebugControl::GetStackTrace failed" );
python::list frameList;
for ( ULONG i = 0; i < filledFrames; ++i )
{
python::object frameObj( frames[i] );
frameList.append( frameObj );
}
return frameList;
}
python::list
getCurrentStack()
{
return g_dbgClient->getCurrentStack();
}
///////////////////////////////////////////////////////////////////////////////////
} }

View File

@ -8,6 +8,8 @@ ULONG64 getCurrentProcess();
ULONG64 getImplicitThread(); ULONG64 getImplicitThread();
python::list getCurrentStack();
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
} }

View File

@ -29,13 +29,19 @@ TypedVarPtr TypedVar::getTypedVar( IDebugClient4 *client, const TypeInfoPtr& t
return tv; return tv;
} }
if ( typeInfo->isUserDefined() ) if ( typeInfo->isUserDefined() )
{ {
tv.reset( new UdtTypedVar( client, typeInfo, offset ) ); tv.reset( new UdtTypedVar( client, typeInfo, offset ) );
return tv; return tv;
} }
throw DbgException( "can not get field" ); if ( typeInfo->isBitField() )
{
tv.reset( new BitFieldVar( client, typeInfo, offset ) );
return tv;
}
throw DbgException( "can not create typedVar for this type" );
return tv; return tv;
} }
@ -123,4 +129,36 @@ UdtTypedVar::getField( const std::string &fieldName )
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
BaseTypeVariant BitFieldVar::getValue()
{
ULONG64 val = 0;
HRESULT hres;
hres = m_dataSpaces->ReadVirtual( m_offset, &val, m_typeInfo->getSize(), NULL );
if ( FAILED( hres ) )
throw MemoryException( m_offset, false );
val >>= m_typeInfo->getBitOffset();
val &= m_typeInfo->getBitWidth();
switch ( m_typeInfo->getSize() )
{
case 1:
return (ULONG)*(PUCHAR)&val;
case 2:
return (ULONG)*(PUSHORT)&val;
case 4:
return *(PULONG)&val;
case 8:
return *(PULONG64)&val;
}
throw DbgException( "failed get value " );
}
///////////////////////////////////////////////////////////////////////////////////
} // end pykd namespace } // end pykd namespace

View File

@ -55,8 +55,6 @@ public:
protected: protected:
//TypedVar ( const TypeInfoPtr& typeInfo, ULONG64 offset );
TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ); TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset );
virtual BaseTypeVariant getValue() { virtual BaseTypeVariant getValue() {
@ -146,4 +144,19 @@ public:
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
class BitFieldVar: public TypedVar {
public:
BitFieldVar( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ) : TypedVar(client, typeInfo, offset){}
virtual std::string print() {
return intBase::str();
}
virtual BaseTypeVariant getValue();
};
///////////////////////////////////////////////////////////////////////////////////
} // namespace pykd } // namespace pykd

View File

@ -30,8 +30,6 @@ TypeInfoPtr TypeInfo::getTypeInfo( pyDia::SymbolPtr &typeSym )
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
//static const boost::regex arrayMatch("^(.*)\\[(\\d+)\\]$");
TypeInfoPtr TypeInfo::getTypeInfo( pyDia::SymbolPtr &symScope, const std::string &symName ) TypeInfoPtr TypeInfo::getTypeInfo( pyDia::SymbolPtr &symScope, const std::string &symName )
{ {
size_t pos = symName.find_first_of( "*[" ); size_t pos = symName.find_first_of( "*[" );
@ -45,27 +43,19 @@ TypeInfoPtr TypeInfo::getTypeInfo( pyDia::SymbolPtr &symScope, const std::strin
pyDia::SymbolPtr typeSym = symScope->getChildByName( symName ); pyDia::SymbolPtr typeSym = symScope->getChildByName( symName );
if ( typeSym->getSymTag() == SymTagData ) if ( typeSym->getSymTag() == SymTagData )
{
if ( typeSym->getLocType() == LocIsBitField )
{
return TypeInfoPtr( new BitFieldTypeInfo(typeSym) );
}
typeSym = typeSym->getType(); typeSym = typeSym->getType();
}
return getTypeInfo( typeSym ); return getTypeInfo( typeSym );
} }
return getComplexType( symScope, symName ); return getComplexType( symScope, symName );
//if ( symName[ symName.size() - 1 ] == '*' )
// return TypeInfoPtr( new PointerTypeInfo( symScope,symName.substr( 0, symName.size() - 1 ) ) );
//boost::cmatch matchResult;
//if ( boost::regex_match( symName.c_str(), matchResult, arrayMatch ) )
//{
// std::string sym = std::string( matchResult[1].first, matchResult[1].second );
// return TypeInfoPtr( new ArrayTypeInfo( symScope, sym, std::atoi( matchResult[2].first ) ) );
//}
//throw DbgException( "type name invalid" );
} }
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
@ -134,12 +124,24 @@ TypeInfo::getBaseTypeInfo( pyDia::SymbolPtr &symbol )
return getBaseTypeInfo( sstr.str() ); return getBaseTypeInfo( sstr.str() );
} }
TypeInfoPtr ptr = getBaseTypeInfo( symName ); return getBaseTypeInfo( symName );
}
if ( ptr == 0 ) /////////////////////////////////////////////////////////////////////////////////////
ptr = TypeInfoPtr( new BaseTypeInfo( symbol ) );
return ptr; BitFieldTypeInfo::BitFieldTypeInfo( pyDia::SymbolPtr &symbol )
{
m_bitWidth = (ULONG)symbol->getSize();
m_bitPos = (ULONG)symbol->getBitPosition();
TypeInfoPtr typeInfo = TypeInfo::getBaseTypeInfo( symbol->getType() );
m_size = (ULONG)typeInfo->getSize();
std::stringstream sstr;
sstr << typeInfo->getName() << ":" << (ULONG)m_bitWidth;
m_name = sstr.str();
} }
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////

View File

@ -35,7 +35,9 @@ public:
virtual ULONG getSize() = 0; virtual ULONG getSize() = 0;
virtual TypeInfoPtr getField( const std::string &fieldName ) = 0; virtual TypeInfoPtr getField( const std::string &fieldName ) {
throw DbgException( "there is no fields" );
}
virtual bool isBasicType() { virtual bool isBasicType() {
return false; return false;
@ -53,6 +55,10 @@ public:
return false; return false;
} }
virtual bool isBitField() {
return false;
}
virtual ULONG getCount() { virtual ULONG getCount() {
throw DbgException( "there is no element" ); throw DbgException( "there is no element" );
} }
@ -61,6 +67,15 @@ public:
throw DbgException( "there is no element" ); throw DbgException( "there is no element" );
} }
virtual ULONG getBitOffset() {
return 0;
}
virtual ULONG getBitWidth() {
return 8 * getSize();
}
ULONG getOffset() { ULONG getOffset() {
return m_offset; return m_offset;
} }
@ -84,38 +99,6 @@ protected:
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
class BaseTypeInfo : public TypeInfo
{
public:
BaseTypeInfo( pyDia::SymbolPtr &symbol ) :
m_dia( symbol )
{}
protected:
virtual std::string getName() {
return m_dia->getBasicTypeName( m_dia->getBaseType() );
}
virtual ULONG getSize() {
return (ULONG)m_dia->getSize();
}
virtual TypeInfoPtr getField( const std::string &fieldName ) {
throw DbgException( "there is no such field" );
}
virtual bool isBasicType() {
return true;
}
pyDia::SymbolPtr m_dia;
};
///////////////////////////////////////////////////////////////////////////////////
template<typename T> template<typename T>
class TypeInfoWrapper : public TypeInfo class TypeInfoWrapper : public TypeInfo
{ {
@ -148,6 +131,42 @@ private:
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
class BitFieldTypeInfo : public TypeInfo
{
public:
BitFieldTypeInfo( pyDia::SymbolPtr &symbol );
virtual std::string getName() {
return m_name;
}
virtual ULONG getSize() {
return m_size;
}
virtual bool isBitField() {
return true;
}
virtual ULONG getBitOffset() {
return m_bitPos;
}
virtual ULONG getBitWidth() {
return m_bitWidth;
}
private:
ULONG m_size;
ULONG m_bitWidth;
ULONG m_bitPos;
std::string m_name;
};
///////////////////////////////////////////////////////////////////////////////////
class UdtTypeInfo : public TypeInfo class UdtTypeInfo : public TypeInfo
{ {
public: public:

View File

@ -68,3 +68,7 @@ class TypedVarTest( unittest.TestCase ):
off2 = target.module.offset( "g_structTest" ) off2 = target.module.offset( "g_structTest" )
tv = target.module.containingRecord( off2 + off1, "structTest", "m_field2" ) tv = target.module.containingRecord( off2 + off1, "structTest", "m_field2" )
self.assertEqual( True, tv.m_field2 ) self.assertEqual( True, tv.m_field2 )
def testBitField(self):
tv = target.module.typedVar("g_structWithBits")
self.assertEqual( 4, tv.m_bit0_4 )

View File

@ -68,4 +68,13 @@ class TypeInfoTest( unittest.TestCase ):
ti1 = target.module.type( "structTest" ) ti1 = target.module.type( "structTest" )
self.assertEqual( 20, ti1.size() ) self.assertEqual( 20, ti1.size() )
self.assertEqual( pykd.ptrSize(), target.module.type("structTest**").size() ) self.assertEqual( pykd.ptrSize(), target.module.type("structTest**").size() )
def testBitField( self ):
ti = target.module.type( "g_structWithBits" )
self.assertEqual( 0, ti.m_bit6_7.offset() )
self.assertEqual( 4, ti.m_bit6_7.size() )
self.assertEqual( "ULong:2", ti.m_bit6_7.name() )
self.assertEqual( 2, ti.m_bit6_7.bitWidth() )
self.assertEqual( 6, ti.m_bit6_7.bitOffset() )

View File

@ -25,6 +25,7 @@ struct structWithBits {
ULONG m_bit6_7 : 2; ULONG m_bit6_7 : 2;
}; };
union unionTest { union unionTest {
ULONG m_value; ULONG m_value;
structWithBits m_bits; structWithBits m_bits;
@ -46,7 +47,7 @@ struct structTest {
structTest* m_field4; structTest* m_field4;
}; };
structWithBits g_structWithBits = {0}; structWithBits g_structWithBits = { 4, 1, 3};
structTest g_structTest = { 0, 500, true, 1, NULL }; structTest g_structTest = { 0, 500, true, 1, NULL };
structTest g_structTest1 = { 0, 500, true, 1, &g_structTest }; structTest g_structTest1 = { 0, 500, true, 1, &g_structTest };