From: Simon Glass <simon.glass@canonical.com> When CONFIG_MCHECK_HEAP_PROTECTION is enabled, show the original caller info for freed chunks. This helps identify what code allocated memory that is now free. The mcheck header's canary and caller fields survive after free since dlmalloc only overwrites the first 16 bytes (size, aln_skip) with its free list pointers (fd, bk). We detect freed headers by looking for the MAGICFREE canary pattern. For small chunks or coalesced chunks where the header is not preserved, the caller info is simply omitted. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- common/dlmalloc.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/common/dlmalloc.c b/common/dlmalloc.c index c294b355ff2..62e1e0a77da 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -7093,6 +7093,39 @@ next: return NULL; } + +/** + * find_freed_mcheck_hdr() - find a freed mcheck header in a free chunk + * + * For freed chunks, the mcheck header remains with MAGICFREE canaries. + * Since freed entries are removed from the registry, scan the chunk + * for the MAGICFREE pattern. Only check offset 0 since free chunks + * may have been coalesced and we want the first (original) allocation. + * + * Note: dlmalloc overwrites the first 16 bytes (size, aln_skip) with + * free list pointers (fd, bk), but the canary and caller remain intact. + * + * @mem: chunk memory pointer (from chunk2mem) + * @sz: chunk size + * Return: pointer to mcheck header if found, NULL otherwise + */ +static struct mcheck_hdr *find_freed_mcheck_hdr(void *mem, size_t sz) +{ + struct mcheck_hdr *hdr = (struct mcheck_hdr *)mem; + int i; + + /* Only check at offset 0 - coalesced chunks lose alignment info */ + if (sz < sizeof(struct mcheck_hdr)) + return NULL; + + /* Check for MAGICFREE canary pattern */ + for (i = 0; i < CANARY_DEPTH; i++) { + if (hdr->canary.elems[i] != MAGICFREE) + return NULL; + } + + return hdr; +} #endif void malloc_dump(void) @@ -7142,8 +7175,20 @@ void malloc_dump(void) used += sz; used_count++; } else { - printf("%12lx %10zx <free>\n", +#if CONFIG_IS_ENABLED(MCHECK_HEAP_PROTECTION) + struct mcheck_hdr *hdr; + + hdr = find_freed_mcheck_hdr(mem, sz); + if (hdr && hdr->caller[0]) + printf("%12lx %10zx free %s\n", + (ulong)mem, sz, hdr->caller); + else + printf("%12lx %10zx free\n", + (ulong)mem, sz); +#else + printf("%12lx %10zx free\n", (ulong)mem, sz); +#endif free_space += sz; free_count++; } -- 2.43.0