summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorotto <>2023-06-30 06:24:58 +0000
committerotto <>2023-06-30 06:24:58 +0000
commit381f720c29b5d098065924022851c0a39f95211d (patch)
treec482c90f81a97095ad86696e78043e6ed1d42d0a
parent7e760c5cfae4ba21498ea8ffebdf11bc9315fac9 (diff)
downloadopenbsd-381f720c29b5d098065924022851c0a39f95211d.tar.gz
openbsd-381f720c29b5d098065924022851c0a39f95211d.tar.bz2
openbsd-381f720c29b5d098065924022851c0a39f95211d.zip
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.
-rw-r--r--src/lib/libc/stdlib/malloc.326
-rw-r--r--src/lib/libc/stdlib/malloc.c57
2 files changed, 71 insertions, 12 deletions
diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3
index 79e85f39ee..88a8264da5 100644
--- a/src/lib/libc/stdlib/malloc.3
+++ b/src/lib/libc/stdlib/malloc.3
@@ -30,9 +30,9 @@
30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31.\" SUCH DAMAGE. 31.\" SUCH DAMAGE.
32.\" 32.\"
33.\" $OpenBSD: malloc.3,v 1.135 2023/06/23 05:26:45 otto Exp $ 33.\" $OpenBSD: malloc.3,v 1.136 2023/06/30 06:24:58 otto Exp $
34.\" 34.\"
35.Dd $Mdocdate: June 23 2023 $ 35.Dd $Mdocdate: June 30 2023 $
36.Dt MALLOC 3 36.Dt MALLOC 3
37.Os 37.Os
38.Sh NAME 38.Sh NAME
@@ -294,6 +294,17 @@ To record the dump:
294To view the leak report: 294To view the leak report:
295.Pp 295.Pp
296.Dl $ kdump -u malloc ... 296.Dl $ kdump -u malloc ...
297.Pp
298By default, the immediate caller of a
299.Nm
300function will be recorded.
301Use malloc options
302.Cm 2
303or
304.Cm 3
305to record the caller one or two stack frames deeper instead.
306These malloc options imply
307.Cm D .
297.It Cm F 308.It Cm F
298.Dq Freecheck . 309.Dq Freecheck .
299Enable more extensive double free and use after free detection. 310Enable more extensive double free and use after free detection.
@@ -813,3 +824,14 @@ and
813.Fn realloc 824.Fn realloc
814to avoid these problems on 825to avoid these problems on
815.Ox . 826.Ox .
827.Pp
828The mechanism to record caller functions when using malloc options
829.Cm 2
830or
831.Cm 3
832is not guaranteed to work for all platforms, compilers or compilation
833options,
834and might even crash your program.
835Use
836.Em only
837for debugging purposes.
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
index 34b2bb5e66..c09e1541e5 100644
--- a/src/lib/libc/stdlib/malloc.c
+++ b/src/lib/libc/stdlib/malloc.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: malloc.c,v 1.288 2023/06/23 05:26:45 otto Exp $ */ 1/* $OpenBSD: malloc.c,v 1.289 2023/06/30 06:24:58 otto Exp $ */
2/* 2/*
3 * Copyright (c) 2008, 2010, 2011, 2016, 2023 Otto Moerbeek <otto@drijf.net> 3 * Copyright (c) 2008, 2010, 2011, 2016, 2023 Otto Moerbeek <otto@drijf.net>
4 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> 4 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
@@ -255,7 +255,37 @@ void malloc_dump(void);
255PROTO_NORMAL(malloc_dump); 255PROTO_NORMAL(malloc_dump);
256static void malloc_exit(void); 256static void malloc_exit(void);
257#endif 257#endif
258#define CALLER (DO_STATS ? __builtin_return_address(0) : NULL) 258
259#if defined(__aarch64__) || \
260 defined(__amd64__) || \
261 defined(__arm__)
262static inline void* caller(void)
263{
264 void *p;
265
266 switch (DO_STATS) {
267 case 0:
268 default:
269 return NULL;
270 case 1:
271 p = __builtin_return_address(0);
272 break;
273 case 2:
274 p = __builtin_return_address(1);
275 break;
276 case 3:
277 p = __builtin_return_address(2);
278 break;
279 }
280 return __builtin_extract_return_addr(p);
281}
282#else
283static inline void* caller(void)
284{
285 return DO_STATS == 0 ? NULL :
286 __builtin_extract_return_addr(__builtin_return_address(0));
287}
288#endif
259 289
260/* low bits of r->p determine size: 0 means >= page size and r->size holding 290/* low bits of r->p determine size: 0 means >= page size and r->size holding
261 * real size, otherwise low bits is the bucket + 1 291 * real size, otherwise low bits is the bucket + 1
@@ -365,8 +395,15 @@ omalloc_parseopt(char opt)
365 mopts.malloc_stats = 0; 395 mopts.malloc_stats = 0;
366 break; 396 break;
367 case 'D': 397 case 'D':
398 case '1':
368 mopts.malloc_stats = 1; 399 mopts.malloc_stats = 1;
369 break; 400 break;
401 case '2':
402 mopts.malloc_stats = 2;
403 break;
404 case '3':
405 mopts.malloc_stats = 3;
406 break;
370#endif /* MALLOC_STATS */ 407#endif /* MALLOC_STATS */
371 case 'f': 408 case 'f':
372 mopts.malloc_freecheck = 0; 409 mopts.malloc_freecheck = 0;
@@ -1436,7 +1473,7 @@ malloc(size_t size)
1436 int saved_errno = errno; 1473 int saved_errno = errno;
1437 1474
1438 PROLOGUE(getpool(), "malloc") 1475 PROLOGUE(getpool(), "malloc")
1439 r = omalloc(d, size, 0, CALLER); 1476 r = omalloc(d, size, 0, caller());
1440 EPILOGUE() 1477 EPILOGUE()
1441 return r; 1478 return r;
1442} 1479}
@@ -1450,7 +1487,7 @@ malloc_conceal(size_t size)
1450 int saved_errno = errno; 1487 int saved_errno = errno;
1451 1488
1452 PROLOGUE(mopts.malloc_pool[0], "malloc_conceal") 1489 PROLOGUE(mopts.malloc_pool[0], "malloc_conceal")
1453 r = omalloc(d, size, 0, CALLER); 1490 r = omalloc(d, size, 0, caller());
1454 EPILOGUE() 1491 EPILOGUE()
1455 return r; 1492 return r;
1456} 1493}
@@ -1860,7 +1897,7 @@ realloc(void *ptr, size_t size)
1860 int saved_errno = errno; 1897 int saved_errno = errno;
1861 1898
1862 PROLOGUE(getpool(), "realloc") 1899 PROLOGUE(getpool(), "realloc")
1863 r = orealloc(&d, ptr, size, CALLER); 1900 r = orealloc(&d, ptr, size, caller());
1864 EPILOGUE() 1901 EPILOGUE()
1865 return r; 1902 return r;
1866} 1903}
@@ -1891,7 +1928,7 @@ calloc(size_t nmemb, size_t size)
1891 } 1928 }
1892 1929
1893 size *= nmemb; 1930 size *= nmemb;
1894 r = omalloc(d, size, 1, CALLER); 1931 r = omalloc(d, size, 1, caller());
1895 EPILOGUE() 1932 EPILOGUE()
1896 return r; 1933 return r;
1897} 1934}
@@ -1916,7 +1953,7 @@ calloc_conceal(size_t nmemb, size_t size)
1916 } 1953 }
1917 1954
1918 size *= nmemb; 1955 size *= nmemb;
1919 r = omalloc(d, size, 1, CALLER); 1956 r = omalloc(d, size, 1, caller());
1920 EPILOGUE() 1957 EPILOGUE()
1921 return r; 1958 return r;
1922} 1959}
@@ -2072,7 +2109,7 @@ recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
2072 oldsize = oldnmemb * size; 2109 oldsize = oldnmemb * size;
2073 } 2110 }
2074 2111
2075 r = orecallocarray(&d, ptr, oldsize, newsize, CALLER); 2112 r = orecallocarray(&d, ptr, oldsize, newsize, caller());
2076 EPILOGUE() 2113 EPILOGUE()
2077 return r; 2114 return r;
2078} 2115}
@@ -2204,7 +2241,7 @@ posix_memalign(void **memptr, size_t alignment, size_t size)
2204 malloc_recurse(d); 2241 malloc_recurse(d);
2205 goto err; 2242 goto err;
2206 } 2243 }
2207 r = omemalign(d, alignment, size, 0, CALLER); 2244 r = omemalign(d, alignment, size, 0, caller());
2208 d->active--; 2245 d->active--;
2209 _MALLOC_UNLOCK(d->mutex); 2246 _MALLOC_UNLOCK(d->mutex);
2210 if (r == NULL) { 2247 if (r == NULL) {
@@ -2242,7 +2279,7 @@ aligned_alloc(size_t alignment, size_t size)
2242 } 2279 }
2243 2280
2244 PROLOGUE(getpool(), "aligned_alloc") 2281 PROLOGUE(getpool(), "aligned_alloc")
2245 r = omemalign(d, alignment, size, 0, CALLER); 2282 r = omemalign(d, alignment, size, 0, caller());
2246 EPILOGUE() 2283 EPILOGUE()
2247 return r; 2284 return r;
2248} 2285}