diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libc/stdlib/malloc.3 | 44 | ||||
-rw-r--r-- | src/lib/libc/stdlib/malloc.c | 67 |
2 files changed, 38 insertions, 73 deletions
diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3 index b9d62d04d0..8da3a299e1 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.54 2008/08/07 18:41:47 otto Exp $ | 33 | .\" $OpenBSD: malloc.3,v 1.55 2008/11/02 08:50:41 otto Exp $ |
34 | .\" | 34 | .\" |
35 | .Dd $Mdocdate: August 7 2008 $ | 35 | .Dd $Mdocdate: November 2 2008 $ |
36 | .Dt MALLOC 3 | 36 | .Dt MALLOC 3 |
37 | .Os | 37 | .Os |
38 | .Sh NAME | 38 | .Sh NAME |
@@ -215,9 +215,11 @@ Flags are single letters, uppercase means on, lowercase means off. | |||
215 | .It Cm A | 215 | .It Cm A |
216 | .Dq Abort . | 216 | .Dq Abort . |
217 | .Fn malloc | 217 | .Fn malloc |
218 | will coredump the process, rather than tolerate failure. | 218 | will coredump the process, rather than tolerate internal |
219 | This is a very handy debugging aid, since the core file will represent the | 219 | inconsistencies or incorrect usage. |
220 | time of failure, rather than when the null pointer was accessed. | 220 | This is the default and a very handy debugging aid, |
221 | since the core file represents the time of failure, | ||
222 | rather than when the bogus pointer was used. | ||
221 | .It Cm D | 223 | .It Cm D |
222 | .Dq Dump . | 224 | .Dq Dump . |
223 | .Fn malloc | 225 | .Fn malloc |
@@ -248,9 +250,6 @@ Currently junk is bytes of 0xd0 when allocating; this is pronounced | |||
248 | .Dq Duh . | 250 | .Dq Duh . |
249 | \&:-) | 251 | \&:-) |
250 | Freed chunks are filled with 0xdf. | 252 | Freed chunks are filled with 0xdf. |
251 | .It Cm N | ||
252 | Do not output warning messages when encountering possible corruption | ||
253 | or bad pointers. | ||
254 | .It Cm P | 253 | .It Cm P |
255 | .Dq Move allocations within a page. | 254 | .Dq Move allocations within a page. |
256 | Allocations larger than half a page but smaller that a page | 255 | Allocations larger than half a page but smaller that a page |
@@ -297,7 +296,7 @@ Increase the size of the free page cache by a factor of two. | |||
297 | .El | 296 | .El |
298 | .Pp | 297 | .Pp |
299 | So to set a systemwide reduction of cache size and coredumps on problems: | 298 | So to set a systemwide reduction of cache size and coredumps on problems: |
300 | .Li ln -s 'A<' /etc/malloc.conf | 299 | .Li ln -s 'G<' /etc/malloc.conf |
301 | .Pp | 300 | .Pp |
302 | The | 301 | The |
303 | .Cm J | 302 | .Cm J |
@@ -349,22 +348,19 @@ If | |||
349 | .Fn realloc , | 348 | .Fn realloc , |
350 | or | 349 | or |
351 | .Fn free | 350 | .Fn free |
352 | detect an error or warning condition, | 351 | detect an error condition, |
353 | a message will be printed to file descriptor | 352 | a message will be printed to file descriptor |
354 | 2 (not using stdio). | 353 | 2 (not using stdio). |
355 | Errors will always result in the process being | 354 | Errors will result in the process being aborted, |
356 | .Xr abort 3 'ed. | 355 | unless the |
357 | If the | 356 | .Cm a |
358 | .Cm A | 357 | option has been specified. |
359 | option has been specified, warnings will also | ||
360 | .Xr abort 3 | ||
361 | the process. | ||
362 | .Pp | 358 | .Pp |
363 | Here is a brief description of the error messages and what they mean: | 359 | Here is a brief description of the error messages and what they mean: |
364 | .Bl -tag -width Ds | 360 | .Bl -tag -width Ds |
365 | .It Dq out of memory | 361 | .It Dq out of memory |
366 | If the | 362 | If the |
367 | .Cm A | 363 | .Cm X |
368 | option is specified it is an error for | 364 | option is specified it is an error for |
369 | .Fn malloc , | 365 | .Fn malloc , |
370 | .Fn calloc , | 366 | .Fn calloc , |
@@ -375,14 +371,6 @@ to return | |||
375 | .It Dq malloc init mmap failed | 371 | .It Dq malloc init mmap failed |
376 | This is a rather weird condition that is most likely to indicate a | 372 | This is a rather weird condition that is most likely to indicate a |
377 | seriously overloaded system or a ulimit restriction. | 373 | seriously overloaded system or a ulimit restriction. |
378 | .It any other error | ||
379 | .Fn malloc | ||
380 | detected an internal error; | ||
381 | consult sources and/or wizards. | ||
382 | .El | ||
383 | .Pp | ||
384 | Here is a brief description of the warning messages and what they mean: | ||
385 | .Bl -tag -width Ds | ||
386 | .It Dq bogus pointer (double free?) | 374 | .It Dq bogus pointer (double free?) |
387 | An attempt to | 375 | An attempt to |
388 | .Fn free | 376 | .Fn free |
@@ -418,6 +406,10 @@ The internal malloc page cache has been corrupted. | |||
418 | The internal malloc page cache has been corrupted. | 406 | The internal malloc page cache has been corrupted. |
419 | .It Dq guard size | 407 | .It Dq guard size |
420 | An inconsistent guard size was detected. | 408 | An inconsistent guard size was detected. |
409 | .It any other error | ||
410 | .Fn malloc | ||
411 | detected an internal error; | ||
412 | consult sources and/or wizards. | ||
421 | .El | 413 | .El |
422 | .Sh SEE ALSO | 414 | .Sh SEE ALSO |
423 | .Xr brk 2 , | 415 | .Xr brk 2 , |
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index 603cc55f18..0af2e2fdea 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.104 2008/10/29 14:05:15 otto Exp $ */ | 1 | /* $OpenBSD: malloc.c,v 1.105 2008/11/02 08:50:41 otto Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> | 3 | * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> |
4 | * | 4 | * |
@@ -149,7 +149,6 @@ static int malloc_hint; /* call madvice on free pages? */ | |||
149 | static int malloc_junk; /* junk fill? */ | 149 | static int malloc_junk; /* junk fill? */ |
150 | static int malloc_move; /* move allocations to end of page? */ | 150 | static int malloc_move; /* move allocations to end of page? */ |
151 | static int malloc_realloc; /* always realloc? */ | 151 | static int malloc_realloc; /* always realloc? */ |
152 | static int malloc_silent; /* avoid outputting warnings? */ | ||
153 | static int malloc_xmalloc; /* xmalloc behaviour? */ | 152 | static int malloc_xmalloc; /* xmalloc behaviour? */ |
154 | static int malloc_zero; /* zero fill? */ | 153 | static int malloc_zero; /* zero fill? */ |
155 | static size_t malloc_guard; /* use guard pages after allocations? */ | 154 | static size_t malloc_guard; /* use guard pages after allocations? */ |
@@ -355,31 +354,6 @@ wrterror(char *p) | |||
355 | abort(); | 354 | abort(); |
356 | } | 355 | } |
357 | 356 | ||
358 | static void | ||
359 | wrtwarning(char *p) | ||
360 | { | ||
361 | char *q = " warning: "; | ||
362 | struct iovec iov[5]; | ||
363 | |||
364 | if (malloc_abort) | ||
365 | wrterror(p); | ||
366 | else if (malloc_silent) | ||
367 | return; | ||
368 | |||
369 | iov[0].iov_base = __progname; | ||
370 | iov[0].iov_len = strlen(__progname); | ||
371 | iov[1].iov_base = malloc_func; | ||
372 | iov[1].iov_len = strlen(malloc_func); | ||
373 | iov[2].iov_base = q; | ||
374 | iov[2].iov_len = strlen(q); | ||
375 | iov[3].iov_base = p; | ||
376 | iov[3].iov_len = strlen(p); | ||
377 | iov[4].iov_base = "\n"; | ||
378 | iov[4].iov_len = 1; | ||
379 | |||
380 | writev(STDERR_FILENO, iov, 5); | ||
381 | } | ||
382 | |||
383 | /* | 357 | /* |
384 | * Cache maintenance. We keep at most malloc_cache pages cached. | 358 | * Cache maintenance. We keep at most malloc_cache pages cached. |
385 | * If the cache is becoming full, unmap pages in the cache for real, | 359 | * If the cache is becoming full, unmap pages in the cache for real, |
@@ -428,7 +402,7 @@ unmap(struct dir_info *d, void *p, size_t sz) | |||
428 | } | 402 | } |
429 | } | 403 | } |
430 | if (tounmap > 0) | 404 | if (tounmap > 0) |
431 | wrtwarning("malloc cache underflow"); | 405 | wrterror("malloc cache underflow"); |
432 | for (i = 0; i < malloc_cache; i++) { | 406 | for (i = 0; i < malloc_cache; i++) { |
433 | r = &d->free_regions[i]; | 407 | r = &d->free_regions[i]; |
434 | if (r->p == NULL) { | 408 | if (r->p == NULL) { |
@@ -443,9 +417,9 @@ unmap(struct dir_info *d, void *p, size_t sz) | |||
443 | } | 417 | } |
444 | } | 418 | } |
445 | if (i == malloc_cache) | 419 | if (i == malloc_cache) |
446 | wrtwarning("malloc free slot lost"); | 420 | wrterror("malloc free slot lost"); |
447 | if (d->free_regions_size > malloc_cache) | 421 | if (d->free_regions_size > malloc_cache) |
448 | wrtwarning("malloc cache overflow"); | 422 | wrterror("malloc cache overflow"); |
449 | } | 423 | } |
450 | 424 | ||
451 | static void | 425 | static void |
@@ -525,7 +499,7 @@ map(struct dir_info *d, size_t sz, int zero_fill) | |||
525 | if (p != MAP_FAILED) | 499 | if (p != MAP_FAILED) |
526 | malloc_used += sz; | 500 | malloc_used += sz; |
527 | if (d->free_regions_size > malloc_cache) | 501 | if (d->free_regions_size > malloc_cache) |
528 | wrtwarning("malloc cache"); | 502 | wrterror("malloc cache"); |
529 | /* zero fill not needed */ | 503 | /* zero fill not needed */ |
530 | return p; | 504 | return p; |
531 | } | 505 | } |
@@ -628,10 +602,7 @@ omalloc_init(struct dir_info *d) | |||
628 | malloc_junk = 1; | 602 | malloc_junk = 1; |
629 | break; | 603 | break; |
630 | case 'n': | 604 | case 'n': |
631 | malloc_silent = 0; | ||
632 | break; | ||
633 | case 'N': | 605 | case 'N': |
634 | malloc_silent = 1; | ||
635 | break; | 606 | break; |
636 | case 'p': | 607 | case 'p': |
637 | malloc_move = 0; | 608 | malloc_move = 0; |
@@ -660,7 +631,7 @@ omalloc_init(struct dir_info *d) | |||
660 | default: | 631 | default: |
661 | j = malloc_abort; | 632 | j = malloc_abort; |
662 | malloc_abort = 0; | 633 | malloc_abort = 0; |
663 | wrtwarning("unknown char in MALLOC_OPTIONS"); | 634 | wrterror("unknown char in MALLOC_OPTIONS"); |
664 | malloc_abort = j; | 635 | malloc_abort = j; |
665 | break; | 636 | break; |
666 | } | 637 | } |
@@ -675,9 +646,11 @@ omalloc_init(struct dir_info *d) | |||
675 | malloc_junk = 1; | 646 | malloc_junk = 1; |
676 | 647 | ||
677 | #ifdef MALLOC_STATS | 648 | #ifdef MALLOC_STATS |
678 | if (malloc_stats && (atexit(malloc_exit) == -1)) | 649 | if (malloc_stats && (atexit(malloc_exit) == -1)) { |
679 | wrtwarning("atexit(2) failed." | 650 | char *q = "malloc() warning: atexit(2) failed." |
680 | " Will not be able to dump malloc stats on exit"); | 651 | " Will not be able to dump stats on exit\n"; |
652 | write(STDERR_FILENO, q, strlen(q)); | ||
653 | } | ||
681 | #endif /* MALLOC_STATS */ | 654 | #endif /* MALLOC_STATS */ |
682 | 655 | ||
683 | d->regions_bits = 9; | 656 | d->regions_bits = 9; |
@@ -1024,11 +997,11 @@ free_bytes(struct dir_info *d, struct region_info *r, void *ptr) | |||
1024 | i = ((uintptr_t)ptr & MALLOC_PAGEMASK) >> info->shift; | 997 | i = ((uintptr_t)ptr & MALLOC_PAGEMASK) >> info->shift; |
1025 | 998 | ||
1026 | if ((uintptr_t)ptr & ((1UL << (info->shift)) - 1)) { | 999 | if ((uintptr_t)ptr & ((1UL << (info->shift)) - 1)) { |
1027 | wrtwarning("modified chunk-pointer"); | 1000 | wrterror("modified chunk-pointer"); |
1028 | return; | 1001 | return; |
1029 | } | 1002 | } |
1030 | if (info->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) { | 1003 | if (info->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) { |
1031 | wrtwarning("chunk is already free"); | 1004 | wrterror("chunk is already free"); |
1032 | return; | 1005 | return; |
1033 | } | 1006 | } |
1034 | 1007 | ||
@@ -1149,7 +1122,7 @@ malloc_recurse(void) | |||
1149 | 1122 | ||
1150 | if (noprint == 0) { | 1123 | if (noprint == 0) { |
1151 | noprint = 1; | 1124 | noprint = 1; |
1152 | wrtwarning("recursive call"); | 1125 | wrterror("recursive call"); |
1153 | } | 1126 | } |
1154 | malloc_active--; | 1127 | malloc_active--; |
1155 | _MALLOC_UNLOCK(); | 1128 | _MALLOC_UNLOCK(); |
@@ -1197,14 +1170,14 @@ ofree(void *p) | |||
1197 | 1170 | ||
1198 | r = find(&g_pool, p); | 1171 | r = find(&g_pool, p); |
1199 | if (r == NULL) { | 1172 | if (r == NULL) { |
1200 | wrtwarning("bogus pointer (double free?)"); | 1173 | wrterror("bogus pointer (double free?)"); |
1201 | return; | 1174 | return; |
1202 | } | 1175 | } |
1203 | REALSIZE(sz, r); | 1176 | REALSIZE(sz, r); |
1204 | if (sz > MALLOC_MAXCHUNK) { | 1177 | if (sz > MALLOC_MAXCHUNK) { |
1205 | if (sz - malloc_guard >= MALLOC_PAGESIZE - MALLOC_MINSIZE) { | 1178 | if (sz - malloc_guard >= MALLOC_PAGESIZE - MALLOC_MINSIZE) { |
1206 | if (r->p != p) | 1179 | if (r->p != p) |
1207 | wrtwarning("bogus pointer"); | 1180 | wrterror("bogus pointer"); |
1208 | } else { | 1181 | } else { |
1209 | #if notyetbecause_of_realloc | 1182 | #if notyetbecause_of_realloc |
1210 | /* shifted towards the end */ | 1183 | /* shifted towards the end */ |
@@ -1217,7 +1190,7 @@ ofree(void *p) | |||
1217 | } | 1190 | } |
1218 | if (malloc_guard) { | 1191 | if (malloc_guard) { |
1219 | if (sz < malloc_guard) | 1192 | if (sz < malloc_guard) |
1220 | wrtwarning("guard size"); | 1193 | wrterror("guard size"); |
1221 | if (!malloc_freeprot) { | 1194 | if (!malloc_freeprot) { |
1222 | if (mprotect((char *)p + PAGEROUND(sz) - | 1195 | if (mprotect((char *)p + PAGEROUND(sz) - |
1223 | malloc_guard, malloc_guard, | 1196 | malloc_guard, malloc_guard, |
@@ -1243,7 +1216,7 @@ ofree(void *p) | |||
1243 | if (p != NULL) { | 1216 | if (p != NULL) { |
1244 | r = find(&g_pool, p); | 1217 | r = find(&g_pool, p); |
1245 | if (r == NULL) { | 1218 | if (r == NULL) { |
1246 | wrtwarning("bogus pointer (double free?)"); | 1219 | wrterror("bogus pointer (double free?)"); |
1247 | return; | 1220 | return; |
1248 | } | 1221 | } |
1249 | free_bytes(&g_pool, r, p); | 1222 | free_bytes(&g_pool, r, p); |
@@ -1285,7 +1258,7 @@ orealloc(void *p, size_t newsz) | |||
1285 | 1258 | ||
1286 | r = find(&g_pool, p); | 1259 | r = find(&g_pool, p); |
1287 | if (r == NULL) { | 1260 | if (r == NULL) { |
1288 | wrtwarning("bogus pointer (double free?)"); | 1261 | wrterror("bogus pointer (double free?)"); |
1289 | return NULL; | 1262 | return NULL; |
1290 | } | 1263 | } |
1291 | if (newsz >= SIZE_MAX - malloc_guard - MALLOC_PAGESIZE) { | 1264 | if (newsz >= SIZE_MAX - malloc_guard - MALLOC_PAGESIZE) { |
@@ -1297,7 +1270,7 @@ orealloc(void *p, size_t newsz) | |||
1297 | goldsz = oldsz; | 1270 | goldsz = oldsz; |
1298 | if (oldsz > MALLOC_MAXCHUNK) { | 1271 | if (oldsz > MALLOC_MAXCHUNK) { |
1299 | if (oldsz < malloc_guard) | 1272 | if (oldsz < malloc_guard) |
1300 | wrtwarning("guard size"); | 1273 | wrterror("guard size"); |
1301 | oldsz -= malloc_guard; | 1274 | oldsz -= malloc_guard; |
1302 | } | 1275 | } |
1303 | 1276 | ||