Blame malloc/hooks.c

Packit Service 82fcde
/* Malloc implementation for multiple threads without lock contention.
Packit Service 82fcde
   Copyright (C) 2001-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Wolfram Gloger <wg@malloc.de>, 2001.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public License as
Packit Service 82fcde
   published by the Free Software Foundation; either version 2.1 of the
Packit Service 82fcde
   License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; see the file COPYING.LIB.  If
Packit Service 82fcde
   not, see <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
/* What to do if the standard debugging hooks are in place and a
Packit Service 82fcde
   corrupt pointer is detected: do nothing (0), print an error message
Packit Service 82fcde
   (1), or call abort() (2). */
Packit Service 82fcde
Packit Service 82fcde
/* Hooks for debugging versions.  The initial hooks just call the
Packit Service 82fcde
   initialization routine, then do the normal work. */
Packit Service 82fcde
Packit Service 82fcde
static void *
Packit Service 82fcde
malloc_hook_ini (size_t sz, const void *caller)
Packit Service 82fcde
{
Packit Service 82fcde
  __malloc_hook = NULL;
Packit Service 82fcde
  ptmalloc_init ();
Packit Service 82fcde
  return __libc_malloc (sz);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static void *
Packit Service 82fcde
realloc_hook_ini (void *ptr, size_t sz, const void *caller)
Packit Service 82fcde
{
Packit Service 82fcde
  __malloc_hook = NULL;
Packit Service 82fcde
  __realloc_hook = NULL;
Packit Service 82fcde
  ptmalloc_init ();
Packit Service 82fcde
  return __libc_realloc (ptr, sz);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static void *
Packit Service 82fcde
memalign_hook_ini (size_t alignment, size_t sz, const void *caller)
Packit Service 82fcde
{
Packit Service 82fcde
  __memalign_hook = NULL;
Packit Service 82fcde
  ptmalloc_init ();
Packit Service 82fcde
  return __libc_memalign (alignment, sz);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Whether we are using malloc checking.  */
Packit Service 82fcde
static int using_malloc_checking;
Packit Service 82fcde
Packit Service 82fcde
/* Activate a standard set of debugging hooks. */
Packit Service 82fcde
void
Packit Service 82fcde
__malloc_check_init (void)
Packit Service 82fcde
{
Packit Service 82fcde
  using_malloc_checking = 1;
Packit Service 82fcde
  __malloc_hook = malloc_check;
Packit Service 82fcde
  __free_hook = free_check;
Packit Service 82fcde
  __realloc_hook = realloc_check;
Packit Service 82fcde
  __memalign_hook = memalign_check;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* A simple, standard set of debugging hooks.  Overhead is `only' one
Packit Service 82fcde
   byte per chunk; still this will catch most cases of double frees or
Packit Service 82fcde
   overruns.  The goal here is to avoid obscure crashes due to invalid
Packit Service 82fcde
   usage, unlike in the MALLOC_DEBUG code. */
Packit Service 82fcde
Packit Service 82fcde
static unsigned char
Packit Service 82fcde
magicbyte (const void *p)
Packit Service 82fcde
{
Packit Service 82fcde
  unsigned char magic;
Packit Service 82fcde
Packit Service 82fcde
  magic = (((uintptr_t) p >> 3) ^ ((uintptr_t) p >> 11)) & 0xFF;
Packit Service 82fcde
  /* Do not return 1.  See the comment in mem2mem_check().  */
Packit Service 82fcde
  if (magic == 1)
Packit Service 82fcde
    ++magic;
Packit Service 82fcde
  return magic;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Visualize the chunk as being partitioned into blocks of 255 bytes from the
Packit Service 82fcde
   highest address of the chunk, downwards.  The end of each block tells
Packit Service 82fcde
   us the size of that block, up to the actual size of the requested
Packit Service 82fcde
   memory.  Our magic byte is right at the end of the requested size, so we
Packit Service 82fcde
   must reach it with this iteration, otherwise we have witnessed a memory
Packit Service 82fcde
   corruption.  */
Packit Service 82fcde
static size_t
Packit Service 82fcde
malloc_check_get_size (mchunkptr p)
Packit Service 82fcde
{
Packit Service 82fcde
  size_t size;
Packit Service 82fcde
  unsigned char c;
Packit Service 82fcde
  unsigned char magic = magicbyte (p);
Packit Service 82fcde
Packit Service 82fcde
  assert (using_malloc_checking == 1);
Packit Service 82fcde
Packit Service 82fcde
  for (size = chunksize (p) - 1 + (chunk_is_mmapped (p) ? 0 : SIZE_SZ);
Packit Service 82fcde
       (c = ((unsigned char *) p)[size]) != magic;
Packit Service 82fcde
       size -= c)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (c <= 0 || size < (c + 2 * SIZE_SZ))
Packit Service 82fcde
	malloc_printerr ("malloc_check_get_size: memory corruption");
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* chunk2mem size.  */
Packit Service 82fcde
  return size - 2 * SIZE_SZ;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Instrument a chunk with overrun detector byte(s) and convert it
Packit Service 82fcde
   into a user pointer with requested size req_sz. */
Packit Service 82fcde
Packit Service 82fcde
static void *
Packit Service 82fcde
mem2mem_check (void *ptr, size_t req_sz)
Packit Service 82fcde
{
Packit Service 82fcde
  mchunkptr p;
Packit Service 82fcde
  unsigned char *m_ptr = ptr;
Packit Service 82fcde
  size_t max_sz, block_sz, i;
Packit Service 82fcde
  unsigned char magic;
Packit Service 82fcde
Packit Service 82fcde
  if (!ptr)
Packit Service 82fcde
    return ptr;
Packit Service 82fcde
Packit Service 82fcde
  p = mem2chunk (ptr);
Packit Service 82fcde
  magic = magicbyte (p);
Packit Service 82fcde
  max_sz = chunksize (p) - 2 * SIZE_SZ;
Packit Service 82fcde
  if (!chunk_is_mmapped (p))
Packit Service 82fcde
    max_sz += SIZE_SZ;
Packit Service 82fcde
  for (i = max_sz - 1; i > req_sz; i -= block_sz)
Packit Service 82fcde
    {
Packit Service 82fcde
      block_sz = MIN (i - req_sz, 0xff);
Packit Service 82fcde
      /* Don't allow the magic byte to appear in the chain of length bytes.
Packit Service 82fcde
         For the following to work, magicbyte cannot return 0x01.  */
Packit Service 82fcde
      if (block_sz == magic)
Packit Service 82fcde
        --block_sz;
Packit Service 82fcde
Packit Service 82fcde
      m_ptr[i] = block_sz;
Packit Service 82fcde
    }
Packit Service 82fcde
  m_ptr[req_sz] = magic;
Packit Service 82fcde
  return (void *) m_ptr;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Convert a pointer to be free()d or realloc()ed to a valid chunk
Packit Service 82fcde
   pointer.  If the provided pointer is not valid, return NULL. */
Packit Service 82fcde
Packit Service 82fcde
static mchunkptr
Packit Service 82fcde
mem2chunk_check (void *mem, unsigned char **magic_p)
Packit Service 82fcde
{
Packit Service 82fcde
  mchunkptr p;
Packit Service 82fcde
  INTERNAL_SIZE_T sz, c;
Packit Service 82fcde
  unsigned char magic;
Packit Service 82fcde
Packit Service 82fcde
  if (!aligned_OK (mem))
Packit Service 82fcde
    return NULL;
Packit Service 82fcde
Packit Service 82fcde
  p = mem2chunk (mem);
Packit Service 82fcde
  sz = chunksize (p);
Packit Service 82fcde
  magic = magicbyte (p);
Packit Service 82fcde
  if (!chunk_is_mmapped (p))
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Must be a chunk in conventional heap memory. */
Packit Service 82fcde
      int contig = contiguous (&main_arena);
Packit Service 82fcde
      if ((contig &&
Packit Service 82fcde
           ((char *) p < mp_.sbrk_base ||
Packit Service 82fcde
            ((char *) p + sz) >= (mp_.sbrk_base + main_arena.system_mem))) ||
Packit Service 82fcde
          sz < MINSIZE || sz & MALLOC_ALIGN_MASK || !inuse (p) ||
Packit Service 82fcde
          (!prev_inuse (p) && ((prev_size (p) & MALLOC_ALIGN_MASK) != 0 ||
Packit Service 82fcde
                               (contig && (char *) prev_chunk (p) < mp_.sbrk_base) ||
Packit Service 82fcde
                               next_chunk (prev_chunk (p)) != p)))
Packit Service 82fcde
        return NULL;
Packit Service 82fcde
Packit Service 82fcde
      for (sz += SIZE_SZ - 1; (c = ((unsigned char *) p)[sz]) != magic; sz -= c)
Packit Service 82fcde
        {
Packit Service 82fcde
          if (c == 0 || sz < (c + 2 * SIZE_SZ))
Packit Service 82fcde
            return NULL;
Packit Service 82fcde
        }
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      unsigned long offset, page_mask = GLRO (dl_pagesize) - 1;
Packit Service 82fcde
Packit Service 82fcde
      /* mmap()ed chunks have MALLOC_ALIGNMENT or higher power-of-two
Packit Service 82fcde
         alignment relative to the beginning of a page.  Check this
Packit Service 82fcde
         first. */
Packit Service 82fcde
      offset = (unsigned long) mem & page_mask;
Packit Service 82fcde
      if ((offset != MALLOC_ALIGNMENT && offset != 0 && offset != 0x10 &&
Packit Service 82fcde
           offset != 0x20 && offset != 0x40 && offset != 0x80 && offset != 0x100 &&
Packit Service 82fcde
           offset != 0x200 && offset != 0x400 && offset != 0x800 && offset != 0x1000 &&
Packit Service 82fcde
           offset < 0x2000) ||
Packit Service 82fcde
          !chunk_is_mmapped (p) || prev_inuse (p) ||
Packit Service 82fcde
          ((((unsigned long) p - prev_size (p)) & page_mask) != 0) ||
Packit Service 82fcde
          ((prev_size (p) + sz) & page_mask) != 0)
Packit Service 82fcde
        return NULL;
Packit Service 82fcde
Packit Service 82fcde
      for (sz -= 1; (c = ((unsigned char *) p)[sz]) != magic; sz -= c)
Packit Service 82fcde
        {
Packit Service 82fcde
          if (c == 0 || sz < (c + 2 * SIZE_SZ))
Packit Service 82fcde
            return NULL;
Packit Service 82fcde
        }
Packit Service 82fcde
    }
Packit Service 82fcde
  ((unsigned char *) p)[sz] ^= 0xFF;
Packit Service 82fcde
  if (magic_p)
Packit Service 82fcde
    *magic_p = (unsigned char *) p + sz;
Packit Service 82fcde
  return p;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Check for corruption of the top chunk.  */
Packit Service 82fcde
static void
Packit Service 82fcde
top_check (void)
Packit Service 82fcde
{
Packit Service 82fcde
  mchunkptr t = top (&main_arena);
Packit Service 82fcde
Packit Service 82fcde
  if (t == initial_top (&main_arena) ||
Packit Service 82fcde
      (!chunk_is_mmapped (t) &&
Packit Service 82fcde
       chunksize (t) >= MINSIZE &&
Packit Service 82fcde
       prev_inuse (t) &&
Packit Service 82fcde
       (!contiguous (&main_arena) ||
Packit Service 82fcde
        (char *) t + chunksize (t) == mp_.sbrk_base + main_arena.system_mem)))
Packit Service 82fcde
    return;
Packit Service 82fcde
Packit Service 82fcde
  malloc_printerr ("malloc: top chunk is corrupt");
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static void *
Packit Service 82fcde
malloc_check (size_t sz, const void *caller)
Packit Service 82fcde
{
Packit Service 82fcde
  void *victim;
Packit Service 82fcde
Packit Service 82fcde
  if (sz + 1 == 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      __set_errno (ENOMEM);
Packit Service 82fcde
      return NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  __libc_lock_lock (main_arena.mutex);
Packit Service 82fcde
  top_check ();
Packit Service 82fcde
  victim = _int_malloc (&main_arena, sz + 1);
Packit Service 82fcde
  __libc_lock_unlock (main_arena.mutex);
Packit Service 82fcde
  return mem2mem_check (victim, sz);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
free_check (void *mem, const void *caller)
Packit Service 82fcde
{
Packit Service 82fcde
  mchunkptr p;
Packit Service 82fcde
Packit Service 82fcde
  if (!mem)
Packit Service 82fcde
    return;
Packit Service 82fcde
Packit Service 82fcde
  __libc_lock_lock (main_arena.mutex);
Packit Service 82fcde
  p = mem2chunk_check (mem, NULL);
Packit Service 82fcde
  if (!p)
Packit Service 82fcde
    malloc_printerr ("free(): invalid pointer");
Packit Service 82fcde
  if (chunk_is_mmapped (p))
Packit Service 82fcde
    {
Packit Service 82fcde
      __libc_lock_unlock (main_arena.mutex);
Packit Service 82fcde
      munmap_chunk (p);
Packit Service 82fcde
      return;
Packit Service 82fcde
    }
Packit Service 82fcde
  _int_free (&main_arena, p, 1);
Packit Service 82fcde
  __libc_lock_unlock (main_arena.mutex);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static void *
Packit Service 82fcde
realloc_check (void *oldmem, size_t bytes, const void *caller)
Packit Service 82fcde
{
Packit Service 82fcde
  INTERNAL_SIZE_T nb;
Packit Service 82fcde
  void *newmem = 0;
Packit Service 82fcde
  unsigned char *magic_p;
Packit Service 82fcde
Packit Service 82fcde
  if (bytes + 1 == 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      __set_errno (ENOMEM);
Packit Service 82fcde
      return NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
  if (oldmem == 0)
Packit Service 82fcde
    return malloc_check (bytes, NULL);
Packit Service 82fcde
Packit Service 82fcde
  if (bytes == 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      free_check (oldmem, NULL);
Packit Service 82fcde
      return NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
  __libc_lock_lock (main_arena.mutex);
Packit Service 82fcde
  const mchunkptr oldp = mem2chunk_check (oldmem, &magic_p);
Packit Service 82fcde
  __libc_lock_unlock (main_arena.mutex);
Packit Service 82fcde
  if (!oldp)
Packit Service 82fcde
    malloc_printerr ("realloc(): invalid pointer");
Packit Service 82fcde
  const INTERNAL_SIZE_T oldsize = chunksize (oldp);
Packit Service 82fcde
Packit Service 82fcde
  checked_request2size (bytes + 1, nb);
Packit Service 82fcde
  __libc_lock_lock (main_arena.mutex);
Packit Service 82fcde
Packit Service 82fcde
  if (chunk_is_mmapped (oldp))
Packit Service 82fcde
    {
Packit Service 82fcde
#if HAVE_MREMAP
Packit Service 82fcde
      mchunkptr newp = mremap_chunk (oldp, nb);
Packit Service 82fcde
      if (newp)
Packit Service 82fcde
        newmem = chunk2mem (newp);
Packit Service 82fcde
      else
Packit Service 82fcde
#endif
Packit Service 82fcde
      {
Packit Service 82fcde
        /* Note the extra SIZE_SZ overhead. */
Packit Service 82fcde
        if (oldsize - SIZE_SZ >= nb)
Packit Service 82fcde
          newmem = oldmem; /* do nothing */
Packit Service 82fcde
        else
Packit Service 82fcde
          {
Packit Service 82fcde
            /* Must alloc, copy, free. */
Packit Service 82fcde
	    top_check ();
Packit Service 82fcde
	    newmem = _int_malloc (&main_arena, bytes + 1);
Packit Service 82fcde
            if (newmem)
Packit Service 82fcde
              {
Packit Service 82fcde
                memcpy (newmem, oldmem, oldsize - 2 * SIZE_SZ);
Packit Service 82fcde
                munmap_chunk (oldp);
Packit Service 82fcde
              }
Packit Service 82fcde
          }
Packit Service 82fcde
      }
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      top_check ();
Packit Service 82fcde
      INTERNAL_SIZE_T nb;
Packit Service 82fcde
      checked_request2size (bytes + 1, nb);
Packit Service 82fcde
      newmem = _int_realloc (&main_arena, oldp, oldsize, nb);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  DIAG_PUSH_NEEDS_COMMENT;
Packit Service 82fcde
#if __GNUC_PREREQ (7, 0)
Packit Service 82fcde
  /* GCC 7 warns about magic_p may be used uninitialized.  But we never
Packit Service 82fcde
     reach here if magic_p is uninitialized.  */
Packit Service 82fcde
  DIAG_IGNORE_NEEDS_COMMENT (7, "-Wmaybe-uninitialized");
Packit Service 82fcde
#endif
Packit Service 82fcde
  /* mem2chunk_check changed the magic byte in the old chunk.
Packit Service 82fcde
     If newmem is NULL, then the old chunk will still be used though,
Packit Service 82fcde
     so we need to invert that change here.  */
Packit Service 82fcde
  if (newmem == NULL)
Packit Service 82fcde
    *magic_p ^= 0xFF;
Packit Service 82fcde
  DIAG_POP_NEEDS_COMMENT;
Packit Service 82fcde
Packit Service 82fcde
  __libc_lock_unlock (main_arena.mutex);
Packit Service 82fcde
Packit Service 82fcde
  return mem2mem_check (newmem, bytes);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static void *
Packit Service 82fcde
memalign_check (size_t alignment, size_t bytes, const void *caller)
Packit Service 82fcde
{
Packit Service 82fcde
  void *mem;
Packit Service 82fcde
Packit Service 82fcde
  if (alignment <= MALLOC_ALIGNMENT)
Packit Service 82fcde
    return malloc_check (bytes, NULL);
Packit Service 82fcde
Packit Service 82fcde
  if (alignment < MINSIZE)
Packit Service 82fcde
    alignment = MINSIZE;
Packit Service 82fcde
Packit Service 82fcde
  /* If the alignment is greater than SIZE_MAX / 2 + 1 it cannot be a
Packit Service 82fcde
     power of 2 and will cause overflow in the check below.  */
Packit Service 82fcde
  if (alignment > SIZE_MAX / 2 + 1)
Packit Service 82fcde
    {
Packit Service 82fcde
      __set_errno (EINVAL);
Packit Service 82fcde
      return 0;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Check for overflow.  */
Packit Service 82fcde
  if (bytes > SIZE_MAX - alignment - MINSIZE)
Packit Service 82fcde
    {
Packit Service 82fcde
      __set_errno (ENOMEM);
Packit Service 82fcde
      return 0;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Make sure alignment is power of 2.  */
Packit Service 82fcde
  if (!powerof2 (alignment))
Packit Service 82fcde
    {
Packit Service 82fcde
      size_t a = MALLOC_ALIGNMENT * 2;
Packit Service 82fcde
      while (a < alignment)
Packit Service 82fcde
        a <<= 1;
Packit Service 82fcde
      alignment = a;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  __libc_lock_lock (main_arena.mutex);
Packit Service 82fcde
  top_check ();
Packit Service 82fcde
  mem = _int_memalign (&main_arena, alignment, bytes + 1);
Packit Service 82fcde
  __libc_lock_unlock (main_arena.mutex);
Packit Service 82fcde
  return mem2mem_check (mem, bytes);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_25)
Packit Service 82fcde
Packit Service 82fcde
/* Support for restoring dumped heaps contained in historic Emacs
Packit Service 82fcde
   executables.  The heap saving feature (malloc_get_state) is no
Packit Service 82fcde
   longer implemented in this version of glibc, but we have a heap
Packit Service 82fcde
   rewriter in malloc_set_state which transforms the heap into a
Packit Service 82fcde
   version compatible with current malloc.  */
Packit Service 82fcde
Packit Service 82fcde
#define MALLOC_STATE_MAGIC   0x444c4541l
Packit Service 82fcde
#define MALLOC_STATE_VERSION (0 * 0x100l + 5l) /* major*0x100 + minor */
Packit Service 82fcde
Packit Service 82fcde
struct malloc_save_state
Packit Service 82fcde
{
Packit Service 82fcde
  long magic;
Packit Service 82fcde
  long version;
Packit Service 82fcde
  mbinptr av[NBINS * 2 + 2];
Packit Service 82fcde
  char *sbrk_base;
Packit Service 82fcde
  int sbrked_mem_bytes;
Packit Service 82fcde
  unsigned long trim_threshold;
Packit Service 82fcde
  unsigned long top_pad;
Packit Service 82fcde
  unsigned int n_mmaps_max;
Packit Service 82fcde
  unsigned long mmap_threshold;
Packit Service 82fcde
  int check_action;
Packit Service 82fcde
  unsigned long max_sbrked_mem;
Packit Service 82fcde
  unsigned long max_total_mem;	/* Always 0, for backwards compatibility.  */
Packit Service 82fcde
  unsigned int n_mmaps;
Packit Service 82fcde
  unsigned int max_n_mmaps;
Packit Service 82fcde
  unsigned long mmapped_mem;
Packit Service 82fcde
  unsigned long max_mmapped_mem;
Packit Service 82fcde
  int using_malloc_checking;
Packit Service 82fcde
  unsigned long max_fast;
Packit Service 82fcde
  unsigned long arena_test;
Packit Service 82fcde
  unsigned long arena_max;
Packit Service 82fcde
  unsigned long narenas;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
/* Dummy implementation which always fails.  We need to provide this
Packit Service 82fcde
   symbol so that existing Emacs binaries continue to work with
Packit Service 82fcde
   BIND_NOW.  */
Packit Service 82fcde
void *
Packit Service 82fcde
attribute_compat_text_section
Packit Service 82fcde
malloc_get_state (void)
Packit Service 82fcde
{
Packit Service 82fcde
  __set_errno (ENOSYS);
Packit Service 82fcde
  return NULL;
Packit Service 82fcde
}
Packit Service 82fcde
compat_symbol (libc, malloc_get_state, malloc_get_state, GLIBC_2_0);
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
attribute_compat_text_section
Packit Service 82fcde
malloc_set_state (void *msptr)
Packit Service 82fcde
{
Packit Service 82fcde
  struct malloc_save_state *ms = (struct malloc_save_state *) msptr;
Packit Service 82fcde
Packit Service 82fcde
  if (ms->magic != MALLOC_STATE_MAGIC)
Packit Service 82fcde
    return -1;
Packit Service 82fcde
Packit Service 82fcde
  /* Must fail if the major version is too high. */
Packit Service 82fcde
  if ((ms->version & ~0xffl) > (MALLOC_STATE_VERSION & ~0xffl))
Packit Service 82fcde
    return -2;
Packit Service 82fcde
Packit Service 82fcde
  /* We do not need to perform locking here because malloc_set_state
Packit Service 82fcde
     must be called before the first call into the malloc subsytem
Packit Service 82fcde
     (usually via __malloc_initialize_hook).  pthread_create always
Packit Service 82fcde
     calls calloc and thus must be called only afterwards, so there
Packit Service 82fcde
     cannot be more than one thread when we reach this point.  */
Packit Service 82fcde
Packit Service 82fcde
  /* Disable the malloc hooks (and malloc checking).  */
Packit Service 82fcde
  __malloc_hook = NULL;
Packit Service 82fcde
  __realloc_hook = NULL;
Packit Service 82fcde
  __free_hook = NULL;
Packit Service 82fcde
  __memalign_hook = NULL;
Packit Service 82fcde
  using_malloc_checking = 0;
Packit Service 82fcde
Packit Service 82fcde
  /* Patch the dumped heap.  We no longer try to integrate into the
Packit Service 82fcde
     existing heap.  Instead, we mark the existing chunks as mmapped.
Packit Service 82fcde
     Together with the update to dumped_main_arena_start and
Packit Service 82fcde
     dumped_main_arena_end, realloc and free will recognize these
Packit Service 82fcde
     chunks as dumped fake mmapped chunks and never free them.  */
Packit Service 82fcde
Packit Service 82fcde
  /* Find the chunk with the lowest address with the heap.  */
Packit Service 82fcde
  mchunkptr chunk = NULL;
Packit Service 82fcde
  {
Packit Service 82fcde
    size_t *candidate = (size_t *) ms->sbrk_base;
Packit Service 82fcde
    size_t *end = (size_t *) (ms->sbrk_base + ms->sbrked_mem_bytes);
Packit Service 82fcde
    while (candidate < end)
Packit Service 82fcde
      if (*candidate != 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  chunk = mem2chunk ((void *) (candidate + 1));
Packit Service 82fcde
	  break;
Packit Service 82fcde
	}
Packit Service 82fcde
      else
Packit Service 82fcde
	++candidate;
Packit Service 82fcde
  }
Packit Service 82fcde
  if (chunk == NULL)
Packit Service 82fcde
    return 0;
Packit Service 82fcde
Packit Service 82fcde
  /* Iterate over the dumped heap and patch the chunks so that they
Packit Service 82fcde
     are treated as fake mmapped chunks.  */
Packit Service 82fcde
  mchunkptr top = ms->av[2];
Packit Service 82fcde
  while (chunk < top)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (inuse (chunk))
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Mark chunk as mmapped, to trigger the fallback path.  */
Packit Service 82fcde
	  size_t size = chunksize (chunk);
Packit Service 82fcde
	  set_head (chunk, size | IS_MMAPPED);
Packit Service 82fcde
	}
Packit Service 82fcde
      chunk = next_chunk (chunk);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* The dumped fake mmapped chunks all lie in this address range.  */
Packit Service 82fcde
  dumped_main_arena_start = (mchunkptr) ms->sbrk_base;
Packit Service 82fcde
  dumped_main_arena_end = top;
Packit Service 82fcde
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
compat_symbol (libc, malloc_set_state, malloc_set_state, GLIBC_2_0);
Packit Service 82fcde
Packit Service 82fcde
#endif	/* SHLIB_COMPAT */
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * Local variables:
Packit Service 82fcde
 * c-basic-offset: 2
Packit Service 82fcde
 * End:
Packit Service 82fcde
 */