From patchwork Sat Jan 3 20:04:55 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1242 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=1767470823; bh=WhKTa2DMIzQ6Evrnw9BkfZKdN2duEO6102DyzV/79DQ=; 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=t3muE+N0ciCivj/AQHVYJ+mpkgVcAjPsk7Q9zDH+YjJGtOH9jj6JhULRvzXOiP7qe IyahhF1gVWOAQhw1Jeb5JIuuoLClcpDwbEYzwHUHzMARo0olB+3ZzJDSwSo1qgCuIY oldjat/KBXHESuyIdXIQ0BoN66Swvpu0II9TOflbTg2C6RTxGmgsAyGDAkFydCZ6KU HOj6CDClgBjjaM/o4CMabpQAyE6i50dbPxc0s/fcGgY/W9BsyJBwRN865UPIknWFGJ xnqgtMBPB7gpf+/LFTlmP9WgEKkV8tlEtuKajcpKnDlEEnno8bT4MqLPhouXmrV07l bzETzbU8WXzhQ== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id EA4FB68FD2 for ; Sat, 3 Jan 2026 13:07:03 -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 M-0Wl4PJy8RE for ; Sat, 3 Jan 2026 13:07:03 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767470823; bh=WhKTa2DMIzQ6Evrnw9BkfZKdN2duEO6102DyzV/79DQ=; 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=t3muE+N0ciCivj/AQHVYJ+mpkgVcAjPsk7Q9zDH+YjJGtOH9jj6JhULRvzXOiP7qe IyahhF1gVWOAQhw1Jeb5JIuuoLClcpDwbEYzwHUHzMARo0olB+3ZzJDSwSo1qgCuIY oldjat/KBXHESuyIdXIQ0BoN66Swvpu0II9TOflbTg2C6RTxGmgsAyGDAkFydCZ6KU HOj6CDClgBjjaM/o4CMabpQAyE6i50dbPxc0s/fcGgY/W9BsyJBwRN865UPIknWFGJ xnqgtMBPB7gpf+/LFTlmP9WgEKkV8tlEtuKajcpKnDlEEnno8bT4MqLPhouXmrV07l bzETzbU8WXzhQ== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 8B4246907B for ; Sat, 3 Jan 2026 13:07:03 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767470821; bh=7RhMejDA6PuSN5gAg6qlg4dEoNOthZUZRkyr5w34suY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=N8NYgvJeZa5LHmu3oNe2fbMB9njz+nmmSlZQXwRyDWzs8Lm4smjhU1CWHJfsiByDD eol6QhRHwz2Dc25HOF0RBtkPJJo4xgeaADsJtVPlSBDewiunr+HKWNWxtB8f3mUPoE UrTD8dNmWXUvVYMb7YzHPi6+UzgRRkOuKLNXDX2JCFeryp0Tn8aMWqztLjpApaVfha Vn4gUm+e8Uk4Ao+KVikhSzgtoQ1gv+TBSnEdKNMjAqWjPaVnaYnICb6gN7pcq9CNGr e6dv+snlN4pTFg/KiVqw+8MiZWmdNSfbNidjltnYBlvnXI/dlxOEK6C/cpYMvf2UIi /oWSuljUirJag== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 5FEB269097; Sat, 3 Jan 2026 13:07:01 -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 K3pCG3w_PckA; Sat, 3 Jan 2026 13:07:01 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767470819; bh=nrdhZnIZ0Rqb5gOw1Y6vkZccxF4IFCkBP42YyVsqcHI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NdZi4LoXb5OsVreBbzjo8qIbrPPe+yk69pLIzzx/Yvx+/g3qjcAJvuLAwPQjcTNF/ bI6kgcNe8WEac02BWoj2SM9lJq3gjhsh4v+MBNkg+2rB9RKjRXYIMjQdfNWjnsMCLk VZfgJfVEjwzwUps8U+ExtJGM0iyt01cthFiaaCiOk3pPFfi4FLnsbBUi/Ckhb1jCn3 GWY/ZrpsacRDLJ/+sWvPca1yaNUvZaJB8lrQn2tQv0vuSgcTGpEGDPNlZfklHww0g6 byJLI3AlV//W6r+UzxBMLyn5YDqe/V/WWELIKMFCioOleCIdIgqacf7zgZJZ+2gp6P zZr1+F/m66jog== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id DDF8869085; Sat, 3 Jan 2026 13:06:58 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sat, 3 Jan 2026 13:04:55 -0700 Message-ID: <20260103200510.3605009-25-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260103200510.3605009-1-sjg@u-boot.org> References: <20260103200510.3605009-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: WAL42DV4CCZ2GNXFX2LV23A375L6HIZE X-Message-ID-Hash: WAL42DV4CCZ2GNXFX2LV23A375L6HIZE 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 v2 24/29] doc: malloc: Add a section on finding memory leaks 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 Document the practical workflow for detecting and diagnosing memory leaks in U-Boot, particularly in sandbox builds. This covers: - Using ut_check_delta() in unit tests for leak detection - Comparing heap dumps with malloc_dump_to_file() - Using malloc traffic logging to trace allocations - Verifying debug functions don't affect heap state - A step-by-step practical workflow Co-developed-by: Claude Signed-off-by: Simon Glass --- (no changes since v1) doc/develop/malloc.rst | 93 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/doc/develop/malloc.rst b/doc/develop/malloc.rst index 776294809b8..b5c84c4c3bd 100644 --- a/doc/develop/malloc.rst +++ b/doc/develop/malloc.rst @@ -418,6 +418,99 @@ malloc testing Unit tests can use malloc_enable_testing() to simulate allocation failures. +Finding Memory Leaks +~~~~~~~~~~~~~~~~~~~~ + +U-Boot provides several tools for detecting and diagnosing memory leaks. +These techniques are primarily supported on sandbox, which has the full +debugging infrastructure enabled by default (``CONFIG_MALLOC_DEBUG``, +``CONFIG_MCHECK_HEAP_PROTECTION``) and access to host filesystem functions +for writing dump files. + +**Leak detection in unit tests** + +Unit tests can use ``ut_check_delta()`` to detect memory leaks:: + + ulong mem_start; + + mem_start = ut_check_delta(0); /* Record starting heap usage */ + + /* ... test code that allocates and frees memory ... */ + + ut_asserteq(0, ut_check_delta(mem_start)); /* Verify no leak */ + +This uses ``mallinfo().uordblks`` to compare heap usage before and after. + +**Heap dump comparison** + +When a leak is detected, use ``malloc_dump()`` to capture heap state before +and after the operation. In sandbox builds, ``malloc_dump_to_file()`` writes +the dump to a host file for easier comparison:: + + malloc_dump_to_file("/tmp/before.txt"); + + /* ... operation that may leak ... */ + + malloc_dump_to_file("/tmp/after.txt"); + +Then compare the dumps to find leaked allocations:: + + $ diff /tmp/before.txt /tmp/after.txt + +Or extract just the addresses and sizes for comparison:: + + $ awk '{print $1, $2}' /tmp/before.txt | sort > /tmp/b.txt + $ awk '{print $1, $2}' /tmp/after.txt | sort > /tmp/a.txt + $ comm -13 /tmp/b.txt /tmp/a.txt # Show allocations only in 'after' + +The dump includes caller information when ``CONFIG_MCHECK_HEAP_PROTECTION`` +is enabled, showing exactly where each leaked allocation originated. + +**Malloc-traffic logging** + +For more detailed analysis, use the malloc-traffic log to record all +allocations during an operation:: + + malloc_log_start(); + + /* ... operation to trace ... */ + + malloc_log_stop(); + malloc_log_to_file("/tmp/malloc_log.txt"); /* Sandbox only */ + +The log shows every malloc(), free(), and realloc() call with addresses, sizes, +and caller backtraces (if enabled). Search for allocations that were never +freed:: + + $ grep "alloc" /tmp/malloc_log.txt # Find all allocations + $ grep "16ad1290" /tmp/malloc_log.txt # Check if a specific address was freed + +**Verifying debug functions don't allocate** + +When using these debugging functions, verify they don't affect heap state +by checking ``malloc_get_info()`` before and after:: + + struct malloc_info before, after; + + malloc_get_info(&before); + malloc_dump_to_file("/tmp/dump.txt"); + malloc_get_info(&after); + + /* Verify no allocations occurred */ + assert(before.malloc_count == after.malloc_count); + assert(before.in_use_bytes == after.in_use_bytes); + +**Practical workflow** + +1. Add ``ut_check_delta()`` assertions to your test to detect leaks +2. When a leak is detected, add ``malloc_dump_to_file()`` calls before and + after the leaking operation +3. Run the test and compare the dump files to identify leaked allocations +4. Use the caller backtrace in the dump to find the allocation site +5. If more detail is needed, enable ``malloc_log_start()`` to trace all + allocations during the operation +6. Fix the leak and verify the test passes + API Reference -------------