From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4795CC433EF for ; Wed, 23 Mar 2022 18:05:38 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6AE2283F89; Wed, 23 Mar 2022 19:05:35 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="HyELCt+N"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 5BA3983F89; Wed, 23 Mar 2022 19:05:16 +0100 (CET) Received: from mail-qt1-x830.google.com (mail-qt1-x830.google.com [IPv6:2607:f8b0:4864:20::830]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id CB55683F8E for ; Wed, 23 Mar 2022 19:05:06 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=seanga2@gmail.com Received: by mail-qt1-x830.google.com with SMTP id c4so1872835qtx.1 for ; Wed, 23 Mar 2022 11:05:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=P396HirB0niIDYVQYg5f1rS1OVVmiUBroFGCE/E+3e4=; b=HyELCt+N3E4/92Sp8/sYl4GBzX7Lq37QPG0b/MVfuZyCq/va20geXlO76oNKYvP5PQ fJV5Y7sTn6k7OdIMHTkHx24Pq/vigqbMRrur/NjhzDw3ocEPpPuKoKgBcuJiepdAT0bZ 4XR6mIR+LlyJJsVT0Xb8rItWOOrr4VeXXeLusaI53dWbF+jqdNO10DBDyz2uij9iRJur 0AJ0q7VKmZ9B2/drceeOQT8/pnXSM0qvrj4plCsxVM17ju7eoAF+SA2+CrATVs187FYa G9nNvF35SnpCyARlo33tYhYJAx9jlA/fCvbFk96XooT1UpUR4F9TpGEipv2cIrS6/hog tY6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=P396HirB0niIDYVQYg5f1rS1OVVmiUBroFGCE/E+3e4=; b=ltdhWm4aBOF2RH8J7UhQMZbafp7tswg/QSt5Pq1V0H82Vvt34luetvFjOZZ0GtV2CT EmjlNjIJ1PhZIAybxUcw2T/63VjKzusIxUwMwTTijBtoa5kAVS5xGA7CGOQTjlkHVNGA q168AISIhSZqwjs5S8xe68CGPfV0TLBGbzZysNGxc4TG8FeQA8yhOct0ZuXoc6SCr6NA m407Wbylsuy2C+rQE/Hu5zSyYRqYwT3WX2HtkZMEu2E7oefOghHP65fLfiAT1GuRBMni GKM0ZKMskAu9qsdcdawmOmF/JBJJxDRs4gcEIfxhW7nrQq9slXFSQ/iExJtCFUREIxIv vTVQ== X-Gm-Message-State: AOAM531OxrIw1cxzUtJHOKhDEzSdgMPOdyX1zHAG3PyidzGIgV6KiIFS o3+YyWx5jjIprO784aquc1k= X-Google-Smtp-Source: ABdhPJxkWGNYBr/qxO06HB/EgZT8HoysNe81v6LYIfQ/Vk50WouwDOTeYz+CRHeLGnpQGzTLYD7C5Q== X-Received: by 2002:a05:622a:392:b0:2e2:34d1:979c with SMTP id j18-20020a05622a039200b002e234d1979cmr936895qtx.672.1648058705658; Wed, 23 Mar 2022 11:05:05 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-18-137-133.washdc.fios.verizon.net. [108.18.137.133]) by smtp.gmail.com with ESMTPSA id v9-20020a05620a0a8900b0067db9cc46a9sm314122qkg.62.2022.03.23.11.05.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 23 Mar 2022 11:05:05 -0700 (PDT) From: Sean Anderson To: Tom Rini , u-boot@lists.denx.de Cc: Heinrich Schuchardt , Simon Glass , Sean Anderson Subject: [PATCH v3 2/3] malloc: Annotate allocator for valgrind Date: Wed, 23 Mar 2022 14:04:49 -0400 Message-Id: <20220323180451.48950-3-seanga2@gmail.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220323180451.48950-1-seanga2@gmail.com> References: <20220323180451.48950-1-seanga2@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean This annotates malloc and friends so that valgrind can track the heap. To do this, we need to follow a few rules: * Call VALGRIND_MALLOCLIKE_BLOCK whenever we malloc something * Call VALGRIND_FREELIKE_BLOCK whenever we free something (generally after we have done our bookkeeping) * Call VALGRIND_RESIZEINPLACE_BLOCK whenever we change the size of an allocation. We don't record the original request size of a block, and neither does valgrind. For this reason, we pretend that the old size of the allocation was for 0 bytes. This marks the whole allocaton as undefined, so in order to mark all bits correctly, we must make the whole new allocation defined with VALGRIND_MAKE_MEM_DEFINED. This may cause us to miss some invalid reads, but there is no way to detect these without recording the original size of the allocation. In addition to the above, dlmalloc itself tends to make a lot of accesses which we know are safe, but which would be unsafe outside of dlmalloc. For this reason, we provide a suppression file which ignores errors ocurring in dlmalloc.c Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- Changes in v3: - Fix an additional rEALLOc branch missing VALGRIND_RESIZEINPLACE_BLOCK Changes in v2: - Fix one branch of rEALLOc missing a VALGRIND_*_BLOCK call - Add some additional suppressions for cALLOc and rEALLOc - Simplify calloc clearing logic common/dlmalloc.c | 31 +++++++++++++++++++++++- common/malloc_simple.c | 10 ++++++++ include/malloc.h | 4 ++++ scripts/u-boot.supp | 53 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 scripts/u-boot.supp diff --git a/common/dlmalloc.c b/common/dlmalloc.c index 11729e8c85..f48cd2a333 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -18,6 +18,7 @@ #include #include +#include #ifdef DEBUG #if __STD_C @@ -1339,6 +1340,7 @@ Void_t* mALLOc(bytes) size_t bytes; unlink(victim, bck, fwd); set_inuse_bit_at_offset(victim, victim_size); check_malloced_chunk(victim, nb); + VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(victim), bytes, SIZE_SZ, false); return chunk2mem(victim); } @@ -1366,6 +1368,7 @@ Void_t* mALLOc(bytes) size_t bytes; unlink(victim, bck, fwd); set_inuse_bit_at_offset(victim, victim_size); check_malloced_chunk(victim, nb); + VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(victim), bytes, SIZE_SZ, false); return chunk2mem(victim); } } @@ -1389,6 +1392,7 @@ Void_t* mALLOc(bytes) size_t bytes; set_head(remainder, remainder_size | PREV_INUSE); set_foot(remainder, remainder_size); check_malloced_chunk(victim, nb); + VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(victim), bytes, SIZE_SZ, false); return chunk2mem(victim); } @@ -1398,6 +1402,7 @@ Void_t* mALLOc(bytes) size_t bytes; { set_inuse_bit_at_offset(victim, victim_size); check_malloced_chunk(victim, nb); + VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(victim), bytes, SIZE_SZ, false); return chunk2mem(victim); } @@ -1453,6 +1458,7 @@ Void_t* mALLOc(bytes) size_t bytes; set_head(remainder, remainder_size | PREV_INUSE); set_foot(remainder, remainder_size); check_malloced_chunk(victim, nb); + VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(victim), bytes, SIZE_SZ, false); return chunk2mem(victim); } @@ -1461,6 +1467,7 @@ Void_t* mALLOc(bytes) size_t bytes; set_inuse_bit_at_offset(victim, victim_size); unlink(victim, bck, fwd); check_malloced_chunk(victim, nb); + VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(victim), bytes, SIZE_SZ, false); return chunk2mem(victim); } @@ -1509,6 +1516,7 @@ Void_t* mALLOc(bytes) size_t bytes; /* If big and would otherwise need to extend, try to use mmap instead */ if ((unsigned long)nb >= (unsigned long)mmap_threshold && (victim = mmap_chunk(nb))) + VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(victim), bytes, SIZE_SZ, false); return chunk2mem(victim); #endif @@ -1523,6 +1531,7 @@ Void_t* mALLOc(bytes) size_t bytes; top = chunk_at_offset(victim, nb); set_head(top, remainder_size | PREV_INUSE); check_malloced_chunk(victim, nb); + VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(victim), bytes, SIZE_SZ, false); return chunk2mem(victim); } @@ -1571,8 +1580,10 @@ void fREe(mem) Void_t* mem; #if CONFIG_VAL(SYS_MALLOC_F_LEN) /* 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 if (mem == NULL) /* free(0) has no effect */ @@ -1594,6 +1605,7 @@ void fREe(mem) Void_t* mem; sz = hd & ~PREV_INUSE; next = chunk_at_offset(p, sz); nextsz = chunksize(next); + VALGRIND_FREELIKE_BLOCK(mem, SIZE_SZ); if (next == top) /* merge with top */ { @@ -1782,6 +1794,8 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; top = chunk_at_offset(oldp, nb); set_head(top, (newsize - nb) | PREV_INUSE); set_head_size(oldp, nb); + VALGRIND_RESIZEINPLACE_BLOCK(chunk2mem(oldp), 0, bytes, SIZE_SZ); + VALGRIND_MAKE_MEM_DEFINED(chunk2mem(oldp), bytes); return chunk2mem(oldp); } } @@ -1791,6 +1805,8 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; { unlink(next, bck, fwd); newsize += nextsize; + VALGRIND_RESIZEINPLACE_BLOCK(chunk2mem(oldp), 0, bytes, SIZE_SZ); + VALGRIND_MAKE_MEM_DEFINED(chunk2mem(oldp), bytes); goto split; } } @@ -1820,10 +1836,12 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; newp = prev; newsize += prevsize + nextsize; newmem = chunk2mem(newp); + VALGRIND_MALLOCLIKE_BLOCK(newmem, bytes, SIZE_SZ, false); MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ); top = chunk_at_offset(newp, nb); set_head(top, (newsize - nb) | PREV_INUSE); set_head_size(newp, nb); + VALGRIND_FREELIKE_BLOCK(oldmem, SIZE_SZ); return newmem; } } @@ -1836,6 +1854,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; newp = prev; newsize += nextsize + prevsize; newmem = chunk2mem(newp); + VALGRIND_MALLOCLIKE_BLOCK(newmem, bytes, SIZE_SZ, false); MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ); goto split; } @@ -1848,6 +1867,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; newp = prev; newsize += prevsize; newmem = chunk2mem(newp); + VALGRIND_MALLOCLIKE_BLOCK(newmem, bytes, SIZE_SZ, false); MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ); goto split; } @@ -1874,6 +1894,9 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ); fREe(oldmem); return newmem; + } else { + VALGRIND_RESIZEINPLACE_BLOCK(oldmem, 0, bytes, SIZE_SZ); + VALGRIND_MAKE_MEM_DEFINED(oldmem, bytes); } @@ -1886,6 +1909,8 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; set_head_size(newp, nb); set_head(remainder, remainder_size | PREV_INUSE); set_inuse_bit_at_offset(remainder, remainder_size); + VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(remainder), remainder_size, SIZE_SZ, + false); fREe(chunk2mem(remainder)); /* let free() deal with it */ } else @@ -2043,6 +2068,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; set_head_size(p, leadsize); fREe(chunk2mem(p)); p = newp; + VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(p), bytes, SIZE_SZ, false); assert (newsize >= nb && (((unsigned long)(chunk2mem(p))) % alignment) == 0); } @@ -2056,6 +2082,8 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; remainder = chunk_at_offset(p, nb); set_head(remainder, remainder_size | PREV_INUSE); set_head_size(p, nb); + VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(remainder), remainder_size, SIZE_SZ, + false); fREe(chunk2mem(remainder)); } @@ -2159,6 +2187,7 @@ Void_t* cALLOc(n, elem_size) size_t n; size_t elem_size; #endif MALLOC_ZERO(mem, csz - SIZE_SZ); + VALGRIND_MAKE_MEM_DEFINED(mem, sz); return mem; } } diff --git a/common/malloc_simple.c b/common/malloc_simple.c index 67ee623850..0a004d40e1 100644 --- a/common/malloc_simple.c +++ b/common/malloc_simple.c @@ -13,6 +13,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -45,6 +46,7 @@ void *malloc_simple(size_t bytes) return ptr; log_debug("%lx\n", (ulong)ptr); + VALGRIND_MALLOCLIKE_BLOCK(ptr, bytes, 0, false); return ptr; } @@ -57,6 +59,7 @@ void *memalign_simple(size_t align, size_t bytes) if (!ptr) return ptr; log_debug("aligned to %lx\n", (ulong)ptr); + VALGRIND_MALLOCLIKE_BLOCK(ptr, bytes, 0, false); return ptr; } @@ -74,6 +77,13 @@ void *calloc(size_t nmemb, size_t elem_size) return ptr; } + +#if IS_ENABLED(CONFIG_VALGRIND) +void free_simple(void *ptr) +{ + VALGRIND_FREELIKE_BLOCK(ptr, 0); +} +#endif #endif void malloc_simple_info(void) diff --git a/include/malloc.h b/include/malloc.h index 1fbaf3755c..e8c8b254c0 100644 --- a/include/malloc.h +++ b/include/malloc.h @@ -887,7 +887,11 @@ void malloc_simple_info(void); #define malloc malloc_simple #define realloc realloc_simple #define memalign memalign_simple +#if IS_ENABLED(CONFIG_VALGRIND) +#define free free_simple +#else static inline void free(void *ptr) {} +#endif void *calloc(size_t nmemb, size_t size); void *realloc_simple(void *ptr, size_t size); #else diff --git a/scripts/u-boot.supp b/scripts/u-boot.supp new file mode 100644 index 0000000000..9562b27a61 --- /dev/null +++ b/scripts/u-boot.supp @@ -0,0 +1,53 @@ +{ + dlmalloc + Memcheck:Addr1 + src:dlmalloc.c +} +{ + dlmalloc + Memcheck:Addr4 + src:dlmalloc.c +} +{ + dlmalloc + Memcheck:Addr8 + src:dlmalloc.c +} +{ + dlmalloc + Memcheck:Addr1 + fun:* + src:dlmalloc.c +} +{ + dlmalloc + Memcheck:Addr4 + fun:* + src:dlmalloc.c +} +{ + dlmalloc + Memcheck:Addr8 + fun:* + src:dlmalloc.c +} +{ + dlmalloc + Memcheck:Value4 + src:dlmalloc.c +} +{ + dlmalloc + Memcheck:Value8 + src:dlmalloc.c +} +{ + dlmalloc + Memcheck:Cond + src:dlmalloc.c +} +{ + dlmalloc + Memcheck:Free + src:dlmalloc.c +} -- 2.35.1