4 ms·
Can you expand a bit on how that works in principle ? Can you make it work with a standard python or did you need to insert probes' into the python interpreter
by cdavid 13y ago
Can you expand a bit on how that works in principle ? Can you make it work with a standard python or did you need to insert probes' into the python interpreter to catch when it goes form C to Python and vice et versa
- DinoV 13y agoVS 2012 added a new debugging framework for supporting debugging multiple code types at the same time. That model requires that the debugger work out of process - inspecting various data structures cross process and reporting them back to VS. That's different from how Python debuggers are usually built w/ sys.settrace and a debugger helper thread running in the process. To accomplish that we require that we have symbols for the Python interpreter (which are typically available on python.org). The debug engine uses a combination of the native equivalent of sys.settrace, strategic breakpoints, and using the symbols to walk core Python data structures. There's a bunch of fun tricks for evaluating code when stopped at a Python frame and creating strings, ints, etc... when users type them into the watch window. If you'd like to dig in more the source is at http://pytools.codeplex.com/SourceControl/latest http://pytools.codeplex.com/SourceControl/latest under Python\Product\Debugger\DkmDebugger.
- ritonlajoie 13y agoMy understanding is that dual debugging works when your main process is oythin and you can the debug some C python module. Is ther a way to debug a C process loading python27.dll which then runs some pythin code using the oython-C api?
- int_19h 13y agoMixed-mode debugging works in both of these scenarios (remember that python.exe is really just a "C process loading python27.dll"). You don't need a Python project at all, you can just attach to a running process (whether it is python.exe or your own host) and start debugging. You can even do that if the host process hasn't actually loaded python##.dll yet, though of course Python breakpoints etc will only light up once that happens. Here's a screenshot of a debug session with a custom host process written in C# running Python code that in turn uses a C++ extension module: http://i.imgur.com/IDPsWUu.png http://i.imgur.com/IDPsWUu.png
- int_19h 13y agoSome more specifics: Stack walking works by rewriting the native stack. Basically we just let the native stack walker do its job, then strip out all python##.dll frames except for PyEval_EvalFrameEx. For that one we read the "f" argument and then parse the PyFrameObject to which it points, and replace the frame with our own using data from that frame object. We parse the data structures ourselves, but use symbols to do so, which is why it'll work on any CPython build with symbols. This is why you can inspect objects even when process is stopped somewhere in native code, and it's impossible to eval using the interpreter. We still use sys.settrace for breakpoints and Python stepping. Python-to-native stepping works by setting native breakpoints on code paths inside Python interpreter that can potentially invoke some user code (e.g. type_call invokes tp_init, which may point to a user function). When those breakpoints are hit, we eval the function pointer and see if it's outside of python##.dll, and if so, then set another breakpoint there. When it's hit, your step is complete. So no, there are no special hooks added to the interpreter. We do end up relying quite a bit on internal implementation details, since we need to do things such as set breakpoints inside static functions, and read their arguments. However, because we use symbols for that, this works on any CPython build, including debug ones, and even customized ones so long as you don't rename anything that we rely on. E.g. adding a new field to PyObject is kosher, but renaming ob_type to something else would break us.
- cdavid 13y agoThanks a lot for the detailed explanation.