From 33993919037383ae495ed3e3b843921a4dec4810 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Wed, 22 May 2013 08:36:33 +0000 Subject: [PATCH] [0.3.x] added : module class tests git-svn-id: https://pykd.svn.codeplex.com/svn@83752 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgexcept.cpp | 57 +++++++++ pykd/dbgexcept.h | 256 +++++++++++++++++++++++++++++++++++++ pykd/pykd.vcxproj | 4 + pykd/pykd.vcxproj.filters | 12 ++ pykd/pymod.cpp | 75 +++++------ test/scripts/memtest.py | 14 +- test/scripts/moduletest.py | 6 +- test/scripts/pykdtest.py | 4 +- 8 files changed, 379 insertions(+), 49 deletions(-) create mode 100644 pykd/dbgexcept.cpp create mode 100644 pykd/dbgexcept.h diff --git a/pykd/dbgexcept.cpp b/pykd/dbgexcept.cpp new file mode 100644 index 0000000..96acd83 --- /dev/null +++ b/pykd/dbgexcept.cpp @@ -0,0 +1,57 @@ +#include "stdafx.h" + +#include "kdlib/dbgio.h" + +#include "dbgexcept.h" + +namespace pykd { + +/////////////////////////////////////////////////////////////////////////////////// + +python::handle<> exceptPyType::pyExceptType; +python::handle<> exceptPyType::pyExceptType; +python::handle<> exceptPyType::pyExceptType; +//python::handle<> exceptPyType::pyExceptType; +//python::handle<> exceptPyType::pyExceptType; +////python::handle<> exceptPyType::pyExceptType; +//python::handle<> exceptPyType::pyExceptType; +//python::handle<> exceptPyType::pyExceptType; +//python::handle<> exceptPyType::pyExceptType; +//python::handle<> exceptPyType::pyExceptType; + +/////////////////////////////////////////////////////////////////////////////////// + +void printException() +{ + // ошибка в скрипте + PyObject *errtype = NULL, *errvalue = NULL, *traceback = NULL; + + PyErr_Fetch( &errtype, &errvalue, &traceback ); + + PyErr_NormalizeException( &errtype, &errvalue, &traceback ); + + if ( errtype == PyExc_SystemExit ) + return; + + python::object tracebackModule = python::import("traceback"); + + std::wstringstream sstr; + + python::object lst = + python::object( tracebackModule.attr("format_exception" ) )( + python::handle<>( errtype ), + python::handle<>( python::allow_null( errvalue ) ), + python::handle<>( python::allow_null( traceback ) ) ); + + sstr << std::endl << std::endl; + + for ( long i = 0; i < python::len(lst); ++i ) + sstr << std::wstring( python::extract(lst[i]) ) << std::endl; + + kdlib::eprintln( sstr.str() ); +} + + +/////////////////////////////////////////////////////////////////////////////////// + +}; // end namespace pykd diff --git a/pykd/dbgexcept.h b/pykd/dbgexcept.h new file mode 100644 index 0000000..2a85d95 --- /dev/null +++ b/pykd/dbgexcept.h @@ -0,0 +1,256 @@ +#pragma once + +#include +#include + +#include "kdlib/exceptions.h" + +/////////////////////////////////////////////////////////////////////////////// + +namespace pykd { + +template< class TExcept > +struct exceptPyType{ + static python::handle<> pyExceptType; +}; + +template< class TExcept, class TBaseExcept = python::detail::not_specified > +class exception { + +public: + + exception( const std::string& className, const std::string& classDesc ) + { + python::handle<> basedtype; + + if ( boost::is_same::value ) + { + basedtype = python::handle<>(PyExc_Exception); + } + else + { + basedtype = exceptPyType::pyExceptType; + } + + python::dict ob_dict; + + ob_dict["__doc__"] = classDesc; + + python::tuple ob_bases = python::make_tuple( basedtype ); + + python::object ob = python::object( python::handle<>(Py_TYPE(basedtype.get()) ) )( className, ob_bases, ob_dict ); + + python::scope().attr( className.c_str() ) = ob; + + exceptPyType::pyExceptType = python::handle<>( ob.ptr() ); + + python::register_exception_translator( &exceptionTranslate ); + } + + static + void + exceptionTranslate(const TExcept &e ) { + + python::object exceptObj = python::object( exceptPyType::pyExceptType )( e.what() ); + + PyErr_SetObject( exceptPyType::pyExceptType.get(), exceptObj.ptr()); + } + +}; + +//////////////////////////////////////////////////////////////////////////////// +// +//class PyException : public std::exception +//{ +//public: +// +// PyException( PyObject* pyObj, const std::string &desc ) : +// std::exception( desc.c_str() ), +// m_typeObj( pyObj ) +// {} +// +// static +// void +// exceptionTranslate(const PyException &e ) { +// PyErr_SetString( e.m_typeObj, e.what() ); +// } +// +//private: +// +// PyObject* m_typeObj; +//}; +// +/////////////////////////////////////////////////////////////////////////////////// +// +//class DbgException : public std::exception +//{ +//public: +// +// DbgException( const std::string &desc ) : +// std::exception( desc.c_str() ) +// {} +// +// DbgException( const std::string &methodName, HRESULT hres ) : +// std::exception( buildHresultDesc( methodName, hres ).c_str() ) +// {} +// +// const char* getDesc() const { +// return what(); +// } +// +//private: +// +// std::string buildHresultDesc( const std::string &methodName, HRESULT hres ) +// { +// std::stringstream sstream; +// sstream << "Call " << methodName << " failed\n"; +// sstream << "HRESULT 0x" << std::hex << hres; +// return sstream.str(); +// } +// +//}; +// +/////////////////////////////////////////////////////////////////////////////////// +// +//class SymbolException : public DbgException +//{ +//public: +// +// SymbolException( const std::string &desc ) : +// DbgException( desc.c_str() ) +// {} +// +//}; +// +/////////////////////////////////////////////////////////////////////////////////// +// +//class WaitEventException : public DbgException +//{ +//public: +// +// WaitEventException() +// : DbgException( "None of the targets could generate events" ) +// {} +//}; +// +/////////////////////////////////////////////////////////////////////////////////// +// +//class TypeException : public SymbolException +//{ +//public: +// +// TypeException( const std::string &typeName, const std::string &errorStr ) +// : SymbolException( buildDesc( typeName, errorStr ) ) +// {} +// +//private: +// +// static std::string buildDesc( const std::string &typeName, const std::string &errorStr ) +// { +// std::stringstream sstr; +// sstr << typeName << " : " << errorStr; +// return sstr.str(); +// } +//}; +// +/////////////////////////////////////////////////////////////////////////////////// +// +//class MemoryException : public DbgException +//{ +//public: +// +// MemoryException( ULONG64 targetAddr, bool phyAddr = false ) : +// m_targetAddress( targetAddr ), +// DbgException( buildDesc( targetAddr, phyAddr ) ) +// {} +// +// ULONG64 +// getAddress() const { +// return m_targetAddress; +// } +// +//private: +// +// ULONG64 m_targetAddress; +// +// static std::string buildDesc( 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"; +// +// return sstr.str(); +// } +//}; +// +/////////////////////////////////////////////////////////////////////////////////// +// +//class AddSyntheticSymbolException : public DbgException +//{ +//public: +// +// AddSyntheticSymbolException(HRESULT hres) +// : DbgException( buildDesc(hres) ) +// { +// } +// +//private: +// static std::string buildDesc(HRESULT hres) { +// std::stringstream sstream; +// sstream << "Add synthetic symbol faield\n"; +// sstream << "HRESULT 0x" << std::hex << hres; +// return sstream.str(); +// } +//}; +// +// +/////////////////////////////////////////////////////////////////////////////////// +// +//class WrongEventTypeException : public DbgException +//{ +//public: +// +// WrongEventTypeException(ULONG eventType) +// : DbgException( buildDesc(eventType) ) +// {} +// +//private: +// static std::string buildDesc(ULONG eventType) { +// std::stringstream sstream; +// sstream << "Unknown/not compatible debug event type: 0x"; +// sstream << std::hex << eventType; +// return sstream.str(); +// } +//}; +// +/////////////////////////////////////////////////////////////////////////////////// +// +//class ImplementException : public DbgException +//{ +//public: +// +// ImplementException( const std::string &file, int line, const std::string &msg ) : +// DbgException( buildDesc(file,line, msg) ) +// {} +// +//private: +// +// static std::string buildDesc( const std::string &file, int line, const std::string &msg ) +// { +// std::stringstream sstream; +// sstream << "File: " << file << " Line: " << line << " " << msg; +// return sstream.str(); +// } +// +//}; +// +/////////////////////////////////////////////////////////////////////////////////// + +void printException(); + +/////////////////////////////////////////////////////////////////////////////////// + +}; // namespace pykd + diff --git a/pykd/pykd.vcxproj b/pykd/pykd.vcxproj index 01c72b0..deaab4f 100644 --- a/pykd/pykd.vcxproj +++ b/pykd/pykd.vcxproj @@ -123,14 +123,18 @@ + + + + false false diff --git a/pykd/pykd.vcxproj.filters b/pykd/pykd.vcxproj.filters index a289c00..5d70400 100644 --- a/pykd/pykd.vcxproj.filters +++ b/pykd/pykd.vcxproj.filters @@ -33,6 +33,15 @@ Header Files + + Header Files + + + Header Files + + + Header Files + @@ -50,6 +59,9 @@ Source Files + + Source Files + diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index 55f33f5..6f92403 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -7,6 +7,8 @@ #include "variant.h" #include "module.h" #include "target.h" +#include "dbgexcept.h" +#include "memaccess.h" using namespace pykd; @@ -55,17 +57,17 @@ BOOST_PYTHON_FUNCTION_OVERLOADS( dprintln_, kdlib::dprintln, 1, 2 ); BOOST_PYTHON_FUNCTION_OVERLOADS( loadChars_, kdlib::loadChars, 2, 3 ); BOOST_PYTHON_FUNCTION_OVERLOADS( loadWChars_, kdlib::loadWChars, 2, 3 ); -BOOST_PYTHON_FUNCTION_OVERLOADS( loadBytes_, kdlib::loadBytes, 2, 3 ); -BOOST_PYTHON_FUNCTION_OVERLOADS( loadWords_, kdlib::loadWords, 2, 3 ); -BOOST_PYTHON_FUNCTION_OVERLOADS( loadDWords_, kdlib::loadDWords, 2, 3 ); -BOOST_PYTHON_FUNCTION_OVERLOADS( loadQWords_, kdlib::loadQWords, 2, 3 ); -BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignBytes_, kdlib::loadSignBytes, 2, 3 ); -BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignWords_, kdlib::loadSignWords, 2, 3 ); -BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignDWords_, kdlib::loadSignDWords, 2, 3 ); -BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignQWords_, kdlib::loadSignQWords, 2, 3 ); -BOOST_PYTHON_FUNCTION_OVERLOADS( loadFloats_, kdlib::loadFloats, 2, 3 ); -BOOST_PYTHON_FUNCTION_OVERLOADS( loadDoubles_, kdlib::loadDoubles, 2, 3 ); -//BOOST_PYTHON_FUNCTION_OVERLOADS( compareMemory_, compareMemory, 3, 4 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( loadBytes_, loadBytes, 2, 3 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( loadWords_, loadWords, 2, 3 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( loadDWords_, loadDWords, 2, 3 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( loadQWords_, loadQWords, 2, 3 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignBytes_, loadSignBytes, 2, 3 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignWords_, loadSignWords, 2, 3 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignDWords_, loadSignDWords, 2, 3 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignQWords_, loadSignQWords, 2, 3 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( loadFloats_, loadFloats, 2, 3 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( loadDoubles_, loadDoubles, 2, 3 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( compareMemory_, kdlib::compareMemory, 3, 4 ); // //BOOST_PYTHON_FUNCTION_OVERLOADS( getSourceLine_, getSourceLine, 0, 1 ); //BOOST_PYTHON_FUNCTION_OVERLOADS( getSourceFile_, getSourceFile, 0, 1 ); @@ -156,18 +158,17 @@ BOOST_PYTHON_MODULE( pykd ) // python::def("getSystemVersion", &getSystemVersion, // "Return systemVersion"); - // // Manage target memory access - // python::def( "addr64", &addr64, - // "Extend address to 64 bits formats" ); - // python::def( "isValid", &isVaValid, - // "Check if the virtual address is valid" ); - // python::def( "compareMemory", &compareMemory, compareMemory_( python::args( "offset1", "offset2", "length", "phyAddr" ), - // "Compare two memory buffers by virtual or physical addresses" ) ); - - // python::def( "findMemoryRegion", &findMemoryRegionPy, - // "Return address of begining valid memory region nearest to offset" ); - // python::def( "getVaProtect", &getVaProtect, - // "Return memory attributes" ); + // Manage target memory access + python::def( "addr64", &kdlib::addr64, + "Extend address to 64 bits formats" ); + python::def( "isValid", &kdlib::isVaValid, + "Check if the virtual address is valid" ); + python::def( "compareMemory", &kdlib::compareMemory, compareMemory_( python::args( "offset1", "offset2", "length", "phyAddr" ), + "Compare two memory buffers by virtual or physical addresses" ) ); + //python::def( "findMemoryRegion", &kdlib::findMemoryRegion, + // "Return address of begining valid memory region nearest to offset" ); + //python::def( "getVaProtect", &kdlib::getVaProtect, + // "Return memory attributes" ); python::def( "ptrByte", &kdlib::ptrByte, "Read an unsigned 1-byte integer from the target memory" ); @@ -196,21 +197,21 @@ BOOST_PYTHON_MODULE( pykd ) python::def( "ptrDouble", &kdlib::ptrDoubleFloat, "Read a float with single precision from the target memory" ); - python::def( "loadBytes", &kdlib::loadBytes, loadBytes_( python::args( "offset", "count", "phyAddr" ), + python::def( "loadBytes", &loadBytes, loadBytes_( python::args( "offset", "count", "phyAddr" ), "Read the block of the target's memory and return it as list of unsigned bytes" ) ); - python::def( "loadWords", &kdlib::loadWords, loadWords_( python::args( "offset", "count", "phyAddr" ), + python::def( "loadWords", &loadWords, loadWords_( python::args( "offset", "count", "phyAddr" ), "Read the block of the target's memory and return it as list of unsigned shorts" ) ); - python::def( "loadDWords", &kdlib::loadDWords, loadDWords_( python::args( "offset", "count", "phyAddr" ), + python::def( "loadDWords", &loadDWords, loadDWords_( python::args( "offset", "count", "phyAddr" ), "Read the block of the target's memory and return it as list of unsigned long ( double word )" ) ); - python::def( "loadQWords", &kdlib::loadQWords, loadQWords_( python::args( "offset", "count", "phyAddr" ), + python::def( "loadQWords", &loadQWords, loadQWords_( python::args( "offset", "count", "phyAddr" ), "Read the block of the target's memory and return it as list of unsigned long long ( quad word )" ) ); - python::def( "loadSignBytes", &kdlib::loadSignBytes, loadSignBytes_( python::args( "offset", "count", "phyAddr" ), + python::def( "loadSignBytes", &loadSignBytes, loadSignBytes_( python::args( "offset", "count", "phyAddr" ), "Read the block of the target's memory and return it as list of signed bytes" ) ); - python::def( "loadSignWords", &kdlib::loadSignWords, loadSignWords_( python::args( "offset", "count", "phyAddr" ), + python::def( "loadSignWords", &loadSignWords, loadSignWords_( python::args( "offset", "count", "phyAddr" ), "Read the block of the target's memory and return it as list of signed words" ) ); - python::def( "loadSignDWords", &kdlib::loadSignDWords, loadSignDWords_( python::args( "offset", "count", "phyAddr" ), + python::def( "loadSignDWords", &loadSignDWords, loadSignDWords_( python::args( "offset", "count", "phyAddr" ), "Read the block of the target's memory and return it as list of signed longs" ) ); - python::def( "loadSignQWords", &kdlib::loadSignQWords, loadSignQWords_( python::args( "offset", "count", "phyAddr" ), + python::def( "loadSignQWords", &loadSignQWords, loadSignQWords_( python::args( "offset", "count", "phyAddr" ), "Read the block of the target's memory and return it as list of signed long longs" ) ); python::def( "loadChars", &kdlib::loadChars, loadChars_( python::args( "address", "count", "phyAddr" ), "Load string from target memory" ) ); @@ -228,9 +229,9 @@ BOOST_PYTHON_MODULE( pykd ) // "Return list of pointers, each points to next" ); //python::def( "loadPtrs", &loadPtrArray, // "Read the block of the target's memory and return it as a list of pointers" ); - python::def( "loadFloats", &kdlib::loadFloats, loadFloats_( python::args( "offset", "count", "phyAddr" ), + python::def( "loadFloats", &loadFloats, loadFloats_( python::args( "offset", "count", "phyAddr" ), "Read the block of the target's memory and return it as list of floats" ) ); - python::def( "loadDoubles", &kdlib::loadDoubles, loadDoubles_( python::args( "offset", "count", "phyAddr" ), + python::def( "loadDoubles", &loadDoubles, loadDoubles_( python::args( "offset", "count", "phyAddr" ), "Read the block of the target's memory and return it as list of doubles" ) ); // // types and vaiables @@ -380,8 +381,8 @@ python::class_( "numVariant", "numVarian "Return name of the module" ) .def("reload", &kdlib::Module::reloadSymbols, "(Re)load symbols for the module" ) - //.def("image", &Module::getImageName, - // "Return name of the image of the module" ) + .def("image", &kdlib::Module::getImageName, + "Return name of the image of the module" ) //.def("symfile", &Module::getSymFile, // "Return the full path to the module's symbol information" ) //.def("offset", &Module::getSymbolOffset, @@ -664,8 +665,8 @@ python::class_( "numVariant", "numVarian // // wrapper for standart python exceptions // python::register_exception_translator( &PyException::exceptionTranslate ); - // pykd::exception( "BaseException", "Pykd base exception class" ); - // pykd::exception( "MemoryException", "Target memory access exception class" ); + pykd::exception( "DbgException", "Pykd base exception class" ); + pykd::exception( "MemoryException", "Target memory access exception class" ); // pykd::exception( "WaitEventException", "None of the targets could generate events" ); // pykd::exception( "WrongEventTypeException", "Unknown last event type" ); // pykd::exception( "SymbolException", "Symbol exception" ); diff --git a/test/scripts/memtest.py b/test/scripts/memtest.py index 9117c4b..67c8a1d 100644 --- a/test/scripts/memtest.py +++ b/test/scripts/memtest.py @@ -45,7 +45,7 @@ class MemoryTest( unittest.TestCase ): charArray = pykd.loadSignBytes( target.module.ucharArray, 5 ) testArray = [ 0, 10, 0x78, -128, -1 ] self.assertEqual( 5, len(charArray) ) - self.assertEqual( 0, len( [ charArray[i] for i in xrange(len(testArray)) if charArray[i] != testArray[i] ] ) ) + self.assertEqual( 0, len( [ charArray[i] for i in xrange(len(testArray)) if charArray[i] != testArray[i] ] ) ) def testLoadSignWords( self ): loadArray = pykd.loadSignWords( target.module.ushortArray, 5 ) @@ -111,13 +111,13 @@ class MemoryTest( unittest.TestCase ): self.assertTrue( math.fabs( pykd.ptrDouble( target.module.g_double) - 5.1234567891 ) < 0.0000001 ) def testLoadFloats(self): - testArray = [ 1.0, 2.001, -3.0004 ]; - readArray = pykd.loadFloats( target.module.floatArray, 3 ); - for i in range(0,3): + testArray = [ 1.0, 0.001, -199.999, 20000.01, 0.111111 ]; + readArray = pykd.loadFloats( target.module.floatArray, 5 ); + for i in range(5): self.assertTrue( math.fabs( testArray[i] - readArray[i] ) < 0.001 ) def testLoadDoubles(self): - testArray = [ 1.0, 2.0000001, -3.0000004 ]; - readArray = pykd.loadDoubles( target.module.doubleArray, 3 ); - for i in range(0,3): + testArray = [ 1.0000000, 0.0000000001, -199.99999999998, 200000.00000001, 0.3333333333 ]; + readArray = pykd.loadDoubles( target.module.doubleArray, 5 ); + for i in range(5): self.assertTrue( math.fabs( testArray[i] - readArray[i] ) < 0.0000001 ) diff --git a/test/scripts/moduletest.py b/test/scripts/moduletest.py index 1b960b2..a0c7a7d 100644 --- a/test/scripts/moduletest.py +++ b/test/scripts/moduletest.py @@ -40,13 +40,13 @@ class ModuleTest( unittest.TestCase ): self.assertEqual( target.module.name() + ".exe", target.module.image() ) def testFindModule( self ): - self.assertRaises( pykd.BaseException, pykd.module, target.module.begin() - 0x10 ) + self.assertRaises( pykd.DbgException, pykd.module, target.module.begin() - 0x10 ) self.assertNotEqual( None, pykd.module( target.module.begin() ) ) self.assertNotEqual( None, pykd.module( target.module.begin() + 0x10) ) - self.assertRaises( pykd.BaseException, pykd.module, target.module.end() ) - self.assertRaises( pykd.BaseException, pykd.module, target.module.end() + 0x10 ) + self.assertRaises( pykd.DbgException, pykd.module, target.module.end() ) + self.assertRaises( pykd.DbgException, pykd.module, target.module.end() + 0x10 ) def testSymbol( self ): self.assertEqual( target.module.rva("FuncWithName0"), target.module.offset("FuncWithName0") - target.module.begin() ) diff --git a/test/scripts/pykdtest.py b/test/scripts/pykdtest.py index b1284f7..5fd6da4 100644 --- a/test/scripts/pykdtest.py +++ b/test/scripts/pykdtest.py @@ -15,7 +15,7 @@ import target import intbase import memtest -#import moduletest +import moduletest #import typeinfo #import typedvar #import regtest @@ -47,7 +47,7 @@ def getTestSuite( singleName = "" ): unittest.TestLoader().loadTestsFromTestCase( StartProcessWithoutParamsTest ), # *** Test without start/kill new processes - #unittest.TestLoader().loadTestsFromTestCase( moduletest.ModuleTest ), + unittest.TestLoader().loadTestsFromTestCase( moduletest.ModuleTest ), unittest.TestLoader().loadTestsFromTestCase( memtest.MemoryTest ), #unittest.TestLoader().loadTestsFromTestCase( typeinfo.TypeInfoTest ), #unittest.TestLoader().loadTestsFromTestCase( typedvar.TypedVarTest ),