Ok, it seems like very few people know how to use python-gdb.py :-/ Sorry, I expect that everybody was using it! python-gdb.py was written by Dave Malcolm, it includes: * a pretty printer for many builtin Python types: str, tuple, list, dict, frame, etc. It means that a regular gdb "print obj" command displays the Python object content instead of a raw pointer. This feature is super useful, it avoids to call _PyObject_Dump(obj) which is likely to crash! * commands to navigate between Python frames: py-up, py-down * command to dump the Python traceback: py-bt, py-bt-full (also include C frames) * a few more commands For me, these commands are really amazing! It's impressive to be able to that in a debugger which doesn't know Python internals at all! It's cool to be able to "program" (extend) a debugger! I never tried to install it, I always use it with a ./python binary compiled in the source code tree: --- $ make $ gdb ./python # load ./python-gdb.py ... --- Note: ./python-gdb.py is simply a copy of Tools/gdb/libpython.py, copied by Makefile. On Fedora, gdb doesn't load python-gdb.py because it doesn't trust my $HOME/prog directory (root of all my development directories). I had to trust it using this ~/.gdbinit config: --- add-auto-load-safe-path ~/prog/ --- More generally, when gdb loads a "program", it tries to load "program-gdb.py" in the same directory. Maybe it can load "program-gdb.py" from other directories, but I never understood this part, and hopefully I never had to understand it :-D Maybe the debug package of Python on Debian and Fedora installs pythonX.Y-gdb.py in the right directory, I didn't check, but I always debug using a freshly compiled Python, so I never tried to understand how these things work. Example: ---- haypo@selma$ gdb ./python (gdb) b _PyEval_EvalFrameDefault (gdb) run Breakpoint 1, _PyEval_EvalFrameDefault ( f=Frame 0x7ffff7f22058, for file <frozen importlib._bootstrap>, line 25, in <module> (), throwflag=0) at Python/ceval.c:678 678 PyObject *retval = NULL; /* Return value */ => gdb displays the content of the frame "f", you can see immediately the filename and the line number (well, this frame is a little bit special, it's the frozen module importlib) (gdb) py-bt Traceback (most recent call first): File "<frozen importlib._bootstrap>", line 25, in <module> --- Example of Python traceback: ---- haypo@selma$ gdb -args ./python -m test -r (gdb) run ... ^C (gdb) py-bt Traceback (most recent call first): File "/home/haypo/prog/python/master/Lib/test/test_long.py", line 947, in test_bit_length self.assertEqual(k, len(bin(x).lstrip('-0b'))) File "/home/haypo/prog/python/master/Lib/unittest/case.py", line 601, in run testMethod() File "/home/haypo/prog/python/master/Lib/unittest/case.py", line 649, in __call__ return self.run(*args, **kwds) File "/home/haypo/prog/python/master/Lib/unittest/suite.py", line 122, in run test(result) File "/home/haypo/prog/python/master/Lib/unittest/suite.py", line 84, in __call__ return self.run(*args, **kwds) ... => you get filename, line number, function name and even the Python line! It seems obvious to get such information, but remind that you are in gdb, not in Python (gdb) py-list 942 def test_bit_length(self): 943 tiny = 1e-10 944 for x in range(-65000, 65000): 945 k = x.bit_length() 946 # Check equivalence with Python version
947 self.assertEqual(k, len(bin(x).lstrip('-0b'))) 948 # Behaviour as specified in the docs 949 if x != 0: 950 self.assertTrue(2**(k-1) <= abs(x) < 2**k) 951 else: 952 self.assertEqual(k, 0)
# move to the parent Python frame (= skip mutiple C frames until the next Python frame) (gdb) py-up (...) (gdb) py-list 596 with outcome.testPartExecutor(self): 597 self.setUp() 598 if outcome.success: 599 outcome.expecting_failure = expecting_failure 600 with outcome.testPartExecutor(self, isTest=True):
601 testMethod() 602 outcome.expecting_failure = False 603 with outcome.testPartExecutor(self): 604 self.tearDown() 605 606 self.doCleanups()
(gdb) py-locals
self =