diff --git a/pykd/dbgexcept.h b/pykd/dbgexcept.h index 66bd439..ed69942 100644 --- a/pykd/dbgexcept.h +++ b/pykd/dbgexcept.h @@ -17,6 +17,15 @@ public: {} }; +class AttributeException : public std::exception +{ +public: + + AttributeException(const char* desc) : std::exception(desc) + {} +}; + + template< class TExcept > struct exceptPyType{ static python::handle<> pyExceptType; @@ -96,6 +105,12 @@ inline void pykdExceptionTranslate(const std::exception &e) return; } + if (typeid(e).hash_code() == typeid(AttributeException).hash_code()) + { + PyErr_SetString(PyExc_AttributeError, e.what()); + return; + } + } inline void registerExceptions() @@ -107,6 +122,7 @@ inline void registerExceptions() python::register_exception_translator<kdlib::DbgException>( &dbgExceptionTranslate ); python::register_exception_translator<OverflowException>( &pykdExceptionTranslate ); + python::register_exception_translator<AttributeException>(&pykdExceptionTranslate); } ///////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index f9b64c2..6191413 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -717,7 +717,7 @@ BOOST_PYTHON_MODULE( pykd ) "Return tuple of the module's file version") .def("getFixedFileInfo", ModuleAdapter::getFixedFileInfo, "Return FixedFileInfo" ) - .def("__getattr__", ModuleAdapter::getSymbolVa, + .def("__getattr__", ModuleAdapter::getSymbolVaAttr, "Return address of the symbol" ) .def( "__str__", &ModuleAdapter::print ); @@ -783,7 +783,7 @@ BOOST_PYTHON_MODULE( pykd ) "Return class parent" ) .def( "__str__", TypeInfoAdapter::str, "Return type as a printable string" ) - .def( "__getattr__", TypeInfoAdapter::getElementByName ) + .def( "__getattr__", TypeInfoAdapter::getElementAttr ) .def( "__len__", TypeInfoAdapter::getElementCount ) .def( "__getitem__", TypeInfoAdapter::getElementByIndex ) .def( "__dir__", TypeInfoAdapter::getElementDir ) @@ -825,7 +825,7 @@ BOOST_PYTHON_MODULE( pykd ) "Return value by pointer" ) .def("type", TypedVarAdapter::getType, "Return typeInfo instance" ) - .def("__getattr__", TypedVarAdapter::getField, + .def("__getattr__", TypedVarAdapter::getFieldAttr, "Return field of structure as an object attribute" ) .def( "__str__", TypedVarAdapter::print ) .def("__len__", TypedVarAdapter::getElementCount ) diff --git a/pykd/pymodule.h b/pykd/pymodule.h index 03507bc..b4277c8 100644 --- a/pykd/pymodule.h +++ b/pykd/pymodule.h @@ -2,10 +2,15 @@ #include <sstream> +#include <comutil.h> + + #include "kdlib/module.h" +#include "kdlib/exceptions.h" #include "stladaptor.h" #include "pythreadstate.h" +#include "dbgexcept.h" namespace pykd { @@ -74,6 +79,20 @@ struct ModuleAdapter : public kdlib::Module return module.getSymbolVa(symbolName); } + static kdlib::MEMOFFSET_64 getSymbolVaAttr(kdlib::Module& module, const std::wstring &symbolName) + { + AutoRestorePyState pystate; + try { + return module.getSymbolVa(symbolName); + } + catch (kdlib::DbgException&) + { + std::wstringstream sstr; + sstr << L'\'' << module.getName() << L'\'' << L" module has no symbol " << L'\'' << symbolName << L'\''; + throw AttributeException(std::string(_bstr_t(sstr.str().c_str())).c_str()); + } + } + static kdlib::MEMOFFSET_32 getSymbolRva( kdlib::Module& module, const std::wstring &symbolName ) { AutoRestorePyState pystate; diff --git a/pykd/pytypedvar.h b/pykd/pytypedvar.h index 86f1c72..4f7caf0 100644 --- a/pykd/pytypedvar.h +++ b/pykd/pytypedvar.h @@ -1,5 +1,7 @@ #pragma once +#include <comutil.h> + #include <boost/python/list.hpp> #include <boost/python/tuple.hpp> namespace python = boost::python; @@ -8,6 +10,7 @@ namespace python = boost::python; #include "stladaptor.h" #include "pythreadstate.h" +#include "dbgexcept.h" namespace pykd { @@ -106,6 +109,20 @@ struct TypedVarAdapter { return typedVar.getElement( name ); } + static kdlib::TypedVarPtr getFieldAttr(kdlib::TypedVar& typedVar, const std::wstring &name) + { + try + { + return getField(typedVar, name); + } + catch (kdlib::DbgException&) + { + std::wstringstream sstr; + sstr << L"typed var has no field " << L'\'' << name << L'\''; + throw AttributeException(std::string(_bstr_t(sstr.str().c_str())).c_str()); + } + } + static size_t getElementCount( kdlib::TypedVar& typedVar ) { AutoRestorePyState pystate; diff --git a/pykd/pytypeinfo.h b/pykd/pytypeinfo.h index 33d82dd..1bf8de6 100644 --- a/pykd/pytypeinfo.h +++ b/pykd/pytypeinfo.h @@ -1,7 +1,11 @@ #pragma once +#include <comutil.h> + #include "kdlib/typeinfo.h" + #include "pythreadstate.h" +#include "dbgexcept.h" namespace pykd { @@ -109,6 +113,20 @@ struct TypeInfoAdapter : public kdlib::TypeInfo { return typeInfo.getElement(name); } + static kdlib::TypeInfoPtr getElementAttr(kdlib::TypeInfo &typeInfo, const std::wstring &name) + { + try + { + return getElementByName(typeInfo, name); + } + catch (kdlib::DbgException&) + { + std::wstringstream sstr; + sstr << L'\'' << typeInfo.getName() << L'\'' << L" type has no field " << L'\'' << name << L'\''; + throw AttributeException(std::string(_bstr_t(sstr.str().c_str())).c_str()); + } + } + static kdlib::TypeInfoPtr getElementByIndex( kdlib::TypeInfo &typeInfo, size_t index ) {