mirror of
https://github.com/apache/nuttx.git
synced 2026-08-08 14:07:17 +00:00
gdb/memdump: add option to parse memdump log from device
igned-off-by: xuxingliang <xuxingliang@xiaomi.com>
This commit is contained in:
parent
06a696076a
commit
f849092ede
1 changed files with 86 additions and 10 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue