malloc: Add function to dump the malloc()-traffic log
Add malloc_log_dump() to print all recorded malloc/free/realloc calls with their addresses, sizes, and caller information. This provides a way to inspect the log after recording. The dump shows a summary line with entry counts, followed by a table with sequence number, operation type, pointer, size, and caller for each recorded operation. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com>
This commit is contained in:
@@ -6070,6 +6070,72 @@ void malloc_log_stop(void)
|
||||
mlog.enabled = false;
|
||||
}
|
||||
|
||||
/* Output function type for malloc_log_impl */
|
||||
typedef void (*log_out_fn)(void *ctx, const char *fmt, ...)
|
||||
__printf(2, 3);
|
||||
|
||||
/* Console output function for log */
|
||||
static void log_to_console(void *ctx, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vprintf(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void malloc_log_impl(log_out_fn out, void *ctx)
|
||||
{
|
||||
static const char * const mlog_type_names[] = {
|
||||
"alloc", "free", "realloc", "memalign"
|
||||
};
|
||||
uint i, start, count;
|
||||
|
||||
if (!mlog.buf) {
|
||||
out(ctx, "Malloc log not started\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mlog.enabled) {
|
||||
out(ctx, "Warning: log still active, results may be incomplete\n");
|
||||
malloc_log_stop();
|
||||
}
|
||||
|
||||
if (mlog.count > mlog.size) {
|
||||
out(ctx, "Warning: log wrapped, %u entries lost\n",
|
||||
mlog.count - mlog.size);
|
||||
count = mlog.size;
|
||||
start = mlog.head; /* oldest entry is at current head */
|
||||
} else {
|
||||
count = mlog.count;
|
||||
start = 0;
|
||||
}
|
||||
|
||||
out(ctx, "Malloc log: %u entries (max %u, total %u)\n", count, mlog.size,
|
||||
mlog.count);
|
||||
out(ctx, "%4s %-8s %10s %8s %s\n", "Seq", "Type", "Address", "Size",
|
||||
"Caller");
|
||||
out(ctx, "---- -------- ---------- -------- ------\n");
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
uint idx = (start + i) % mlog.size;
|
||||
struct mlog_entry *ent = &mlog.buf[idx];
|
||||
|
||||
out(ctx, "%4u %-8s %10lx %8lx", i, mlog_type_names[ent->type],
|
||||
(ulong)map_to_sysmem(ent->ptr), (ulong)ent->size);
|
||||
if (ent->type == MLOG_REALLOC)
|
||||
out(ctx, " (was %lx)", (ulong)ent->old_size);
|
||||
if (ent->caller[0])
|
||||
out(ctx, " %s", ent->caller);
|
||||
out(ctx, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void malloc_log_dump(void)
|
||||
{
|
||||
malloc_log_impl(log_to_console, NULL);
|
||||
}
|
||||
|
||||
int malloc_log_info(struct mlog_info *info)
|
||||
{
|
||||
if (!mlog.buf)
|
||||
@@ -6123,6 +6189,10 @@ void malloc_log_stop(void)
|
||||
{
|
||||
}
|
||||
|
||||
void malloc_log_dump(void)
|
||||
{
|
||||
}
|
||||
|
||||
int malloc_log_info(struct mlog_info *info)
|
||||
{
|
||||
return -ENOENT;
|
||||
|
||||
@@ -725,6 +725,14 @@ void malloc_log_start(void);
|
||||
*/
|
||||
void malloc_log_stop(void);
|
||||
|
||||
/**
|
||||
* malloc_log_dump() - Dump the malloc traffic log
|
||||
*
|
||||
* Prints all recorded malloc/free/realloc calls with their addresses,
|
||||
* sizes, and caller information.
|
||||
*/
|
||||
void malloc_log_dump(void);
|
||||
|
||||
/**
|
||||
* enum mlog_type - Type of malloc log entry
|
||||
*/
|
||||
|
||||
@@ -688,4 +688,45 @@ static int common_test_malloc_log_info(struct unit_test_state *uts)
|
||||
return 0;
|
||||
}
|
||||
COMMON_TEST(common_test_malloc_log_info, 0);
|
||||
|
||||
/* Test malloc_log_dump() */
|
||||
static int common_test_malloc_log_dump(struct unit_test_state *uts)
|
||||
{
|
||||
struct mlog_info info;
|
||||
void *ptr, *ptr2;
|
||||
|
||||
malloc_log_start();
|
||||
|
||||
/* Do an allocation, realloc, and free */
|
||||
ptr = malloc(0x100);
|
||||
ut_assertnonnull(ptr);
|
||||
|
||||
ptr2 = realloc(ptr, 0x200);
|
||||
ut_assertnonnull(ptr2);
|
||||
|
||||
free(ptr2);
|
||||
|
||||
malloc_log_stop();
|
||||
|
||||
ut_assertok(malloc_log_info(&info));
|
||||
|
||||
console_record_reset_enable();
|
||||
malloc_log_dump();
|
||||
|
||||
ut_assert_nextline("Malloc log: 3 entries (max %u, total 3)",
|
||||
info.max_entries);
|
||||
ut_assert_nextline("%4s %-8s %10s %8s %s", "Seq", "Type", "Address",
|
||||
"Size", "Caller");
|
||||
ut_assert_nextline("---- -------- ---------- -------- ------");
|
||||
ut_assert_nextlinen(" 0 alloc %10lx 100",
|
||||
(ulong)map_to_sysmem(ptr));
|
||||
ut_assert_nextlinen(" 1 realloc %10lx 200 (was 100)",
|
||||
(ulong)map_to_sysmem(ptr2));
|
||||
ut_assert_nextlinen(" 2 free %10lx 0",
|
||||
(ulong)map_to_sysmem(ptr2));
|
||||
ut_assert_console_end();
|
||||
|
||||
return 0;
|
||||
}
|
||||
COMMON_TEST(common_test_malloc_log_dump, 0);
|
||||
#endif /* MCHECK_LOG */
|
||||
|
||||
Reference in New Issue
Block a user