This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit f849092ede7ffb3231e62ff48c9be8db68e5c1bb Author: xuxingliang <xuxingli...@xiaomi.com> AuthorDate: Thu Nov 21 20:34:03 2024 +0800 gdb/memdump: add option to parse memdump log from device igned-off-by: xuxingliang <xuxingli...@xiaomi.com> --- tools/gdb/nuttxgdb/memdump.py | 96 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 10 deletions(-) diff --git a/tools/gdb/nuttxgdb/memdump.py b/tools/gdb/nuttxgdb/memdump.py index 823f7b600f..aac6f39994 100644 --- a/tools/gdb/nuttxgdb/memdump.py +++ b/tools/gdb/nuttxgdb/memdump.py @@ -21,6 +21,7 @@ ############################################################################ import argparse +import re from collections import defaultdict from typing import Dict, Generator, List, Protocol, Tuple @@ -75,7 +76,7 @@ def dump_nodes( filters=None, ) -> Generator[MMNodeDump, None, None]: no_heap = filters and filters.get("no_heap") - no_pool = filters and filters.get("no_heap") + no_pool = filters and filters.get("no_pool") if not no_heap: yield from ( @@ -150,6 +151,64 @@ def get_heaps(args_heap=None) -> List[mm.MMHeap]: return mm.get_heaps() +def parse_memdump_log(logfile, filters=None) -> Generator[MMNodeDump, None, None]: + nodes = [] + + class DumpNode(MMNodeDump): + def __init__(self, address, nodesize, seqno, pid, backtrace, is_free, overhead): + # C code dump the start address of the node, convert it the actual start address + self.address = address - overhead + self.nodesize = nodesize + self.seqno = seqno + self.pid = pid + self.backtrace = backtrace + self.overhead = overhead + self.is_free = False + self.from_pool = False + + def __repr__(self) -> str: + return f"node@{self.address:#x}: size:{self.nodesize} seq:{self.seqno} pid:{self.pid} " + + def contains(self, addr: int) -> bool: + return self.address <= addr < self.address + self.nodesize + + @property + def prevnode(self): + return next( + (node for node in nodes if node.contains(self.address - 1)), None + ) + + @property + def nextnode(self): + address = self.address + self.nodesize # address of the next node + return next( + (node for node in nodes if node.address == address), + None, + ) + + with open(logfile) as f: + for line in f: + match = re.search( + r"\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+((?:\s+0x[0-9a-fA-F]+)+)", line + ) + if not match: + continue + + try: + pid = int(match.group(1)) + size = int(match.group(2)) + overhead = int(match.group(3)) + seq = int(match.group(4)) + addresses = match.group(5).split() + addr = int(addresses[0], base=16) + mem = tuple(int(addr, base=16) for addr in addresses[1:]) + nodes.append(DumpNode(addr, size, seq, pid, mem, False, overhead)) + except Exception as e: + print(f"Error parsing line: {line}, {e}") + + return filter(filter_node(**filters), nodes) if filters else nodes + + class MMDump(gdb.Command): """Dump memory manager heap""" @@ -168,6 +227,14 @@ class MMDump(gdb.Command): help="Find the node that contains the address and exit", ) + parser.add_argument( + "-l", + "--log", + type=str, + default=None, + help="Use the memdump log file generated by memdump command on device instead of live dump", + ) + parser.add_argument( "--heap", type=str, @@ -237,21 +304,30 @@ class MMDump(gdb.Command): def find_address(self, addr, heap=None, log=None): """Find the node that contains the address from memdump log or live dump.""" addr = int(gdb.parse_and_eval(addr)) - heaps = [mm.MMHeap(gdb.parse_and_eval(heap))] if heap else mm.get_heaps() + if log: + nodes = parse_memdump_log(log) + node = next((node for node in nodes if node.contains(addr)), None) + else: + heaps = [mm.MMHeap(gdb.parse_and_eval(heap))] if heap else mm.get_heaps() - # Find pool firstly - node = next( - (blk for pool in mm.get_pools(heaps) if (blk := pool.find(addr))), None - ) + # Find pool firstly + node = next( + (blk for pool in mm.get_pools(heaps) if (blk := pool.find(addr))), None + ) - # Try heap if not found in pool - node = node or next((node for heap in heaps if (node := heap.find(addr))), None) + # Try heap if not found in pool + node = node or next( + (node for heap in heaps if (node := heap.find(addr))), None + ) return addr, node def collect_nodes(self, heap, log=None, filters=None): - heaps = [mm.MMHeap(gdb.parse_and_eval(heap))] if heap else mm.get_heaps() - nodes = dump_nodes(heaps, filters) + if log: + nodes = parse_memdump_log(log, filters=filters) + else: + heaps = [mm.MMHeap(gdb.parse_and_eval(heap))] if heap else mm.get_heaps() + nodes = dump_nodes(heaps, filters) return nodes