2015-03-23 01:29:38 +08:00
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
#include <DbgEng.h>
|
|
|
|
|
#include <atlbase.h>
|
2015-04-30 20:14:34 +08:00
|
|
|
|
#include <comutil.h>
|
|
|
|
|
|
2015-03-23 01:29:38 +08:00
|
|
|
|
#include <boost/python.hpp>
|
|
|
|
|
namespace python = boost::python;
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
#include <boost/tokenizer.hpp>
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class AutoRestorePyState
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
AutoRestorePyState()
|
|
|
|
|
{
|
|
|
|
|
m_state = PyEval_SaveThread();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~AutoRestorePyState()
|
|
|
|
|
{
|
|
|
|
|
PyEval_RestoreThread(m_state);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
PyThreadState* m_state;
|
|
|
|
|
};
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
2015-04-23 06:30:39 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
class DbgOut
|
2015-03-23 01:29:38 +08:00
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
DbgOut(PDEBUG_CLIENT client)
|
|
|
|
|
: m_control(client)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
void write(const std::wstring& str)
|
|
|
|
|
{
|
2015-03-23 01:29:38 +08:00
|
|
|
|
AutoRestorePyState pystate;
|
2015-05-14 19:05:55 +08:00
|
|
|
|
|
|
|
|
|
m_control->ControlledOutputWide(
|
|
|
|
|
DEBUG_OUTCTL_THIS_CLIENT,
|
|
|
|
|
DEBUG_OUTPUT_NORMAL,
|
|
|
|
|
L"%ws",
|
|
|
|
|
str.c_str()
|
|
|
|
|
);
|
|
|
|
|
|
2015-03-23 01:29:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
void writedml(const std::wstring& str)
|
|
|
|
|
{
|
2015-03-23 01:29:38 +08:00
|
|
|
|
AutoRestorePyState pystate;
|
2015-05-14 19:05:55 +08:00
|
|
|
|
|
|
|
|
|
m_control->ControlledOutputWide(
|
|
|
|
|
DEBUG_OUTCTL_THIS_CLIENT | DEBUG_OUTCTL_DML,
|
|
|
|
|
DEBUG_OUTPUT_NORMAL,
|
|
|
|
|
L"%ws",
|
|
|
|
|
str.c_str()
|
|
|
|
|
);
|
2015-03-23 01:29:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void flush() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::wstring encoding() {
|
|
|
|
|
return L"ascii";
|
|
|
|
|
}
|
2015-05-14 19:05:55 +08:00
|
|
|
|
|
2016-01-28 23:27:49 +08:00
|
|
|
|
bool closed() {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-28 17:09:46 +08:00
|
|
|
|
bool isatty() {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
CComQIPtr<IDebugControl4> m_control;
|
2015-03-23 01:29:38 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
class DbgIn
|
2015-03-23 01:29:38 +08:00
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
DbgIn(PDEBUG_CLIENT client)
|
|
|
|
|
: m_control(client)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
std::wstring readline()
|
|
|
|
|
{
|
2015-03-23 01:29:38 +08:00
|
|
|
|
AutoRestorePyState pystate;
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
std::vector<wchar_t> inputBuffer(0x10000);
|
|
|
|
|
|
|
|
|
|
ULONG read = 0;
|
|
|
|
|
m_control->InputWide(&inputBuffer[0], static_cast<ULONG>(inputBuffer.size()), &read);
|
|
|
|
|
|
|
|
|
|
std::wstring inputstr = std::wstring(&inputBuffer[0]);
|
|
|
|
|
|
|
|
|
|
return inputstr.empty() ? L"\n" : inputstr;
|
2015-03-23 01:29:38 +08:00
|
|
|
|
}
|
2015-05-14 19:05:55 +08:00
|
|
|
|
|
2016-01-28 23:27:49 +08:00
|
|
|
|
bool closed() {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
CComQIPtr<IDebugControl4> m_control;
|
2015-03-23 01:29:38 +08:00
|
|
|
|
};
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class PythonInterpreter
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
PythonInterpreter()
|
|
|
|
|
{
|
|
|
|
|
PyThreadState* state = Py_NewInterpreter();
|
|
|
|
|
|
|
|
|
|
PyThreadState_Swap(state);
|
|
|
|
|
|
|
|
|
|
m_state = PyEval_SaveThread();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~PythonInterpreter()
|
|
|
|
|
{
|
|
|
|
|
PyEval_RestoreThread(m_state);
|
|
|
|
|
|
|
|
|
|
PyInterpreterState *interpreter = m_state->interp;
|
|
|
|
|
|
|
|
|
|
while (interpreter->tstate_head != NULL)
|
|
|
|
|
{
|
|
|
|
|
PyThreadState *threadState = (PyThreadState*)(interpreter->tstate_head);
|
|
|
|
|
|
|
|
|
|
PyThreadState_Clear(threadState);
|
|
|
|
|
|
|
|
|
|
PyThreadState_Swap(NULL);
|
|
|
|
|
|
|
|
|
|
PyThreadState_Delete(threadState);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyInterpreterState_Clear(interpreter);
|
|
|
|
|
|
|
|
|
|
PyInterpreterState_Delete(interpreter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void acivate()
|
|
|
|
|
{
|
|
|
|
|
PyEval_RestoreThread(m_state);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void deactivate()
|
|
|
|
|
{
|
|
|
|
|
m_state = PyEval_SaveThread();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
PyThreadState* m_state;
|
|
|
|
|
|
|
|
|
|
};
|
2015-04-23 06:30:39 +08:00
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class PythonSingleton
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
static PythonSingleton* get()
|
|
|
|
|
{
|
2015-04-23 06:30:39 +08:00
|
|
|
|
if (!m_instance)
|
|
|
|
|
m_instance = new PythonSingleton();
|
|
|
|
|
|
|
|
|
|
return m_instance;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
void stop()
|
2015-04-23 06:30:39 +08:00
|
|
|
|
{
|
2015-05-14 19:05:55 +08:00
|
|
|
|
delete m_globalInterpreter;
|
|
|
|
|
m_globalInterpreter = 0;
|
2015-05-16 22:25:52 +08:00
|
|
|
|
PyThreadState_Swap(m_globalState);
|
2016-04-26 18:04:22 +08:00
|
|
|
|
|
|
|
|
|
if (m_pykdInit)
|
|
|
|
|
{
|
|
|
|
|
python::object main = python::import("__main__");
|
|
|
|
|
python::object globalScope(main.attr("__dict__"));
|
|
|
|
|
python::exec("__import__('pykd').deinitialize()", globalScope);
|
|
|
|
|
m_pykdInit = false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-16 22:25:52 +08:00
|
|
|
|
m_globalState = PyEval_SaveThread();
|
2015-04-23 06:30:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
void start()
|
2015-04-23 06:30:39 +08:00
|
|
|
|
{
|
2015-05-14 19:05:55 +08:00
|
|
|
|
PyEval_RestoreThread(m_globalState);
|
2015-04-23 06:30:39 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
m_globalInterpreter = new PythonInterpreter();
|
|
|
|
|
}
|
2015-04-23 06:30:39 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
void acivateGlobal() {
|
|
|
|
|
m_globalInterpreter->acivate();
|
|
|
|
|
}
|
2015-04-23 06:30:39 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
void deactivateGlobal() {
|
|
|
|
|
m_globalInterpreter->deactivate();
|
|
|
|
|
}
|
2015-04-23 06:30:39 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
void acivateLocal() {
|
|
|
|
|
PyEval_RestoreThread(m_globalState);
|
|
|
|
|
m_locallInterpreter = new PythonInterpreter();
|
|
|
|
|
m_locallInterpreter->acivate();
|
|
|
|
|
}
|
2015-04-23 06:30:39 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
void deactivateLocal() {
|
|
|
|
|
m_locallInterpreter->deactivate();
|
|
|
|
|
delete m_locallInterpreter;
|
|
|
|
|
m_locallInterpreter = 0;
|
|
|
|
|
PyThreadState_Swap(m_globalState);
|
|
|
|
|
m_globalState = PyEval_SaveThread();
|
|
|
|
|
}
|
2015-04-23 06:30:39 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
void checkPykd()
|
|
|
|
|
{
|
|
|
|
|
if (m_pykdInit)
|
|
|
|
|
return;
|
2015-04-23 06:30:39 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
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\"");
|
2015-04-23 06:30:39 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
python::object main = python::import("__main__");
|
|
|
|
|
python::object globalScope(main.attr("__dict__"));
|
|
|
|
|
python::exec("__import__('pykd').initialize()", globalScope);
|
2015-04-23 06:30:39 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
m_pykdInit = true;
|
|
|
|
|
}
|
2015-04-23 06:30:39 +08:00
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
static PythonSingleton* m_instance;
|
2015-04-23 06:30:39 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
PythonSingleton()
|
|
|
|
|
{
|
|
|
|
|
Py_Initialize();
|
|
|
|
|
PyEval_InitThreads();
|
2016-02-17 15:10:09 +08:00
|
|
|
|
|
|
|
|
|
// 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)
|
2016-04-28 17:09:46 +08:00
|
|
|
|
.def("isatty", &DbgOut::isatty)
|
2016-02-17 15:10:09 +08:00
|
|
|
|
.add_property("encoding", &DbgOut::encoding)
|
|
|
|
|
.add_property("closed", &DbgOut::closed);
|
|
|
|
|
|
|
|
|
|
python::class_<DbgIn>("din", "din", python::no_init)
|
|
|
|
|
.def("readline", &DbgIn::readline)
|
|
|
|
|
.add_property("closed", &DbgIn::closed);
|
|
|
|
|
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
m_globalState = PyEval_SaveThread();
|
|
|
|
|
}
|
2015-04-23 06:30:39 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
PythonInterpreter* m_globalInterpreter;
|
|
|
|
|
PythonInterpreter* m_locallInterpreter;
|
|
|
|
|
PyThreadState* m_globalState;
|
2015-04-23 06:30:39 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
bool m_pykdInit;
|
2015-04-23 06:30:39 +08:00
|
|
|
|
};
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
PythonSingleton* PythonSingleton::m_instance = 0;
|
2015-04-23 06:30:39 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
class InterruptWatch
|
2015-03-23 01:29:38 +08:00
|
|
|
|
{
|
2015-05-14 19:05:55 +08:00
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
InterruptWatch(PDEBUG_CLIENT client)
|
|
|
|
|
{
|
|
|
|
|
m_control = client;
|
|
|
|
|
m_stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
|
|
|
m_thread = CreateThread(NULL, 0, threadRoutine, this, 0, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~InterruptWatch()
|
|
|
|
|
{
|
|
|
|
|
SetEvent(m_stopEvent);
|
|
|
|
|
WaitForSingleObject(m_thread, INFINITE);
|
|
|
|
|
CloseHandle(m_stopEvent);
|
|
|
|
|
CloseHandle(m_thread);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool onInterrupt()
|
2015-03-23 01:29:38 +08:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
2015-05-14 19:05:55 +08:00
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
static DWORD WINAPI threadRoutine(LPVOID lpParameter) {
|
|
|
|
|
return static_cast<InterruptWatch*>(lpParameter)->interruptWatchRoutine();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD InterruptWatch::interruptWatchRoutine()
|
|
|
|
|
{
|
|
|
|
|
while (WAIT_TIMEOUT == WaitForSingleObject(m_stopEvent, 250))
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HANDLE m_thread;
|
|
|
|
|
|
|
|
|
|
HANDLE m_stopEvent;
|
|
|
|
|
|
|
|
|
|
CComQIPtr<IDebugControl> m_control;
|
2015-03-23 01:29:38 +08:00
|
|
|
|
};
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
typedef std::vector< std::string > ArgsList;
|
|
|
|
|
typedef boost::escaped_list_separator<char> char_separator_t;
|
|
|
|
|
typedef boost::tokenizer< char_separator_t > char_tokenizer_t;
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
ArgsList getArgsList(
|
|
|
|
|
PCSTR args
|
|
|
|
|
)
|
2015-03-23 01:29:38 +08:00
|
|
|
|
{
|
2015-05-14 19:05:55 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
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";
|
|
|
|
|
|
|
|
|
|
void printUsage(PDEBUG_CLIENT client)
|
|
|
|
|
{
|
|
|
|
|
CComQIPtr<IDebugControl>(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);
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
|
|
|
|
bool global = false;
|
|
|
|
|
bool local = false;
|
|
|
|
|
bool clean = false;
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
if (!argsList.empty())
|
2015-03-23 01:29:38 +08:00
|
|
|
|
{
|
2015-05-14 19:05:55 +08:00
|
|
|
|
if (argsList[0] == "-h" || argsList[0] == "--help")
|
2015-03-23 01:29:38 +08:00
|
|
|
|
{
|
2015-05-14 19:05:55 +08:00
|
|
|
|
printUsage(client);
|
|
|
|
|
return S_OK;
|
2015-03-23 01:29:38 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
2015-05-14 19:05:55 +08:00
|
|
|
|
if (argsList[0] == "-g" || argsList[0] == "--global")
|
2015-04-16 07:01:43 +08:00
|
|
|
|
{
|
|
|
|
|
global = true;
|
2015-05-14 19:05:55 +08:00
|
|
|
|
argsList.erase(argsList.begin());
|
2015-04-16 07:01:43 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
2015-05-14 19:05:55 +08:00
|
|
|
|
if (argsList[0] == "-l" || argsList[0] == "--local")
|
2015-04-16 07:01:43 +08:00
|
|
|
|
{
|
|
|
|
|
local = true;
|
2015-05-14 19:05:55 +08:00
|
|
|
|
argsList.erase(argsList.begin());
|
2015-04-16 07:01:43 +08:00
|
|
|
|
}
|
2015-03-23 01:29:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
if (argsList.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
global = !(global || local) ? false : global; //set local by default
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
global = !(global || local) ? true : global; //set global by default
|
|
|
|
|
}
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
DbgOut dbgOut(client);
|
|
|
|
|
DbgOut dbgErr(client);
|
|
|
|
|
DbgIn dbgIn(client);
|
2015-04-30 20:14:34 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
ULONG oldMask;
|
|
|
|
|
client->GetOutputMask(&oldMask);
|
|
|
|
|
client->SetOutputMask(DEBUG_OUTPUT_NORMAL | DEBUG_OUTPUT_ERROR);
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
if (global)
|
|
|
|
|
PythonSingleton::get()->acivateGlobal();
|
|
|
|
|
else
|
|
|
|
|
PythonSingleton::get()->acivateLocal();
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
try {
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
InterruptWatch interruptWatch(client);
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
python::object sys = python::import("sys");
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
sys.attr("stdout") = python::object(dbgOut);
|
|
|
|
|
sys.attr("stderr") = python::object(dbgErr);
|
|
|
|
|
sys.attr("stdin") = python::object(dbgIn);
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
python::object main = python::import("__main__");
|
|
|
|
|
python::object globalScope(main.attr("__dict__"));
|
2015-04-30 20:14:34 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
PythonSingleton::get()->checkPykd();
|
2015-04-30 20:14:34 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
if (argsList.size() == 0)
|
2015-04-30 20:14:34 +08:00
|
|
|
|
{
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-04-16 07:01:43 +08:00
|
|
|
|
python::exec("import pykd", globalScope);
|
|
|
|
|
python::exec("from pykd import *", globalScope);
|
|
|
|
|
python::exec("__import__('code').InteractiveConsole(__import__('__main__').__dict__).interact()", globalScope);
|
2015-03-23 01:29:38 +08:00
|
|
|
|
}
|
2015-04-16 07:01:43 +08:00
|
|
|
|
else
|
|
|
|
|
{
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
std::string scriptFileName = getScriptFileName(argsList[0]);
|
|
|
|
|
if (scriptFileName.empty())
|
2016-04-11 19:57:43 +08:00
|
|
|
|
throw std::invalid_argument("script not found\n");
|
2015-04-16 07:01:43 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
char **pythonArgs = new char*[argsList.size()];
|
|
|
|
|
|
|
|
|
|
pythonArgs[0] = const_cast<char*>(scriptFileName.c_str());
|
|
|
|
|
|
|
|
|
|
for (size_t i = 1; i < argsList.size(); ++i)
|
|
|
|
|
pythonArgs[i] = const_cast<char*>(argsList[i].c_str());
|
|
|
|
|
|
|
|
|
|
PySys_SetArgv((int)argsList.size(), pythonArgs);
|
|
|
|
|
|
2015-04-16 07:01:43 +08:00
|
|
|
|
delete[] pythonArgs;
|
|
|
|
|
|
|
|
|
|
python::exec_file(scriptFileName.c_str(), globalScope);
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-04-30 20:14:34 +08:00
|
|
|
|
catch (const python::error_already_set&)
|
2015-04-16 07:01:43 +08:00
|
|
|
|
{
|
2015-05-14 19:05:55 +08:00
|
|
|
|
printException(dbgOut);
|
2015-04-16 07:01:43 +08:00
|
|
|
|
}
|
2015-04-30 20:14:34 +08:00
|
|
|
|
catch (const std::exception& invalidArg)
|
|
|
|
|
{
|
|
|
|
|
_bstr_t bstrInavalidArg(invalidArg.what());
|
2015-05-14 19:05:55 +08:00
|
|
|
|
dbgOut.write(std::wstring(bstrInavalidArg));
|
2015-04-30 20:14:34 +08:00
|
|
|
|
}
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
if (global)
|
|
|
|
|
PythonSingleton::get()->deactivateGlobal();
|
|
|
|
|
else
|
|
|
|
|
PythonSingleton::get()->deactivateLocal();
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
client->SetOutputMask(oldMask);
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
return S_OK;
|
2015-03-23 01:29:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
extern "C"
|
|
|
|
|
HRESULT
|
|
|
|
|
CALLBACK
|
|
|
|
|
install(
|
|
|
|
|
PDEBUG_CLIENT client,
|
|
|
|
|
PCSTR args
|
|
|
|
|
)
|
2015-03-23 03:13:26 +08:00
|
|
|
|
{
|
2015-05-14 19:05:55 +08:00
|
|
|
|
DbgOut dbgOut(client);
|
|
|
|
|
DbgOut dbgErr(client);
|
|
|
|
|
DbgIn dbgIn(client);
|
2015-03-23 03:13:26 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
PythonSingleton::get()->acivateGlobal();
|
|
|
|
|
|
2015-04-16 07:01:43 +08:00
|
|
|
|
try {
|
2015-05-14 19:05:55 +08:00
|
|
|
|
|
|
|
|
|
python::object sys = python::import("sys");
|
|
|
|
|
|
|
|
|
|
sys.attr("stdout") = python::object(dbgOut);
|
|
|
|
|
sys.attr("stderr") = python::object(dbgErr);
|
|
|
|
|
sys.attr("stdin") = python::object(dbgIn);
|
2015-03-23 03:13:26 +08:00
|
|
|
|
|
2015-04-16 07:01:43 +08:00
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ( <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> exec_file )
|
|
|
|
|
python::object main = python::import("__main__");
|
|
|
|
|
python::object global(main.attr("__dict__"));
|
2015-03-23 03:13:26 +08:00
|
|
|
|
|
|
|
|
|
python::exec("import pip\n", global);
|
|
|
|
|
python::exec("pip.logger.consumers = []\n", global);
|
|
|
|
|
python::exec("pip.main(['install', 'pykd'])\n", global);
|
2015-05-14 19:05:55 +08:00
|
|
|
|
|
2015-03-23 03:13:26 +08:00
|
|
|
|
}
|
2015-05-14 19:05:55 +08:00
|
|
|
|
catch (const python::error_already_set&)
|
2015-03-23 03:13:26 +08:00
|
|
|
|
{
|
2015-05-14 19:05:55 +08:00
|
|
|
|
printException(dbgOut);
|
2015-03-23 03:13:26 +08:00
|
|
|
|
}
|
2015-04-30 20:14:34 +08:00
|
|
|
|
catch (const std::exception& invalidArg)
|
|
|
|
|
{
|
|
|
|
|
_bstr_t bstrInavalidArg(invalidArg.what());
|
2015-05-14 19:05:55 +08:00
|
|
|
|
dbgOut.write(std::wstring(bstrInavalidArg));
|
2015-04-30 20:14:34 +08:00
|
|
|
|
}
|
2015-05-14 19:05:55 +08:00
|
|
|
|
|
|
|
|
|
PythonSingleton::get()->deactivateGlobal();
|
2015-03-23 03:13:26 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
return S_OK;
|
2015-03-23 03:13:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
2015-03-23 03:13:26 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
extern "C"
|
|
|
|
|
HRESULT
|
|
|
|
|
CALLBACK
|
|
|
|
|
upgrade(
|
|
|
|
|
PDEBUG_CLIENT client,
|
|
|
|
|
PCSTR args
|
|
|
|
|
)
|
2015-03-23 03:13:26 +08:00
|
|
|
|
{
|
2015-05-14 19:05:55 +08:00
|
|
|
|
DbgOut dbgOut(client);
|
|
|
|
|
DbgOut dbgErr(client);
|
|
|
|
|
DbgIn dbgIn(client);
|
|
|
|
|
|
|
|
|
|
PythonSingleton::get()->acivateGlobal();
|
2015-03-23 03:13:26 +08:00
|
|
|
|
|
|
|
|
|
try {
|
2015-04-16 07:01:43 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
python::object sys = python::import("sys");
|
2015-03-23 03:13:26 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
sys.attr("stdout") = python::object(dbgOut);
|
|
|
|
|
sys.attr("stderr") = python::object(dbgErr);
|
|
|
|
|
sys.attr("stdin") = python::object(dbgIn);
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ( <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> exec_file )
|
2015-04-16 07:01:43 +08:00
|
|
|
|
python::object main = python::import("__main__");
|
|
|
|
|
python::object global(main.attr("__dict__"));
|
2015-05-14 19:05:55 +08:00
|
|
|
|
|
2015-03-23 03:13:26 +08:00
|
|
|
|
python::exec("import pip\n", global);
|
|
|
|
|
python::exec("pip.logger.consumers = []\n", global);
|
|
|
|
|
python::exec("pip.main(['install', '--upgrade', 'pykd'])\n", global);
|
2015-05-14 19:05:55 +08:00
|
|
|
|
|
2015-03-23 03:13:26 +08:00
|
|
|
|
}
|
2015-05-14 19:05:55 +08:00
|
|
|
|
catch (const python::error_already_set&)
|
2015-03-23 03:13:26 +08:00
|
|
|
|
{
|
2015-05-14 19:05:55 +08:00
|
|
|
|
printException(dbgOut);
|
2015-03-23 03:13:26 +08:00
|
|
|
|
}
|
2015-04-30 20:14:34 +08:00
|
|
|
|
catch (const std::exception& invalidArg)
|
|
|
|
|
{
|
|
|
|
|
_bstr_t bstrInavalidArg(invalidArg.what());
|
2015-05-14 19:05:55 +08:00
|
|
|
|
dbgOut.write(std::wstring(bstrInavalidArg));
|
2015-04-30 20:14:34 +08:00
|
|
|
|
}
|
2015-03-23 03:13:26 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
PythonSingleton::get()->deactivateGlobal();
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
return S_OK;
|
2015-03-23 01:29:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
std::string findScript(const std::string &fullFileName)
|
2015-03-23 01:29:38 +08:00
|
|
|
|
{
|
|
|
|
|
if (GetFileAttributesA(fullFileName.c_str()) != INVALID_FILE_ATTRIBUTES)
|
|
|
|
|
return fullFileName;
|
|
|
|
|
|
|
|
|
|
python::object sys = python::import("sys");
|
|
|
|
|
|
|
|
|
|
python::list pathList(sys.attr("path"));
|
|
|
|
|
|
|
|
|
|
python::ssize_t n = python::len(pathList);
|
|
|
|
|
|
|
|
|
|
for (python::ssize_t i = 0; i < n; i++)
|
|
|
|
|
{
|
|
|
|
|
std::string path = boost::python::extract<std::string>(pathList[i]);
|
|
|
|
|
|
|
|
|
|
DWORD bufSize = SearchPathA(
|
|
|
|
|
path.c_str(),
|
|
|
|
|
fullFileName.c_str(),
|
|
|
|
|
NULL,
|
|
|
|
|
0,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
if (bufSize > 0)
|
|
|
|
|
{
|
|
|
|
|
bufSize += 1;
|
|
|
|
|
std::vector<char> fullFileNameCStr(bufSize);
|
|
|
|
|
char *partFileNameCStr = NULL;
|
|
|
|
|
|
|
|
|
|
bufSize = SearchPathA(
|
|
|
|
|
path.c_str(),
|
|
|
|
|
fullFileName.c_str(),
|
|
|
|
|
NULL,
|
|
|
|
|
bufSize,
|
|
|
|
|
&fullFileNameCStr[0],
|
|
|
|
|
&partFileNameCStr);
|
|
|
|
|
|
2015-04-30 20:14:34 +08:00
|
|
|
|
DWORD fileAttr = GetFileAttributesA(&fullFileNameCStr[0]);
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
if ((fileAttr & FILE_ATTRIBUTE_DIRECTORY) == 0)
|
2015-03-23 01:29:38 +08:00
|
|
|
|
return std::string(&fullFileNameCStr[0]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
std::string getScriptFileName(const std::string &scriptName)
|
|
|
|
|
{
|
|
|
|
|
std::string scriptFileName = findScript(scriptName);
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
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)
|
2015-03-23 01:29:38 +08:00
|
|
|
|
{
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
PyObject *errtype = NULL, *errvalue = NULL, *traceback = NULL;
|
|
|
|
|
|
|
|
|
|
PyErr_Fetch(&errtype, &errvalue, &traceback);
|
|
|
|
|
|
|
|
|
|
PyErr_NormalizeException(&errtype, &errvalue, &traceback);
|
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
if (errtype != PyExc_SystemExit)
|
|
|
|
|
{
|
|
|
|
|
python::object tracebackModule = python::import("traceback");
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
std::wstringstream sstr;
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
python::object lst =
|
|
|
|
|
python::object(tracebackModule.attr("format_exception"))(
|
|
|
|
|
python::handle<>(errtype),
|
|
|
|
|
python::handle<>(python::allow_null(errvalue)),
|
|
|
|
|
python::handle<>(python::allow_null(traceback)));
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
sstr << std::endl << std::endl;
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
for (long i = 0; i < python::len(lst); ++i)
|
|
|
|
|
sstr << std::wstring(python::extract<std::wstring>(lst[i])) << std::endl;
|
2015-03-23 01:29:38 +08:00
|
|
|
|
|
2015-05-14 19:05:55 +08:00
|
|
|
|
dbgOut.write(sstr.str());
|
|
|
|
|
}
|
2015-03-23 01:29:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|