mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-29 11:53:23 +08:00
[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:
parent
c8aa7b6112
commit
ef857b33d8
@ -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;
|
||||
|
@ -85,12 +85,16 @@ public:
|
||||
|
||||
ULONG64 getCurrentProcess();
|
||||
|
||||
python::list getCurrentStack();
|
||||
|
||||
python::tuple getDebuggeeType();
|
||||
|
||||
ULONG64 getImplicitThread();
|
||||
|
||||
ULONG getExecutionStatus();
|
||||
|
||||
ULONG64 getOffset( const std::wstring symbolname );
|
||||
|
||||
template<ULONG status>
|
||||
void changeDebuggerStatus();
|
||||
|
||||
@ -265,6 +269,8 @@ python::tuple getDebuggeeType();
|
||||
|
||||
ULONG getExecutionStatus();
|
||||
|
||||
ULONG64 getOffset( const std::wstring symbolname );
|
||||
|
||||
bool is64bitSystem();
|
||||
|
||||
bool isKernelDebugging();
|
||||
|
@ -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<DEBUG_STATUS_GO>,
|
||||
"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<DEBUG_STATUS_GO>,
|
||||
"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_<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",
|
||||
python::no_init )
|
||||
//.def( python::init<const TypeInfoPtr&, ULONG64>() )
|
||||
.def("getAddress", &TypedVar::getAddress,
|
||||
"Return virtual address" )
|
||||
.def("sizeof", &TypedVar::getSize,
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
@ -8,6 +8,8 @@ ULONG64 getCurrentProcess();
|
||||
|
||||
ULONG64 getImplicitThread();
|
||||
|
||||
python::list getCurrentStack();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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<typename T>
|
||||
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:
|
||||
|
@ -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 )
|
||||
|
@ -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() )
|
||||
|
||||
|
||||
|
@ -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 };
|
||||
|
Loading…
Reference in New Issue
Block a user