From 5f0c994b3e51cb13cbb2a0f8f313942220e82fdc Mon Sep 17 00:00:00 2001 From: otto Date: Fri, 30 Jun 2023 06:24:58 +0000 Subject: [PATCH] Recommit "Allow to ask for deeper callers for leak reports using malloc options" Now only enabled for platforms where it's know to work and written as a inline functions instead of a macro. --- lib/libc/stdlib/malloc.3 | 26 ++++++++++++++++-- lib/libc/stdlib/malloc.c | 57 +++++++++++++++++++++++++++++++++------- 2 files changed, 71 insertions(+), 12 deletions(-) diff --git a/lib/libc/stdlib/malloc.3 b/lib/libc/stdlib/malloc.3 index 79e85f39ee8..88a8264da52 100644 --- a/lib/libc/stdlib/malloc.3 +++ b/lib/libc/stdlib/malloc.3 @@ -30,9 +30,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $OpenBSD: malloc.3,v 1.135 2023/06/23 05:26:45 otto Exp $ +.\" $OpenBSD: malloc.3,v 1.136 2023/06/30 06:24:58 otto Exp $ .\" -.Dd $Mdocdate: June 23 2023 $ +.Dd $Mdocdate: June 30 2023 $ .Dt MALLOC 3 .Os .Sh NAME @@ -294,6 +294,17 @@ To record the dump: To view the leak report: .Pp .Dl $ kdump -u malloc ... +.Pp +By default, the immediate caller of a +.Nm +function will be recorded. +Use malloc options +.Cm 2 +or +.Cm 3 +to record the caller one or two stack frames deeper instead. +These malloc options imply +.Cm D . .It Cm F .Dq Freecheck . Enable more extensive double free and use after free detection. @@ -813,3 +824,14 @@ and .Fn realloc to avoid these problems on .Ox . +.Pp +The mechanism to record caller functions when using malloc options +.Cm 2 +or +.Cm 3 +is not guaranteed to work for all platforms, compilers or compilation +options, +and might even crash your program. +Use +.Em only +for debugging purposes. diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c index 34b2bb5e66f..c09e1541e5f 100644 --- a/lib/libc/stdlib/malloc.c +++ b/lib/libc/stdlib/malloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: malloc.c,v 1.288 2023/06/23 05:26:45 otto Exp $ */ +/* $OpenBSD: malloc.c,v 1.289 2023/06/30 06:24:58 otto Exp $ */ /* * Copyright (c) 2008, 2010, 2011, 2016, 2023 Otto Moerbeek * Copyright (c) 2012 Matthew Dempsky @@ -255,7 +255,37 @@ void malloc_dump(void); PROTO_NORMAL(malloc_dump); static void malloc_exit(void); #endif -#define CALLER (DO_STATS ? __builtin_return_address(0) : NULL) + +#if defined(__aarch64__) || \ + defined(__amd64__) || \ + defined(__arm__) +static inline void* caller(void) +{ + void *p; + + switch (DO_STATS) { + case 0: + default: + return NULL; + case 1: + p = __builtin_return_address(0); + break; + case 2: + p = __builtin_return_address(1); + break; + case 3: + p = __builtin_return_address(2); + break; + } + return __builtin_extract_return_addr(p); +} +#else +static inline void* caller(void) +{ + return DO_STATS == 0 ? NULL : + __builtin_extract_return_addr(__builtin_return_address(0)); +} +#endif /* low bits of r->p determine size: 0 means >= page size and r->size holding * real size, otherwise low bits is the bucket + 1 @@ -365,8 +395,15 @@ omalloc_parseopt(char opt) mopts.malloc_stats = 0; break; case 'D': + case '1': mopts.malloc_stats = 1; break; + case '2': + mopts.malloc_stats = 2; + break; + case '3': + mopts.malloc_stats = 3; + break; #endif /* MALLOC_STATS */ case 'f': mopts.malloc_freecheck = 0; @@ -1436,7 +1473,7 @@ malloc(size_t size) int saved_errno = errno; PROLOGUE(getpool(), "malloc") - r = omalloc(d, size, 0, CALLER); + r = omalloc(d, size, 0, caller()); EPILOGUE() return r; } @@ -1450,7 +1487,7 @@ malloc_conceal(size_t size) int saved_errno = errno; PROLOGUE(mopts.malloc_pool[0], "malloc_conceal") - r = omalloc(d, size, 0, CALLER); + r = omalloc(d, size, 0, caller()); EPILOGUE() return r; } @@ -1860,7 +1897,7 @@ realloc(void *ptr, size_t size) int saved_errno = errno; PROLOGUE(getpool(), "realloc") - r = orealloc(&d, ptr, size, CALLER); + r = orealloc(&d, ptr, size, caller()); EPILOGUE() return r; } @@ -1891,7 +1928,7 @@ calloc(size_t nmemb, size_t size) } size *= nmemb; - r = omalloc(d, size, 1, CALLER); + r = omalloc(d, size, 1, caller()); EPILOGUE() return r; } @@ -1916,7 +1953,7 @@ calloc_conceal(size_t nmemb, size_t size) } size *= nmemb; - r = omalloc(d, size, 1, CALLER); + r = omalloc(d, size, 1, caller()); EPILOGUE() return r; } @@ -2072,7 +2109,7 @@ recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size) oldsize = oldnmemb * size; } - r = orecallocarray(&d, ptr, oldsize, newsize, CALLER); + r = orecallocarray(&d, ptr, oldsize, newsize, caller()); EPILOGUE() return r; } @@ -2204,7 +2241,7 @@ posix_memalign(void **memptr, size_t alignment, size_t size) malloc_recurse(d); goto err; } - r = omemalign(d, alignment, size, 0, CALLER); + r = omemalign(d, alignment, size, 0, caller()); d->active--; _MALLOC_UNLOCK(d->mutex); if (r == NULL) { @@ -2242,7 +2279,7 @@ aligned_alloc(size_t alignment, size_t size) } PROLOGUE(getpool(), "aligned_alloc") - r = omemalign(d, alignment, size, 0, CALLER); + r = omemalign(d, alignment, size, 0, caller()); EPILOGUE() return r; } -- 2.20.1