@@ -241,12 +241,13 @@ def is_optimized_out(self):
241
241
242
242
def safe_tp_name (self ):
243
243
try :
244
- return self .type ().field ('tp_name' ).string ()
245
- except NullPyObjectPtr :
246
- # NULL tp_name?
247
- return 'unknown'
248
- except RuntimeError :
249
- # Can't even read the object at all?
244
+ ob_type = self .type ()
245
+ tp_name = ob_type .field ('tp_name' )
246
+ return tp_name .string ()
247
+ # NullPyObjectPtr: NULL tp_name?
248
+ # RuntimeError: Can't even read the object at all?
249
+ # UnicodeDecodeError: Failed to decode tp_name bytestring
250
+ except (NullPyObjectPtr , RuntimeError , UnicodeDecodeError ):
250
251
return 'unknown'
251
252
252
253
def proxyval (self , visited ):
@@ -320,7 +321,9 @@ def subclass_from_type(cls, t):
320
321
try :
321
322
tp_name = t .field ('tp_name' ).string ()
322
323
tp_flags = int (t .field ('tp_flags' ))
323
- except RuntimeError :
324
+ # RuntimeError: NULL pointers
325
+ # UnicodeDecodeError: string() fails to decode the bytestring
326
+ except (RuntimeError , UnicodeDecodeError ):
324
327
# Handle any kind of error e.g. NULL ptrs by simply using the base
325
328
# class
326
329
return cls
@@ -336,6 +339,7 @@ def subclass_from_type(cls, t):
336
339
'set' : PySetObjectPtr ,
337
340
'frozenset' : PySetObjectPtr ,
338
341
'builtin_function_or_method' : PyCFunctionObjectPtr ,
342
+ 'method-wrapper' : wrapperobject ,
339
343
}
340
344
if tp_name in name_map :
341
345
return name_map [tp_name ]
@@ -602,7 +606,10 @@ class PyCFunctionObjectPtr(PyObjectPtr):
602
606
603
607
def proxyval (self , visited ):
604
608
m_ml = self .field ('m_ml' ) # m_ml is a (PyMethodDef*)
605
- ml_name = m_ml ['ml_name' ].string ()
609
+ try :
610
+ ml_name = m_ml ['ml_name' ].string ()
611
+ except UnicodeDecodeError :
612
+ ml_name = '<ml_name:UnicodeDecodeError>'
606
613
607
614
pyop_m_self = self .pyop_field ('m_self' )
608
615
if pyop_m_self .is_null ():
@@ -1131,7 +1138,9 @@ def proxyval(self, visited):
1131
1138
# Convert the int code points to unicode characters, and generate a
1132
1139
# local unicode instance.
1133
1140
# This splits surrogate pairs if sizeof(Py_UNICODE) is 2 here (in gdb).
1134
- result = u'' .join ([_unichr (ucs ) for ucs in Py_UNICODEs ])
1141
+ result = u'' .join ([
1142
+ (_unichr (ucs ) if ucs <= 0x10ffff else '\ufffd ' )
1143
+ for ucs in Py_UNICODEs ])
1135
1144
return result
1136
1145
1137
1146
def write_repr (self , out , visited ):
@@ -1144,6 +1153,41 @@ def write_repr(self, out, visited):
1144
1153
out .write (val .lstrip ('u' ))
1145
1154
1146
1155
1156
+ class wrapperobject (PyObjectPtr ):
1157
+ _typename = 'wrapperobject'
1158
+
1159
+ def safe_name (self ):
1160
+ try :
1161
+ name = self .field ('descr' )['d_base' ]['name' ].string ()
1162
+ return repr (name )
1163
+ except (NullPyObjectPtr , RuntimeError , UnicodeDecodeError ):
1164
+ return '<unknown name>'
1165
+
1166
+ def safe_tp_name (self ):
1167
+ try :
1168
+ return self .field ('self' )['ob_type' ]['tp_name' ].string ()
1169
+ except (NullPyObjectPtr , RuntimeError , UnicodeDecodeError ):
1170
+ return '<unknown tp_name>'
1171
+
1172
+ def safe_self_addresss (self ):
1173
+ try :
1174
+ address = long (self .field ('self' ))
1175
+ return '%#x' % address
1176
+ except (NullPyObjectPtr , RuntimeError ):
1177
+ return '<failed to get self address>'
1178
+
1179
+ def proxyval (self , visited ):
1180
+ name = self .safe_name ()
1181
+ tp_name = self .safe_tp_name ()
1182
+ self_address = self .safe_self_addresss ()
1183
+ return ("<method-wrapper %s of %s object at %s>"
1184
+ % (name , tp_name , self_address ))
1185
+
1186
+ def write_repr (self , out , visited ):
1187
+ proxy = self .proxyval (visited )
1188
+ out .write (proxy )
1189
+
1190
+
1147
1191
def int_from_int (gdbval ):
1148
1192
return int (str (gdbval ))
1149
1193
@@ -1176,11 +1220,13 @@ def to_string (self):
1176
1220
1177
1221
def pretty_printer_lookup (gdbval ):
1178
1222
type = gdbval .type .unqualified ()
1179
- if type .code == gdb .TYPE_CODE_PTR :
1180
- type = type .target ().unqualified ()
1181
- t = str (type )
1182
- if t in ("PyObject" , "PyFrameObject" ):
1183
- return PyObjectPtrPrinter (gdbval )
1223
+ if type .code != gdb .TYPE_CODE_PTR :
1224
+ return None
1225
+
1226
+ type = type .target ().unqualified ()
1227
+ t = str (type )
1228
+ if t in ("PyObject" , "PyFrameObject" , "PyUnicodeObject" , "wrapperobject" ):
1229
+ return PyObjectPtrPrinter (gdbval )
1184
1230
1185
1231
"""
1186
1232
During development, I've been manually invoking the code in this way:
@@ -1202,7 +1248,7 @@ def pretty_printer_lookup(gdbval):
1202
1248
/usr/lib/debug/usr/lib/libpython2.6.so.1.0.debug-gdb.py
1203
1249
"""
1204
1250
def register (obj ):
1205
- if obj == None :
1251
+ if obj is None :
1206
1252
obj = gdb
1207
1253
1208
1254
# Wire up the pretty-printer
@@ -1304,23 +1350,43 @@ def is_other_python_frame(self):
1304
1350
'''
1305
1351
if self .is_waiting_for_gil ():
1306
1352
return 'Waiting for the GIL'
1307
- elif self .is_gc_collect ():
1353
+
1354
+ if self .is_gc_collect ():
1308
1355
return 'Garbage-collecting'
1309
- else :
1310
- # Detect invocations of PyCFunction instances:
1311
- older = self .older ()
1312
- if older and older ._gdbframe .name () == 'PyCFunction_Call' :
1313
- # Within that frame:
1314
- # "func" is the local containing the PyObject* of the
1315
- # PyCFunctionObject instance
1316
- # "f" is the same value, but cast to (PyCFunctionObject*)
1317
- # "self" is the (PyObject*) of the 'self'
1318
- try :
1319
- # Use the prettyprinter for the func:
1320
- func = older ._gdbframe .read_var ('func' )
1321
- return str (func )
1322
- except RuntimeError :
1323
- return 'PyCFunction invocation (unable to read "func")'
1356
+
1357
+ # Detect invocations of PyCFunction instances:
1358
+ frame = self ._gdbframe
1359
+ caller = frame .name ()
1360
+ if not caller :
1361
+ return False
1362
+
1363
+ if caller == 'PyCFunction_Call' :
1364
+ arg_name = 'func'
1365
+ # Within that frame:
1366
+ # "func" is the local containing the PyObject* of the
1367
+ # PyCFunctionObject instance
1368
+ # "f" is the same value, but cast to (PyCFunctionObject*)
1369
+ # "self" is the (PyObject*) of the 'self'
1370
+ try :
1371
+ # Use the prettyprinter for the func:
1372
+ func = frame .read_var (arg_name )
1373
+ return str (func )
1374
+ except ValueError :
1375
+ return ('PyCFunction invocation (unable to read %s: '
1376
+ 'missing debuginfos?)' % arg_name )
1377
+ except RuntimeError :
1378
+ return 'PyCFunction invocation (unable to read %s)' % arg_name
1379
+
1380
+ if caller == 'wrapper_call' :
1381
+ arg_name = 'wp'
1382
+ try :
1383
+ func = frame .read_var (arg_name )
1384
+ return str (func )
1385
+ except ValueError :
1386
+ return ('<wrapper_call invocation (unable to read %s: '
1387
+ 'missing debuginfos?)>' % arg_name )
1388
+ except RuntimeError :
1389
+ return '<wrapper_call invocation (unable to read %s)>' % arg_name
1324
1390
1325
1391
# This frame isn't worth reporting:
1326
1392
return False
@@ -1368,7 +1434,11 @@ def get_selected_frame(cls):
1368
1434
def get_selected_python_frame (cls ):
1369
1435
'''Try to obtain the Frame for the python-related code in the selected
1370
1436
frame, or None'''
1371
- frame = cls .get_selected_frame ()
1437
+ try :
1438
+ frame = cls .get_selected_frame ()
1439
+ except gdb .error :
1440
+ # No frame: Python didn't start yet
1441
+ return None
1372
1442
1373
1443
while frame :
1374
1444
if frame .is_python_frame ():
@@ -1509,6 +1579,10 @@ def invoke(self, args, from_tty):
1509
1579
def move_in_stack (move_up ):
1510
1580
'''Move up or down the stack (for the py-up/py-down command)'''
1511
1581
frame = Frame .get_selected_python_frame ()
1582
+ if not frame :
1583
+ print ('Unable to locate python frame' )
1584
+ return
1585
+
1512
1586
while frame :
1513
1587
if move_up :
1514
1588
iter_frame = frame .older ()
@@ -1571,6 +1645,10 @@ def __init__(self):
1571
1645
1572
1646
def invoke (self , args , from_tty ):
1573
1647
frame = Frame .get_selected_python_frame ()
1648
+ if not frame :
1649
+ print ('Unable to locate python frame' )
1650
+ return
1651
+
1574
1652
while frame :
1575
1653
if frame .is_python_frame ():
1576
1654
frame .print_summary ()
@@ -1588,8 +1666,12 @@ def __init__(self):
1588
1666
1589
1667
1590
1668
def invoke (self , args , from_tty ):
1591
- sys .stdout .write ('Traceback (most recent call first):\n ' )
1592
1669
frame = Frame .get_selected_python_frame ()
1670
+ if not frame :
1671
+ print ('Unable to locate python frame' )
1672
+ return
1673
+
1674
+ sys .stdout .write ('Traceback (most recent call first):\n ' )
1593
1675
while frame :
1594
1676
if frame .is_python_frame ():
1595
1677
frame .print_traceback ()
0 commit comments