# adapted some code from https://github.com/python/cpython/blob/2.7/Tools/gdb/libpython.py class PyBtLinked(gdb.Command): def __init__(self): gdb.Command.__init__ (self, "py-bt-linked", gdb.COMMAND_STACK, gdb.COMPLETE_NONE) def invoke(self, args, from_tty): try: print('Traceback (most recent call first):') def p_stack(filename, lineno, funcname): print(' File "{}", line {}, in {}'.format( filename if filename is not None else '', lineno, funcname)) if filename is not None: import os try: cwd = os.readlink('/proc/{}/cwd'.format(gdb.selected_inferior().pid)) except IOError: pass else: filename = os.path.join(cwd, filename) try: file = open(filename, 'rb') except IOError: print(' '.format(filename)) else: with file: print(' ' + file.read().split(b'\n')[int(lineno)-1] .decode('utf-8').strip()) def pystr(pystrptr): assert pystrptr['ob_type']['tp_name'].string() == 'str' pystrptr = pystrptr.cast(gdb.lookup_type('PyStringObject').pointer()) field_ob_size = int(pystrptr['ob_size']) field_ob_sval = pystrptr['ob_sval'] return ''.join(chr(field_ob_sval[i]) for i in range(field_ob_size)) def addr2line(code, addrq): co_lnotab = pystr(code['co_lnotab']) lineno = int(code['co_firstlineno']) addr = 0 for addr_incr, line_incr in zip(co_lnotab[::2], co_lnotab[1::2]): addr += ord(addr_incr) if addr > addrq: return lineno lineno += ord(line_incr) return lineno filename, lineno = None, '?' frame = None gdbframe = gdb.newest_frame() while not frame: gdbframe = gdbframe.older() regs = ['rax', 'rbx', 'rcx', 'rdx', 'rsi', 'rdi', 'rbp', 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15'] for reg in regs: r = gdbframe.read_register(reg) try: r = r.cast(gdb.lookup_type('PyFrameObject').pointer()) if r['ob_type']['tp_name'].string() == 'frame': frame = r except Exception: continue while frame: code = frame['f_code'] filename = pystr(code['co_filename']) lineno = addr2line(code, int(frame['f_lasti'])) funcname = pystr(code['co_name']) p_stack(filename, lineno, funcname) frame = frame['f_back'] except Exception: import traceback traceback.print_exc() PyBtLinked()