mirror of
https://github.com/apache/nuttx.git
synced 2026-05-22 22:20:01 +08:00
gdb/mmleak: add diagnose API to report details of the leak
Example of json dump:
{
"title": "Memory Leak Report",
"summary": "Total 105 blks, 22768 bytes leaked",
"result": "fail",
"command": "mm leak",
"data": [
{
"count": 1,
"pid": 0,
"size": 48,
"address": 1100447608,
"seqno": 0,
"alive": true,
"backtrace": []
},
{
"count": 1,
"pid": 4,
"size": 368,
"address": 1100549056,
"seqno": 1041,
"alive": false,
"backtrace": [
{
"address": 1076428472,
"function": "<mm_zalloc+8>",
"source": "mm_heap/mm_zalloc.c:45"
},
{
"address": 1076424018,
"function": "<mm_calloc+18>",
"source": "mm_heap/mm_calloc.c:57"
},
{
"address": 1076419750,
"function": "<calloc+22>",
"source": "umm_heap/umm_calloc.c:73"
},
....
]
},
}
Signed-off-by: xuxingliang <xuxingliang@xiaomi.com>
This commit is contained in:
@@ -22,7 +22,7 @@ import bisect
|
||||
import json
|
||||
import time
|
||||
from os import path
|
||||
from typing import Dict, Generator, List
|
||||
from typing import Dict, Generator, List, Tuple
|
||||
|
||||
import gdb
|
||||
|
||||
@@ -100,13 +100,9 @@ class MMLeak(gdb.Command):
|
||||
|
||||
return nodes
|
||||
|
||||
def invoke(self, arg: str, from_tty: bool) -> None:
|
||||
heaps = memdump.get_heaps("g_mmheap")
|
||||
pids = [int(tcb["pid"]) for tcb in utils.get_tcbs()]
|
||||
|
||||
def is_pid_alive(pid):
|
||||
return pid in pids
|
||||
|
||||
def collect_leaks(
|
||||
self, heaps: List[mm.MMHeap]
|
||||
) -> Dict[memdump.MMNodeDump, List[memdump.MMNodeDump]]:
|
||||
t = time.time()
|
||||
print("Loading globals from elf...", flush=True, end="")
|
||||
good_nodes = self.global_nodes() # Global memory are all good.
|
||||
@@ -155,15 +151,67 @@ class MMLeak(gdb.Command):
|
||||
|
||||
print(f" {time.time() - t:.2f}s", flush=True, end="\n")
|
||||
|
||||
leak_nodes = memdump.group_nodes(nodes_dict[addr] for addr in sorted_addr)
|
||||
return memdump.group_nodes((nodes_dict[addr] for addr in sorted_addr))
|
||||
|
||||
def _iterate_leaks(
|
||||
self, nodes: Dict[memdump.MMNodeDump, List[memdump.MMNodeDump]]
|
||||
) -> Generator[Tuple[memdump.MMNodeDump, bool, int], None, None]:
|
||||
pids = [int(tcb["pid"]) for tcb in utils.get_tcbs()]
|
||||
|
||||
def is_pid_alive(pid):
|
||||
return pid in pids
|
||||
|
||||
for node in nodes.keys():
|
||||
count = len(nodes[node])
|
||||
yield node, is_pid_alive(node.pid), count
|
||||
|
||||
def invoke(self, arg: str, from_tty: bool) -> None:
|
||||
heaps = memdump.get_heaps("g_mmheap")
|
||||
|
||||
leak_nodes = self.collect_leaks(heaps)
|
||||
memdump.print_header()
|
||||
total_blk = total_size = 0
|
||||
for node in leak_nodes.keys():
|
||||
count = len(leak_nodes[node])
|
||||
for node, alive, count in self._iterate_leaks(leak_nodes):
|
||||
total_blk += count
|
||||
total_size += count * node.nodesize
|
||||
memdump.print_node(
|
||||
node, is_pid_alive(node.pid), count=len(leak_nodes[node])
|
||||
)
|
||||
memdump.print_node(node, alive, count=count)
|
||||
|
||||
print(f"Leaked {total_blk} blks, {total_size} bytes")
|
||||
|
||||
def diagnose(self, *args, **kwargs):
|
||||
heaps = memdump.get_heaps("g_mmheap")
|
||||
leak_nodes = self.collect_leaks(heaps)
|
||||
total_blk = total_size = 0
|
||||
data = []
|
||||
for node, alive, count in self._iterate_leaks(leak_nodes):
|
||||
total_blk += count
|
||||
total_size += count * node.nodesize
|
||||
info = {
|
||||
"count": count,
|
||||
"pid": node.pid,
|
||||
"size": node.nodesize,
|
||||
"address": node.address,
|
||||
"seqno": node.seqno,
|
||||
"alive": alive,
|
||||
"backtrace": [],
|
||||
}
|
||||
|
||||
if mm.CONFIG_MM_BACKTRACE and node.backtrace and node.backtrace[0]:
|
||||
bt = utils.Backtrace(node.backtrace)
|
||||
info["backtrace"] = [
|
||||
{
|
||||
"address": addr,
|
||||
"function": func,
|
||||
"source": source,
|
||||
}
|
||||
for addr, func, source in bt.backtrace
|
||||
]
|
||||
data.append(info)
|
||||
|
||||
return {
|
||||
"title": "Memory Leak Report",
|
||||
"summary": f"Total {total_blk} blks, {total_size} bytes leaked",
|
||||
"result": "fail" if total_blk else "pass",
|
||||
"command": "mm leak",
|
||||
"data": data,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user