From patchwork Sat Jan 3 01:18:52 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1210 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767403225; bh=Nq1isjIJobKlOGekEtvdfbNh4ovJWyLsqmd9vTCWd6U=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=EWQX2RA5i6G60X3POq3PbZgG3bYHVMdobtvFdGxykXSI953i07qq/1io6WTdH4uQ6 Nb05pDwMB7sZBTxF9jU8uwCebMYNwhXCfc3estRTloii7/HxvMyXpI1UBEoUmlecDb y9NJesi0jTGT0zGXuj3hgtmiRFk0CFvE9rhep8+K8kC2HfgsB1hsRZbIa+F63nVOPz o6H9x398lh0nmjyW70MM+qVsRRsS6DY2yv47xLXUCL82AUuGBP+zVzAbs9YFV8HvHB kGL+bCBI3UmQU+8MdMv3nEdO2iAtjsdSV2C/eJKbmRx6CatFovNIf2sS21BJ+diy/R W3waaVUJJAFdw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id C206669060 for ; Fri, 2 Jan 2026 18:20:25 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id K-GZ5ogHWQ30 for ; Fri, 2 Jan 2026 18:20:25 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767403223; bh=Nq1isjIJobKlOGekEtvdfbNh4ovJWyLsqmd9vTCWd6U=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=KBL3xg23tl+SZzMg0FseoPoR2X/NawhQtQTOsPqA4Ku0lSVeBLqIrTRXk0xRiXB9s xsDV6wb2/JNRODsLyXDII+36y/FAOKqtfpJwFkbukCTzhR45T4lEvFs4Hj/1tWUuIO /RggoRGSxLN+dRrJH+bkmDxXIPbBysNjt/OC5G5vxUH2eNGPsmSKOThM5QV5tC6Ibp 8mj0wi90/L4fm/uiOojmTTPk5/dABnGQ9up6QS/tqtETxCOQlqlKMISM0/QOCBwSj+ nHog6kJMipyv/7Tq/s/oAvzw0tTbw4VTbpzmMynm3WD+xyFUK/xF4y6vGtwHjyIMDe GFgqRXfVycYwg== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id B9C9368F8A for ; Fri, 2 Jan 2026 18:20:23 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767403220; bh=efrJPHlOS3zUYoCR4UKeiJjefdN3ajNjkr4ABufB4fI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=d2lqfzH8UTpaVdghNnD4l0bqzRrqnloemMqU1MCi02/1OwuRbK9FVsnbQ4Vst5FZB VTEoabmau3gg0dz5Jq6GrYm0UsXj0giH51f2UeMNN/cU/nPCGshQrwdnxDtOd9GNjb twqV/efL1sNX1pBysDaXiYEFE78bgJTlLGhuTTYLTu0w9c9mR/cAPyI5iKddhpBcXi 8QGeTna1WmWfk5qRcU+Fgur0z8KPac824ytQzsi81JivkCDLZU784ctNHmCU+T9MgP ESyu+g1egA+v9yU+buSvGsdfW3VBpv151z3Fh8PUwO2W57m6Fzn3EODzFNXT80pxuO 3KWtMJBspc5iQ== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id EA53D6904D; Fri, 2 Jan 2026 18:20:20 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id NaJkKlxMYDYu; Fri, 2 Jan 2026 18:20:20 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767403220; bh=TpG1pb+SMgwtS/fo/mXplpwcbPed0UkD0nMumx1MK4o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qjFQRltOfMZS/uaqeLEo01X1CFl/BxNQcsrrPUpyVHZoizrntnkihT5y91HDOMSlo BmvTwgAlX7kKoQMJoBDTwdx+rXlX30VUrVS4qGKwT8iJk5zKakbywSocewVnZJK3lH WxMpEhlc6iSGbfw7H5pOJjvMS1AVstRVEuD6Sx1QRWSwkUock8BI5zgu6N2x/Y/DuM JccrzDP3aHWkMdZJONARSuDkqTfdRTvNR5q135zNTtLFjf043HizZQ5NOzshaQZ7ee glRDxnVI0nf0VhX4GpMVv5ay9hrI9nXlY6eHcwirhfPG2Vp7f52RLlP1CIi6AMfXMe syyYtiVjBkDaQ== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 07A4868F87; Fri, 2 Jan 2026 18:20:19 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Fri, 2 Jan 2026 18:18:52 -0700 Message-ID: <20260103011908.149445-17-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260103011908.149445-1-sjg@u-boot.org> References: <20260103011908.149445-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: 5M2VDKMDXVBD5MCP54DYCRHLD7RBJDS6 X-Message-ID-Hash: 5M2VDKMDXVBD5MCP54DYCRHLD7RBJDS6 X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 16/24] cmd: malloc: Add a command to show the malloc log List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass Add a command interface for the malloc-traffic log: - malloc log start: Start recording allocations - malloc log stop: Stop recording - malloc log: Dump the recorded entries Example output: => malloc log Malloc log: 29 entries (max 524288, total 29) Seq Type Ptr Size Caller ---- -------- ---------------- -------- ------ 0 free 16a016e0 0 free_pipe_list:2001 <-parse_stream_outer:3208 <-parse_file_outer:3300 1 alloc 16a01b90 20 hush_file_init:3277 <-parse_file_outer:3295 <-run_pipe_real:1986 Co-developed-by: Claude Signed-off-by: Simon Glass --- cmd/Kconfig | 10 +++++++++ cmd/malloc.c | 41 ++++++++++++++++++++++++++++++++-- doc/develop/malloc.rst | 3 ++- doc/usage/cmd/malloc.rst | 30 ++++++++++++++++++++++++- test/cmd/malloc.c | 48 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 128 insertions(+), 4 deletions(-) diff --git a/cmd/Kconfig b/cmd/Kconfig index d602f430ab6..072ff879cd8 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -3049,6 +3049,16 @@ config CMD_MALLOC about memory allocation, such as total memory allocated and currently in use. +config CMD_MALLOC_LOG + bool "malloc log - Log malloc traffic" + depends on CMD_MALLOC && MCHECK_LOG + default y + help + This adds the 'malloc log' subcommand which records all + malloc/free/realloc calls with their addresses, sizes, and caller + information. Use 'malloc log start' to begin recording and + 'malloc log' to display the recorded entries. + config CMD_MOUSE bool "mouse - Show mouse input" default y if MOUSE diff --git a/cmd/malloc.c b/cmd/malloc.c index 9c7dfbfc0c3..361750c45dd 100644 --- a/cmd/malloc.c +++ b/cmd/malloc.c @@ -38,10 +38,47 @@ static int do_malloc_dump(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } +static int __maybe_unused do_malloc_log(struct cmd_tbl *cmdtp, int flag, + int argc, char *const argv[]) +{ + if (argc < 2) { + malloc_log_dump(); + return 0; + } + + if (!strcmp(argv[1], "start")) { + malloc_log_start(); + printf("Malloc logging started\n"); + } else if (!strcmp(argv[1], "stop")) { + malloc_log_stop(); + printf("Malloc logging stopped\n"); + } else if (!strcmp(argv[1], "dump")) { + malloc_log_dump(); + } else { + return CMD_RET_USAGE; + } + + return 0; +} + +#if CONFIG_IS_ENABLED(CMD_MALLOC_LOG) +#define MALLOC_LOG_HELP \ + "malloc log [start|stop|dump] - log malloc traffic\n" \ + " start - start recording malloc/free calls\n" \ + " stop - stop recording\n" \ + " dump - print the log (or just 'malloc log')\n" +#define MALLOC_LOG_SUBCMD , U_BOOT_SUBCMD_MKENT(log, 3, 1, do_malloc_log) +#else +#define MALLOC_LOG_HELP +#define MALLOC_LOG_SUBCMD +#endif + U_BOOT_LONGHELP(malloc, "info - display malloc statistics\n" - "malloc dump - dump heap chunks (address, size, status)\n"); + "malloc dump - dump heap chunks (address, size, status)\n" + MALLOC_LOG_HELP); U_BOOT_CMD_WITH_SUBCMDS(malloc, "malloc information", malloc_help_text, U_BOOT_SUBCMD_MKENT(info, 1, 1, do_malloc_info), - U_BOOT_SUBCMD_MKENT(dump, 1, 1, do_malloc_dump)); + U_BOOT_SUBCMD_MKENT(dump, 1, 1, do_malloc_dump) + MALLOC_LOG_SUBCMD); diff --git a/doc/develop/malloc.rst b/doc/develop/malloc.rst index 92180af055a..b9ab884d419 100644 --- a/doc/develop/malloc.rst +++ b/doc/develop/malloc.rst @@ -390,7 +390,8 @@ Malloc-Traffic Log On sandbox, when mcheck is enabled, a malloc-traffic log can record all malloc/free/realloc calls. This is useful for debugging allocation patterns -and finding where allocations without caller info originate. +and finding where allocations without caller info originate. See +:doc:`../usage/cmd/malloc` for usage. The log buffer is allocated from host memory using ``os_malloc()``, so it does not affect U-Boot's heap. The size is controlled by diff --git a/doc/usage/cmd/malloc.rst b/doc/usage/cmd/malloc.rst index 3693034b41e..03f0669658b 100644 --- a/doc/usage/cmd/malloc.rst +++ b/doc/usage/cmd/malloc.rst @@ -13,6 +13,7 @@ Synopsis malloc info malloc dump + malloc log [start|stop] Description ----------- @@ -31,6 +32,13 @@ dump for debugging memory allocation issues. When CONFIG_MCHECK_HEAP_PROTECTION is enabled, the caller string is also shown if available. +log + Controls the malloc traffic log. With no argument, dumps the recorded log + entries. Use ``start`` to begin recording malloc/free/realloc calls, and + ``stop`` to stop recording. Each entry shows the operation type, pointer + address, size, and caller backtrace. This is useful for tracking down + memory leaks or understanding allocation patterns. + The total heap size is set by ``CONFIG_SYS_MALLOC_LEN``. Example @@ -71,11 +79,31 @@ With CONFIG_MCHECK_HEAP_PROTECTION enabled, the caller backtrace is shown:: 18a3b840 90 used of_alias_scan:911 <-board_init_ ... +With CONFIG_CMD_MALLOC_LOG enabled, the log subcommand is available:: + + => malloc log start + Malloc logging started + => ... do some operations ... + => malloc log stop + Malloc logging stopped + => malloc log + Malloc log: 5 entries (max 524288, total 5) + Seq Type Ptr Size Caller + ---- -------- ---------------- -------- ------ + 0 alloc 16a01b90 20 hush_file_init:3277 + <-parse_file_outer:3295 <-run_pipe_real:1986 + 1 alloc 16a01bc0 100 xmalloc:107 <-xzalloc:117 + <-new_pipe:1498 <-run_list_real:1702 + 2 free 16a01bc0 0 free_pipe_list:2001 + <-parse_stream_outer:3208 <-parse_file_outer:3300 + ... + Configuration ------------- The malloc command is enabled by CONFIG_CMD_MALLOC which depends on -CONFIG_MALLOC_DEBUG. +CONFIG_MALLOC_DEBUG. The log subcommand is enabled by CONFIG_CMD_MALLOC_LOG +which additionally requires CONFIG_MCHECK_LOG. Return value ------------ diff --git a/test/cmd/malloc.c b/test/cmd/malloc.c index 3c1a44bcacf..75e8afdec63 100644 --- a/test/cmd/malloc.c +++ b/test/cmd/malloc.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -52,3 +53,50 @@ static int cmd_test_malloc_dump(struct unit_test_state *uts) return 0; } CMD_TEST(cmd_test_malloc_dump, UTF_CONSOLE); + +#if CONFIG_IS_ENABLED(MCHECK_LOG) +/* Test 'malloc log' command */ +static int cmd_test_malloc_log(struct unit_test_state *uts) +{ + struct mlog_info info; + void *ptr, *ptr2; + int seq; + + ut_assertok(run_command("malloc log start", 0)); + ut_assert_nextline("Malloc logging started"); + ut_assert_console_end(); + + /* Get current log position so we know our sequence numbers */ + ut_assertok(malloc_log_info(&info)); + seq = info.total_count; + + /* Do allocations with distinctive sizes we can search for */ + ptr = malloc(12345); + ut_assertnonnull(ptr); + ptr2 = realloc(ptr, 23456); + ut_assertnonnull(ptr2); + free(ptr2); + + ut_assertok(run_command("malloc log stop", 0)); + ut_assert_nextline("Malloc logging stopped"); + ut_assert_console_end(); + + /* Dump the log and find our allocations by sequence number and size */ + ut_assertok(run_command("malloc log", 0)); + ut_assert_nextlinen("Malloc log: "); + ut_assert_nextline("%4s %-8s %10s %8s %s", + "Seq", "Type", "Address", "Size", "Caller"); + ut_assert_nextline("---- -------- ---------- -------- ------"); + /* 12345 = 0x3039, 23456 = 0x5ba0 */ + ut_assert_skip_to_linen("%4d alloc %10lx 3039", seq, + (ulong)map_to_sysmem(ptr)); + ut_assert_skip_to_linen("%4d realloc %10lx 5ba0", seq + 1, + (ulong)map_to_sysmem(ptr2)); + ut_assert_skip_to_linen("%4d free %10lx 0", seq + 2, + (ulong)map_to_sysmem(ptr2)); + console_record_reset_enable(); /* discard remaining output */ + + return 0; +} +CMD_TEST(cmd_test_malloc_log, UTF_CONSOLE); +#endif /* MCHECK_LOG */