Forked from kouk/debugging python object fields with gdb
Created
November 9, 2017 02:46
-
-
Save wweic/dd8d2593da95572dea4093fee0ab66f9 to your computer and use it in GitHub Desktop.
pyfields.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ python foo.py & | |
[1] 21377 | |
$ gdb -p 21377 | |
GNU gdb (GDB) Fedora 7.7.1-17.fc20 | |
[... gdb loading messages ...] | |
0x00007f9a09af46e3 in __select_nocancel () at ../sysdeps/unix/syscall-template.S:81 | |
81 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS) | |
(gdb) py-bt | |
#4 Frame 0x22d9c70, for file foo.py, line 12, in forever () | |
sleep(1) | |
#7 Frame 0x224f830, for file foo.py, line 14, in <module> () | |
forever() | |
(gdb) py-print f | |
global 'f' = <Foo(foo=1) at remote 0x7f9a0abba830> | |
(gdb) py-print f.foo | |
'f.foo' not found | |
(gdb) source pyfields.py | |
(gdb) py-fields f.foo | |
global 'foo' = 1 | |
(gdb) quit | |
A debugging session is active. | |
Inferior 1 [process 21377] will be detached. | |
Quit anyway? (y or n) y | |
Detaching from program: /usr/bin/python2.7, process 21377 | |
$ exit | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from time import sleep | |
class Foo: | |
def __init__(self): | |
self.foo = 1 | |
f = Foo() | |
def forever(): | |
while f.foo == 1: | |
sleep(1) | |
forever() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class PyPrintFields(gdb.Command): | |
'Look up the given python variable name, and print it' | |
def __init__(self): | |
gdb.Command.__init__ (self, | |
"py-fields", | |
gdb.COMMAND_DATA, | |
gdb.COMPLETE_NONE) | |
def invoke(self, args, from_tty): | |
name = str(args) | |
frame = Frame.get_selected_python_frame() | |
if not frame: | |
print 'Unable to locate python frame' | |
return | |
pyop_frame = frame.get_pyop() | |
if not pyop_frame: | |
print 'Unable to read information on python frame' | |
return | |
def get_var_dict(v): | |
if isinstance(v, PyInstanceObjectPtr): | |
return v.pyop_field('in_dict') | |
elif isinstance(v, HeapTypeObjectPtr): | |
return v.get_attr_dict() | |
else: | |
return {} | |
parent = None | |
fields = name.split('.') | |
for name in fields: | |
if parent is None: | |
pyop_var, scope = pyop_frame.get_var_by_name(name) | |
else: | |
for k, pyop_var in get_var_dict(parent).iteritems(): | |
if str(k) == name: | |
break | |
else: | |
print "Can't find field %s of %s" % (name, parent) | |
return | |
parent = pyop_var | |
if pyop_var: | |
print ('%s %r = %s' | |
% (scope, | |
name, | |
pyop_var.get_truncated_repr(MAX_OUTPUT_LEN))) | |
else: | |
print '%r not found' % name | |
PyPrintFields() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment