From ef857b33d8a41aec2c618659cc4cbc9b42ffa94b Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Tue, 13 Dec 2011 07:52:04 +0000 Subject: [PATCH] [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 --- pykd/dbgclient.cpp | 19 ++++++++ pykd/dbgclient.h | 6 +++ pykd/dbgext.cpp | 11 ++++- pykd/process.cpp | 32 ++++++++++++++ pykd/process.h | 2 + pykd/typedvar.cpp | 42 +++++++++++++++++- pykd/typedvar.h | 17 +++++++- pykd/typeinfo.cpp | 44 ++++++++++--------- pykd/typeinfo.h | 85 ++++++++++++++++++++++-------------- test/scripts/typedvar.py | 4 ++ test/scripts/typeinfo.py | 9 ++++ test/targetapp/targetapp.cpp | 3 +- 12 files changed, 214 insertions(+), 60 deletions(-) diff --git a/pykd/dbgclient.cpp b/pykd/dbgclient.cpp index e792676..f02d338 100644 --- a/pykd/dbgclient.cpp +++ b/pykd/dbgclient.cpp @@ -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 ) { HRESULT hres; diff --git a/pykd/dbgclient.h b/pykd/dbgclient.h index 45c5855..2514edf 100644 --- a/pykd/dbgclient.h +++ b/pykd/dbgclient.h @@ -85,12 +85,16 @@ public: ULONG64 getCurrentProcess(); + python::list getCurrentStack(); + python::tuple getDebuggeeType(); ULONG64 getImplicitThread(); ULONG getExecutionStatus(); + ULONG64 getOffset( const std::wstring symbolname ); + template void changeDebuggerStatus(); @@ -265,6 +269,8 @@ python::tuple getDebuggeeType(); ULONG getExecutionStatus(); +ULONG64 getOffset( const std::wstring symbolname ); + bool is64bitSystem(); bool isKernelDebugging(); diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 4923dee..bb8e9ea 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -154,12 +154,16 @@ BOOST_PYTHON_MODULE( pykd ) "Find symbol by the target virtual memory offset" ) .def( "getCurrentProcess", &DebugClient::getCurrentProcess, "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, "Return type of the debuggee" ) .def( "getImplicitThread", &getImplicitThread, "Return implicit thread for current process" ) .def( "getExecutionStatus", &DebugClient::getExecutionStatus, "Return information about the execution status of the debugger" ) + .def( "getOffset", &DebugClient::getOffset, + "Return traget virtual address for specified symbol" ) .def( "go", &DebugClient::changeDebuggerStatus, "Change debugger status to DEBUG_STATUS_GO" ) .def( "is64bitSystem", &DebugClient::is64bitSystem, @@ -271,6 +275,8 @@ BOOST_PYTHON_MODULE( pykd ) "Find symbol by the target virtual memory offset" ); python::def( "getCurrentProcess", &getCurrentProcess, "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, "Return type of the debuggee" ); python::def( "getImplicitThread", &getImplicitThread, @@ -279,6 +285,8 @@ BOOST_PYTHON_MODULE( pykd ) "Return full path to the process image that uses pykd" ); python::def( "getExecutionStatus", &getExecutionStatus, "Return information about the execution status of the debugger" ); + python::def( "getOffset", &getOffset, + "Return traget virtual address for specified symbol" ); python::def( "go", &changeDebuggerStatus, "Change debugger status to DEBUG_STATUS_GO" ); python::def( "is64bitSystem", &is64bitSystem, @@ -376,13 +384,14 @@ BOOST_PYTHON_MODULE( pykd ) .def( "name", &TypeInfo::getName ) .def( "size", &TypeInfo::getSize ) .def( "offset", &TypeInfo::getOffset ) + .def( "bitOffset", &TypeInfo::getBitOffset ) + .def( "bitWidth", &TypeInfo::getBitWidth ) .def( "field", &TypeInfo::getField ) .def( "__getattr__", &TypeInfo::getField ); 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( python::init() ) .def("getAddress", &TypedVar::getAddress, "Return virtual address" ) .def("sizeof", &TypedVar::getSize, diff --git a/pykd/process.cpp b/pykd/process.cpp index 85e6905..22d0b56 100644 --- a/pykd/process.cpp +++ b/pykd/process.cpp @@ -46,4 +46,36 @@ getImplicitThread() { /////////////////////////////////////////////////////////////////////////////////// +python::list +DebugClient::getCurrentStack() +{ + HRESULT hres; + + ULONG filledFrames; + std::vector 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(); +} + +/////////////////////////////////////////////////////////////////////////////////// + } \ No newline at end of file diff --git a/pykd/process.h b/pykd/process.h index aeda263..823d739 100644 --- a/pykd/process.h +++ b/pykd/process.h @@ -8,6 +8,8 @@ ULONG64 getCurrentProcess(); ULONG64 getImplicitThread(); +python::list getCurrentStack(); + /////////////////////////////////////////////////////////////////////////////////// } diff --git a/pykd/typedvar.cpp b/pykd/typedvar.cpp index 8c9c440..e9cc7f8 100644 --- a/pykd/typedvar.cpp +++ b/pykd/typedvar.cpp @@ -29,13 +29,19 @@ TypedVarPtr TypedVar::getTypedVar( IDebugClient4 *client, const TypeInfoPtr& t return tv; } - if ( typeInfo->isUserDefined() ) + if ( typeInfo->isUserDefined() ) { tv.reset( new UdtTypedVar( client, typeInfo, offset ) ); 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; } @@ -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 \ No newline at end of file diff --git a/pykd/typedvar.h b/pykd/typedvar.h index afbbfb2..0a7a606 100644 --- a/pykd/typedvar.h +++ b/pykd/typedvar.h @@ -55,8 +55,6 @@ public: protected: - //TypedVar ( const TypeInfoPtr& typeInfo, ULONG64 offset ); - TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ); 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 diff --git a/pykd/typeinfo.cpp b/pykd/typeinfo.cpp index 6f102ce..bc1f27f 100644 --- a/pykd/typeinfo.cpp +++ b/pykd/typeinfo.cpp @@ -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 ) { 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 ); if ( typeSym->getSymTag() == SymTagData ) + { + if ( typeSym->getLocType() == LocIsBitField ) + { + return TypeInfoPtr( new BitFieldTypeInfo(typeSym) ); + } + typeSym = typeSym->getType(); + } return getTypeInfo( typeSym ); } 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() ); } - 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(); } ///////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/typeinfo.h b/pykd/typeinfo.h index f8b1d7e..f9f6b35 100644 --- a/pykd/typeinfo.h +++ b/pykd/typeinfo.h @@ -35,7 +35,9 @@ public: 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() { return false; @@ -53,6 +55,10 @@ public: return false; } + virtual bool isBitField() { + return false; + } + virtual ULONG getCount() { throw DbgException( "there is no element" ); } @@ -61,6 +67,15 @@ public: throw DbgException( "there is no element" ); } + virtual ULONG getBitOffset() { + return 0; + } + + virtual ULONG getBitWidth() { + return 8 * getSize(); + } + + ULONG getOffset() { 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 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 { public: diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index d907615..35b3a38 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -68,3 +68,7 @@ class TypedVarTest( unittest.TestCase ): off2 = target.module.offset( "g_structTest" ) tv = target.module.containingRecord( off2 + off1, "structTest", "m_field2" ) self.assertEqual( True, tv.m_field2 ) + + def testBitField(self): + tv = target.module.typedVar("g_structWithBits") + self.assertEqual( 4, tv.m_bit0_4 ) diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py index 641fd21..1294f5a 100644 --- a/test/scripts/typeinfo.py +++ b/test/scripts/typeinfo.py @@ -68,4 +68,13 @@ class TypeInfoTest( unittest.TestCase ): ti1 = target.module.type( "structTest" ) self.assertEqual( 20, ti1.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() ) + diff --git a/test/targetapp/targetapp.cpp b/test/targetapp/targetapp.cpp index 9a30f20..de61839 100644 --- a/test/targetapp/targetapp.cpp +++ b/test/targetapp/targetapp.cpp @@ -25,6 +25,7 @@ struct structWithBits { ULONG m_bit6_7 : 2; }; + union unionTest { ULONG m_value; structWithBits m_bits; @@ -46,7 +47,7 @@ struct structTest { structTest* m_field4; }; -structWithBits g_structWithBits = {0}; +structWithBits g_structWithBits = { 4, 1, 3}; structTest g_structTest = { 0, 500, true, 1, NULL }; structTest g_structTest1 = { 0, 500, true, 1, &g_structTest };