From 9a0d80eb23621f13bc2b08604d96252532dcf158 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Mon, 23 May 2011 06:43:24 +0000 Subject: [PATCH] [pykd] added: typeInfo class [pykd] added: typeException, memoryException and their translation into python git-svn-id: https://pykd.svn.codeplex.com/svn@65714 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgcmd.cpp | 135 --- pykd/dbgcmd.h | 37 - pykd/dbgeventcb.cpp | 2 +- pykd/dbgexcept.h | 110 ++- pykd/dbgext.cpp | 234 +++-- pykd/dbgext.h | 1 + pykd/dbgmem.cpp | 286 ++---- pykd/dbgmem.h | 28 +- pykd/dbgprocess.cpp | 2 +- pykd/dbgtype.cpp | 2231 +++++++++++++++++++++++++++++++------------ pykd/dbgtype.h | 770 ++++++++++----- pykd/pykd.vcproj | 12 + 12 files changed, 2563 insertions(+), 1285 deletions(-) diff --git a/pykd/dbgcmd.cpp b/pykd/dbgcmd.cpp index 4cceefd..e6f4337 100644 --- a/pykd/dbgcmd.cpp +++ b/pykd/dbgcmd.cpp @@ -120,141 +120,6 @@ dbgExtensionClass::print() const return ""; } -/////////////////////////////////////////////////////////////////////////////// - -dbgBreakpointClass::breakpointMap dbgBreakpointClass::m_breakMap; - -/////////////////////////////////////////////////////////////////////////////// - -HRESULT dbgBreakpointClass::onBreakpointEvnet( IDebugBreakpoint* bp ) -{ - try { - - breakpointMap::iterator it = m_breakMap.find( bp ); - if ( it != m_breakMap.end() ) - return boost::python::extract( it->second->m_callback() ); - - } - catch(...) - {} - - return DEBUG_STATUS_NO_CHANGE; -} - -/////////////////////////////////////////////////////////////////////////////// - -dbgBreakpointClass::dbgBreakpointClass( ULONG64 offset, boost::python::object &callback ) -{ - m_offset = offset; - m_breakpoint = NULL; - m_callback = callback; - - set(); -} - -/////////////////////////////////////////////////////////////////////////////// - -dbgBreakpointClass::~dbgBreakpointClass() -{ - remove(); -} - -/////////////////////////////////////////////////////////////////////////////// - -bool -dbgBreakpointClass::set() -{ - HRESULT hres; - - try { - - if ( m_breakpoint ) - return true; - - hres = dbgExt->control->AddBreakpoint( DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &m_breakpoint ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::AddBreakpoint failed" ); - - hres = m_breakpoint->SetOffset( m_offset ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugBreakpoint::SetOffset failed" ); - - hres = m_breakpoint->SetFlags( DEBUG_BREAKPOINT_ENABLED ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugBreakpoint::SetFlags failed" ); - - m_breakMap.insert( std::make_pair( m_breakpoint, this ) ); - - return true; - } - 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" ); - } - - remove(); - - return false; -} - -/////////////////////////////////////////////////////////////////////////////// - -void -dbgBreakpointClass::remove() -{ - if ( m_breakpoint ) - { - dbgExt->control->RemoveBreakpoint( m_breakpoint ); - - breakpointMap::iterator bp = m_breakMap.find( m_breakpoint ); - if ( bp != m_breakMap.end() ) - m_breakMap.erase( bp ); - - m_breakpoint = NULL; - } -} - -/////////////////////////////////////////////////////////////////////////////// - -std::string -dbgBreakpointClass::print() const -{ - HRESULT status = S_OK; - - try - { - if (!m_breakpoint) - return "not set"; - - DEBUG_BREAKPOINT_PARAMETERS params; - status = m_breakpoint->GetParameters(¶ms); - if (FAILED(status)) - throw DbgException("IDebugBreakpoint::GetParameters failed"); - - boost::format fmt("%1$2d %2%%3% %4%:*** "); - fmt % params.Id - % (params.Flags & DEBUG_BREAKPOINT_ENABLED ? 'e' : 'd') - % 'u' - % params.CurrentPassCount; - - return fmt.str(); - } - 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 ""; -} - /////////////////////////////////////////////////////////////////////////////// ULONG64 diff --git a/pykd/dbgcmd.h b/pykd/dbgcmd.h index 3cb4028..930ea88 100644 --- a/pykd/dbgcmd.h +++ b/pykd/dbgcmd.h @@ -79,43 +79,6 @@ private: std::string m_path; }; -///////////////////////////////////////////////////////////////////////////////// - -class dbgBreakpointClass { - -public: - - dbgBreakpointClass( ULONG64 offset, boost::python::object &callback ); - - ~dbgBreakpointClass(); - - bool - set(); - - void - remove(); - - std::string - print() const; - -private: - - ULONG64 m_offset; - - IDebugBreakpoint *m_breakpoint; - - boost::python::object m_callback; - -private: - - typedef std::map breakpointMap; - static breakpointMap m_breakMap; - -public: - - static HRESULT onBreakpointEvnet( IDebugBreakpoint* bp ); - -}; ///////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgeventcb.cpp b/pykd/dbgeventcb.cpp index 32df821..9587dbc 100644 --- a/pykd/dbgeventcb.cpp +++ b/pykd/dbgeventcb.cpp @@ -6,7 +6,7 @@ #include "dbgexcept.h" #include "dbgmodule.h" #include "dbgsynsym.h" -#include "dbgcmd.h" +#include "dbgbreak.h" #include "dbgmodevent.h" /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgexcept.h b/pykd/dbgexcept.h index 83a7701..47da5b6 100644 --- a/pykd/dbgexcept.h +++ b/pykd/dbgexcept.h @@ -1,16 +1,120 @@ #pragma once #include +#include ///////////////////////////////////////////////////////////////////////////////// -class DbgException : public std::exception +class DbgException : public std::exception { public: - DbgException( const char* desc ) : - std::exception( desc ) + DbgException( const std::string &desc ) : + std::exception( desc.c_str() ) {} + + const char* getDesc() const { + return what(); + } + + + static + void + exceptionTranslate(const DbgException &e ); }; +///////////////////////////////////////////////////////////////////////////////// + +class TypeException : public DbgException +{ +public: + + TypeException() : + DbgException( "type operation invalid" ) + {} + + TypeException( const std::string &desc ) : + DbgException( desc ) + {} + + static + void + exceptionTranslate(const TypeException &e ); + +}; + +///////////////////////////////////////////////////////////////////////////////// + +class IndexException : public DbgException +{ +public: + + IndexException() : + DbgException( "Index out of range" ) + {} + + static + void + translate(const IndexException &e ) { + PyErr_SetString(PyExc_IndexError, "Index out of range"); + } +}; + +///////////////////////////////////////////////////////////////////////////////// + +class MemoryException : public DbgException +{ +public: + + MemoryException( ULONG64 targetAddr ) : + m_targetAddress( targetAddr ), + DbgException( MemoryException::DescMaker( targetAddr, false ).desc() ) + {} + + MemoryException( ULONG64 targetAddr, bool phyAddr ) : + m_targetAddress( targetAddr ), + DbgException( MemoryException::DescMaker( targetAddr, phyAddr ).desc() ) + {} + + static + void + translate( const MemoryException &e ); + + ULONG64 + getAddress() const { + return m_targetAddress; + } + +private: + + ULONG64 m_targetAddress; + + class DescMaker { + public: + DescMaker( ULONG64 addr, bool phyAddr ) + { + std::stringstream sstr; + if ( phyAddr ) + sstr << "Memory exception at 0x" << std::hex << addr << " target physical address"; + else + sstr << "Memory exception at 0x" << std::hex << addr << " target virtual address"; + m_desc = sstr.str(); + } + + const std::string& + desc() const { + return m_desc; + } + + private: + std::string m_desc; + }; +}; + +///////////////////////////////////////////////////////////////////////////////// + +extern PyObject *baseExceptionType; +extern PyObject *typeExceptionType; +extern PyObject *memoryExceptionType; + ///////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 3dd6ca5..678b567 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -29,6 +29,7 @@ #include "dbgsynsym.h" #include "dbgclient.h" #include "dbgmodevent.h" +#include "dbgbreak.h" ////////////////////////////////////////////////////////////////////////////// @@ -56,8 +57,16 @@ BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignQWords, loadArray<__int64>, 2, 3 ) BOOST_PYTHON_FUNCTION_OVERLOADS( compareMemoryOver, compareMemory, 3, 4 ) -#define _DEF_PY_CONST(x) \ +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( appendOver, TypeInfo::appendField, 2, 3 ) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( loadOver, TypeInfo::loadVar, 1, 2 ) + + +#define DEF_PY_CONST(x) \ boost::python::scope().attr(#x) = ##x + +#define DEF_PY_GLOBAL(x,y) \ + boost::python::scope().attr(x) = ##y + BOOST_PYTHON_MODULE( pykd ) { @@ -80,7 +89,7 @@ BOOST_PYTHON_MODULE( pykd ) boost::python::def( "loadDump", &dbgLoadDump, "Load crash dump (only for console)"); boost::python::def( "startProcess", &startProcess, - "Start process for debugging(only for console)"); + "Start process for debugging (only for console)"); boost::python::def( "dbgCommand", &dbgCommand, "Execute debugger command. For example: dbgCommand( \"lmvm nt\" )" ); boost::python::def( "isValid", &isOffsetValid, @@ -95,8 +104,6 @@ BOOST_PYTHON_MODULE( pykd ) "Return pointer size ( in bytes )" ); boost::python::def( "reg", &loadRegister, "Return CPU's register value" ); - boost::python::def( "typedVar", &loadTypedVar, - "Return instance of the typedVarClass. It's values are loaded from the target memory" ); boost::python::def( "typedVarList", &loadTypedVarList, "Return list of typedVarClass instances. Each item represents one item of the linked list in the target memory" ); boost::python::def( "typedVarArray", &loadTypedVarArray, @@ -104,8 +111,6 @@ BOOST_PYTHON_MODULE( pykd ) boost::python::def( "containingRecord", &containingRecord, "Return instance of the typedVarClass. It's value are loaded from the target memory." "The start address is calculated by the same method as standard macro CONTAINING_RECORD" ); - boost::python::def( "getTypeClass", &getTypeClass, - "Return instance of the typeClass with information about type" ); boost::python::def( "sizeof", &sizeofType, "Return size of type" ); boost::python::def( "loadModule", &loadModule, @@ -204,21 +209,56 @@ BOOST_PYTHON_MODULE( pykd ) "Delete synthetic symbols by virtual address" ); boost::python::def( "delSynSymbolsMask", &delSyntheticSymbolsMask, "Delete synthetic symbols by mask of module and symbol name"); - - boost::python::class_ >( "typeClass", + + boost::python::class_( "typeInfo", "Class representing non-primitive type info: structure, union, etc. attributes is a fields of non-primitive type" ) - .def("sizeof", &typeClass::size, - "Return full size of non-primitive type" ) - .def("offset", &typeClass::getOffset, - "Return offset as field of parent" ) - .def("__str__", &typeClass::print, - "Return a nice string represention: print names and offsets of fields"); - - boost::python::class_, boost::shared_ptr >( "typedVarClass", + .def(boost::python::init( boost::python::args("module", "type"), "constructor" ) ) + .def(boost::python::init( boost::python::args("typeName"), "constructor" ) ) + .def(boost::python::init( boost::python::args("typeName", "align"), "constructor" ) ) + .def("size", &TypeInfo::size, + "Return full size of non-primitive type" ) + .def("name", &TypeInfo::name, + "Return type's name" ) + .def("__str__", &TypeInfo::print, + "Return a nice string represention: print names and offsets of fields" ) + .def("__getattr__", &TypeInfo::getField ) + .def("__len__", &TypeInfo::getFieldCount ) + .def("__getitem__", &TypeInfo::getFieldByIndex ) + .def("append", &TypeInfo::appendField, appendOver( boost::python::args("type", "fieldName", "count"), + "add new field for typeInfo" ) ) + .def("offset", &TypeInfo::getFieldOffset, + "Return offset while type is part of the more complex type" ) + .def("load", &TypeInfo::loadVar, loadOver( boost::python::args( "offset", "count"), + "Create instance of the typedVar class with this typeInfo" ) ); + + DEF_PY_GLOBAL( "char_t", TypeInfo("", "char") ); + DEF_PY_GLOBAL( "uchar_t", TypeInfo("", "unsigned char") ); + DEF_PY_GLOBAL( "short_t", TypeInfo("", "short") ); + DEF_PY_GLOBAL( "ushort_t", TypeInfo("", "unsigned short") ); + DEF_PY_GLOBAL( "long_t", TypeInfo("", "long") ); + DEF_PY_GLOBAL( "ulong_t", TypeInfo("", "unsigned long") ); + DEF_PY_GLOBAL( "int_t", TypeInfo("", "int") ); + DEF_PY_GLOBAL( "uint_t", TypeInfo("", "unsigned int") ); + DEF_PY_GLOBAL( "ptr_t", TypeInfo("", "viod*") ); + DEF_PY_GLOBAL( "double_t", TypeInfo("", "double") ); + DEF_PY_GLOBAL( "longlong_t", TypeInfo("", "int64") ); + DEF_PY_GLOBAL( "ulonglong_t", TypeInfo("", "unsigned int64") ); + + boost::python::class_( "typedVar", "Class of non-primitive type object, child class of typeClass. Data from target is copied into object instance" ) - .def("getAddress", &typedVarClass::getAddress, - "Return virtual address" ); - + .def(boost::python::init(boost::python::args("typeInfo", "address"), + "constructor" ) ) + .def(boost::python::init(boost::python::args("moduleName", "typeName", "address"), + "constructor" ) ) + .def("getAddress", &TypedVar::getAddress, + "Return virtual address" ) + .def("sizeof", &TypedVar::getSize, + "Return size of a variable in the target memory" ) + .def("__getattr__", &TypedVar::getFieldWrap, + "Return field of structure as a object attribute" ) + .def("__str__", &TypedVar::print, + "Return a nice string represention: print names and offsets of fields" ); + boost::python::class_( "dbgModuleClass", "Class representing module in the target memory" ) .def("begin", &dbgModuleClass::getBegin, @@ -251,14 +291,15 @@ BOOST_PYTHON_MODULE( pykd ) .def("__str__", &dbgModuleClass::print, "Return a nice string represention of the dbgModuleClass" ); - boost::python::class_( + boost::python::class_( "ext", "windbg extension wrapper", - boost::python::init( boost::python::args("path"), "__init__ dbgExtensionClass" ) ) + boost::python::init( boost::python::args("path"), "__init__ dbgExtensionClass" ) ) .def("call", &dbgExtensionClass::call, "Call extension command" ) .def("__str__", &dbgExtensionClass::print, "Return a nice string represention of the dbgExtensionClass" ); + boost::python::class_( "dbgStackFrameClass", "Class representing a frame of the call satck" ) .def_readonly( "instructionOffset", &dbgStackFrameClass::InstructionOffset, @@ -273,10 +314,13 @@ BOOST_PYTHON_MODULE( pykd ) "Return a frame's number" ) .def( "__str__", &dbgStackFrameClass::print, "Return a nice string represention of the dbgStackFrameClass" ); + boost::python::class_( "windbgOut", "windbgOut" ) .def( "write", &dbgOut::write ); + boost::python::class_( "windbgIn", "windbgIn" ) .def( "readline", &dbgIn::readline ); + boost::python::class_( "bp", "Class representing breakpoint", boost::python::init( boost::python::args("offset", "callback"), @@ -287,7 +331,7 @@ BOOST_PYTHON_MODULE( pykd ) "Remove a breakpoint set before" ) .def( "__str__", &dbgBreakpointClass::print, "Return a nice string represention of the breakpoint class" ); - + boost::python::class_( "modEvents", "Class for processing of events: loading and unloading modules" ) .def( "onLoad", &moduleEvents::onLoad, &moduleEventsWrap::onLoadDef, @@ -295,64 +339,98 @@ BOOST_PYTHON_MODULE( pykd ) "For ignore event method must return DEBUG_STATUS_NO_CHANGE value" ) .def( "onUnload", &moduleEvents::onUnload, &moduleEventsWrap::onUnloadDef, "Unload module event. Parameter is instance of dbgModuleClass. " - "For ignore event method must return DEBUG_STATUS_NO_CHANGE value" ); + "For ignore event method must return DEBUG_STATUS_NO_CHANGE value" ); + + // исключения + boost::python::class_ dbgExceptionClass( "BaseException", + "Pykd base exception class", + boost::python::no_init ); + //boost::python::init() ); + + dbgExceptionClass + .def( boost::python::init( boost::python::args("desc"), "constructor" ) ) + .def( "desc", &DbgException::getDesc, + "Get exception description" ); + + boost::python::class_ > typeExceptionClass( "TypeException", + "Type exception class", + boost::python::no_init ); + + boost::python::class_ > memoryExceptionClass( "MemoryException", + "Memory exception class", + boost::python::no_init ); + + memoryExceptionClass + .def( boost::python::init( boost::python::args("targetAddress"), "constructor" ) ) + .def( "getAddress", &MemoryException::getAddress, + "Return target address" ); + + baseExceptionType = dbgExceptionClass.ptr(); + typeExceptionType = typeExceptionClass.ptr(); + memoryExceptionType = memoryExceptionClass.ptr(); + + boost::python::register_exception_translator( &DbgException::exceptionTranslate ); + boost::python::register_exception_translator( &TypeException::exceptionTranslate ); + boost::python::register_exception_translator( &IndexException::translate); + boost::python::register_exception_translator( &MemoryException::translate ); + // debug status - _DEF_PY_CONST(DEBUG_STATUS_NO_CHANGE); - _DEF_PY_CONST(DEBUG_STATUS_GO); - _DEF_PY_CONST(DEBUG_STATUS_GO_HANDLED); - _DEF_PY_CONST(DEBUG_STATUS_GO_NOT_HANDLED); - _DEF_PY_CONST(DEBUG_STATUS_STEP_OVER); - _DEF_PY_CONST(DEBUG_STATUS_STEP_INTO); - _DEF_PY_CONST(DEBUG_STATUS_BREAK); - _DEF_PY_CONST(DEBUG_STATUS_NO_DEBUGGEE); - _DEF_PY_CONST(DEBUG_STATUS_STEP_BRANCH); - _DEF_PY_CONST(DEBUG_STATUS_IGNORE_EVENT); - _DEF_PY_CONST(DEBUG_STATUS_RESTART_REQUESTED); - _DEF_PY_CONST(DEBUG_STATUS_REVERSE_GO); - _DEF_PY_CONST(DEBUG_STATUS_REVERSE_STEP_BRANCH); - _DEF_PY_CONST(DEBUG_STATUS_REVERSE_STEP_OVER); - _DEF_PY_CONST(DEBUG_STATUS_REVERSE_STEP_INTO); + DEF_PY_CONST(DEBUG_STATUS_NO_CHANGE); + DEF_PY_CONST(DEBUG_STATUS_GO); + DEF_PY_CONST(DEBUG_STATUS_GO_HANDLED); + DEF_PY_CONST(DEBUG_STATUS_GO_NOT_HANDLED); + DEF_PY_CONST(DEBUG_STATUS_STEP_OVER); + DEF_PY_CONST(DEBUG_STATUS_STEP_INTO); + DEF_PY_CONST(DEBUG_STATUS_BREAK); + DEF_PY_CONST(DEBUG_STATUS_NO_DEBUGGEE); + DEF_PY_CONST(DEBUG_STATUS_STEP_BRANCH); + DEF_PY_CONST(DEBUG_STATUS_IGNORE_EVENT); + DEF_PY_CONST(DEBUG_STATUS_RESTART_REQUESTED); + DEF_PY_CONST(DEBUG_STATUS_REVERSE_GO); + DEF_PY_CONST(DEBUG_STATUS_REVERSE_STEP_BRANCH); + DEF_PY_CONST(DEBUG_STATUS_REVERSE_STEP_OVER); + DEF_PY_CONST(DEBUG_STATUS_REVERSE_STEP_INTO); // debug status additional mask - _DEF_PY_CONST(DEBUG_STATUS_INSIDE_WAIT); - _DEF_PY_CONST(DEBUG_STATUS_WAIT_TIMEOUT); + DEF_PY_CONST(DEBUG_STATUS_INSIDE_WAIT); + DEF_PY_CONST(DEBUG_STATUS_WAIT_TIMEOUT); // break point type - _DEF_PY_CONST(DEBUG_BREAKPOINT_CODE); - _DEF_PY_CONST(DEBUG_BREAKPOINT_DATA); - _DEF_PY_CONST(DEBUG_BREAKPOINT_TIME); + DEF_PY_CONST(DEBUG_BREAKPOINT_CODE); + DEF_PY_CONST(DEBUG_BREAKPOINT_DATA); + DEF_PY_CONST(DEBUG_BREAKPOINT_TIME); // break point flag - _DEF_PY_CONST(DEBUG_BREAKPOINT_GO_ONLY); - _DEF_PY_CONST(DEBUG_BREAKPOINT_DEFERRED); - _DEF_PY_CONST(DEBUG_BREAKPOINT_ENABLED); - _DEF_PY_CONST(DEBUG_BREAKPOINT_ADDER_ONLY); - _DEF_PY_CONST(DEBUG_BREAKPOINT_ONE_SHOT); + DEF_PY_CONST(DEBUG_BREAKPOINT_GO_ONLY); + DEF_PY_CONST(DEBUG_BREAKPOINT_DEFERRED); + DEF_PY_CONST(DEBUG_BREAKPOINT_ENABLED); + DEF_PY_CONST(DEBUG_BREAKPOINT_ADDER_ONLY); + DEF_PY_CONST(DEBUG_BREAKPOINT_ONE_SHOT); // break point access type - _DEF_PY_CONST(DEBUG_BREAK_READ); - _DEF_PY_CONST(DEBUG_BREAK_WRITE); - _DEF_PY_CONST(DEBUG_BREAK_EXECUTE); - _DEF_PY_CONST(DEBUG_BREAK_IO); + DEF_PY_CONST(DEBUG_BREAK_READ); + DEF_PY_CONST(DEBUG_BREAK_WRITE); + DEF_PY_CONST(DEBUG_BREAK_EXECUTE); + DEF_PY_CONST(DEBUG_BREAK_IO); // exception flags - _DEF_PY_CONST(EXCEPTION_NONCONTINUABLE); + DEF_PY_CONST(EXCEPTION_NONCONTINUABLE); // debug events - _DEF_PY_CONST(DEBUG_EVENT_BREAKPOINT); - _DEF_PY_CONST(DEBUG_EVENT_EXCEPTION); - _DEF_PY_CONST(DEBUG_EVENT_CREATE_THREAD); - _DEF_PY_CONST(DEBUG_EVENT_EXIT_THREAD); - _DEF_PY_CONST(DEBUG_EVENT_CREATE_PROCESS); - _DEF_PY_CONST(DEBUG_EVENT_EXIT_PROCESS); - _DEF_PY_CONST(DEBUG_EVENT_LOAD_MODULE); - _DEF_PY_CONST(DEBUG_EVENT_UNLOAD_MODULE); - _DEF_PY_CONST(DEBUG_EVENT_SYSTEM_ERROR); - _DEF_PY_CONST(DEBUG_EVENT_SESSION_STATUS); - _DEF_PY_CONST(DEBUG_EVENT_CHANGE_DEBUGGEE_STATE); - _DEF_PY_CONST(DEBUG_EVENT_CHANGE_ENGINE_STATE); - _DEF_PY_CONST(DEBUG_EVENT_CHANGE_SYMBOL_STATE); + DEF_PY_CONST(DEBUG_EVENT_BREAKPOINT); + DEF_PY_CONST(DEBUG_EVENT_EXCEPTION); + DEF_PY_CONST(DEBUG_EVENT_CREATE_THREAD); + DEF_PY_CONST(DEBUG_EVENT_EXIT_THREAD); + DEF_PY_CONST(DEBUG_EVENT_CREATE_PROCESS); + DEF_PY_CONST(DEBUG_EVENT_EXIT_PROCESS); + DEF_PY_CONST(DEBUG_EVENT_LOAD_MODULE); + DEF_PY_CONST(DEBUG_EVENT_UNLOAD_MODULE); + DEF_PY_CONST(DEBUG_EVENT_SYSTEM_ERROR); + DEF_PY_CONST(DEBUG_EVENT_SESSION_STATUS); + DEF_PY_CONST(DEBUG_EVENT_CHANGE_DEBUGGEE_STATE); + DEF_PY_CONST(DEBUG_EVENT_CHANGE_ENGINE_STATE); + DEF_PY_CONST(DEBUG_EVENT_CHANGE_SYMBOL_STATE); // debugger type //_DEF_PY_CONST(DEBUG_CLASS_UNINITIALIZED); @@ -424,10 +502,25 @@ private: Py_Initialize(); - boost::python::import( "pykd" ); - main = boost::python::import("__main__"); + boost::python::object main_namespace = main.attr("__dict__"); + + + // делаем аналог from pykd import * + boost::python::object pykd = boost::python::import( "pykd" ); + + boost::python::dict pykd_namespace( pykd.attr("__dict__") ); + + boost::python::list iterkeys( pykd_namespace.iterkeys() ); + + for (int i = 0; i < boost::python::len(iterkeys); i++) + { + std::string key = boost::python::extract(iterkeys[i]); + + main_namespace[ key ] = pykd_namespace[ key ]; + } + // перенаправление стандартных потоков ВВ boost::python::object sys = boost::python::import( "sys"); @@ -491,6 +584,9 @@ DbgExt::DbgExt( IDebugClient4 *masterClient ) client4 = NULL; masterClient->QueryInterface( __uuidof(IDebugClient4), (void **)&client4 ); + + client5 = NULL; + masterClient->QueryInterface( __uuidof(IDebugClient5), (void **)&client5 ); control = NULL; masterClient->QueryInterface( __uuidof(IDebugControl), (void **)&control ); @@ -747,7 +843,9 @@ pycmd( PDEBUG_CLIENT4 client, PCSTR args ) if ( !stopInput ) try { + boost::python::exec( str, WindbgGlobalSession::global(), WindbgGlobalSession::global() ); + } catch( boost::python::error_already_set const & ) { diff --git a/pykd/dbgext.h b/pykd/dbgext.h index 461aab9..8492358 100644 --- a/pykd/dbgext.h +++ b/pykd/dbgext.h @@ -9,6 +9,7 @@ public: IDebugClient *client; IDebugClient4 *client4; + IDebugClient5 *client5; IDebugControl *control; IDebugControl4 *control4; diff --git a/pykd/dbgmem.cpp b/pykd/dbgmem.cpp index 189267f..5f0548a 100644 --- a/pykd/dbgmem.cpp +++ b/pykd/dbgmem.cpp @@ -13,40 +13,24 @@ using namespace std; /////////////////////////////////////////////////////////////////////////////////// -bool +void loadMemory( ULONG64 address, PVOID dest, ULONG length, BOOLEAN phyAddr ) { address = addr64( address ); - - try { - if ( phyAddr == FALSE ) - { - HRESULT hres = dbgExt->dataSpaces->ReadVirtual( address, dest, length, NULL ); - if ( FAILED( hres ) ) - return false; - - } - else - { - HRESULT hres = dbgExt->dataSpaces->ReadPhysical( address, dest, length, NULL ); - if ( FAILED( hres ) ) - return false; - } - - return true; - - } - 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; + HRESULT hres; + + if ( phyAddr == FALSE ) + { + hres = dbgExt->dataSpaces->ReadVirtual( address, dest, length, NULL ); + } + else + { + hres = dbgExt->dataSpaces->ReadPhysical( address, dest, length, NULL ); + } + + if ( FAILED( hres ) ) + throw MemoryException( address, !!phyAddr ); } /////////////////////////////////////////////////////////////////////////////////// @@ -151,33 +135,27 @@ loadPtrArray( ULONG64 address, ULONG number ) { boost::scoped_array buffer(new ULONG64[number]); - if ( loadMemory( address, buffer.get(), number*sizeof(ULONG64) ) ) - { - boost::python::list lst; + loadMemory( address, buffer.get(), number*sizeof(ULONG64) ); + + boost::python::list lst; - for ( ULONG i = 0; i < number; ++i ) - lst.append( buffer[i] ); - - return lst; - } - - return boost::python::object(); + for ( ULONG i = 0; i < number; ++i ) + lst.append( buffer[i] ); + + return lst; } else { boost::scoped_array buffer(new ULONG[number]); - if ( loadMemory( address, buffer.get(), number*sizeof(ULONG) ) ) - { - boost::python::list lst; + loadMemory( address, buffer.get(), number*sizeof(ULONG) ); - for ( ULONG i = 0; i < number; ++i ) - lst.append( addr64( buffer[i] ) ); + boost::python::list lst; + + for ( ULONG i = 0; i < number; ++i ) + lst.append( addr64( buffer[i] ) ); - return lst; - } - - return boost::python::object(); + return lst; } } @@ -188,12 +166,9 @@ loadChars( ULONG64 address, ULONG number, BOOLEAN phyAddr ) { std::vector buffer(number); - if ( loadMemory( address, &buffer[0], (ULONG)buffer.size(), phyAddr ) ) - { - return boost::python::object(std::string( buffer.begin(), buffer.end() ) ); - } + loadMemory( address, &buffer[0], (ULONG)buffer.size(), phyAddr ); - return boost::python::object(); + return boost::python::object(std::string( buffer.begin(), buffer.end() ) ); } /////////////////////////////////////////////////////////////////////////////////// @@ -203,12 +178,9 @@ loadWChars( ULONG64 address, ULONG number, BOOLEAN phyAddr ) { std::vector buffer(number); - if ( loadMemory( address, &buffer[0], (ULONG)buffer.size(), phyAddr ) ) - { - return boost::python::object(std::wstring( buffer.begin(), buffer.end() ) ); - } - - return boost::python::object(); + loadMemory( address, &buffer[0], (ULONG)buffer.size(), phyAddr ); + + return boost::python::object(std::wstring( buffer.begin(), buffer.end() ) ); } /////////////////////////////////////////////////////////////////////////////////// @@ -222,8 +194,9 @@ loadPtrByPtr( ULONG64 address ) loadMemory( address, &value, sizeof(ULONG64) ); else { - if ( loadMemory( address, &value, sizeof(ULONG) ) ) - value = addr64( value ); + loadMemory( address, &value, sizeof(ULONG) ); + + value = addr64( value ); } return value; @@ -267,12 +240,9 @@ loadByPtr( ULONG64 address ) { char value; - if ( loadMemory( address, &value, sizeof(char) ) ) - { - return boost::python::object( (int)value ); - } + loadMemory( address, &value, sizeof(char) ); - return boost::python::object(); + return boost::python::object( (int)value ); } /////////////////////////////////////////////////////////////////////////////////// @@ -286,16 +256,14 @@ loadUnicodeStr( ULONG64 address ) do { - if ( !loadMemory( address, &length, sizeof( length ) ) ) - break; + loadMemory( address, &length, sizeof( length ) ); if ( length == 0 ) break; address += sizeof( length ); - if ( !loadMemory( address, &maximumLength, sizeof( maximumLength ) ) ) - break; + loadMemory( address, &maximumLength, sizeof( maximumLength ) ); address += sizeof( maximumLength ); @@ -303,8 +271,7 @@ loadUnicodeStr( ULONG64 address ) { address += address % 8 ? ( 8 - address % 8 ) : 0 ; // выравнивание на 8 байт - if ( !loadMemory( address, &buffer, 8 ) ) - break; + loadMemory( address, &buffer, 8 ); address += 8; } @@ -312,18 +279,16 @@ loadUnicodeStr( ULONG64 address ) { address += address % 4 ? ( 4 - address % 4 ) : 0 ; // выравнивание на 8 байт - if ( !loadMemory( address, &buffer, 4 ) ) - break; + loadMemory( address, &buffer, 4 ); buffer = addr64( buffer ); address += 4; } - std::vector str(length / 2); + std::vector str(length / 2); - if ( !loadMemory( buffer, &str[0], length ) ) - break; + loadMemory( buffer, &str[0], length ); std::wstring strValue(&str[0], length/2); @@ -346,16 +311,14 @@ loadAnsiStr( ULONG64 address ) do { - if ( !loadMemory( address, &length, sizeof( length ) ) ) - break; + loadMemory( address, &length, sizeof( length ) ); if ( length == 0 ) break; address += sizeof( length ); - if ( !loadMemory( address, &maximumLength, sizeof( maximumLength ) ) ) - break; + loadMemory( address, &maximumLength, sizeof( maximumLength ) ); address += sizeof( maximumLength ); @@ -363,8 +326,7 @@ loadAnsiStr( ULONG64 address ) { address += address % 8 ? ( 8 - address % 8 ) : 0; // выравнивание на 8 байт - if ( !loadMemory( address, &buffer, 8 ) ) - break; + loadMemory( address, &buffer, 8 ); address += 8; } @@ -372,8 +334,7 @@ loadAnsiStr( ULONG64 address ) { address += address % 4 ? ( 4 - address % 4 ) : 0; // выравнивание на 8 байт - if ( !loadMemory( address, &buffer, 4 ) ) - break; + loadMemory( address, &buffer, 4 ); buffer = addr64( buffer ); @@ -381,10 +342,9 @@ loadAnsiStr( ULONG64 address ) } - std::vector str(length); + std::vector str(length); - if ( !loadMemory( buffer, &str[0], length ) ) - break; + loadMemory( buffer, &str[0], length ); std::string strVal ( &str[0], length ); @@ -397,112 +357,65 @@ loadAnsiStr( ULONG64 address ) /////////////////////////////////////////////////////////////////////////////////// -bool +void loadCStrToBuffer( ULONG64 address, PCHAR buffer, ULONG bufferLen ) { address = addr64( address ); - - try { - HRESULT hres = - dbgExt->dataSpaces4->ReadMultiByteStringVirtual( - address, - bufferLen, - buffer, - bufferLen/sizeof(CHAR), - NULL ); - - if ( FAILED( hres ) ) - return false; - - return true; - } - 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; + HRESULT hres = + dbgExt->dataSpaces4->ReadMultiByteStringVirtual( + address, + bufferLen, + buffer, + bufferLen/sizeof(CHAR), + NULL ); + + if ( FAILED( hres ) ) + throw MemoryException( address ); } /////////////////////////////////////////////////////////////////////////////////// -bool +void loadWStrToBuffer( ULONG64 address, PWCHAR buffer, ULONG bufferLen ) { address = addr64( address ); - - try { - HRESULT hres = - dbgExt->dataSpaces4->ReadUnicodeStringVirtualWide( - address, - bufferLen, - buffer, - bufferLen/sizeof(WCHAR), - NULL ); - - if ( FAILED( hres ) ) - return false; - - return true; + HRESULT hres = + dbgExt->dataSpaces4->ReadUnicodeStringVirtualWide( + address, + bufferLen, + buffer, + bufferLen/sizeof(WCHAR), + NULL ); - } - 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; + if ( FAILED( hres ) ) + throw MemoryException( address ); } - /////////////////////////////////////////////////////////////////////////////////// boost::python::object loadCStr( ULONG64 address ) { const size_t maxLength = 0x1000; - boost::python::object strObj( std::string("") ); - + address = addr64( address ); boost::scoped_array buffer(new char[maxLength]); - - try { - HRESULT hres = - dbgExt->dataSpaces4->ReadMultiByteStringVirtual( - address, - maxLength, - buffer.get(), - maxLength, - NULL ); - - if ( FAILED( hres ) ) - throw DbgException( "IDebugDataSpace4::ReadMultiByteStringVirtual failed" ); - - strObj = boost::python::object( std::string( buffer.get() ) ); + HRESULT hres = + dbgExt->dataSpaces4->ReadMultiByteStringVirtual( + address, + maxLength, + buffer.get(), + maxLength, + NULL ); - } - 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 strObj; + if ( FAILED( hres ) ) + throw MemoryException( address ); + + return boost::python::object( std::string( buffer.get() ) ); } /////////////////////////////////////////////////////////////////////////////////// @@ -511,38 +424,23 @@ boost::python::object loadWStr( ULONG64 address ) { const size_t maxLength = 0x1000; - boost::python::object strObj( std::wstring(L"") ); address = addr64( address ); boost::scoped_array buffer(new wchar_t[maxLength]); - - try { - HRESULT hres = - dbgExt->dataSpaces4->ReadUnicodeStringVirtualWide( - address, - maxLength*sizeof(wchar_t), - buffer.get(), - maxLength, - NULL ); + HRESULT hres = + dbgExt->dataSpaces4->ReadUnicodeStringVirtualWide( + address, + maxLength*sizeof(wchar_t), + buffer.get(), + maxLength, + NULL ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugDataSpace4::ReadUnicodeStringVirtualWide failed" ); + if ( FAILED( hres ) ) + throw MemoryException( address ); - strObj = boost::python::object( std::wstring(buffer.get()) ); - - } - 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 strObj; + return boost::python::object( std::wstring(buffer.get()) ); } diff --git a/pykd/dbgmem.h b/pykd/dbgmem.h index 4a3e2a2..d97cc76 100644 --- a/pykd/dbgmem.h +++ b/pykd/dbgmem.h @@ -4,7 +4,7 @@ ///////////////////////////////////////////////////////////////////////////////// -bool +void loadMemory( ULONG64 address, PVOID dest, ULONG length, BOOLEAN phyAddr = FALSE ); ULONG64 @@ -23,17 +23,14 @@ loadArray( ULONG64 address, ULONG number, BOOLEAN phyAddr = FALSE ) { boost::scoped_array buffer(new T[number]); - if ( loadMemory( address, buffer.get(), number*sizeof(T), phyAddr ) ) - { - boost::python::list lst; + loadMemory( address, buffer.get(), number*sizeof(T), phyAddr ); + + boost::python::list lst; - for ( ULONG i = 0; i < number; ++i ) - lst.append( buffer[i] ); + for ( ULONG i = 0; i < number; ++i ) + lst.append( buffer[i] ); - return lst; - } - - return boost::python::object(); + return lst; } boost::python::object @@ -48,12 +45,9 @@ loadByPtr( ULONG64 address ) { T value; - if ( loadMemory( address, &value, sizeof(T) ) ) - { - return boost::python::object( value ); - } + loadMemory( address, &value, sizeof(T) ); - return boost::python::object(); + return boost::python::object( value ); } template<> @@ -72,13 +66,13 @@ loadAnsiStr( ULONG64 address ); boost::python::object loadCStr( ULONG64 address ); -bool +void loadCStrToBuffer( ULONG64 address, PCHAR buffer, ULONG bufferLen ); boost::python::object loadWStr( ULONG64 address ); -bool +void loadWStrToBuffer( ULONG64 address, PWCHAR buffer, ULONG bufferLen ); bool diff --git a/pykd/dbgprocess.cpp b/pykd/dbgprocess.cpp index 12c2e5c..ec32030 100644 --- a/pykd/dbgprocess.cpp +++ b/pykd/dbgprocess.cpp @@ -388,7 +388,7 @@ getLocals() if ( FAILED( hres ) ) throw DbgException( "IDebugSymbolGroup2::GetSymbolOffset failed" ); - arr[ varName ] = loadTypedVar( moduleName, typeName, varOffset ); + arr[ varName ] = TypedVar( moduleName, typeName, varOffset ); } return arr; diff --git a/pykd/dbgtype.cpp b/pykd/dbgtype.cpp index be6fd76..4e091d5 100644 --- a/pykd/dbgtype.cpp +++ b/pykd/dbgtype.cpp @@ -2,6 +2,8 @@ #include +#include + #include "dbgext.h" #include "dbgtype.h" #include "dbgexcept.h" @@ -11,228 +13,588 @@ using namespace std; -///////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// -boost::python::object -loadTypedVar( const std::string &moduleName, const std::string &typeName, ULONG64 address ) -{ - const TypeInfo *typeInfo = TypeInfo::get( moduleName, typeName ); +TypeInfo::TypeInfoMap TypeInfo::g_typeInfoCache; - return typeInfo != NULL ? typeInfo->load( address ) : boost::python::object(); -} +/////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////// - -ULONG -sizeofType( const std::string &moduleName, const std::string &typeName ) +TypeInfo::TypeInfo( const std::string &moduleName, const std::string &typeName ) { 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" ); + bool baseType = checkBaseType(typeName); - const TypeInfo *typeInfo = TypeInfo::get( moduleName, typeName ); - - return typeInfo != NULL ? (ULONG)typeInfo->size() : 0L; - } - catch( std::exception &e ) + TypeInfoMap::iterator findIt = baseType ? + g_typeInfoCache.find( std::make_pair("",typeName) ) : + g_typeInfoCache.find( std::make_pair(moduleName,typeName) ); + + if ( findIt != g_typeInfoCache.end() ) { - 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; -} - -///////////////////////////////////////////////////////////////////////////////// - -boost::python::object -containingRecord( ULONG64 address, const std::string &moduleName, const std::string &typeName, const std::string &fieldName ) -{ - HRESULT hres; - - try { - - ULONG64 moduleBase; - - hres = dbgExt->symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase ); - 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" ); - - ULONG fieldTypeId; - ULONG fieldOffset; - hres = dbgExt->symbols3->GetFieldTypeAndOffset( moduleBase, typeId, fieldName.c_str(), &fieldTypeId, &fieldOffset ); - - return loadTypedVar( moduleName, typeName, 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(); -} - -///////////////////////////////////////////////////////////////////////////////// - -boost::python::object -getTypeClass( const std::string &moduleName, const std::string &typeName ) -{ - try - { - const TypeInfo *typeInfo = TypeInfo::get( moduleName, typeName ); - - return typeInfo != NULL ? typeInfo->build() : 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" ); + *this = findIt->second; + return; } - return boost::python::object(); -} - -///////////////////////////////////////////////////////////////////////////////// - -boost::python::object -loadTypedVarList( ULONG64 address, const std::string &moduleName, const std::string &typeName, const std::string &listEntryName ) -{ - address = addr64(address); + m_typeName = typeName; - ULONG64 entryAddress = 0; - - const TypeInfo *typeInfo = TypeInfo::get( moduleName, typeName ); + m_isPointer = false; + m_isBaseType = false; + m_isFreezed = true; + m_parentOffset = 0; - if ( !typeInfo ) - return boost::python::object(); + if ( !baseType ) + m_moduleName = moduleName; - boost::python::list objList; + do { - for ( TypeInfo::TypeFieldList::const_iterator field = typeInfo->getFields().begin(); field != typeInfo->getFields().end(); field++ ) - { - if ( field->name == listEntryName ) + if ( typeName.find("*") < typeName.size() ) { - if ( field->type.name() == ( typeName + "*" ) ) + m_isPointer = true; + m_size = ptrSize(); + break; + } + + if ( baseType ) + { + m_isBaseType = true; + m_size = getBaseTypeSize( typeName ); + break; + } + + ULONG64 moduleBase = 0; + hres = dbgExt->symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase ); + if ( FAILED( hres ) ) + throw TypeException(); + + ULONG typeId = 0; + hres = dbgExt->symbols->GetTypeId( moduleBase, m_typeName.c_str(), &typeId ); + if ( FAILED( hres ) ) + throw TypeException(); + + hres = dbgExt->symbols->GetTypeSize( moduleBase, typeId, &m_size ); + if ( FAILED( hres ) ) + throw TypeException(); + + for ( ULONG i = 0; ; ++i ) + { + char fieldName[100]; + hres = dbgExt->symbols2->GetFieldName( moduleBase, typeId, i, fieldName, sizeof(fieldName), NULL ); + if ( FAILED( hres ) ) + break; + + ULONG fieldTypeId; + ULONG fieldOffset; + hres = dbgExt->symbols3->GetFieldTypeAndOffset( moduleBase, typeId, fieldName, &fieldTypeId, &fieldOffset ); + + if ( FAILED( hres ) ) + throw TypeException(); + + ULONG fieldSize; + hres = dbgExt->symbols->GetTypeSize( moduleBase, fieldTypeId, &fieldSize ); + if ( FAILED( hres ) ) + throw TypeException(); + + char fieldTypeName[100]; + hres = dbgExt->symbols->GetTypeName( moduleBase, fieldTypeId, fieldTypeName, sizeof(fieldTypeName), NULL ); + if ( FAILED( hres ) ) + throw TypeException(); + + std::string fieldTypeNameStr( fieldTypeName ); + + if ( fieldTypeNameStr == "__unnamed" + || fieldTypeNameStr.find("") < fieldTypeNameStr.size() ) { - for( entryAddress = loadPtrByPtr( address ); entryAddress != address && entryAddress != NULL; entryAddress = loadPtrByPtr( entryAddress + field->offset ) ) - objList.append( loadTypedVar( moduleName, typeName, entryAddress ) ); - } + m_fields.push_back( TypeField( fieldName, TypeInfo( moduleName, moduleBase, fieldTypeId ), fieldSize, fieldOffset ) ); + } else { - for( entryAddress = loadPtrByPtr( address ); entryAddress != address && entryAddress != NULL; entryAddress = loadPtrByPtr( entryAddress ) ) - objList.append( containingRecord( entryAddress, moduleName, typeName, listEntryName ) ); - } - - return objList; + m_fields.push_back( TypeField( fieldName, TypeInfo( moduleName, fieldTypeName ), fieldSize, fieldOffset ) ); + } + } + + } while( FALSE ); + + m_arraySize = m_size; + + g_typeInfoCache.insert( std::make_pair( std::make_pair( m_moduleName, m_typeName), *this) ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +TypeInfo::TypeInfo( const std::string &moduleName, ULONG64 moduleBase, ULONG typeId ) +{ + HRESULT hres; + + m_isPointer = false; + m_isBaseType = false; + m_isFreezed = true; + m_parentOffset = 0; + + hres = dbgExt->symbols->GetTypeSize( moduleBase, typeId, &m_size ); + if ( FAILED( hres ) ) + throw TypeException(); + + for ( ULONG i = 0; ; ++i ) + { + char fieldName[100]; + hres = dbgExt->symbols2->GetFieldName( moduleBase, typeId, i, fieldName, sizeof(fieldName), NULL ); + if ( FAILED( hres ) ) + break; + + ULONG fieldTypeId; + ULONG fieldOffset; + hres = dbgExt->symbols3->GetFieldTypeAndOffset( moduleBase, typeId, fieldName, &fieldTypeId, &fieldOffset ); + + if ( FAILED( hres ) ) + throw TypeException(); + + ULONG fieldSize; + hres = dbgExt->symbols->GetTypeSize( moduleBase, fieldTypeId, &fieldSize ); + if ( FAILED( hres ) ) + throw TypeException(); + + char fieldTypeName[100]; + hres = dbgExt->symbols->GetTypeName( moduleBase, fieldTypeId, fieldTypeName, sizeof(fieldTypeName), NULL ); + if ( FAILED( hres ) ) + throw TypeException(); + + std::string fieldTypeNameStr( fieldTypeName ); + + if ( fieldTypeNameStr == "__unnamed" + || fieldTypeNameStr.find("") < fieldTypeNameStr.size() ) + { + m_fields.push_back( TypeField( fieldName, TypeInfo( moduleName, moduleBase, fieldTypeId ), fieldSize, fieldOffset ) ); } + else + { + m_fields.push_back( TypeField( fieldName, TypeInfo( moduleName, fieldTypeName ), fieldSize, fieldOffset ) ); + } + } + + m_arraySize = m_size; +} + +/////////////////////////////////////////////////////////////////////////////////// + +const TypeInfo& +TypeInfo::get( const std::string &moduleName, const std::string &typeName ) +{ + TypeInfoMap::iterator findIt = g_typeInfoCache.find( std::make_pair(moduleName,typeName) ); + + if ( findIt != g_typeInfoCache.end() ) + return findIt->second; + + TypeInfo type( moduleName, typeName ); + + return g_typeInfoCache.insert( std::make_pair( std::make_pair( moduleName, typeName), type) ).first->second; +} + +/////////////////////////////////////////////////////////////////////////////////// + +std::string +TypeInfo::print() const +{ + std::stringstream sstream; + + if ( m_typeName.size() != 0 ) + { + if ( m_moduleName.size() != 0 ) + sstream << m_moduleName << "!"; + + sstream << m_typeName; } + else + sstream << "unnamed"; + + if ( m_arraySize > m_size ) + { + sstream << " size = " << dec << m_arraySize << "(0x" << hex << m_arraySize << ") " << dec << "[" << m_arraySize/m_size << "]"; + } + else + { + sstream << " size = " << dec << m_size << "(0x" << hex << m_size << ")" << endl; + } + + TypeFieldList::const_iterator it = m_fields.begin(); + for(;it != m_fields.end(); ++it ) + { + sstream << "\t" << it->print() << std::endl; + } + + return sstream.str(); +} + +/////////////////////////////////////////////////////////////////////////////////// + +TypeInfo +TypeInfo::getField( const std::string &fieldName ) const +{ + TypeFieldList::const_iterator it = m_fields.begin(); + for(;it != m_fields.end(); ++it ) + { + if ( it->name == fieldName ) + { + TypeInfo tinf = it->type; + + tinf.m_parentOffset = m_parentOffset + it->offset; + tinf.m_arraySize = it->size; + + return tinf; + } + } + + throw TypeException(); +} + +/////////////////////////////////////////////////////////////////////////////////// + +TypeInfo +TypeInfo::getFieldAt( size_t index ) const +{ + TypeInfo tinf = m_fields[index].type; + + tinf.m_parentOffset = m_parentOffset + m_fields[index].offset; + tinf.m_arraySize = m_fields[index].size; + + return tinf; +} + +/////////////////////////////////////////////////////////////////////////////////// + +boost::python::object +TypeInfo::getFieldByIndex( boost::python::object &obj ) const +{ + if ( PyInt_Check( obj.ptr() ) ) + { + long index = PyInt_AsLong(obj.ptr()); + + if ( index > (long)m_fields.size() ) + throw IndexException(); + + if ( index < 0 ) + { + index = (long)m_fields.size() - abs(index); + if ( index < 0 ) + throw IndexException(); + } + + TypeInfo tinf = m_fields[index].type; + tinf.m_parentOffset = m_fields[index].offset; + return boost::python::object( tinf ); + } + else + { + boost::python::slice sl( boost::python::detail::borrowed_reference( obj.ptr() ) ); + + boost::python::slice::range< TypeFieldList::const_iterator > bounds; + + bounds = sl.get_indicies( m_fields.begin(), m_fields.end() ); + + boost::python::list valList; + + do { + + TypeInfo tinf = bounds.start->type; + tinf.m_parentOffset = bounds.start->offset; + + valList.append( tinf ); + + if ( bounds.start == bounds.stop) + break; + + std::advance( bounds.start, bounds.step); + + } while( true ); + + return valList; + } + + throw IndexException(); return boost::python::object(); } -///////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// -boost::python::object -loadTypedVarArray( ULONG64 address, const std::string &moduleName, const std::string &typeName, long number ) +void +TypeInfo::appendField( const TypeInfo &typeInfo, const std::string &fieldName, ULONG count ) { - boost::python::list objList; + if ( m_isFreezed ) + throw TypeException(); + + if ( count == 0 ) + throw TypeException(); + + if ( count == 1 && typeInfo.m_typeName.find("[]") != std::string::npos ) + throw TypeException(); + + TypeFieldList::const_iterator it = m_fields.begin(); + for(;it != m_fields.end(); ++it ) + { + if ( it->name == fieldName ) + throw TypeException(); + } - const TypeInfo *typeInfo = TypeInfo::get( moduleName, typeName ); + if ( count > 1 && typeInfo.m_typeName.find("[]") == std::string::npos ) + { + TypeInfo arrayInfo( typeInfo ); + arrayInfo.m_typeName += "[]"; + appendField( arrayInfo, fieldName, count ); + return; + } + + ULONG offset = m_size; + + if ( typeInfo.isBaseType() ) + { + offset += offset % min( typeInfo.size(), m_align ); + } - if ( !typeInfo ) - return boost::python::object(); - - for( long i = 0; i < number; ++i ) - objList.append( loadTypedVar( moduleName, typeName, address + i * typeInfo->size() ) ); - - return objList; + if ( count == 1 ) + { + m_fields.push_back( TypeField( fieldName, typeInfo, typeInfo.size(), offset ) ); + m_size = offset + typeInfo.size(); + } + else + { + m_fields.push_back( TypeField( fieldName, typeInfo, typeInfo.size()*count, offset ) ); + m_size = offset + typeInfo.size()*count; + } } -///////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// -bool -isBaseType( const std::string &typeName ); +boost::python::object +TypeInfo::loadVar( ULONG64 targetOffset, ULONG count ) const +{ + if ( count == 0 ) + throw TypeException(); + + if ( count == 1 ) + { + boost::python::object obj( TypedVar( *this, targetOffset ) ); + + return obj; + } + else + { + boost::python::list lst; + + for( ULONG i = 0; i < count; ++i ) + lst.append( TypedVar( *this, targetOffset + m_size*i ) ); + + return lst; + } +} + +/////////////////////////////////////////////////////////////////////////////////// template< typename valType> boost::python::object -valueLoader( PVOID address, ULONG size ); +valueLoader( void* address, size_t size ) +{ + if ( size == sizeof(valType) ) + { + valType v = *(valType*)address; + //return boost::python::long_( (unsigned __int64)v ); + + return boost::python::object( v ); + + + //if ( loadMemory( address, &v, sizeof(v) ) ) + //{ + // return boost::python::long_( (unsigned __int64)v ); + //} + } + else + { + boost::python::list arr; + + for ( unsigned int i = 0; i < size / sizeof(valType); ++i ) + { + valType v = *( (valType*)address + i ); + arr.append( v ); + + //arr[i] = boost::python::long_( (unsigned __int64)v ); + } + + return arr; + } + + throw TypeException(); +} template<> boost::python::object -valueLoader( PVOID address, ULONG size ) +valueLoader( void* address, size_t size ) { + if ( is64bitSystem() ) - return valueLoader<__int64>( address, size ); + { + if ( size == sizeof(ULONG64) ) + { + return boost::python::object( *(PULONG64)address ); + } + else + { + boost::python::list arr; + + for ( unsigned int i = 0; i < size / sizeof(ULONG64); ++i ) + { + ULONG64 v = *( (PULONG64)address + i ); + arr.append( v ); + } + + return arr; + } + } else - return valueLoader( address, size ); + { + if ( size == sizeof(ULONG) ) + { + return boost::python::object( addr64( *(PULONG)address ) ); + } + else + { + boost::python::list arr; + + for ( unsigned int i = 0; i < size / sizeof(ULONG); ++i ) + { + ULONG64 v = addr64(*( (PULONG)address + i ) ); + arr.append( v ); + } + + return arr; + } + } + + throw TypeException(); } +template<> boost::python::object -voidLoader( PVOID address, ULONG size ) { +valueLoader( void* address, size_t size ) +{ return boost::python::object(); } -static const char* -basicTypeNames[] = { - "unsigned char", - "char", - "unsigned short", - "short", - "unsigned long", - "long", - "int", - "unsigned int", - "", - "void", - "double", - "int64", - "unsigned int64", - "ptr" + + +template +std::string +valuePrinter( void* address, size_t size ) +{ + std::stringstream sstr; + + if ( size == sizeof(valType) ) + { + valType v = *(valType*)address; + + sstr << v; + } + else + { + + for ( unsigned int i = 0; i < size / sizeof(valType); ++i ) + { + valType v = *( (valType*)address + i ); + sstr << endl << "\t[" << dec << i << "] " << dec << v << " (" << hex << v << ")"; + } + } + + return sstr.str(); +} + +template<> +std::string +valuePrinter( void* address, size_t size ) +{ + if ( is64bitSystem() ) + { + return valuePrinter( address, size ); + } + + return valuePrinter( address, size ); +} + +template <> +std::string +valuePrinter( void* address, size_t size ) +{ + std::stringstream sstr; + + if ( size == sizeof(unsigned char) ) + { + unsigned int v = *(unsigned char*)address; + + sstr << v; + } + else + { + + for ( unsigned int i = 0; i < size / sizeof(unsigned char); ++i ) + { + unsigned int v = *( (unsigned char*)address + i ); + sstr << endl << "\t[" << dec << i << "] " << dec << v << " (" << hex << v << ")"; + } + } + + return sstr.str(); +} + + +template <> +std::string +valuePrinter( void* address, size_t size ) +{ + std::stringstream sstr; + + if ( size == sizeof(unsigned char) ) + { + int v = *(char*)address; + + sstr << v; + } + else + { + + for ( unsigned int i = 0; i < size / sizeof(unsigned char); ++i ) + { + int v = *( (char*)address + i ); + sstr << endl << "\t[" << dec << i << "] " << dec << v << " (" << hex << v << ")"; + } + } + + return sstr.str(); +} + + +template<> +std::string +valuePrinter( void* address, size_t size ) +{ + return ""; +} + + +const char* TypeInfo::basicTypeNames[] = { + "unsigned char", + "char", + "unsigned short", + "short", + "unsigned long", + "long", + "int", + "unsigned int", + "", + "void", + "double", + "int64", + "unsigned int64", + "ptr" }; -typedef -boost::python::object -(*basicTypeLoader)( PVOID address, ULONG size ); -basicTypeLoader basicTypeLoaders[] = { - valueLoader, - valueLoader, - valueLoader, - valueLoader, - valueLoader, - valueLoader, - valueLoader, - valueLoader, - valueLoader, - voidLoader, - valueLoader, - valueLoader<__int64>, - valueLoader - }; - -size_t basicTypeSizes[] = { +size_t TypeInfo::basicTypeSizes[] = { sizeof( unsigned char ), sizeof( char ), sizeof( unsigned short ), @@ -247,303 +609,42 @@ size_t basicTypeSizes[] = { sizeof( __int64 ), sizeof( unsigned __int64 ) }; - -///////////////////////////////////////////////////////////////////////////////// -TypeInfo::TypeInfoMap TypeInfo::g_typeInfoCache; -const TypeInfo* -TypeInfo::get( const std::string &moduleName, const std::string &typeName ) -{ - HRESULT hres; - - try { - - TypeInfoMap::iterator findIt = g_typeInfoCache.find( TypeName( moduleName, typeName ) ); - - if ( findIt != g_typeInfoCache.end() ) - return &findIt->second; - - TypeInfo typeInfo( typeName ); - - do { - - if ( typeName.find("*") < typeName.size() ) - { - typeInfo.m_pointer = true; - typeInfo.m_size = ptrSize(); - break; - } - - typeInfo.m_baseType = isBaseType( typeName ); - if ( typeInfo.m_baseType ) - { - typeInfo.setupBaseType(); - break; - } - - ULONG64 moduleBase = 0; - hres = dbgExt->symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugSymbol::GetModuleByModuleName failed" ); - - ULONG typeId = 0; - hres = dbgExt->symbols->GetTypeId( moduleBase, typeInfo.m_typeName.c_str(), &typeId ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugSymbol::GetTypeId failed" ); - - hres = dbgExt->symbols->GetTypeSize( moduleBase, typeId, &typeInfo.m_size ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugSymbol::GetTypeSize failed" ); - - for ( ULONG i = 0; ; ++i ) - { - char fieldName[100]; - hres = dbgExt->symbols2->GetFieldName( moduleBase, typeId, i, fieldName, sizeof(fieldName), NULL ); - - if ( FAILED( hres ) ) - break; - - 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 ); - if ( FAILED( hres ) ) - 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() ) - { - TypeInfo unnamedType; - if ( !getById( moduleName, fieldTypeId, unnamedType ) ) - return NULL; - - typeInfo.m_fields.push_back( TypeField( fieldName, unnamedType, fieldSize, fieldOffset ) ); - } - else - { - const TypeInfo *fieldTypeInfo = get( moduleName, fieldTypeName ); - if ( !fieldTypeInfo ) - return NULL; - - typeInfo.m_fields.push_back( TypeField( fieldName, *fieldTypeInfo, fieldSize, fieldOffset ) ); - } - } - - } while( FALSE ); - - return &g_typeInfoCache.insert( std::make_pair( TypeName( moduleName, typeName ), typeInfo) ).first->second; - } - catch( std::exception& ) - { - //dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); - // это нормально: на вход был передан не верный тип - } - catch(...) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); - } - - return NULL; -} - -///////////////////////////////////////////////////////////////////////////////// +TypeInfo::basicTypeLoader TypeInfo::basicTypeLoaders[] = { + valueLoader, + valueLoader, + valueLoader, + valueLoader, + valueLoader, + valueLoader, + valueLoader, + valueLoader, + valueLoader, + valueLoader, + valueLoader, + valueLoader<__int64>, + valueLoader + }; + +TypeInfo::basicTypePrinter TypeInfo::basicTypePrinters[] = { + valuePrinter, + valuePrinter, + valuePrinter, + valuePrinter, + valuePrinter, + valuePrinter, + valuePrinter, + valuePrinter, + valuePrinter, + valuePrinter, + valuePrinter, + valuePrinter<__int64>, + valuePrinter +}; bool -TypeInfo::getById( const std::string &moduleName, ULONG typeId, TypeInfo& typeInfo ) -{ - HRESULT hres; - - try { - - ULONG64 moduleBase = 0; - hres = dbgExt->symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugSymbol::GetModuleByModuleName failed" ); - - hres = dbgExt->symbols->GetTypeSize( moduleBase, typeId, &typeInfo.m_size ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugSymbol::GetTypeSize failed" ); - - for ( ULONG i = 0; ; ++i ) - { - char fieldName[100]; - hres = dbgExt->symbols2->GetFieldName( moduleBase, typeId, i, fieldName, sizeof(fieldName), NULL ); - - if ( FAILED( hres ) ) - break; - - 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 ); - if ( FAILED( hres ) ) - 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() ) - { - TypeInfo unnamedType; - if ( !getById( moduleName, fieldTypeId, unnamedType ) ) - return false; - - typeInfo.m_fields.push_back( TypeField( fieldName, unnamedType, fieldSize, fieldOffset ) ); - } - else - { - const TypeInfo *fieldTypeInfo = get( moduleName, fieldTypeName ); - if ( !fieldTypeInfo ) - return false; - - typeInfo.m_fields.push_back( TypeField( fieldName, *fieldTypeInfo, fieldSize, fieldOffset ) ); - } - } - - return true; - } - catch( std::exception& ) - { - //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; -} - -///////////////////////////////////////////////////////////////////////////////// - -void -TypeInfo::setupBaseType() -{ - for ( int i = 0; i < sizeof( basicTypeSizes ) / sizeof( size_t ); ++i ) - { - if ( m_typeName == basicTypeNames[i] || - m_typeName == ( std::string( basicTypeNames[i] ) + "[]" ) ) - { - m_size = (ULONG)basicTypeSizes[i]; - return; - } - } -} - -///////////////////////////////////////////////////////////////////////////////// - -boost::python::object -TypeInfo::build( ULONG offset /* = 0 */ ) const -{ - boost::shared_ptr ptr( new typeClass( *this, offset ) ); - boost::python::object var( ptr ); - ptr->setPyObj( var ); - - 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 targetAddr, PVOID cacheBuffer , ULONG offset /* = 0 */ ) const -{ - if ( !isOffsetValid( targetAddr) ) - return boost::python::object(); - - boost::scoped_array rawBuffer; - - if ( cacheBuffer == NULL ) - { - rawBuffer.reset( new char[ m_size ] ); - cacheBuffer = rawBuffer.get(); - - if ( !loadMemory( targetAddr, cacheBuffer, m_size ) ) - return boost::python::object(); - } - - if ( m_pointer ) - return ptrLoader( (PVOID)( (ULONG_PTR)cacheBuffer + offset ) ); - - if ( m_baseType ) - return loadBaseType( (PVOID)( (ULONG_PTR)cacheBuffer + offset ) ); - - boost::shared_ptr ptr( new typedVarClass( *this, offset, targetAddr ) ); - boost::python::object var( ptr ); - ptr->setPyObj( var ); - - 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.load( targetAddr + field->offset, cacheBuffer, offset + field->offset ); - } - else - { - boost::python::list arr; - - for ( unsigned int i = 0; i < field->size / field->type.size(); ++i ) - { - const ULONG locOffset = field->offset + i * (ULONG)field->type.size(); - arr.append( field->type.load( targetAddr + locOffset, cacheBuffer, offset + locOffset ) ); - } - - var.attr( field->name.c_str() ) = arr; - } - } - - return var; -} - -///////////////////////////////////////////////////////////////////////////////// - -bool -isBaseType( const std::string &typeName ) +TypeInfo::checkBaseType( const std::string &typeName ) { for ( int i = 0; i < sizeof( basicTypeNames ) / sizeof( char* ); ++i ) { @@ -563,163 +664,1111 @@ isBaseType( const std::string &typeName ) return false; } -///////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// -boost::python::object -TypeInfo::loadBaseType( PVOID address ) const +ULONG +TypeInfo::getBaseTypeSize( const std::string &typeName ) { - for ( int i = 0; i < sizeof( basicTypeNames ) / sizeof( char* ); ++i ) + for ( int i = 0; i < sizeof( basicTypeSizes ) / sizeof( size_t ); ++i ) { - 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 boost::python::object(); + if ( typeName == basicTypeNames[i] || + typeName == ( std::string( basicTypeNames[i] ) + "[]" ) ) + { + return (ULONG)basicTypeSizes[i]; + } + } + + return 0; } -///////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// -template< typename valType> boost::python::object -valueLoader( PVOID address, ULONG size ) +TypeInfo::load( void* buffer, size_t bufferLength ) const { - if ( size == sizeof(valType) ) + if ( bufferLength < m_size ) + throw TypeException(); + + if ( m_isPointer ) { - valType v = *(valType*)address; - return boost::python::long_( (unsigned __int64)v ); - - - //if ( loadMemory( address, &v, sizeof(v) ) ) - //{ - // return boost::python::long_( (unsigned __int64)v ); - //} - } - else - { - boost::python::dict arr; - - for ( unsigned int i = 0; i < size / sizeof(valType); ++i ) - { - valType v = *( (valType*)address + i ); - //if ( !loadMemory( address + i * sizeof(valType), &v, sizeof(v) ) ) - - arr[i] = boost::python::long_( (unsigned __int64)v ); - } - - return arr; + return valueLoader( buffer, bufferLength ); } - return boost::python::object(); + if ( m_isBaseType ) + { + for ( int i = 0; i < sizeof( basicTypeNames ) / sizeof( char* ); ++i ) + { + if ( m_typeName == basicTypeNames[i] ) + return basicTypeLoaders[i]( buffer, m_size ); + + if ( m_typeName == ( std::string( basicTypeNames[i] ) + "*" ) ) + return valueLoader( buffer, ptrSize() ); + + if ( m_typeName == ( std::string( basicTypeNames[i] ) + "[]" ) ) + return basicTypeLoaders[i]( buffer, m_arraySize ); + + if ( m_typeName == ( std::string( basicTypeNames[i] ) + "*[]" ) ) + return valueLoader( buffer, ptrSize()*count() ); + } + } + + throw TypeException(); } -///////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// -std::string typeClass::print() const +template<> +std::string +TypeInfo::TypeField::print() const { - stringstream sstr; + std::stringstream sstr; + + sstr << hex << "+" << offset << " "; + sstr << type.m_typeName << " "; + sstr << name; + + return sstr.str(); +} - sstr << getTypeInfo().name() << " "; - printSelf(sstr); - sstr << std::endl; +/////////////////////////////////////////////////////////////////////////////////// - TypeInfo::TypeFieldList::const_iterator itField = - getTypeInfo().getFields().begin(); - while (itField != getTypeInfo().getFields().end()) +std::string +TypeInfo::printField( size_t index, void* buffer, size_t bufferLength ) const +{ + stringstream sstr; + const TypeField &field = m_fields[index]; + const TypeInfo &fieldType = field.type; + ULONG offset = field.offset; + ULONG count = field.size / fieldType.size(); + + if ( fieldType.m_isPointer ) { - sstr << "\t" << hex << "+" << itField->offset << " "; - sstr << itField->type.name() << " "; - sstr << itField->name << " "; + sstr << hex << "+" << offset; + sstr << " " << field.name; + sstr << " " << fieldType.name(); + sstr << " " << valuePrinter( (char*)buffer + offset, field.size ); + sstr << endl; + return sstr.str(); + } + + if ( fieldType.m_isBaseType ) + { + for ( int i = 0; i < sizeof( basicTypeNames ) / sizeof( char* ); ++i ) + { + if ( fieldType.m_typeName == basicTypeNames[i] || + fieldType.m_typeName == ( std::string( basicTypeNames[i] ) + "[]" ) ) + { + sstr << hex << "+" << offset; + sstr << " " << field.name; + sstr << " " << fieldType.name(); + sstr << " " << basicTypePrinters[i]( (char*)buffer + offset, field.size ); + sstr << endl; + return sstr.str(); + } + } + + throw TypeException(); + } - printField(*itField, sstr); + if ( count == 1 ) + { + sstr << hex << "+" << offset; + sstr << " " << field.name; + sstr << " " << fieldType.name(); + sstr << endl; + } + else + { + sstr << hex << "+" << offset; + sstr << " " << field.name; + sstr << " " << fieldType.name() << "[" << dec << count << "]"; + sstr << endl; + } + + return sstr.str(); +} - sstr << std::endl; +/////////////////////////////////////////////////////////////////////////////////// - ++itField; +TypedVar::TypedVar( const TypeInfo &typeInfo, ULONG64 targetOffset, char* buffer, size_t bufferLength ) : + m_typeInfo( typeInfo ), + m_targetOffset( addr64(targetOffset) ) +{ + if ( bufferLength < typeInfo.size() ) + throw TypeException(); + + m_buffer.insert( m_buffer.begin(), buffer, buffer + bufferLength ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +boost::python::object +TypedVar::getFieldWrap( PyObject* self, const std::string &fieldName ) +{ + boost::python::object pyobj( boost::python::handle<>( boost::python::borrowed(self) ) ); + + TypedVar &tv = boost::python::extract( pyobj ); + + return tv.getField( pyobj, fieldName ); +} + +boost::python::object +TypedVar::getField( boost::python::object &pyobj, const std::string &fieldName ) +{ + if ( m_buffer.size() == 0 ) + { + m_buffer.resize( (size_t)m_typeInfo.fullSize() ); + + loadMemory( m_targetOffset, (PVOID)&m_buffer[0], (ULONG)m_buffer.size() ); + } + + TypeInfo typeInfo = m_typeInfo.getField( fieldName ); + + // относительный оффсет + ULONG offset = typeInfo.getFieldOffset() - m_typeInfo.getFieldOffset(); + + if ( typeInfo.isBaseType() || typeInfo.isPtr() ) + { + pyobj.attr(fieldName.c_str()) = typeInfo.load( &(m_buffer.begin() + offset)[0], typeInfo.fullSize() ); + } + else + { + if ( typeInfo.count() == 1 ) + { + pyobj.attr(fieldName.c_str()) = + boost::python::object( + TypedVar( + typeInfo, + m_targetOffset + offset, + &m_buffer[0] + offset, + typeInfo.size() ) ); + } + else + { + boost::python::list arr; + + for ( unsigned int i = 0; i < typeInfo.count(); ++i ) + { + arr.append( + boost::python::object( + TypedVar( + typeInfo, + m_targetOffset + offset + i*typeInfo.size(), + &m_buffer[0] + offset + i*typeInfo.size(), + typeInfo.size() ) ) ); + } + + pyobj.attr(fieldName.c_str()) = arr; + } + } + + return pyobj.attr(fieldName.c_str()); +} + +///////////////////////////////////////////////////////////////////////////////////// + +std::string +TypedVar::print() +{ + if ( m_buffer.size() == 0 ) + { + m_buffer.resize( (size_t)m_typeInfo.fullSize() ); + + loadMemory( m_targetOffset, (PVOID)&m_buffer[0], (ULONG)m_buffer.size() ); + } + + stringstream sstr; + + if ( m_typeInfo.name().size() != 0 ) + { + if ( m_typeInfo.moduleName().size() ) + sstr << m_typeInfo.moduleName() << "!"; + + sstr << m_typeInfo.name(); + } + else + sstr << "unnamed"; + + sstr << " address = " << hex << "0x" << getTargetOffset(); + sstr << " size = " << dec << m_typeInfo.fullSize() << " (0x" << hex << m_typeInfo.fullSize() << ")" << endl; + + + for ( size_t i = 0; i < m_typeInfo.getFieldCount(); ++i ) + { + sstr << m_typeInfo.printField( i, (PVOID)&m_buffer[0], (ULONG)m_buffer.size() ); + + //TypeInfo fieldType = m_typeInfo.getFieldAt( i ); + + //// относительный оффсет + //ULONG offset = fieldType.getFieldOffset() - m_typeInfo.getFieldOffset(); + + //if ( fieldType.isBaseType() || fieldType.isPtr() ) + //{ + // sstr << hex << "+" << offset << " " << fieldType.name(); + // sstr << fieldType.printValue( &(m_buffer.begin() + offset)[0], fieldType.fullSize() ); + //} + //else + //{ + // if ( fieldType.count() == 1 ) + // { + // sstr << hex << "+" << offset << " " << fieldType.name() << endl; + // } + // else + // { + // sstr << hex << "+" << offset << " " << fieldType.name() << "[" << dec << "]" << endl; + // } + //} } return sstr.str(); } -///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// -void -typedVarClass::printField(const TypeInfo::TypeField &field, stringstream &sstr) const +ULONG +sizeofType( const std::string &moduleName, const std::string &typeName ) { - if ( field.type.isComplex() && !field.type.isPtr()) - sstr << field.type.name(); + return TypeInfo::get( moduleName, typeName ).size(); +} + +/////////////////////////////////////////////////////////////////////////////////// + +boost::python::object +containingRecord( ULONG64 address, const std::string &moduleName, const std::string &typeName, const std::string &fieldName ) +{ + address = addr64(address); + + HRESULT hres; + ULONG64 moduleBase; + + hres = dbgExt->symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase ); + if ( FAILED( hres ) ) + throw TypeException(); + + ULONG typeId; + hres = dbgExt->symbols->GetTypeId( moduleBase, typeName.c_str(), &typeId ); + if ( FAILED( hres ) ) + throw TypeException(); + + ULONG fieldTypeId; + ULONG fieldOffset; + hres = dbgExt->symbols3->GetFieldTypeAndOffset( moduleBase, typeId, fieldName.c_str(), &fieldTypeId, &fieldOffset ); + if ( FAILED( hres ) ) + throw TypeException(); + + TypedVar var( moduleName, typeName, address - fieldOffset ); + + return boost::python::object( var ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +boost::python::object +loadTypedVarList( ULONG64 address, const std::string &moduleName, const std::string &typeName, const std::string &listEntryName ) +{ + address = addr64(address); + + ULONG64 entryAddress = 0; + + const TypeInfo &typeInfo = TypeInfo::get( moduleName, typeName ); + + boost::python::list objList; + + + TypeInfo fieldType = typeInfo.getField( listEntryName ); + + if ( fieldType.name() == ( typeName + "*" ) ) + { + for( entryAddress = loadPtrByPtr( address ); entryAddress != address && entryAddress != NULL; entryAddress = loadPtrByPtr( entryAddress + fieldType.getFieldOffset() ) ) + objList.append( TypedVar( moduleName, typeName, entryAddress ) ); + } else { - boost::python::object attr = getPyObj().attr( field.name.c_str() ); - - if ( field.size == field.type.size() ) - { - if ( attr.ptr() == Py_None ) - { - sstr << "memory error"; - } - else - { - unsigned __int64 val = boost::python::extract( attr ); - - sstr << hex << "0x" << val; - - if ( field.type.name() == "char*" ) - { - char buf[0x100]; - if ( loadCStrToBuffer( val, buf, sizeof(buf) ) ) - sstr << " (" << buf << " )"; - else - sstr << " ( read string error )"; - } - else if ( field.type.name() == "unsigned short*" ) - { - wchar_t wbuf[0x100]; - if ( loadWStrToBuffer( val, wbuf, sizeof(wbuf) ) ) - { - char mbBuf[0x100] = { 0 }; - - WideCharToMultiByte( - CP_ACP, - 0, - wbuf, - (ULONG)wcslen(wbuf) + 1, - mbBuf, - sizeof(mbBuf), - NULL, - NULL); - - sstr << " (" << mbBuf << " )"; - } - else - sstr << " ( read string error )"; - } - else - { - sstr << dec << " ( " << val << " )"; - } - } - } - else - { - for ( size_t i = 0; i < field.size/field.type.size(); ++i ) - { - unsigned __int64 val = boost::python::extract( attr[i] ); - - sstr << "\n\t\t\t[" << i << "] " << hex << "0x" << val << dec << " ( " << val << " )"; - } - } + for( entryAddress = loadPtrByPtr( address ); entryAddress != address && entryAddress != NULL; entryAddress = loadPtrByPtr( entryAddress ) ) + objList.append( containingRecord( entryAddress, moduleName, typeName, listEntryName ) ); } + + return objList; +} + +///////////////////////////////////////////////////////////////////////////////// + +boost::python::object +loadTypedVarArray( ULONG64 address, const std::string &moduleName, const std::string &typeName, long number ) +{ + address = addr64(address); + + const TypeInfo &typeInfo = TypeInfo::get( moduleName, typeName ); + + boost::python::list objList; + + for( long i = 0; i < number; ++i ) + objList.append( TypedVar(typeInfo, address + i * typeInfo.size() ) ); + + return objList; } ///////////////////////////////////////////////////////////////////////////////// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// +//boost::python::object +//loadTypedVar( const std::string &moduleName, const std::string &typeName, ULONG64 address ) +//{ +// const TypeInfo *typeInfo = TypeInfo::get( moduleName, typeName ); +// +// return typeInfo != NULL ? typeInfo->load( address ) : boost::python::object(); +//} +// +/////////////////////////////////////////////////////////////////////////////////////// +// +//ULONG +//sizeofType( const std::string &moduleName, const std::string &typeName ) +//{ +// 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" ); +// +// const TypeInfo *typeInfo = TypeInfo::get( moduleName, typeName ); +// +// return typeInfo != NULL ? (ULONG)typeInfo->size() : 0L; +// } +// 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; +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//boost::python::object +//containingRecord( ULONG64 address, const std::string &moduleName, const std::string &typeName, const std::string &fieldName ) +//{ +// HRESULT hres; +// +// try { +// +// ULONG64 moduleBase; +// +// hres = dbgExt->symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase ); +// 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" ); +// +// ULONG fieldTypeId; +// ULONG fieldOffset; +// hres = dbgExt->symbols3->GetFieldTypeAndOffset( moduleBase, typeId, fieldName.c_str(), &fieldTypeId, &fieldOffset ); +// +// return loadTypedVar( moduleName, typeName, 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(); +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//boost::python::object +//getTypeClass( const std::string &moduleName, const std::string &typeName ) +//{ +// try +// { +// const TypeInfo *typeInfo = TypeInfo::get( moduleName, typeName ); +// +// return typeInfo != NULL ? typeInfo->build() : 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(); +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//boost::python::object +//loadTypedVarList( ULONG64 address, const std::string &moduleName, const std::string &typeName, const std::string &listEntryName ) +//{ +// address = addr64(address); +// +// ULONG64 entryAddress = 0; +// +// const TypeInfo *typeInfo = TypeInfo::get( moduleName, typeName ); +// +// if ( !typeInfo ) +// return boost::python::object(); +// +// boost::python::list objList; +// +// for ( TypeInfo::TypeFieldList::const_iterator field = typeInfo->getFields().begin(); field != typeInfo->getFields().end(); field++ ) +// { +// if ( field->name == listEntryName ) +// { +// if ( field->type.name() == ( typeName + "*" ) ) +// { +// for( entryAddress = loadPtrByPtr( address ); entryAddress != address && entryAddress != NULL; entryAddress = loadPtrByPtr( entryAddress + field->offset ) ) +// objList.append( loadTypedVar( moduleName, typeName, entryAddress ) ); +// } +// else +// { +// for( entryAddress = loadPtrByPtr( address ); entryAddress != address && entryAddress != NULL; entryAddress = loadPtrByPtr( entryAddress ) ) +// objList.append( containingRecord( entryAddress, moduleName, typeName, listEntryName ) ); +// } +// +// return objList; +// } +// } +// +// return boost::python::object(); +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//boost::python::object +//loadTypedVarArray( ULONG64 address, const std::string &moduleName, const std::string &typeName, long number ) +//{ +// boost::python::list objList; +// +// const TypeInfo *typeInfo = TypeInfo::get( moduleName, typeName ); +// +// if ( !typeInfo ) +// return boost::python::object(); +// +// for( long i = 0; i < number; ++i ) +// objList.append( loadTypedVar( moduleName, typeName, address + i * typeInfo->size() ) ); +// +// return objList; +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//bool +//isBaseType( const std::string &typeName ); +// +//template< typename valType> +//boost::python::object +//valueLoader( PVOID address, ULONG size ); +// +//template<> +//boost::python::object +//valueLoader( PVOID address, ULONG size ) +//{ +// if ( is64bitSystem() ) +// return valueLoader<__int64>( address, size ); +// else +// return valueLoader( address, size ); +//} +// +//boost::python::object +//voidLoader( PVOID address, ULONG size ) { +// return boost::python::object(); +//} +// +//static const char* +//basicTypeNames[] = { +// "unsigned char", +// "char", +// "unsigned short", +// "short", +// "unsigned long", +// "long", +// "int", +// "unsigned int", +// "", +// "void", +// "double", +// "int64", +// "unsigned int64", +// "ptr" +//}; +// +//typedef +//boost::python::object +//(*basicTypeLoader)( PVOID address, ULONG size ); +// +//basicTypeLoader basicTypeLoaders[] = { +// valueLoader, +// valueLoader, +// valueLoader, +// valueLoader, +// valueLoader, +// valueLoader, +// valueLoader, +// valueLoader, +// valueLoader, +// voidLoader, +// valueLoader, +// valueLoader<__int64>, +// valueLoader +// }; +// +//size_t basicTypeSizes[] = { +// sizeof( unsigned char ), +// sizeof( char ), +// sizeof( unsigned short ), +// sizeof( short ), +// sizeof( unsigned long ), +// sizeof( long ), +// sizeof( int ), +// sizeof( unsigned int ), +// sizeof( void* ), +// 0, +// sizeof( double ), +// sizeof( __int64 ), +// sizeof( unsigned __int64 ) +//}; +// +/////////////////////////////////////////////////////////////////////////////////// +// +//TypeInfo::TypeInfoMap TypeInfo::g_typeInfoCache; +// +//const TypeInfo* +//TypeInfo::get( const std::string &moduleName, const std::string &typeName ) +//{ +// HRESULT hres; +// +// try { +// +// TypeInfoMap::iterator findIt = g_typeInfoCache.find( TypeName( moduleName, typeName ) ); +// +// if ( findIt != g_typeInfoCache.end() ) +// return &findIt->second; +// +// TypeInfo typeInfo( typeName ); +// +// do { +// +// if ( typeName.find("*") < typeName.size() ) +// { +// typeInfo.m_pointer = true; +// typeInfo.m_size = ptrSize(); +// break; +// } +// +// typeInfo.m_baseType = isBaseType( typeName ); +// if ( typeInfo.m_baseType ) +// { +// typeInfo.setupBaseType(); +// break; +// } +// +// ULONG64 moduleBase = 0; +// hres = dbgExt->symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase ); +// if ( FAILED( hres ) ) +// throw DbgException( "IDebugSymbol::GetModuleByModuleName failed" ); +// +// ULONG typeId = 0; +// hres = dbgExt->symbols->GetTypeId( moduleBase, typeInfo.m_typeName.c_str(), &typeId ); +// if ( FAILED( hres ) ) +// throw DbgException( "IDebugSymbol::GetTypeId failed" ); +// +// hres = dbgExt->symbols->GetTypeSize( moduleBase, typeId, &typeInfo.m_size ); +// if ( FAILED( hres ) ) +// throw DbgException( "IDebugSymbol::GetTypeSize failed" ); +// +// for ( ULONG i = 0; ; ++i ) +// { +// char fieldName[100]; +// hres = dbgExt->symbols2->GetFieldName( moduleBase, typeId, i, fieldName, sizeof(fieldName), NULL ); +// +// if ( FAILED( hres ) ) +// break; +// +// 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 ); +// if ( FAILED( hres ) ) +// 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() ) +// { +// TypeInfo unnamedType; +// if ( !getById( moduleName, fieldTypeId, unnamedType ) ) +// return NULL; +// +// typeInfo.m_fields.push_back( TypeField( fieldName, unnamedType, fieldSize, fieldOffset ) ); +// } +// else +// { +// const TypeInfo *fieldTypeInfo = get( moduleName, fieldTypeName ); +// if ( !fieldTypeInfo ) +// return NULL; +// +// typeInfo.m_fields.push_back( TypeField( fieldName, *fieldTypeInfo, fieldSize, fieldOffset ) ); +// } +// } +// +// } while( FALSE ); +// +// return &g_typeInfoCache.insert( std::make_pair( TypeName( moduleName, typeName ), typeInfo) ).first->second; +// } +// catch( std::exception& ) +// { +// //dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); +// // это нормально: на вход был передан не верный тип +// } +// catch(...) +// { +// dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); +// } +// +// return NULL; +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//bool +//TypeInfo::getById( const std::string &moduleName, ULONG typeId, TypeInfo& typeInfo ) +//{ +// HRESULT hres; +// +// try { +// +// ULONG64 moduleBase = 0; +// hres = dbgExt->symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase ); +// if ( FAILED( hres ) ) +// throw DbgException( "IDebugSymbol::GetModuleByModuleName failed" ); +// +// hres = dbgExt->symbols->GetTypeSize( moduleBase, typeId, &typeInfo.m_size ); +// if ( FAILED( hres ) ) +// throw DbgException( "IDebugSymbol::GetTypeSize failed" ); +// +// for ( ULONG i = 0; ; ++i ) +// { +// char fieldName[100]; +// hres = dbgExt->symbols2->GetFieldName( moduleBase, typeId, i, fieldName, sizeof(fieldName), NULL ); +// +// if ( FAILED( hres ) ) +// break; +// +// 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 ); +// if ( FAILED( hres ) ) +// throw DbgException( "IDebugSymbol::GetTypeSize failed" ); +// +// char fieldTypeName[100]; +// hres = dbgExt->symbols->GetTypeName( moduleBase, fieldTypeId, fieldTypeName, sizeof(fieldTypeName), NULL ); +// if ( FAILED( hres ) ) +// throw DbgException( "IDebugSymbol::GetTypeName failed" ); +// +// std::string fieldTypeNameStr( fieldTypeName ); +// +// if ( fieldTypeNameStr == "__unnamed" +// || fieldTypeNameStr.find("") < fieldTypeNameStr.size() ) +// { +// TypeInfo unnamedType; +// if ( !getById( moduleName, fieldTypeId, unnamedType ) ) +// return false; +// +// typeInfo.m_fields.push_back( TypeField( fieldName, unnamedType, fieldSize, fieldOffset ) ); +// } +// else +// { +// const TypeInfo *fieldTypeInfo = get( moduleName, fieldTypeName ); +// if ( !fieldTypeInfo ) +// return false; +// +// typeInfo.m_fields.push_back( TypeField( fieldName, *fieldTypeInfo, fieldSize, fieldOffset ) ); +// } +// } +// +// return true; +// } +// catch( std::exception& ) +// { +// //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; +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//void +//TypeInfo::setupBaseType() +//{ +// for ( int i = 0; i < sizeof( basicTypeSizes ) / sizeof( size_t ); ++i ) +// { +// if ( m_typeName == basicTypeNames[i] || +// m_typeName == ( std::string( basicTypeNames[i] ) + "[]" ) ) +// { +// m_size = (ULONG)basicTypeSizes[i]; +// return; +// } +// } +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//boost::python::object +//TypeInfo::build( ULONG offset /* = 0 */ ) const +//{ +// boost::shared_ptr ptr( new typeClass( *this, offset ) ); +// boost::python::object var( ptr ); +// ptr->setPyObj( var ); +// +// 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 targetAddr, PVOID cacheBuffer , ULONG offset /* = 0 */ ) const +//{ +// if ( !isOffsetValid( targetAddr) ) +// return boost::python::object(); +// +// boost::scoped_array rawBuffer; +// +// if ( cacheBuffer == NULL ) +// { +// rawBuffer.reset( new char[ m_size ] ); +// cacheBuffer = rawBuffer.get(); +// +// if ( !loadMemory( targetAddr, cacheBuffer, m_size ) ) +// return boost::python::object(); +// } +// +// if ( m_pointer ) +// return ptrLoader( (PVOID)( (ULONG_PTR)cacheBuffer + offset ) ); +// +// if ( m_baseType ) +// return loadBaseType( (PVOID)( (ULONG_PTR)cacheBuffer + offset ) ); +// +// boost::shared_ptr ptr( new typedVarClass( *this, offset, targetAddr ) ); +// boost::python::object var( ptr ); +// ptr->setPyObj( var ); +// +// 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.load( targetAddr + field->offset, cacheBuffer, offset + field->offset ); +// } +// else +// { +// boost::python::list arr; +// +// for ( unsigned int i = 0; i < field->size / field->type.size(); ++i ) +// { +// const ULONG locOffset = field->offset + i * (ULONG)field->type.size(); +// arr.append( field->type.load( targetAddr + locOffset, cacheBuffer, offset + locOffset ) ); +// } +// +// var.attr( field->name.c_str() ) = arr; +// } +// } +// +// return var; +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//bool +//isBaseType( const std::string &typeName ) +//{ +// for ( int i = 0; i < sizeof( basicTypeNames ) / sizeof( char* ); ++i ) +// { +// 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; +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//boost::python::object +//TypeInfo::loadBaseType( PVOID address ) const +//{ +// for ( int i = 0; i < sizeof( basicTypeNames ) / sizeof( char* ); ++i ) +// { +// 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 boost::python::object(); +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//template< typename valType> +//boost::python::object +//valueLoader( PVOID address, ULONG size ) +//{ +// if ( size == sizeof(valType) ) +// { +// valType v = *(valType*)address; +// return boost::python::long_( (unsigned __int64)v ); +// +// +// //if ( loadMemory( address, &v, sizeof(v) ) ) +// //{ +// // return boost::python::long_( (unsigned __int64)v ); +// //} +// } +// else +// { +// boost::python::dict arr; +// +// for ( unsigned int i = 0; i < size / sizeof(valType); ++i ) +// { +// valType v = *( (valType*)address + i ); +// //if ( !loadMemory( address + i * sizeof(valType), &v, sizeof(v) ) ) +// +// arr[i] = boost::python::long_( (unsigned __int64)v ); +// } +// +// return arr; +// } +// +// return boost::python::object(); +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//std::string typeClass::print() const +//{ +// stringstream sstr; +// +// 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->type.name() << " "; +// sstr << itField->name << " "; +// +// printField(*itField, sstr); +// +// sstr << std::endl; +// +// ++itField; +// } +// +// return sstr.str(); +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//void +//typedVarClass::printField(const TypeInfo::TypeField &field, stringstream &sstr) const +//{ +// if ( field.type.isComplex() && !field.type.isPtr()) +// sstr << field.type.name(); +// else +// { +// boost::python::object attr = getPyObj().attr( field.name.c_str() ); +// +// if ( field.size == field.type.size() ) +// { +// if ( attr.ptr() == Py_None ) +// { +// sstr << "memory error"; +// } +// else +// { +// unsigned __int64 val = boost::python::extract( attr ); +// +// sstr << hex << "0x" << val; +// +// if ( field.type.name() == "char*" ) +// { +// char buf[0x100]; +// if ( loadCStrToBuffer( val, buf, sizeof(buf) ) ) +// sstr << " (" << buf << " )"; +// else +// sstr << " ( read string error )"; +// } +// else if ( field.type.name() == "unsigned short*" ) +// { +// wchar_t wbuf[0x100]; +// if ( loadWStrToBuffer( val, wbuf, sizeof(wbuf) ) ) +// { +// char mbBuf[0x100] = { 0 }; +// +// WideCharToMultiByte( +// CP_ACP, +// 0, +// wbuf, +// (ULONG)wcslen(wbuf) + 1, +// mbBuf, +// sizeof(mbBuf), +// NULL, +// NULL); +// +// sstr << " (" << mbBuf << " )"; +// } +// else +// sstr << " ( read string error )"; +// } +// else +// { +// sstr << dec << " ( " << val << " )"; +// } +// } +// } +// else +// { +// for ( size_t i = 0; i < field.size/field.type.size(); ++i ) +// { +// unsigned __int64 val = boost::python::extract( attr[i] ); +// +// sstr << "\n\t\t\t[" << i << "] " << hex << "0x" << val << dec << " ( " << val << " )"; +// } +// } +// } +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +// diff --git a/pykd/dbgtype.h b/pykd/dbgtype.h index 26e424d..d1e9fe5 100644 --- a/pykd/dbgtype.h +++ b/pykd/dbgtype.h @@ -2,15 +2,251 @@ #include #include -#include +#include #include "dbgmem.h" #include "dbgsystem.h" -///////////////////////////////////////////////////////////////////////////////// +#include -boost::python::object -loadTypedVar( const std::string &moduleName, const std::string &typeName, ULONG64 address ); +/////////////////////////////////////////////////////////////////////////////////// + +class TypedVar; +class TypeInfo; + +/////////////////////////////////////////////////////////////////////////////////// + +class TypeInfo { + +public: + + TypeInfo() : + m_size(0), + m_arraySize( 0 ), + m_parentOffset( 0 ), + m_align( ptrSize() ), + m_isFreezed( false ) + {} + + TypeInfo( const std::string customName, ULONG align=0 ) : + m_typeName( customName ), + m_size( 0 ), + m_arraySize( 0 ), + m_parentOffset( 0 ), + m_isFreezed( false ), + m_align( align == 0 ? ptrSize() : align ) + {} + + TypeInfo( const std::string &moduleName, const std::string &typeName ); + + TypeInfo( const std::string &moduleName, ULONG64 moduleBase, ULONG typeId ); + + static + const TypeInfo& + get( const std::string &moduleName, const std::string &typeName ); + + ULONG + size() const { + return m_size; + } + + ULONG + count() const { + assert( m_size != 0 ); + return m_arraySize / m_size; + } + + ULONG + fullSize() const { + return m_arraySize; + } + + const std::string + name() const { + return m_typeName; + } + + const std::string + moduleName() const { + return m_moduleName; + } + + boost::python::object + load( void* buffer, size_t bufferLength ) const; + + std::string + printField( size_t index, void* buffer, size_t bufferLength ) const; + + std::string + print() const; + + TypeInfo + getField( const std::string &fieldName ) const; + + TypeInfo + getFieldAt( size_t index ) const; + + ULONG + getFieldOffset() const { + return m_parentOffset; + } + + boost::python::object + getFieldByIndex( boost::python::object &index ) const; + + size_t + getFieldCount() const { + return m_fields.size(); + } + + void + appendField( const TypeInfo &typeInfo, const std::string &fieldName, ULONG count = 1 ); + + bool + isBaseType() const { + return m_isBaseType; + } + + bool + isPtr() const { + return m_isPointer; + } + + boost::python::object + loadVar( ULONG64 targetOffset, ULONG count = 1) const; + +public: + + typedef std::map< std::pair, TypeInfo> TypeInfoMap; + + template< typename TTypeInfo> + struct TypeFieldT { + + std::string name; + + ULONG offset; + + ULONG size; + + TTypeInfo type; + + TypeFieldT( const std::string &name_, const TTypeInfo &type_, ULONG size_, ULONG offset_ ) : + name( name_ ), + size( size_ ), + offset( offset_ ), + type( type_ ) + {} + + std::string print() const; + }; + + typedef TypeFieldT TypeField; + + typedef std::vector TypeFieldList; + + + +private: + + typedef + boost::python::object + (*basicTypeLoader)( void* address, size_t size ); + + typedef + std::string + (*basicTypePrinter)( void* address, size_t size ); + + static TypeInfoMap g_typeInfoCache; + + static const char* basicTypeNames[]; + + static size_t basicTypeSizes[]; + + static basicTypeLoader basicTypeLoaders[]; + + static basicTypePrinter basicTypePrinters[]; + + ULONG m_size; + + ULONG m_arraySize; + + std::string m_typeName; + + std::string m_moduleName; + + TypeFieldList m_fields; + + bool m_isPointer; + + bool m_isBaseType; + + bool m_isFreezed; + + ULONG m_align; + + ULONG m_parentOffset; + + static bool checkBaseType( const std::string &typeName ); + + static ULONG getBaseTypeSize( const std::string &typeName ); +}; + + +/////////////////////////////////////////////////////////////////////////////////// + +class TypedVar { + +public: + + TypedVar() : + m_targetOffset ( 0 ) + {} + + TypedVar( const TypeInfo &typeInfo, ULONG64 targetOffset ) : + m_typeInfo( typeInfo ), + m_targetOffset( addr64(targetOffset) ) + {} + + TypedVar( const std::string &moduleName, const std::string &typeName, ULONG64 targetOffset ) : + m_typeInfo( moduleName, typeName ), + m_targetOffset( addr64(targetOffset) ) + {} + + ULONG64 + getAddress() const { + return m_targetOffset; + } + + ULONG + getSize() const { + return m_typeInfo.fullSize(); + } + + static + boost::python::object + getFieldWrap( PyObject* self, const std::string &fieldName ); + + boost::python::object + getField( boost::python::object &pyobj, const std::string &fieldName ); + + ULONG64 getTargetOffset() const { + return m_targetOffset; + } + + std::string print(); + +private: + + TypedVar( const TypeInfo &typeInfo, ULONG64 targetOffset, char* buffer, size_t bufferLength ); + + ULONG64 m_targetOffset; + + TypeInfo m_typeInfo; + + std::vector m_buffer; +}; + +/////////////////////////////////////////////////////////////////////////////////// boost::python::object loadTypedVarList( ULONG64 address, const std::string &moduleName, const std::string &typeName, const std::string &listEntryName ); @@ -21,250 +257,308 @@ loadTypedVarArray( ULONG64 address, const std::string &moduleName, const std::st boost::python::object containingRecord( ULONG64 address, const std::string &moduleName, const std::string &typeName, const std::string &fieldName ); -boost::python::object -getTypeClass( const std::string &moduleName, const std::string &typeName ); - ULONG sizeofType( const std::string &moduleName, const std::string &typeName ); +/////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////// -class TypeInfo { - -public: - - template< typename TTypeInfo> - struct TypeFieldT { - ULONG size; - ULONG offset; - TTypeInfo type; - std::string name; - - TypeFieldT( const std::string &name_, const TTypeInfo &type_, ULONG size_, ULONG offset_ ) : - name( name_ ), - size( size_ ), - offset( offset_ ), - type( type_ ) - {} - }; - struct TypeName { - std::string module; - std::string symbol; - - TypeName( const std::string &module_, const std::string &symbol_ ) : - module( module_ ), - symbol( symbol_ ) - {} - - bool - operator < ( const TypeName &typeName ) const { - - if ( typeName.module < module ) - return true; - - if ( typeName.module > module ) - return false; - - return typeName.symbol < symbol; - } - - }; - typedef TypeFieldT TypeField; - - typedef std::map TypeInfoMap; - - typedef std::list TypeFieldList; +//public: +// +// typedVarClass() : m_addr(0) +// {} +// +// typedVarClass( const TypeInfo &typeInfo, ULONG64 addr) : +// m_typeInfo( typeInfo ), +// m_addr( addr ) +// {} +// +// ULONG64 +// getAddress() const { +// return m_addr; +// } +// +// //virtual void +// //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: +// +// TypeInfo m_typeInfo; +// +// ULONG64 m_addr; +//}; -public: +/////////////////////////////////////////////////////////////////////////////////// - TypeInfo() : - m_size( 0 ), - m_baseType( false ), - m_pointer( false ) - {} - - TypeInfo( const std::string &typeName ) : - m_size( 0 ), - m_baseType( false ), - m_pointer( false ), - m_typeName( typeName ) - {} - - boost::python::object - load( ULONG64 targetAddr, PVOID cacheBuffer = NULL, 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; - } - const TypeFieldList& - getFields() const { - return m_fields; - } - - bool - isComplex() const { - return !m_baseType; - } - - bool - isPtr() const { - return m_pointer; - } - - static const TypeInfo* - get( const std::string &moduleName, const std::string &typeName ); - -private: - - static TypeInfoMap g_typeInfoCache; - - boost::python::object - loadBaseType( PVOID addr ) const; - - boost::python::object - ptrLoader( PVOID addr ) const { - if ( is64bitSystem() ) - return boost::python::object( *(PULONG64)addr ); - else - return boost::python::object( addr64( *(PULONG)addr ) ); - } - - void - setupBaseType(); - - static bool - getById( const std::string &moduleName, ULONG typeId, TypeInfo& typeInfo ); - -private: - - bool m_baseType; - bool m_pointer; - TypeFieldList m_fields; - std::string m_typeName; - ULONG m_size; -}; - -///////////////////////////////////////////////////////////////////////////////// - -class typeClass -{ -public: - - typeClass() - : m_offset(0) - { - } - - typeClass( - const TypeInfo &typeInfo, - ULONG offset - ) : m_typeInfo(typeInfo) - , m_offset(offset) - { - } - - // sizeof(TYPE) - ULONG size() const - { - return (ULONG)m_typeInfo.size(); - } - - void setPyObj( const boost::python::object &obj ) - { - m_pyobj = obj; - } - - // TypeInfo getter - TypeInfo &getTypeInfo() - { - return m_typeInfo; - } - const TypeInfo &getTypeInfo() const - { - return m_typeInfo; - } - - // boost::python::object getter - boost::python::object &getPyObj() - { - return m_pyobj; - } - const boost::python::object &getPyObj() const - { - return m_pyobj; - } - - std::string print() const; - - virtual void printField( - const TypeInfo::TypeField &field, - std::stringstream &sstr - ) const - { - // no data - nothing print - } - virtual void printSelf( - std::stringstream &sstr - ) const - { - // no data - nothing print - } - - // field offset getter/setter - ULONG getOffset() const { return m_offset; } - -private: - TypeInfo m_typeInfo; - ULONG m_offset; - boost::python::object m_pyobj; -}; - -///////////////////////////////////////////////////////////////////////////////// - -class typedVarClass : public typeClass { - -public: - - typedVarClass() : m_addr(0) - {} - - typedVarClass( const TypeInfo &typeInfo, ULONG offset, ULONG64 addr) : - typeClass( typeInfo, offset ), - m_addr( addr ) - {} - - ULONG64 - getAddress() const { - return m_addr; - } - - virtual void - 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: - - ULONG64 m_addr; -}; - -///////////////////////////////////////////////////////////////////////////////// \ No newline at end of file +// +//boost::python::object +//loadTypedVar( const std::string &moduleName, const std::string &typeName, ULONG64 address ); +// +//boost::python::object +//loadTypedVarList( ULONG64 address, const std::string &moduleName, const std::string &typeName, const std::string &listEntryName ); +// +//boost::python::object +//loadTypedVarArray( ULONG64 address, const std::string &moduleName, const std::string &typeName, long number ); +// +//boost::python::object +//containingRecord( ULONG64 address, const std::string &moduleName, const std::string &typeName, const std::string &fieldName ); +// +//boost::python::object +//getTypeClass( const std::string &moduleName, const std::string &typeName ); +// +//ULONG +//sizeofType( const std::string &moduleName, const std::string &typeName ); +// +// +/////////////////////////////////////////////////////////////////////////////////// +// +//class TypeInfo { +// +//public: +// +// template< typename TTypeInfo> +// struct TypeFieldT { +// ULONG size; +// ULONG offset; +// TTypeInfo type; +// std::string name; +// +// TypeFieldT( const std::string &name_, const TTypeInfo &type_, ULONG size_, ULONG offset_ ) : +// name( name_ ), +// size( size_ ), +// offset( offset_ ), +// type( type_ ) +// {} +// }; +// +// struct TypeName { +// std::string module; +// std::string symbol; +// +// TypeName( const std::string &module_, const std::string &symbol_ ) : +// module( module_ ), +// symbol( symbol_ ) +// {} +// +// bool +// operator < ( const TypeName &typeName ) const { +// +// if ( typeName.module < module ) +// return true; +// +// if ( typeName.module > module ) +// return false; +// +// return typeName.symbol < symbol; +// } +// +// }; +// +// typedef TypeFieldT TypeField; +// +// typedef std::map TypeInfoMap; +// +// typedef std::list TypeFieldList; +// +//public: +// +// TypeInfo() : +// m_size( 0 ), +// m_baseType( false ), +// m_pointer( false ) +// {} +// +// TypeInfo( const std::string &typeName ) : +// m_size( 0 ), +// m_baseType( false ), +// m_pointer( false ), +// m_typeName( typeName ) +// {} +// +// boost::python::object +// load( ULONG64 targetAddr, PVOID cacheBuffer = NULL, 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; +// } +// +// const TypeFieldList& +// getFields() const { +// return m_fields; +// } +// +// bool +// isComplex() const { +// return !m_baseType; +// } +// +// bool +// isPtr() const { +// return m_pointer; +// } +// +// static const TypeInfo* +// get( const std::string &moduleName, const std::string &typeName ); +// +//private: +// +// static TypeInfoMap g_typeInfoCache; +// +// boost::python::object +// loadBaseType( PVOID addr ) const; +// +// boost::python::object +// ptrLoader( PVOID addr ) const { +// if ( is64bitSystem() ) +// return boost::python::object( *(PULONG64)addr ); +// else +// return boost::python::object( addr64( *(PULONG)addr ) ); +// } +// +// void +// setupBaseType(); +// +// static bool +// getById( const std::string &moduleName, ULONG typeId, TypeInfo& typeInfo ); +// +//private: +// +// bool m_baseType; +// bool m_pointer; +// TypeFieldList m_fields; +// std::string m_typeName; +// ULONG m_size; +//}; +// +/////////////////////////////////////////////////////////////////////////////////// +// +//class typeClass +//{ +//public: +// +// typeClass() +// : m_offset(0) +// { +// } +// +// typeClass( +// const TypeInfo &typeInfo, +// ULONG offset +// ) : m_typeInfo(typeInfo) +// , m_offset(offset) +// { +// } +// +// // sizeof(TYPE) +// ULONG size() const +// { +// return (ULONG)m_typeInfo.size(); +// } +// +// void setPyObj( const boost::python::object &obj ) +// { +// m_pyobj = obj; +// } +// +// // TypeInfo getter +// TypeInfo &getTypeInfo() +// { +// return m_typeInfo; +// } +// const TypeInfo &getTypeInfo() const +// { +// return m_typeInfo; +// } +// +// // boost::python::object getter +// boost::python::object &getPyObj() +// { +// return m_pyobj; +// } +// const boost::python::object &getPyObj() const +// { +// return m_pyobj; +// } +// +// std::string print() const; +// +// virtual void printField( +// const TypeInfo::TypeField &field, +// std::stringstream &sstr +// ) const +// { +// // no data - nothing print +// } +// virtual void printSelf( +// std::stringstream &sstr +// ) const +// { +// // no data - nothing print +// } +// +// // field offset getter/setter +// ULONG getOffset() const { return m_offset; } +// +//private: +// TypeInfo m_typeInfo; +// ULONG m_offset; +// boost::python::object m_pyobj; +//}; +// +/////////////////////////////////////////////////////////////////////////////////// +// +//class typedVarClass : public typeClass { +// +//public: +// +// typedVarClass() : m_addr(0) +// {} +// +// typedVarClass( const TypeInfo &typeInfo, ULONG offset, ULONG64 addr) : +// typeClass( typeInfo, offset ), +// m_addr( addr ) +// {} +// +// ULONG64 +// getAddress() const { +// return m_addr; +// } +// +// virtual void +// 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: +// +// ULONG64 m_addr; +//}; +// +/////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/pykd.vcproj b/pykd/pykd.vcproj index 4867e86..363d9fb 100644 --- a/pykd/pykd.vcproj +++ b/pykd/pykd.vcproj @@ -356,6 +356,10 @@ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > + + @@ -368,6 +372,10 @@ RelativePath=".\dbgeventcb.cpp" > + + @@ -462,6 +470,10 @@ Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > + +