[~] align of sruct

[+] view MIDL-generated server RPC-interface

git-svn-id: https://pykd.svn.codeplex.com/svn@69642 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\EreTIk_cp 2011-09-08 17:53:36 +00:00
parent 4af5301232
commit b06f995200
4 changed files with 229 additions and 75 deletions

View File

@ -221,17 +221,17 @@ BOOST_PYTHON_MODULE( pykd )
"Delete synthetic symbols by virtual address" ); "Delete synthetic symbols by virtual address" );
boost::python::def( "delSynSymbolsMask", &delSyntheticSymbolsMask, boost::python::def( "delSynSymbolsMask", &delSyntheticSymbolsMask,
"Delete synthetic symbols by mask of module and symbol name"); "Delete synthetic symbols by mask of module and symbol name");
boost::python::class_<TypeInfo>( "typeInfo", boost::python::class_<TypeInfo>( "typeInfo",
"Class representing non-primitive type info: structure, union, etc. attributes is a fields of non-primitive type" ) "Class representing non-primitive type info: structure, union, etc. attributes is a fields of non-primitive type" )
.def(boost::python::init<std::string,std::string>( boost::python::args("module", "type"), "constructor" ) ) .def(boost::python::init<std::string,std::string>( boost::python::args("module", "type"), "constructor" ) )
.def(boost::python::init<std::string>( boost::python::args("typeName"), "constructor" ) ) .def(boost::python::init<std::string>( boost::python::args("typeName"), "constructor" ) )
.def(boost::python::init<std::string,ULONG>( boost::python::args("typeName", "align"), "constructor" ) ) .def(boost::python::init<std::string,ULONG>( boost::python::args("typeName", "align"), "constructor" ) )
.def("size", &TypeInfo::size, .def("size", &TypeInfo::size,
"Return full size of non-primitive type" ) "Return full size of non-primitive type" )
.def("name", &TypeInfo::name, .def("name", &TypeInfo::name,
"Return type's name" ) "Return type's name" )
.def("__str__", &TypeInfo::print, .def("__str__", &TypeInfo::print,
"Return a nice string represention: print names and offsets of fields" ) "Return a nice string represention: print names and offsets of fields" )
.def("__getattr__", &TypeInfo::getField ) .def("__getattr__", &TypeInfo::getField )
@ -241,9 +241,11 @@ BOOST_PYTHON_MODULE( pykd )
"add new field for typeInfo" ) ) "add new field for typeInfo" ) )
.def("offset", &TypeInfo::getFieldOffset, .def("offset", &TypeInfo::getFieldOffset,
"Return offset while type is part of the more complex type" ) "Return offset while type is part of the more complex type" )
.def("setAlignReq", &TypeInfo::setAlignReq,
"Set alignment requirement" )
.def("load", &TypeInfo::loadVar, loadOver( boost::python::args( "offset", "count"), .def("load", &TypeInfo::loadVar, loadOver( boost::python::args( "offset", "count"),
"Create instance of the typedVar class with this typeInfo" ) ); "Create instance of the typedVar class with this typeInfo" ) );
DEF_PY_GLOBAL( "char_t", TypeInfo("", "char") ); DEF_PY_GLOBAL( "char_t", TypeInfo("", "char") );
DEF_PY_GLOBAL( "uchar_t", TypeInfo("", "unsigned char") ); DEF_PY_GLOBAL( "uchar_t", TypeInfo("", "unsigned char") );
DEF_PY_GLOBAL( "short_t", TypeInfo("", "short") ); DEF_PY_GLOBAL( "short_t", TypeInfo("", "short") );
@ -251,11 +253,11 @@ BOOST_PYTHON_MODULE( pykd )
DEF_PY_GLOBAL( "long_t", TypeInfo("", "long") ); DEF_PY_GLOBAL( "long_t", TypeInfo("", "long") );
DEF_PY_GLOBAL( "ulong_t", TypeInfo("", "unsigned long") ); DEF_PY_GLOBAL( "ulong_t", TypeInfo("", "unsigned long") );
DEF_PY_GLOBAL( "int_t", TypeInfo("", "int") ); DEF_PY_GLOBAL( "int_t", TypeInfo("", "int") );
DEF_PY_GLOBAL( "uint_t", TypeInfo("", "unsigned int") ); DEF_PY_GLOBAL( "uint_t", TypeInfo("", "unsigned int") );
DEF_PY_GLOBAL( "ptr_t", TypeInfo("", "void*") ); DEF_PY_GLOBAL( "ptr_t", TypeInfo("", "void*") );
DEF_PY_GLOBAL( "double_t", TypeInfo("", "double") ); DEF_PY_GLOBAL( "double_t", TypeInfo("", "double") );
DEF_PY_GLOBAL( "longlong_t", TypeInfo("", "int64") ); DEF_PY_GLOBAL( "longlong_t", TypeInfo("", "int64") );
DEF_PY_GLOBAL( "ulonglong_t", TypeInfo("", "unsigned int64") ); DEF_PY_GLOBAL( "ulonglong_t", TypeInfo("", "unsigned int64") );
boost::python::class_<TypedVar>( "typedVar", boost::python::class_<TypedVar>( "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" )

View File

@ -20,6 +20,8 @@ TypeInfo::TypeInfoMap TypeInfo::g_typeInfoCache;
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
TypeInfo::TypeInfo( const std::string &moduleName, const std::string &typeName ) TypeInfo::TypeInfo( const std::string &moduleName, const std::string &typeName )
: m_align(0)
, m_alignReq(1)
{ {
HRESULT hres; HRESULT hres;
bool baseType = checkBaseType(typeName); bool baseType = checkBaseType(typeName);
@ -51,14 +53,14 @@ TypeInfo::TypeInfo( const std::string &moduleName, const std::string &typeName
m_isPointer = true; m_isPointer = true;
m_size = ptrSize(); m_size = ptrSize();
break; break;
} }
if ( baseType ) if ( baseType )
{ {
m_isBaseType = true; m_isBaseType = true;
m_size = getBaseTypeSize( typeName ); m_size = getBaseTypeSize( typeName );
break; break;
} }
ULONG64 moduleBase = 0; ULONG64 moduleBase = 0;
hres = dbgExt->symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase ); hres = dbgExt->symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase );
@ -72,7 +74,7 @@ TypeInfo::TypeInfo( const std::string &moduleName, const std::string &typeName
hres = dbgExt->symbols->GetTypeSize( moduleBase, typeId, &m_size ); hres = dbgExt->symbols->GetTypeSize( moduleBase, typeId, &m_size );
if ( FAILED( hres ) ) if ( FAILED( hres ) )
throw TypeException(); throw TypeException();
for ( ULONG i = 0; ; ++i ) for ( ULONG i = 0; ; ++i )
{ {
@ -103,13 +105,13 @@ TypeInfo::TypeInfo( const std::string &moduleName, const std::string &typeName
if ( fieldTypeNameStr == "__unnamed" if ( fieldTypeNameStr == "__unnamed"
|| fieldTypeNameStr.find("<unnamed-tag>") < fieldTypeNameStr.size() ) || fieldTypeNameStr.find("<unnamed-tag>") < fieldTypeNameStr.size() )
{ {
m_fields.push_back( TypeField( fieldName, TypeInfo( moduleName, moduleBase, fieldTypeId ), fieldSize, fieldOffset ) ); addField( fieldName, TypeInfo( moduleName, moduleBase, fieldTypeId ), fieldSize, fieldOffset );
} }
else else
{ {
m_fields.push_back( TypeField( fieldName, TypeInfo( moduleName, fieldTypeName ), fieldSize, fieldOffset ) ); addField( fieldName, TypeInfo( moduleName, fieldTypeName ), fieldSize, fieldOffset );
} }
} }
} while( FALSE ); } while( FALSE );
@ -121,6 +123,8 @@ TypeInfo::TypeInfo( const std::string &moduleName, const std::string &typeName
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
TypeInfo::TypeInfo( const std::string &moduleName, ULONG64 moduleBase, ULONG typeId ) TypeInfo::TypeInfo( const std::string &moduleName, ULONG64 moduleBase, ULONG typeId )
: m_align(0)
, m_alignReq(1)
{ {
HRESULT hres; HRESULT hres;
@ -162,11 +166,11 @@ TypeInfo::TypeInfo( const std::string &moduleName, ULONG64 moduleBase, ULONG typ
if ( fieldTypeNameStr == "__unnamed" if ( fieldTypeNameStr == "__unnamed"
|| fieldTypeNameStr.find("<unnamed-tag>") < fieldTypeNameStr.size() ) || fieldTypeNameStr.find("<unnamed-tag>") < fieldTypeNameStr.size() )
{ {
m_fields.push_back( TypeField( fieldName, TypeInfo( moduleName, moduleBase, fieldTypeId ), fieldSize, fieldOffset ) ); addField( fieldName, TypeInfo( moduleName, moduleBase, fieldTypeId ), fieldSize, fieldOffset );
} }
else else
{ {
m_fields.push_back( TypeField( fieldName, TypeInfo( moduleName, fieldTypeName ), fieldSize, fieldOffset ) ); addField( fieldName, TypeInfo( moduleName, fieldTypeName ), fieldSize, fieldOffset );
} }
} }
@ -278,8 +282,8 @@ TypeInfo::getFieldByIndex( boost::python::object &obj ) const
} }
TypeInfo tinf = m_fields[index].type; TypeInfo tinf = m_fields[index].type;
tinf.m_parentOffset = m_fields[index].offset; tinf.m_parentOffset = m_fields[index].offset;
return boost::python::object( tinf ); return boost::python::object( tinf );
} }
else else
{ {
@ -343,14 +347,10 @@ TypeInfo::appendField( const TypeInfo &typeInfo, const std::string &fieldName, U
} }
ULONG offset = m_size; ULONG offset = m_size;
offset += offset % ( m_align ? m_align : typeInfo.getAlignReq() );
if ( typeInfo.isBaseType() )
{
offset += offset % min( typeInfo.size(), m_align );
}
const ULONG addSize = typeInfo.size() * count; const ULONG addSize = typeInfo.size() * count;
m_fields.push_back( TypeField( fieldName, typeInfo, addSize, offset ) ); addField( fieldName, typeInfo, addSize, offset );
m_size = offset + addSize; m_size = offset + addSize;
m_arraySize = offset + addSize; m_arraySize = offset + addSize;
} }
@ -856,10 +856,10 @@ TypedVar::TypedVar( const TypeInfo &typeInfo, ULONG64 targetOffset, char* buffer
{ {
if ( bufferLength < typeInfo.size() ) if ( bufferLength < typeInfo.size() )
throw TypeException(); throw TypeException();
m_buffer.insert( m_buffer.begin(), buffer, buffer + bufferLength ); m_buffer.insert( m_buffer.begin(), buffer, buffer + bufferLength );
} }
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
boost::python::object boost::python::object
@ -1001,6 +1001,32 @@ TypedVar::print()
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
ULONG TypeInfo::getAlignReq() const
{
if (isBaseType())
return size();
if (isPtr())
return ptrSize();
return m_alignReq;
}
/////////////////////////////////////////////////////////////////////////////////////
void TypeInfo::addField(
const std::string &name_,
const TypeInfo &type_,
ULONG size_,
ULONG offset_
)
{
m_alignReq = max(m_alignReq, type_.getAlignReq());
m_fields.push_back( TypeField( name_, type_, size_, offset_ ) );
}
/////////////////////////////////////////////////////////////////////////////////////
ULONG ULONG
sizeofType( const std::string &moduleName, const std::string &typeName ) sizeofType( const std::string &moduleName, const std::string &typeName )
{ {

View File

@ -23,106 +23,112 @@ public:
m_size(0), m_size(0),
m_arraySize( 0 ), m_arraySize( 0 ),
m_parentOffset( 0 ), m_parentOffset( 0 ),
m_align( ptrSize() ), m_align( 0 ),
m_isFreezed( false ), m_isFreezed( false ),
m_isBaseType( false ), m_isBaseType( false ),
m_isPointer( false ) m_isPointer( false ),
m_alignReq(1)
{} {}
TypeInfo( const std::string customName, ULONG align=0 ) : TypeInfo( const std::string customName, ULONG align = 0) :
m_typeName( customName ), m_typeName( customName ),
m_size( 0 ), m_size( 0 ),
m_arraySize( 0 ), m_arraySize( 0 ),
m_parentOffset( 0 ), m_parentOffset( 0 ),
m_isFreezed( false ), m_isFreezed( false ),
m_align( align == 0 ? ptrSize() : align ), m_align( align ),
m_isBaseType( false ), m_isBaseType( false ),
m_isPointer( false ) m_isPointer( false ),
m_alignReq(1)
{} {}
TypeInfo( const std::string &moduleName, const std::string &typeName ); TypeInfo( const std::string &moduleName, const std::string &typeName );
TypeInfo( const std::string &moduleName, ULONG64 moduleBase, ULONG typeId ); TypeInfo( const std::string &moduleName, ULONG64 moduleBase, ULONG typeId );
static static
const TypeInfo& const TypeInfo&
get( const std::string &moduleName, const std::string &typeName ); get( const std::string &moduleName, const std::string &typeName );
ULONG ULONG
size() const { size() const {
return m_size; return m_size;
} }
ULONG ULONG
count() const { count() const {
assert( m_size != 0 && m_arraySize >= m_size ); assert( m_size != 0 && m_arraySize >= m_size );
return m_arraySize / m_size; return m_arraySize / m_size;
} }
ULONG ULONG
fullSize() const { fullSize() const {
return m_arraySize; return m_arraySize;
} }
const std::string const std::string
name() const { name() const {
return m_typeName; return m_typeName;
} }
const std::string const std::string
moduleName() const { moduleName() const {
return m_moduleName; return m_moduleName;
} }
boost::python::object boost::python::object
load( void* buffer, size_t bufferLength ) const; load( void* buffer, size_t bufferLength ) const;
std::string std::string
printField( size_t index, void* buffer, size_t bufferLength ) const; printField( size_t index, void* buffer, size_t bufferLength ) const;
std::string std::string
print() const; print() const;
TypeInfo TypeInfo
getField( const std::string &fieldName ) const; getField( const std::string &fieldName ) const;
TypeInfo TypeInfo
getFieldAt( size_t index ) const; getFieldAt( size_t index ) const;
ULONG ULONG
getFieldOffset() const { getFieldOffset() const {
return m_parentOffset; return m_parentOffset;
} }
boost::python::object boost::python::object
getFieldByIndex( boost::python::object &index ) const; getFieldByIndex( boost::python::object &index ) const;
size_t size_t
getFieldCount() const { getFieldCount() const {
return m_fields.size(); return m_fields.size();
} }
void void
appendField( const TypeInfo &typeInfo, const std::string &fieldName, ULONG count = 1 ); appendField( const TypeInfo &typeInfo, const std::string &fieldName, ULONG count = 1 );
bool bool
isBaseType() const { isBaseType() const {
return m_isBaseType; return m_isBaseType;
} }
bool bool
isPtr() const { isPtr() const {
return m_isPointer; return m_isPointer;
} }
bool bool
isEnum() const { isEnum() const {
return !m_isBaseType && !m_isPointer && m_fields.size() == 0 && m_size == 4; return !m_isBaseType && !m_isPointer && m_fields.size() == 0 && m_size == 4;
} }
boost::python::object boost::python::object
loadVar( ULONG64 targetOffset, ULONG count = 1) const; loadVar( ULONG64 targetOffset, ULONG count = 1) const;
void setAlignReq(ULONG alignReq) {
m_alignReq = alignReq;
}
public: public:
typedef std::map< std::pair<std::string, std::string>, TypeInfo> TypeInfoMap; typedef std::map< std::pair<std::string, std::string>, TypeInfo> TypeInfoMap;
@ -154,46 +160,57 @@ public:
private: private:
ULONG getAlignReq() const;
void addField(
const std::string &name_,
const TypeInfo &type_,
ULONG size_,
ULONG offset_
);
typedef typedef
boost::python::object boost::python::object
(*basicTypeLoader)( void* address, size_t size ); (*basicTypeLoader)( void* address, size_t size );
typedef typedef
std::string std::string
(*basicTypePrinter)( void* address, size_t size ); (*basicTypePrinter)( void* address, size_t size );
static TypeInfoMap g_typeInfoCache; static TypeInfoMap g_typeInfoCache;
static const char* basicTypeNames[]; static const char* basicTypeNames[];
static size_t basicTypeSizes[]; static size_t basicTypeSizes[];
static basicTypeLoader basicTypeLoaders[]; static basicTypeLoader basicTypeLoaders[];
static basicTypePrinter basicTypePrinters[]; static basicTypePrinter basicTypePrinters[];
ULONG m_size; ULONG m_size;
ULONG m_arraySize; ULONG m_arraySize;
std::string m_typeName; std::string m_typeName;
std::string m_moduleName; std::string m_moduleName;
TypeFieldList m_fields; TypeFieldList m_fields;
bool m_isPointer; bool m_isPointer;
bool m_isBaseType; bool m_isBaseType;
bool m_isFreezed; bool m_isFreezed;
ULONG m_align; ULONG m_align;
ULONG m_parentOffset; ULONG m_alignReq;
ULONG m_parentOffset;
static bool checkBaseType( const std::string &typeName ); static bool checkBaseType( const std::string &typeName );
static ULONG getBaseTypeSize( const std::string &typeName ); static ULONG getBaseTypeSize( const std::string &typeName );
}; };

109
samples/rpcSrvIf.py Normal file
View File

@ -0,0 +1,109 @@
"""
Prase first param RpcServerRegisterIf[Xxx]
"""
import sys
from pykd import *
def rpcSrvIf(ifSpec):
"""
Prase RPC server interface specification
Usage example:
kd> ba e 1 rpcrt4!RPC_SERVER::RegisterInterface
kd> gc
And analyze first parameter
for x86:
kd> !py rpcSrvIf poi(@esp+@$ptrsize)
or for x64:
kd> !py rpcSrvIf @rdx
P.S. RPC_SERVER::RegisterInterface called from: RpcServerRegisterIf,
RpcServerRegisterIf2 and RpcServerRegisterIfEx
"""
def formatSintaxId(synId):
def formatGuid(guid):
part1 = "%08x-%04x-%04x" % (guid.data1, guid.data2, guid.data3)
part2 = "".join( ["%02x" % _byte for _byte in guid.data4] )
part3 = "".join( ["%02x" % _byte for _byte in guid.data5] )
return part1 + "-" + part2 + "-" + part3
def formatRpcVer(prcVer):
return "v.%d.%d" % (prcVer.MajorVersion, prcVer.MinorVersion)
return formatGuid(synId.SyntaxGUID) + " " + formatRpcVer(synId.SyntaxVersion)
# prepare structures for parsing
commGuid = typeInfo("rpcSrvIf~_GUID")
commGuid.append(ulong_t, "data1")
commGuid.append(ushort_t, "data2")
commGuid.append(ushort_t, "data3")
commGuid.append(uchar_t, "data4", 2)
commGuid.append(uchar_t, "data5", 6)
# print commGuid
rpcVersion = typeInfo("rpcSrvIf~_RPC_VERSION")
rpcVersion.append(ushort_t, "MajorVersion")
rpcVersion.append(ushort_t, "MinorVersion")
# print rpcVersion
rpcSintaxIdentifier = typeInfo("rpcSrvIf~_RPC_SYNTAX_IDENTIFIER")
rpcSintaxIdentifier.append(commGuid, "SyntaxGUID")
rpcSintaxIdentifier.append(rpcVersion, "SyntaxVersion")
# print rpcSintaxIdentifier
prcDispatchTable = typeInfo("rpcSrvIf~_RPC_DISPATCH_TABLE")
prcDispatchTable.append(uint_t, "DispatchTableCount")
prcDispatchTable.append(ptr_t, "DispatchTable")
prcDispatchTable.append(ptr_t, "Reserved")
# print prcDispatchTable
midlServerInfoHeader = typeInfo("rpcSrvIf~_MIDL_SERVER_INFO_hdr")
midlServerInfoHeader.append(ptr_t, "pStubDesc")
midlServerInfoHeader.append(ptr_t, "DispatchTable")
# print midlServerInfoHeader
rpcServerInterface = typeInfo("rpcSrvIf~_RPC_SERVER_INTERFACE")
rpcServerInterface.append(uint_t, "Length")
rpcServerInterface.append(rpcSintaxIdentifier, "InterfaceId")
rpcServerInterface.append(rpcSintaxIdentifier, "TransferSyntax")
rpcServerInterface.append(ptr_t, "DispatchTable") # -> prcDispatchTable
rpcServerInterface.append(uint_t, "RpcProtseqEndpointCount")
rpcServerInterface.append(ptr_t, "RpcProtseqEndpoint")
rpcServerInterface.append(ptr_t, "DefaultManagerEpv")
rpcServerInterface.append(ptr_t, "InterpreterInfo") # -> midlServerInfoHeader
rpcServerInterface.append(uint_t, "Flags")
# print rpcServerInterface
# get and print interface header
srvIf = rpcServerInterface.load( ifSpec )
dprintln("Interface ID : " + formatSintaxId(srvIf.InterfaceId) )
dprintln("Transfer Syntax : " + formatSintaxId(srvIf.TransferSyntax) )
dprintln("Endpoint count : %d" % srvIf.RpcProtseqEndpointCount )
if srvIf.RpcProtseqEndpointCount:
protoseqEndp = srvIf.RpcProtseqEndpoint
for i in range(0, srvIf.RpcProtseqEndpointCount):
dprintln("\t[%02d] protocol is `" % i + loadCStr( ptrPtr(protoseqEndp) ) + "'" )
protoseqEndp += ptrSize()
dprintln("\t[%02d] endpoint is `" % i + loadCStr( ptrPtr(protoseqEndp) ) + "'" )
protoseqEndp += ptrSize()
dprintln("")
# query dispatch routines table
dspTableSize = prcDispatchTable.load(srvIf.DispatchTable).DispatchTableCount
dspTable = midlServerInfoHeader.load(srvIf.InterpreterInfo).DispatchTable
dprintln('<exec cmd="dps 0x%x L 0x%x">Routine Table 0x%x, count %d (0x%02x)</exec>\n' %
(dspTable, dspTableSize, dspTable, dspTableSize, dspTableSize) ,True)
if __name__ == "__main__":
if len(sys.argv) == 2:
rpcSrvIf( expr(sys.argv[1]) )
else:
dprintln(rpcSrvIf.__doc__)