From 220597a88153338589ae80a008c11834e37433e7 Mon Sep 17 00:00:00 2001 From: Mathieu Maret Date: Thu, 19 Aug 2021 16:42:44 +0200 Subject: [PATCH] gdb: add custom cmd for printing linked list --- custom_gdb_extension.py | 86 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/custom_gdb_extension.py b/custom_gdb_extension.py index 3af1f4c..5ce128e 100644 --- a/custom_gdb_extension.py +++ b/custom_gdb_extension.py @@ -136,6 +136,92 @@ class PhyMemDescListDumpCmd(gdb.Command): print(self._phy_memDesc_lit_to_str(desc)) +class PrintStructC99Cmd(gdb.Command): + def __init__(self): + super(PrintStructC99Cmd, self).__init__( + "print_struct_c99", + gdb.COMMAND_USER, + ) + + def complete(self, text, word): + return gdb.COMPLETE_SYMBOL + + def get_count_heading(self, string): + for i, s in enumerate(string): + if s != ' ': + break + return i + + def extract_typename(self, string): + first_line = string.split('\n')[0] + return first_line.split('=')[1][:-1].strip() + + def invoke(self, arg, from_tty): + gdb.execute("set print pretty") + gdb.execute('set pagination off') + gdb.execute('set print repeats 0') + gdb.execute('set print elements unlimited') + ret_ptype = gdb.execute('ptype {}'.format(arg), to_string=True) + tname = self.extract_typename(ret_ptype) + print('{} {} = {{'.format(tname, arg)) + r = gdb.execute('p {}'.format(arg), to_string=True) + r = r.split('\n') + for rr in r[1:]: + if '=' not in rr: + print(rr) + continue + hs = self.get_count_heading(rr) + rr_s = rr.strip().split('=', 1) + rr_rval = rr_s[1].strip() + print(' ' * hs + '.' + rr_s[0] + '= ' + rr_rval) + +class ListDumpCmd(gdb.Command): + """Prints a linked list""" + + def __init__(self): + super(ListDumpCmd, self).__init__( + "list_dump", gdb.COMMAND_USER + ) + + def _print_list(self, val): + """Walk through the linked list. + + We will simply follow the 'next' pointers until we encounter the HEAD again + """ + idx = 0 + head = val + kthread_ptr = val + result = "" + while kthread_ptr != 0 and (idx == 0 or kthread_ptr != head): + result += gdb.execute('p *({}){}'.format(str(kthread_ptr.type),kthread_ptr), to_string=True) + kthread_ptr = kthread_ptr["next"] + idx += 1 + result = ("Found a Linked List with %d items:" % idx) + "\n"+ result + return result + + def complete(self, text, word): + # We expect the argument passed to be a symbol so fallback to the + # internal tab-completion handler for symbols + return gdb.COMPLETE_SYMBOL + + def invoke(self, args, from_tty): + # We can pass args here and use Python CLI utilities like argparse + # to do argument parsing + print("Args Passed: %s" % args) + if args: + ptr_val = gdb.parse_and_eval(args) + else: + ptr_val = gdb.parse_and_eval("currentThread") + try: + ptr_val["next"] + except: + print("Expected pointer argument with a next field") + return + + print(self._print_list(ptr_val)) + register_pretty_printer(None, CustomPrettyPrinterLocator(), replace=True) KthreadListDumpCmd() PhyMemDescListDumpCmd() +PrintStructC99Cmd() +ListDumpCmd()