From dfbbc434d33fc53ffda8a60884de4643b3b148d8 Mon Sep 17 00:00:00 2001 From: "SND\\EreTIk_cp" Date: Sat, 19 Feb 2011 15:45:04 +0000 Subject: [PATCH] [+] offset into TypeInfo (for fields) [+] method TypeInfo::build() for recursive typeClass building [+] virtual method printSelf() for address value for typedVarClass [~] remove trailing blanks, tabs replaced by spaces git-svn-id: https://pykd.svn.codeplex.com/svn@61693 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgext.cpp | 3 +- pykd/dbgmem.cpp | 34 +++--- pykd/dbgtype.cpp | 272 ++++++++++++++++++++++++++--------------------- pykd/dbgtype.h | 77 +++++++++----- 4 files changed, 224 insertions(+), 162 deletions(-) diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 14cf40e..6894df3 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -153,6 +153,7 @@ BOOST_PYTHON_MODULE( pykd ) boost::python::def( "setProcessorMode", &setProcessorMode ); boost::python::class_ >( "typeClass" ) .def("sizeof", &typeClass::size ) + .def("offset", &typeClass::getOffset ) .def("__str__", &typeClass::print); boost::python::class_, boost::shared_ptr >( "typedVarClass" ) .def("getAddress", &typedVarClass::getAddress ); @@ -168,7 +169,7 @@ BOOST_PYTHON_MODULE( pykd ) "ext", "windbg extension", boost::python::init( boost::python::args("path"), "__init__ dbgExtensionClass" ) ) - .def("call", &dbgExtensionClass::call ); + .def("call", &dbgExtensionClass::call ); boost::python::class_( "dbgStackFrameClass", "dbgStackFrameClass" ) .def_readonly( "instructionOffset", &dbgStackFrameClass::InstructionOffset ) .def_readonly( "returnOffset", &dbgStackFrameClass::ReturnOffset ) diff --git a/pykd/dbgmem.cpp b/pykd/dbgmem.cpp index dde15a7..47f9cb8 100644 --- a/pykd/dbgmem.cpp +++ b/pykd/dbgmem.cpp @@ -534,10 +534,10 @@ isOffsetValid( ULONG64 addr ) HRESULT hres; try { - + // нужно подавить возможный вывод в консоль об отсутствующей странице памяти OutputReader outputReader( dbgExt->client ); - + ULONG offsetInfo; hres = @@ -548,23 +548,23 @@ isOffsetValid( ULONG64 addr ) &offsetInfo, sizeof( offsetInfo ), NULL ); - + if ( FAILED( hres ) ) - throw DbgException( "IDebugDataSpace4::GetOffsetInformation failed" ); - - return offsetInfo != DEBUG_VSOURCE_INVALID; + throw DbgException( "IDebugDataSpace4::GetOffsetInformation failed" ); + + return offsetInfo != DEBUG_VSOURCE_INVALID; - } - catch( std::exception &e ) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); - } - catch(...) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); - } - - return false; + } + catch( std::exception &e ) + { + dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); + } + catch(...) + { + dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); + } + + return false; } /////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/dbgtype.cpp b/pykd/dbgtype.cpp index 536a6d5..ce57734 100644 --- a/pykd/dbgtype.cpp +++ b/pykd/dbgtype.cpp @@ -19,35 +19,34 @@ loadTypedVar( const std::string &moduleName, const std::string &typeName, ULONG6 return TypeInfo::get( moduleName, typeName ).load( address ); } -///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// ULONG sizeofType( const std::string &moduleName, const std::string &typeName ) { - HRESULT hres; - ULONG typeSize = ~0; + HRESULT hres; + ULONG typeSize = ~0; try { - + ULONG64 moduleBase; hres = dbgExt->symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugSymbol::GetModuleByModuleName failed" ); - + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetModuleByModuleName failed" ); + typeSize = (ULONG)TypeInfo::get( moduleName, typeName ).size(); - } - - catch( std::exception &e ) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); - } - catch(...) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); - } - - return typeSize; + } + catch( std::exception &e ) + { + dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); + } + catch(...) + { + dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); + } + + return typeSize; } ///////////////////////////////////////////////////////////////////////////////// @@ -55,38 +54,37 @@ sizeofType( const std::string &moduleName, const std::string &typeName ) boost::python::object containingRecord( ULONG64 address, const std::string &moduleName, const std::string &typeName, const std::string &fieldName ) { - HRESULT hres; + HRESULT hres; try { ULONG64 moduleBase; - + hres = dbgExt->symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugSymbol::GetModuleByModuleName failed" ); - + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetModuleByModuleName failed" ); + ULONG typeId; hres = dbgExt->symbols->GetTypeId( moduleBase, typeName.c_str(), &typeId ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugSymbol::GetTypeId failed" ); - + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetTypeId failed" ); + ULONG fieldTypeId; ULONG fieldOffset; hres = dbgExt->symbols3->GetFieldTypeAndOffset( moduleBase, typeId, fieldName.c_str(), &fieldTypeId, &fieldOffset ); return TypeInfo::get( moduleName, typeName ).load( address - fieldOffset ); - } - - catch( std::exception &e ) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); - } - catch(...) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); - } - - return boost::python::object(); + } + catch( std::exception &e ) + { + dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); + } + catch(...) + { + dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); + } + + return boost::python::object(); } ///////////////////////////////////////////////////////////////////////////////// @@ -96,13 +94,7 @@ getTypeClass( const std::string &moduleName, const std::string &typeName ) { try { - boost::shared_ptr ptr( - new typeClass( TypeInfo::get( moduleName, typeName )) - ); - boost::python::object var( ptr ); - ptr->setPyObj(var); - - return var; + return TypeInfo::get( moduleName, typeName ).build(); } catch( std::exception &e ) { @@ -232,14 +224,14 @@ TypeInfo::TypeInfoMap TypeInfo::g_typeInfoCache; const TypeInfo& TypeInfo::get( const std::string &moduleName, const std::string &typeName ) -{ +{ TypeInfoMap::iterator findIt = g_typeInfoCache.find( TypeName( moduleName, typeName ) ); - + if ( findIt != g_typeInfoCache.end() ) return findIt->second; - + TypeInfo typeInfo( moduleName, typeName ); - + return g_typeInfoCache.insert( std::make_pair( TypeName( moduleName, typeName ), typeInfo) ).first->second; } @@ -264,41 +256,41 @@ TypeInfo::setupBaseType() TypeInfo::TypeInfo( const std::string &moduleName, const std::string &typeName ) { HRESULT hres; - + m_typeName = typeName; m_size = 0; m_baseType = false; m_pointer = false; - + m_offset = 0; try { - + if ( typeName.find("*") < typeName.size() ) { m_pointer = true; m_size = ptrSize(); return; } - + m_baseType = isBaseType( typeName ); - if ( m_baseType ) - { + if ( m_baseType ) + { setupBaseType(); return; - } + } ULONG64 moduleBase = 0; hres = dbgExt->symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugSymbol::GetModuleByModuleName failed" ); - + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetModuleByModuleName failed" ); + ULONG typeId = 0; hres = dbgExt->symbols->GetTypeId( moduleBase, m_typeName.c_str(), &typeId ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugSymbol::GetTypeId failed" ); - - hres = dbgExt->symbols->GetTypeSize( moduleBase, typeId, &m_size ); if ( FAILED( hres ) ) - throw DbgException( "IDebugSymbol::GetTypeSize failed" ); + throw DbgException( "IDebugSymbol::GetTypeId failed" ); + + hres = dbgExt->symbols->GetTypeSize( moduleBase, typeId, &m_size ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetTypeSize failed" ); for ( ULONG i = 0; ; ++i ) { @@ -311,41 +303,76 @@ TypeInfo::TypeInfo( const std::string &moduleName, const std::string &typeName ULONG fieldTypeId; ULONG fieldOffset; hres = dbgExt->symbols3->GetFieldTypeAndOffset( moduleBase, typeId, fieldName, &fieldTypeId, &fieldOffset ); - + if ( FAILED( hres ) ) throw DbgException( "IDebugSymbol3::GetFieldTypeAndOffset failed" ); - + ULONG fieldSize; - hres = dbgExt->symbols->GetTypeSize( moduleBase, fieldTypeId, &fieldSize ); + hres = dbgExt->symbols->GetTypeSize( moduleBase, fieldTypeId, &fieldSize ); if ( FAILED( hres ) ) - throw DbgException( "IDebugSymbol::GetTypeSize failed" ); - + throw DbgException( "IDebugSymbol::GetTypeSize failed" ); + char fieldTypeName[100]; hres = dbgExt->symbols->GetTypeName( moduleBase, fieldTypeId, fieldTypeName, sizeof(fieldTypeName), NULL ); - + std::string fieldTypeNameStr( fieldTypeName ); if ( fieldTypeNameStr == "__unnamed" || fieldTypeNameStr.find("") < fieldTypeNameStr.size() ) continue; - + m_fields.push_back( TypeField( fieldName, get(moduleName, fieldTypeName), fieldSize, fieldOffset ) ); - } - + } + } + catch( std::exception &e ) + { + dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); + } + catch(...) + { + dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); } - catch( std::exception &e ) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); - } - catch(...) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); - } } ///////////////////////////////////////////////////////////////////////////////// boost::python::object -TypeInfo::load( ULONG64 addr ) const +TypeInfo::build( ULONG offset /* = 0 */ ) const +{ + boost::shared_ptr ptr( new typeClass( *this ) ); + boost::python::object var( ptr ); + ptr->setPyObj( var ); + ptr->getTypeInfo().setOffset(offset); + + TypeFieldList::const_iterator field = m_fields.begin(); + for ( field = m_fields.begin(); field != m_fields.end(); ++field ) + { + + if ( field->size == field->type.size() ) + { + var.attr( field->name.c_str() ) = + field->type.build( offset + field->offset ); + } + else + { + boost::python::dict arr; + + for ( unsigned int i = 0; i < field->size / field->type.size(); ++i ) + { + const ULONG locOffset = field->offset + i * (ULONG)field->type.size(); + arr[i] = field->type.build( offset + locOffset ); + } + + var.attr( field->name.c_str() ) = arr; + } + } + + return var; +} + +///////////////////////////////////////////////////////////////////////////////// + +boost::python::object +TypeInfo::load( ULONG64 addr, ULONG offset /* = 0 */ ) const { if ( !isOffsetValid( addr) ) return boost::python::object(); @@ -355,10 +382,11 @@ TypeInfo::load( ULONG64 addr ) const if ( m_baseType ) return loadBaseType( addr ); - + boost::shared_ptr ptr( new typedVarClass( *this, addr ) ); boost::python::object var( ptr ); ptr->setPyObj( var ); + ptr->getTypeInfo().setOffset(offset); TypeFieldList::const_iterator field = m_fields.begin(); for ( field = m_fields.begin(); field != m_fields.end(); ++field ) @@ -366,19 +394,22 @@ TypeInfo::load( ULONG64 addr ) const if ( field->size == field->type.size() ) { - var.attr( field->name.c_str() ) = field->type.load( addr + field->offset ); - + var.attr( field->name.c_str() ) = + field->type.load( addr + field->offset, offset + field->offset ); } else { boost::python::dict arr; - + for ( unsigned int i = 0; i < field->size / field->type.size(); ++i ) - arr[i] = field->type.load( addr + field->offset + i * field->type.size() ); - - var.attr( field->name.c_str() ) = arr; - } - } + { + const ULONG locOffset = field->offset + i * (ULONG)field->type.size(); + arr[i] = field->type.load( addr + locOffset, offset + locOffset ); + } + + var.attr( field->name.c_str() ) = arr; + } + } return var; } @@ -392,20 +423,20 @@ isBaseType( const std::string &typeName ) { if ( typeName == basicTypeNames[i] ) return true; - + if ( typeName == ( std::string( basicTypeNames[i] ) + "*" ) ) return true; - + if ( typeName == ( std::string( basicTypeNames[i] ) + "[]" ) ) return true; - + if ( typeName == ( std::string( basicTypeNames[i] ) + "*[]" ) ) return true; } - - return false; + + return false; } - + ///////////////////////////////////////////////////////////////////////////////// boost::python::object @@ -415,17 +446,17 @@ TypeInfo::loadBaseType( ULONG64 address ) const { if ( m_typeName == basicTypeNames[i] ) return basicTypeLoaders[i]( address, m_size ); - + if ( m_typeName == ( std::string( basicTypeNames[i] ) + "*" ) ) return valueLoader( address, ptrSize() ); - + if ( m_typeName == ( std::string( basicTypeNames[i] ) + "[]" ) ) return basicTypeLoaders[i]( address, m_size ); - + if ( m_typeName == ( std::string( basicTypeNames[i] ) + "*[]" ) ) - return valueLoader( address, ptrSize() ); + return valueLoader( address, ptrSize() ); } - + return boost::python::object(); } @@ -444,16 +475,16 @@ valueLoader( ULONG64 address, ULONG size ) else { boost::python::dict arr; - + for ( unsigned int i = 0; i < size / sizeof(valType); ++i ) { - valType v = 0; + valType v = 0; if ( !loadMemory( address + i * sizeof(valType), &v, sizeof(v) ) ) return boost::python::object(); - + arr[i] = boost::python::long_( (unsigned __int64)v ); - } - + } + return arr; } @@ -466,14 +497,17 @@ std::string typeClass::print() const { stringstream sstr; - sstr << getTypeInfo().name() << std::endl; + sstr << getTypeInfo().name() << " "; + printSelf(sstr); + sstr << std::endl; TypeInfo::TypeFieldList::const_iterator itField = getTypeInfo().getFields().begin(); while (itField != getTypeInfo().getFields().end()) { - sstr << "\t" << hex << "+" << itField->offset; - sstr << " " << itField->name << " "; + sstr << "\t" << hex << "+" << itField->offset << " "; + sstr << itField->type.name() << " "; + sstr << itField->name << " "; printField(*itField, sstr); @@ -495,7 +529,7 @@ typedVarClass::printField(const TypeInfo::TypeField &field, stringstream &sstr) else { boost::python::object attr = getPyObj().attr( field.name.c_str() ); - + if ( field.size == field.type.size() ) { if ( attr.ptr() == Py_None ) @@ -505,9 +539,9 @@ typedVarClass::printField(const TypeInfo::TypeField &field, stringstream &sstr) else { unsigned __int64 val = boost::python::extract( attr ); - + sstr << hex << "0x" << val; - + if ( field.type.name() == "char*" ) { char buf[0x100]; @@ -522,20 +556,20 @@ typedVarClass::printField(const TypeInfo::TypeField &field, stringstream &sstr) if ( loadWStrToBuffer( val, wbuf, sizeof(wbuf) ) ) { char mbBuf[0x100] = { 0 }; - + WideCharToMultiByte( CP_ACP, 0, wbuf, wcslen(wbuf)+1, mbBuf, sizeof(mbBuf), NULL, NULL ); - + sstr << " (" << mbBuf << " )"; } else - sstr << " ( read string error )"; + sstr << " ( read string error )"; } else { sstr << dec << " ( " << val << " )"; } - } - } + } + } else { for ( size_t i = 0; i < field.size/field.type.size(); ++i ) diff --git a/pykd/dbgtype.h b/pykd/dbgtype.h index 1b5147d..d3c8893 100644 --- a/pykd/dbgtype.h +++ b/pykd/dbgtype.h @@ -38,11 +38,11 @@ public: template< typename TTypeInfo> struct TypeFieldT { - ULONG size; + ULONG size; ULONG offset; - TTypeInfo type; + TTypeInfo type; std::string name; - + TypeFieldT( const std::string &name_, const TTypeInfo &type_, ULONG size_, ULONG offset_ ) : name( name_ ), size( size_ ), @@ -65,12 +65,12 @@ public: if ( typeName.module < module ) return true; - + if ( typeName.module > module ) return false; - - return typeName.symbol < symbol; - } + + return typeName.symbol < symbol; + } }; @@ -85,46 +85,55 @@ public: TypeInfo() : m_size( 0 ), m_baseType( false ), - m_pointer( false ) + m_pointer( false ), + m_offset(0) {} - + TypeInfo( const std::string &moduleName, const std::string &typeName ); - + boost::python::object - load( ULONG64 addr ) const; - + load( ULONG64 addr, ULONG offset = 0 ) const; + + boost::python::object + build( ULONG offset = 0 ) const; + + ULONG64 size() const { return m_size; } - + const std::string& name() const { return m_typeName; } - + static const TypeInfo& get( const std::string &moduleName, const std::string &typeName ); - + const TypeFieldList& getFields() const { return m_fields; } - + bool isComplex() const { return !m_baseType; - } - + } + bool isPtr() const { return m_pointer; - } - -private: - + } + + // field offset getter/setter + void setOffset(ULONG offset) { m_offset = offset; } + ULONG getOffset() const { return m_offset; } + +private: + static TypeInfoMap g_typeInfoCache; boost::python::object @@ -134,7 +143,7 @@ private: ptrLoader( ULONG64 addr ) const { return boost::python::object( loadPtrByPtr( addr ) ); } - + void setupBaseType(); @@ -145,6 +154,7 @@ private: TypeFieldList m_fields; std::string m_typeName; ULONG m_size; + ULONG m_offset; }; ///////////////////////////////////////////////////////////////////////////////// @@ -163,9 +173,10 @@ public: { } + // sizeof(TYPE) ULONG size() const { - return m_typeInfo.size(); + return (ULONG)m_typeInfo.size(); } void setPyObj( const boost::python::object &obj ) @@ -173,6 +184,7 @@ public: m_pyobj = obj; } + // TypeInfo getter TypeInfo &getTypeInfo() { return m_typeInfo; @@ -182,6 +194,7 @@ public: return m_typeInfo; } + // boost::python::object getter boost::python::object &getPyObj() { return m_pyobj; @@ -200,6 +213,14 @@ public: { // no data - nothing print } + virtual void printSelf( + std::stringstream &sstr + ) const + { + // no data - nothing print + } + + ULONG getOffset() const { return m_typeInfo.getOffset(); } private: TypeInfo m_typeInfo; @@ -226,7 +247,13 @@ public: } virtual void - printField(const TypeInfo::TypeField &field, std::stringstream &sstr) const override; + printField( const TypeInfo::TypeField &field, std::stringstream &sstr ) const override; + + virtual void + printSelf( std::stringstream &sstr ) const override + { + sstr << std::hex << "0x" << getAddress() << std::dec << " "; + } private: