diff --git a/tools/gdb/memdump.py b/tools/gdb/memdump.py index a53e20831f..5f0d1cc3f9 100644 --- a/tools/gdb/memdump.py +++ b/tools/gdb/memdump.py @@ -18,6 +18,8 @@ # ############################################################################ +import argparse + import gdb import utils from lists import list_for_each_entry, sq_for_every, sq_queue @@ -35,6 +37,11 @@ PID_MM_LEAK = -2 PID_MM_MEMPOOL = -1 +def mm_nodesize(size) -> int: + """Return the real size of a memory node""" + return size & ~MM_MASK_BIT + + def mm_foreach(heap): """Iterate over a heap, yielding each node""" node = gdb.Value(heap["mm_heapstart"][0]).cast( @@ -43,7 +50,7 @@ def mm_foreach(heap): while 1: yield node next = gdb.Value(node).cast(gdb.lookup_type("char").pointer()) - next = gdb.Value(next + (node["size"] & ~MM_MASK_BIT)).cast( + next = gdb.Value(next + mm_nodesize(node["size"])).cast( gdb.lookup_type("struct mm_allocnode_s").pointer() ) if node >= heap["mm_heapend"].dereference() or next == node: @@ -66,7 +73,7 @@ class Nxmemdump(gdb.Command): def __init__(self): super(Nxmemdump, self).__init__("memdump", gdb.COMMAND_USER) - def mempool_dump(self, mpool, pid, seqmin, seqmax): + def mempool_dump(self, mpool, pid, seqmin, seqmax, address): """Dump the mempool memory""" for pool in mempool_multiple_foreach(mpool): if pid == PID_MM_FREE: @@ -95,7 +102,7 @@ class Nxmemdump(gdb.Command): "%6d%12u%12u%#*x" % ( node["pid"], - pool["blocksize"] & ~MM_MASK_BIT, + mm_nodesize(pool["blocksize"]), node["seqno"], self.align, (int)(charnode - pool["blocksize"]), @@ -111,11 +118,23 @@ class Nxmemdump(gdb.Command): ) ) + if address and ( + address < int(charnode) + and address >= (int)(charnode - pool["blocksize"]) + ): + gdb.write( + "\nThe address 0x%x found belongs to" + "the mempool node with base address 0x%x\n" + % (address, charnode) + ) + return True + gdb.write("\n") self.aordblks += 1 self.uordblks += pool["blocksize"] + return False - def memdump(self, pid, seqmin, seqmax): + def memdump(self, pid, seqmin, seqmax, address): """Dump the heap memory""" if pid >= PID_MM_ALLOC: gdb.write("Dump all used memory node info:\n") @@ -129,7 +148,8 @@ class Nxmemdump(gdb.Command): heap = gdb.parse_and_eval("g_mmheap") if heap.type.has_key("mm_mpool"): - self.mempool_dump(heap["mm_mpool"], pid, seqmin, seqmax) + if self.mempool_dump(heap["mm_mpool"], pid, seqmin, seqmax, address): + return for node in mm_foreach(heap): if node["size"] & MM_ALLOC_BIT != 0: @@ -142,7 +162,7 @@ class Nxmemdump(gdb.Command): "%6d%12u%12u%#*x" % ( node["pid"], - node["size"] & ~MM_MASK_BIT, + mm_nodesize(node["size"]), node["seqno"], self.align, (int)( @@ -164,15 +184,29 @@ class Nxmemdump(gdb.Command): gdb.write("\n") + if address and ( + address < int(charnode + node["size"]) + and address + >= (int)( + charnode + gdb.lookup_type("struct mm_allocnode_s").sizeof + ) + ): + gdb.write( + "\nThe address 0x%x found belongs to" + "the memory node with base address 0x%x\n" + % (address, charnode) + ) + return + self.aordblks += 1 - self.uordblks += node["size"] & ~MM_MASK_BIT + self.uordblks += mm_nodesize(node["size"]) else: if pid == PID_MM_FREE: charnode = gdb.Value(node).cast(gdb.lookup_type("char").pointer()) gdb.write( "%12u%#*x\n" % ( - node["size"] & ~MM_MASK_BIT, + mm_nodesize(node["size"]), self.align, (int)( charnode @@ -181,7 +215,7 @@ class Nxmemdump(gdb.Command): ) ) self.aordblks += 1 - self.uordblks += node["size"] & ~MM_MASK_BIT + self.uordblks += mm_nodesize(node["size"]) gdb.write("%12s%12s\n" % ("Total Blks", "Total Size")) gdb.write("%12d%12d\n" % (self.aordblks, self.uordblks)) @@ -189,36 +223,43 @@ class Nxmemdump(gdb.Command): def complete(self, text, word): return gdb.COMPLETE_SYMBOL + def parse_arguments(self, argv): + parser = argparse.ArgumentParser(description="memdump command") + parser.add_argument("-p", "--pid", type=str, help="Thread PID") + parser.add_argument("-a", "--addr", type=str, help="Query memory address") + parser.add_argument("-i", "--min", type=str, help="Minimum value") + parser.add_argument("-x", "--max", type=str, help="Maximum value") + parser.add_argument("--used", action="store_true", help="Used flag") + parser.add_argument("--free", action="store_true", help="Free flag") + args = parser.parse_args(args=(None if len(argv) == 1 else argv)) + return { + "pid": int(args.pid, 0) if args.pid else None, + "seqmin": int(args.min, 0) if args.min else 0, + "seqmax": int(args.max, 0) if args.max else 0xFFFFFFFF, + "used": args.used, + "free": args.free, + "addr": int(args.addr, 0) if args.addr else None, + } + def invoke(self, args, from_tty): if gdb.lookup_type("size_t").sizeof == 4: self.align = 11 else: self.align = 19 - arg = args.split(" ") + arg = self.parse_arguments(args.split(" ")) - if arg[0] == "": + pid = PID_MM_ALLOC + if arg["used"]: pid = PID_MM_ALLOC - elif arg[0] == "used": - pid = PID_MM_ALLOC - elif arg[0] == "free": + elif arg["free"]: pid = PID_MM_LEAK - else: - pid = int(arg[0]) - - if len(arg) == 2: - seqmin = int(arg[1]) - else: - seqmin = 0 - - if len(arg) == 3: - seqmax = int(arg[2]) - else: - seqmax = 0xFFFFFFFF + elif arg["pid"]: + pid = arg["pid"] self.aordblks = 0 self.uordblks = 0 - self.memdump(pid, seqmin, seqmax) + self.memdump(pid, arg["seqmin"], arg["seqmax"], arg["addr"]) Nxmemdump()