From daf92069122da40ff892860642e728080cfffb95 Mon Sep 17 00:00:00 2001 From: Fabio Zadrozny Date: Wed, 19 Jun 2019 09:11:38 -0300 Subject: [PATCH] Support running code in target process to attach to pid in Linux. Partial fix for #863 (#1525) --- .gitignore | 3 - src/ptvsd/__main__.py | 86 +++----- src/ptvsd/_vendored/pydevd/pydevd.py | 1 + .../attach_linux_amd64.so | Bin 0 -> 15952 bytes .../attach_linux_x86.so | Bin 0 -> 15260 bytes .../linux/attach_linux.c | 81 ++++--- .../linux/compile_so.sh | 0 .../pydevd_attach_to_process/linux/python.h | 203 +++++++++++++++--- src/ptvsd/attach_script_ptvsd_pid.py | 24 +++ src/ptvsd/pydevd_hooks.py | 10 +- 10 files changed, 299 insertions(+), 109 deletions(-) create mode 100755 src/ptvsd/_vendored/pydevd/pydevd_attach_to_process/attach_linux_amd64.so create mode 100755 src/ptvsd/_vendored/pydevd/pydevd_attach_to_process/attach_linux_x86.so mode change 100644 => 100755 src/ptvsd/_vendored/pydevd/pydevd_attach_to_process/linux/compile_so.sh create mode 100644 src/ptvsd/attach_script_ptvsd_pid.py diff --git a/.gitignore b/.gitignore index e95c34ea..2abc816e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,9 +3,6 @@ __pycache__/ *.py[cod] *$py.class -# C extensions -*.so - # Distribution / packaging .Python env/ diff --git a/src/ptvsd/__main__.py b/src/ptvsd/__main__.py index a28f9d13..1d384241 100644 --- a/src/ptvsd/__main__.py +++ b/src/ptvsd/__main__.py @@ -350,66 +350,50 @@ def run_code(): def attach_to_pid(): - def quoted_str(s): - if s is None: - return s - assert not isinstance(s, bytes) - unescaped = set(chr(ch) for ch in range(32, 127)) - {'"', "'", '\\'} - - def escape(ch): - return ch if ch in unescaped else '\\u%04X' % ord(ch) - - return 'u"' + ''.join(map(escape, s)) + '"' - ptvsd.log.info('Attaching to process with ID {0}', ptvsd.options.target) pid = ptvsd.options.target - host = quoted_str(ptvsd.options.host) + host = ptvsd.options.host port = ptvsd.options.port client = ptvsd.options.client - log_dir = quoted_str(ptvsd.options.log_dir) - - ptvsd_path = os.path.abspath(os.path.join(ptvsd.__file__, '../..')) - if isinstance(ptvsd_path, bytes): - ptvsd_path = ptvsd_path.decode(sys.getfilesystemencoding()) - ptvsd_path = quoted_str(ptvsd_path) - - # pydevd requires injected code to not contain any single quotes. - code = ''' -import os -assert os.getpid() == {pid} - -import sys -sys.path.insert(0, {ptvsd_path}) -import ptvsd -del sys.path[0] - -import ptvsd.options -ptvsd.options.log_dir = {log_dir} -ptvsd.options.client = {client} -ptvsd.options.host = {host} -ptvsd.options.port = {port} - -import ptvsd.log -ptvsd.log.to_file() -ptvsd.log.info("Debugger successfully injected") - -if ptvsd.options.client: - from ptvsd._remote import attach - attach(({host}, {port})) -else: - ptvsd.enable_attach() -'''.format(**locals()) - - ptvsd.log.debug('Injecting debugger into target process: \n"""{0}\n"""'.format(code)) - assert "'" not in code, 'Injected code should not contain any single quotes' + log_dir = ptvsd.options.log_dir + if log_dir is None: + log_dir = "" + # pydevd requires injected code to not contain any single quotes nor new lines and + # double quotes must be escaped properly. pydevd_attach_to_process_path = os.path.join( os.path.dirname(pydevd.__file__), 'pydevd_attach_to_process') - sys.path.insert(0, pydevd_attach_to_process_path) - from add_code_to_python_process import run_python_code - run_python_code(pid, code, connect_debugger_tracing=True) + + sys.path.append(pydevd_attach_to_process_path) + + import add_code_to_python_process # noqa + show_debug_info_on_target_process = 0 # hard-coded (1 to debug) + + ptvsd_dirname = os.path.dirname(os.path.dirname(__file__)) + log_dir = log_dir.replace('\\', '/') + setup = {'host': host, 'port': port, 'client': client, 'log_dir': log_dir, 'pid': pid} + + if sys.platform == 'win32': + setup['pythonpath'] = ptvsd_dirname.replace('\\', '/') + python_code = '''import sys; +sys.path.append("%(pythonpath)s"); +from ptvsd import attach_script_ptvsd_pid; +attach_script_ptvsd_pid.attach(port=%(port)s, host="%(host)s", client=%(client)s, log_dir="%(log_dir)s"); +'''.replace('\r\n', '').replace('\r', '').replace('\n', '') + else: + setup['pythonpath'] = ptvsd_dirname + # We have to pass it a bit differently for gdb + python_code = '''import sys; +sys.path.append(\\\"%(pythonpath)s\\\"); +from ptvsd import attach_script_ptvsd_pid; +attach_script_ptvsd_pid.attach(port=%(port)s, host=\\\"%(host)s\\\", client=%(client)s, log_dir=\\\"%(log_dir)s\\\"); +'''.replace('\r\n', '').replace('\r', '').replace('\n', '') + + python_code = python_code % setup + add_code_to_python_process.run_python_code( + setup['pid'], python_code, connect_debugger_tracing=True, show_debug_info=show_debug_info_on_target_process) def main(argv=sys.argv): diff --git a/src/ptvsd/_vendored/pydevd/pydevd.py b/src/ptvsd/_vendored/pydevd/pydevd.py index c62f5a8d..085dc13a 100644 --- a/src/ptvsd/_vendored/pydevd/pydevd.py +++ b/src/ptvsd/_vendored/pydevd/pydevd.py @@ -912,6 +912,7 @@ class PyDB(object): self._finish_debugging_session = True def initialize_network(self, sock, terminate_on_socket_close=True): + assert sock is not None try: sock.settimeout(None) # infinite, no timeouts from now on - jython does not have it except: diff --git a/src/ptvsd/_vendored/pydevd/pydevd_attach_to_process/attach_linux_amd64.so b/src/ptvsd/_vendored/pydevd/pydevd_attach_to_process/attach_linux_amd64.so new file mode 100755 index 0000000000000000000000000000000000000000..503331563fa540be89a5f0a3f9c4b829cf08dc57 GIT binary patch literal 15952 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 JO4OgJ_y5JBtzZBE literal 0 HcmV?d00001 diff --git a/src/ptvsd/_vendored/pydevd/pydevd_attach_to_process/linux/attach_linux.c b/src/ptvsd/_vendored/pydevd/pydevd_attach_to_process/linux/attach_linux.c index 3687ba56..0e28faad 100644 --- a/src/ptvsd/_vendored/pydevd/pydevd_attach_to_process/linux/attach_linux.c +++ b/src/ptvsd/_vendored/pydevd/pydevd_attach_to_process/linux/attach_linux.c @@ -60,6 +60,7 @@ typedef int (*PyEval_ThreadsInitialized)(); typedef unsigned long (*_PyEval_GetSwitchInterval)(void); typedef void (*_PyEval_SetSwitchInterval)(unsigned long microseconds); typedef int (*PyRun_SimpleString)(const char *command); +typedef int (*PyObject_Not) (PyObject *o); // Helper so that we get a PyObject where we can access its fields (in debug or release). PyObject* GetPyObjectPointerNoDebugInfo(bool isDebug, PyObject* object) { @@ -121,7 +122,7 @@ public: }; -# define CHECK_NULL(ptr, msg, returnVal) if(ptr == NULL){if(showDebugInfo){printf(msg);} return returnVal;} +# define CHECK_NULL(ptr, msg, returnVal) if(ptr == NULL){printf(msg); return returnVal;} int DoAttach(bool isDebug, const char *command, bool showDebugInfo) { @@ -161,7 +162,7 @@ int DoAttach(bool isDebug, const char *command, bool showDebugInfo) PyRun_SimpleString pyRun_SimpleString; *(void**)(&pyRun_SimpleString) = dlsym(main_hndl, "PyRun_SimpleString"); - CHECK_NULL(pyRun_SimpleString, "PyRun_SimpleString not found.\n", 6); + CHECK_NULL(pyRun_SimpleString, "PyRun_SimpleString not found.\n", 7); PyGILState_STATE pyGILState = pyGilStateEnsureFunc(); pyRun_SimpleString(command); @@ -171,7 +172,7 @@ int DoAttach(bool isDebug, const char *command, bool showDebugInfo) // All of the code below is the same as: -// sys.settrace(pydevd.GetGlobalDebugger().trace_dispatch) +// sys.settrace(pydevd.get_global_debugger().trace_dispatch) // // (with error checking) int SetSysTraceFunc(bool showDebugInfo, bool isDebug) @@ -188,25 +189,25 @@ int SetSysTraceFunc(bool showDebugInfo, bool isDebug) if(showDebugInfo){ printf("Py_IsInitialized returned false.\n"); } - return 2; + return 20; } PythonVersion version = GetPythonVersion(); PyInterpreterState_Head interpHeadFunc; *(void**)(&interpHeadFunc) = dlsym(main_hndl, "PyInterpreterState_Head"); - CHECK_NULL(interpHeadFunc, "PyInterpreterState_Head not found.\n", 3); + CHECK_NULL(interpHeadFunc, "PyInterpreterState_Head not found.\n", 21); PyInterpreterState* head = interpHeadFunc(); - CHECK_NULL(head, "Interpreter not initialized.\n", 4); + CHECK_NULL(head, "Interpreter not initialized.\n", 22); PyGILState_Ensure pyGilStateEnsureFunc; *(void**)(&pyGilStateEnsureFunc) = dlsym(main_hndl, "PyGILState_Ensure"); - CHECK_NULL(pyGilStateEnsureFunc, "PyGILState_Ensure not found.\n", 5); + CHECK_NULL(pyGilStateEnsureFunc, "PyGILState_Ensure not found.\n", 23); PyGILState_Release pyGilStateReleaseFunc; *(void**)(&pyGilStateReleaseFunc) = dlsym(main_hndl, "PyGILState_Release"); - CHECK_NULL(pyGilStateReleaseFunc, "PyGILState_Release not found.\n", 6); + CHECK_NULL(pyGilStateReleaseFunc, "PyGILState_Release not found.\n", 24); PyGILState_STATE pyGILState = pyGilStateEnsureFunc(); int ret = _PYDEVD_ExecWithGILSetSysStrace(showDebugInfo, isDebug); @@ -221,63 +222,91 @@ int _PYDEVD_ExecWithGILSetSysStrace(bool showDebugInfo, bool isDebug){ void *main_hndl = dlopen(NULL, 0x2); *(void**)(&boolFromLongFunc) = dlsym(main_hndl, "PyBool_FromLong"); - CHECK_NULL(boolFromLongFunc, "PyBool_FromLong not found.\n", 7); + CHECK_NULL(boolFromLongFunc, "PyBool_FromLong not found.\n", 41); PyObject_HasAttrString pyHasAttrFunc; *(void**)(&pyHasAttrFunc) = dlsym(main_hndl, "PyObject_HasAttrString"); - CHECK_NULL(pyHasAttrFunc, "PyObject_HasAttrString not found.\n", 7); + CHECK_NULL(pyHasAttrFunc, "PyObject_HasAttrString not found.\n", 42); //Important: we need a non-blocking import here: PyImport_ImportModule //could end up crashing (this makes us work only from 2.6 onwards). PyImport_ImportModuleNoBlock pyImportModFunc; *(void**)(&pyImportModFunc) = dlsym(main_hndl, "PyImport_ImportModuleNoBlock"); - CHECK_NULL(pyImportModFunc, "PyImport_ImportModuleNoBlock not found.\n", 8); + CHECK_NULL(pyImportModFunc, "PyImport_ImportModuleNoBlock not found.\n", 43); + + PyObject_Not pyObjectNot; + *(void**)(&pyObjectNot) = dlsym(main_hndl, "PyObject_Not"); + CHECK_NULL(pyObjectNot, "PyObject_Not not found.\n", 44); PyObjectHolder pydevdTracingMod = PyObjectHolder(isDebug, pyImportModFunc("pydevd_tracing")); - CHECK_NULL(pydevdTracingMod.ToPython(), "pydevd_tracing module null.\n", 9); + CHECK_NULL(pydevdTracingMod.ToPython(), "pydevd_tracing module null.\n", 45); if(!pyHasAttrFunc(pydevdTracingMod.ToPython(), "_original_settrace")){ if(showDebugInfo){ printf("pydevd_tracing module has no _original_settrace!\n"); } - return 8; + return 46; } PyObject_GetAttrString pyGetAttr; *(void**)(&pyGetAttr) = dlsym(main_hndl, "PyObject_GetAttrString"); - CHECK_NULL(pyGetAttr, "PyObject_GetAttrString not found.\n", 8); + CHECK_NULL(pyGetAttr, "PyObject_GetAttrString not found.\n", 47); PyObjectHolder settrace = PyObjectHolder(isDebug, pyGetAttr(pydevdTracingMod.ToPython(), "_original_settrace")); - CHECK_NULL(settrace.ToPython(), "pydevd_tracing._original_settrace null!\n", 10); + CHECK_NULL(settrace.ToPython(), "pydevd_tracing._original_settrace null!\n", 48); + + if(pyObjectNot(settrace.ToPython())){ + printf("_original_settrace is None."); + return 49; + } PyObjectHolder pydevdMod = PyObjectHolder(isDebug, pyImportModFunc("pydevd")); - CHECK_NULL(pydevdMod.ToPython(), "pydevd module null.\n", 10); + CHECK_NULL(pydevdMod.ToPython(), "pydevd module null.\n", 50); - PyObjectHolder getGlobalDebugger = PyObjectHolder(isDebug, pyGetAttr(pydevdMod.ToPython(), "GetGlobalDebugger")); - CHECK_NULL(getGlobalDebugger.ToPython(), "pydevd.GetGlobalDebugger null.\n", 11); + if(pyObjectNot(pydevdMod.ToPython())){ + printf("pydevdMod is None."); + return 51; + } + + if(!pyHasAttrFunc(pydevdMod.ToPython(), "get_global_debugger")){ + printf("pydevd module has no attribute get_global_debugger!\n"); + return 52; + } + + + PyObjectHolder getGlobalDebugger = PyObjectHolder(isDebug, pyGetAttr(pydevdMod.ToPython(), "get_global_debugger")); + CHECK_NULL(getGlobalDebugger.ToPython(), "pydevd.get_global_debugger is null.\n", 53); + + if(pyObjectNot(getGlobalDebugger.ToPython())){ + printf("getGlobalDebugger returned None."); + return 54; + } PyObject_CallFunctionObjArgs call; *(void**)(&call) = dlsym(main_hndl, "PyObject_CallFunctionObjArgs"); - CHECK_NULL(call, "PyObject_CallFunctionObjArgs not found.\n", 11); + CHECK_NULL(call, "PyObject_CallFunctionObjArgs not found.\n", 55); PyObjectHolder globalDbg = PyObjectHolder(isDebug, call(getGlobalDebugger.ToPython(), NULL)); - CHECK_NULL(globalDbg.ToPython(), "pydevd.GetGlobalDebugger() returned null.\n", 12); + CHECK_NULL(globalDbg.ToPython(), "pydevd.get_global_debugger() returned null.\n", 56); if(!pyHasAttrFunc(globalDbg.ToPython(), "trace_dispatch")){ - if(showDebugInfo){ - printf("pydevd.GetGlobalDebugger() has no attribute trace_dispatch!\n"); - } - return 13; + printf("pydevd.get_global_debugger() has no attribute trace_dispatch!\n"); + return 57; } PyObjectHolder traceFunc = PyObjectHolder(isDebug, pyGetAttr(globalDbg.ToPython(), "trace_dispatch")); - CHECK_NULL(traceFunc.ToPython(), "pydevd.GetGlobalDebugger().trace_dispatch returned null!\n", 14); + CHECK_NULL(traceFunc.ToPython(), "pydevd.get_global_debugger().trace_dispatch returned null!\n", 58); + + if(pyObjectNot(traceFunc.ToPython())){ + printf("pydevd.get_global_debugger().trace_dispatch is None."); + return 59; + } DecRef(call(settrace.ToPython(), traceFunc.ToPython(), NULL), isDebug); if(showDebugInfo){ - printf("sys.settrace(pydevd.GetGlobalDebugger().trace_dispatch) worked.\n"); + printf("sys.settrace(pydevd.get_global_debugger().trace_dispatch) worked.\n"); } return 0; diff --git a/src/ptvsd/_vendored/pydevd/pydevd_attach_to_process/linux/compile_so.sh b/src/ptvsd/_vendored/pydevd/pydevd_attach_to_process/linux/compile_so.sh old mode 100644 new mode 100755 diff --git a/src/ptvsd/_vendored/pydevd/pydevd_attach_to_process/linux/python.h b/src/ptvsd/_vendored/pydevd/pydevd_attach_to_process/linux/python.h index 93bfe6e4..0238cfc1 100644 --- a/src/ptvsd/_vendored/pydevd/pydevd_attach_to_process/linux/python.h +++ b/src/ptvsd/_vendored/pydevd/pydevd_attach_to_process/linux/python.h @@ -26,7 +26,10 @@ enum PythonVersion { PythonVersion_31 = 0x0301, PythonVersion_32 = 0x0302, PythonVersion_33 = 0x0303, - PythonVersion_34 = 0x0304 + PythonVersion_34 = 0x0304, + PythonVersion_35 = 0x0305, + PythonVersion_36 = 0x0306, + PythonVersion_37 = 0x0307 }; @@ -111,8 +114,8 @@ public: } }; -// 3.3-3.4 -class PyCodeObject33_34 : public PyObject { +// 3.3-3.5 +class PyCodeObject33_35 : public PyObject { public: int co_argcount; /* #arguments, except *args */ int co_kwonlyargcount; /* #keyword only arguments */ @@ -134,15 +137,77 @@ public: void *co_zombieframe; /* for optimization only (see frameobject.c) */ static bool IsFor(int majorVersion, int minorVersion) { - return majorVersion == 3 && (minorVersion >= 3 && minorVersion <= 4); + return majorVersion == 3 && (minorVersion >= 3 && minorVersion <= 5); } static bool IsFor(PythonVersion version) { - return version >= PythonVersion_33 && version <= PythonVersion_34; + return version >= PythonVersion_33 && version <= PythonVersion_35; } }; -// 2.5 - 3.1 +// 3.6 +class PyCodeObject36 : public PyObject { +public: + int co_argcount; /* #arguments, except *args */ + int co_kwonlyargcount; /* #keyword only arguments */ + int co_nlocals; /* #local variables */ + int co_stacksize; /* #entries needed for evaluation stack */ + int co_flags; /* CO_..., see below */ + int co_firstlineno; /* first source line number */ + PyObject *co_code; /* instruction opcodes */ + PyObject *co_consts; /* list (constants used) */ + PyObject *co_names; /* list of strings (names used) */ + PyObject *co_varnames; /* tuple of strings (local variable names) */ + PyObject *co_freevars; /* tuple of strings (free variable names) */ + PyObject *co_cellvars; /* tuple of strings (cell variable names) */ + /* The rest doesn't count for hash or comparisons */ + unsigned char *co_cell2arg; /* Maps cell vars which are arguments. */ + PyObject *co_filename; /* unicode (where it was loaded from) */ + PyObject *co_name; /* unicode (name, for reference) */ + PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) */ + void *co_zombieframe; /* for optimization only (see frameobject.c) */ + + static bool IsFor(int majorVersion, int minorVersion) { + return majorVersion == 3 && minorVersion == 6; + } + + static bool IsFor(PythonVersion version) { + return version == PythonVersion_36; + } +}; + +// 3.7 +class PyCodeObject37 : public PyObject { +public: + int co_argcount; /* #arguments, except *args */ + int co_kwonlyargcount; /* #keyword only arguments */ + int co_nlocals; /* #local variables */ + int co_stacksize; /* #entries needed for evaluation stack */ + int co_flags; /* CO_..., see below */ + int co_firstlineno; /* first source line number */ + PyObject *co_code; /* instruction opcodes */ + PyObject *co_consts; /* list (constants used) */ + PyObject *co_names; /* list of strings (names used) */ + PyObject *co_varnames; /* tuple of strings (local variable names) */ + PyObject *co_freevars; /* tuple of strings (free variable names) */ + PyObject *co_cellvars; /* tuple of strings (cell variable names) */ + /* The rest doesn't count for hash or comparisons */ + ssize_t *co_cell2arg; /* Maps cell vars which are arguments. */ + PyObject *co_filename; /* unicode (where it was loaded from) */ + PyObject *co_name; /* unicode (name, for reference) */ + PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) */ + void *co_zombieframe; /* for optimization only (see frameobject.c) */ + + static bool IsFor(int majorVersion, int minorVersion) { + return majorVersion == 3 && minorVersion >= 7; + } + + static bool IsFor(PythonVersion version) { + return version >= PythonVersion_37; + } +}; + +// 2.5 - 3.7 class PyFunctionObject : public PyObject { public: PyObject *func_code; /* A code object */ @@ -165,7 +230,7 @@ public: */ }; -// 2.4 - 3.2 compatible +// 2.4 - 3.7 compatible typedef struct { PyObject_HEAD size_t length; /* Length of raw Unicode data in buffer */ @@ -173,7 +238,7 @@ typedef struct { long hash; /* Hash value; -1 if not set */ } PyUnicodeObject; -// 2.4 - 3.4 compatible +// 2.4 - 3.7 compatible class PyFrameObject : public PyVarObject { public: PyFrameObject *f_back; /* previous frame, or NULL */ @@ -187,7 +252,6 @@ public: to the current stack top. */ PyObject **f_stacktop; PyObject *f_trace; /* Trace function */ - PyObject *f_exc_type, *f_exc_value, *f_exc_traceback; }; #define CO_MAXBLOCKS 20 @@ -199,6 +263,7 @@ typedef struct { class PyFrameObject25_33 : public PyFrameObject { public: + PyObject * f_exc_type, *f_exc_value, *f_exc_traceback; PyThreadState* f_tstate; int f_lasti; /* Last instruction if called */ /* As of 2.3 f_lineno is only valid when tracing is active (i.e. when @@ -214,8 +279,9 @@ public: } }; -class PyFrameObject34 : public PyFrameObject { +class PyFrameObject34_36 : public PyFrameObject { public: + PyObject * f_exc_type, *f_exc_value, *f_exc_traceback; /* Borrowed reference to a generator, or NULL */ PyObject *f_gen; @@ -229,22 +295,43 @@ public: PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */ static bool IsFor(int majorVersion, int minorVersion) { - return majorVersion == 3 && minorVersion == 4; + return majorVersion == 3 && minorVersion >= 4 && minorVersion <= 6; + } +}; + +class PyFrameObject37 : public PyFrameObject { +public: + char f_trace_lines; /* Emit per-line trace events? */ + char f_trace_opcodes; /* Emit per-opcode trace events? */ + /* Borrowed reference to a generator, or NULL */ + PyObject *f_gen; + + int f_lasti; /* Last instruction if called */ + /* As of 2.3 f_lineno is only valid when tracing is active (i.e. when + f_trace is set) -- at other times use PyCode_Addr2Line instead. */ + int f_lineno; /* Current line number */ + int f_iblock; /* index in f_blockstack */ + char f_executing; /* whether the frame is still executing */ + PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */ + PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */ + + static bool IsFor(int majorVersion, int minorVersion) { + return majorVersion == 3 && minorVersion >= 7; } }; typedef void (*destructor)(PyObject *); -// 2.4 - 3.4 +// 2.4 - 3.7 class PyMethodDef { public: char *ml_name; /* The name of the built-in function/method */ }; -// -// 2.4 - 3.4, 2.4 has different compat in 64-bit but we don't support any of the released 64-bit platforms (which includes only IA-64) +// +// 2.5 - 3.7 // While these are compatible there are fields only available on later versions. class PyTypeObject : public PyVarObject { public: @@ -257,7 +344,10 @@ public: void* tp_print; void* tp_getattr; void* tp_setattr; - void* tp_compare; + union { + void* tp_compare; /* 2.4 - 3.4 */ + void *tp_as_async; /* 3.5 - 3.7 */ + }; void* tp_repr; /* Method suites for standard classes */ @@ -326,7 +416,7 @@ public: unsigned int tp_version_tag; }; -// 2.4 - 3.4 +// 2.4 - 3.7 class PyTupleObject : public PyVarObject { public: PyObject *ob_item[1]; @@ -337,7 +427,7 @@ public: */ }; -// 2.4 - 3.4 +// 2.4 - 3.7 class PyCFunctionObject : public PyObject { public: PyMethodDef *m_ml; /* Description of the C function to call */ @@ -422,7 +512,7 @@ public: int recursion_depth; char overflowed; /* The stack has overflowed. Allow 50 more calls to handle the runtime error. */ - char recursion_critical; /* The current calls must not cause + char recursion_critical; /* The current calls must not cause a stack overflow. */ /* 'tracing' keeps track of the execution depth when tracing/profiling. This is to prevent the actual trace/profile code from being recorded in @@ -468,7 +558,7 @@ public: } }; -class PyThreadState_34 : public PyThreadState { +class PyThreadState_34_36 : public PyThreadState { public: PyThreadState *prev; PyThreadState *next; @@ -478,7 +568,7 @@ public: int recursion_depth; char overflowed; /* The stack has overflowed. Allow 50 more calls to handle the runtime error. */ - char recursion_critical; /* The current calls must not cause + char recursion_critical; /* The current calls must not cause a stack overflow. */ /* 'tracing' keeps track of the execution depth when tracing/profiling. This is to prevent the actual trace/profile code from being recorded in @@ -504,15 +594,70 @@ public: int gilstate_counter; PyObject *async_exc; /* Asynchronous exception to raise */ - long thread_id; /* Thread id where this tstate was created */ + long thread_id; /* Thread id where this tstate was created */ /* XXX signal handlers should also be here */ + static bool IsFor(int majorVersion, int minorVersion) { - return majorVersion == 3 && minorVersion == 4; + return majorVersion == 3 && minorVersion >= 4 && minorVersion <= 6; } static bool IsFor(PythonVersion version) { - return version == PythonVersion_34; + return version >= PythonVersion_34 && version <= PythonVersion_36; + } +}; + +struct _PyErr_StackItem { + PyObject *exc_type, *exc_value, *exc_traceback; + struct _PyErr_StackItem *previous_item; +}; + +class PyThreadState_37 : public PyThreadState { +public: + PyThreadState * prev; + PyThreadState *next; + PyInterpreterState *interp; + + PyFrameObject *frame; + int recursion_depth; + char overflowed; /* The stack has overflowed. Allow 50 more calls + to handle the runtime error. */ + char recursion_critical; /* The current calls must not cause + a stack overflow. */ + /* 'tracing' keeps track of the execution depth when tracing/profiling. + This is to prevent the actual trace/profile code from being recorded in + the trace/profile. */ + int stackcheck_counter; + + int tracing; + int use_tracing; + + Py_tracefunc c_profilefunc; + Py_tracefunc c_tracefunc; + PyObject *c_profileobj; + PyObject *c_traceobj; + + PyObject *curexc_type; + PyObject *curexc_value; + PyObject *curexc_traceback; + + _PyErr_StackItem exc_state; + _PyErr_StackItem *exc_info; + + PyObject *dict; /* Stores per-thread state */ + + int gilstate_counter; + + PyObject *async_exc; /* Asynchronous exception to raise */ + + unsigned long thread_id; /* Thread id where this tstate was created */ + + static bool IsFor(int majorVersion, int minorVersion) { + return majorVersion == 3 && minorVersion >= 7; + } + + static bool IsFor(PythonVersion version) { + return version >= PythonVersion_37; } }; @@ -553,19 +698,23 @@ static PythonVersion GetPythonVersion() { if(versionFunc != NULL) { const char* version = versionFunc(); if(version != NULL && strlen(version) >= 3 && version[1] == '.') { - if(version[0] == '2') { - switch(version[2]) { + if (version[0] == '2') { + switch (version[2]) { case '5': return PythonVersion_25; case '6': return PythonVersion_26; case '7': return PythonVersion_27; } - } else if(version[0] == '3') { - switch(version[2]) { + } + else if (version[0] == '3') { + switch (version[2]) { case '0': return PythonVersion_30; case '1': return PythonVersion_31; case '2': return PythonVersion_32; case '3': return PythonVersion_33; case '4': return PythonVersion_34; + case '5': return PythonVersion_35; + case '6': return PythonVersion_36; + case '7': return PythonVersion_37; } } } diff --git a/src/ptvsd/attach_script_ptvsd_pid.py b/src/ptvsd/attach_script_ptvsd_pid.py new file mode 100644 index 00000000..1aae105c --- /dev/null +++ b/src/ptvsd/attach_script_ptvsd_pid.py @@ -0,0 +1,24 @@ +def attach(port, host, client, log_dir): + try: + if not log_dir: + log_dir = None + + import ptvsd.options + ptvsd.options.log_dir = log_dir + ptvsd.options.client = client + ptvsd.options.host = host + ptvsd.options.port = port + + import ptvsd.log + ptvsd.log.to_file() + ptvsd.log.info("Debugger successfully injected") + + if ptvsd.options.client: + from ptvsd._remote import attach + attach((host, port)) + else: + ptvsd.enable_attach((host, port)) + + except: + import traceback + traceback.print_exc() diff --git a/src/ptvsd/pydevd_hooks.py b/src/ptvsd/pydevd_hooks.py index a12377d6..07e092b4 100644 --- a/src/ptvsd/pydevd_hooks.py +++ b/src/ptvsd/pydevd_hooks.py @@ -127,9 +127,15 @@ def install(pydevd_module, address, addr = Address.from_raw(address) daemon = Daemon(**kwargs) - _start_server = (lambda p: start_server(daemon, addr.host, p)) + def _start_server(p): + ptvsd.log.debug('ptvsd: install._start_server.') + return start_server(daemon, addr.host, p) + + def _start_client(h, p): + ptvsd.log.debug('ptvsd: install._start_client.') + return start_client(daemon, h, p) + _start_server.orig = start_server - _start_client = (lambda h, p: start_client(daemon, h, p)) _start_client.orig = start_client # These are the functions pydevd invokes to get a socket to the client.