From 6689f6a5e61189c00bcd4801d60d55f00339cc08 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Thu, 14 May 2015 11:05:55 +0000 Subject: [PATCH] [0.3.x] reworked : pykd bootstrapper git-svn-id: https://pykd.svn.codeplex.com/svn@90642 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/pykdver.h | 2 +- pykd_bootstrapper/version.h | 2 +- pykd_bootstrapper/windbgext.cpp | 901 +++++++++++++++++++------------- setup/setup.py | 2 +- 4 files changed, 541 insertions(+), 366 deletions(-) diff --git a/pykd/pykdver.h b/pykd/pykdver.h index 7c60e11..3906302 100644 --- a/pykd/pykdver.h +++ b/pykd/pykdver.h @@ -2,7 +2,7 @@ #define PYKD_VERSION_MAJOR 0 #define PYKD_VERSION_MINOR 3 #define PYKD_VERSION_SUBVERSION 0 -#define PYKD_VERSION_BUILDNO 24 +#define PYKD_VERSION_BUILDNO 25 #define __VER_STR2__(x) #x #define __VER_STR1__(x) __VER_STR2__(x) diff --git a/pykd_bootstrapper/version.h b/pykd_bootstrapper/version.h index 2099c89..3ecc07a 100644 --- a/pykd_bootstrapper/version.h +++ b/pykd_bootstrapper/version.h @@ -3,7 +3,7 @@ #define PYKDEXT_VERSION_MAJOR 1 #define PYKDEXT_VERSION_MINOR 0 #define PYKDEXT_VERSION_SUBVERSION 1 -#define PYKDEXT_VERSION_BUILDNO 7 +#define PYKDEXT_VERSION_BUILDNO 8 #define __VER_STR2__(x) #x #define __VER_STR1__(x) __VER_STR2__(x) diff --git a/pykd_bootstrapper/windbgext.cpp b/pykd_bootstrapper/windbgext.cpp index b9d13e0..8436ddb 100644 --- a/pykd_bootstrapper/windbgext.cpp +++ b/pykd_bootstrapper/windbgext.cpp @@ -1,14 +1,15 @@ #include "stdafx.h" +#include + +#include +#include #include #include - namespace python = boost::python; -#include "kdlib/windbg.h" - -using namespace kdlib; +#include /////////////////////////////////////////////////////////////////////////////// @@ -21,12 +22,6 @@ public: m_state = PyEval_SaveThread(); } - explicit AutoRestorePyState(PyThreadState **state) - { - *state = PyEval_SaveThread(); - m_state = *state; - } - ~AutoRestorePyState() { PyEval_RestoreThread(m_state); @@ -37,21 +32,39 @@ private: PyThreadState* m_state; }; +////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -class DbgOut : public windbg::WindbgOut +class DbgOut { public: - virtual void write(const std::wstring& str) { + DbgOut(PDEBUG_CLIENT client) + : m_control(client) + {} + + void write(const std::wstring& str) + { AutoRestorePyState pystate; - windbg::WindbgOut::write(str); + + m_control->ControlledOutputWide( + DEBUG_OUTCTL_THIS_CLIENT, + DEBUG_OUTPUT_NORMAL, + L"%ws", + str.c_str() + ); + } - virtual void writedml(const std::wstring& str) { + void writedml(const std::wstring& str) + { AutoRestorePyState pystate; - windbg::WindbgOut::writedml(str); + + m_control->ControlledOutputWide( + DEBUG_OUTCTL_THIS_CLIENT | DEBUG_OUTCTL_DML, + DEBUG_OUTPUT_NORMAL, + L"%ws", + str.c_str() + ); } void flush() { @@ -60,273 +73,61 @@ public: std::wstring encoding() { return L"ascii"; } + +private: + + CComQIPtr m_control; }; /////////////////////////////////////////////////////////////////////////////// -class DbgIn : public windbg::WindbgIn +class DbgIn { public: - std::wstring readline() { + DbgIn(PDEBUG_CLIENT client) + : m_control(client) + {} + + std::wstring readline() + { AutoRestorePyState pystate; - return kdlib::windbg::WindbgIn::readline(); - } - std::wstring encoding() { - return L"ascii"; - } -}; + std::vector inputBuffer(0x10000); + ULONG read = 0; + m_control->InputWide(&inputBuffer[0], static_cast(inputBuffer.size()), &read); -/////////////////////////////////////////////////////////////////////////////// + std::wstring inputstr = std::wstring(&inputBuffer[0]); -class PythonSingleton -{ - -public: - - static PythonSingleton* get() { - if (!m_instance) - m_instance = new PythonSingleton(); - - return m_instance; - } - - void beginPythonCode() - { - PyEval_RestoreThread(m_pyState); - } - - void endPythonCode() - { - m_pyState = PyEval_SaveThread(); + return inputstr.empty() ? L"\n" : inputstr; } private: - PythonSingleton() - { - PyEval_InitThreads(); - - Py_Initialize(); - - python::object main = boost::python::import("__main__"); - - python::object main_namespace = main.attr("__dict__"); - - // Python debug output console helper classes - python::class_<::DbgOut>("dout", "dout", python::no_init) - .def("write", &::DbgOut::write) - .def("writedml", &::DbgOut::writedml) - .def("flush", &::DbgOut::flush) - .add_property("encoding", &::DbgOut::encoding); - - python::class_<::DbgIn>("din", "din", python::no_init) - .def("readline", &::DbgIn::readline) - .add_property("encoding", &::DbgIn::encoding); - - python::object sys = python::import("sys"); - - sys.attr("stdout") = python::object(::DbgOut()); - sys.attr("stderr") = python::object(::DbgOut()); - sys.attr("stdin") = python::object(::DbgIn()); - - m_pyState = PyEval_SaveThread(); - } - - static PythonSingleton* m_instance; - - PyThreadState *m_pyState; + CComQIPtr m_control; }; -PythonSingleton* PythonSingleton::m_instance = 0; - - /////////////////////////////////////////////////////////////////////////////// -class PykdBootsTrapper: public windbg::WindbgExtension +class PythonInterpreter { - public: - KDLIB_EXT_COMMAND_METHOD(py); - KDLIB_EXT_COMMAND_METHOD(install); - KDLIB_EXT_COMMAND_METHOD(upgrade); - - virtual void setUp(); - - virtual void tearDown(); - -private: - - void printUsage(); - - void printException(); - - std::string getScriptFileName(const std::string &scriptName); - - std::string findScript(const std::string &fullFileName); - - - bool m_pykdInitialized; - -}; - - -/////////////////////////////////////////////////////////////////////////////// - -class InterruptWatch : public windbg::InterruptWatch -{ - virtual bool onInterrupt() + PythonInterpreter() { - HANDLE quitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - PyGILState_STATE state = PyGILState_Ensure(); - Py_AddPendingCall(&quit, (void*)quitEvent); - PyGILState_Release(state); - WaitForSingleObject(quitEvent, INFINITE); - CloseHandle(quitEvent); - return true; + PyThreadState* state = Py_NewInterpreter(); + + PyThreadState_Swap(state); + + m_state = PyEval_SaveThread(); } - static int quit(void *context) + ~PythonInterpreter() { - HANDLE quitEvent = (HANDLE)context; - kdlib::eprintln(L"User Interrupt: CTRL+BREAK"); - PyErr_SetString(PyExc_SystemExit, "CTRL+BREAK"); - SetEvent(quitEvent); - return -1; - } -}; + PyEval_RestoreThread(m_state); -/////////////////////////////////////////////////////////////////////////////// - -KDLIB_WINDBG_EXTENSION_INIT(PykdBootsTrapper); - -KDLIB_EXT_COMMAND_METHOD_IMPL(PykdBootsTrapper, py) -{ - ArgsList args = getArgs(); - - bool global = false; - bool local = false; - bool clean = false; - - ArgsList::iterator foundArg; - - if (!args.empty()) - { - if (args[0] == "-h" || args[0] == "--help") - { - printUsage(); - return; - } - else - if (args[0] == "-g" || args[0] == "--global") - { - global = true; - args.erase(args.begin()); - } - else - if (args[0] == "-l" || args[0] == "--local") - { - local = true; - args.erase(args.begin()); - } - } - - PyThreadState *localState = NULL; - PyThreadState *globalState = NULL; - - PythonSingleton::get()->beginPythonCode(); - - try { - - InterruptWatch interruptWatch; - - if (!global) - { - globalState = PyThreadState_Swap(NULL); - - Py_NewInterpreter(); - - localState = PyThreadState_Get(); - - python::object sys = python::import("sys"); - - sys.attr("stdout") = python::object(::DbgOut()); - sys.attr("stderr") = python::object(::DbgOut()); - sys.attr("stdin") = python::object(::DbgIn()); - } - - std::string scriptFileName; - if (args.size() > 0) - { - scriptFileName = getScriptFileName(args[0]); - - if (scriptFileName.empty()) - throw std::invalid_argument("script not found"); - - global = !(global || local) ? false : global; //set local by default - } - else - { - global = !(global || local) ? true : global; //set global by default - } - - // получаем доступ к глобальному мапу ( нужен для вызова exec_file ) - python::object main = python::import("__main__"); - python::object globalScope(main.attr("__dict__")); - - - if (!m_pykdInitialized) - { - python::handle<> pykdHandle(python::allow_null(PyImport_ImportModule("pykd"))); - if (!pykdHandle) - { - PyErr_SetString(PyExc_Exception, "Pykd package is not installed. You can install it by command \"!pykd.install\""); - python::throw_error_already_set(); - } - - python::exec("__import__('pykd').initialize()", globalScope); - m_pykdInitialized = true; - } - - if (args.size() == 0) - { - python::exec("import pykd", globalScope); - python::exec("from pykd import *", globalScope); - python::exec("__import__('code').InteractiveConsole(__import__('__main__').__dict__).interact()", globalScope); - } - else - { - // устанавиливаем питоновские аргументы - char **pythonArgs = new char*[args.size()]; - - pythonArgs[0] = const_cast(scriptFileName.c_str()); - - for (size_t i = 1; i < args.size(); ++i) - pythonArgs[i] = const_cast(args[i].c_str()); - - PySys_SetArgv((int)args.size(), pythonArgs); - - delete[] pythonArgs; - - python::exec_file(scriptFileName.c_str(), globalScope); - } - } - catch (const python::error_already_set&) - { - printException(); - } - catch (const std::exception& invalidArg) - { - _bstr_t bstrInavalidArg(invalidArg.what()); - kdlib::eprintln(std::wstring(bstrInavalidArg)); - } - - if (!global && localState) - { - PyInterpreterState *interpreter = localState->interp; + PyInterpreterState *interpreter = m_state->interp; while (interpreter->tstate_head != NULL) { @@ -342,145 +143,499 @@ KDLIB_EXT_COMMAND_METHOD_IMPL(PykdBootsTrapper, py) PyInterpreterState_Clear(interpreter); PyInterpreterState_Delete(interpreter); - - PyThreadState_Swap(globalState); } - PythonSingleton::get()->endPythonCode(); -} + void acivate() + { + PyEval_RestoreThread(m_state); + } + + void deactivate() + { + m_state = PyEval_SaveThread(); + } + +private: + + PyThreadState* m_state; + +}; /////////////////////////////////////////////////////////////////////////////// -KDLIB_EXT_COMMAND_METHOD_IMPL(PykdBootsTrapper, install) +class PythonSingleton { - PythonSingleton::get()->beginPythonCode(); - try { +public: - // получаем доступ к глобальному мапу ( нужен для вызова exec_file ) - python::object main = python::import("__main__"); - - python::object global(main.attr("__dict__")); - - InterruptWatch interruptWatch; - - python::exec("import pip\n", global); - python::exec("pip.logger.consumers = []\n", global); - python::exec("pip.main(['install', 'pykd'])\n", global); - - } - catch (python::error_already_set const &) + static PythonSingleton* get() { - printException(); + if (!m_instance) + m_instance = new PythonSingleton(); + + return m_instance; } - catch (const std::exception& invalidArg) + + void stop() { - _bstr_t bstrInavalidArg(invalidArg.what()); - kdlib::eprintln(std::wstring(bstrInavalidArg)); + delete m_globalInterpreter; + m_globalInterpreter = 0; } - PythonSingleton::get()->endPythonCode(); -} + void start() + { + PyEval_RestoreThread(m_globalState); -/////////////////////////////////////////////////////////////////////////////// + m_globalInterpreter = new PythonInterpreter(); -KDLIB_EXT_COMMAND_METHOD_IMPL(PykdBootsTrapper, upgrade) -{ - PythonSingleton::get()->beginPythonCode(); + m_globalInterpreter->acivate(); - try { + python::object main = boost::python::import("__main__"); - InterruptWatch interruptWatch; + python::object main_namespace = main.attr("__dict__"); + + // Python debug output console helper classes + python::class_("dout", "dout", python::no_init) + .def("write", &DbgOut::write) + .def("writedml", &DbgOut::writedml) + .def("flush", &DbgOut::flush) + .add_property("encoding", &DbgOut::encoding); + + python::class_("din", "din", python::no_init) + .def("readline", &DbgIn::readline); + + m_globalInterpreter->deactivate(); + } + + void acivateGlobal() { + m_globalInterpreter->acivate(); + } + + void deactivateGlobal() { + m_globalInterpreter->deactivate(); + } + + void acivateLocal() { + PyEval_RestoreThread(m_globalState); + m_locallInterpreter = new PythonInterpreter(); + m_locallInterpreter->acivate(); + } + + void deactivateLocal() { + m_locallInterpreter->deactivate(); + delete m_locallInterpreter; + m_locallInterpreter = 0; + PyThreadState_Swap(m_globalState); + m_globalState = PyEval_SaveThread(); + } + + void checkPykd() + { + if (m_pykdInit) + return; + + python::handle<> pykdHandle(python::allow_null(PyImport_ImportModule("pykd"))); + if (!pykdHandle) + throw std::exception("Pykd package is not installed.You can install it by command \"!pykd.install\""); python::object main = python::import("__main__"); - python::object global(main.attr("__dict__")); - python::exec("import pip\n", global); - python::exec("pip.logger.consumers = []\n", global); - python::exec("pip.main(['install', '--upgrade', 'pykd'])\n", global); + python::object globalScope(main.attr("__dict__")); + python::exec("__import__('pykd').initialize()", globalScope); + + m_pykdInit = true; } - catch (python::error_already_set const &) + +private: + + static PythonSingleton* m_instance; + + PythonSingleton() { - printException(); - } - catch (const std::exception& invalidArg) - { - _bstr_t bstrInavalidArg(invalidArg.what()); - kdlib::eprintln(std::wstring(bstrInavalidArg)); + Py_Initialize(); + PyEval_InitThreads(); + m_globalState = PyEval_SaveThread(); } - PythonSingleton::get()->endPythonCode(); -} + PythonInterpreter* m_globalInterpreter; + PythonInterpreter* m_locallInterpreter; + PyThreadState* m_globalState; -///////////////////////////////////////////////////////////////////////////// + bool m_pykdInit; +}; -void PykdBootsTrapper::setUp() +PythonSingleton* PythonSingleton::m_instance = 0; + +////////////////////////////////////////////////////////////////////////////// + +class InterruptWatch { - WindbgExtension::setUp(); -} +public: -///////////////////////////////////////////////////////////////////////////// - -void PykdBootsTrapper::tearDown() -{ - if (m_pykdInitialized) + InterruptWatch(PDEBUG_CLIENT client) { - PythonSingleton::get()->beginPythonCode(); + m_control = client; + m_stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + m_thread = CreateThread(NULL, 0, threadRoutine, this, 0, NULL); + } - try { - python::object main = python::import("__main__"); - python::object global(main.attr("__dict__")); - python::exec("__import__('pykd').deinitialize()", global); - m_pykdInitialized = false; - } - catch (python::error_already_set const &) + ~InterruptWatch() + { + SetEvent(m_stopEvent); + WaitForSingleObject(m_thread, INFINITE); + CloseHandle(m_stopEvent); + CloseHandle(m_thread); + } + + bool onInterrupt() + { + HANDLE quitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + PyGILState_STATE state = PyGILState_Ensure(); + Py_AddPendingCall(&quit, (void*)quitEvent); + PyGILState_Release(state); + WaitForSingleObject(quitEvent, INFINITE); + CloseHandle(quitEvent); + return true; + } + + static int quit(void *context) + { + HANDLE quitEvent = (HANDLE)context; + PyErr_SetString(PyExc_SystemExit, "CTRL+BREAK"); + SetEvent(quitEvent); + return -1; + } + +private: + + static DWORD WINAPI threadRoutine(LPVOID lpParameter) { + return static_cast(lpParameter)->interruptWatchRoutine(); + } + + DWORD InterruptWatch::interruptWatchRoutine() + { + while (WAIT_TIMEOUT == WaitForSingleObject(m_stopEvent, 250)) { - printException(); + HRESULT hres = m_control->GetInterrupt(); + if (hres == S_OK) + { + HANDLE quitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + PyGILState_STATE state = PyGILState_Ensure(); + Py_AddPendingCall(&quit, (void*)quitEvent); + PyGILState_Release(state); + WaitForSingleObject(quitEvent, INFINITE); + CloseHandle(quitEvent); + } } - PythonSingleton::get()->endPythonCode(); + return 0; } - WindbgExtension::tearDown(); -} + HANDLE m_thread; -/////////////////////////////////////////////////////////////////////////////// + HANDLE m_stopEvent; -void PykdBootsTrapper::printUsage() + CComQIPtr m_control; +}; + +////////////////////////////////////////////////////////////////////////////// + +typedef std::vector< std::string > ArgsList; +typedef boost::escaped_list_separator char_separator_t; +typedef boost::tokenizer< char_separator_t > char_tokenizer_t; + +ArgsList getArgsList( + PCSTR args + ) { - kdlib::dprintln(L"usage:"); - kdlib::dprintln(L"!py [options] [file]"); - kdlib::dprintln(L"\tOptions:"); - kdlib::dprintln(L"\t-g --global : run code in the common namespace"); - kdlib::dprintln(L"\t-l --local : run code in the isolate namespace"); - kdlib::dprintln(L"!install"); - kdlib::dprintln(L"!upgrade"); + std::string argsStr(args); + + char_tokenizer_t token(argsStr, char_separator_t("", " \t", "\"")); + ArgsList argsList; + + for (char_tokenizer_t::iterator it = token.begin(); it != token.end(); ++it) + { + if (*it != "") + argsList.push_back(*it); + } + + return argsList; } ////////////////////////////////////////////////////////////////////////////// -std::string PykdBootsTrapper::getScriptFileName(const std::string &scriptName) -{ - std::string scriptFileName = findScript(scriptName); +static const char printUsageMsg[] = + "usage:\n" + "!py [options] [file]\n" + "\tOptions:\n" + "\t-g --global : run code in the common namespace\n" + "\t-l --local : run code in the isolate namespace\n" + "!install\n" + "!upgrade\n"; - if (scriptFileName.empty()) +void printUsage(PDEBUG_CLIENT client) +{ + CComQIPtr(client)-> + ControlledOutput( + DEBUG_OUTCTL_THIS_CLIENT, + DEBUG_OUTPUT_NORMAL, + "%s", + printUsageMsg + ); +} + +////////////////////////////////////////////////////////////////////////////// + +extern "C" +HRESULT +CALLBACK +DebugExtensionInitialize( + PULONG Version, + PULONG Flags + ) +{ + PythonSingleton::get()->start(); + return S_OK; +} + +////////////////////////////////////////////////////////////////////////////// + +extern "C" +VOID +CALLBACK +DebugExtensionUninitialize() +{ + PythonSingleton::get()->stop(); +} + +////////////////////////////////////////////////////////////////////////////// + +std::string getScriptFileName(const std::string &scriptName); + +void printException(DbgOut &dbgOut); + +////////////////////////////////////////////////////////////////////////////// + +extern "C" +HRESULT +CALLBACK +py( + PDEBUG_CLIENT client, + PCSTR args + ) +{ + ArgsList argsList = getArgsList(args); + + bool global = false; + bool local = false; + bool clean = false; + + if (!argsList.empty()) { - std::string scriptNameLow; - scriptNameLow.resize(scriptName.size()); - std::transform( - scriptName.begin(), - scriptName.end(), - scriptNameLow.begin(), - ::tolower); - if (scriptNameLow.rfind(".py") != (scriptNameLow.length() - 3)) - scriptFileName = findScript(scriptName + ".py"); + if (argsList[0] == "-h" || argsList[0] == "--help") + { + printUsage(client); + return S_OK; + } + else + if (argsList[0] == "-g" || argsList[0] == "--global") + { + global = true; + argsList.erase(argsList.begin()); + } + else + if (argsList[0] == "-l" || argsList[0] == "--local") + { + local = true; + argsList.erase(argsList.begin()); + } } - return scriptFileName; + if (argsList.size() > 0) + { + global = !(global || local) ? false : global; //set local by default + } + else + { + global = !(global || local) ? true : global; //set global by default + } + + DbgOut dbgOut(client); + DbgOut dbgErr(client); + DbgIn dbgIn(client); + + ULONG oldMask; + client->GetOutputMask(&oldMask); + client->SetOutputMask(DEBUG_OUTPUT_NORMAL | DEBUG_OUTPUT_ERROR); + + + if (global) + PythonSingleton::get()->acivateGlobal(); + else + PythonSingleton::get()->acivateLocal(); + + try { + + InterruptWatch interruptWatch(client); + + python::object sys = python::import("sys"); + + sys.attr("stdout") = python::object(dbgOut); + sys.attr("stderr") = python::object(dbgErr); + sys.attr("stdin") = python::object(dbgIn); + + python::object main = python::import("__main__"); + python::object globalScope(main.attr("__dict__")); + + PythonSingleton::get()->checkPykd(); + + if (argsList.size() == 0) + { + + python::exec("import pykd", globalScope); + python::exec("from pykd import *", globalScope); + python::exec("__import__('code').InteractiveConsole(__import__('__main__').__dict__).interact()", globalScope); + } + else + { + + std::string scriptFileName = getScriptFileName(argsList[0]); + if (scriptFileName.empty()) + throw std::invalid_argument("script not found"); + + // устанавиливаем питоновские аргументы + char **pythonArgs = new char*[argsList.size()]; + + pythonArgs[0] = const_cast(scriptFileName.c_str()); + + for (size_t i = 1; i < argsList.size(); ++i) + pythonArgs[i] = const_cast(argsList[i].c_str()); + + PySys_SetArgv((int)argsList.size(), pythonArgs); + + delete[] pythonArgs; + + python::exec_file(scriptFileName.c_str(), globalScope); + } + } + catch (const python::error_already_set&) + { + printException(dbgOut); + } + catch (const std::exception& invalidArg) + { + _bstr_t bstrInavalidArg(invalidArg.what()); + dbgOut.write(std::wstring(bstrInavalidArg)); + } + + if (global) + PythonSingleton::get()->deactivateGlobal(); + else + PythonSingleton::get()->deactivateLocal(); + + client->SetOutputMask(oldMask); + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////////// + +extern "C" +HRESULT +CALLBACK +install( + PDEBUG_CLIENT client, + PCSTR args + ) +{ + DbgOut dbgOut(client); + DbgOut dbgErr(client); + DbgIn dbgIn(client); + + PythonSingleton::get()->acivateGlobal(); + + try { + + python::object sys = python::import("sys"); + + sys.attr("stdout") = python::object(dbgOut); + sys.attr("stderr") = python::object(dbgErr); + sys.attr("stdin") = python::object(dbgIn); + + // получаем доступ к глобальному мапу ( нужен для вызова exec_file ) + python::object main = python::import("__main__"); + python::object global(main.attr("__dict__")); + + python::exec("import pip\n", global); + python::exec("pip.logger.consumers = []\n", global); + python::exec("pip.main(['install', 'pykd'])\n", global); + + } + catch (const python::error_already_set&) + { + printException(dbgOut); + } + catch (const std::exception& invalidArg) + { + _bstr_t bstrInavalidArg(invalidArg.what()); + dbgOut.write(std::wstring(bstrInavalidArg)); + } + + PythonSingleton::get()->deactivateGlobal(); + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////////// + +extern "C" +HRESULT +CALLBACK +upgrade( + PDEBUG_CLIENT client, + PCSTR args + ) +{ + DbgOut dbgOut(client); + DbgOut dbgErr(client); + DbgIn dbgIn(client); + + PythonSingleton::get()->acivateGlobal(); + + try { + + python::object sys = python::import("sys"); + + sys.attr("stdout") = python::object(dbgOut); + sys.attr("stderr") = python::object(dbgErr); + sys.attr("stdin") = python::object(dbgIn); + + // получаем доступ к глобальному мапу ( нужен для вызова exec_file ) + python::object main = python::import("__main__"); + python::object global(main.attr("__dict__")); + + python::exec("import pip\n", global); + python::exec("pip.logger.consumers = []\n", global); + python::exec("pip.main(['install', '--upgrade', 'pykd'])\n", global); + + } + catch (const python::error_already_set&) + { + printException(dbgOut); + } + catch (const std::exception& invalidArg) + { + _bstr_t bstrInavalidArg(invalidArg.what()); + dbgOut.write(std::wstring(bstrInavalidArg)); + } + + PythonSingleton::get()->deactivateGlobal(); + + return S_OK; } /////////////////////////////////////////////////////////////////////////////// -std::string PykdBootsTrapper::findScript(const std::string &fullFileName) +std::string findScript(const std::string &fullFileName) { if (GetFileAttributesA(fullFileName.c_str()) != INVALID_FILE_ATTRIBUTES) return fullFileName; @@ -519,7 +674,7 @@ std::string PykdBootsTrapper::findScript(const std::string &fullFileName) DWORD fileAttr = GetFileAttributesA(&fullFileNameCStr[0]); - if ( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) == 0 ) + if ((fileAttr & FILE_ATTRIBUTE_DIRECTORY) == 0) return std::string(&fullFileNameCStr[0]); } } @@ -529,8 +684,29 @@ std::string PykdBootsTrapper::findScript(const std::string &fullFileName) /////////////////////////////////////////////////////////////////////////////// +std::string getScriptFileName(const std::string &scriptName) +{ + std::string scriptFileName = findScript(scriptName); -void PykdBootsTrapper::printException() + if (scriptFileName.empty()) + { + std::string scriptNameLow; + scriptNameLow.resize(scriptName.size()); + std::transform( + scriptName.begin(), + scriptName.end(), + scriptNameLow.begin(), + ::tolower); + if (scriptNameLow.rfind(".py") != (scriptNameLow.length() - 3)) + scriptFileName = findScript(scriptName + ".py"); + } + + return scriptFileName; +} + +/////////////////////////////////////////////////////////////////////////////// + +void printException(DbgOut &dbgOut) { // ошибка в скрипте PyObject *errtype = NULL, *errvalue = NULL, *traceback = NULL; @@ -539,26 +715,25 @@ void PykdBootsTrapper::printException() PyErr_NormalizeException(&errtype, &errvalue, &traceback); - if (errtype == PyExc_SystemExit) - return; + if (errtype != PyExc_SystemExit) + { + python::object tracebackModule = python::import("traceback"); - python::object tracebackModule = python::import("traceback"); + std::wstringstream sstr; - 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))); - 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; - sstr << std::endl << std::endl; + for (long i = 0; i < python::len(lst); ++i) + sstr << std::wstring(python::extract(lst[i])) << std::endl; - for (long i = 0; i < python::len(lst); ++i) - sstr << std::wstring(python::extract(lst[i])) << std::endl; - - kdlib::eprintln(sstr.str()); + dbgOut.write(sstr.str()); + } } /////////////////////////////////////////////////////////////////////////////// - diff --git a/setup/setup.py b/setup/setup.py index 557a4b4..b824fcf 100644 --- a/setup/setup.py +++ b/setup/setup.py @@ -8,7 +8,7 @@ import zipfile _name = "pykd" _desc = "python windbg extension" -_version = '0.3.0.22' +_version = '0.3.0.25' def makeWheel(args):