Fix last change
[jlayton/glibc.git] / malloc / hooks.c
1 /* Malloc implementation for multiple threads without lock contention.
2    Copyright (C) 2001-2009, 2011, 2012 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Wolfram Gloger <wg@malloc.de>, 2001.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public License as
8    published by the Free Software Foundation; either version 2.1 of the
9    License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; see the file COPYING.LIB.  If
18    not, see <http://www.gnu.org/licenses/>.  */
19
20 /* What to do if the standard debugging hooks are in place and a
21    corrupt pointer is detected: do nothing (0), print an error message
22    (1), or call abort() (2). */
23
24 /* Hooks for debugging versions.  The initial hooks just call the
25    initialization routine, then do the normal work. */
26
27 static void*
28 malloc_hook_ini(size_t sz, const __malloc_ptr_t caller)
29 {
30   __malloc_hook = NULL;
31   ptmalloc_init();
32   return __libc_malloc(sz);
33 }
34
35 static void*
36 realloc_hook_ini(void* ptr, size_t sz, const __malloc_ptr_t caller)
37 {
38   __malloc_hook = NULL;
39   __realloc_hook = NULL;
40   ptmalloc_init();
41   return __libc_realloc(ptr, sz);
42 }
43
44 static void*
45 memalign_hook_ini(size_t alignment, size_t sz, const __malloc_ptr_t caller)
46 {
47   __memalign_hook = NULL;
48   ptmalloc_init();
49   return __libc_memalign(alignment, sz);
50 }
51
52 /* Whether we are using malloc checking.  */
53 static int using_malloc_checking;
54
55 /* A flag that is set by malloc_set_state, to signal that malloc checking
56    must not be enabled on the request from the user (via the MALLOC_CHECK_
57    environment variable).  It is reset by __malloc_check_init to tell
58    malloc_set_state that the user has requested malloc checking.
59
60    The purpose of this flag is to make sure that malloc checking is not
61    enabled when the heap to be restored was constructed without malloc
62    checking, and thus does not contain the required magic bytes.
63    Otherwise the heap would be corrupted by calls to free and realloc.  If
64    it turns out that the heap was created with malloc checking and the
65    user has requested it malloc_set_state just calls __malloc_check_init
66    again to enable it.  On the other hand, reusing such a heap without
67    further malloc checking is safe.  */
68 static int disallow_malloc_check;
69
70 /* Activate a standard set of debugging hooks. */
71 void
72 __malloc_check_init()
73 {
74   if (disallow_malloc_check) {
75     disallow_malloc_check = 0;
76     return;
77   }
78   using_malloc_checking = 1;
79   __malloc_hook = malloc_check;
80   __free_hook = free_check;
81   __realloc_hook = realloc_check;
82   __memalign_hook = memalign_check;
83 }
84
85 /* A simple, standard set of debugging hooks.  Overhead is `only' one
86    byte per chunk; still this will catch most cases of double frees or
87    overruns.  The goal here is to avoid obscure crashes due to invalid
88    usage, unlike in the MALLOC_DEBUG code. */
89
90 #define MAGICBYTE(p) ( ( ((size_t)p >> 3) ^ ((size_t)p >> 11)) & 0xFF )
91
92 /* Instrument a chunk with overrun detector byte(s) and convert it
93    into a user pointer with requested size sz. */
94
95 static void*
96 internal_function
97 mem2mem_check(void *ptr, size_t sz)
98 {
99   mchunkptr p;
100   unsigned char* m_ptr = ptr;
101   size_t i;
102
103   if (!ptr)
104     return ptr;
105   p = mem2chunk(ptr);
106   for(i = chunksize(p) - (chunk_is_mmapped(p) ? 2*SIZE_SZ+1 : SIZE_SZ+1);
107       i > sz;
108       i -= 0xFF) {
109     if(i-sz < 0x100) {
110       m_ptr[i] = (unsigned char)(i-sz);
111       break;
112     }
113     m_ptr[i] = 0xFF;
114   }
115   m_ptr[sz] = MAGICBYTE(p);
116   return (void*)m_ptr;
117 }
118
119 /* Convert a pointer to be free()d or realloc()ed to a valid chunk
120    pointer.  If the provided pointer is not valid, return NULL. */
121
122 static mchunkptr
123 internal_function
124 mem2chunk_check(void* mem, unsigned char **magic_p)
125 {
126   mchunkptr p;
127   INTERNAL_SIZE_T sz, c;
128   unsigned char magic;
129
130   if(!aligned_OK(mem)) return NULL;
131   p = mem2chunk(mem);
132   if (!chunk_is_mmapped(p)) {
133     /* Must be a chunk in conventional heap memory. */
134     int contig = contiguous(&main_arena);
135     sz = chunksize(p);
136     if((contig &&
137         ((char*)p<mp_.sbrk_base ||
138          ((char*)p + sz)>=(mp_.sbrk_base+main_arena.system_mem) )) ||
139        sz<MINSIZE || sz&MALLOC_ALIGN_MASK || !inuse(p) ||
140        ( !prev_inuse(p) && (p->prev_size&MALLOC_ALIGN_MASK ||
141                             (contig && (char*)prev_chunk(p)<mp_.sbrk_base) ||
142                             next_chunk(prev_chunk(p))!=p) ))
143       return NULL;
144     magic = MAGICBYTE(p);
145     for(sz += SIZE_SZ-1; (c = ((unsigned char*)p)[sz]) != magic; sz -= c) {
146       if(c<=0 || sz<(c+2*SIZE_SZ)) return NULL;
147     }
148   } else {
149     unsigned long offset, page_mask = GLRO(dl_pagesize)-1;
150
151     /* mmap()ed chunks have MALLOC_ALIGNMENT or higher power-of-two
152        alignment relative to the beginning of a page.  Check this
153        first. */
154     offset = (unsigned long)mem & page_mask;
155     if((offset!=MALLOC_ALIGNMENT && offset!=0 && offset!=0x10 &&
156         offset!=0x20 && offset!=0x40 && offset!=0x80 && offset!=0x100 &&
157         offset!=0x200 && offset!=0x400 && offset!=0x800 && offset!=0x1000 &&
158         offset<0x2000) ||
159        !chunk_is_mmapped(p) || (p->size & PREV_INUSE) ||
160        ( (((unsigned long)p - p->prev_size) & page_mask) != 0 ) ||
161        ( (sz = chunksize(p)), ((p->prev_size + sz) & page_mask) != 0 ) )
162       return NULL;
163     magic = MAGICBYTE(p);
164     for(sz -= 1; (c = ((unsigned char*)p)[sz]) != magic; sz -= c) {
165       if(c<=0 || sz<(c+2*SIZE_SZ)) return NULL;
166     }
167   }
168   ((unsigned char*)p)[sz] ^= 0xFF;
169   if (magic_p)
170     *magic_p = (unsigned char *)p + sz;
171   return p;
172 }
173
174 /* Check for corruption of the top chunk, and try to recover if
175    necessary. */
176
177 static int
178 internal_function
179 top_check(void)
180 {
181   mchunkptr t = top(&main_arena);
182   char* brk, * new_brk;
183   INTERNAL_SIZE_T front_misalign, sbrk_size;
184   unsigned long pagesz = GLRO(dl_pagesize);
185
186   if (t == initial_top(&main_arena) ||
187       (!chunk_is_mmapped(t) &&
188        chunksize(t)>=MINSIZE &&
189        prev_inuse(t) &&
190        (!contiguous(&main_arena) ||
191         (char*)t + chunksize(t) == mp_.sbrk_base + main_arena.system_mem)))
192     return 0;
193
194   malloc_printerr (check_action, "malloc: top chunk is corrupt", t);
195
196   /* Try to set up a new top chunk. */
197   brk = MORECORE(0);
198   front_misalign = (unsigned long)chunk2mem(brk) & MALLOC_ALIGN_MASK;
199   if (front_misalign > 0)
200     front_misalign = MALLOC_ALIGNMENT - front_misalign;
201   sbrk_size = front_misalign + mp_.top_pad + MINSIZE;
202   sbrk_size += pagesz - ((unsigned long)(brk + sbrk_size) & (pagesz - 1));
203   new_brk = (char*)(MORECORE (sbrk_size));
204   if (new_brk == (char*)(MORECORE_FAILURE))
205     {
206       __set_errno (ENOMEM);
207       return -1;
208     }
209   /* Call the `morecore' hook if necessary.  */
210   void (*hook) (void) = force_reg (__after_morecore_hook);
211   if (hook)
212     (*hook) ();
213   main_arena.system_mem = (new_brk - mp_.sbrk_base) + sbrk_size;
214
215   top(&main_arena) = (mchunkptr)(brk + front_misalign);
216   set_head(top(&main_arena), (sbrk_size - front_misalign) | PREV_INUSE);
217
218   return 0;
219 }
220
221 static void*
222 malloc_check(size_t sz, const void *caller)
223 {
224   void *victim;
225
226   if (sz+1 == 0) {
227     __set_errno (ENOMEM);
228     return NULL;
229   }
230
231   (void)mutex_lock(&main_arena.mutex);
232   victim = (top_check() >= 0) ? _int_malloc(&main_arena, sz+1) : NULL;
233   (void)mutex_unlock(&main_arena.mutex);
234   return mem2mem_check(victim, sz);
235 }
236
237 static void
238 free_check(void* mem, const void *caller)
239 {
240   mchunkptr p;
241
242   if(!mem) return;
243   (void)mutex_lock(&main_arena.mutex);
244   p = mem2chunk_check(mem, NULL);
245   if(!p) {
246     (void)mutex_unlock(&main_arena.mutex);
247
248     malloc_printerr(check_action, "free(): invalid pointer", mem);
249     return;
250   }
251   if (chunk_is_mmapped(p)) {
252     (void)mutex_unlock(&main_arena.mutex);
253     munmap_chunk(p);
254     return;
255   }
256   _int_free(&main_arena, p, 1);
257   (void)mutex_unlock(&main_arena.mutex);
258 }
259
260 static void*
261 realloc_check(void* oldmem, size_t bytes, const void *caller)
262 {
263   INTERNAL_SIZE_T nb;
264   void* newmem = 0;
265   unsigned char *magic_p;
266
267   if (bytes+1 == 0) {
268     __set_errno (ENOMEM);
269     return NULL;
270   }
271   if (oldmem == 0) return malloc_check(bytes, NULL);
272   if (bytes == 0) {
273     free_check (oldmem, NULL);
274     return NULL;
275   }
276   (void)mutex_lock(&main_arena.mutex);
277   const mchunkptr oldp = mem2chunk_check(oldmem, &magic_p);
278   (void)mutex_unlock(&main_arena.mutex);
279   if(!oldp) {
280     malloc_printerr(check_action, "realloc(): invalid pointer", oldmem);
281     return malloc_check(bytes, NULL);
282   }
283   const INTERNAL_SIZE_T oldsize = chunksize(oldp);
284
285   checked_request2size(bytes+1, nb);
286   (void)mutex_lock(&main_arena.mutex);
287
288   if (chunk_is_mmapped(oldp)) {
289 #if HAVE_MREMAP
290     mchunkptr newp = mremap_chunk(oldp, nb);
291     if(newp)
292       newmem = chunk2mem(newp);
293     else
294 #endif
295     {
296       /* Note the extra SIZE_SZ overhead. */
297       if(oldsize - SIZE_SZ >= nb)
298         newmem = oldmem; /* do nothing */
299       else {
300         /* Must alloc, copy, free. */
301         if (top_check() >= 0)
302           newmem = _int_malloc(&main_arena, bytes+1);
303         if (newmem) {
304           MALLOC_COPY(newmem, oldmem, oldsize - 2*SIZE_SZ);
305           munmap_chunk(oldp);
306         }
307       }
308     }
309   } else {
310     if (top_check() >= 0) {
311       INTERNAL_SIZE_T nb;
312       checked_request2size(bytes + 1, nb);
313       newmem = _int_realloc(&main_arena, oldp, oldsize, nb);
314     }
315   }
316
317   /* mem2chunk_check changed the magic byte in the old chunk.
318      If newmem is NULL, then the old chunk will still be used though,
319      so we need to invert that change here.  */
320   if (newmem == NULL) *magic_p ^= 0xFF;
321
322   (void)mutex_unlock(&main_arena.mutex);
323
324   return mem2mem_check(newmem, bytes);
325 }
326
327 static void*
328 memalign_check(size_t alignment, size_t bytes, const void *caller)
329 {
330   void* mem;
331
332   if (alignment <= MALLOC_ALIGNMENT) return malloc_check(bytes, NULL);
333   if (alignment <  MINSIZE) alignment = MINSIZE;
334
335   if (bytes+1 == 0) {
336     __set_errno (ENOMEM);
337     return NULL;
338   }
339   (void)mutex_lock(&main_arena.mutex);
340   mem = (top_check() >= 0) ? _int_memalign(&main_arena, alignment, bytes+1) :
341     NULL;
342   (void)mutex_unlock(&main_arena.mutex);
343   return mem2mem_check(mem, bytes);
344 }
345
346
347 /* Get/set state: malloc_get_state() records the current state of all
348    malloc variables (_except_ for the actual heap contents and `hook'
349    function pointers) in a system dependent, opaque data structure.
350    This data structure is dynamically allocated and can be free()d
351    after use.  malloc_set_state() restores the state of all malloc
352    variables to the previously obtained state.  This is especially
353    useful when using this malloc as part of a shared library, and when
354    the heap contents are saved/restored via some other method.  The
355    primary example for this is GNU Emacs with its `dumping' procedure.
356    `Hook' function pointers are never saved or restored by these
357    functions, with two exceptions: If malloc checking was in use when
358    malloc_get_state() was called, then malloc_set_state() calls
359    __malloc_check_init() if possible; if malloc checking was not in
360    use in the recorded state but the user requested malloc checking,
361    then the hooks are reset to 0.  */
362
363 #define MALLOC_STATE_MAGIC   0x444c4541l
364 #define MALLOC_STATE_VERSION (0*0x100l + 4l) /* major*0x100 + minor */
365
366 struct malloc_save_state {
367   long          magic;
368   long          version;
369   mbinptr       av[NBINS * 2 + 2];
370   char*         sbrk_base;
371   int           sbrked_mem_bytes;
372   unsigned long trim_threshold;
373   unsigned long top_pad;
374   unsigned int  n_mmaps_max;
375   unsigned long mmap_threshold;
376   int           check_action;
377   unsigned long max_sbrked_mem;
378   unsigned long max_total_mem;
379   unsigned int  n_mmaps;
380   unsigned int  max_n_mmaps;
381   unsigned long mmapped_mem;
382   unsigned long max_mmapped_mem;
383   int           using_malloc_checking;
384   unsigned long max_fast;
385   unsigned long arena_test;
386   unsigned long arena_max;
387   unsigned long narenas;
388 };
389
390 void*
391 __malloc_get_state(void)
392 {
393   struct malloc_save_state* ms;
394   int i;
395   mbinptr b;
396
397   ms = (struct malloc_save_state*)__libc_malloc(sizeof(*ms));
398   if (!ms)
399     return 0;
400   (void)mutex_lock(&main_arena.mutex);
401   malloc_consolidate(&main_arena);
402   ms->magic = MALLOC_STATE_MAGIC;
403   ms->version = MALLOC_STATE_VERSION;
404   ms->av[0] = 0;
405   ms->av[1] = 0; /* used to be binblocks, now no longer used */
406   ms->av[2] = top(&main_arena);
407   ms->av[3] = 0; /* used to be undefined */
408   for(i=1; i<NBINS; i++) {
409     b = bin_at(&main_arena, i);
410     if(first(b) == b)
411       ms->av[2*i+2] = ms->av[2*i+3] = 0; /* empty bin */
412     else {
413       ms->av[2*i+2] = first(b);
414       ms->av[2*i+3] = last(b);
415     }
416   }
417   ms->sbrk_base = mp_.sbrk_base;
418   ms->sbrked_mem_bytes = main_arena.system_mem;
419   ms->trim_threshold = mp_.trim_threshold;
420   ms->top_pad = mp_.top_pad;
421   ms->n_mmaps_max = mp_.n_mmaps_max;
422   ms->mmap_threshold = mp_.mmap_threshold;
423   ms->check_action = check_action;
424   ms->max_sbrked_mem = main_arena.max_system_mem;
425   ms->max_total_mem = 0;
426   ms->n_mmaps = mp_.n_mmaps;
427   ms->max_n_mmaps = mp_.max_n_mmaps;
428   ms->mmapped_mem = mp_.mmapped_mem;
429   ms->max_mmapped_mem = mp_.max_mmapped_mem;
430   ms->using_malloc_checking = using_malloc_checking;
431   ms->max_fast = get_max_fast();
432 #ifdef PER_THREAD
433   ms->arena_test = mp_.arena_test;
434   ms->arena_max = mp_.arena_max;
435   ms->narenas = narenas;
436 #endif
437   (void)mutex_unlock(&main_arena.mutex);
438   return (void*)ms;
439 }
440
441 int
442 __malloc_set_state(void* msptr)
443 {
444   struct malloc_save_state* ms = (struct malloc_save_state*)msptr;
445   size_t i;
446   mbinptr b;
447
448   disallow_malloc_check = 1;
449   ptmalloc_init();
450   if(ms->magic != MALLOC_STATE_MAGIC) return -1;
451   /* Must fail if the major version is too high. */
452   if((ms->version & ~0xffl) > (MALLOC_STATE_VERSION & ~0xffl)) return -2;
453   (void)mutex_lock(&main_arena.mutex);
454   /* There are no fastchunks.  */
455   clear_fastchunks(&main_arena);
456   if (ms->version >= 4)
457     set_max_fast(ms->max_fast);
458   else
459     set_max_fast(64);   /* 64 used to be the value we always used.  */
460   for (i=0; i<NFASTBINS; ++i)
461     fastbin (&main_arena, i) = 0;
462   for (i=0; i<BINMAPSIZE; ++i)
463     main_arena.binmap[i] = 0;
464   top(&main_arena) = ms->av[2];
465   main_arena.last_remainder = 0;
466   for(i=1; i<NBINS; i++) {
467     b = bin_at(&main_arena, i);
468     if(ms->av[2*i+2] == 0) {
469       assert(ms->av[2*i+3] == 0);
470       first(b) = last(b) = b;
471     } else {
472       if(ms->version >= 3 &&
473          (i<NSMALLBINS || (largebin_index(chunksize(ms->av[2*i+2]))==i &&
474                            largebin_index(chunksize(ms->av[2*i+3]))==i))) {
475         first(b) = ms->av[2*i+2];
476         last(b) = ms->av[2*i+3];
477         /* Make sure the links to the bins within the heap are correct.  */
478         first(b)->bk = b;
479         last(b)->fd = b;
480         /* Set bit in binblocks.  */
481         mark_bin(&main_arena, i);
482       } else {
483         /* Oops, index computation from chunksize must have changed.
484            Link the whole list into unsorted_chunks.  */
485         first(b) = last(b) = b;
486         b = unsorted_chunks(&main_arena);
487         ms->av[2*i+2]->bk = b;
488         ms->av[2*i+3]->fd = b->fd;
489         b->fd->bk = ms->av[2*i+3];
490         b->fd = ms->av[2*i+2];
491       }
492     }
493   }
494   if (ms->version < 3) {
495     /* Clear fd_nextsize and bk_nextsize fields.  */
496     b = unsorted_chunks(&main_arena)->fd;
497     while (b != unsorted_chunks(&main_arena)) {
498       if (!in_smallbin_range(chunksize(b))) {
499         b->fd_nextsize = NULL;
500         b->bk_nextsize = NULL;
501       }
502       b = b->fd;
503     }
504   }
505   mp_.sbrk_base = ms->sbrk_base;
506   main_arena.system_mem = ms->sbrked_mem_bytes;
507   mp_.trim_threshold = ms->trim_threshold;
508   mp_.top_pad = ms->top_pad;
509   mp_.n_mmaps_max = ms->n_mmaps_max;
510   mp_.mmap_threshold = ms->mmap_threshold;
511   check_action = ms->check_action;
512   main_arena.max_system_mem = ms->max_sbrked_mem;
513   mp_.n_mmaps = ms->n_mmaps;
514   mp_.max_n_mmaps = ms->max_n_mmaps;
515   mp_.mmapped_mem = ms->mmapped_mem;
516   mp_.max_mmapped_mem = ms->max_mmapped_mem;
517   /* add version-dependent code here */
518   if (ms->version >= 1) {
519     /* Check whether it is safe to enable malloc checking, or whether
520        it is necessary to disable it.  */
521     if (ms->using_malloc_checking && !using_malloc_checking &&
522         !disallow_malloc_check)
523       __malloc_check_init ();
524     else if (!ms->using_malloc_checking && using_malloc_checking) {
525       __malloc_hook = NULL;
526       __free_hook = NULL;
527       __realloc_hook = NULL;
528       __memalign_hook = NULL;
529       using_malloc_checking = 0;
530     }
531   }
532   if (ms->version >= 4) {
533 #ifdef PER_THREAD
534     mp_.arena_test = ms->arena_test;
535     mp_.arena_max = ms->arena_max;
536     narenas = ms->narenas;
537 #endif
538   }
539   check_malloc_state(&main_arena);
540
541   (void)mutex_unlock(&main_arena.mutex);
542   return 0;
543 }
544
545 /*
546  * Local variables:
547  * c-basic-offset: 2
548  * End:
549  */