From 6876c4ee3d5f24d27f033feef044c3b63de9ce82 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Tue, 17 Jan 2012 16:30:15 +0000 Subject: [PATCH] [0.1.x] fixed : issue #10149 ( handling pykd exceptions ) git-svn-id: https://pykd.svn.codeplex.com/svn@73250 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgexcept.cpp | 14 +++--- pykd/dbgexcept.h | 93 +++++++++++++++++++++++++++++++++------- pykd/dbgext.cpp | 89 ++++---------------------------------- pykd/diawrapper.cpp | 11 +---- pykd/diawrapper.h | 15 ++----- pykd/typeinfo.cpp | 8 ++-- pykd/typeinfo.h | 24 +++-------- test/scripts/typedvar.py | 2 + test/scripts/typeinfo.py | 53 ++++++++++++++--------- 9 files changed, 143 insertions(+), 166 deletions(-) diff --git a/pykd/dbgexcept.cpp b/pykd/dbgexcept.cpp index a3ba94b..6e07b6a 100644 --- a/pykd/dbgexcept.cpp +++ b/pykd/dbgexcept.cpp @@ -6,12 +6,14 @@ namespace pykd { /////////////////////////////////////////////////////////////////////////////////// -PyObject *ExceptionTranslator::exceptTypeObject = NULL; -PyObject *ExceptionTranslator::exceptTypeObject = NULL; -PyObject *ExceptionTranslator::exceptTypeObject = NULL; -PyObject *ExceptionTranslator::exceptTypeObject = NULL; -PyObject *ExceptionTranslator::exceptTypeObject = NULL; +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; /////////////////////////////////////////////////////////////////////////////////// - }; // end namespace pykd diff --git a/pykd/dbgexcept.h b/pykd/dbgexcept.h index e94a14c..2fe51be 100644 --- a/pykd/dbgexcept.h +++ b/pykd/dbgexcept.h @@ -3,34 +3,65 @@ #include #include +/////////////////////////////////////////////////////////////////////////////// + namespace pykd { -///////////////////////////////////////////////////////////////////////////////// -template -class ExceptionTranslator { +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 pyExcept(e); - PyErr_SetObject( exceptTypeObject, pyExcept.ptr() ); + + python::object exceptObj = python::object( exceptPyType::pyExceptType )( e.what() ); + + PyErr_SetObject( exceptPyType::pyExceptType.get(), exceptObj.ptr()); } - static void setTypeObject(PyObject *p) { - exceptTypeObject = p; - python::register_exception_translator( &exceptionTranslate ); - } - -private: - - static PyObject *exceptTypeObject; - }; -///////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// class PyException : public std::exception { @@ -84,6 +115,18 @@ private: ///////////////////////////////////////////////////////////////////////////////// +class SymbolException : public DbgException +{ +public: + + SymbolException( const std::string &desc ) : + DbgException( desc.c_str() ) + {} + +}; + +///////////////////////////////////////////////////////////////////////////////// + class WaitEventException : public DbgException { public: @@ -95,6 +138,26 @@ public: ///////////////////////////////////////////////////////////////////////////////// +class TypeException : public SymbolException +{ +public: + + TypeException( const std::string &typeName, const std::string &errorStr ) + : SymbolException( buildDesc( typeName, errorStr ) ) + {} + +private: + + 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: diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 655e8b0..a7e1c9d 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -801,92 +801,19 @@ BOOST_PYTHON_MODULE( pykd ) python::scope().attr("diaAmd64Regs") = genDict(pyDia::Symbol::amd64RegName, pyDia::Symbol::cntAmd64RegName); - // exception: + // exception: // wrapper for standart python exceptions python::register_exception_translator( &PyException::exceptionTranslate ); - // BaseException - ExceptionTranslator::setTypeObject( - python::class_( "BaseException", "Pykd base exception class", python::no_init ) - .def( "__str__", &DbgException::getDesc ) - .def( "__repr__", &DbgException::getDesc ) - .ptr() - ); - - // DIA exception - ExceptionTranslator::setTypeObject( - python::class_ >( - "DiaException", "Debug interface access exception", python::no_init) - .ptr() - ); - // Memory exception - ExceptionTranslator::setTypeObject( - python::class_ >( - "MemoryException", "Target memory access exception class", python::no_init ) - .def( "getAddress", &pykd::MemoryException::getAddress, "Return a target address where the exception occurs" ) - .ptr() - ); - - // WaitEventException - ExceptionTranslator::setTypeObject( - python::class_ >( - "WaitEventException", "Debug interface access exception", python::no_init) - .ptr() - ); - - // AddSyntheticSymbolException - ExceptionTranslator::setTypeObject( - python::class_ >( - "AddSynSymbolException", "Add new synthetic symbol exception", python::no_init) - .ptr() - ); - - -// -//#define _DECL_BASE_EXCEPT_STR .def( "__repr__", &pykd::DbgException::print ) -// -// // base exception -// python::class_ dbgExceptionClass( "BaseException", -// "Pykd base exception class", -// python::no_init ); -// dbgExceptionClass -// .def( python::init( python::args("desc"), "constructor" ) ) -// .def( "desc", &pykd::DbgException::getDesc, -// "Get exception description" ) -// _DECL_BASE_EXCEPT_STR; -// pykd::DbgException::setTypeObject( dbgExceptionClass.ptr() ); -// python::register_exception_translator( -// &pykd::DbgException::exceptionTranslate ); -// -// // DIA exceptions -// python::class_ > diaException( -// "DiaException", "Debug interface access exception", python::no_init); -// diaException -// .def( "hres", &pyDia::Exception::getRes ) -// _DECL_BASE_EXCEPT_STR; -// pyDia::Exception::setTypeObject( diaException.ptr() ); -// python::register_exception_translator( -// &pyDia::Exception::exceptionTranslate ); -// -// // Memory exception -// python::class_ > memException( -// "MemoryException", "Target memory access exception class", -// python::no_init ); -// memException.def( "getAddress", &pykd::MemoryException::getAddress, "Return a target address where the exception occurs" ); -// pykd::MemoryException::setTypeObject( memException.ptr() ); -// python::register_exception_translator( -// &pykd::MemoryException::exceptionTranslate ); -// -// // Wait debug event exception -// python::class_ > waitEventException( -// "WaitEventException", "Debug interface access exception", python::no_init); -// waitEventException -// _DECL_BASE_EXCEPT_STR; -// WaitEventException::setTypeObject( waitEventException.ptr() ); -// python::register_exception_translator( -// &WaitEventException::exceptionTranslate ); + pykd::exception( "BaseException", "Pykd base exception class" ); + pykd::exception( "MemoryException", "Target memory access exception class" ); + pykd::exception( "WaitEventException", "Debug interface access exception" ); + pykd::exception( "SymbolException", "Symbol exception" ); + pykd::exception( "DiaException", "Debug interface access exception" ); + pykd::exception( "TypeException", "type exception" ); + pykd::exception( "AddSynSymbolException", "synthetic symbol exception" ); DEF_PY_CONST_ULONG( DEBUG_CLASS_UNINITIALIZED ); DEF_PY_CONST_ULONG( DEBUG_CLASS_KERNEL ); diff --git a/pykd/diawrapper.cpp b/pykd/diawrapper.cpp index b9b07dc..bf9e0fd 100644 --- a/pykd/diawrapper.cpp +++ b/pykd/diawrapper.cpp @@ -8,7 +8,7 @@ namespace pyDia { //////////////////////////////////////////////////////////////////////////////// -PyObject *Exception::diaExceptTypeObject = NULL; +//PyObject *Exception::diaExceptTypeObject = NULL; const std::string Exception::descPrefix("pyDia: "); @@ -50,15 +50,6 @@ std::string Exception::makeFullDesc(const std::string &desc, HRESULT hres) //////////////////////////////////////////////////////////////////////////////// -void Exception::exceptionTranslate( const Exception &e ) -{ - boost::python::object pyExcept(e); - - PyErr_SetObject( diaExceptTypeObject, pyExcept.ptr() ); -} - -//////////////////////////////////////////////////////////////////////////////// - SymbolPtrList Symbol::findChildrenImpl( ULONG symTag, const std::string &name, diff --git a/pykd/diawrapper.h b/pykd/diawrapper.h index 231890a..e0fc09c 100644 --- a/pykd/diawrapper.h +++ b/pykd/diawrapper.h @@ -18,16 +18,16 @@ typedef CComPtr< IDiaSession > DiaSessionPtr; //////////////////////////////////////////////////////////////////////////////// // DIA Exceptions //////////////////////////////////////////////////////////////////////////////// -class Exception : public pykd::DbgException { +class Exception : public pykd::SymbolException { public: Exception(const std::string &desc, HRESULT hres) - : DbgException( makeFullDesc(desc, hres) ) + : SymbolException( makeFullDesc(desc, hres) ) , m_hres(hres) { } Exception(const std::string &desc) - : DbgException(descPrefix + desc) + : SymbolException(descPrefix + desc) , m_hres(S_FALSE) { } @@ -35,19 +35,10 @@ public: HRESULT getRes() const { return m_hres; } - - static void exceptionTranslate(const Exception &e); - - static void setTypeObject(PyObject *p) { - diaExceptTypeObject = p; - } - private: static const std::string descPrefix; - static PyObject *diaExceptTypeObject; - static std::string makeFullDesc(const std::string &desc, HRESULT hres); HRESULT m_hres; diff --git a/pykd/typeinfo.cpp b/pykd/typeinfo.cpp index aafd551..f58e0d3 100644 --- a/pykd/typeinfo.cpp +++ b/pykd/typeinfo.cpp @@ -28,7 +28,7 @@ TypeInfoPtr TypeInfo::getTypeInfo( pyDia::SymbolPtr &typeSym ) return TypeInfoPtr( new EnumTypeInfo( typeSym ) ); } - throw DbgException( "type name invalid" ); + throw TypeException( typeSym->getName(), "this type is not supported" ); } ///////////////////////////////////////////////////////////////////////////////////// @@ -36,7 +36,7 @@ TypeInfoPtr TypeInfo::getTypeInfo( pyDia::SymbolPtr &typeSym ) BaseTypeVariant TypeInfo::getValue() { if ( !m_constant ) - throw DbgException( "The type is not a constant and has not a value" ); + throw TypeException( getName(), "this type is not a constant and has not a value" ); switch( m_constantValue.vt ) { @@ -65,7 +65,7 @@ BaseTypeVariant TypeInfo::getValue() return (LONG64)m_constantValue.llVal; } - throw DbgException( "Failed to convert constant type" ); + throw TypeException( getName(), "Failed to convert constant type to any integer type" ); } ///////////////////////////////////////////////////////////////////////////////////// @@ -337,7 +337,7 @@ TypeInfoPtr TypeInfo::getComplexType( pyDia::SymbolPtr &symScope, const std::str boost::cmatch matchResult; if ( !boost::regex_match( symName.c_str(), matchResult, typeMatch ) ) - DbgException( "type name invalid" ); + TypeException( symName, "type name is invalid" ); TypeInfoPtr lowestTypeInfo = getTypeInfo( symScope, std::string( matchResult[1].first, matchResult[1].second ) ); diff --git a/pykd/typeinfo.h b/pykd/typeinfo.h index 2bb3451..2aa35d7 100644 --- a/pykd/typeinfo.h +++ b/pykd/typeinfo.h @@ -37,7 +37,7 @@ public: virtual ULONG getSize() = 0; virtual TypeInfoPtr getField( const std::string &fieldName ) { - throw DbgException( "there is no fields" ); + throw TypeException( getName(), "type is not a struct" ); } virtual BaseTypeVariant getValue(); @@ -67,11 +67,11 @@ public: } virtual ULONG getCount() { - throw DbgException( "there is no element" ); + throw TypeException( getName(), "type is not an array" ); } virtual TypeInfoPtr getElementType() { - throw DbgException( "there is no element" ); + throw TypeException( getName(), "type is not an array" ); } virtual ULONG getBitOffset() { @@ -83,11 +83,11 @@ public: } virtual python::dict asMap() { - throw DbgException( "there is no fields" ); + throw TypeException( getName(), "type cannot be converted to a dict" ); } virtual TypeInfoPtr deref() { - throw DbgException( "type is not a pointer" ); + throw TypeException( getName(), "type is not a pointer" ); } ULONG getOffset() { @@ -114,7 +114,7 @@ protected: static TypeInfoPtr getRecurciveComplexType( TypeInfoPtr &lowestType, std::string &suffix, ULONG ptrSize ); - ULONG m_offset; + ULONG m_offset; bool m_constant; @@ -141,10 +141,6 @@ private: return sizeof(T); } - virtual TypeInfoPtr getField( const std::string &fieldName ) { - throw DbgException( "there is no such field" ); - } - virtual bool isBasicType() { return true; } @@ -278,10 +274,6 @@ public: virtual ULONG getSize(); - virtual TypeInfoPtr getField( const std::string &fieldName ) { - throw DbgException( "there is no such field" ); - } - virtual bool isPointer() { return true; } @@ -320,10 +312,6 @@ public: virtual ULONG getSize(); - virtual TypeInfoPtr getField( const std::string &fieldName ) { - throw DbgException( "there is no such field" ); - } - virtual bool isArray() { return true; } diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index a0bdff5..df3770a 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -21,6 +21,8 @@ class TypedVarTest( unittest.TestCase ): self.assertEqual( -2, target.module.typedVar( "g_shortValue" ) ) self.assertEqual( -4, target.module.typedVar( "g_longValue" ) ) self.assertEqual( -8, target.module.typedVar( "g_longlongValue" ) ) + + def testConst(self): try: self.assertEqual( True, target.module.typedVar( "g_constBoolValue" ) ) except pykd.BaseException: diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py index 5b6f9ab..656ae50 100644 --- a/test/scripts/typeinfo.py +++ b/test/scripts/typeinfo.py @@ -13,17 +13,6 @@ class TypeInfoTest( unittest.TestCase ): try: pykd.typeInfo() except RuntimeError: pass - - def testBaseTypes(self): - self.assertEqual("Int1B", target.module.type( "Int1B" ).name() ) - self.assertEqual("Int2B", target.module.type( "Int2B" ).name() ) - self.assertEqual("Int4B", target.module.type( "Int4B" ).name() ) - self.assertEqual("Int8B", target.module.type( "Int8B" ).name() ) - self.assertEqual("UInt1B", target.module.type( "UInt1B" ).name() ) - self.assertEqual("UInt2B", target.module.type( "UInt2B" ).name() ) - self.assertEqual("UInt4B", target.module.type( "UInt4B" ).name() ) - self.assertEqual("UInt8B", target.module.type( "UInt8B" ).name() ) - def testCreateByName( self ): """ creating typeInfo by the type name """ self.assertEqual( "structTest", target.module.type( "structTest" ).name() ) @@ -52,14 +41,41 @@ class TypeInfoTest( unittest.TestCase ): except pykd.BaseException: pass def testBaseTypes( self ): - self.assertEqual( 1, target.module.type("Char").size() ) - self.assertEqual( 2, target.module.type("WChar").size() ) + + self.assertEqual("Int1B", target.module.type( "Int1B" ).name() ) + self.assertEqual("Int2B", target.module.type( "Int2B" ).name() ) + self.assertEqual("Int4B", target.module.type( "Int4B" ).name() ) + self.assertEqual("Int8B", target.module.type( "Int8B" ).name() ) + self.assertEqual("UInt1B", target.module.type( "UInt1B" ).name() ) + self.assertEqual("UInt2B", target.module.type( "UInt2B" ).name() ) + self.assertEqual("UInt4B", target.module.type( "UInt4B" ).name() ) + self.assertEqual("UInt8B", target.module.type( "UInt8B" ).name() ) + + self.assertEqual("Long", target.module.type( "Long" ).name() ) + self.assertEqual("ULong", target.module.type( "ULong" ).name() ) + self.assertEqual("Bool", target.module.type( "Bool" ).name() ) + self.assertEqual("Char", target.module.type("Char").name() ) + self.assertEqual("WChar", target.module.type("WChar").name() ) + + self.assertEqual( 1, target.module.type("Int1B").size() ) + self.assertEqual( 1, target.module.type("UInt1B").size() ) self.assertEqual( 2, target.module.type("Int2B").size() ) self.assertEqual( 2, target.module.type("UInt2B").size() ) self.assertEqual( 4, target.module.type("Int4B").size() ) self.assertEqual( 4, target.module.type("UInt4B").size() ) self.assertEqual( 8, target.module.type("Int8B").size() ) - self.assertEqual( 8, target.module.type("UInt8B").size() ) + self.assertEqual( 8, target.module.type("UInt8B").size() ) + + self.assertEqual( 4, target.module.type("Long" ).size() ) + self.assertEqual( 4, target.module.type("ULong" ).size() ) + self.assertEqual( 1, target.module.type("Bool" ).size() ) + self.assertEqual( 1, target.module.type("Char").size() ) + self.assertEqual( 2, target.module.type("WChar").size() ) + + try: + self.assertEqual("Int9B", target.module.type( "Int9B" ).name() ) + except pykd.SymbolException: + pass def testName( self ): ti1 = target.module.type( "classChild" ) @@ -114,11 +130,8 @@ class TypeInfoTest( unittest.TestCase ): self.assertEqual( "listStruct1", ti.deref().name() ) ti = target.module.type("classChild") - try: - ti.deref() - self.assertTrue(False) - except pykd.BaseException: - pass - + self.assertRaises( pykd.BaseException, ti.deref ); + + \ No newline at end of file