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
 

Reply via email to