diff options
| author | otto <> | 2023-06-30 06:24:58 +0000 | 
|---|---|---|
| committer | otto <> | 2023-06-30 06:24:58 +0000 | 
| commit | c111c67219ce3e64e18b69cac66db4f26b34a254 (patch) | |
| tree | c482c90f81a97095ad86696e78043e6ed1d42d0a /src/lib/libc | |
| parent | aae739209b87ebfee0f0dcfdea36069ec4946043 (diff) | |
| download | openbsd-c111c67219ce3e64e18b69cac66db4f26b34a254.tar.gz openbsd-c111c67219ce3e64e18b69cac66db4f26b34a254.tar.bz2 openbsd-c111c67219ce3e64e18b69cac66db4f26b34a254.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.
Diffstat (limited to 'src/lib/libc')
| -rw-r--r-- | src/lib/libc/stdlib/malloc.3 | 26 | ||||
| -rw-r--r-- | src/lib/libc/stdlib/malloc.c | 57 | 
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: | |||
| 294 | To view the leak report: | 294 | To view the leak report: | 
| 295 | .Pp | 295 | .Pp | 
| 296 | .Dl $ kdump -u malloc ... | 296 | .Dl $ kdump -u malloc ... | 
| 297 | .Pp | ||
| 298 | By default, the immediate caller of a | ||
| 299 | .Nm | ||
| 300 | function will be recorded. | ||
| 301 | Use malloc options | ||
| 302 | .Cm 2 | ||
| 303 | or | ||
| 304 | .Cm 3 | ||
| 305 | to record the caller one or two stack frames deeper instead. | ||
| 306 | These malloc options imply | ||
| 307 | .Cm D . | ||
| 297 | .It Cm F | 308 | .It Cm F | 
| 298 | .Dq Freecheck . | 309 | .Dq Freecheck . | 
| 299 | Enable more extensive double free and use after free detection. | 310 | Enable more extensive double free and use after free detection. | 
| @@ -813,3 +824,14 @@ and | |||
| 813 | .Fn realloc | 824 | .Fn realloc | 
| 814 | to avoid these problems on | 825 | to avoid these problems on | 
| 815 | .Ox . | 826 | .Ox . | 
| 827 | .Pp | ||
| 828 | The mechanism to record caller functions when using malloc options | ||
| 829 | .Cm 2 | ||
| 830 | or | ||
| 831 | .Cm 3 | ||
| 832 | is not guaranteed to work for all platforms, compilers or compilation | ||
| 833 | options, | ||
| 834 | and might even crash your program. | ||
| 835 | Use | ||
| 836 | .Em only | ||
| 837 | for 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); | |||
| 255 | PROTO_NORMAL(malloc_dump); | 255 | PROTO_NORMAL(malloc_dump); | 
| 256 | static void malloc_exit(void); | 256 | static 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__) | ||
| 262 | static 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 | ||
| 283 | static 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 | } | 
