From patchwork Mon Mar 16 18:30:30 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 2018 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=1773685886; bh=ACr2PCjqNHBfC48nwguGN7vto1NXH39pOGA7kcwF1Xs=; 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=RacZiG6lGeCtcrohdQNEqKzun++S+EAOqpUxdSK0eKr0qKu7kWHrg1JFF3/N4sxL8 OkkLiP5Xzl/4g359qHVDnycHJB6UMnjviaUusf4jiUJojPyEYSCYjep1SKlnJVGltD J/+1pQHUoIiRfVDXGzTaacnN8Y/YiR5N6asRdmZcBrVNYzn+bKOXLZGVDMdsbeHkx5 oZSOMSIBRSyPCJ6T5CIhgJ+AHr1/5HGOe2FtOvS98DTV3vhSKqnrwDVOpfrFNHennv A2UgqkIS426L0Y99xa2y8GKQuoHqGgY2HSSakEeyO0dUSrrhh4pUUxJCGBnncdkCvJ 9eehrgKckchjw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id CEC516A0A5 for ; Mon, 16 Mar 2026 12:31:26 -0600 (MDT) 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 2mNvegKotkaz for ; Mon, 16 Mar 2026 12:31:26 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1773685886; bh=ACr2PCjqNHBfC48nwguGN7vto1NXH39pOGA7kcwF1Xs=; 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=RacZiG6lGeCtcrohdQNEqKzun++S+EAOqpUxdSK0eKr0qKu7kWHrg1JFF3/N4sxL8 OkkLiP5Xzl/4g359qHVDnycHJB6UMnjviaUusf4jiUJojPyEYSCYjep1SKlnJVGltD J/+1pQHUoIiRfVDXGzTaacnN8Y/YiR5N6asRdmZcBrVNYzn+bKOXLZGVDMdsbeHkx5 oZSOMSIBRSyPCJ6T5CIhgJ+AHr1/5HGOe2FtOvS98DTV3vhSKqnrwDVOpfrFNHennv A2UgqkIS426L0Y99xa2y8GKQuoHqGgY2HSSakEeyO0dUSrrhh4pUUxJCGBnncdkCvJ 9eehrgKckchjw== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 833416A081 for ; Mon, 16 Mar 2026 12:31:26 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1773685880; bh=Sm/5YlCHfkAHrXqaAMlH67q8w+Gi/yOKTy1OlzEpO4A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uAUNYqmx9faCF1ZZUwKBo5LqFPC015uQMGTbxTBoZcq2laAIaxqC0NTKmiKs6glBc 7LZl5MAq1OzbmBsgFTDqgVPQ08FC6VjblyTYGEkTBWhkaovtyldjqsKqpZ6PkcZyb6 hm5+GYRixlKqppy3czuLvW44/MEjzMFD1v/nw58aLTtWEI+v9jk3xle+hXw+Bj9/RE Tbow1klXAoIhtVyp3GXw2tU45W9c+hQkT34bb/oE825dt7sJrBh49vJo7fmZvpiWyo puJBTU7HFqNo+A2TLhDJL0hYEGjHADRb5+cMjTw/dDxIk+y2k5i5m7V/K74uetTqiQ 1FIoUg1GzHJ9w== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 61CA36A09B; Mon, 16 Mar 2026 12:31:20 -0600 (MDT) 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 kO9LXVoah9wI; Mon, 16 Mar 2026 12:31:20 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1773685877; bh=EvAEZ4u4pYM5C/Tz4u0KKFHFGG2X8WaW+M6L3xbe6rY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YaGWwdEOTCnnDn6LLhjKf+N5/tlDlhGMOkQ0BIWXLHboctZOum2tQHCPpVozDZPPn OlGYdfkBSVTvCQWZdZgXn6FNo8RhHjaGM/cvt9HrNpkMNDifLkUEOVuOx4hEZlGOn8 TrzkEoknnXyC6pc2yhrOkL5eOdPLV9tQiKQIY1fU0Uc7JNLyAVqzJued6vsd+0iIHK t4CYw+7iofW3N50mZUdkC03kMC+dNOlgoZXNI3o3WCcANgIA27WyT9nD8PUO++huGA 4aLGcawQMt2eyhBSghC47218kF9I9MziRqKbF7JV5nvjjXS78cwOp4WdVxnm/NCwSF eVBbzYB9wYmog== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 6DC2D6A09E; Mon, 16 Mar 2026 12:31:17 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Mon, 16 Mar 2026 12:30:30 -0600 Message-ID: <20260316183050.3855921-8-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260316183050.3855921-1-sjg@u-boot.org> References: <20260316183050.3855921-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: HTJNUOB6W2JEBR7TT3CELVB3PY5BCVGU X-Message-ID-Hash: HTJNUOB6W2JEBR7TT3CELVB3PY5BCVGU 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: Simon Glass X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 07/17] test: Show leaked allocations with ut -L 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 Use the new malloc_leak_check functions to show the address, size and caller backtrace of each leaked allocation, rather than just the total byte count. Example output: Test: acpi_bgrt: acpi.c Leak: 2 allocs 14a5c5c0 110 stdio_clone:230 <-stdio_register_dev:244 14a5c6d0 b0 map_to_sysmem:210 <-video_post_probe:823 Signed-off-by: Simon Glass --- doc/develop/malloc.rst | 30 +++++++++++++++++------------- test/test-main.c | 21 +++++++++++---------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/doc/develop/malloc.rst b/doc/develop/malloc.rst index 74acc3220af..6bb17dca7b1 100644 --- a/doc/develop/malloc.rst +++ b/doc/develop/malloc.rst @@ -503,14 +503,21 @@ by checking ``malloc_get_info()`` before and after:: **Automatic leak checking with ut -L** The ``ut`` command accepts a ``-L`` flag that checks for memory leaks around -each test. It takes a ``mallinfo()`` snapshot at the start of ``ut_run_test()`` -and compares it at the end, after both ``test_pre_run()`` and -``test_post_run()`` have completed:: +each test. It snapshots every in-use heap chunk at the start of +``ut_run_test()`` and compares after both ``test_pre_run()`` and +``test_post_run()`` have completed. Any new allocations are reported with +their address, size and caller backtrace:: - => ut -L dm dm_test_acpi_bgrt + => ut -LE dm dm_test_acpi_bgrt Test: acpi_bgrt: acpi.c - Leak: 448 bytes: acpi_bgrt - ... + Leak: 2 allocs + 14a5c5c0 110 stdio_clone:230 <-stdio_register_dev:244 <-vidconsole_post_probe:961 + 14a5c6d0 b0 map_to_sysmem:210 <-video_post_probe:823 <-device_probe:589 + Result: PASS: acpi_bgrt: acpi.c + +The snapshot is stored using ``os_malloc()`` so it does not affect the +heap being measured. Caller backtraces are available when +``CONFIG_MCHECK_HEAP_PROTECTION`` is enabled (the default for sandbox). When using uman, pass ``--leak-check``:: @@ -523,13 +530,10 @@ This makes it easy to scan an entire test suite for leaks:: **Practical workflow** 1. Run ``um t --leak-check -V dm`` (or another suite) to find leaky tests -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 +2. Use the caller backtrace in the ``-L`` output to find the allocation site +3. If more detail is needed, add ``malloc_dump_to_file()`` calls or enable + ``malloc_log_start()`` to trace all allocations during the operation +4. Fix the leak and verify the test passes **Dumping heap state on exit** diff --git a/test/test-main.c b/test/test-main.c index be13084ed92..09458fa91da 100644 --- a/test/test-main.c +++ b/test/test-main.c @@ -631,7 +631,7 @@ static int ut_run_test(struct unit_test_state *uts, struct unit_test *test, { const char *fname = strrchr(test->file, '/') + 1; const char *note = ""; - struct mallinfo leak_before; + struct malloc_leak_snap leak_snap = {}; int old_fail_count; int ret; @@ -640,7 +640,7 @@ static int ut_run_test(struct unit_test_state *uts, struct unit_test *test, printf("Test: %s: %s%s\n", test_name, fname, note); if (uts->leak_check) - leak_before = mallinfo(); + malloc_leak_check_start(&leak_snap); /* Allow access to test state from drivers */ ut_set_state(uts); @@ -664,14 +664,15 @@ static int ut_run_test(struct unit_test_state *uts, struct unit_test *test, ut_set_state(NULL); if (uts->leak_check) { - struct mallinfo leak_after; - int diff; - - leak_after = mallinfo(); - diff = leak_after.uordblks - leak_before.uordblks; - if (diff) - printf("Leak: %d bytes: %s%s\n", diff, test_name, - note); + int leaks; + + leaks = malloc_leak_check_count(&leak_snap); + if (leaks > 0) { + printf("Leak: %d allocs\n", leaks); + malloc_leak_check_end(&leak_snap); + } else { + malloc_leak_check_free(&leak_snap); + } } if (uts->emit_result) {