Files
u-boot/test/cmd/malloc.c
Simon Glass 7856369dc2 cmd: malloc: Add a command to show the malloc log
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 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2026-01-03 12:41:32 -07:00

103 lines
3.1 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Test for 'malloc' command
*
* Copyright 2025 Canonical Ltd
* Written by Simon Glass <simon.glass@canonical.com>
*/
#include <malloc.h>
#include <mapmem.h>
#include <dm/test.h>
#include <test/cmd.h>
#include <test/ut.h>
/* Test 'malloc info' command */
static int cmd_test_malloc_info(struct unit_test_state *uts)
{
struct malloc_info info;
ut_assertok(malloc_get_info(&info));
ut_assert(info.total_bytes >= CONFIG_SYS_MALLOC_LEN);
ut_assert(info.in_use_bytes < info.total_bytes);
ut_assert(info.malloc_count > 0);
ut_assertok(run_command("malloc info", 0));
ut_assert_nextlinen("total bytes = ");
ut_assert_nextlinen("in use bytes = ");
ut_assert_nextlinen("malloc count = ");
ut_assert_nextlinen("free count = ");
ut_assert_nextlinen("realloc count = ");
ut_assert_console_end();
return 0;
}
CMD_TEST(cmd_test_malloc_info, UTF_CONSOLE);
/* Test 'malloc dump' command */
static int cmd_test_malloc_dump(struct unit_test_state *uts)
{
/* this takes a long time to dump, with truetype enabled, so skip it */
return -EAGAIN;
ut_assertok(run_command("malloc dump", 0));
ut_assert_nextlinen("Heap dump: ");
ut_assert_nextline("%12s %10s %s", "Address", "Size", "Status");
ut_assert_nextline("----------------------------------");
ut_assert_nextline("%12lx %10x (chunk header)", mem_malloc_start, 0x10);
ut_assert_skip_to_line("----------------------------------");
ut_assert_nextlinen("Used: ");
ut_assert_nextlinen("Free: ");
ut_assert_console_end();
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 */