[Concept,19/37] malloc: Annotate allocator for valgrind

Message ID 20251201170529.3237986-20-sjg@u-boot.org
State New
Headers
Series malloc: Import dlmalloc 2.8.6 |

Commit Message

Simon Glass Dec. 1, 2025, 5:04 p.m. UTC
  From: Simon Glass <simon.glass@canonical.com>

Add valgrind annotations to track memory allocations:
- VALGRIND_MALLOCLIKE_BLOCK in dlmalloc() at the postaction label
- VALGRIND_FREELIKE_BLOCK in dlfree() for both pre-reloc and post-reloc paths
- VALGRIND_RESIZEINPLACE_BLOCK/VALGRIND_MAKE_MEM_DEFINED in dlrealloc()
  and dlrealloc_in_place() when resizing in place
- VALGRIND_MALLOCLIKE_BLOCK/VALGRIND_FREELIKE_BLOCK in dlrealloc() when
  allocating new memory

Changes from original commit:
- The new dlmalloc 2.8.6 uses a centralized "postaction" label pattern
  instead of multiple return points, allowing simpler annotation
- Annotations placed at strategic points covering all allocation paths
- dlrealloc_in_place() is a new function that needs annotations

Signed-off-by: Sean Anderson <seanga2@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
(cherry picked from commit bdaeea1b6863b0ec80f2d4bc15d50b8d16efa708)
---

 common/dlmalloc.c | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)
  

Patch

diff --git a/common/dlmalloc.c b/common/dlmalloc.c
index a07166206dc..9298fc445e4 100644
--- a/common/dlmalloc.c
+++ b/common/dlmalloc.c
@@ -588,6 +588,7 @@  MAX_RELEASE_CHECK_RATE   default: 4095 unless not HAVE_MMAP
 #include <mapmem.h>
 #include <vsprintf.h>
 #include <asm/global_data.h>
+#include <valgrind/memcheck.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -4743,6 +4744,10 @@  void* dlmalloc(size_t bytes) {
 
   postaction:
     POSTACTION(gm);
+#ifdef __UBOOT__
+    if (mem)
+      VALGRIND_MALLOCLIKE_BLOCK(mem, bytes, SIZE_SZ, false);
+#endif
     return mem;
   }
 
@@ -4755,8 +4760,10 @@  void dlfree(void* mem) {
 #ifdef __UBOOT__
 #if CONFIG_IS_ENABLED(SYS_MALLOC_F)
   /* free() is a no-op - all the memory will be freed on relocation */
-  if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT))
+  if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT)) {
+    VALGRIND_FREELIKE_BLOCK(mem, SIZE_SZ);
     return;
+  }
 #endif
 #endif
   /*
@@ -4778,6 +4785,9 @@  void dlfree(void* mem) {
 #endif /* FOOTERS */
     if (!PREACTION(fm)) {
       check_inuse_chunk(fm, p);
+#ifdef __UBOOT__
+      VALGRIND_FREELIKE_BLOCK(mem, SIZE_SZ);
+#endif
       if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) {
         size_t psize = chunksize(p);
         mchunkptr next = chunk_plus_offset(p, psize);
@@ -5349,12 +5359,25 @@  void* dlrealloc(void* oldmem, size_t bytes) {
       if (newp != 0) {
         check_inuse_chunk(m, newp);
         mem = chunk2mem(newp);
+#ifdef __UBOOT__
+        if (mem == oldmem) {
+          VALGRIND_RESIZEINPLACE_BLOCK(oldmem, 0, bytes, SIZE_SZ);
+          VALGRIND_MAKE_MEM_DEFINED(oldmem, bytes);
+        } else {
+          VALGRIND_MALLOCLIKE_BLOCK(mem, bytes, SIZE_SZ, false);
+          VALGRIND_FREELIKE_BLOCK(oldmem, SIZE_SZ);
+        }
+#endif
       }
       else {
         mem = internal_malloc(m, bytes);
         if (mem != 0) {
           size_t oc = chunksize(oldp) - overhead_for(oldp);
           memcpy(mem, oldmem, (oc < bytes)? oc : bytes);
+#ifdef __UBOOT__
+          VALGRIND_MALLOCLIKE_BLOCK(mem, bytes, SIZE_SZ, false);
+          VALGRIND_FREELIKE_BLOCK(oldmem, SIZE_SZ);
+#endif
           internal_free(m, oldmem);
         }
       }
@@ -5387,6 +5410,10 @@  void* dlrealloc_in_place(void* oldmem, size_t bytes) {
         if (newp == oldp) {
           check_inuse_chunk(m, newp);
           mem = oldmem;
+#ifdef __UBOOT__
+          VALGRIND_RESIZEINPLACE_BLOCK(oldmem, 0, bytes, SIZE_SZ);
+          VALGRIND_MAKE_MEM_DEFINED(oldmem, bytes);
+#endif
         }
       }
     }