📄 hooks.c
字号:
/* Malloc implementation for multiple threads without lock contention. Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Wolfram Gloger <wg@malloc.de>, 2001. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* $Id: hooks.c,v 1.12 2004/11/05 14:42:32 wg Exp $ */#ifndef DEFAULT_CHECK_ACTION#define DEFAULT_CHECK_ACTION 1#endif/* What to do if the standard debugging hooks are in place and a corrupt pointer is detected: do nothing (0), print an error message (1), or call abort() (2). *//* Hooks for debugging versions. The initial hooks just call the initialization routine, then do the normal work. */#if !(USE_STARTER & 2)static Void_t*#if __STD_Cmalloc_hook_ini(size_t sz, const __malloc_ptr_t caller)#elsemalloc_hook_ini(sz, caller) size_t sz; const __malloc_ptr_t caller;#endif{ __malloc_hook = NULL; ptmalloc_init(); return public_mALLOc(sz);}static Void_t*#if __STD_Crealloc_hook_ini(Void_t* ptr, size_t sz, const __malloc_ptr_t caller)#elserealloc_hook_ini(ptr, sz, caller) Void_t* ptr; size_t sz; const __malloc_ptr_t caller;#endif{ __malloc_hook = NULL; __realloc_hook = NULL; ptmalloc_init(); return public_rEALLOc(ptr, sz);}static Void_t*#if __STD_Cmemalign_hook_ini(size_t alignment, size_t sz, const __malloc_ptr_t caller)#elsememalign_hook_ini(alignment, sz, caller) size_t alignment; size_t sz; const __malloc_ptr_t caller;#endif{ __memalign_hook = NULL; ptmalloc_init(); return public_mEMALIGn(alignment, sz);}#endif /* !(USE_STARTER & 2) */static int check_action = DEFAULT_CHECK_ACTION;/* Whether we are using malloc checking. */static int using_malloc_checking;/* A flag that is set by malloc_set_state, to signal that malloc checking must not be enabled on the request from the user (via the MALLOC_CHECK_ environment variable). It is reset by __malloc_check_init to tell malloc_set_state that the user has requested malloc checking. The purpose of this flag is to make sure that malloc checking is not enabled when the heap to be restored was constructed without malloc checking, and thus does not contain the required magic bytes. Otherwise the heap would be corrupted by calls to free and realloc. If it turns out that the heap was created with malloc checking and the user has requested it malloc_set_state just calls __malloc_check_init again to enable it. On the other hand, reusing such a heap without further malloc checking is safe. */static int disallow_malloc_check;/* Activate a standard set of debugging hooks. */void__malloc_check_init(){ if (disallow_malloc_check) { disallow_malloc_check = 0; return; } using_malloc_checking = 1; __malloc_hook = malloc_check; __free_hook = free_check; __realloc_hook = realloc_check; __memalign_hook = memalign_check; if(check_action & 1) fprintf(stderr, "malloc: using debugging hooks\n");}/* A simple, standard set of debugging hooks. Overhead is `only' one byte per chunk; still this will catch most cases of double frees or overruns. The goal here is to avoid obscure crashes due to invalid usage, unlike in the MALLOC_DEBUG code. */#define MAGICBYTE(p) ( ( ((size_t)p >> 3) ^ ((size_t)p >> 11)) & 0xFF )/* Instrument a chunk with overrun detector byte(s) and convert it into a user pointer with requested size sz. */static Void_t*internal_function#if __STD_Cmem2mem_check(Void_t *ptr, size_t sz)#elsemem2mem_check(ptr, sz) Void_t *ptr; size_t sz;#endif{ mchunkptr p; unsigned char* m_ptr = (unsigned char*)BOUNDED_N(ptr, sz); size_t i; if (!ptr) return ptr; p = mem2chunk(ptr); for(i = chunksize(p) - (chunk_is_mmapped(p) ? 2*SIZE_SZ+1 : SIZE_SZ+1); i > sz; i -= 0xFF) { if(i-sz < 0x100) { m_ptr[i] = (unsigned char)(i-sz); break; } m_ptr[i] = 0xFF; } m_ptr[sz] = MAGICBYTE(p); return (Void_t*)m_ptr;}/* Convert a pointer to be free()d or realloc()ed to a valid chunk pointer. If the provided pointer is not valid, return NULL. */static mchunkptrinternal_function#if __STD_Cmem2chunk_check(Void_t* mem)#elsemem2chunk_check(mem) Void_t* mem;#endif{ mchunkptr p; INTERNAL_SIZE_T sz, c; unsigned char magic; if(!aligned_OK(mem)) return NULL; p = mem2chunk(mem); if (!chunk_is_mmapped(p)) { /* Must be a chunk in conventional heap memory. */ int contig = contiguous(&main_arena); sz = chunksize(p); if((contig && ((char*)p<mp_.sbrk_base || ((char*)p + sz)>=(mp_.sbrk_base+main_arena.system_mem) )) || sz<MINSIZE || sz&MALLOC_ALIGN_MASK || !inuse(p) || ( !prev_inuse(p) && (p->prev_size&MALLOC_ALIGN_MASK || (contig && (char*)prev_chunk(p)<mp_.sbrk_base) || next_chunk(prev_chunk(p))!=p) )) return NULL; magic = MAGICBYTE(p); for(sz += SIZE_SZ-1; (c = ((unsigned char*)p)[sz]) != magic; sz -= c) { if(c<=0 || sz<(c+2*SIZE_SZ)) return NULL; } ((unsigned char*)p)[sz] ^= 0xFF; } else { unsigned long offset, page_mask = malloc_getpagesize-1; /* mmap()ed chunks have MALLOC_ALIGNMENT or higher power-of-two alignment relative to the beginning of a page. Check this first. */ offset = (unsigned long)mem & page_mask; if((offset!=MALLOC_ALIGNMENT && offset!=0 && offset!=0x10 && offset!=0x20 && offset!=0x40 && offset!=0x80 && offset!=0x100 && offset!=0x200 && offset!=0x400 && offset!=0x800 && offset!=0x1000 && offset<0x2000) || !chunk_is_mmapped(p) || (p->size & PREV_INUSE) || ( (((unsigned long)p - p->prev_size) & page_mask) != 0 ) || ( (sz = chunksize(p)), ((p->prev_size + sz) & page_mask) != 0 ) ) return NULL; magic = MAGICBYTE(p); for(sz -= 1; (c = ((unsigned char*)p)[sz]) != magic; sz -= c) { if(c<=0 || sz<(c+2*SIZE_SZ)) return NULL; } ((unsigned char*)p)[sz] ^= 0xFF; } return p;}/* Check for corruption of the top chunk, and try to recover if necessary. */static intinternal_function#if __STD_Ctop_check(void)#elsetop_check()#endif{ mchunkptr t = top(&main_arena); char* brk, * new_brk; INTERNAL_SIZE_T front_misalign, sbrk_size; unsigned long pagesz = malloc_getpagesize; if (t == initial_top(&main_arena) || (!chunk_is_mmapped(t) && chunksize(t)>=MINSIZE && prev_inuse(t) && (!contiguous(&main_arena) || (char*)t + chunksize(t) == mp_.sbrk_base + main_arena.system_mem))) return 0; if(check_action & 1) fprintf(stderr, "malloc: top chunk is corrupt\n"); if(check_action & 2) abort(); /* Try to set up a new top chunk. */ brk = MORECORE(0); front_misalign = (unsigned long)chunk2mem(brk) & MALLOC_ALIGN_MASK; if (front_misalign > 0) front_misalign = MALLOC_ALIGNMENT - front_misalign; sbrk_size = front_misalign + mp_.top_pad + MINSIZE; sbrk_size += pagesz - ((unsigned long)(brk + sbrk_size) & (pagesz - 1)); new_brk = (char*)(MORECORE (sbrk_size)); if (new_brk == (char*)(MORECORE_FAILURE)) return -1; /* Call the `morecore' hook if necessary. */ if (__after_morecore_hook) (*__after_morecore_hook) (); main_arena.system_mem = (new_brk - mp_.sbrk_base) + sbrk_size; top(&main_arena) = (mchunkptr)(brk + front_misalign); set_head(top(&main_arena), (sbrk_size - front_misalign) | PREV_INUSE); return 0;}static Void_t*#if __STD_Cmalloc_check(size_t sz, const Void_t *caller)#elsemalloc_check(sz, caller) size_t sz; const Void_t *caller;#endif{ Void_t *victim; (void)mutex_lock(&main_arena.mutex); victim = (top_check() >= 0) ? _int_malloc(&main_arena, sz+1) : NULL; (void)mutex_unlock(&main_arena.mutex); return mem2mem_check(victim, sz);}static void#if __STD_Cfree_check(Void_t* mem, const Void_t *caller)#elsefree_check(mem, caller) Void_t* mem; const Void_t *caller;#endif{ mchunkptr p; if(!mem) return; (void)mutex_lock(&main_arena.mutex); p = mem2chunk_check(mem); if(!p) { (void)mutex_unlock(&main_arena.mutex); if(check_action & 1) fprintf(stderr, "free(): invalid pointer %p!\n", mem); if(check_action & 2) abort(); return; }#if HAVE_MMAP if (chunk_is_mmapped(p)) { (void)mutex_unlock(&main_arena.mutex); munmap_chunk(p); return; }#endif#if 0 /* Erase freed memory. */ memset(mem, 0, chunksize(p) - (SIZE_SZ+1));#endif _int_free(&main_arena, mem); (void)mutex_unlock(&main_arena.mutex);}static Void_t*#if __STD_Crealloc_check(Void_t* oldmem, size_t bytes, const Void_t *caller)#elserealloc_check(oldmem, bytes, caller) Void_t* oldmem; size_t bytes; const Void_t *caller;#endif{ mchunkptr oldp; INTERNAL_SIZE_T nb, oldsize; Void_t* newmem = 0; if (oldmem == 0) return malloc_check(bytes, NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -