gdb: add custom cmd for printing linked list
This commit is contained in:
parent
31aaf10635
commit
220597a881
@ -136,6 +136,92 @@ class PhyMemDescListDumpCmd(gdb.Command):
|
|||||||
print(self._phy_memDesc_lit_to_str(desc))
|
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)
|
register_pretty_printer(None, CustomPrettyPrinterLocator(), replace=True)
|
||||||
KthreadListDumpCmd()
|
KthreadListDumpCmd()
|
||||||
PhyMemDescListDumpCmd()
|
PhyMemDescListDumpCmd()
|
||||||
|
PrintStructC99Cmd()
|
||||||
|
ListDumpCmd()
|
||||||
|
Loading…
Reference in New Issue
Block a user