1
0
Fork 0
forked from nuttx/nuttx-update

memdump: Enhance memdump

The method of passing in parameters to memdump is modified and the
incoming address is added. After traversing the node to which the
address belongs, the memdump command will end.

Signed-off-by: wangmingrong <wangmingrong@xiaomi.com>
This commit is contained in:
wangmingrong 2024-02-27 16:26:30 +08:00 committed by Xiang Xiao
parent ac7433eb5a
commit 52a349ab13

View file

@ -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()