Back to index

glibc  2.9
Classes | Defines | Functions | Variables
hooks.c File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  malloc_save_state

Defines

#define MAGICBYTE(p)   ( ( ((size_t)p >> 3) ^ ((size_t)p >> 11)) & 0xFF )
#define MALLOC_STATE_MAGIC   0x444c4541l
#define MALLOC_STATE_VERSION   (0*0x100l + 3l) /* major*0x100 + minor */

Functions

static Void_tmalloc_hook_ini (size_t sz, const __malloc_ptr_t caller)
static Void_trealloc_hook_ini (Void_t *ptr, size_t sz, const __malloc_ptr_t caller)
static Void_tmemalign_hook_ini (size_t alignment, size_t sz, const __malloc_ptr_t caller)
void __malloc_check_init ()
static Void_t *internal_function mem2mem_check (Void_t *ptr, size_t sz)
static mchunkptr internal_function mem2chunk_check (Void_t *mem, unsigned char **magic_p)
static int internal_function top_check ()
static Void_tmalloc_check (size_t sz, const Void_t *caller)
static void free_check (Void_t *mem, const Void_t *caller)
static Void_trealloc_check (Void_t *oldmem, size_t bytes, const Void_t *caller)
static Void_tmemalign_check (size_t alignment, size_t bytes, const Void_t *caller)
static Void_tmalloc_starter (size_t sz, const Void_t *caller)
static Void_tmemalign_starter (size_t align, size_t sz, const Void_t *caller)
static void free_starter (Void_t *mem, const Void_t *caller)
Void_tpublic_gET_STATe (void)
int public_sET_STATe (Void_t *msptr)

Variables

static int using_malloc_checking
static int disallow_malloc_check

Class Documentation

struct malloc_save_state

Definition at line 499 of file hooks.c.

Collaboration diagram for malloc_save_state:
Class Members
mbinptr av
int check_action
long magic
unsigned long max_mmapped_mem
unsigned int max_n_mmaps
unsigned long max_sbrked_mem
unsigned long max_total_mem
unsigned long mmap_threshold
unsigned long mmapped_mem
unsigned int n_mmaps
unsigned int n_mmaps_max
char * sbrk_base
int sbrked_mem_bytes
unsigned long top_pad
unsigned long trim_threshold
int using_malloc_checking
long version

Define Documentation

#define MAGICBYTE (   p)    ( ( ((size_t)p >> 3) ^ ((size_t)p >> 11)) & 0xFF )

Definition at line 106 of file hooks.c.

#define MALLOC_STATE_MAGIC   0x444c4541l

Definition at line 496 of file hooks.c.

#define MALLOC_STATE_VERSION   (0*0x100l + 3l) /* major*0x100 + minor */

Definition at line 497 of file hooks.c.


Function Documentation

Definition at line 88 of file hooks.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void free_check ( Void_t mem,
const Void_t caller 
) [static]

Definition at line 272 of file hooks.c.

