OpenBSD_malloc_Linux.c (46253B)
1 /* Version 1.83 for Linux. 2 * Compilation: gcc -shared -fPIC -O2 OpenBSD_malloc_Linux.c -o malloc.so 3 * Launching: LD_PRELOAD=/path/to/malloc.so firefox 4 */ 5 6 /* $OpenBSD: malloc.c,v 1.83 2006/05/14 19:53:40 otto Exp $ */ 7 8 /* 9 * ---------------------------------------------------------------------------- 10 * "THE BEER-WARE LICENSE" (Revision 42): 11 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you 12 * can do whatever you want with this stuff. If we meet some day, and you think 13 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 14 * ---------------------------------------------------------------------------- 15 */ 16 17 /* We use this macro to remove some code that we don't actually want, 18 * rather than to fix its warnings. */ 19 #define BUILDING_FOR_TOR 20 21 /* 22 * Defining MALLOC_EXTRA_SANITY will enable extra checks which are 23 * related to internal conditions and consistency in malloc.c. This has 24 * a noticeable runtime performance hit, and generally will not do you 25 * any good unless you fiddle with the internals of malloc or want 26 * to catch random pointer corruption as early as possible. 27 */ 28 #ifndef MALLOC_EXTRA_SANITY 29 #undef MALLOC_EXTRA_SANITY 30 #endif 31 32 /* 33 * Defining MALLOC_STATS will enable you to call malloc_dump() and set 34 * the [dD] options in the MALLOC_OPTIONS environment variable. 35 * It has no run-time performance hit, but does pull in stdio... 36 */ 37 #ifndef MALLOC_STATS 38 #undef MALLOC_STATS 39 #endif 40 41 /* 42 * What to use for Junk. This is the byte value we use to fill with 43 * when the 'J' option is enabled. 44 */ 45 #define SOME_JUNK 0xd0 /* as in "Duh" :-) */ 46 47 #include <sys/types.h> 48 #include <sys/time.h> 49 #include <sys/resource.h> 50 #include <sys/param.h> 51 #include <sys/mman.h> 52 #include <sys/uio.h> 53 #include <stdio.h> 54 #include <stdlib.h> 55 #include <string.h> 56 #include <unistd.h> 57 #include <fcntl.h> 58 #include <limits.h> 59 #include <errno.h> 60 #include <err.h> 61 /* For SIZE_MAX */ 62 #include "lib/cc/torint.h" 63 64 //#include "thread_private.h" 65 66 /* 67 * The basic parameters you can tweak. 68 * 69 * malloc_pageshift pagesize = 1 << malloc_pageshift 70 * It's probably best if this is the native 71 * page size, but it shouldn't have to be. 72 * 73 * malloc_minsize minimum size of an allocation in bytes. 74 * If this is too small it's too much work 75 * to manage them. This is also the smallest 76 * unit of alignment used for the storage 77 * returned by malloc/realloc. 78 * 79 */ 80 81 static int align = 0; 82 static size_t g_alignment = 0; 83 84 extern int __libc_enable_secure; 85 86 #ifndef HAVE_ISSETUGID 87 static int issetugid(void) 88 { 89 if (__libc_enable_secure) return 1; 90 if (getuid() != geteuid()) return 1; 91 if (getgid() != getegid()) return 1; 92 return 0; 93 } 94 #endif 95 96 #define PGSHIFT 12 97 #undef MADV_FREE 98 #define MADV_FREE MADV_DONTNEED 99 #include <pthread.h> 100 static pthread_mutex_t gen_mutex = PTHREAD_MUTEX_INITIALIZER; 101 102 #define _MALLOC_LOCK_INIT() {;} 103 #define _MALLOC_LOCK() {pthread_mutex_lock(&gen_mutex);} 104 #define _MALLOC_UNLOCK() {pthread_mutex_unlock(&gen_mutex);} 105 106 #if defined(__sparc__) || defined(__alpha__) 107 #define malloc_pageshift 13U 108 #endif 109 #if defined(__ia64__) 110 #define malloc_pageshift 14U 111 #endif 112 113 #ifndef malloc_pageshift 114 #define malloc_pageshift (PGSHIFT) 115 #endif 116 117 /* 118 * No user serviceable parts behind this point. 119 * 120 * This structure describes a page worth of chunks. 121 */ 122 struct pginfo { 123 struct pginfo *next; /* next on the free list */ 124 void *page; /* Pointer to the page */ 125 u_short size; /* size of this page's chunks */ 126 u_short shift; /* How far to shift for this size chunks */ 127 u_short free; /* How many free chunks */ 128 u_short total; /* How many chunk */ 129 u_long bits[1];/* Which chunks are free */ 130 }; 131 132 /* How many bits per u_long in the bitmap */ 133 #define MALLOC_BITS (int)((NBBY * sizeof(u_long))) 134 135 /* 136 * This structure describes a number of free pages. 137 */ 138 struct pgfree { 139 struct pgfree *next; /* next run of free pages */ 140 struct pgfree *prev; /* prev run of free pages */ 141 void *page; /* pointer to free pages */ 142 void *pdir; /* pointer to the base page's dir */ 143 size_t size; /* number of bytes free */ 144 }; 145 146 /* 147 * Magic values to put in the page_directory 148 */ 149 #define MALLOC_NOT_MINE ((struct pginfo*) 0) 150 #define MALLOC_FREE ((struct pginfo*) 1) 151 #define MALLOC_FIRST ((struct pginfo*) 2) 152 #define MALLOC_FOLLOW ((struct pginfo*) 3) 153 #define MALLOC_MAGIC ((struct pginfo*) 4) 154 155 #ifndef malloc_minsize 156 #define malloc_minsize 16UL 157 #endif 158 159 #if !defined(malloc_pagesize) 160 #define malloc_pagesize (1UL<<malloc_pageshift) 161 #endif 162 163 #if ((1UL<<malloc_pageshift) != malloc_pagesize) 164 #error "(1UL<<malloc_pageshift) != malloc_pagesize" 165 #endif 166 167 #ifndef malloc_maxsize 168 #define malloc_maxsize ((malloc_pagesize)>>1) 169 #endif 170 171 /* A mask for the offset inside a page. */ 172 #define malloc_pagemask ((malloc_pagesize)-1) 173 174 #define pageround(foo) (((foo) + (malloc_pagemask)) & ~malloc_pagemask) 175 #define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)+malloc_pageshift) 176 #define index2ptr(idx) ((void*)(((idx)-malloc_pageshift)<<malloc_pageshift)) 177 178 /* Set when initialization has been done */ 179 static unsigned int malloc_started; 180 181 /* Number of free pages we cache */ 182 static unsigned int malloc_cache = 16; 183 184 /* Structure used for linking discrete directory pages. */ 185 struct pdinfo { 186 struct pginfo **base; 187 struct pdinfo *prev; 188 struct pdinfo *next; 189 u_long dirnum; 190 }; 191 static struct pdinfo *last_dir; /* Caches to the last and previous */ 192 static struct pdinfo *prev_dir; /* referenced directory pages. */ 193 194 static size_t pdi_off; 195 static u_long pdi_mod; 196 #define PD_IDX(num) ((num) / (malloc_pagesize/sizeof(struct pginfo *))) 197 #define PD_OFF(num) ((num) & ((malloc_pagesize/sizeof(struct pginfo *))-1)) 198 #define PI_IDX(index) ((index) / pdi_mod) 199 #define PI_OFF(index) ((index) % pdi_mod) 200 201 /* The last index in the page directory we care about */ 202 static u_long last_index; 203 204 /* Pointer to page directory. Allocated "as if with" malloc */ 205 static struct pginfo **page_dir; 206 207 /* Free pages line up here */ 208 static struct pgfree free_list; 209 210 /* Abort(), user doesn't handle problems. */ 211 static int malloc_abort = 2; 212 213 /* Are we trying to die ? */ 214 static int suicide; 215 216 #ifdef MALLOC_STATS 217 /* dump statistics */ 218 static int malloc_stats; 219 #endif 220 221 /* avoid outputting warnings? */ 222 static int malloc_silent; 223 224 /* always realloc ? */ 225 static int malloc_realloc; 226 227 /* mprotect free pages PROT_NONE? */ 228 static int malloc_freeprot; 229 230 /* use guard pages after allocations? */ 231 static size_t malloc_guard = 0; 232 static size_t malloc_guarded; 233 /* align pointers to end of page? */ 234 static int malloc_ptrguard; 235 236 static int malloc_hint = 1; 237 238 /* xmalloc behaviour ? */ 239 static int malloc_xmalloc; 240 241 /* zero fill ? */ 242 static int malloc_zero; 243 244 /* junk fill ? */ 245 static int malloc_junk; 246 247 #ifdef __FreeBSD__ 248 /* utrace ? */ 249 static int malloc_utrace; 250 251 struct ut { 252 void *p; 253 size_t s; 254 void *r; 255 }; 256 257 void utrace(struct ut *, int); 258 259 #define UTRACE(a, b, c) \ 260 if (malloc_utrace) \ 261 {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);} 262 #else /* !__FreeBSD__ */ 263 #define UTRACE(a,b,c) 264 #endif 265 266 /* Status of malloc. */ 267 static int malloc_active; 268 269 /* Allocated memory. */ 270 static size_t malloc_used; 271 272 /* My last break. */ 273 static caddr_t malloc_brk; 274 275 /* One location cache for free-list holders. */ 276 static struct pgfree *px; 277 278 /* Compile-time options. */ 279 char *malloc_options; 280 281 /* Name of the current public function. */ 282 static const char *malloc_func; 283 284 #define MMAP(size) \ 285 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \ 286 -1, (off_t)0) 287 288 /* 289 * Necessary function declarations. 290 */ 291 static void *imalloc(size_t size); 292 static void ifree(void *ptr); 293 static void *irealloc(void *ptr, size_t size); 294 static void *malloc_bytes(size_t size); 295 void *memalign(size_t boundary, size_t size); 296 size_t malloc_good_size(size_t size); 297 298 /* 299 * Function for page directory lookup. 300 */ 301 static int 302 pdir_lookup(u_long index, struct pdinfo ** pdi) 303 { 304 struct pdinfo *spi; 305 u_long pidx = PI_IDX(index); 306 307 if (last_dir != NULL && PD_IDX(last_dir->dirnum) == pidx) 308 *pdi = last_dir; 309 else if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) == pidx) 310 *pdi = prev_dir; 311 else if (last_dir != NULL && prev_dir != NULL) { 312 if ((PD_IDX(last_dir->dirnum) > pidx) ? 313 (PD_IDX(last_dir->dirnum) - pidx) : 314 (pidx - PD_IDX(last_dir->dirnum)) 315 < (PD_IDX(prev_dir->dirnum) > pidx) ? 316 (PD_IDX(prev_dir->dirnum) - pidx) : 317 (pidx - PD_IDX(prev_dir->dirnum))) 318 *pdi = last_dir; 319 else 320 *pdi = prev_dir; 321 322 if (PD_IDX((*pdi)->dirnum) > pidx) { 323 for (spi = (*pdi)->prev; 324 spi != NULL && PD_IDX(spi->dirnum) > pidx; 325 spi = spi->prev) 326 *pdi = spi; 327 if (spi != NULL) 328 *pdi = spi; 329 } else 330 for (spi = (*pdi)->next; 331 spi != NULL && PD_IDX(spi->dirnum) <= pidx; 332 spi = spi->next) 333 *pdi = spi; 334 } else { 335 *pdi = (struct pdinfo *) ((caddr_t) page_dir + pdi_off); 336 for (spi = *pdi; 337 spi != NULL && PD_IDX(spi->dirnum) <= pidx; 338 spi = spi->next) 339 *pdi = spi; 340 } 341 342 return ((PD_IDX((*pdi)->dirnum) == pidx) ? 0 : 343 (PD_IDX((*pdi)->dirnum) > pidx) ? 1 : -1); 344 } 345 346 #ifdef MALLOC_STATS 347 void 348 malloc_dump(int fd) 349 { 350 char buf[1024]; 351 struct pginfo **pd; 352 struct pgfree *pf; 353 struct pdinfo *pi; 354 u_long j; 355 356 pd = page_dir; 357 pi = (struct pdinfo *) ((caddr_t) pd + pdi_off); 358 359 /* print out all the pages */ 360 for (j = 0; j <= last_index;) { 361 snprintf(buf, sizeof buf, "%08lx %5lu ", j << malloc_pageshift, j); 362 write(fd, buf, strlen(buf)); 363 if (pd[PI_OFF(j)] == MALLOC_NOT_MINE) { 364 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_NOT_MINE;) { 365 if (!PI_OFF(++j)) { 366 if ((pi = pi->next) == NULL || 367 PD_IDX(pi->dirnum) != PI_IDX(j)) 368 break; 369 pd = pi->base; 370 j += pdi_mod; 371 } 372 } 373 j--; 374 snprintf(buf, sizeof buf, ".. %5lu not mine\n", j); 375 write(fd, buf, strlen(buf)); 376 } else if (pd[PI_OFF(j)] == MALLOC_FREE) { 377 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FREE;) { 378 if (!PI_OFF(++j)) { 379 if ((pi = pi->next) == NULL || 380 PD_IDX(pi->dirnum) != PI_IDX(j)) 381 break; 382 pd = pi->base; 383 j += pdi_mod; 384 } 385 } 386 j--; 387 snprintf(buf, sizeof buf, ".. %5lu free\n", j); 388 write(fd, buf, strlen(buf)); 389 } else if (pd[PI_OFF(j)] == MALLOC_FIRST) { 390 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FOLLOW;) { 391 if (!PI_OFF(++j)) { 392 if ((pi = pi->next) == NULL || 393 PD_IDX(pi->dirnum) != PI_IDX(j)) 394 break; 395 pd = pi->base; 396 j += pdi_mod; 397 } 398 } 399 j--; 400 snprintf(buf, sizeof buf, ".. %5lu in use\n", j); 401 write(fd, buf, strlen(buf)); 402 } else if (pd[PI_OFF(j)] < MALLOC_MAGIC) { 403 snprintf(buf, sizeof buf, "(%p)\n", pd[PI_OFF(j)]); 404 write(fd, buf, strlen(buf)); 405 } else { 406 snprintf(buf, sizeof buf, "%p %d (of %d) x %d @ %p --> %p\n", 407 pd[PI_OFF(j)], pd[PI_OFF(j)]->free, 408 pd[PI_OFF(j)]->total, pd[PI_OFF(j)]->size, 409 pd[PI_OFF(j)]->page, pd[PI_OFF(j)]->next); 410 write(fd, buf, strlen(buf)); 411 } 412 if (!PI_OFF(++j)) { 413 if ((pi = pi->next) == NULL) 414 break; 415 pd = pi->base; 416 j += (1 + PD_IDX(pi->dirnum) - PI_IDX(j)) * pdi_mod; 417 } 418 } 419 420 for (pf = free_list.next; pf; pf = pf->next) { 421 snprintf(buf, sizeof buf, "Free: @%p [%p...%p[ %ld ->%p <-%p\n", 422 pf, pf->page, (char *)pf->page + pf->size, 423 pf->size, pf->prev, pf->next); 424 write(fd, buf, strlen(buf)); 425 if (pf == pf->next) { 426 snprintf(buf, sizeof buf, "Free_list loops\n"); 427 write(fd, buf, strlen(buf)); 428 break; 429 } 430 } 431 432 /* print out various info */ 433 snprintf(buf, sizeof buf, "Minsize\t%lu\n", malloc_minsize); 434 write(fd, buf, strlen(buf)); 435 snprintf(buf, sizeof buf, "Maxsize\t%lu\n", malloc_maxsize); 436 write(fd, buf, strlen(buf)); 437 snprintf(buf, sizeof buf, "Pagesize\t%lu\n", malloc_pagesize); 438 write(fd, buf, strlen(buf)); 439 snprintf(buf, sizeof buf, "Pageshift\t%u\n", malloc_pageshift); 440 write(fd, buf, strlen(buf)); 441 snprintf(buf, sizeof buf, "In use\t%lu\n", (u_long) malloc_used); 442 write(fd, buf, strlen(buf)); 443 snprintf(buf, sizeof buf, "Guarded\t%lu\n", (u_long) malloc_guarded); 444 write(fd, buf, strlen(buf)); 445 } 446 #endif /* MALLOC_STATS */ 447 448 extern char *__progname; 449 450 static void 451 wrterror(const char *p) 452 { 453 #ifndef BUILDING_FOR_TOR 454 const char *q = " error: "; 455 struct iovec iov[5]; 456 457 iov[0].iov_base = __progname; 458 iov[0].iov_len = strlen(__progname); 459 iov[1].iov_base = (char*)malloc_func; 460 iov[1].iov_len = strlen(malloc_func); 461 iov[2].iov_base = (char*)q; 462 iov[2].iov_len = strlen(q); 463 iov[3].iov_base = (char*)p; 464 iov[3].iov_len = strlen(p); 465 iov[4].iov_base = (char*)"\n"; 466 iov[4].iov_len = 1; 467 writev(STDERR_FILENO, iov, 5); 468 #else 469 (void)p; 470 #endif 471 suicide = 1; 472 #ifdef MALLOC_STATS 473 if (malloc_stats) 474 malloc_dump(STDERR_FILENO); 475 #endif /* MALLOC_STATS */ 476 malloc_active--; 477 if (malloc_abort) 478 abort(); 479 } 480 481 static void 482 wrtwarning(const char *p) 483 { 484 #ifndef BUILDING_FOR_TOR 485 const char *q = " warning: "; 486 struct iovec iov[5]; 487 #endif 488 489 if (malloc_abort) 490 wrterror(p); 491 else if (malloc_silent) 492 return; 493 494 #ifndef BUILDING_FOR_TOR 495 iov[0].iov_base = __progname; 496 iov[0].iov_len = strlen(__progname); 497 iov[1].iov_base = (char*)malloc_func; 498 iov[1].iov_len = strlen(malloc_func); 499 iov[2].iov_base = (char*)q; 500 iov[2].iov_len = strlen(q); 501 iov[3].iov_base = (char*)p; 502 iov[3].iov_len = strlen(p); 503 iov[4].iov_base = (char*)"\n"; 504 iov[4].iov_len = 1; 505 506 (void) writev(STDERR_FILENO, iov, 5); 507 #else 508 (void)p; 509 #endif 510 } 511 512 #ifdef MALLOC_STATS 513 static void 514 malloc_exit(void) 515 { 516 char *q = "malloc() warning: Couldn't dump stats\n"; 517 int save_errno = errno, fd; 518 519 fd = open("malloc.out", O_RDWR|O_APPEND); 520 if (fd != -1) { 521 malloc_dump(fd); 522 close(fd); 523 } else 524 write(STDERR_FILENO, q, strlen(q)); 525 errno = save_errno; 526 } 527 #endif /* MALLOC_STATS */ 528 529 /* 530 * Allocate aligned mmaped chunk 531 */ 532 533 static void *MMAP_A(size_t pages, size_t alignment) 534 { 535 void *j, *p; 536 size_t first_size, rest, begin, end; 537 if (pages%malloc_pagesize != 0) 538 pages = pages - pages%malloc_pagesize + malloc_pagesize; 539 first_size = pages + alignment - malloc_pagesize; 540 p = MMAP(first_size); 541 rest = ((size_t)p) % alignment; 542 j = (rest == 0) ? p : (void*) ((size_t)p + alignment - rest); 543 begin = (size_t)j - (size_t)p; 544 if (begin != 0) munmap(p, begin); 545 end = (size_t)p + first_size - ((size_t)j + pages); 546 if(end != 0) munmap( (void*) ((size_t)j + pages), end); 547 548 return j; 549 } 550 551 552 /* 553 * Allocate a number of pages from the OS 554 */ 555 static void * 556 map_pages(size_t pages) 557 { 558 struct pdinfo *pi, *spi; 559 struct pginfo **pd; 560 u_long idx, pidx, lidx; 561 caddr_t result, tail; 562 u_long index, lindex; 563 void *pdregion = NULL; 564 size_t dirs, cnt; 565 566 pages <<= malloc_pageshift; 567 if (!align) 568 result = MMAP(pages + malloc_guard); 569 else { 570 result = MMAP_A(pages + malloc_guard, g_alignment); 571 } 572 if (result == MAP_FAILED) { 573 #ifdef MALLOC_EXTRA_SANITY 574 wrtwarning("(ES): map_pages fails"); 575 #endif /* MALLOC_EXTRA_SANITY */ 576 errno = ENOMEM; 577 return (NULL); 578 } 579 index = ptr2index(result); 580 tail = result + pages + malloc_guard; 581 lindex = ptr2index(tail) - 1; 582 if (malloc_guard) 583 mprotect(result + pages, malloc_guard, PROT_NONE); 584 585 pidx = PI_IDX(index); 586 lidx = PI_IDX(lindex); 587 588 if (tail > malloc_brk) { 589 malloc_brk = tail; 590 last_index = lindex; 591 } 592 593 dirs = lidx - pidx; 594 595 /* Insert directory pages, if needed. */ 596 if (pdir_lookup(index, &pi) != 0) 597 dirs++; 598 599 if (dirs > 0) { 600 pdregion = MMAP(malloc_pagesize * dirs); 601 if (pdregion == MAP_FAILED) { 602 munmap(result, tail - result); 603 #ifdef MALLOC_EXTRA_SANITY 604 wrtwarning("(ES): map_pages fails"); 605 #endif 606 errno = ENOMEM; 607 return (NULL); 608 } 609 } 610 611 cnt = 0; 612 for (idx = pidx, spi = pi; idx <= lidx; idx++) { 613 if (pi == NULL || PD_IDX(pi->dirnum) != idx) { 614 pd = (struct pginfo **)((char *)pdregion + 615 cnt * malloc_pagesize); 616 cnt++; 617 memset(pd, 0, malloc_pagesize); 618 pi = (struct pdinfo *) ((caddr_t) pd + pdi_off); 619 pi->base = pd; 620 pi->prev = spi; 621 pi->next = spi->next; 622 pi->dirnum = idx * (malloc_pagesize / 623 sizeof(struct pginfo *)); 624 625 if (spi->next != NULL) 626 spi->next->prev = pi; 627 spi->next = pi; 628 } 629 if (idx > pidx && idx < lidx) { 630 pi->dirnum += pdi_mod; 631 } else if (idx == pidx) { 632 if (pidx == lidx) { 633 pi->dirnum += (u_long)(tail - result) >> 634 malloc_pageshift; 635 } else { 636 pi->dirnum += pdi_mod - PI_OFF(index); 637 } 638 } else { 639 pi->dirnum += PI_OFF(ptr2index(tail - 1)) + 1; 640 } 641 #ifdef MALLOC_EXTRA_SANITY 642 if (PD_OFF(pi->dirnum) > pdi_mod || PD_IDX(pi->dirnum) > idx) { 643 wrterror("(ES): pages directory overflow"); 644 errno = EFAULT; 645 return (NULL); 646 } 647 #endif /* MALLOC_EXTRA_SANITY */ 648 if (idx == pidx && pi != last_dir) { 649 prev_dir = last_dir; 650 last_dir = pi; 651 } 652 spi = pi; 653 pi = spi->next; 654 } 655 #ifdef MALLOC_EXTRA_SANITY 656 if (cnt > dirs) 657 wrtwarning("(ES): cnt > dirs"); 658 #endif /* MALLOC_EXTRA_SANITY */ 659 if (cnt < dirs) 660 munmap((char *)pdregion + cnt * malloc_pagesize, 661 (dirs - cnt) * malloc_pagesize); 662 663 return (result); 664 } 665 666 /* 667 * Initialize the world 668 */ 669 static void 670 malloc_init(void) 671 { 672 char *p, b[64]; 673 int i, j, save_errno = errno; 674 675 _MALLOC_LOCK_INIT(); 676 677 #ifdef MALLOC_EXTRA_SANITY 678 malloc_junk = 1; 679 #endif /* MALLOC_EXTRA_SANITY */ 680 681 for (i = 0; i < 3; i++) { 682 switch (i) { 683 case 0: 684 j = (int) readlink("/etc/malloc.conf", b, sizeof b - 1); 685 if (j <= 0) 686 continue; 687 b[j] = '\0'; 688 p = b; 689 break; 690 case 1: 691 if (issetugid() == 0) 692 p = getenv("MALLOC_OPTIONS"); 693 else 694 continue; 695 break; 696 case 2: 697 p = malloc_options; 698 break; 699 default: 700 p = NULL; 701 } 702 703 for (; p != NULL && *p != '\0'; p++) { 704 switch (*p) { 705 case '>': 706 malloc_cache <<= 1; 707 break; 708 case '<': 709 malloc_cache >>= 1; 710 break; 711 case 'a': 712 malloc_abort = 0; 713 break; 714 case 'A': 715 malloc_abort = 1; 716 break; 717 #ifdef MALLOC_STATS 718 case 'd': 719 malloc_stats = 0; 720 break; 721 case 'D': 722 malloc_stats = 1; 723 break; 724 #endif /* MALLOC_STATS */ 725 case 'f': 726 malloc_freeprot = 0; 727 break; 728 case 'F': 729 malloc_freeprot = 1; 730 break; 731 case 'g': 732 malloc_guard = 0; 733 break; 734 case 'G': 735 malloc_guard = malloc_pagesize; 736 break; 737 case 'h': 738 malloc_hint = 0; 739 break; 740 case 'H': 741 malloc_hint = 1; 742 break; 743 case 'j': 744 malloc_junk = 0; 745 break; 746 case 'J': 747 malloc_junk = 1; 748 break; 749 case 'n': 750 malloc_silent = 0; 751 break; 752 case 'N': 753 malloc_silent = 1; 754 break; 755 case 'p': 756 malloc_ptrguard = 0; 757 break; 758 case 'P': 759 malloc_ptrguard = 1; 760 break; 761 case 'r': 762 malloc_realloc = 0; 763 break; 764 case 'R': 765 malloc_realloc = 1; 766 break; 767 #ifdef __FreeBSD__ 768 case 'u': 769 malloc_utrace = 0; 770 break; 771 case 'U': 772 malloc_utrace = 1; 773 break; 774 #endif /* __FreeBSD__ */ 775 case 'x': 776 malloc_xmalloc = 0; 777 break; 778 case 'X': 779 malloc_xmalloc = 1; 780 break; 781 case 'z': 782 malloc_zero = 0; 783 break; 784 case 'Z': 785 malloc_zero = 1; 786 break; 787 default: 788 j = malloc_abort; 789 malloc_abort = 0; 790 wrtwarning("unknown char in MALLOC_OPTIONS"); 791 malloc_abort = j; 792 break; 793 } 794 } 795 } 796 797 UTRACE(0, 0, 0); 798 799 /* 800 * We want junk in the entire allocation, and zero only in the part 801 * the user asked for. 802 */ 803 if (malloc_zero) 804 malloc_junk = 1; 805 806 #ifdef MALLOC_STATS 807 if (malloc_stats && (atexit(malloc_exit) == -1)) 808 wrtwarning("atexit(2) failed." 809 " Will not be able to dump malloc stats on exit"); 810 #endif /* MALLOC_STATS */ 811 812 if (malloc_pagesize != getpagesize()) { 813 wrterror("malloc() replacement compiled with a different " 814 "page size from what we're running with. Failing."); 815 errno = ENOMEM; 816 return; 817 } 818 819 /* Allocate one page for the page directory. */ 820 page_dir = (struct pginfo **)MMAP(malloc_pagesize); 821 822 if (page_dir == MAP_FAILED) { 823 wrterror("mmap(2) failed, check limits"); 824 errno = ENOMEM; 825 return; 826 } 827 pdi_off = (malloc_pagesize - sizeof(struct pdinfo)) & ~(malloc_minsize - 1); 828 pdi_mod = pdi_off / sizeof(struct pginfo *); 829 830 last_dir = (struct pdinfo *) ((caddr_t) page_dir + pdi_off); 831 last_dir->base = page_dir; 832 last_dir->prev = last_dir->next = NULL; 833 last_dir->dirnum = malloc_pageshift; 834 835 /* Been here, done that. */ 836 malloc_started++; 837 838 /* Recalculate the cache size in bytes, and make sure it's nonzero. */ 839 if (!malloc_cache) 840 malloc_cache++; 841 malloc_cache <<= malloc_pageshift; 842 errno = save_errno; 843 } 844 845 /* 846 * Allocate a number of complete pages 847 */ 848 static void * 849 malloc_pages(size_t size) 850 { 851 void *p, *delay_free = NULL, *tp; 852 size_t i; 853 struct pginfo **pd; 854 struct pdinfo *pi; 855 u_long pidx, index; 856 struct pgfree *pf; 857 858 size = pageround(size) + malloc_guard; 859 860 p = NULL; 861 /* Look for free pages before asking for more */ 862 if (!align) 863 for (pf = free_list.next; pf; pf = pf->next) { 864 865 #ifdef MALLOC_EXTRA_SANITY 866 if (pf->size & malloc_pagemask) { 867 wrterror("(ES): junk length entry on free_list"); 868 errno = EFAULT; 869 return (NULL); 870 } 871 if (!pf->size) { 872 wrterror("(ES): zero length entry on free_list"); 873 errno = EFAULT; 874 return (NULL); 875 } 876 if (pf->page > (pf->page + pf->size)) { 877 wrterror("(ES): sick entry on free_list"); 878 errno = EFAULT; 879 return (NULL); 880 } 881 if ((pi = pf->pdir) == NULL) { 882 wrterror("(ES): invalid page directory on free-list"); 883 errno = EFAULT; 884 return (NULL); 885 } 886 if ((pidx = PI_IDX(ptr2index(pf->page))) != PD_IDX(pi->dirnum)) { 887 wrterror("(ES): directory index mismatch on free-list"); 888 errno = EFAULT; 889 return (NULL); 890 } 891 pd = pi->base; 892 if (pd[PI_OFF(ptr2index(pf->page))] != MALLOC_FREE) { 893 wrterror("(ES): non-free first page on free-list"); 894 errno = EFAULT; 895 return (NULL); 896 } 897 pidx = PI_IDX(ptr2index((pf->page) + (pf->size)) - 1); 898 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx; 899 pi = pi->next) 900 ; 901 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 902 wrterror("(ES): last page not referenced in page directory"); 903 errno = EFAULT; 904 return (NULL); 905 } 906 pd = pi->base; 907 if (pd[PI_OFF(ptr2index((pf->page) + (pf->size)) - 1)] != MALLOC_FREE) { 908 wrterror("(ES): non-free last page on free-list"); 909 errno = EFAULT; 910 return (NULL); 911 } 912 #endif /* MALLOC_EXTRA_SANITY */ 913 914 if (pf->size < size) 915 continue; 916 917 if (pf->size == size) { 918 p = pf->page; 919 pi = pf->pdir; 920 if (pf->next != NULL) 921 pf->next->prev = pf->prev; 922 pf->prev->next = pf->next; 923 delay_free = pf; 924 break; 925 } 926 p = pf->page; 927 pf->page = (char *) pf->page + size; 928 pf->size -= size; 929 pidx = PI_IDX(ptr2index(pf->page)); 930 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx; 931 pi = pi->next) 932 ; 933 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 934 wrterror("(ES): hole in directories"); 935 errno = EFAULT; 936 return (NULL); 937 } 938 tp = pf->pdir; 939 pf->pdir = pi; 940 pi = tp; 941 break; 942 } 943 944 size -= malloc_guard; 945 946 #ifdef MALLOC_EXTRA_SANITY 947 if (p != NULL && pi != NULL) { 948 pidx = PD_IDX(pi->dirnum); 949 pd = pi->base; 950 } 951 if (p != NULL && pd[PI_OFF(ptr2index(p))] != MALLOC_FREE) { 952 wrterror("(ES): allocated non-free page on free-list"); 953 errno = EFAULT; 954 return (NULL); 955 } 956 #endif /* MALLOC_EXTRA_SANITY */ 957 958 if (p != NULL && (malloc_guard || malloc_freeprot)) 959 mprotect(p, size, PROT_READ | PROT_WRITE); 960 961 size >>= malloc_pageshift; 962 963 /* Map new pages */ 964 if (p == NULL) 965 p = map_pages(size); 966 967 if (p != NULL) { 968 index = ptr2index(p); 969 pidx = PI_IDX(index); 970 pdir_lookup(index, &pi); 971 #ifdef MALLOC_EXTRA_SANITY 972 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 973 wrterror("(ES): mapped pages not found in directory"); 974 errno = EFAULT; 975 return (NULL); 976 } 977 #endif /* MALLOC_EXTRA_SANITY */ 978 if (pi != last_dir) { 979 prev_dir = last_dir; 980 last_dir = pi; 981 } 982 pd = pi->base; 983 pd[PI_OFF(index)] = MALLOC_FIRST; 984 985 for (i = 1; i < size; i++) { 986 if (!PI_OFF(index + i)) { 987 pidx++; 988 pi = pi->next; 989 #ifdef MALLOC_EXTRA_SANITY 990 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 991 wrterror("(ES): hole in mapped pages directory"); 992 errno = EFAULT; 993 return (NULL); 994 } 995 #endif /* MALLOC_EXTRA_SANITY */ 996 pd = pi->base; 997 } 998 pd[PI_OFF(index + i)] = MALLOC_FOLLOW; 999 } 1000 if (malloc_guard) { 1001 if (!PI_OFF(index + i)) { 1002 pidx++; 1003 pi = pi->next; 1004 #ifdef MALLOC_EXTRA_SANITY 1005 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 1006 wrterror("(ES): hole in mapped pages directory"); 1007 errno = EFAULT; 1008 return (NULL); 1009 } 1010 #endif /* MALLOC_EXTRA_SANITY */ 1011 pd = pi->base; 1012 } 1013 pd[PI_OFF(index + i)] = MALLOC_FIRST; 1014 } 1015 1016 malloc_used += size << malloc_pageshift; 1017 malloc_guarded += malloc_guard; 1018 1019 if (malloc_junk) 1020 memset(p, SOME_JUNK, size << malloc_pageshift); 1021 } 1022 if (delay_free) { 1023 if (px == NULL) 1024 px = delay_free; 1025 else 1026 ifree(delay_free); 1027 } 1028 return (p); 1029 } 1030 1031 /* 1032 * Allocate a page of fragments 1033 */ 1034 1035 static __inline__ int 1036 malloc_make_chunks(int bits) 1037 { 1038 struct pginfo *bp, **pd; 1039 struct pdinfo *pi; 1040 #ifdef MALLOC_EXTRA_SANITY 1041 u_long pidx; 1042 #endif /* MALLOC_EXTRA_SANITY */ 1043 void *pp; 1044 long i, k; 1045 size_t l; 1046 1047 /* Allocate a new bucket */ 1048 pp = malloc_pages((size_t) malloc_pagesize); 1049 if (pp == NULL) 1050 return (0); 1051 1052 /* Find length of admin structure */ 1053 l = sizeof *bp - sizeof(u_long); 1054 l += sizeof(u_long) * 1055 (((malloc_pagesize >> bits) + MALLOC_BITS - 1) / MALLOC_BITS); 1056 1057 /* Don't waste more than two chunks on this */ 1058 1059 /* 1060 * If we are to allocate a memory protected page for the malloc(0) 1061 * case (when bits=0), it must be from a different page than the 1062 * pginfo page. 1063 * --> Treat it like the big chunk alloc, get a second data page. 1064 */ 1065 if (bits != 0 && (1UL << (bits)) <= l + l) { 1066 bp = (struct pginfo *) pp; 1067 } else { 1068 bp = (struct pginfo *) imalloc(l); 1069 if (bp == NULL) { 1070 ifree(pp); 1071 return (0); 1072 } 1073 } 1074 1075 /* memory protect the page allocated in the malloc(0) case */ 1076 if (bits == 0) { 1077 bp->size = 0; 1078 bp->shift = 1; 1079 i = malloc_minsize - 1; 1080 while (i >>= 1) 1081 bp->shift++; 1082 bp->total = bp->free = malloc_pagesize >> bp->shift; 1083 bp->page = pp; 1084 1085 k = mprotect(pp, malloc_pagesize, PROT_NONE); 1086 if (k < 0) { 1087 ifree(pp); 1088 ifree(bp); 1089 return (0); 1090 } 1091 } else { 1092 bp->size = (1UL << bits); 1093 bp->shift = bits; 1094 bp->total = bp->free = malloc_pagesize >> bits; 1095 bp->page = pp; 1096 } 1097 1098 /* set all valid bits in the bitmap */ 1099 k = bp->total; 1100 i = 0; 1101 1102 /* Do a bunch at a time */ 1103 for (; (k - i) >= MALLOC_BITS; i += MALLOC_BITS) 1104 bp->bits[i / MALLOC_BITS] = ~0UL; 1105 1106 for (; i < k; i++) 1107 bp->bits[i / MALLOC_BITS] |= 1UL << (i % MALLOC_BITS); 1108 1109 k = (long)l; 1110 if (bp == bp->page) { 1111 /* Mark the ones we stole for ourselves */ 1112 for (i = 0; k > 0; i++) { 1113 bp->bits[i / MALLOC_BITS] &= ~(1UL << (i % MALLOC_BITS)); 1114 bp->free--; 1115 bp->total--; 1116 k -= (1 << bits); 1117 } 1118 } 1119 /* MALLOC_LOCK */ 1120 1121 pdir_lookup(ptr2index(pp), &pi); 1122 #ifdef MALLOC_EXTRA_SANITY 1123 pidx = PI_IDX(ptr2index(pp)); 1124 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 1125 wrterror("(ES): mapped pages not found in directory"); 1126 errno = EFAULT; 1127 return (0); 1128 } 1129 #endif /* MALLOC_EXTRA_SANITY */ 1130 if (pi != last_dir) { 1131 prev_dir = last_dir; 1132 last_dir = pi; 1133 } 1134 pd = pi->base; 1135 pd[PI_OFF(ptr2index(pp))] = bp; 1136 1137 bp->next = page_dir[bits]; 1138 page_dir[bits] = bp; 1139 1140 /* MALLOC_UNLOCK */ 1141 return (1); 1142 } 1143 1144 /* 1145 * Allocate a fragment 1146 */ 1147 static void * 1148 malloc_bytes(size_t size) 1149 { 1150 int i, j; 1151 size_t k; 1152 u_long u, *lp; 1153 struct pginfo *bp; 1154 1155 /* Don't bother with anything less than this */ 1156 /* unless we have a malloc(0) requests */ 1157 if (size != 0 && size < malloc_minsize) 1158 size = malloc_minsize; 1159 1160 /* Find the right bucket */ 1161 if (size == 0) 1162 j = 0; 1163 else { 1164 size_t ii; 1165 j = 1; 1166 ii = size - 1; 1167 while (ii >>= 1) 1168 j++; 1169 } 1170 1171 /* If it's empty, make a page more of that size chunks */ 1172 if (page_dir[j] == NULL && !malloc_make_chunks(j)) 1173 return (NULL); 1174 1175 bp = page_dir[j]; 1176 1177 /* Find first word of bitmap which isn't empty */ 1178 for (lp = bp->bits; !*lp; lp++); 1179 1180 /* Find that bit, and tweak it */ 1181 u = 1; 1182 k = 0; 1183 while (!(*lp & u)) { 1184 u += u; 1185 k++; 1186 } 1187 1188 if (malloc_guard) { 1189 /* Walk to a random position. */ 1190 // i = arc4random() % bp->free; 1191 i = rand() % bp->free; 1192 while (i > 0) { 1193 u += u; 1194 k++; 1195 if (k >= MALLOC_BITS) { 1196 lp++; 1197 u = 1; 1198 k = 0; 1199 } 1200 #ifdef MALLOC_EXTRA_SANITY 1201 if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) { 1202 wrterror("chunk overflow"); 1203 errno = EFAULT; 1204 return (NULL); 1205 } 1206 #endif /* MALLOC_EXTRA_SANITY */ 1207 if (*lp & u) 1208 i--; 1209 } 1210 } 1211 *lp ^= u; 1212 1213 /* If there are no more free, remove from free-list */ 1214 if (!--bp->free) { 1215 page_dir[j] = bp->next; 1216 bp->next = NULL; 1217 } 1218 /* Adjust to the real offset of that chunk */ 1219 k += (lp - bp->bits) * MALLOC_BITS; 1220 k <<= bp->shift; 1221 1222 if (malloc_junk && bp->size != 0) 1223 memset((char *)bp->page + k, SOME_JUNK, (size_t)bp->size); 1224 1225 return ((u_char *) bp->page + k); 1226 } 1227 1228 /* 1229 * Magic so that malloc(sizeof(ptr)) is near the end of the page. 1230 */ 1231 #define PTR_GAP (malloc_pagesize - sizeof(void *)) 1232 #define PTR_SIZE (sizeof(void *)) 1233 #define PTR_ALIGNED(p) (((unsigned long)p & malloc_pagemask) == PTR_GAP) 1234 1235 /* 1236 * Allocate a piece of memory 1237 */ 1238 static void * 1239 imalloc(size_t size) 1240 { 1241 void *result; 1242 int ptralloc = 0; 1243 1244 if (!malloc_started) 1245 malloc_init(); 1246 1247 if (suicide) 1248 abort(); 1249 1250 /* does not matter if malloc_bytes fails */ 1251 if (px == NULL) 1252 px = malloc_bytes(sizeof *px); 1253 1254 if (malloc_ptrguard && size == PTR_SIZE) { 1255 ptralloc = 1; 1256 size = malloc_pagesize; 1257 } 1258 if (size > SIZE_MAX - malloc_pagesize) { /* Check for overflow */ 1259 result = NULL; 1260 errno = ENOMEM; 1261 } else if (size <= malloc_maxsize) 1262 result = malloc_bytes(size); 1263 else 1264 result = malloc_pages(size); 1265 1266 if (malloc_abort == 1 && result == NULL) 1267 wrterror("allocation failed"); 1268 1269 if (malloc_zero && result != NULL) 1270 memset(result, 0, size); 1271 1272 if (result && ptralloc) 1273 return ((char *) result + PTR_GAP); 1274 return (result); 1275 } 1276 1277 /* 1278 * Change the size of an allocation. 1279 */ 1280 static void * 1281 irealloc(void *ptr, size_t size) 1282 { 1283 void *p; 1284 size_t osize; 1285 u_long index, i; 1286 struct pginfo **mp; 1287 struct pginfo **pd; 1288 struct pdinfo *pi; 1289 #ifdef MALLOC_EXTRA_SANITY 1290 u_long pidx; 1291 #endif /* MALLOC_EXTRA_SANITY */ 1292 1293 if (suicide) 1294 abort(); 1295 1296 if (!malloc_started) { 1297 wrtwarning("malloc() has never been called"); 1298 return (NULL); 1299 } 1300 if (malloc_ptrguard && PTR_ALIGNED(ptr)) { 1301 if (size <= PTR_SIZE) 1302 return (ptr); 1303 1304 p = imalloc(size); 1305 if (p) 1306 memcpy(p, ptr, PTR_SIZE); 1307 ifree(ptr); 1308 return (p); 1309 } 1310 index = ptr2index(ptr); 1311 1312 if (index < malloc_pageshift) { 1313 wrtwarning("junk pointer, too low to make sense"); 1314 return (NULL); 1315 } 1316 if (index > last_index) { 1317 wrtwarning("junk pointer, too high to make sense"); 1318 return (NULL); 1319 } 1320 pdir_lookup(index, &pi); 1321 #ifdef MALLOC_EXTRA_SANITY 1322 pidx = PI_IDX(index); 1323 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 1324 wrterror("(ES): mapped pages not found in directory"); 1325 errno = EFAULT; 1326 return (NULL); 1327 } 1328 #endif /* MALLOC_EXTRA_SANITY */ 1329 if (pi != last_dir) { 1330 prev_dir = last_dir; 1331 last_dir = pi; 1332 } 1333 pd = pi->base; 1334 mp = &pd[PI_OFF(index)]; 1335 1336 if (*mp == MALLOC_FIRST) { /* Page allocation */ 1337 1338 /* Check the pointer */ 1339 if ((u_long) ptr & malloc_pagemask) { 1340 wrtwarning("modified (page-) pointer"); 1341 return (NULL); 1342 } 1343 /* Find the size in bytes */ 1344 i = index; 1345 if (!PI_OFF(++i)) { 1346 pi = pi->next; 1347 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i)) 1348 pi = NULL; 1349 if (pi != NULL) 1350 pd = pi->base; 1351 } 1352 for (osize = malloc_pagesize; 1353 pi != NULL && pd[PI_OFF(i)] == MALLOC_FOLLOW;) { 1354 osize += malloc_pagesize; 1355 if (!PI_OFF(++i)) { 1356 pi = pi->next; 1357 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i)) 1358 pi = NULL; 1359 if (pi != NULL) 1360 pd = pi->base; 1361 } 1362 } 1363 1364 if (!malloc_realloc && size <= osize && 1365 size > osize - malloc_pagesize) { 1366 if (malloc_junk) 1367 memset((char *)ptr + size, SOME_JUNK, osize - size); 1368 return (ptr); /* ..don't do anything else. */ 1369 } 1370 } else if (*mp >= MALLOC_MAGIC) { /* Chunk allocation */ 1371 1372 /* Check the pointer for sane values */ 1373 if ((u_long) ptr & ((1UL << ((*mp)->shift)) - 1)) { 1374 wrtwarning("modified (chunk-) pointer"); 1375 return (NULL); 1376 } 1377 /* Find the chunk index in the page */ 1378 i = ((u_long) ptr & malloc_pagemask) >> (*mp)->shift; 1379 1380 /* Verify that it isn't a free chunk already */ 1381 if ((*mp)->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) { 1382 wrtwarning("chunk is already free"); 1383 return (NULL); 1384 } 1385 osize = (*mp)->size; 1386 1387 if (!malloc_realloc && size <= osize && 1388 (size > osize / 2 || osize == malloc_minsize)) { 1389 if (malloc_junk) 1390 memset((char *) ptr + size, SOME_JUNK, osize - size); 1391 return (ptr); /* ..don't do anything else. */ 1392 } 1393 } else { 1394 wrtwarning("irealloc: pointer to wrong page"); 1395 return (NULL); 1396 } 1397 1398 p = imalloc(size); 1399 1400 if (p != NULL) { 1401 /* copy the lesser of the two sizes, and free the old one */ 1402 /* Don't move from/to 0 sized region !!! */ 1403 if (osize != 0 && size != 0) { 1404 if (osize < size) 1405 memcpy(p, ptr, osize); 1406 else 1407 memcpy(p, ptr, size); 1408 } 1409 ifree(ptr); 1410 } 1411 return (p); 1412 } 1413 1414 /* 1415 * Free a sequence of pages 1416 */ 1417 static __inline__ void 1418 free_pages(void *ptr, u_long index, struct pginfo * info) 1419 { 1420 u_long i, pidx, lidx; 1421 size_t l, cachesize = 0; 1422 struct pginfo **pd; 1423 struct pdinfo *pi, *spi; 1424 struct pgfree *pf, *pt = NULL; 1425 caddr_t tail; 1426 1427 if (info == MALLOC_FREE) { 1428 wrtwarning("page is already free"); 1429 return; 1430 } 1431 if (info != MALLOC_FIRST) { 1432 wrtwarning("free_pages: pointer to wrong page"); 1433 return; 1434 } 1435 if ((u_long) ptr & malloc_pagemask) { 1436 wrtwarning("modified (page-) pointer"); 1437 return; 1438 } 1439 /* Count how many pages and mark them free at the same time */ 1440 pidx = PI_IDX(index); 1441 pdir_lookup(index, &pi); 1442 #ifdef MALLOC_EXTRA_SANITY 1443 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 1444 wrterror("(ES): mapped pages not found in directory"); 1445 errno = EFAULT; 1446 return; 1447 } 1448 #endif /* MALLOC_EXTRA_SANITY */ 1449 1450 spi = pi; /* Save page index for start of region. */ 1451 1452 pd = pi->base; 1453 pd[PI_OFF(index)] = MALLOC_FREE; 1454 i = 1; 1455 if (!PI_OFF(index + i)) { 1456 pi = pi->next; 1457 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i)) 1458 pi = NULL; 1459 else 1460 pd = pi->base; 1461 } 1462 while (pi != NULL && pd[PI_OFF(index + i)] == MALLOC_FOLLOW) { 1463 pd[PI_OFF(index + i)] = MALLOC_FREE; 1464 i++; 1465 if (!PI_OFF(index + i)) { 1466 if ((pi = pi->next) == NULL || 1467 PD_IDX(pi->dirnum) != PI_IDX(index + i)) 1468 pi = NULL; 1469 else 1470 pd = pi->base; 1471 } 1472 } 1473 1474 l = i << malloc_pageshift; 1475 1476 if (malloc_junk) 1477 memset(ptr, SOME_JUNK, l); 1478 1479 malloc_used -= l; 1480 malloc_guarded -= malloc_guard; 1481 if (malloc_guard) { 1482 #ifdef MALLOC_EXTRA_SANITY 1483 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i)) { 1484 wrterror("(ES): hole in mapped pages directory"); 1485 errno = EFAULT; 1486 return; 1487 } 1488 #endif /* MALLOC_EXTRA_SANITY */ 1489 pd[PI_OFF(index + i)] = MALLOC_FREE; 1490 l += malloc_guard; 1491 } 1492 tail = (caddr_t)ptr + l; 1493 1494 if (malloc_hint) 1495 madvise(ptr, l, MADV_FREE); 1496 1497 if (malloc_freeprot) 1498 mprotect(ptr, l, PROT_NONE); 1499 1500 /* Add to free-list. */ 1501 if (px == NULL && (px = malloc_bytes(sizeof *px)) == NULL) 1502 goto not_return; 1503 px->page = ptr; 1504 px->pdir = spi; 1505 px->size = l; 1506 1507 if (free_list.next == NULL) { 1508 /* Nothing on free list, put this at head. */ 1509 px->next = NULL; 1510 px->prev = &free_list; 1511 free_list.next = px; 1512 pf = px; 1513 px = NULL; 1514 } else { 1515 /* 1516 * Find the right spot, leave pf pointing to the modified 1517 * entry. 1518 */ 1519 1520 /* Race ahead here, while calculating cache size. */ 1521 for (pf = free_list.next; 1522 (caddr_t)ptr > ((caddr_t)pf->page + pf->size) 1523 && pf->next != NULL; 1524 pf = pf->next) 1525 cachesize += pf->size; 1526 1527 /* Finish cache size calculation. */ 1528 pt = pf; 1529 while (pt) { 1530 cachesize += pt->size; 1531 pt = pt->next; 1532 } 1533 1534 if ((caddr_t)pf->page > tail) { 1535 /* Insert before entry */ 1536 px->next = pf; 1537 px->prev = pf->prev; 1538 pf->prev = px; 1539 px->prev->next = px; 1540 pf = px; 1541 px = NULL; 1542 } else if (((caddr_t)pf->page + pf->size) == ptr) { 1543 /* Append to the previous entry. */ 1544 cachesize -= pf->size; 1545 pf->size += l; 1546 if (pf->next != NULL && 1547 pf->next->page == ((caddr_t)pf->page + pf->size)) { 1548 /* And collapse the next too. */ 1549 pt = pf->next; 1550 pf->size += pt->size; 1551 pf->next = pt->next; 1552 if (pf->next != NULL) 1553 pf->next->prev = pf; 1554 } 1555 } else if (pf->page == tail) { 1556 /* Prepend to entry. */ 1557 cachesize -= pf->size; 1558 pf->size += l; 1559 pf->page = ptr; 1560 pf->pdir = spi; 1561 } else if (pf->next == NULL) { 1562 /* Append at tail of chain. */ 1563 px->next = NULL; 1564 px->prev = pf; 1565 pf->next = px; 1566 pf = px; 1567 px = NULL; 1568 } else { 1569 wrterror("freelist is destroyed"); 1570 errno = EFAULT; 1571 return; 1572 } 1573 } 1574 1575 if (pf->pdir != last_dir) { 1576 prev_dir = last_dir; 1577 last_dir = pf->pdir; 1578 } 1579 1580 /* Return something to OS ? */ 1581 if (pf->size > (malloc_cache - cachesize)) { 1582 1583 /* 1584 * Keep the cache intact. Notice that the '>' above guarantees that 1585 * the pf will always have at least one page afterwards. 1586 */ 1587 if (munmap((char *) pf->page + (malloc_cache - cachesize), 1588 pf->size - (malloc_cache - cachesize)) != 0) 1589 goto not_return; 1590 tail = (caddr_t)pf->page + pf->size; 1591 lidx = ptr2index(tail) - 1; 1592 pf->size = malloc_cache - cachesize; 1593 1594 index = ptr2index((caddr_t)pf->page + pf->size); 1595 1596 pidx = PI_IDX(index); 1597 if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) >= pidx) 1598 prev_dir = NULL; /* Will be wiped out below ! */ 1599 1600 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx; 1601 pi = pi->next) 1602 ; 1603 1604 spi = pi; 1605 if (pi != NULL && PD_IDX(pi->dirnum) == pidx) { 1606 pd = pi->base; 1607 1608 for (i = index; i <= lidx;) { 1609 if (pd[PI_OFF(i)] != MALLOC_NOT_MINE) { 1610 pd[PI_OFF(i)] = MALLOC_NOT_MINE; 1611 #ifdef MALLOC_EXTRA_SANITY 1612 if (!PD_OFF(pi->dirnum)) { 1613 wrterror("(ES): pages directory underflow"); 1614 errno = EFAULT; 1615 return; 1616 } 1617 #endif /* MALLOC_EXTRA_SANITY */ 1618 pi->dirnum--; 1619 } 1620 #ifdef MALLOC_EXTRA_SANITY 1621 else 1622 wrtwarning("(ES): page already unmapped"); 1623 #endif /* MALLOC_EXTRA_SANITY */ 1624 i++; 1625 if (!PI_OFF(i)) { 1626 /* 1627 * If no page in that dir, free 1628 * directory page. 1629 */ 1630 if (!PD_OFF(pi->dirnum)) { 1631 /* Remove from list. */ 1632 if (spi == pi) 1633 spi = pi->prev; 1634 if (pi->prev != NULL) 1635 pi->prev->next = pi->next; 1636 if (pi->next != NULL) 1637 pi->next->prev = pi->prev; 1638 pi = pi->next; 1639 munmap(pd, malloc_pagesize); 1640 } else 1641 pi = pi->next; 1642 if (pi == NULL || 1643 PD_IDX(pi->dirnum) != PI_IDX(i)) 1644 break; 1645 pd = pi->base; 1646 } 1647 } 1648 if (pi && !PD_OFF(pi->dirnum)) { 1649 /* Resulting page dir is now empty. */ 1650 /* Remove from list. */ 1651 if (spi == pi) /* Update spi only if first. */ 1652 spi = pi->prev; 1653 if (pi->prev != NULL) 1654 pi->prev->next = pi->next; 1655 if (pi->next != NULL) 1656 pi->next->prev = pi->prev; 1657 pi = pi->next; 1658 munmap(pd, malloc_pagesize); 1659 } 1660 } 1661 if (pi == NULL && malloc_brk == tail) { 1662 /* Resize down the malloc upper boundary. */ 1663 last_index = index - 1; 1664 malloc_brk = index2ptr(index); 1665 } 1666 1667 /* XXX: We could realloc/shrink the pagedir here I guess. */ 1668 if (pf->size == 0) { /* Remove from free-list as well. */ 1669 if (px) 1670 ifree(px); 1671 if ((px = pf->prev) != &free_list) { 1672 if (pi == NULL && last_index == (index - 1)) { 1673 if (spi == NULL) { 1674 malloc_brk = NULL; 1675 i = 11; 1676 } else { 1677 pd = spi->base; 1678 if (PD_IDX(spi->dirnum) < pidx) 1679 index = 1680 ((PD_IDX(spi->dirnum) + 1) * 1681 pdi_mod) - 1; 1682 for (pi = spi, i = index; 1683 pd[PI_OFF(i)] == MALLOC_NOT_MINE; 1684 i--) 1685 #ifdef MALLOC_EXTRA_SANITY 1686 if (!PI_OFF(i)) { 1687 pi = pi->prev; 1688 if (pi == NULL || i == 0) 1689 break; 1690 pd = pi->base; 1691 i = (PD_IDX(pi->dirnum) + 1) * pdi_mod; 1692 } 1693 #else /* !MALLOC_EXTRA_SANITY */ 1694 { 1695 } 1696 #endif /* MALLOC_EXTRA_SANITY */ 1697 malloc_brk = index2ptr(i + 1); 1698 } 1699 last_index = i; 1700 } 1701 if ((px->next = pf->next) != NULL) 1702 px->next->prev = px; 1703 } else { 1704 if ((free_list.next = pf->next) != NULL) 1705 free_list.next->prev = &free_list; 1706 } 1707 px = pf; 1708 last_dir = prev_dir; 1709 prev_dir = NULL; 1710 } 1711 } 1712 not_return: 1713 if (pt != NULL) 1714 ifree(pt); 1715 } 1716 1717 /* 1718 * Free a chunk, and possibly the page it's on, if the page becomes empty. 1719 */ 1720 1721 /* ARGSUSED */ 1722 static __inline__ void 1723 free_bytes(void *ptr, u_long index, struct pginfo * info) 1724 { 1725 struct pginfo **mp, **pd; 1726 struct pdinfo *pi; 1727 #ifdef MALLOC_EXTRA_SANITY 1728 u_long pidx; 1729 #endif /* MALLOC_EXTRA_SANITY */ 1730 void *vp; 1731 long i; 1732 (void) index; 1733 1734 /* Find the chunk number on the page */ 1735 i = ((u_long) ptr & malloc_pagemask) >> info->shift; 1736 1737 if ((u_long) ptr & ((1UL << (info->shift)) - 1)) { 1738 wrtwarning("modified (chunk-) pointer"); 1739 return; 1740 } 1741 if (info->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) { 1742 wrtwarning("chunk is already free"); 1743 return; 1744 } 1745 if (malloc_junk && info->size != 0) 1746 memset(ptr, SOME_JUNK, (size_t)info->size); 1747 1748 info->bits[i / MALLOC_BITS] |= 1UL << (i % MALLOC_BITS); 1749 info->free++; 1750 1751 if (info->size != 0) 1752 mp = page_dir + info->shift; 1753 else 1754 mp = page_dir; 1755 1756 if (info->free == 1) { 1757 /* Page became non-full */ 1758 1759 /* Insert in address order */ 1760 while (*mp != NULL && (*mp)->next != NULL && 1761 (*mp)->next->page < info->page) 1762 mp = &(*mp)->next; 1763 info->next = *mp; 1764 *mp = info; 1765 return; 1766 } 1767 if (info->free != info->total) 1768 return; 1769 1770 /* Find & remove this page in the queue */ 1771 while (*mp != info) { 1772 mp = &((*mp)->next); 1773 #ifdef MALLOC_EXTRA_SANITY 1774 if (!*mp) { 1775 wrterror("(ES): Not on queue"); 1776 errno = EFAULT; 1777 return; 1778 } 1779 #endif /* MALLOC_EXTRA_SANITY */ 1780 } 1781 *mp = info->next; 1782 1783 /* Free the page & the info structure if need be */ 1784 pdir_lookup(ptr2index(info->page), &pi); 1785 #ifdef MALLOC_EXTRA_SANITY 1786 pidx = PI_IDX(ptr2index(info->page)); 1787 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 1788 wrterror("(ES): mapped pages not found in directory"); 1789 errno = EFAULT; 1790 return; 1791 } 1792 #endif /* MALLOC_EXTRA_SANITY */ 1793 if (pi != last_dir) { 1794 prev_dir = last_dir; 1795 last_dir = pi; 1796 } 1797 pd = pi->base; 1798 pd[PI_OFF(ptr2index(info->page))] = MALLOC_FIRST; 1799 1800 /* If the page was mprotected, unprotect it before releasing it */ 1801 if (info->size == 0) 1802 mprotect(info->page, malloc_pagesize, PROT_READ | PROT_WRITE); 1803 1804 vp = info->page; /* Order is important ! */ 1805 if (vp != (void *) info) 1806 ifree(info); 1807 ifree(vp); 1808 } 1809 1810 static void 1811 ifree(void *ptr) 1812 { 1813 struct pginfo *info, **pd; 1814 u_long index; 1815 #ifdef MALLOC_EXTRA_SANITY 1816 u_long pidx; 1817 #endif /* MALLOC_EXTRA_SANITY */ 1818 struct pdinfo *pi; 1819 1820 if (!malloc_started) { 1821 wrtwarning("malloc() has never been called"); 1822 return; 1823 } 1824 /* If we're already sinking, don't make matters any worse. */ 1825 if (suicide) 1826 return; 1827 1828 if (malloc_ptrguard && PTR_ALIGNED(ptr)) 1829 ptr = (char *) ptr - PTR_GAP; 1830 1831 index = ptr2index(ptr); 1832 1833 if (index < malloc_pageshift) { 1834 warnx("(%p)", ptr); 1835 wrtwarning("ifree: junk pointer, too low to make sense"); 1836 return; 1837 } 1838 if (index > last_index) { 1839 warnx("(%p)", ptr); 1840 wrtwarning("ifree: junk pointer, too high to make sense"); 1841 return; 1842 } 1843 pdir_lookup(index, &pi); 1844 #ifdef MALLOC_EXTRA_SANITY 1845 pidx = PI_IDX(index); 1846 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 1847 wrterror("(ES): mapped pages not found in directory"); 1848 errno = EFAULT; 1849 return; 1850 } 1851 #endif /* MALLOC_EXTRA_SANITY */ 1852 if (pi != last_dir) { 1853 prev_dir = last_dir; 1854 last_dir = pi; 1855 } 1856 pd = pi->base; 1857 info = pd[PI_OFF(index)]; 1858 1859 if (info < MALLOC_MAGIC) 1860 free_pages(ptr, index, info); 1861 else 1862 free_bytes(ptr, index, info); 1863 1864 /* does not matter if malloc_bytes fails */ 1865 if (px == NULL) 1866 px = malloc_bytes(sizeof *px); 1867 1868 return; 1869 } 1870 1871 /* 1872 * Common function for handling recursion. Only 1873 * print the error message once, to avoid making the problem 1874 * potentially worse. 1875 */ 1876 static void 1877 malloc_recurse(void) 1878 { 1879 static int noprint; 1880 1881 if (noprint == 0) { 1882 noprint = 1; 1883 wrtwarning("recursive call"); 1884 } 1885 malloc_active--; 1886 _MALLOC_UNLOCK(); 1887 errno = EDEADLK; 1888 } 1889 1890 /* 1891 * These are the public exported interface routines. 1892 */ 1893 void * 1894 malloc(size_t size) 1895 { 1896 void *r; 1897 1898 if (!align) 1899 _MALLOC_LOCK(); 1900 malloc_func = " in malloc():"; 1901 if (malloc_active++) { 1902 malloc_recurse(); 1903 return (NULL); 1904 } 1905 r = imalloc(size); 1906 UTRACE(0, size, r); 1907 malloc_active--; 1908 if (!align) 1909 _MALLOC_UNLOCK(); 1910 if (malloc_xmalloc && r == NULL) { 1911 wrterror("out of memory"); 1912 errno = ENOMEM; 1913 } 1914 return (r); 1915 } 1916 1917 void 1918 free(void *ptr) 1919 { 1920 /* This is legal. XXX quick path */ 1921 if (ptr == NULL) 1922 return; 1923 1924 _MALLOC_LOCK(); 1925 malloc_func = " in free():"; 1926 if (malloc_active++) { 1927 malloc_recurse(); 1928 return; 1929 } 1930 ifree(ptr); 1931 UTRACE(ptr, 0, 0); 1932 malloc_active--; 1933 _MALLOC_UNLOCK(); 1934 return; 1935 } 1936 1937 void * 1938 realloc(void *ptr, size_t size) 1939 { 1940 void *r; 1941 1942 _MALLOC_LOCK(); 1943 malloc_func = " in realloc():"; 1944 if (malloc_active++) { 1945 malloc_recurse(); 1946 return (NULL); 1947 } 1948 1949 if (ptr == NULL) 1950 r = imalloc(size); 1951 else 1952 r = irealloc(ptr, size); 1953 1954 UTRACE(ptr, size, r); 1955 malloc_active--; 1956 _MALLOC_UNLOCK(); 1957 if (malloc_xmalloc && r == NULL) { 1958 wrterror("out of memory"); 1959 errno = ENOMEM; 1960 } 1961 return (r); 1962 } 1963 1964 void * 1965 calloc(size_t num, size_t size) 1966 { 1967 void *p; 1968 1969 if (num && SIZE_MAX / num < size) { 1970 fprintf(stderr,"OOOOPS"); 1971 errno = ENOMEM; 1972 return NULL; 1973 } 1974 size *= num; 1975 p = malloc(size); 1976 if (p) 1977 memset(p, 0, size); 1978 return(p); 1979 } 1980 1981 #ifndef BUILDING_FOR_TOR 1982 static int ispowerof2 (size_t a) { 1983 size_t b; 1984 for (b = 1ULL << (sizeof(size_t)*NBBY - 1); b > 1; b >>= 1) 1985 if (b == a) 1986 return 1; 1987 return 0; 1988 } 1989 #endif 1990 1991 #ifndef BUILDING_FOR_TOR 1992 int posix_memalign(void **memptr, size_t alignment, size_t size) 1993 { 1994 void *r; 1995 size_t max; 1996 if ((alignment < PTR_SIZE) || (alignment%PTR_SIZE != 0)) return EINVAL; 1997 if (!ispowerof2(alignment)) return EINVAL; 1998 if (alignment < malloc_minsize) alignment = malloc_minsize; 1999 max = alignment > size ? alignment : size; 2000 if (alignment <= malloc_pagesize) 2001 r = malloc(max); 2002 else { 2003 _MALLOC_LOCK(); 2004 align = 1; 2005 g_alignment = alignment; 2006 r = malloc(size); 2007 align=0; 2008 _MALLOC_UNLOCK(); 2009 } 2010 *memptr = r; 2011 if (!r) return ENOMEM; 2012 return 0; 2013 } 2014 2015 void *memalign(size_t boundary, size_t size) 2016 { 2017 void *r; 2018 posix_memalign(&r, boundary, size); 2019 return r; 2020 } 2021 2022 void *valloc(size_t size) 2023 { 2024 void *r; 2025 posix_memalign(&r, malloc_pagesize, size); 2026 return r; 2027 } 2028 #endif 2029 2030 size_t malloc_good_size(size_t size) 2031 { 2032 if (size == 0) { 2033 return 1; 2034 } else if (size <= malloc_maxsize) { 2035 int j; 2036 size_t ii; 2037 /* round up to the nearest power of 2, with same approach 2038 * as malloc_bytes() uses. */ 2039 j = 1; 2040 ii = size - 1; 2041 while (ii >>= 1) 2042 j++; 2043 return ((size_t)1) << j; 2044 } else { 2045 return pageround(size); 2046 } 2047 }