{
  mchunkptr p;

  if(!mem) return;
  (void)mutex_lock(&main_arena.mutex);
  p = mem2chunk_check(mem, NULL);
  if(!p) {
    (void)mutex_unlock(&main_arena.mutex);

    malloc_printerr(check_action, "free(): invalid pointer", mem);
    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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void free_starter ( Void_t mem,
const Void_t caller 
) [static]

Definition at line 460 of file hooks.c.

{
  mchunkptr p;

  if(!mem) return;
  p = mem2chunk(mem);
#if HAVE_MMAP
  if (chunk_is_mmapped(p)) {
    munmap_chunk(p);
    return;
  }
#endif
  _int_free(&main_arena, mem);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static Void_t* malloc_check ( size_t  sz,
const Void_t caller 
) [static]

Definition at line 252 of file hooks.c.

{
  Void_t *victim;

  if (sz+1 == 0) {
    MALLOC_FAILURE_ACTION;
    return NULL;
  }

  (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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static Void_t* malloc_hook_ini ( size_t  sz,
const __malloc_ptr_t  caller 
) [static]

Definition at line 32 of file hooks.c.

Here is the call graph for this function:

static Void_t* malloc_starter ( size_t  sz,
const Void_t caller 
) [static]

Definition at line 432 of file hooks.c.

{
  Void_t* victim;

  victim = _int_malloc(&main_arena, sz);

  return victim ? BOUNDED_N(victim, sz) : 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static mchunkptr internal_function mem2chunk_check ( Void_t mem,
unsigned char **  magic_p 
) [static]

Definition at line 147 of file hooks.c.

{
  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;
    }
  } 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;
  if (magic_p)
    *magic_p = (unsigned char *)p + sz;
  return p;
}

Here is the caller graph for this function:

static Void_t* internal_function mem2mem_check ( Void_t ptr,
size_t  sz 
) [static]

Definition at line 116 of file hooks.c.

{
  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;
}

Here is the caller graph for this function:

static Void_t* memalign_check ( size_t  alignment,
size_t  bytes,
const Void_t caller 
) [static]

Definition at line 390 of file hooks.c.

{
  INTERNAL_SIZE_T nb;
  Void_t* mem;

  if (alignment <= MALLOC_ALIGNMENT) return malloc_check(bytes, NULL);
  if (alignment <  MINSIZE) alignment = MINSIZE;

  if (bytes+1 == 0) {
    MALLOC_FAILURE_ACTION;
    return NULL;
  }
  checked_request2size(bytes+1, nb);
  (void)mutex_lock(&main_arena.mutex);
  mem = (top_check() >= 0) ? _int_memalign(&main_arena, alignment, bytes+1) :
    NULL;
  (void)mutex_unlock(&main_arena.mutex);
  return mem2mem_check(mem, bytes);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static Void_t* memalign_hook_ini ( size_t  alignment,
size_t  sz,
const __malloc_ptr_t  caller 
) [static]

Definition at line 59 of file hooks.c.

{
  __memalign_hook = NULL;
  ptmalloc_init();
  return public_mEMALIGn(alignment, sz);
}

Here is the call graph for this function:

static Void_t* memalign_starter ( size_t  align,
size_t  sz,
const Void_t caller 
) [static]

Definition at line 446 of file hooks.c.

{
  Void_t* victim;

  victim = _int_memalign(&main_arena, align, sz);

  return victim ? BOUNDED_N(victim, sz) : 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Void_t* public_gET_STATe ( void  )

Definition at line 520 of file hooks.c.

{
  struct malloc_save_state* ms;
  int i;
  mbinptr b;

  ms = (struct malloc_save_state*)public_mALLOc(sizeof(*ms));
  if (!ms)
    return 0;
  (void)mutex_lock(&main_arena.mutex);
  malloc_consolidate(&main_arena);
  ms->magic = MALLOC_STATE_MAGIC;
  ms->version = MALLOC_STATE_VERSION;
  ms->av[0] = 0;
  ms->av[1] = 0; /* used to be binblocks, now no longer used */
  ms->av[2] = top(&main_arena);
  ms->av[3] = 0; /* used to be undefined */
  for(i=1; i<NBINS; i++) {
    b = bin_at(&main_arena, i);
    if(first(b) == b)
      ms->av[2*i+2] = ms->av[2*i+3] = 0; /* empty bin */
    else {
      ms->av[2*i+2] = first(b);
      ms->av[2*i+3] = last(b);
    }
  }
  ms->sbrk_base = mp_.sbrk_base;
  ms->sbrked_mem_bytes = main_arena.system_mem;
  ms->trim_threshold = mp_.trim_threshold;
  ms->top_pad = mp_.top_pad;
  ms->n_mmaps_max = mp_.n_mmaps_max;
  ms->mmap_threshold = mp_.mmap_threshold;
  ms->check_action = check_action;
  ms->max_sbrked_mem = main_arena.max_system_mem;
#ifdef NO_THREADS
  ms->max_total_mem = mp_.max_total_mem;
#else
  ms->max_total_mem = 0;
#endif
  ms->n_mmaps = mp_.n_mmaps;
  ms->max_n_mmaps = mp_.max_n_mmaps;
  ms->mmapped_mem = mp_.mmapped_mem;
  ms->max_mmapped_mem = mp_.max_mmapped_mem;
  ms->using_malloc_checking = using_malloc_checking;
  (void)mutex_unlock(&main_arena.mutex);
  return (Void_t*)ms;
}

Here is the call graph for this function:

int public_sET_STATe ( Void_t msptr)

Definition at line 569 of file hooks.c.

{
  struct malloc_save_state* ms = (struct malloc_save_state*)msptr;
  size_t i;
  mbinptr b;

  disallow_malloc_check = 1;
  ptmalloc_init();
  if(ms->magic != MALLOC_STATE_MAGIC) return -1;
  /* Must fail if the major version is too high. */
  if((ms->version & ~0xffl) > (MALLOC_STATE_VERSION & ~0xffl)) return -2;
  (void)mutex_lock(&main_arena.mutex);
  /* There are no fastchunks.  */
  clear_fastchunks(&main_arena);
  set_max_fast(DEFAULT_MXFAST);
  for (i=0; i<NFASTBINS; ++i)
    main_arena.fastbins[i] = 0;
  for (i=0; i<BINMAPSIZE; ++i)
    main_arena.binmap[i] = 0;
  top(&main_arena) = ms->av[2];
  main_arena.last_remainder = 0;
  for(i=1; i<NBINS; i++) {
    b = bin_at(&main_arena, i);
    if(ms->av[2*i+2] == 0) {
      assert(ms->av[2*i+3] == 0);
      first(b) = last(b) = b;
    } else {
      if(ms->version >= 3 &&
        (i<NSMALLBINS || (largebin_index(chunksize(ms->av[2*i+2]))==i &&
                        largebin_index(chunksize(ms->av[2*i+3]))==i))) {
       first(b) = ms->av[2*i+2];
       last(b) = ms->av[2*i+3];
       /* Make sure the links to the bins within the heap are correct.  */
       first(b)->bk = b;
       last(b)->fd = b;
       /* Set bit in binblocks.  */
       mark_bin(&main_arena, i);
      } else {
       /* Oops, index computation from chunksize must have changed.
           Link the whole list into unsorted_chunks.  */
       first(b) = last(b) = b;
       b = unsorted_chunks(&main_arena);
       ms->av[2*i+2]->bk = b;
       ms->av[2*i+3]->fd = b->fd;
       b->fd->bk = ms->av[2*i+3];
       b->fd = ms->av[2*i+2];
      }
    }
  }
  if (ms->version < 3) {
    /* Clear fd_nextsize and bk_nextsize fields.  */
    b = unsorted_chunks(&main_arena)->fd;
    while (b != unsorted_chunks(&main_arena)) {
      if (!in_smallbin_range(chunksize(b))) {
       b->fd_nextsize = NULL;
       b->bk_nextsize = NULL;
      }
      b = b->fd;
    }
  }
  mp_.sbrk_base = ms->sbrk_base;
  main_arena.system_mem = ms->sbrked_mem_bytes;
  mp_.trim_threshold = ms->trim_threshold;
  mp_.top_pad = ms->top_pad;
  mp_.n_mmaps_max = ms->n_mmaps_max;
  mp_.mmap_threshold = ms->mmap_threshold;
  check_action = ms->check_action;
  main_arena.max_system_mem = ms->max_sbrked_mem;
#ifdef NO_THREADS
  mp_.max_total_mem = ms->max_total_mem;
#endif
  mp_.n_mmaps = ms->n_mmaps;
  mp_.max_n_mmaps = ms->max_n_mmaps;
  mp_.mmapped_mem = ms->mmapped_mem;
  mp_.max_mmapped_mem = ms->max_mmapped_mem;
  /* add version-dependent code here */
  if (ms->version >= 1) {
    /* Check whether it is safe to enable malloc checking, or whether
       it is necessary to disable it.  */
    if (ms->using_malloc_checking && !using_malloc_checking &&
        !disallow_malloc_check)
      __malloc_check_init ();
    else if (!ms->using_malloc_checking && using_malloc_checking) {
      __malloc_hook = 0;
      __free_hook = 0;
      __realloc_hook = 0;
      __memalign_hook = 0;
      using_malloc_checking = 0;
    }
  }
  check_malloc_state(&main_arena);

  (void)mutex_unlock(&main_arena.mutex);
  return 0;
}

Here is the call graph for this function:

static Void_t* realloc_check ( Void_t oldmem,
size_t  bytes,
const Void_t caller 
) [static]

Definition at line 304 of file hooks.c.

{
  mchunkptr oldp;
  INTERNAL_SIZE_T nb, oldsize;
  Void_t* newmem = 0;
  unsigned char *magic_p;

  if (bytes+1 == 0) {
    MALLOC_FAILURE_ACTION;
    return NULL;
  }
  if (oldmem == 0) return malloc_check(bytes, NULL);
  if (bytes == 0) {
    free_check (oldmem, NULL);
    return NULL;
  }
  (void)mutex_lock(&main_arena.mutex);
  oldp = mem2chunk_check(oldmem, &magic_p);
  (void)mutex_unlock(&main_arena.mutex);
  if(!oldp) {
    malloc_printerr(check_action, "realloc(): invalid pointer", oldmem);
    return malloc_check(bytes, NULL);
  }
  oldsize = chunksize(oldp);

  checked_request2size(bytes+1, nb);
  (void)mutex_lock(&main_arena.mutex);

#if HAVE_MMAP
  if (chunk_is_mmapped(oldp)) {
#if HAVE_MREMAP
    mchunkptr newp = mremap_chunk(oldp, nb);
    if(newp)
      newmem = chunk2mem(newp);
    else
#endif
    {
      /* Note the extra SIZE_SZ overhead. */
      if(oldsize - SIZE_SZ >= nb)
       newmem = oldmem; /* do nothing */
      else {
        /* Must alloc, copy, free. */
        if (top_check() >= 0)
         newmem = _int_malloc(&main_arena, bytes+1);
        if (newmem) {
          MALLOC_COPY(BOUNDED_N(newmem, bytes+1), oldmem, oldsize - 2*SIZE_SZ);
          munmap_chunk(oldp);
        }
      }
    }
  } else {
#endif /* HAVE_MMAP */
    if (top_check() >= 0)
      newmem = _int_realloc(&main_arena, oldmem, bytes+1);
#if 0 /* Erase freed memory. */
    if(newmem)
      newp = mem2chunk(newmem);
    nb = chunksize(newp);
    if(oldp<newp || oldp>=chunk_at_offset(newp, nb)) {
      memset((char*)oldmem + 2*sizeof(mbinptr), 0,
             oldsize - (2*sizeof(mbinptr)+2*SIZE_SZ+1));
    } else if(nb > oldsize+SIZE_SZ) {
      memset((char*)BOUNDED_N(chunk2mem(newp), bytes) + oldsize,
            0, nb - (oldsize+SIZE_SZ));
    }
#endif
#if HAVE_MMAP
  }
#endif

  /* mem2chunk_check changed the magic byte in the old chunk.
     If newmem is NULL, then the old chunk will still be used though,
     so we need to invert that change here.  */
  if (newmem == NULL) *magic_p ^= 0xFF;

  (void)mutex_unlock(&main_arena.mutex);

  return mem2mem_check(newmem, bytes);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static Void_t* realloc_hook_ini ( Void_t ptr,
size_t  sz,
const __malloc_ptr_t  caller 
) [static]

Definition at line 45 of file hooks.c.

Here is the call graph for this function:

static int internal_function top_check ( ) [static]

Definition at line 206 of file hooks.c.

{
  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;

  malloc_printerr (check_action, "malloc: top chunk is corrupt", t);

  /* 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))
    {
      MALLOC_FAILURE_ACTION;
      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;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 84 of file hooks.c.

Definition at line 69 of file hooks.c.