Reformat malloc to gnu style.

This commit is contained in:
Ondřej Bílka 2014-01-02 09:38:18 +01:00
parent 9a3c6a6ff6
commit 6c8dbf00f5
18 changed files with 3843 additions and 3559 deletions

View File

@ -1,3 +1,37 @@
2013-01-02 Ondřej Bílka <neleai@seznam.cz>
* malloc/arena.c (malloc_atfork, free_atfork, ptmalloc_lock_all,
ptmalloc_unlock_all, ptmalloc_unlock_all2, next_env_entry,
__failing_morecore, ptmalloc_init, dump_heap, new_heap, grow_heap,
heap_trim, _int_new_arena, get_free_list, reused_arena, arena_get2):
Convert to GNU style.
* malloc/hooks.c (memalign_hook_ini, __malloc_check_init,
mem2mem_check, mem2chunk_check, top_check, realloc_check,
memalign_check, __malloc_set_state): Likewise.
* malloc/mallocbug.c (main): Likewise.
* malloc/malloc.c (__malloc_assert, malloc_init_state, free_perturb,
do_check_malloced_chunk, do_check_malloc_state, sysmalloc, systrim,
mremap_chunk, __libc_malloc, __libc_free, __libc_realloc, _mid_memalign,
_int_malloc, malloc_consolidate, _int_realloc, _int_memalign, mtrim,
musable, __libc_mallopt, __posix_memalign, malloc_info): Likewise.
* malloc/malloc.h: Likewise.
* malloc/mcheck.c (checkhdr, unlink_blk, link_blk, freehook, mallochook,
memalignhook, reallochook, mabort): Likewise.
* malloc/mcheck.h: Likewise.
* malloc/memusage.c (update_data, me, malloc, realloc, calloc, free, mmap,
mmap64, mremap, munmap, dest): Likewise.
* malloc/memusagestat.c (main, parse_opt, more_help): Likewise.
* malloc/morecore.c (__default_morecore): Likewise.
* malloc/mtrace.c (tr_break, lock_and_info, mtrace): Likewise.
* malloc/obstack.c (_obstack_begin, _obstack_newchunk,
_obstack_allocated_p, obstack_free, _obstack_memory_used,
print_and_abort): Likewise.
* malloc/obstack.h: Likewise.
* malloc/set-freeres.c (__libc_freeres): Likewise.
* malloc/tst-mallocstate.c (main): Likewise.
* malloc/tst-mtrace.c (main): Likewise.
* malloc/tst-realloc.c (do_test): Likewise.
2013-01-02 Siddhesh Poyarekar <siddhesh@redhat.com> 2013-01-02 Siddhesh Poyarekar <siddhesh@redhat.com>
[BZ #16366] [BZ #16366]

File diff suppressed because it is too large Load Diff

View File

@ -24,29 +24,29 @@
/* Hooks for debugging versions. The initial hooks just call the /* Hooks for debugging versions. The initial hooks just call the
initialization routine, then do the normal work. */ initialization routine, then do the normal work. */
static void* static void *
malloc_hook_ini(size_t sz, const void *caller) malloc_hook_ini (size_t sz, const void *caller)
{ {
__malloc_hook = NULL; __malloc_hook = NULL;
ptmalloc_init(); ptmalloc_init ();
return __libc_malloc(sz); return __libc_malloc (sz);
} }
static void* static void *
realloc_hook_ini(void* ptr, size_t sz, const void *caller) realloc_hook_ini (void *ptr, size_t sz, const void *caller)
{ {
__malloc_hook = NULL; __malloc_hook = NULL;
__realloc_hook = NULL; __realloc_hook = NULL;
ptmalloc_init(); ptmalloc_init ();
return __libc_realloc(ptr, sz); return __libc_realloc (ptr, sz);
} }
static void* static void *
memalign_hook_ini(size_t alignment, size_t sz, const void *caller) memalign_hook_ini (size_t alignment, size_t sz, const void *caller)
{ {
__memalign_hook = NULL; __memalign_hook = NULL;
ptmalloc_init(); ptmalloc_init ();
return __libc_memalign(alignment, sz); return __libc_memalign (alignment, sz);
} }
/* Whether we are using malloc checking. */ /* Whether we are using malloc checking. */
@ -71,10 +71,11 @@ static int disallow_malloc_check;
void void
__malloc_check_init (void) __malloc_check_init (void)
{ {
if (disallow_malloc_check) { if (disallow_malloc_check)
disallow_malloc_check = 0; {
return; disallow_malloc_check = 0;
} return;
}
using_malloc_checking = 1; using_malloc_checking = 1;
__malloc_hook = malloc_check; __malloc_hook = malloc_check;
__free_hook = free_check; __free_hook = free_check;
@ -87,7 +88,7 @@ __malloc_check_init (void)
overruns. The goal here is to avoid obscure crashes due to invalid overruns. The goal here is to avoid obscure crashes due to invalid
usage, unlike in the MALLOC_DEBUG code. */ usage, unlike in the MALLOC_DEBUG code. */
#define MAGICBYTE(p) ( ( ((size_t)p >> 3) ^ ((size_t)p >> 11)) & 0xFF ) #define MAGICBYTE(p) ((((size_t) p >> 3) ^ ((size_t) p >> 11)) & 0xFF)
/* Visualize the chunk as being partitioned into blocks of 256 bytes from the /* Visualize the chunk as being partitioned into blocks of 256 bytes from the
highest address of the chunk, downwards. The beginning of each block tells highest address of the chunk, downwards. The beginning of each block tells
@ -96,53 +97,58 @@ __malloc_check_init (void)
must reach it with this iteration, otherwise we have witnessed a memory must reach it with this iteration, otherwise we have witnessed a memory
corruption. */ corruption. */
static size_t static size_t
malloc_check_get_size(mchunkptr p) malloc_check_get_size (mchunkptr p)
{ {
size_t size; size_t size;
unsigned char c; unsigned char c;
unsigned char magic = MAGICBYTE(p); unsigned char magic = MAGICBYTE (p);
assert(using_malloc_checking == 1); assert (using_malloc_checking == 1);
for (size = chunksize(p) - 1 + (chunk_is_mmapped(p) ? 0 : SIZE_SZ); for (size = chunksize (p) - 1 + (chunk_is_mmapped (p) ? 0 : SIZE_SZ);
(c = ((unsigned char*)p)[size]) != magic; (c = ((unsigned char *) p)[size]) != magic;
size -= c) { size -= c)
if(c<=0 || size<(c+2*SIZE_SZ)) { {
malloc_printerr(check_action, "malloc_check_get_size: memory corruption", if (c <= 0 || size < (c + 2 * SIZE_SZ))
chunk2mem(p)); {
return 0; malloc_printerr (check_action, "malloc_check_get_size: memory corruption",
chunk2mem (p));
return 0;
}
} }
}
/* chunk2mem size. */ /* chunk2mem size. */
return size - 2*SIZE_SZ; return size - 2 * SIZE_SZ;
} }
/* Instrument a chunk with overrun detector byte(s) and convert it /* Instrument a chunk with overrun detector byte(s) and convert it
into a user pointer with requested size sz. */ into a user pointer with requested size sz. */
static void* static void *
internal_function internal_function
mem2mem_check(void *ptr, size_t sz) mem2mem_check (void *ptr, size_t sz)
{ {
mchunkptr p; mchunkptr p;
unsigned char* m_ptr = ptr; unsigned char *m_ptr = ptr;
size_t i; size_t i;
if (!ptr) if (!ptr)
return ptr; return ptr;
p = mem2chunk(ptr);
for(i = chunksize(p) - (chunk_is_mmapped(p) ? 2*SIZE_SZ+1 : SIZE_SZ+1); p = mem2chunk (ptr);
i > sz; for (i = chunksize (p) - (chunk_is_mmapped (p) ? 2 * SIZE_SZ + 1 : SIZE_SZ + 1);
i -= 0xFF) { i > sz;
if(i-sz < 0x100) { i -= 0xFF)
m_ptr[i] = (unsigned char)(i-sz); {
break; if (i - sz < 0x100)
{
m_ptr[i] = (unsigned char) (i - sz);
break;
}
m_ptr[i] = 0xFF;
} }
m_ptr[i] = 0xFF; m_ptr[sz] = MAGICBYTE (p);
} return (void *) m_ptr;
m_ptr[sz] = MAGICBYTE(p);
return (void*)m_ptr;
} }
/* Convert a pointer to be free()d or realloc()ed to a valid chunk /* Convert a pointer to be free()d or realloc()ed to a valid chunk
@ -150,53 +156,64 @@ mem2mem_check(void *ptr, size_t sz)
static mchunkptr static mchunkptr
internal_function internal_function
mem2chunk_check(void* mem, unsigned char **magic_p) mem2chunk_check (void *mem, unsigned char **magic_p)
{ {
mchunkptr p; mchunkptr p;
INTERNAL_SIZE_T sz, c; INTERNAL_SIZE_T sz, c;
unsigned char magic; unsigned char magic;
if(!aligned_OK(mem)) return NULL; if (!aligned_OK (mem))
p = mem2chunk(mem); return NULL;
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 = GLRO(dl_pagesize)-1;
/* mmap()ed chunks have MALLOC_ALIGNMENT or higher power-of-two p = mem2chunk (mem);
alignment relative to the beginning of a page. Check this if (!chunk_is_mmapped (p))
first. */ {
offset = (unsigned long)mem & page_mask; /* Must be a chunk in conventional heap memory. */
if((offset!=MALLOC_ALIGNMENT && offset!=0 && offset!=0x10 && int contig = contiguous (&main_arena);
offset!=0x20 && offset!=0x40 && offset!=0x80 && offset!=0x100 && sz = chunksize (p);
offset!=0x200 && offset!=0x400 && offset!=0x800 && offset!=0x1000 && if ((contig &&
offset<0x2000) || ((char *) p < mp_.sbrk_base ||
!chunk_is_mmapped(p) || (p->size & PREV_INUSE) || ((char *) p + sz) >= (mp_.sbrk_base + main_arena.system_mem))) ||
( (((unsigned long)p - p->prev_size) & page_mask) != 0 ) || sz < MINSIZE || sz & MALLOC_ALIGN_MASK || !inuse (p) ||
( (sz = chunksize(p)), ((p->prev_size + sz) & page_mask) != 0 ) ) (!prev_inuse (p) && (p->prev_size & MALLOC_ALIGN_MASK ||
return NULL; (contig && (char *) prev_chunk (p) < mp_.sbrk_base) ||
magic = MAGICBYTE(p); next_chunk (prev_chunk (p)) != p)))
for(sz -= 1; (c = ((unsigned char*)p)[sz]) != magic; sz -= c) { return NULL;
if(c<=0 || sz<(c+2*SIZE_SZ)) 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 char*)p)[sz] ^= 0xFF; {
unsigned long offset, page_mask = GLRO (dl_pagesize) - 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) if (magic_p)
*magic_p = (unsigned char *)p + sz; *magic_p = (unsigned char *) p + sz;
return p; return p;
} }
@ -205,32 +222,32 @@ mem2chunk_check(void* mem, unsigned char **magic_p)
static int static int
internal_function internal_function
top_check(void) top_check (void)
{ {
mchunkptr t = top(&main_arena); mchunkptr t = top (&main_arena);
char* brk, * new_brk; char *brk, *new_brk;
INTERNAL_SIZE_T front_misalign, sbrk_size; INTERNAL_SIZE_T front_misalign, sbrk_size;
unsigned long pagesz = GLRO(dl_pagesize); unsigned long pagesz = GLRO (dl_pagesize);
if (t == initial_top(&main_arena) || if (t == initial_top (&main_arena) ||
(!chunk_is_mmapped(t) && (!chunk_is_mmapped (t) &&
chunksize(t)>=MINSIZE && chunksize (t) >= MINSIZE &&
prev_inuse(t) && prev_inuse (t) &&
(!contiguous(&main_arena) || (!contiguous (&main_arena) ||
(char*)t + chunksize(t) == mp_.sbrk_base + main_arena.system_mem))) (char *) t + chunksize (t) == mp_.sbrk_base + main_arena.system_mem)))
return 0; return 0;
malloc_printerr (check_action, "malloc: top chunk is corrupt", t); malloc_printerr (check_action, "malloc: top chunk is corrupt", t);
/* Try to set up a new top chunk. */ /* Try to set up a new top chunk. */
brk = MORECORE(0); brk = MORECORE (0);
front_misalign = (unsigned long)chunk2mem(brk) & MALLOC_ALIGN_MASK; front_misalign = (unsigned long) chunk2mem (brk) & MALLOC_ALIGN_MASK;
if (front_misalign > 0) if (front_misalign > 0)
front_misalign = MALLOC_ALIGNMENT - front_misalign; front_misalign = MALLOC_ALIGNMENT - front_misalign;
sbrk_size = front_misalign + mp_.top_pad + MINSIZE; sbrk_size = front_misalign + mp_.top_pad + MINSIZE;
sbrk_size += pagesz - ((unsigned long)(brk + sbrk_size) & (pagesz - 1)); sbrk_size += pagesz - ((unsigned long) (brk + sbrk_size) & (pagesz - 1));
new_brk = (char*)(MORECORE (sbrk_size)); new_brk = (char *) (MORECORE (sbrk_size));
if (new_brk == (char*)(MORECORE_FAILURE)) if (new_brk == (char *) (MORECORE_FAILURE))
{ {
__set_errno (ENOMEM); __set_errno (ENOMEM);
return -1; return -1;
@ -238,128 +255,148 @@ top_check(void)
/* Call the `morecore' hook if necessary. */ /* Call the `morecore' hook if necessary. */
void (*hook) (void) = atomic_forced_read (__after_morecore_hook); void (*hook) (void) = atomic_forced_read (__after_morecore_hook);
if (hook) if (hook)
(*hook) (); (*hook)();
main_arena.system_mem = (new_brk - mp_.sbrk_base) + sbrk_size; main_arena.system_mem = (new_brk - mp_.sbrk_base) + sbrk_size;
top(&main_arena) = (mchunkptr)(brk + front_misalign); top (&main_arena) = (mchunkptr) (brk + front_misalign);
set_head(top(&main_arena), (sbrk_size - front_misalign) | PREV_INUSE); set_head (top (&main_arena), (sbrk_size - front_misalign) | PREV_INUSE);
return 0; return 0;
} }
static void* static void *
malloc_check(size_t sz, const void *caller) malloc_check (size_t sz, const void *caller)
{ {
void *victim; void *victim;
if (sz+1 == 0) { if (sz + 1 == 0)
__set_errno (ENOMEM); {
return NULL; __set_errno (ENOMEM);
} return NULL;
}
(void)mutex_lock(&main_arena.mutex); (void) mutex_lock (&main_arena.mutex);
victim = (top_check() >= 0) ? _int_malloc(&main_arena, sz+1) : NULL; victim = (top_check () >= 0) ? _int_malloc (&main_arena, sz + 1) : NULL;
(void)mutex_unlock(&main_arena.mutex); (void) mutex_unlock (&main_arena.mutex);
return mem2mem_check(victim, sz); return mem2mem_check (victim, sz);
} }
static void static void
free_check(void* mem, const void *caller) free_check (void *mem, const void *caller)
{ {
mchunkptr p; mchunkptr p;
if(!mem) return; if (!mem)
(void)mutex_lock(&main_arena.mutex); return;
p = mem2chunk_check(mem, NULL);
if(!p) {
(void)mutex_unlock(&main_arena.mutex);
malloc_printerr(check_action, "free(): invalid pointer", mem); (void) mutex_lock (&main_arena.mutex);
return; p = mem2chunk_check (mem, NULL);
} if (!p)
if (chunk_is_mmapped(p)) { {
(void)mutex_unlock(&main_arena.mutex); (void) mutex_unlock (&main_arena.mutex);
munmap_chunk(p);
return; malloc_printerr (check_action, "free(): invalid pointer", mem);
} return;
_int_free(&main_arena, p, 1); }
(void)mutex_unlock(&main_arena.mutex); if (chunk_is_mmapped (p))
{
(void) mutex_unlock (&main_arena.mutex);
munmap_chunk (p);
return;
}
_int_free (&main_arena, p, 1);
(void) mutex_unlock (&main_arena.mutex);
} }
static void* static void *
realloc_check(void* oldmem, size_t bytes, const void *caller) realloc_check (void *oldmem, size_t bytes, const void *caller)
{ {
INTERNAL_SIZE_T nb; INTERNAL_SIZE_T nb;
void* newmem = 0; void *newmem = 0;
unsigned char *magic_p; unsigned char *magic_p;
if (bytes+1 == 0) { if (bytes + 1 == 0)
__set_errno (ENOMEM);
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);
const mchunkptr 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);
}
const INTERNAL_SIZE_T oldsize = chunksize(oldp);
checked_request2size(bytes+1, nb);
(void)mutex_lock(&main_arena.mutex);
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. */ __set_errno (ENOMEM);
if(oldsize - SIZE_SZ >= nb) return NULL;
newmem = oldmem; /* do nothing */ }
else { if (oldmem == 0)
/* Must alloc, copy, free. */ return malloc_check (bytes, NULL);
if (top_check() >= 0)
newmem = _int_malloc(&main_arena, bytes+1); if (bytes == 0)
if (newmem) { {
memcpy(newmem, oldmem, oldsize - 2*SIZE_SZ); free_check (oldmem, NULL);
munmap_chunk(oldp); return NULL;
} }
(void) mutex_lock (&main_arena.mutex);
const mchunkptr 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);
}
const INTERNAL_SIZE_T oldsize = chunksize (oldp);
checked_request2size (bytes + 1, nb);
(void) mutex_lock (&main_arena.mutex);
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)
{
memcpy (newmem, oldmem, oldsize - 2 * SIZE_SZ);
munmap_chunk (oldp);
}
}
} }
} }
} else { else
if (top_check() >= 0) { {
INTERNAL_SIZE_T nb; if (top_check () >= 0)
checked_request2size(bytes + 1, nb); {
newmem = _int_realloc(&main_arena, oldp, oldsize, nb); INTERNAL_SIZE_T nb;
checked_request2size (bytes + 1, nb);
newmem = _int_realloc (&main_arena, oldp, oldsize, nb);
}
} }
}
/* mem2chunk_check changed the magic byte in the old chunk. /* mem2chunk_check changed the magic byte in the old chunk.
If newmem is NULL, then the old chunk will still be used though, If newmem is NULL, then the old chunk will still be used though,
so we need to invert that change here. */ so we need to invert that change here. */
if (newmem == NULL) *magic_p ^= 0xFF; if (newmem == NULL)
*magic_p ^= 0xFF;
(void)mutex_unlock(&main_arena.mutex); (void) mutex_unlock (&main_arena.mutex);
return mem2mem_check(newmem, bytes); return mem2mem_check (newmem, bytes);
} }
static void* static void *
memalign_check(size_t alignment, size_t bytes, const void *caller) memalign_check (size_t alignment, size_t bytes, const void *caller)
{ {
void* mem; void *mem;
if (alignment <= MALLOC_ALIGNMENT) return malloc_check(bytes, NULL); if (alignment <= MALLOC_ALIGNMENT)
if (alignment < MINSIZE) alignment = MINSIZE; return malloc_check (bytes, NULL);
if (alignment < MINSIZE)
alignment = MINSIZE;
/* If the alignment is greater than SIZE_MAX / 2 + 1 it cannot be a /* If the alignment is greater than SIZE_MAX / 2 + 1 it cannot be a
power of 2 and will cause overflow in the check below. */ power of 2 and will cause overflow in the check below. */
@ -377,17 +414,19 @@ memalign_check(size_t alignment, size_t bytes, const void *caller)
} }
/* Make sure alignment is power of 2. */ /* Make sure alignment is power of 2. */
if (!powerof2(alignment)) { if (!powerof2 (alignment))
size_t a = MALLOC_ALIGNMENT * 2; {
while (a < alignment) a <<= 1; size_t a = MALLOC_ALIGNMENT * 2;
alignment = a; while (a < alignment)
} a <<= 1;
alignment = a;
}
(void)mutex_lock(&main_arena.mutex); (void) mutex_lock (&main_arena.mutex);
mem = (top_check() >= 0) ? _int_memalign(&main_arena, alignment, bytes+1) : mem = (top_check () >= 0) ? _int_memalign (&main_arena, alignment, bytes + 1) :
NULL; NULL;
(void)mutex_unlock(&main_arena.mutex); (void) mutex_unlock (&main_arena.mutex);
return mem2mem_check(mem, bytes); return mem2mem_check (mem, bytes);
} }
@ -408,59 +447,63 @@ memalign_check(size_t alignment, size_t bytes, const void *caller)
then the hooks are reset to 0. */ then the hooks are reset to 0. */
#define MALLOC_STATE_MAGIC 0x444c4541l #define MALLOC_STATE_MAGIC 0x444c4541l
#define MALLOC_STATE_VERSION (0*0x100l + 4l) /* major*0x100 + minor */ #define MALLOC_STATE_VERSION (0 * 0x100l + 4l) /* major*0x100 + minor */
struct malloc_save_state { struct malloc_save_state
long magic; {
long version; long magic;
mbinptr av[NBINS * 2 + 2]; long version;
char* sbrk_base; mbinptr av[NBINS * 2 + 2];
int sbrked_mem_bytes; char *sbrk_base;
int sbrked_mem_bytes;
unsigned long trim_threshold; unsigned long trim_threshold;
unsigned long top_pad; unsigned long top_pad;
unsigned int n_mmaps_max; unsigned int n_mmaps_max;
unsigned long mmap_threshold; unsigned long mmap_threshold;
int check_action; int check_action;
unsigned long max_sbrked_mem; unsigned long max_sbrked_mem;
unsigned long max_total_mem; unsigned long max_total_mem;
unsigned int n_mmaps; unsigned int n_mmaps;
unsigned int max_n_mmaps; unsigned int max_n_mmaps;
unsigned long mmapped_mem; unsigned long mmapped_mem;
unsigned long max_mmapped_mem; unsigned long max_mmapped_mem;
int using_malloc_checking; int using_malloc_checking;
unsigned long max_fast; unsigned long max_fast;
unsigned long arena_test; unsigned long arena_test;
unsigned long arena_max; unsigned long arena_max;
unsigned long narenas; unsigned long narenas;
}; };
void* void *
__malloc_get_state(void) __malloc_get_state (void)
{ {
struct malloc_save_state* ms; struct malloc_save_state *ms;
int i; int i;
mbinptr b; mbinptr b;
ms = (struct malloc_save_state*)__libc_malloc(sizeof(*ms)); ms = (struct malloc_save_state *) __libc_malloc (sizeof (*ms));
if (!ms) if (!ms)
return 0; return 0;
(void)mutex_lock(&main_arena.mutex);
malloc_consolidate(&main_arena); (void) mutex_lock (&main_arena.mutex);
malloc_consolidate (&main_arena);
ms->magic = MALLOC_STATE_MAGIC; ms->magic = MALLOC_STATE_MAGIC;
ms->version = MALLOC_STATE_VERSION; ms->version = MALLOC_STATE_VERSION;
ms->av[0] = 0; ms->av[0] = 0;
ms->av[1] = 0; /* used to be binblocks, now no longer used */ ms->av[1] = 0; /* used to be binblocks, now no longer used */
ms->av[2] = top(&main_arena); ms->av[2] = top (&main_arena);
ms->av[3] = 0; /* used to be undefined */ ms->av[3] = 0; /* used to be undefined */
for(i=1; i<NBINS; i++) { for (i = 1; i < NBINS; i++)
b = bin_at(&main_arena, i); {
if(first(b) == b) b = bin_at (&main_arena, i);
ms->av[2*i+2] = ms->av[2*i+3] = 0; /* empty bin */ if (first (b) == b)
else { ms->av[2 * i + 2] = ms->av[2 * i + 3] = 0; /* empty bin */
ms->av[2*i+2] = first(b); else
ms->av[2*i+3] = last(b); {
ms->av[2 * i + 2] = first (b);
ms->av[2 * i + 3] = last (b);
}
} }
}
ms->sbrk_base = mp_.sbrk_base; ms->sbrk_base = mp_.sbrk_base;
ms->sbrked_mem_bytes = main_arena.system_mem; ms->sbrked_mem_bytes = main_arena.system_mem;
ms->trim_threshold = mp_.trim_threshold; ms->trim_threshold = mp_.trim_threshold;
@ -475,78 +518,92 @@ __malloc_get_state(void)
ms->mmapped_mem = mp_.mmapped_mem; ms->mmapped_mem = mp_.mmapped_mem;
ms->max_mmapped_mem = mp_.max_mmapped_mem; ms->max_mmapped_mem = mp_.max_mmapped_mem;
ms->using_malloc_checking = using_malloc_checking; ms->using_malloc_checking = using_malloc_checking;
ms->max_fast = get_max_fast(); ms->max_fast = get_max_fast ();
ms->arena_test = mp_.arena_test; ms->arena_test = mp_.arena_test;
ms->arena_max = mp_.arena_max; ms->arena_max = mp_.arena_max;
ms->narenas = narenas; ms->narenas = narenas;
(void)mutex_unlock(&main_arena.mutex); (void) mutex_unlock (&main_arena.mutex);
return (void*)ms; return (void *) ms;
} }
int int
__malloc_set_state(void* msptr) __malloc_set_state (void *msptr)
{ {
struct malloc_save_state* ms = (struct malloc_save_state*)msptr; struct malloc_save_state *ms = (struct malloc_save_state *) msptr;
size_t i; size_t i;
mbinptr b; mbinptr b;
disallow_malloc_check = 1; disallow_malloc_check = 1;
ptmalloc_init(); ptmalloc_init ();
if(ms->magic != MALLOC_STATE_MAGIC) return -1; if (ms->magic != MALLOC_STATE_MAGIC)
return -1;
/* Must fail if the major version is too high. */ /* Must fail if the major version is too high. */
if((ms->version & ~0xffl) > (MALLOC_STATE_VERSION & ~0xffl)) return -2; if ((ms->version & ~0xffl) > (MALLOC_STATE_VERSION & ~0xffl))
(void)mutex_lock(&main_arena.mutex); return -2;
(void) mutex_lock (&main_arena.mutex);
/* There are no fastchunks. */ /* There are no fastchunks. */
clear_fastchunks(&main_arena); clear_fastchunks (&main_arena);
if (ms->version >= 4) if (ms->version >= 4)
set_max_fast(ms->max_fast); set_max_fast (ms->max_fast);
else else
set_max_fast(64); /* 64 used to be the value we always used. */ set_max_fast (64); /* 64 used to be the value we always used. */
for (i=0; i<NFASTBINS; ++i) for (i = 0; i < NFASTBINS; ++i)
fastbin (&main_arena, i) = 0; fastbin (&main_arena, i) = 0;
for (i=0; i<BINMAPSIZE; ++i) for (i = 0; i < BINMAPSIZE; ++i)
main_arena.binmap[i] = 0; main_arena.binmap[i] = 0;
top(&main_arena) = ms->av[2]; top (&main_arena) = ms->av[2];
main_arena.last_remainder = 0; main_arena.last_remainder = 0;
for(i=1; i<NBINS; i++) { for (i = 1; i < NBINS; i++)
b = bin_at(&main_arena, i); {
if(ms->av[2*i+2] == 0) { b = bin_at (&main_arena, i);
assert(ms->av[2*i+3] == 0); if (ms->av[2 * i + 2] == 0)
first(b) = last(b) = b; {
} else { assert (ms->av[2 * i + 3] == 0);
if(ms->version >= 3 && first (b) = last (b) = b;
(i<NSMALLBINS || (largebin_index(chunksize(ms->av[2*i+2]))==i && }
largebin_index(chunksize(ms->av[2*i+3]))==i))) { else
first(b) = ms->av[2*i+2]; {
last(b) = ms->av[2*i+3]; if (ms->version >= 3 &&
/* Make sure the links to the bins within the heap are correct. */ (i < NSMALLBINS || (largebin_index (chunksize (ms->av[2 * i + 2])) == i &&
first(b)->bk = b; largebin_index (chunksize (ms->av[2 * i + 3])) == i)))
last(b)->fd = b; {
/* Set bit in binblocks. */ first (b) = ms->av[2 * i + 2];
mark_bin(&main_arena, i); last (b) = ms->av[2 * i + 3];
} else { /* Make sure the links to the bins within the heap are correct. */
/* Oops, index computation from chunksize must have changed. first (b)->bk = b;
Link the whole list into unsorted_chunks. */ last (b)->fd = b;
first(b) = last(b) = b; /* Set bit in binblocks. */
b = unsorted_chunks(&main_arena); mark_bin (&main_arena, i);
ms->av[2*i+2]->bk = b; }
ms->av[2*i+3]->fd = b->fd; else
b->fd->bk = ms->av[2*i+3]; {
b->fd = ms->av[2*i+2]; /* 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)
if (ms->version < 3) { {
/* Clear fd_nextsize and bk_nextsize fields. */ /* Clear fd_nextsize and bk_nextsize fields. */
b = unsorted_chunks(&main_arena)->fd; b = unsorted_chunks (&main_arena)->fd;
while (b != unsorted_chunks(&main_arena)) { while (b != unsorted_chunks (&main_arena))
if (!in_smallbin_range(chunksize(b))) { {
b->fd_nextsize = NULL; if (!in_smallbin_range (chunksize (b)))
b->bk_nextsize = NULL; {
} b->fd_nextsize = NULL;
b = b->fd; b->bk_nextsize = NULL;
}
b = b->fd;
}
} }
}
mp_.sbrk_base = ms->sbrk_base; mp_.sbrk_base = ms->sbrk_base;
main_arena.system_mem = ms->sbrked_mem_bytes; main_arena.system_mem = ms->sbrked_mem_bytes;
mp_.trim_threshold = ms->trim_threshold; mp_.trim_threshold = ms->trim_threshold;
@ -560,28 +617,31 @@ __malloc_set_state(void* msptr)
mp_.mmapped_mem = ms->mmapped_mem; mp_.mmapped_mem = ms->mmapped_mem;
mp_.max_mmapped_mem = ms->max_mmapped_mem; mp_.max_mmapped_mem = ms->max_mmapped_mem;
/* add version-dependent code here */ /* add version-dependent code here */
if (ms->version >= 1) { if (ms->version >= 1)
/* Check whether it is safe to enable malloc checking, or whether {
it is necessary to disable it. */ /* Check whether it is safe to enable malloc checking, or whether
if (ms->using_malloc_checking && !using_malloc_checking && it is necessary to disable it. */
!disallow_malloc_check) if (ms->using_malloc_checking && !using_malloc_checking &&
__malloc_check_init (); !disallow_malloc_check)
else if (!ms->using_malloc_checking && using_malloc_checking) { __malloc_check_init ();
__malloc_hook = NULL; else if (!ms->using_malloc_checking && using_malloc_checking)
__free_hook = NULL; {
__realloc_hook = NULL; __malloc_hook = NULL;
__memalign_hook = NULL; __free_hook = NULL;
using_malloc_checking = 0; __realloc_hook = NULL;
__memalign_hook = NULL;
using_malloc_checking = 0;
}
} }
} if (ms->version >= 4)
if (ms->version >= 4) { {
mp_.arena_test = ms->arena_test; mp_.arena_test = ms->arena_test;
mp_.arena_max = ms->arena_max; mp_.arena_max = ms->arena_max;
narenas = ms->narenas; narenas = ms->narenas;
} }
check_malloc_state(&main_arena); check_malloc_state (&main_arena);
(void)mutex_unlock(&main_arena.mutex); (void) mutex_unlock (&main_arena.mutex);
return 0; return 0;
} }

File diff suppressed because it is too large Load Diff

View File

@ -39,7 +39,7 @@ extern void *malloc (size_t __size) __THROW __attribute_malloc__ __wur;
/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ /* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
extern void *calloc (size_t __nmemb, size_t __size) extern void *calloc (size_t __nmemb, size_t __size)
__THROW __attribute_malloc__ __wur; __THROW __attribute_malloc__ __wur;
/* Re-allocate the previously allocated block in __ptr, making the new /* Re-allocate the previously allocated block in __ptr, making the new
block SIZE bytes long. */ block SIZE bytes long. */
@ -47,7 +47,7 @@ extern void *calloc (size_t __nmemb, size_t __size)
the same pointer that was passed to it, aliasing needs to be allowed the same pointer that was passed to it, aliasing needs to be allowed
between objects pointed by the old and new pointers. */ between objects pointed by the old and new pointers. */
extern void *realloc (void *__ptr, size_t __size) extern void *realloc (void *__ptr, size_t __size)
__THROW __attribute_warn_unused_result__; __THROW __attribute_warn_unused_result__;
/* Free a block allocated by `malloc', `realloc' or `calloc'. */ /* Free a block allocated by `malloc', `realloc' or `calloc'. */
extern void free (void *__ptr) __THROW; extern void free (void *__ptr) __THROW;
@ -57,14 +57,14 @@ extern void cfree (void *__ptr) __THROW;
/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ /* Allocate SIZE bytes allocated to ALIGNMENT bytes. */
extern void *memalign (size_t __alignment, size_t __size) extern void *memalign (size_t __alignment, size_t __size)
__THROW __attribute_malloc__ __wur; __THROW __attribute_malloc__ __wur;
/* Allocate SIZE bytes on a page boundary. */ /* Allocate SIZE bytes on a page boundary. */
extern void *valloc (size_t __size) __THROW __attribute_malloc__ __wur; extern void *valloc (size_t __size) __THROW __attribute_malloc__ __wur;
/* Equivalent to valloc(minimum-page-that-holds(n)), that is, round up /* Equivalent to valloc(minimum-page-that-holds(n)), that is, round up
__size to nearest pagesize. */ __size to nearest pagesize. */
extern void * pvalloc (size_t __size) __THROW __attribute_malloc__ __wur; extern void *pvalloc (size_t __size) __THROW __attribute_malloc__ __wur;
/* Underlying allocation function; successive calls should return /* Underlying allocation function; successive calls should return
contiguous pieces of memory. */ contiguous pieces of memory. */
@ -72,7 +72,7 @@ extern void *(*__morecore) (ptrdiff_t __size);
/* Default value of `__morecore'. */ /* Default value of `__morecore'. */
extern void *__default_morecore (ptrdiff_t __size) extern void *__default_morecore (ptrdiff_t __size)
__THROW __attribute_malloc__; __THROW __attribute_malloc__;
/* SVID2/XPG mallinfo structure */ /* SVID2/XPG mallinfo structure */
@ -95,16 +95,16 @@ extern struct mallinfo mallinfo (void) __THROW;
/* SVID2/XPG mallopt options */ /* SVID2/XPG mallopt options */
#ifndef M_MXFAST #ifndef M_MXFAST
# define M_MXFAST 1 /* maximum request size for "fastbins" */ # define M_MXFAST 1 /* maximum request size for "fastbins" */
#endif #endif
#ifndef M_NLBLKS #ifndef M_NLBLKS
# define M_NLBLKS 2 /* UNUSED in this malloc */ # define M_NLBLKS 2 /* UNUSED in this malloc */
#endif #endif
#ifndef M_GRAIN #ifndef M_GRAIN
# define M_GRAIN 3 /* UNUSED in this malloc */ # define M_GRAIN 3 /* UNUSED in this malloc */
#endif #endif
#ifndef M_KEEP #ifndef M_KEEP
# define M_KEEP 4 /* UNUSED in this malloc */ # define M_KEEP 4 /* UNUSED in this malloc */
#endif #endif
/* mallopt options that actually do something */ /* mallopt options that actually do something */
@ -113,9 +113,9 @@ extern struct mallinfo mallinfo (void) __THROW;
#define M_MMAP_THRESHOLD -3 #define M_MMAP_THRESHOLD -3
#define M_MMAP_MAX -4 #define M_MMAP_MAX -4
#define M_CHECK_ACTION -5 #define M_CHECK_ACTION -5
#define M_PERTURB -6 #define M_PERTURB -6
#define M_ARENA_TEST -7 #define M_ARENA_TEST -7
#define M_ARENA_MAX -8 #define M_ARENA_MAX -8
/* General SVID/XPG interface to tunable parameters. */ /* General SVID/XPG interface to tunable parameters. */
extern int mallopt (int __param, int __val) __THROW; extern int mallopt (int __param, int __val) __THROW;
@ -145,22 +145,22 @@ extern int malloc_set_state (void *__ptr) __THROW;
the application provides the preferred way to set up the hook the application provides the preferred way to set up the hook
pointers. */ pointers. */
extern void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void) extern void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void)
__MALLOC_DEPRECATED; __MALLOC_DEPRECATED;
/* Hooks for debugging and user-defined versions. */ /* Hooks for debugging and user-defined versions. */
extern void (*__MALLOC_HOOK_VOLATILE __free_hook) (void *__ptr, extern void (*__MALLOC_HOOK_VOLATILE __free_hook) (void *__ptr,
const void *) const void *)
__MALLOC_DEPRECATED; __MALLOC_DEPRECATED;
extern void *(*__MALLOC_HOOK_VOLATILE __malloc_hook) (size_t __size, extern void *(*__MALLOC_HOOK_VOLATILE __malloc_hook)(size_t __size,
const void *) const void *)
__MALLOC_DEPRECATED; __MALLOC_DEPRECATED;
extern void *(*__MALLOC_HOOK_VOLATILE __realloc_hook) (void *__ptr, extern void *(*__MALLOC_HOOK_VOLATILE __realloc_hook)(void *__ptr,
size_t __size, size_t __size,
const void *) const void *)
__MALLOC_DEPRECATED; __MALLOC_DEPRECATED;
extern void *(*__MALLOC_HOOK_VOLATILE __memalign_hook) (size_t __alignment, extern void *(*__MALLOC_HOOK_VOLATILE __memalign_hook)(size_t __alignment,
size_t __size, size_t __size,
const void *) const void *)
__MALLOC_DEPRECATED; __MALLOC_DEPRECATED;
extern void (*__MALLOC_HOOK_VOLATILE __after_morecore_hook) (void); extern void (*__MALLOC_HOOK_VOLATILE __after_morecore_hook) (void);
/* Activate a standard set of debugging hooks. */ /* Activate a standard set of debugging hooks. */
@ -168,5 +168,4 @@ extern void __malloc_check_init (void) __THROW __MALLOC_DEPRECATED;
__END_DECLS __END_DECLS
#endif /* malloc.h */ #endif /* malloc.h */

View File

@ -22,14 +22,14 @@ main (int argc, char *argv[])
size_t i; size_t i;
/* Here's what memory is supposed to look like (hex): /* Here's what memory is supposed to look like (hex):
size contents size contents
3000 original_info_table, later fill_info_table1 3000 original_info_table, later fill_info_table1
3fa000 dummy0 3fa000 dummy0
3fa000 dummy1 3fa000 dummy1
6000 info_table_2 6000 info_table_2
3000 over_top 3000 over_top
*/ */
/* mem: original_info_table */ /* mem: original_info_table */
dummy0 = malloc (0x3fa000); dummy0 = malloc (0x3fa000);
/* mem: original_info_table, dummy0 */ /* mem: original_info_table, dummy0 */
@ -54,15 +54,15 @@ main (int argc, char *argv[])
for (i = 0; i < over_top_size; ++i) for (i = 0; i < over_top_size; ++i)
if (over_top[i] != 0) if (over_top[i] != 0)
{ {
printf ("FAIL: malloc expands info table\n"); printf ("FAIL: malloc expands info table\n");
return 0; return 0;
} }
for (i = 0; i < over_top_dup_size; ++i) for (i = 0; i < over_top_dup_size; ++i)
if (over_top_dup[i] != 1) if (over_top_dup[i] != 1)
{ {
printf ("FAIL: malloc expands info table\n"); printf ("FAIL: malloc expands info table\n");
return 0; return 0;
} }
printf ("PASS: malloc expands info table\n"); printf ("PASS: malloc expands info table\n");

View File

@ -17,7 +17,7 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#ifndef _MALLOC_INTERNAL #ifndef _MALLOC_INTERNAL
# define _MALLOC_INTERNAL # define _MALLOC_INTERNAL
# include <malloc.h> # include <malloc.h>
# include <mcheck.h> # include <mcheck.h>
@ -28,32 +28,32 @@
#endif #endif
/* Old hook values. */ /* Old hook values. */
static void (*old_free_hook) (__ptr_t ptr, const __ptr_t); static void (*old_free_hook)(__ptr_t ptr, const __ptr_t);
static __ptr_t (*old_malloc_hook) (size_t size, const __ptr_t); static __ptr_t (*old_malloc_hook) (size_t size, const __ptr_t);
static __ptr_t (*old_memalign_hook) (size_t alignment, size_t size, static __ptr_t (*old_memalign_hook) (size_t alignment, size_t size,
const __ptr_t); const __ptr_t);
static __ptr_t (*old_realloc_hook) (__ptr_t ptr, size_t size, static __ptr_t (*old_realloc_hook) (__ptr_t ptr, size_t size,
const __ptr_t); const __ptr_t);
/* Function to call when something awful happens. */ /* Function to call when something awful happens. */
static void (*abortfunc) (enum mcheck_status); static void (*abortfunc) (enum mcheck_status);
/* Arbitrary magical numbers. */ /* Arbitrary magical numbers. */
#define MAGICWORD 0xfedabeeb #define MAGICWORD 0xfedabeeb
#define MAGICFREE 0xd8675309 #define MAGICFREE 0xd8675309
#define MAGICBYTE ((char) 0xd7) #define MAGICBYTE ((char) 0xd7)
#define MALLOCFLOOD ((char) 0x93) #define MALLOCFLOOD ((char) 0x93)
#define FREEFLOOD ((char) 0x95) #define FREEFLOOD ((char) 0x95)
struct hdr struct hdr
{ {
size_t size; /* Exact size requested by user. */ size_t size; /* Exact size requested by user. */
unsigned long int magic; /* Magic number to check header integrity. */ unsigned long int magic; /* Magic number to check header integrity. */
struct hdr *prev; struct hdr *prev;
struct hdr *next; struct hdr *next;
__ptr_t block; /* Real block allocated, for memalign. */ __ptr_t block; /* Real block allocated, for memalign. */
unsigned long int magic2; /* Extra, keeps us doubleword aligned. */ unsigned long int magic2; /* Extra, keeps us doubleword aligned. */
}; };
/* This is the beginning of the list of all memory blocks allocated. /* This is the beginning of the list of all memory blocks allocated.
It is only constructed if the pedantic testing is requested. */ It is only constructed if the pedantic testing is requested. */
@ -69,11 +69,10 @@ static int pedantic;
# define flood memset # define flood memset
#else #else
static void flood (__ptr_t, int, size_t); static void flood (__ptr_t, int, size_t);
static void static void flood (ptr, val, size)
flood (ptr, val, size) __ptr_t ptr;
__ptr_t ptr; int val;
int val; size_t size;
size_t size;
{ {
char *cp = ptr; char *cp = ptr;
while (size--) while (size--)
@ -101,11 +100,11 @@ checkhdr (const struct hdr *hdr)
break; break;
case MAGICWORD: case MAGICWORD:
if (((char *) &hdr[1])[hdr->size] != MAGICBYTE) if (((char *) &hdr[1])[hdr->size] != MAGICBYTE)
status = MCHECK_TAIL; status = MCHECK_TAIL;
else if ((hdr->magic2 ^ (uintptr_t) hdr->block) != MAGICWORD) else if ((hdr->magic2 ^ (uintptr_t) hdr->block) != MAGICWORD)
status = MCHECK_HEAD; status = MCHECK_HEAD;
else else
status = MCHECK_OK; status = MCHECK_OK;
break; break;
} }
if (status != MCHECK_OK) if (status != MCHECK_OK)
@ -148,13 +147,13 @@ unlink_blk (struct hdr *ptr)
{ {
ptr->next->prev = ptr->prev; ptr->next->prev = ptr->prev;
ptr->next->magic = MAGICWORD ^ ((uintptr_t) ptr->next->prev ptr->next->magic = MAGICWORD ^ ((uintptr_t) ptr->next->prev
+ (uintptr_t) ptr->next->next); + (uintptr_t) ptr->next->next);
} }
if (ptr->prev != NULL) if (ptr->prev != NULL)
{ {
ptr->prev->next = ptr->next; ptr->prev->next = ptr->next;
ptr->prev->magic = MAGICWORD ^ ((uintptr_t) ptr->prev->prev ptr->prev->magic = MAGICWORD ^ ((uintptr_t) ptr->prev->prev
+ (uintptr_t) ptr->prev->next); + (uintptr_t) ptr->prev->next);
} }
else else
root = ptr->next; root = ptr->next;
@ -173,7 +172,7 @@ link_blk (struct hdr *hdr)
{ {
hdr->next->prev = hdr; hdr->next->prev = hdr;
hdr->next->magic = MAGICWORD ^ ((uintptr_t) hdr hdr->next->magic = MAGICWORD ^ ((uintptr_t) hdr
+ (uintptr_t) hdr->next->next); + (uintptr_t) hdr->next->next);
} }
} }
static void static void
@ -194,7 +193,7 @@ freehook (__ptr_t ptr, const __ptr_t caller)
} }
__free_hook = old_free_hook; __free_hook = old_free_hook;
if (old_free_hook != NULL) if (old_free_hook != NULL)
(*old_free_hook) (ptr, caller); (*old_free_hook)(ptr, caller);
else else
free (ptr); free (ptr);
__free_hook = freehook; __free_hook = freehook;
@ -216,8 +215,8 @@ mallochook (size_t size, const __ptr_t caller)
__malloc_hook = old_malloc_hook; __malloc_hook = old_malloc_hook;
if (old_malloc_hook != NULL) if (old_malloc_hook != NULL)
hdr = (struct hdr *) (*old_malloc_hook) (sizeof (struct hdr) + size + 1, hdr = (struct hdr *) (*old_malloc_hook)(sizeof (struct hdr) + size + 1,
caller); caller);
else else
hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1); hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1);
__malloc_hook = mallochook; __malloc_hook = mallochook;
@ -235,7 +234,7 @@ mallochook (size_t size, const __ptr_t caller)
static __ptr_t static __ptr_t
memalignhook (size_t alignment, size_t size, memalignhook (size_t alignment, size_t size,
const __ptr_t caller) const __ptr_t caller)
{ {
struct hdr *hdr; struct hdr *hdr;
size_t slop; size_t slop;
@ -244,7 +243,7 @@ memalignhook (size_t alignment, size_t size,
if (pedantic) if (pedantic)
mcheck_check_all (); mcheck_check_all ();
slop = (sizeof *hdr + alignment - 1) & -alignment; slop = (sizeof *hdr + alignment - 1) & - alignment;
if (size > ~((size_t) 0) - (slop + 1)) if (size > ~((size_t) 0) - (slop + 1))
{ {
@ -254,7 +253,7 @@ memalignhook (size_t alignment, size_t size,
__memalign_hook = old_memalign_hook; __memalign_hook = old_memalign_hook;
if (old_memalign_hook != NULL) if (old_memalign_hook != NULL)
block = (*old_memalign_hook) (alignment, slop + size + 1, caller); block = (*old_memalign_hook)(alignment, slop + size + 1, caller);
else else
block = memalign (alignment, slop + size + 1); block = memalign (alignment, slop + size + 1);
__memalign_hook = memalignhook; __memalign_hook = memalignhook;
@ -301,7 +300,7 @@ reallochook (__ptr_t ptr, size_t size, const __ptr_t caller)
checkhdr (hdr); checkhdr (hdr);
unlink_blk (hdr); unlink_blk (hdr);
if (size < osize) if (size < osize)
flood ((char *) ptr + size, FREEFLOOD, osize - size); flood ((char *) ptr + size, FREEFLOOD, osize - size);
} }
else else
{ {
@ -313,12 +312,12 @@ reallochook (__ptr_t ptr, size_t size, const __ptr_t caller)
__memalign_hook = old_memalign_hook; __memalign_hook = old_memalign_hook;
__realloc_hook = old_realloc_hook; __realloc_hook = old_realloc_hook;
if (old_realloc_hook != NULL) if (old_realloc_hook != NULL)
hdr = (struct hdr *) (*old_realloc_hook) ((__ptr_t) hdr, hdr = (struct hdr *) (*old_realloc_hook)((__ptr_t) hdr,
sizeof (struct hdr) + size + 1, sizeof (struct hdr) + size + 1,
caller); caller);
else else
hdr = (struct hdr *) realloc ((__ptr_t) hdr, hdr = (struct hdr *) realloc ((__ptr_t) hdr,
sizeof (struct hdr) + size + 1); sizeof (struct hdr) + size + 1);
__free_hook = freehook; __free_hook = freehook;
__malloc_hook = mallochook; __malloc_hook = mallochook;
__memalign_hook = memalignhook; __memalign_hook = memalignhook;
@ -344,19 +343,19 @@ mabort (enum mcheck_status status)
switch (status) switch (status)
{ {
case MCHECK_OK: case MCHECK_OK:
msg = _("memory is consistent, library is buggy\n"); msg = _ ("memory is consistent, library is buggy\n");
break; break;
case MCHECK_HEAD: case MCHECK_HEAD:
msg = _("memory clobbered before allocated block\n"); msg = _ ("memory clobbered before allocated block\n");
break; break;
case MCHECK_TAIL: case MCHECK_TAIL:
msg = _("memory clobbered past end of allocated block\n"); msg = _ ("memory clobbered past end of allocated block\n");
break; break;
case MCHECK_FREE: case MCHECK_FREE:
msg = _("block freed twice\n"); msg = _ ("block freed twice\n");
break; break;
default: default:
msg = _("bogus mcheck_status, library is buggy\n"); msg = _ ("bogus mcheck_status, library is buggy\n");
break; break;
} }
#ifdef _LIBC #ifdef _LIBC
@ -370,11 +369,10 @@ mabort (enum mcheck_status status)
/* Memory barrier so that GCC does not optimize out the argument. */ /* Memory barrier so that GCC does not optimize out the argument. */
#define malloc_opt_barrier(x) \ #define malloc_opt_barrier(x) \
({ __typeof (x) __x = x; __asm ("" : "+m" (__x)); __x; }) ({ __typeof (x) __x = x; __asm ("" : "+m" (__x)); __x; })
int int mcheck (func)
mcheck (func) void (*func)(enum mcheck_status);
void (*func) (enum mcheck_status);
{ {
abortfunc = (func != NULL) ? func : &mabort; abortfunc = (func != NULL) ? func : &mabort;
@ -404,9 +402,8 @@ mcheck (func)
libc_hidden_def (mcheck) libc_hidden_def (mcheck)
#endif #endif
int int mcheck_pedantic (func)
mcheck_pedantic (func) void (*func)(enum mcheck_status);
void (*func) (enum mcheck_status);
{ {
int res = mcheck (func); int res = mcheck (func);
if (res == 0) if (res == 0)

View File

@ -16,7 +16,7 @@
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#ifndef _MCHECK_H #ifndef _MCHECK_H
#define _MCHECK_H 1 #define _MCHECK_H 1
#include <features.h> #include <features.h>
@ -25,24 +25,24 @@ __BEGIN_DECLS
/* Return values for `mprobe': these are the kinds of inconsistencies that /* Return values for `mprobe': these are the kinds of inconsistencies that
`mcheck' enables detection of. */ `mcheck' enables detection of. */
enum mcheck_status enum mcheck_status
{ {
MCHECK_DISABLED = -1, /* Consistency checking is not turned on. */ MCHECK_DISABLED = -1, /* Consistency checking is not turned on. */
MCHECK_OK, /* Block is fine. */ MCHECK_OK, /* Block is fine. */
MCHECK_FREE, /* Block freed twice. */ MCHECK_FREE, /* Block freed twice. */
MCHECK_HEAD, /* Memory before the block was clobbered. */ MCHECK_HEAD, /* Memory before the block was clobbered. */
MCHECK_TAIL /* Memory after the block was clobbered. */ MCHECK_TAIL /* Memory after the block was clobbered. */
}; };
/* Activate a standard collection of debugging hooks. This must be called /* Activate a standard collection of debugging hooks. This must be called
before `malloc' is ever called. ABORTFUNC is called with an error code before `malloc' is ever called. ABORTFUNC is called with an error code
(see enum above) when an inconsistency is detected. If ABORTFUNC is (see enum above) when an inconsistency is detected. If ABORTFUNC is
null, the standard function prints on stderr and then calls `abort'. */ null, the standard function prints on stderr and then calls `abort'. */
extern int mcheck (void (*__abortfunc) (enum mcheck_status)) __THROW; extern int mcheck (void (*__abortfunc)(enum mcheck_status)) __THROW;
/* Similar to `mcheck' but performs checks for all block whenever one of /* Similar to `mcheck' but performs checks for all block whenever one of
the memory handling functions is called. This can be very slow. */ the memory handling functions is called. This can be very slow. */
extern int mcheck_pedantic (void (*__abortfunc) (enum mcheck_status)) __THROW; extern int mcheck_pedantic (void (*__abortfunc)(enum mcheck_status)) __THROW;
/* Force check of all blocks now. */ /* Force check of all blocks now. */
extern void mcheck_check_all (void); extern void mcheck_check_all (void);
@ -57,5 +57,4 @@ extern void mtrace (void) __THROW;
extern void muntrace (void) __THROW; extern void muntrace (void) __THROW;
__END_DECLS __END_DECLS
#endif /* mcheck.h */ #endif /* mcheck.h */

View File

@ -38,7 +38,7 @@
/* Pointer to the real functions. These are determined used `dlsym' /* Pointer to the real functions. These are determined used `dlsym'
when really needed. */ when really needed. */
static void *(*mallocp) (size_t); static void *(*mallocp)(size_t);
static void *(*reallocp) (void *, size_t); static void *(*reallocp) (void *, size_t);
static void *(*callocp) (size_t, size_t); static void *(*callocp) (size_t, size_t);
static void (*freep) (void *); static void (*freep) (void *);
@ -89,11 +89,11 @@ static memusage_size_t peak_use[3];
static __thread uintptr_t start_sp; static __thread uintptr_t start_sp;
/* A few macros to make the source more readable. */ /* A few macros to make the source more readable. */
#define peak_heap peak_use[0] #define peak_heap peak_use[0]
#define peak_stack peak_use[1] #define peak_stack peak_use[1]
#define peak_total peak_use[2] #define peak_total peak_use[2]
#define DEFAULT_BUFFER_SIZE 32768 #define DEFAULT_BUFFER_SIZE 32768
static size_t buffer_size; static size_t buffer_size;
static int fd = -1; static int fd = -1;
@ -164,16 +164,16 @@ update_data (struct header *result, size_t len, size_t old_len)
{ {
uatomic32_t idx = catomic_exchange_and_add (&buffer_cnt, 1); uatomic32_t idx = catomic_exchange_and_add (&buffer_cnt, 1);
if (idx + 1 >= 2 * buffer_size) if (idx + 1 >= 2 * buffer_size)
{ {
/* We try to reset the counter to the correct range. If /* We try to reset the counter to the correct range. If
this fails because of another thread increasing the this fails because of another thread increasing the
counter it does not matter since that thread will take counter it does not matter since that thread will take
care of the correction. */ care of the correction. */
uatomic32_t reset = (idx + 1) % (2 * buffer_size); uatomic32_t reset = (idx + 1) % (2 * buffer_size);
catomic_compare_and_exchange_val_acq (&buffer_cnt, reset, idx + 1); catomic_compare_and_exchange_val_acq (&buffer_cnt, reset, idx + 1);
if (idx >= 2 * buffer_size) if (idx >= 2 * buffer_size)
idx = reset - 1; idx = reset - 1;
} }
assert (idx < 2 * DEFAULT_BUFFER_SIZE); assert (idx < 2 * DEFAULT_BUFFER_SIZE);
buffer[idx].heap = current_heap; buffer[idx].heap = current_heap;
@ -182,9 +182,9 @@ update_data (struct header *result, size_t len, size_t old_len)
/* Write out buffer if it is full. */ /* Write out buffer if it is full. */
if (idx + 1 == buffer_size) if (idx + 1 == buffer_size)
write (fd, buffer, buffer_size * sizeof (struct entry)); write (fd, buffer, buffer_size * sizeof (struct entry));
else if (idx + 1 == 2 * buffer_size) else if (idx + 1 == 2 * buffer_size)
write (fd, &buffer[buffer_size], buffer_size * sizeof (struct entry)); write (fd, &buffer[buffer_size], buffer_size * sizeof (struct entry));
} }
} }
@ -221,19 +221,19 @@ me (void)
size_t prog_len = strlen (__progname); size_t prog_len = strlen (__progname);
initialized = -1; initialized = -1;
mallocp = (void *(*) (size_t)) dlsym (RTLD_NEXT, "malloc"); mallocp = (void *(*)(size_t))dlsym (RTLD_NEXT, "malloc");
reallocp = (void *(*) (void *, size_t)) dlsym (RTLD_NEXT, "realloc"); reallocp = (void *(*)(void *, size_t))dlsym (RTLD_NEXT, "realloc");
callocp = (void *(*) (size_t, size_t)) dlsym (RTLD_NEXT, "calloc"); callocp = (void *(*)(size_t, size_t))dlsym (RTLD_NEXT, "calloc");
freep = (void (*) (void *)) dlsym (RTLD_NEXT, "free"); freep = (void (*)(void *))dlsym (RTLD_NEXT, "free");
mmapp = (void *(*) (void *, size_t, int, int, int, off_t)) dlsym (RTLD_NEXT, mmapp = (void *(*)(void *, size_t, int, int, int, off_t))dlsym (RTLD_NEXT,
"mmap"); "mmap");
mmap64p = mmap64p =
(void *(*) (void *, size_t, int, int, int, off64_t)) dlsym (RTLD_NEXT, (void *(*)(void *, size_t, int, int, int, off64_t))dlsym (RTLD_NEXT,
"mmap64"); "mmap64");
mremapp = (void *(*) (void *, size_t, size_t, int, void *)) dlsym (RTLD_NEXT, mremapp = (void *(*)(void *, size_t, size_t, int, void *))dlsym (RTLD_NEXT,
"mremap"); "mremap");
munmapp = (int (*) (void *, size_t)) dlsym (RTLD_NEXT, "munmap"); munmapp = (int (*)(void *, size_t))dlsym (RTLD_NEXT, "munmap");
initialized = 1; initialized = 1;
if (env != NULL) if (env != NULL)
@ -241,8 +241,8 @@ me (void)
/* Check for program name. */ /* Check for program name. */
size_t len = strlen (env); size_t len = strlen (env);
if (len > prog_len || strcmp (env, &__progname[prog_len - len]) != 0 if (len > prog_len || strcmp (env, &__progname[prog_len - len]) != 0
|| (prog_len != len && __progname[prog_len - len - 1] != '/')) || (prog_len != len && __progname[prog_len - len - 1] != '/'))
not_me = true; not_me = true;
} }
/* Only open the file if it's really us. */ /* Only open the file if it's really us. */
@ -251,62 +251,62 @@ me (void)
const char *outname; const char *outname;
if (!start_sp) if (!start_sp)
start_sp = GETSP (); start_sp = GETSP ();
outname = getenv ("MEMUSAGE_OUTPUT"); outname = getenv ("MEMUSAGE_OUTPUT");
if (outname != NULL && outname[0] != '\0' if (outname != NULL && outname[0] != '\0'
&& (access (outname, R_OK | W_OK) == 0 || errno == ENOENT)) && (access (outname, R_OK | W_OK) == 0 || errno == ENOENT))
{ {
fd = creat64 (outname, 0666); fd = creat64 (outname, 0666);
if (fd == -1) if (fd == -1)
/* Don't do anything in future calls if we cannot write to /* Don't do anything in future calls if we cannot write to
the output file. */ the output file. */
not_me = true; not_me = true;
else else
{ {
/* Write the first entry. */ /* Write the first entry. */
first.heap = 0; first.heap = 0;
first.stack = 0; first.stack = 0;
GETTIME (first.time_low, first.time_high); GETTIME (first.time_low, first.time_high);
/* Write it two times since we need the starting and end time. */ /* Write it two times since we need the starting and end time. */
write (fd, &first, sizeof (first)); write (fd, &first, sizeof (first));
write (fd, &first, sizeof (first)); write (fd, &first, sizeof (first));
/* Determine the buffer size. We use the default if the /* Determine the buffer size. We use the default if the
environment variable is not present. */ environment variable is not present. */
buffer_size = DEFAULT_BUFFER_SIZE; buffer_size = DEFAULT_BUFFER_SIZE;
if (getenv ("MEMUSAGE_BUFFER_SIZE") != NULL) if (getenv ("MEMUSAGE_BUFFER_SIZE") != NULL)
{ {
buffer_size = atoi (getenv ("MEMUSAGE_BUFFER_SIZE")); buffer_size = atoi (getenv ("MEMUSAGE_BUFFER_SIZE"));
if (buffer_size == 0 || buffer_size > DEFAULT_BUFFER_SIZE) if (buffer_size == 0 || buffer_size > DEFAULT_BUFFER_SIZE)
buffer_size = DEFAULT_BUFFER_SIZE; buffer_size = DEFAULT_BUFFER_SIZE;
} }
/* Possibly enable timer-based stack pointer retrieval. */ /* Possibly enable timer-based stack pointer retrieval. */
if (getenv ("MEMUSAGE_NO_TIMER") == NULL) if (getenv ("MEMUSAGE_NO_TIMER") == NULL)
{ {
struct sigaction act; struct sigaction act;
act.sa_handler = (sighandler_t) &int_handler; act.sa_handler = (sighandler_t) &int_handler;
act.sa_flags = SA_RESTART; act.sa_flags = SA_RESTART;
sigfillset (&act.sa_mask); sigfillset (&act.sa_mask);
if (sigaction (SIGPROF, &act, NULL) >= 0) if (sigaction (SIGPROF, &act, NULL) >= 0)
{ {
struct itimerval timer; struct itimerval timer;
timer.it_value.tv_sec = 0; timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 1; timer.it_value.tv_usec = 1;
timer.it_interval = timer.it_value; timer.it_interval = timer.it_value;
setitimer (ITIMER_PROF, &timer, NULL); setitimer (ITIMER_PROF, &timer, NULL);
} }
} }
} }
} }
if (!not_me && getenv ("MEMUSAGE_TRACE_MMAP") != NULL) if (!not_me && getenv ("MEMUSAGE_TRACE_MMAP") != NULL)
trace_mmap = true; trace_mmap = true;
} }
} }
@ -317,7 +317,7 @@ __attribute__ ((constructor))
init (void) init (void)
{ {
start_sp = GETSP (); start_sp = GETSP ();
if (! initialized) if (!initialized)
me (); me ();
} }
@ -333,13 +333,14 @@ malloc (size_t len)
if (__builtin_expect (initialized <= 0, 0)) if (__builtin_expect (initialized <= 0, 0))
{ {
if (initialized == -1) if (initialized == -1)
return NULL; return NULL;
me (); me ();
} }
/* If this is not the correct program just use the normal function. */ /* If this is not the correct program just use the normal function. */
if (not_me) if (not_me)
return (*mallocp) (len); return (*mallocp)(len);
/* Keep track of number of calls. */ /* Keep track of number of calls. */
catomic_increment (&calls[idx_malloc]); catomic_increment (&calls[idx_malloc]);
@ -356,7 +357,7 @@ malloc (size_t len)
catomic_increment (&calls_total); catomic_increment (&calls_total);
/* Do the real work. */ /* Do the real work. */
result = (struct header *) (*mallocp) (len + sizeof (struct header)); result = (struct header *) (*mallocp)(len + sizeof (struct header));
if (result == NULL) if (result == NULL)
{ {
catomic_increment (&failed[idx_malloc]); catomic_increment (&failed[idx_malloc]);
@ -384,13 +385,14 @@ realloc (void *old, size_t len)
if (__builtin_expect (initialized <= 0, 0)) if (__builtin_expect (initialized <= 0, 0))
{ {
if (initialized == -1) if (initialized == -1)
return NULL; return NULL;
me (); me ();
} }
/* If this is not the correct program just use the normal function. */ /* If this is not the correct program just use the normal function. */
if (not_me) if (not_me)
return (*reallocp) (old, len); return (*reallocp)(old, len);
if (old == NULL) if (old == NULL)
{ {
@ -402,8 +404,9 @@ realloc (void *old, size_t len)
{ {
real = ((struct header *) old) - 1; real = ((struct header *) old) - 1;
if (real->magic != MAGIC) if (real->magic != MAGIC)
/* This is no memory allocated here. */ /* This is no memory allocated here. */
return (*reallocp) (old, len); return (*reallocp)(old, len);
old_len = real->length; old_len = real->length;
} }
@ -442,7 +445,7 @@ realloc (void *old, size_t len)
catomic_increment (&calls_total); catomic_increment (&calls_total);
/* Do the real work. */ /* Do the real work. */
result = (struct header *) (*reallocp) (real, len + sizeof (struct header)); result = (struct header *) (*reallocp)(real, len + sizeof (struct header));
if (result == NULL) if (result == NULL)
{ {
catomic_increment (&failed[idx_realloc]); catomic_increment (&failed[idx_realloc]);
@ -476,13 +479,14 @@ calloc (size_t n, size_t len)
if (__builtin_expect (initialized <= 0, 0)) if (__builtin_expect (initialized <= 0, 0))
{ {
if (initialized == -1) if (initialized == -1)
return NULL; return NULL;
me (); me ();
} }
/* If this is not the correct program just use the normal function. */ /* If this is not the correct program just use the normal function. */
if (not_me) if (not_me)
return (*callocp) (n, len); return (*callocp)(n, len);
/* Keep track of number of calls. */ /* Keep track of number of calls. */
catomic_increment (&calls[idx_calloc]); catomic_increment (&calls[idx_calloc]);
@ -499,7 +503,7 @@ calloc (size_t n, size_t len)
++calls_total; ++calls_total;
/* Do the real work. */ /* Do the real work. */
result = (struct header *) (*mallocp) (size + sizeof (struct header)); result = (struct header *) (*mallocp)(size + sizeof (struct header));
if (result == NULL) if (result == NULL)
{ {
catomic_increment (&failed[idx_calloc]); catomic_increment (&failed[idx_calloc]);
@ -525,7 +529,8 @@ free (void *ptr)
if (__builtin_expect (initialized <= 0, 0)) if (__builtin_expect (initialized <= 0, 0))
{ {
if (initialized == -1) if (initialized == -1)
return; return;
me (); me ();
} }
@ -576,17 +581,18 @@ mmap (void *start, size_t len, int prot, int flags, int fd, off_t offset)
if (__builtin_expect (initialized <= 0, 0)) if (__builtin_expect (initialized <= 0, 0))
{ {
if (initialized == -1) if (initialized == -1)
return NULL; return NULL;
me (); me ();
} }
/* Always get a block. We don't need extra memory. */ /* Always get a block. We don't need extra memory. */
result = (*mmapp) (start, len, prot, flags, fd, offset); result = (*mmapp)(start, len, prot, flags, fd, offset);
if (!not_me && trace_mmap) if (!not_me && trace_mmap)
{ {
int idx = (flags & MAP_ANON int idx = (flags & MAP_ANON
? idx_mmap_a : prot & PROT_WRITE ? idx_mmap_w : idx_mmap_r); ? idx_mmap_a : prot & PROT_WRITE ? idx_mmap_w : idx_mmap_r);
/* Keep track of number of calls. */ /* Keep track of number of calls. */
catomic_increment (&calls[idx]); catomic_increment (&calls[idx]);
@ -596,20 +602,20 @@ mmap (void *start, size_t len, int prot, int flags, int fd, off_t offset)
catomic_add (&grand_total, len); catomic_add (&grand_total, len);
/* Remember the size of the request. */ /* Remember the size of the request. */
if (len < 65536) if (len < 65536)
catomic_increment (&histogram[len / 16]); catomic_increment (&histogram[len / 16]);
else else
catomic_increment (&large); catomic_increment (&large);
/* Total number of calls of any of the functions. */ /* Total number of calls of any of the functions. */
catomic_increment (&calls_total); catomic_increment (&calls_total);
/* Check for failures. */ /* Check for failures. */
if (result == NULL) if (result == NULL)
catomic_increment (&failed[idx]); catomic_increment (&failed[idx]);
else if (idx == idx_mmap_w) else if (idx == idx_mmap_w)
/* Update the allocation data and write out the records if /* Update the allocation data and write out the records if
necessary. Note the first parameter is NULL which means necessary. Note the first parameter is NULL which means
the size is not tracked. */ the size is not tracked. */
update_data (NULL, len, 0); update_data (NULL, len, 0);
} }
/* Return the pointer to the user buffer. */ /* Return the pointer to the user buffer. */
@ -628,17 +634,18 @@ mmap64 (void *start, size_t len, int prot, int flags, int fd, off64_t offset)
if (__builtin_expect (initialized <= 0, 0)) if (__builtin_expect (initialized <= 0, 0))
{ {
if (initialized == -1) if (initialized == -1)
return NULL; return NULL;
me (); me ();
} }
/* Always get a block. We don't need extra memory. */ /* Always get a block. We don't need extra memory. */
result = (*mmap64p) (start, len, prot, flags, fd, offset); result = (*mmap64p)(start, len, prot, flags, fd, offset);
if (!not_me && trace_mmap) if (!not_me && trace_mmap)
{ {
int idx = (flags & MAP_ANON int idx = (flags & MAP_ANON
? idx_mmap_a : prot & PROT_WRITE ? idx_mmap_w : idx_mmap_r); ? idx_mmap_a : prot & PROT_WRITE ? idx_mmap_w : idx_mmap_r);
/* Keep track of number of calls. */ /* Keep track of number of calls. */
catomic_increment (&calls[idx]); catomic_increment (&calls[idx]);
@ -648,20 +655,20 @@ mmap64 (void *start, size_t len, int prot, int flags, int fd, off64_t offset)
catomic_add (&grand_total, len); catomic_add (&grand_total, len);
/* Remember the size of the request. */ /* Remember the size of the request. */
if (len < 65536) if (len < 65536)
catomic_increment (&histogram[len / 16]); catomic_increment (&histogram[len / 16]);
else else
catomic_increment (&large); catomic_increment (&large);
/* Total number of calls of any of the functions. */ /* Total number of calls of any of the functions. */
catomic_increment (&calls_total); catomic_increment (&calls_total);
/* Check for failures. */ /* Check for failures. */
if (result == NULL) if (result == NULL)
catomic_increment (&failed[idx]); catomic_increment (&failed[idx]);
else if (idx == idx_mmap_w) else if (idx == idx_mmap_w)
/* Update the allocation data and write out the records if /* Update the allocation data and write out the records if
necessary. Note the first parameter is NULL which means necessary. Note the first parameter is NULL which means
the size is not tracked. */ the size is not tracked. */
update_data (NULL, len, 0); update_data (NULL, len, 0);
} }
/* Return the pointer to the user buffer. */ /* Return the pointer to the user buffer. */
@ -672,7 +679,7 @@ mmap64 (void *start, size_t len, int prot, int flags, int fd, off64_t offset)
/* `mremap' replacement. We do not have to keep track of the size since /* `mremap' replacement. We do not have to keep track of the size since
`munmap' will get it as a parameter. */ `munmap' will get it as a parameter. */
void * void *
mremap (void *start, size_t old_len, size_t len, int flags, ...) mremap (void *start, size_t old_len, size_t len, int flags, ...)
{ {
void *result = NULL; void *result = NULL;
va_list ap; va_list ap;
@ -685,49 +692,50 @@ mremap (void *start, size_t old_len, size_t len, int flags, ...)
if (__builtin_expect (initialized <= 0, 0)) if (__builtin_expect (initialized <= 0, 0))
{ {
if (initialized == -1) if (initialized == -1)
return NULL; return NULL;
me (); me ();
} }
/* Always get a block. We don't need extra memory. */ /* Always get a block. We don't need extra memory. */
result = (*mremapp) (start, old_len, len, flags, newaddr); result = (*mremapp)(start, old_len, len, flags, newaddr);
if (!not_me && trace_mmap) if (!not_me && trace_mmap)
{ {
/* Keep track of number of calls. */ /* Keep track of number of calls. */
catomic_increment (&calls[idx_mremap]); catomic_increment (&calls[idx_mremap]);
if (len > old_len) if (len > old_len)
{ {
/* Keep track of total memory consumption for `malloc'. */ /* Keep track of total memory consumption for `malloc'. */
catomic_add (&total[idx_mremap], len - old_len); catomic_add (&total[idx_mremap], len - old_len);
/* Keep track of total memory requirement. */ /* Keep track of total memory requirement. */
catomic_add (&grand_total, len - old_len); catomic_add (&grand_total, len - old_len);
} }
/* Remember the size of the request. */ /* Remember the size of the request. */
if (len < 65536) if (len < 65536)
catomic_increment (&histogram[len / 16]); catomic_increment (&histogram[len / 16]);
else else
catomic_increment (&large); catomic_increment (&large);
/* Total number of calls of any of the functions. */ /* Total number of calls of any of the functions. */
catomic_increment (&calls_total); catomic_increment (&calls_total);
/* Check for failures. */ /* Check for failures. */
if (result == NULL) if (result == NULL)
catomic_increment (&failed[idx_mremap]); catomic_increment (&failed[idx_mremap]);
else else
{ {
/* Record whether the reduction/increase happened in place. */ /* Record whether the reduction/increase happened in place. */
if (start == result) if (start == result)
catomic_increment (&inplace_mremap); catomic_increment (&inplace_mremap);
/* Was the buffer increased? */ /* Was the buffer increased? */
if (old_len > len) if (old_len > len)
catomic_increment (&decreasing_mremap); catomic_increment (&decreasing_mremap);
/* Update the allocation data and write out the records if /* Update the allocation data and write out the records if
necessary. Note the first parameter is NULL which means necessary. Note the first parameter is NULL which means
the size is not tracked. */ the size is not tracked. */
update_data (NULL, len, old_len); update_data (NULL, len, old_len);
} }
} }
/* Return the pointer to the user buffer. */ /* Return the pointer to the user buffer. */
@ -745,12 +753,13 @@ munmap (void *start, size_t len)
if (__builtin_expect (initialized <= 0, 0)) if (__builtin_expect (initialized <= 0, 0))
{ {
if (initialized == -1) if (initialized == -1)
return -1; return -1;
me (); me ();
} }
/* Do the real work. */ /* Do the real work. */
result = (*munmapp) (start, len); result = (*munmapp)(start, len);
if (!not_me && trace_mmap) if (!not_me && trace_mmap)
{ {
@ -758,16 +767,16 @@ munmap (void *start, size_t len)
catomic_increment (&calls[idx_munmap]); catomic_increment (&calls[idx_munmap]);
if (__builtin_expect (result == 0, 1)) if (__builtin_expect (result == 0, 1))
{ {
/* Keep track of total memory freed using `free'. */ /* Keep track of total memory freed using `free'. */
catomic_add (&total[idx_munmap], len); catomic_add (&total[idx_munmap], len);
/* Update the allocation data and write out the records if /* Update the allocation data and write out the records if
necessary. */ necessary. */
update_data (NULL, 0, len); update_data (NULL, 0, len);
} }
else else
catomic_increment (&failed[idx_munmap]); catomic_increment (&failed[idx_munmap]);
} }
return result; return result;
@ -785,6 +794,7 @@ dest (void)
/* If we haven't done anything here just return. */ /* If we haven't done anything here just return. */
if (not_me) if (not_me)
return; return;
/* If we should call any of the memory functions don't do any profiling. */ /* If we should call any of the memory functions don't do any profiling. */
not_me = true; not_me = true;
@ -793,13 +803,13 @@ dest (void)
{ {
/* Write the partially filled buffer. */ /* Write the partially filled buffer. */
if (buffer_cnt > buffer_size) if (buffer_cnt > buffer_size)
write (fd, buffer + buffer_size, write (fd, buffer + buffer_size,
(buffer_cnt - buffer_size) * sizeof (struct entry)); (buffer_cnt - buffer_size) * sizeof (struct entry));
else else
write (fd, buffer, buffer_cnt * sizeof (struct entry)); write (fd, buffer, buffer_cnt * sizeof (struct entry));
/* Go back to the beginning of the file. We allocated two records /* Go back to the beginning of the file. We allocated two records
here when we opened the file. */ here when we opened the file. */
lseek (fd, 0, SEEK_SET); lseek (fd, 0, SEEK_SET);
/* Write out a record containing the total size. */ /* Write out a record containing the total size. */
first.stack = peak_total; first.stack = peak_total;
@ -824,25 +834,25 @@ dest (void)
\e[00;34mrealloc|\e[0m %10lu %12llu %s%12lu\e[00;00m (nomove:%ld, dec:%ld, free:%ld)\n\ \e[00;34mrealloc|\e[0m %10lu %12llu %s%12lu\e[00;00m (nomove:%ld, dec:%ld, free:%ld)\n\
\e[00;34m calloc|\e[0m %10lu %12llu %s%12lu\e[00;00m\n\ \e[00;34m calloc|\e[0m %10lu %12llu %s%12lu\e[00;00m\n\
\e[00;34m free|\e[0m %10lu %12llu\n", \e[00;34m free|\e[0m %10lu %12llu\n",
(unsigned long long int) grand_total, (unsigned long int) peak_heap, (unsigned long long int) grand_total, (unsigned long int) peak_heap,
(unsigned long int) peak_stack, (unsigned long int) peak_stack,
(unsigned long int) calls[idx_malloc], (unsigned long int) calls[idx_malloc],
(unsigned long long int) total[idx_malloc], (unsigned long long int) total[idx_malloc],
failed[idx_malloc] ? "\e[01;41m" : "", failed[idx_malloc] ? "\e[01;41m" : "",
(unsigned long int) failed[idx_malloc], (unsigned long int) failed[idx_malloc],
(unsigned long int) calls[idx_realloc], (unsigned long int) calls[idx_realloc],
(unsigned long long int) total[idx_realloc], (unsigned long long int) total[idx_realloc],
failed[idx_realloc] ? "\e[01;41m" : "", failed[idx_realloc] ? "\e[01;41m" : "",
(unsigned long int) failed[idx_realloc], (unsigned long int) failed[idx_realloc],
(unsigned long int) inplace, (unsigned long int) inplace,
(unsigned long int) decreasing, (unsigned long int) decreasing,
(unsigned long int) realloc_free, (unsigned long int) realloc_free,
(unsigned long int) calls[idx_calloc], (unsigned long int) calls[idx_calloc],
(unsigned long long int) total[idx_calloc], (unsigned long long int) total[idx_calloc],
failed[idx_calloc] ? "\e[01;41m" : "", failed[idx_calloc] ? "\e[01;41m" : "",
(unsigned long int) failed[idx_calloc], (unsigned long int) failed[idx_calloc],
(unsigned long int) calls[idx_free], (unsigned long int) calls[idx_free],
(unsigned long long int) total[idx_free]); (unsigned long long int) total[idx_free]);
if (trace_mmap) if (trace_mmap)
fprintf (stderr, "\ fprintf (stderr, "\
@ -851,28 +861,28 @@ dest (void)
\e[00;34mmmap(a)|\e[0m %10lu %12llu %s%12lu\e[00;00m\n\ \e[00;34mmmap(a)|\e[0m %10lu %12llu %s%12lu\e[00;00m\n\
\e[00;34m mremap|\e[0m %10lu %12llu %s%12lu\e[00;00m (nomove: %ld, dec:%ld)\n\ \e[00;34m mremap|\e[0m %10lu %12llu %s%12lu\e[00;00m (nomove: %ld, dec:%ld)\n\
\e[00;34m munmap|\e[0m %10lu %12llu %s%12lu\e[00;00m\n", \e[00;34m munmap|\e[0m %10lu %12llu %s%12lu\e[00;00m\n",
(unsigned long int) calls[idx_mmap_r], (unsigned long int) calls[idx_mmap_r],
(unsigned long long int) total[idx_mmap_r], (unsigned long long int) total[idx_mmap_r],
failed[idx_mmap_r] ? "\e[01;41m" : "", failed[idx_mmap_r] ? "\e[01;41m" : "",
(unsigned long int) failed[idx_mmap_r], (unsigned long int) failed[idx_mmap_r],
(unsigned long int) calls[idx_mmap_w], (unsigned long int) calls[idx_mmap_w],
(unsigned long long int) total[idx_mmap_w], (unsigned long long int) total[idx_mmap_w],
failed[idx_mmap_w] ? "\e[01;41m" : "", failed[idx_mmap_w] ? "\e[01;41m" : "",
(unsigned long int) failed[idx_mmap_w], (unsigned long int) failed[idx_mmap_w],
(unsigned long int) calls[idx_mmap_a], (unsigned long int) calls[idx_mmap_a],
(unsigned long long int) total[idx_mmap_a], (unsigned long long int) total[idx_mmap_a],
failed[idx_mmap_a] ? "\e[01;41m" : "", failed[idx_mmap_a] ? "\e[01;41m" : "",
(unsigned long int) failed[idx_mmap_a], (unsigned long int) failed[idx_mmap_a],
(unsigned long int) calls[idx_mremap], (unsigned long int) calls[idx_mremap],
(unsigned long long int) total[idx_mremap], (unsigned long long int) total[idx_mremap],
failed[idx_mremap] ? "\e[01;41m" : "", failed[idx_mremap] ? "\e[01;41m" : "",
(unsigned long int) failed[idx_mremap], (unsigned long int) failed[idx_mremap],
(unsigned long int) inplace_mremap, (unsigned long int) inplace_mremap,
(unsigned long int) decreasing_mremap, (unsigned long int) decreasing_mremap,
(unsigned long int) calls[idx_munmap], (unsigned long int) calls[idx_munmap],
(unsigned long long int) total[idx_munmap], (unsigned long long int) total[idx_munmap],
failed[idx_munmap] ? "\e[01;41m" : "", failed[idx_munmap] ? "\e[01;41m" : "",
(unsigned long int) failed[idx_munmap]); (unsigned long int) failed[idx_munmap]);
/* Write out a histoogram of the sizes of the allocations. */ /* Write out a histoogram of the sizes of the allocations. */
fprintf (stderr, "\e[01;32mHistogram for block sizes:\e[0;0m\n"); fprintf (stderr, "\e[01;32mHistogram for block sizes:\e[0;0m\n");
@ -887,20 +897,20 @@ dest (void)
/* Only write out the nonzero entries. */ /* Only write out the nonzero entries. */
if (histogram[cnt / 16] != 0) if (histogram[cnt / 16] != 0)
{ {
percent = (histogram[cnt / 16] * 100) / calls_total; percent = (histogram[cnt / 16] * 100) / calls_total;
fprintf (stderr, "%5d-%-5d%12lu ", cnt, cnt + 15, fprintf (stderr, "%5d-%-5d%12lu ", cnt, cnt + 15,
(unsigned long int) histogram[cnt / 16]); (unsigned long int) histogram[cnt / 16]);
if (percent == 0) if (percent == 0)
fputs (" <1% \e[41;37m", stderr); fputs (" <1% \e[41;37m", stderr);
else else
fprintf (stderr, "%3d%% \e[41;37m", percent); fprintf (stderr, "%3d%% \e[41;37m", percent);
/* Draw a bar with a length corresponding to the current /* Draw a bar with a length corresponding to the current
percentage. */ percentage. */
percent = (histogram[cnt / 16] * 50) / maxcalls; percent = (histogram[cnt / 16] * 50) / maxcalls;
while (percent-- > 0) while (percent-- > 0)
fputc ('=', stderr); fputc ('=', stderr);
fputs ("\e[0;0m\n", stderr); fputs ("\e[0;0m\n", stderr);
} }
if (large != 0) if (large != 0)
@ -908,9 +918,9 @@ dest (void)
percent = (large * 100) / calls_total; percent = (large * 100) / calls_total;
fprintf (stderr, " large %12lu ", (unsigned long int) large); fprintf (stderr, " large %12lu ", (unsigned long int) large);
if (percent == 0) if (percent == 0)
fputs (" <1% \e[41;37m", stderr); fputs (" <1% \e[41;37m", stderr);
else else
fprintf (stderr, "%3d%% \e[41;37m", percent); fprintf (stderr, "%3d%% \e[41;37m", percent);
percent = (large * 50) / maxcalls; percent = (large * 50) / maxcalls;
while (percent-- > 0) while (percent-- > 0)
fputc ('=', stderr); fputc ('=', stderr);

View File

@ -53,24 +53,24 @@
/* Definitions of arguments for argp functions. */ /* Definitions of arguments for argp functions. */
static const struct argp_option options[] = static const struct argp_option options[] =
{ {
{ "output", 'o', N_("FILE"), 0, N_("Name output file") }, { "output", 'o', N_ ("FILE"), 0, N_ ("Name output file") },
{ "string", 's', N_("STRING"), 0, N_("Title string used in output graphic") }, { "string", 's', N_ ("STRING"), 0, N_ ("Title string used in output graphic") },
{ "time", 't', NULL, 0, N_("\ { "time", 't', NULL, 0, N_ (" \
Generate output linear to time (default is linear to number of function calls)\ Generate output linear to time (default is linear to number of function calls)\
") }, ") },
{ "total", 'T', NULL, 0, { "total", 'T', NULL, 0,
N_("Also draw graph for total memory consumption") }, N_ ("Also draw graph for total memory consumption") },
{ "x-size", 'x', N_("VALUE"), 0, { "x-size", 'x', N_ ("VALUE"), 0,
N_("Make output graphic VALUE pixels wide") }, N_ ("Make output graphic VALUE pixels wide") },
{ "y-size", 'y', "VALUE", 0, N_("Make output graphic VALUE pixels high") }, { "y-size", 'y', "VALUE", 0, N_ ("Make output graphic VALUE pixels high") },
{ NULL, 0, NULL, 0, NULL } { NULL, 0, NULL, 0, NULL }
}; };
/* Short description of program. */ /* Short description of program. */
static const char doc[] = N_("Generate graphic from memory profiling data"); static const char doc[] = N_ ("Generate graphic from memory profiling data");
/* Strings for arguments in help texts. */ /* Strings for arguments in help texts. */
static const char args_doc[] = N_("DATAFILE [OUTFILE]"); static const char args_doc[] = N_ ("DATAFILE [OUTFILE]");
/* Prototype for option handler. */ /* Prototype for option handler. */
static error_t parse_opt (int key, char *arg, struct argp_state *state); static error_t parse_opt (int key, char *arg, struct argp_state *state);
@ -152,7 +152,7 @@ main (int argc, char *argv[])
if (remaining >= argc || remaining + 2 < argc) if (remaining >= argc || remaining + 2 < argc)
{ {
argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR, argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
program_invocation_short_name); program_invocation_short_name);
exit (1); exit (1);
} }
@ -197,21 +197,21 @@ main (int argc, char *argv[])
if (maxsize_heap == 0 && maxsize_stack == 0) if (maxsize_heap == 0 && maxsize_stack == 0)
{ {
/* The program aborted before memusage was able to write the /* The program aborted before memusage was able to write the
information about the maximum heap and stack use. Repair information about the maximum heap and stack use. Repair
the file now. */ the file now. */
struct entry next; struct entry next;
while (1) while (1)
{ {
if (read (fd, &next, sizeof (next)) == 0) if (read (fd, &next, sizeof (next)) == 0)
break; break;
if (next.heap > maxsize_heap) if (next.heap > maxsize_heap)
maxsize_heap = next.heap; maxsize_heap = next.heap;
if (next.stack > maxsize_stack) if (next.stack > maxsize_stack)
maxsize_stack = next.stack; maxsize_stack = next.stack;
if (maxsize_heap + maxsize_stack > maxsize_total) if (maxsize_heap + maxsize_stack > maxsize_total)
maxsize_total = maxsize_heap + maxsize_stack; maxsize_total = maxsize_heap + maxsize_stack;
} }
headent[0].stack = maxsize_total; headent[0].stack = maxsize_total;
headent[1].heap = maxsize_heap; headent[1].heap = maxsize_heap;
@ -227,7 +227,7 @@ main (int argc, char *argv[])
if (also_total) if (also_total)
{ {
/* We use one scale and since we also draw the total amount of /* We use one scale and since we also draw the total amount of
memory used we have to adapt the maximum. */ memory used we have to adapt the maximum. */
maxsize_heap = maxsize_total; maxsize_heap = maxsize_total;
maxsize_stack = maxsize_total; maxsize_stack = maxsize_total;
} }
@ -292,145 +292,145 @@ main (int argc, char *argv[])
} }
gdImageString (im_out, gdFontSmall, 38, ysize - 14, (unsigned char *) "0", gdImageString (im_out, gdFontSmall, 38, ysize - 14, (unsigned char *) "0",
blue); blue);
snprintf (buf, sizeof (buf), heap_format, 0); snprintf (buf, sizeof (buf), heap_format, 0);
gdImageString (im_out, gdFontSmall, maxsize_heap < 1024 ? 32 : 26, gdImageString (im_out, gdFontSmall, maxsize_heap < 1024 ? 32 : 26,
ysize - 26, (unsigned char *) buf, red); ysize - 26, (unsigned char *) buf, red);
snprintf (buf, sizeof (buf), stack_format, 0); snprintf (buf, sizeof (buf), stack_format, 0);
gdImageString (im_out, gdFontSmall, xsize - 37, ysize - 26, gdImageString (im_out, gdFontSmall, xsize - 37, ysize - 26,
(unsigned char *) buf, green); (unsigned char *) buf, green);
if (string != NULL) if (string != NULL)
gdImageString (im_out, gdFontLarge, (xsize - strlen (string) * 8) / 2, gdImageString (im_out, gdFontLarge, (xsize - strlen (string) * 8) / 2,
2, (unsigned char *) string, green); 2, (unsigned char *) string, green);
gdImageStringUp (im_out, gdFontSmall, 1, ysize / 2 - 10, gdImageStringUp (im_out, gdFontSmall, 1, ysize / 2 - 10,
(unsigned char *) "allocated", red); (unsigned char *) "allocated", red);
gdImageStringUp (im_out, gdFontSmall, 11, ysize / 2 - 10, gdImageStringUp (im_out, gdFontSmall, 11, ysize / 2 - 10,
(unsigned char *) "memory", red); (unsigned char *) "memory", red);
gdImageStringUp (im_out, gdFontSmall, xsize - 39, ysize / 2 - 10, gdImageStringUp (im_out, gdFontSmall, xsize - 39, ysize / 2 - 10,
(unsigned char *) "used", green); (unsigned char *) "used", green);
gdImageStringUp (im_out, gdFontSmall, xsize - 27, ysize / 2 - 10, gdImageStringUp (im_out, gdFontSmall, xsize - 27, ysize / 2 - 10,
(unsigned char *) "stack", green); (unsigned char *) "stack", green);
snprintf (buf, sizeof (buf), heap_format, maxsize_heap / heap_scale); snprintf (buf, sizeof (buf), heap_format, maxsize_heap / heap_scale);
gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6, 14, gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6, 14,
(unsigned char *) buf, red); (unsigned char *) buf, red);
snprintf (buf, sizeof (buf), stack_format, maxsize_stack / stack_scale); snprintf (buf, sizeof (buf), stack_format, maxsize_stack / stack_scale);
gdImageString (im_out, gdFontSmall, xsize - 37, 14, gdImageString (im_out, gdFontSmall, xsize - 37, 14,
(unsigned char *) buf, green); (unsigned char *) buf, green);
for (line = 1; line <= 3; ++line) for (line = 1; line <= 3; ++line)
{ {
if (maxsize_heap > 0) if (maxsize_heap > 0)
{ {
cnt = (((ysize - 40) * (maxsize_heap / 4 * line / heap_scale)) cnt = (((ysize - 40) * (maxsize_heap / 4 * line / heap_scale))
/ (maxsize_heap / heap_scale)); / (maxsize_heap / heap_scale));
gdImageDashedLine (im_out, 40, ysize - 20 - cnt, xsize - 40, gdImageDashedLine (im_out, 40, ysize - 20 - cnt, xsize - 40,
ysize - 20 - cnt, red); ysize - 20 - cnt, red);
snprintf (buf, sizeof (buf), heap_format, snprintf (buf, sizeof (buf), heap_format,
maxsize_heap / 4 * line / heap_scale); maxsize_heap / 4 * line / heap_scale);
gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6, gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6,
ysize - 26 - cnt, (unsigned char *) buf, red); ysize - 26 - cnt, (unsigned char *) buf, red);
} }
else else
cnt = 0; cnt = 0;
if (maxsize_stack > 0) if (maxsize_stack > 0)
cnt2 = (((ysize - 40) * (maxsize_stack / 4 * line / stack_scale)) cnt2 = (((ysize - 40) * (maxsize_stack / 4 * line / stack_scale))
/ (maxsize_stack / stack_scale)); / (maxsize_stack / stack_scale));
else else
cnt2 = 0; cnt2 = 0;
if (cnt != cnt2) if (cnt != cnt2)
gdImageDashedLine (im_out, 40, ysize - 20 - cnt2, xsize - 40, gdImageDashedLine (im_out, 40, ysize - 20 - cnt2, xsize - 40,
ysize - 20 - cnt2, green); ysize - 20 - cnt2, green);
snprintf (buf, sizeof (buf), stack_format, maxsize_stack / 4 * line / snprintf (buf, sizeof (buf), stack_format, maxsize_stack / 4 * line /
stack_scale); stack_scale);
gdImageString (im_out, gdFontSmall, xsize - 37, ysize - 26 - cnt2, gdImageString (im_out, gdFontSmall, xsize - 37, ysize - 26 - cnt2,
(unsigned char *) buf, green); (unsigned char *) buf, green);
} }
snprintf (buf, sizeof (buf), "%llu", (unsigned long long) total); snprintf (buf, sizeof (buf), "%llu", (unsigned long long) total);
gdImageString (im_out, gdFontSmall, xsize - 50, ysize - 14, gdImageString (im_out, gdFontSmall, xsize - 50, ysize - 14,
(unsigned char *) buf, blue); (unsigned char *) buf, blue);
if (!time_based) if (!time_based)
{ {
uint64_t previously = start_time; uint64_t previously = start_time;
gdImageString (im_out, gdFontSmall, 40 + (xsize - 32 * 6 - 80) / 2, gdImageString (im_out, gdFontSmall, 40 + (xsize - 32 * 6 - 80) / 2,
ysize - 12, ysize - 12,
(unsigned char *) "# memory handling function calls", (unsigned char *) "# memory handling function calls",
blue); blue);
last_stack = last_heap = last_total = ysize - 20; last_stack = last_heap = last_total = ysize - 20;
for (cnt = 1; cnt <= total; ++cnt) for (cnt = 1; cnt <= total; ++cnt)
{ {
struct entry entry; struct entry entry;
size_t new[2]; size_t new[2];
uint64_t now; uint64_t now;
read (fd, &entry, sizeof (entry)); read (fd, &entry, sizeof (entry));
now = ((uint64_t) entry.time_high) << 32 | entry.time_low; now = ((uint64_t) entry.time_high) << 32 | entry.time_low;
if ((((previously - start_time) * 100) / total_time) % 10 < 5) if ((((previously - start_time) * 100) / total_time) % 10 < 5)
gdImageFilledRectangle (im_out, gdImageFilledRectangle (im_out,
40 + ((cnt - 1) * (xsize - 80)) / total, 40 + ((cnt - 1) * (xsize - 80)) / total,
ysize - 19, ysize - 19,
39 + (cnt * (xsize - 80)) / total, 39 + (cnt * (xsize - 80)) / total,
ysize - 14, yellow); ysize - 14, yellow);
previously = now; previously = now;
if (also_total && maxsize_heap > 0) if (also_total && maxsize_heap > 0)
{ {
size_t new3; size_t new3;
new3 = (ysize - 20) - ((((unsigned long long int) (ysize - 40)) new3 = (ysize - 20) - ((((unsigned long long int) (ysize - 40))
* (entry.heap + entry.stack)) * (entry.heap + entry.stack))
/ maxsize_heap); / maxsize_heap);
gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total, gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total,
last_total, last_total,
40 + ((xsize - 80) * cnt) / total, new3, 40 + ((xsize - 80) * cnt) / total, new3,
black); black);
last_total = new3; last_total = new3;
} }
if (maxsize_heap > 0) if (maxsize_heap > 0)
{ {
new[0] = ((ysize - 20) new[0] = ((ysize - 20)
- ((((unsigned long long int) (ysize - 40)) - ((((unsigned long long int) (ysize - 40))
* entry.heap) / maxsize_heap)); * entry.heap) / maxsize_heap));
gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total, gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total,
last_heap, 40 + ((xsize - 80) * cnt) / total, last_heap, 40 + ((xsize - 80) * cnt) / total,
new[0], red); new[0], red);
last_heap = new[0]; last_heap = new[0];
} }
if (maxsize_stack > 0) if (maxsize_stack > 0)
{ {
new[1] = ((ysize - 20) new[1] = ((ysize - 20)
- ((((unsigned long long int) (ysize - 40)) - ((((unsigned long long int) (ysize - 40))
* entry.stack) / maxsize_stack)); * entry.stack) / maxsize_stack));
gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total, gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total,
last_stack, 40 + ((xsize - 80) * cnt) / total, last_stack, 40 + ((xsize - 80) * cnt) / total,
new[1], green); new[1], green);
last_stack = new[1]; last_stack = new[1];
} }
} }
cnt = 0; cnt = 0;
while (cnt < total) while (cnt < total)
{ {
gdImageLine (im_out, 40 + ((xsize - 80) * cnt) / total, ysize - 20, gdImageLine (im_out, 40 + ((xsize - 80) * cnt) / total, ysize - 20,
40 + ((xsize - 80) * cnt) / total, ysize - 15, blue); 40 + ((xsize - 80) * cnt) / total, ysize - 15, blue);
cnt += MAX (1, total / 20); cnt += MAX (1, total / 20);
} }
gdImageLine (im_out, xsize - 40, ysize - 20, xsize - 40, ysize - 15, gdImageLine (im_out, xsize - 40, ysize - 20, xsize - 40, ysize - 15,
blue); blue);
} }
else else
{ {
@ -438,67 +438,67 @@ main (int argc, char *argv[])
size_t last_xpos = 40; size_t last_xpos = 40;
gdImageString (im_out, gdFontSmall, 40 + (xsize - 39 * 6 - 80) / 2, gdImageString (im_out, gdFontSmall, 40 + (xsize - 39 * 6 - 80) / 2,
ysize - 12, ysize - 12,
(unsigned char *) "\ (unsigned char *) " \
# memory handling function calls / time", blue); # memory handling function calls / time", blue);
for (cnt = 0; cnt < 20; cnt += 2) for (cnt = 0; cnt < 20; cnt += 2)
gdImageFilledRectangle (im_out, gdImageFilledRectangle (im_out,
40 + (cnt * (xsize - 80)) / 20, ysize - 19, 40 + (cnt * (xsize - 80)) / 20, ysize - 19,
39 + ((cnt + 1) * (xsize - 80)) / 20, 39 + ((cnt + 1) * (xsize - 80)) / 20,
ysize - 14, yellow); ysize - 14, yellow);
last_stack = last_heap = last_total = ysize - 20; last_stack = last_heap = last_total = ysize - 20;
for (cnt = 1; cnt <= total; ++cnt) for (cnt = 1; cnt <= total; ++cnt)
{ {
struct entry entry; struct entry entry;
size_t new[2]; size_t new[2];
size_t xpos; size_t xpos;
uint64_t now; uint64_t now;
read (fd, &entry, sizeof (entry)); read (fd, &entry, sizeof (entry));
now = ((uint64_t) entry.time_high) << 32 | entry.time_low; now = ((uint64_t) entry.time_high) << 32 | entry.time_low;
xpos = 40 + ((xsize - 80) * (now - start_time)) / total_time; xpos = 40 + ((xsize - 80) * (now - start_time)) / total_time;
if (cnt == next_tick) if (cnt == next_tick)
{ {
gdImageLine (im_out, xpos, ysize - 20, xpos, ysize - 15, blue); gdImageLine (im_out, xpos, ysize - 20, xpos, ysize - 15, blue);
next_tick += MAX (1, total / 20); next_tick += MAX (1, total / 20);
} }
if (also_total && maxsize_heap > 0) if (also_total && maxsize_heap > 0)
{ {
size_t new3; size_t new3;
new3 = (ysize - 20) - ((((unsigned long long int) (ysize - 40)) new3 = (ysize - 20) - ((((unsigned long long int) (ysize - 40))
* (entry.heap + entry.stack)) * (entry.heap + entry.stack))
/ maxsize_heap); / maxsize_heap);
gdImageLine (im_out, last_xpos, last_total, xpos, new3, black); gdImageLine (im_out, last_xpos, last_total, xpos, new3, black);
last_total = new3; last_total = new3;
} }
if (maxsize_heap > 0) if (maxsize_heap > 0)
{ {
new[0] = ((ysize - 20) new[0] = ((ysize - 20)
- ((((unsigned long long int) (ysize - 40)) - ((((unsigned long long int) (ysize - 40))
* entry.heap) / maxsize_heap)); * entry.heap) / maxsize_heap));
gdImageLine (im_out, last_xpos, last_heap, xpos, new[0], red); gdImageLine (im_out, last_xpos, last_heap, xpos, new[0], red);
last_heap = new[0]; last_heap = new[0];
} }
if (maxsize_stack > 0) if (maxsize_stack > 0)
{ {
new[1] = ((ysize - 20) new[1] = ((ysize - 20)
- ((((unsigned long long int) (ysize - 40)) - ((((unsigned long long int) (ysize - 40))
* entry.stack) / maxsize_stack)); * entry.stack) / maxsize_stack));
gdImageLine (im_out, last_xpos, last_stack, xpos, new[1], gdImageLine (im_out, last_xpos, last_stack, xpos, new[1],
green); green);
last_stack = new[1]; last_stack = new[1];
} }
last_xpos = xpos; last_xpos = xpos;
} }
} }
/* Write out the result. */ /* Write out the result. */
@ -537,12 +537,12 @@ parse_opt (int key, char *arg, struct argp_state *state)
case 'x': case 'x':
xsize = atoi (arg); xsize = atoi (arg);
if (xsize == 0) if (xsize == 0)
xsize = XSIZE; xsize = XSIZE;
break; break;
case 'y': case 'y':
ysize = atoi (arg); ysize = atoi (arg);
if (ysize == 0) if (ysize == 0)
ysize = XSIZE; ysize = XSIZE;
break; break;
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
@ -563,8 +563,10 @@ more_help (int key, const char *text, void *input)
if (asprintf (&tp, gettext ("\ if (asprintf (&tp, gettext ("\
For bug reporting instructions, please see:\n\ For bug reporting instructions, please see:\n\
%s.\n"), REPORT_BUGS_TO) < 0) %s.\n"), REPORT_BUGS_TO) < 0)
return NULL; return NULL;
return tp; return tp;
default: default:
break; break;
} }

View File

@ -15,27 +15,27 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#ifndef _MALLOC_INTERNAL #ifndef _MALLOC_INTERNAL
#define _MALLOC_INTERNAL # define _MALLOC_INTERNAL
#include <malloc.h> # include <malloc.h>
#endif #endif
#ifndef __GNU_LIBRARY__ #ifndef __GNU_LIBRARY__
#define __sbrk sbrk # define __sbrk sbrk
#endif #endif
#ifdef __GNU_LIBRARY__ #ifdef __GNU_LIBRARY__
/* It is best not to declare this and cast its result on foreign operating /* It is best not to declare this and cast its result on foreign operating
systems with potentially hostile include files. */ systems with potentially hostile include files. */
#include <stddef.h> # include <stddef.h>
#include <stdlib.h> # include <stdlib.h>
extern void *__sbrk (ptrdiff_t increment) __THROW; extern void *__sbrk (ptrdiff_t increment) __THROW;
libc_hidden_proto (__sbrk) libc_hidden_proto (__sbrk)
#endif #endif
#ifndef NULL #ifndef NULL
#define NULL 0 # define NULL 0
#endif #endif
/* Allocate INCREMENT more bytes of data space, /* Allocate INCREMENT more bytes of data space,
@ -47,6 +47,7 @@ __default_morecore (ptrdiff_t increment)
void *result = (void *) __sbrk (increment); void *result = (void *) __sbrk (increment);
if (result == (void *) -1) if (result == (void *) -1)
return NULL; return NULL;
return result; return result;
} }
libc_hidden_def (__default_morecore) libc_hidden_def (__default_morecore)

View File

@ -1,8 +1,8 @@
/* More debugging hooks for `malloc'. /* More debugging hooks for `malloc'.
Copyright (C) 1991-2014 Free Software Foundation, Inc. Copyright (C) 1991-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Written April 2, 1991 by John Gilmore of Cygnus Support. Written April 2, 1991 by John Gilmore of Cygnus Support.
Based on mcheck.c by Mike Haertel. Based on mcheck.c by Mike Haertel.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
@ -18,11 +18,11 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#ifndef _MALLOC_INTERNAL #ifndef _MALLOC_INTERNAL
#define _MALLOC_INTERNAL # define _MALLOC_INTERNAL
#include <malloc.h> # include <malloc.h>
#include <mcheck.h> # include <mcheck.h>
#include <bits/libc-lock.h> # include <bits/libc-lock.h>
#endif #endif
#include <dlfcn.h> #include <dlfcn.h>
@ -48,7 +48,7 @@
#define TRACE_BUFFER_SIZE 512 #define TRACE_BUFFER_SIZE 512
static FILE *mallstream; static FILE *mallstream;
static const char mallenv[]= "MALLOC_TRACE"; static const char mallenv[] = "MALLOC_TRACE";
static char *malloc_trace_buffer; static char *malloc_trace_buffer;
__libc_lock_define_initialized (static, lock); __libc_lock_define_initialized (static, lock);
@ -60,9 +60,9 @@ __ptr_t mallwatch;
static void (*tr_old_free_hook) (__ptr_t ptr, const __ptr_t); static void (*tr_old_free_hook) (__ptr_t ptr, const __ptr_t);
static __ptr_t (*tr_old_malloc_hook) (size_t size, const __ptr_t); static __ptr_t (*tr_old_malloc_hook) (size_t size, const __ptr_t);
static __ptr_t (*tr_old_realloc_hook) (__ptr_t ptr, size_t size, static __ptr_t (*tr_old_realloc_hook) (__ptr_t ptr, size_t size,
const __ptr_t); const __ptr_t);
static __ptr_t (*tr_old_memalign_hook) (size_t __alignment, size_t __size, static __ptr_t (*tr_old_memalign_hook) (size_t __alignment, size_t __size,
const __ptr_t); const __ptr_t);
/* This function is called when the block being alloc'd, realloc'd, or /* This function is called when the block being alloc'd, realloc'd, or
freed has an address matching the variable "mallwatch". In a debugger, freed has an address matching the variable "mallwatch". In a debugger,
@ -79,39 +79,38 @@ libc_hidden_def (tr_break)
static void tr_where (const __ptr_t, Dl_info *) __THROW internal_function; static void tr_where (const __ptr_t, Dl_info *) __THROW internal_function;
static void static void
internal_function internal_function tr_where (caller, info)
tr_where (caller, info) const __ptr_t caller;
const __ptr_t caller; Dl_info *info;
Dl_info *info;
{ {
if (caller != NULL) if (caller != NULL)
{ {
if (info != NULL) if (info != NULL)
{ {
char *buf = (char *) ""; char *buf = (char *) "";
if (info->dli_sname != NULL) if (info->dli_sname != NULL)
{ {
size_t len = strlen (info->dli_sname); size_t len = strlen (info->dli_sname);
buf = alloca (len + 6 + 2 * sizeof (void *)); buf = alloca (len + 6 + 2 * sizeof (void *));
buf[0] = '('; buf[0] = '(';
__stpcpy (_fitoa (caller >= (const __ptr_t) info->dli_saddr __stpcpy (_fitoa (caller >= (const __ptr_t) info->dli_saddr
? caller - (const __ptr_t) info->dli_saddr ? caller - (const __ptr_t) info->dli_saddr
: (const __ptr_t) info->dli_saddr - caller, : (const __ptr_t) info->dli_saddr - caller,
__stpcpy (__mempcpy (buf + 1, info->dli_sname, __stpcpy (__mempcpy (buf + 1, info->dli_sname,
len), len),
caller >= (__ptr_t) info->dli_saddr caller >= (__ptr_t) info->dli_saddr
? "+0x" : "-0x"), ? "+0x" : "-0x"),
16, 0), 16, 0),
")"); ")");
} }
fprintf (mallstream, "@ %s%s%s[%p] ", fprintf (mallstream, "@ %s%s%s[%p] ",
info->dli_fname ?: "", info->dli_fname ? ":" : "", info->dli_fname ? : "", info->dli_fname ? ":" : "",
buf, caller); buf, caller);
} }
else else
fprintf (mallstream, "@ [%p] ", caller); fprintf (mallstream, "@ [%p] ", caller);
} }
} }
@ -131,10 +130,9 @@ lock_and_info (const __ptr_t caller, Dl_info *mem)
static void tr_freehook (__ptr_t, const __ptr_t) __THROW; static void tr_freehook (__ptr_t, const __ptr_t) __THROW;
static void static void tr_freehook (ptr, caller)
tr_freehook (ptr, caller) __ptr_t ptr;
__ptr_t ptr; const __ptr_t caller;
const __ptr_t caller;
{ {
if (ptr == NULL) if (ptr == NULL)
return; return;
@ -152,7 +150,7 @@ tr_freehook (ptr, caller)
} }
__free_hook = tr_old_free_hook; __free_hook = tr_old_free_hook;
if (tr_old_free_hook != NULL) if (tr_old_free_hook != NULL)
(*tr_old_free_hook) (ptr, caller); (*tr_old_free_hook)(ptr, caller);
else else
free (ptr); free (ptr);
__free_hook = tr_freehook; __free_hook = tr_freehook;
@ -160,10 +158,9 @@ tr_freehook (ptr, caller)
} }
static __ptr_t tr_mallochook (size_t, const __ptr_t) __THROW; static __ptr_t tr_mallochook (size_t, const __ptr_t) __THROW;
static __ptr_t static __ptr_t tr_mallochook (size, caller)
tr_mallochook (size, caller) size_t size;
size_t size; const __ptr_t caller;
const __ptr_t caller;
{ {
__ptr_t hdr; __ptr_t hdr;
@ -172,7 +169,7 @@ tr_mallochook (size, caller)
__malloc_hook = tr_old_malloc_hook; __malloc_hook = tr_old_malloc_hook;
if (tr_old_malloc_hook != NULL) if (tr_old_malloc_hook != NULL)
hdr = (__ptr_t) (*tr_old_malloc_hook) (size, caller); hdr = (__ptr_t) (*tr_old_malloc_hook)(size, caller);
else else
hdr = (__ptr_t) malloc (size); hdr = (__ptr_t) malloc (size);
__malloc_hook = tr_mallochook; __malloc_hook = tr_mallochook;
@ -190,12 +187,11 @@ tr_mallochook (size, caller)
} }
static __ptr_t tr_reallochook (__ptr_t, size_t, const __ptr_t) static __ptr_t tr_reallochook (__ptr_t, size_t, const __ptr_t)
__THROW; __THROW;
static __ptr_t static __ptr_t tr_reallochook (ptr, size, caller)
tr_reallochook (ptr, size, caller) __ptr_t ptr;
__ptr_t ptr; size_t size;
size_t size; const __ptr_t caller;
const __ptr_t caller;
{ {
__ptr_t hdr; __ptr_t hdr;
@ -209,7 +205,7 @@ tr_reallochook (ptr, size, caller)
__malloc_hook = tr_old_malloc_hook; __malloc_hook = tr_old_malloc_hook;
__realloc_hook = tr_old_realloc_hook; __realloc_hook = tr_old_realloc_hook;
if (tr_old_realloc_hook != NULL) if (tr_old_realloc_hook != NULL)
hdr = (__ptr_t) (*tr_old_realloc_hook) (ptr, size, caller); hdr = (__ptr_t) (*tr_old_realloc_hook)(ptr, size, caller);
else else
hdr = (__ptr_t) realloc (ptr, size); hdr = (__ptr_t) realloc (ptr, size);
__free_hook = tr_freehook; __free_hook = tr_freehook;
@ -220,10 +216,10 @@ tr_reallochook (ptr, size, caller)
if (hdr == NULL) if (hdr == NULL)
{ {
if (size != 0) if (size != 0)
/* Failed realloc. */ /* Failed realloc. */
fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long int) size); fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long int) size);
else else
fprintf (mallstream, "- %p\n", ptr); fprintf (mallstream, "- %p\n", ptr);
} }
else if (ptr == NULL) else if (ptr == NULL)
fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size); fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
@ -243,11 +239,10 @@ tr_reallochook (ptr, size, caller)
} }
static __ptr_t tr_memalignhook (size_t, size_t, static __ptr_t tr_memalignhook (size_t, size_t,
const __ptr_t) __THROW; const __ptr_t) __THROW;
static __ptr_t static __ptr_t tr_memalignhook (alignment, size, caller)
tr_memalignhook (alignment, size, caller) size_t alignment, size;
size_t alignment, size; const __ptr_t caller;
const __ptr_t caller;
{ {
__ptr_t hdr; __ptr_t hdr;
@ -257,7 +252,7 @@ tr_memalignhook (alignment, size, caller)
__memalign_hook = tr_old_memalign_hook; __memalign_hook = tr_old_memalign_hook;
__malloc_hook = tr_old_malloc_hook; __malloc_hook = tr_old_malloc_hook;
if (tr_old_memalign_hook != NULL) if (tr_old_memalign_hook != NULL)
hdr = (__ptr_t) (*tr_old_memalign_hook) (alignment, size, caller); hdr = (__ptr_t) (*tr_old_memalign_hook)(alignment, size, caller);
else else
hdr = (__ptr_t) memalign (alignment, size); hdr = (__ptr_t) memalign (alignment, size);
__memalign_hook = tr_memalignhook; __memalign_hook = tr_memalignhook;
@ -321,44 +316,44 @@ mtrace (void)
{ {
char *mtb = malloc (TRACE_BUFFER_SIZE); char *mtb = malloc (TRACE_BUFFER_SIZE);
if (mtb == NULL) if (mtb == NULL)
return; return;
mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "wce"); mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "wce");
if (mallstream != NULL) if (mallstream != NULL)
{ {
#ifndef __ASSUME_O_CLOEXEC #ifndef __ASSUME_O_CLOEXEC
/* Make sure we close the file descriptor on exec. */ /* Make sure we close the file descriptor on exec. */
int flags = __fcntl (fileno (mallstream), F_GETFD, 0); int flags = __fcntl (fileno (mallstream), F_GETFD, 0);
if (flags >= 0) if (flags >= 0)
{ {
flags |= FD_CLOEXEC; flags |= FD_CLOEXEC;
__fcntl (fileno (mallstream), F_SETFD, flags); __fcntl (fileno (mallstream), F_SETFD, flags);
} }
#endif #endif
/* Be sure it doesn't malloc its buffer! */ /* Be sure it doesn't malloc its buffer! */
malloc_trace_buffer = mtb; malloc_trace_buffer = mtb;
setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE); setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE);
fprintf (mallstream, "= Start\n"); fprintf (mallstream, "= Start\n");
tr_old_free_hook = __free_hook; tr_old_free_hook = __free_hook;
__free_hook = tr_freehook; __free_hook = tr_freehook;
tr_old_malloc_hook = __malloc_hook; tr_old_malloc_hook = __malloc_hook;
__malloc_hook = tr_mallochook; __malloc_hook = tr_mallochook;
tr_old_realloc_hook = __realloc_hook; tr_old_realloc_hook = __realloc_hook;
__realloc_hook = tr_reallochook; __realloc_hook = tr_reallochook;
tr_old_memalign_hook = __memalign_hook; tr_old_memalign_hook = __memalign_hook;
__memalign_hook = tr_memalignhook; __memalign_hook = tr_memalignhook;
#ifdef _LIBC #ifdef _LIBC
if (!added_atexit_handler) if (!added_atexit_handler)
{ {
extern void *__dso_handle __attribute__ ((__weak__)); extern void *__dso_handle __attribute__ ((__weak__));
added_atexit_handler = 1; added_atexit_handler = 1;
__cxa_atexit ((void (*) (void *)) release_libc_mem, NULL, __cxa_atexit ((void (*)(void *))release_libc_mem, NULL,
&__dso_handle ? __dso_handle : NULL); &__dso_handle ? __dso_handle : NULL);
} }
#endif #endif
} }
else else
free (mtb); free (mtb);
} }
} }

View File

@ -42,7 +42,7 @@
program understand `configure --with-gnu-libc' and omit the object program understand `configure --with-gnu-libc' and omit the object
files, it is simpler to just do this in the source for each such file. */ files, it is simpler to just do this in the source for each such file. */
#include <stdio.h> /* Random thing to get __GNU_LIBRARY__. */ #include <stdio.h> /* Random thing to get __GNU_LIBRARY__. */
#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1 #if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
# include <gnu-versions.h> # include <gnu-versions.h>
# if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION # if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
@ -78,10 +78,10 @@ struct fooalign
But in fact it might be less smart and round addresses to as much as But in fact it might be less smart and round addresses to as much as
DEFAULT_ROUNDING. So we prepare for it to do that. */ DEFAULT_ROUNDING. So we prepare for it to do that. */
enum enum
{ {
DEFAULT_ALIGNMENT = offsetof (struct fooalign, u), DEFAULT_ALIGNMENT = offsetof (struct fooalign, u),
DEFAULT_ROUNDING = sizeof (union fooround) DEFAULT_ROUNDING = sizeof (union fooround)
}; };
/* When we copy a long block of data, this is the unit to do it with. /* When we copy a long block of data, this is the unit to do it with.
On some machines, copying successive ints does not work; On some machines, copying successive ints does not work;
@ -127,19 +127,19 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
do not allow (expr) ? void : void. */ do not allow (expr) ? void : void. */
# define CALL_CHUNKFUN(h, size) \ # define CALL_CHUNKFUN(h, size) \
(((h) -> use_extra_arg) \ (((h)->use_extra_arg) \
? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ ? (*(h)->chunkfun)((h)->extra_arg, (size)) \
: (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size))) : (*(struct _obstack_chunk *(*)(long))(h)->chunkfun)((size)))
# define CALL_FREEFUN(h, old_chunk) \ # define CALL_FREEFUN(h, old_chunk) \
do { \ do { \
if ((h) -> use_extra_arg) \ if ((h)->use_extra_arg) \
(*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ (*(h)->freefun)((h)->extra_arg, (old_chunk)); \
else \ else \
(*(void (*) (void *)) (h)->freefun) ((old_chunk)); \ (*(void (*)(void *))(h)->freefun)((old_chunk)); \
} while (0) } while (0)
/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). /* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
Objects start on multiples of ALIGNMENT (0 means use default). Objects start on multiples of ALIGNMENT (0 means use default).
CHUNKFUN is the function to use to allocate chunks, CHUNKFUN is the function to use to allocate chunks,
@ -150,44 +150,44 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
int int
_obstack_begin (struct obstack *h, _obstack_begin (struct obstack *h,
int size, int alignment, int size, int alignment,
void *(*chunkfun) (long), void *(*chunkfun)(long),
void (*freefun) (void *)) void (*freefun)(void *))
{ {
struct _obstack_chunk *chunk; /* points to new chunk */ struct _obstack_chunk *chunk; /* points to new chunk */
if (alignment == 0) if (alignment == 0)
alignment = DEFAULT_ALIGNMENT; alignment = DEFAULT_ALIGNMENT;
if (size == 0) if (size == 0)
/* Default size is what GNU malloc can fit in a 4096-byte block. */ /* Default size is what GNU malloc can fit in a 4096-byte block. */
{ {
/* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
Use the values for range checking, because if range checking is off, Use the values for range checking, because if range checking is off,
the extra bytes won't be missed terribly, but if range checking is on the extra bytes won't be missed terribly, but if range checking is on
and we used a larger request, a whole extra 4096 bytes would be and we used a larger request, a whole extra 4096 bytes would be
allocated. allocated.
These number are irrelevant to the new GNU malloc. I suspect it is These number are irrelevant to the new GNU malloc. I suspect it is
less sensitive to the size of the request. */ less sensitive to the size of the request. */
int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+ 4 + DEFAULT_ROUNDING - 1) + 4 + DEFAULT_ROUNDING - 1)
& ~(DEFAULT_ROUNDING - 1)); & ~(DEFAULT_ROUNDING - 1));
size = 4096 - extra; size = 4096 - extra;
} }
h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun; h->chunkfun = (struct _obstack_chunk * (*)(void *, long))chunkfun;
h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; h->freefun = (void (*)(void *, struct _obstack_chunk *))freefun;
h->chunk_size = size; h->chunk_size = size;
h->alignment_mask = alignment - 1; h->alignment_mask = alignment - 1;
h->use_extra_arg = 0; h->use_extra_arg = 0;
chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); chunk = h->chunk = CALL_CHUNKFUN (h, h->chunk_size);
if (!chunk) if (!chunk)
(*obstack_alloc_failed_handler) (); (*obstack_alloc_failed_handler)();
h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
alignment - 1); alignment - 1);
h->chunk_limit = chunk->limit h->chunk_limit = chunk->limit
= (char *) chunk + h->chunk_size; = (char *) chunk + h->chunk_size;
chunk->prev = 0; chunk->prev = 0;
/* The initial chunk now contains no empty object. */ /* The initial chunk now contains no empty object. */
h->maybe_empty_object = 0; h->maybe_empty_object = 0;
@ -197,45 +197,45 @@ _obstack_begin (struct obstack *h,
int int
_obstack_begin_1 (struct obstack *h, int size, int alignment, _obstack_begin_1 (struct obstack *h, int size, int alignment,
void *(*chunkfun) (void *, long), void *(*chunkfun)(void *, long),
void (*freefun) (void *, void *), void (*freefun)(void *, void *),
void *arg) void *arg)
{ {
struct _obstack_chunk *chunk; /* points to new chunk */ struct _obstack_chunk *chunk; /* points to new chunk */
if (alignment == 0) if (alignment == 0)
alignment = DEFAULT_ALIGNMENT; alignment = DEFAULT_ALIGNMENT;
if (size == 0) if (size == 0)
/* Default size is what GNU malloc can fit in a 4096-byte block. */ /* Default size is what GNU malloc can fit in a 4096-byte block. */
{ {
/* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
Use the values for range checking, because if range checking is off, Use the values for range checking, because if range checking is off,
the extra bytes won't be missed terribly, but if range checking is on the extra bytes won't be missed terribly, but if range checking is on
and we used a larger request, a whole extra 4096 bytes would be and we used a larger request, a whole extra 4096 bytes would be
allocated. allocated.
These number are irrelevant to the new GNU malloc. I suspect it is These number are irrelevant to the new GNU malloc. I suspect it is
less sensitive to the size of the request. */ less sensitive to the size of the request. */
int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+ 4 + DEFAULT_ROUNDING - 1) + 4 + DEFAULT_ROUNDING - 1)
& ~(DEFAULT_ROUNDING - 1)); & ~(DEFAULT_ROUNDING - 1));
size = 4096 - extra; size = 4096 - extra;
} }
h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun; h->chunkfun = (struct _obstack_chunk * (*)(void *, long))chunkfun;
h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; h->freefun = (void (*)(void *, struct _obstack_chunk *))freefun;
h->chunk_size = size; h->chunk_size = size;
h->alignment_mask = alignment - 1; h->alignment_mask = alignment - 1;
h->extra_arg = arg; h->extra_arg = arg;
h->use_extra_arg = 1; h->use_extra_arg = 1;
chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); chunk = h->chunk = CALL_CHUNKFUN (h, h->chunk_size);
if (!chunk) if (!chunk)
(*obstack_alloc_failed_handler) (); (*obstack_alloc_failed_handler)();
h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
alignment - 1); alignment - 1);
h->chunk_limit = chunk->limit h->chunk_limit = chunk->limit
= (char *) chunk + h->chunk_size; = (char *) chunk + h->chunk_size;
chunk->prev = 0; chunk->prev = 0;
/* The initial chunk now contains no empty object. */ /* The initial chunk now contains no empty object. */
h->maybe_empty_object = 0; h->maybe_empty_object = 0;
@ -254,7 +254,7 @@ _obstack_newchunk (struct obstack *h, int length)
{ {
struct _obstack_chunk *old_chunk = h->chunk; struct _obstack_chunk *old_chunk = h->chunk;
struct _obstack_chunk *new_chunk; struct _obstack_chunk *new_chunk;
long new_size; long new_size;
long obj_size = h->next_free - h->object_base; long obj_size = h->next_free - h->object_base;
long i; long i;
long already; long already;
@ -268,7 +268,7 @@ _obstack_newchunk (struct obstack *h, int length)
/* Allocate and initialize the new chunk. */ /* Allocate and initialize the new chunk. */
new_chunk = CALL_CHUNKFUN (h, new_size); new_chunk = CALL_CHUNKFUN (h, new_size);
if (!new_chunk) if (!new_chunk)
(*obstack_alloc_failed_handler) (); (*obstack_alloc_failed_handler)();
h->chunk = new_chunk; h->chunk = new_chunk;
new_chunk->prev = old_chunk; new_chunk->prev = old_chunk;
new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
@ -283,12 +283,12 @@ _obstack_newchunk (struct obstack *h, int length)
if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT) if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
{ {
for (i = obj_size / sizeof (COPYING_UNIT) - 1; for (i = obj_size / sizeof (COPYING_UNIT) - 1;
i >= 0; i--) i >= 0; i--)
((COPYING_UNIT *)object_base)[i] ((COPYING_UNIT *) object_base)[i]
= ((COPYING_UNIT *)h->object_base)[i]; = ((COPYING_UNIT *) h->object_base)[i];
/* We used to copy the odd few remaining bytes as one extra COPYING_UNIT, /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
but that can cross a page boundary on a machine but that can cross a page boundary on a machine
which does not do strict alignment for COPYING_UNITS. */ which does not do strict alignment for COPYING_UNITS. */
already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT); already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
} }
else else
@ -300,10 +300,10 @@ _obstack_newchunk (struct obstack *h, int length)
/* If the object just copied was the only data in OLD_CHUNK, /* If the object just copied was the only data in OLD_CHUNK,
free that chunk and remove it from the chain. free that chunk and remove it from the chain.
But not if that chunk might contain an empty object. */ But not if that chunk might contain an empty object. */
if (! h->maybe_empty_object if (!h->maybe_empty_object
&& (h->object_base && (h->object_base
== __PTR_ALIGN ((char *) old_chunk, old_chunk->contents, == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
h->alignment_mask))) h->alignment_mask)))
{ {
new_chunk->prev = old_chunk->prev; new_chunk->prev = old_chunk->prev;
CALL_FREEFUN (h, old_chunk); CALL_FREEFUN (h, old_chunk);
@ -329,8 +329,8 @@ int _obstack_allocated_p (struct obstack *h, void *obj);
int int
_obstack_allocated_p (struct obstack *h, void *obj) _obstack_allocated_p (struct obstack *h, void *obj)
{ {
struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
struct _obstack_chunk *plp; /* point to previous chunk if any */ struct _obstack_chunk *plp; /* point to previous chunk if any */
lp = (h)->chunk; lp = (h)->chunk;
/* We use >= rather than > since the object cannot be exactly at /* We use >= rather than > since the object cannot be exactly at
@ -343,7 +343,7 @@ _obstack_allocated_p (struct obstack *h, void *obj)
} }
return lp != 0; return lp != 0;
} }
/* Free objects in obstack H, including OBJ and everything allocate /* Free objects in obstack H, including OBJ and everything allocate
more recently than OBJ. If OBJ is zero, free everything in H. */ more recently than OBJ. If OBJ is zero, free everything in H. */
@ -352,8 +352,8 @@ _obstack_allocated_p (struct obstack *h, void *obj)
void void
obstack_free (struct obstack *h, void *obj) obstack_free (struct obstack *h, void *obj)
{ {
struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
struct _obstack_chunk *plp; /* point to previous chunk if any */ struct _obstack_chunk *plp; /* point to previous chunk if any */
lp = h->chunk; lp = h->chunk;
/* We use >= because there cannot be an object at the beginning of a chunk. /* We use >= because there cannot be an object at the beginning of a chunk.
@ -365,7 +365,7 @@ obstack_free (struct obstack *h, void *obj)
CALL_FREEFUN (h, lp); CALL_FREEFUN (h, lp);
lp = plp; lp = plp;
/* If we switch chunks, we can't tell whether the new current /* If we switch chunks, we can't tell whether the new current
chunk contains an empty object, so assume that it may. */ chunk contains an empty object, so assume that it may. */
h->maybe_empty_object = 1; h->maybe_empty_object = 1;
} }
if (lp) if (lp)
@ -384,11 +384,11 @@ obstack_free (struct obstack *h, void *obj)
called by non-GCC compilers. */ called by non-GCC compilers. */
strong_alias (obstack_free, _obstack_free) strong_alias (obstack_free, _obstack_free)
# endif # endif
int int
_obstack_memory_used (struct obstack *h) _obstack_memory_used (struct obstack *h)
{ {
struct _obstack_chunk* lp; struct _obstack_chunk *lp;
int nbytes = 0; int nbytes = 0;
for (lp = h->chunk; lp != 0; lp = lp->prev) for (lp = h->chunk; lp != 0; lp = lp->prev)
@ -397,7 +397,7 @@ _obstack_memory_used (struct obstack *h)
} }
return nbytes; return nbytes;
} }
/* Define the error handler. */ /* Define the error handler. */
# ifdef _LIBC # ifdef _LIBC
# include <libintl.h> # include <libintl.h>
@ -429,11 +429,10 @@ print_and_abort (void)
like this and the translation should be reused instead of creating like this and the translation should be reused instead of creating
a very similar string which requires a separate translation. */ a very similar string which requires a separate translation. */
# ifdef _LIBC # ifdef _LIBC
(void) __fxprintf (NULL, "%s\n", _("memory exhausted")); (void) __fxprintf (NULL, "%s\n", _ ("memory exhausted"));
# else # else
fprintf (stderr, "%s\n", _("memory exhausted")); fprintf (stderr, "%s\n", _ ("memory exhausted"));
# endif # endif
exit (obstack_exit_failure); exit (obstack_exit_failure);
} }
#endif /* !ELIDE_CODE */
#endif /* !ELIDE_CODE */

View File

@ -18,85 +18,85 @@
/* Summary: /* Summary:
All the apparent functions defined here are macros. The idea All the apparent functions defined here are macros. The idea
is that you would use these pre-tested macros to solve a is that you would use these pre-tested macros to solve a
very specific set of problems, and they would run fast. very specific set of problems, and they would run fast.
Caution: no side-effects in arguments please!! They may be Caution: no side-effects in arguments please!! They may be
evaluated MANY times!! evaluated MANY times!!
These macros operate a stack of objects. Each object starts life These macros operate a stack of objects. Each object starts life
small, and may grow to maturity. (Consider building a word syllable small, and may grow to maturity. (Consider building a word syllable
by syllable.) An object can move while it is growing. Once it has by syllable.) An object can move while it is growing. Once it has
been "finished" it never changes address again. So the "top of the been "finished" it never changes address again. So the "top of the
stack" is typically an immature growing object, while the rest of the stack" is typically an immature growing object, while the rest of the
stack is of mature, fixed size and fixed address objects. stack is of mature, fixed size and fixed address objects.
These routines grab large chunks of memory, using a function you These routines grab large chunks of memory, using a function you
supply, called `obstack_chunk_alloc'. On occasion, they free chunks, supply, called `obstack_chunk_alloc'. On occasion, they free chunks,
by calling `obstack_chunk_free'. You must define them and declare by calling `obstack_chunk_free'. You must define them and declare
them before using any obstack macros. them before using any obstack macros.
Each independent stack is represented by a `struct obstack'. Each independent stack is represented by a `struct obstack'.
Each of the obstack macros expects a pointer to such a structure Each of the obstack macros expects a pointer to such a structure
as the first argument. as the first argument.
One motivation for this package is the problem of growing char strings One motivation for this package is the problem of growing char strings
in symbol tables. Unless you are "fascist pig with a read-only mind" in symbol tables. Unless you are "fascist pig with a read-only mind"
--Gosper's immortal quote from HAKMEM item 154, out of context--you --Gosper's immortal quote from HAKMEM item 154, out of context--you
would not like to put any arbitrary upper limit on the length of your would not like to put any arbitrary upper limit on the length of your
symbols. symbols.
In practice this often means you will build many short symbols and a In practice this often means you will build many short symbols and a
few long symbols. At the time you are reading a symbol you don't know few long symbols. At the time you are reading a symbol you don't know
how long it is. One traditional method is to read a symbol into a how long it is. One traditional method is to read a symbol into a
buffer, realloc()ating the buffer every time you try to read a symbol buffer, realloc()ating the buffer every time you try to read a symbol
that is longer than the buffer. This is beaut, but you still will that is longer than the buffer. This is beaut, but you still will
want to copy the symbol from the buffer to a more permanent want to copy the symbol from the buffer to a more permanent
symbol-table entry say about half the time. symbol-table entry say about half the time.
With obstacks, you can work differently. Use one obstack for all symbol With obstacks, you can work differently. Use one obstack for all symbol
names. As you read a symbol, grow the name in the obstack gradually. names. As you read a symbol, grow the name in the obstack gradually.
When the name is complete, finalize it. Then, if the symbol exists already, When the name is complete, finalize it. Then, if the symbol exists already,
free the newly read name. free the newly read name.
The way we do this is to take a large chunk, allocating memory from The way we do this is to take a large chunk, allocating memory from
low addresses. When you want to build a symbol in the chunk you just low addresses. When you want to build a symbol in the chunk you just
add chars above the current "high water mark" in the chunk. When you add chars above the current "high water mark" in the chunk. When you
have finished adding chars, because you got to the end of the symbol, have finished adding chars, because you got to the end of the symbol,
you know how long the chars are, and you can create a new object. you know how long the chars are, and you can create a new object.
Mostly the chars will not burst over the highest address of the chunk, Mostly the chars will not burst over the highest address of the chunk,
because you would typically expect a chunk to be (say) 100 times as because you would typically expect a chunk to be (say) 100 times as
long as an average object. long as an average object.
In case that isn't clear, when we have enough chars to make up In case that isn't clear, when we have enough chars to make up
the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed) the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
so we just point to it where it lies. No moving of chars is so we just point to it where it lies. No moving of chars is
needed and this is the second win: potentially long strings need needed and this is the second win: potentially long strings need
never be explicitly shuffled. Once an object is formed, it does not never be explicitly shuffled. Once an object is formed, it does not
change its address during its lifetime. change its address during its lifetime.
When the chars burst over a chunk boundary, we allocate a larger When the chars burst over a chunk boundary, we allocate a larger
chunk, and then copy the partly formed object from the end of the old chunk, and then copy the partly formed object from the end of the old
chunk to the beginning of the new larger chunk. We then carry on chunk to the beginning of the new larger chunk. We then carry on
accreting characters to the end of the object as we normally would. accreting characters to the end of the object as we normally would.
A special macro is provided to add a single char at a time to a A special macro is provided to add a single char at a time to a
growing object. This allows the use of register variables, which growing object. This allows the use of register variables, which
break the ordinary 'growth' macro. break the ordinary 'growth' macro.
Summary: Summary:
We allocate large chunks. We allocate large chunks.
We carve out one object at a time from the current chunk. We carve out one object at a time from the current chunk.
Once carved, an object never moves. Once carved, an object never moves.
We are free to append data of any size to the currently We are free to append data of any size to the currently
growing object. growing object.
Exactly one object is growing in an obstack at any one time. Exactly one object is growing in an obstack at any one time.
You can run one obstack per control block. You can run one obstack per control block.
You may have as many control blocks as you dare. You may have as many control blocks as you dare.
Because of the way we do it, you can `unwind' an obstack Because of the way we do it, you can `unwind' an obstack
back to a previous state. (You may remove objects much back to a previous state. (You may remove objects much
as you would with a stack.) as you would with a stack.)
*/ */
/* Don't do the contents of this file more than once. */ /* Don't do the contents of this file more than once. */
@ -107,7 +107,7 @@ Summary:
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* We need the type of a pointer subtraction. If __PTRDIFF_TYPE__ is /* We need the type of a pointer subtraction. If __PTRDIFF_TYPE__ is
defined, as with GNU C, use that; that way we don't pollute the defined, as with GNU C, use that; that way we don't pollute the
namespace with <stddef.h>'s symbols. Otherwise, include <stddef.h> namespace with <stddef.h>'s symbols. Otherwise, include <stddef.h>
@ -124,7 +124,7 @@ extern "C" {
aligning P to the next multiple of A + 1. B and P must be of type aligning P to the next multiple of A + 1. B and P must be of type
char *. A + 1 must be a power of 2. */ char *. A + 1 must be a power of 2. */
#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A))) #define __BPTR_ALIGN(B, P, A) ((B) + (((P) -(B) + (A)) & ~(A)))
/* Similiar to _BPTR_ALIGN (B, P, A), except optimize the common case /* Similiar to _BPTR_ALIGN (B, P, A), except optimize the common case
where pointers can be converted to integers, aligned as integers, where pointers can be converted to integers, aligned as integers,
@ -133,61 +133,61 @@ extern "C" {
relative to B. Otherwise, use the faster strategy of computing the relative to B. Otherwise, use the faster strategy of computing the
alignment relative to 0. */ alignment relative to 0. */
#define __PTR_ALIGN(B, P, A) \ #define __PTR_ALIGN(B, P, A) \
__BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \ __BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \
P, A) P, A)
#include <string.h> #include <string.h>
struct _obstack_chunk /* Lives at front of each chunk. */ struct _obstack_chunk /* Lives at front of each chunk. */
{ {
char *limit; /* 1 past end of this chunk */ char *limit; /* 1 past end of this chunk */
struct _obstack_chunk *prev; /* address of prior chunk or NULL */ struct _obstack_chunk *prev; /* address of prior chunk or NULL */
char contents[4]; /* objects begin here */ char contents[4]; /* objects begin here */
}; };
struct obstack /* control current object in current chunk */ struct obstack /* control current object in current chunk */
{ {
long chunk_size; /* preferred size to allocate chunks in */ long chunk_size; /* preferred size to allocate chunks in */
struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */ struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */
char *object_base; /* address of object we are building */ char *object_base; /* address of object we are building */
char *next_free; /* where to add next char to current object */ char *next_free; /* where to add next char to current object */
char *chunk_limit; /* address of char after current chunk */ char *chunk_limit; /* address of char after current chunk */
union union
{ {
PTR_INT_TYPE tempint; PTR_INT_TYPE tempint;
void *tempptr; void *tempptr;
} temp; /* Temporary for some macros. */ } temp; /* Temporary for some macros. */
int alignment_mask; /* Mask of alignment for each object. */ int alignment_mask; /* Mask of alignment for each object. */
/* These prototypes vary based on `use_extra_arg', and we use /* These prototypes vary based on `use_extra_arg', and we use
casts to the prototypeless function type in all assignments, casts to the prototypeless function type in all assignments,
but having prototypes here quiets -Wstrict-prototypes. */ but having prototypes here quiets -Wstrict-prototypes. */
struct _obstack_chunk *(*chunkfun) (void *, long); struct _obstack_chunk *(*chunkfun) (void *, long);
void (*freefun) (void *, struct _obstack_chunk *); void (*freefun) (void *, struct _obstack_chunk *);
void *extra_arg; /* first arg for chunk alloc/dealloc funcs */ void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */ unsigned use_extra_arg : 1; /* chunk alloc/dealloc funcs take extra arg */
unsigned maybe_empty_object:1;/* There is a possibility that the current unsigned maybe_empty_object : 1; /* There is a possibility that the current
chunk contains a zero-length object. This chunk contains a zero-length object. This
prevents freeing the chunk if we allocate prevents freeing the chunk if we allocate
a bigger chunk to replace it. */ a bigger chunk to replace it. */
unsigned alloc_failed:1; /* No longer used, as we now call the failed unsigned alloc_failed : 1; /* No longer used, as we now call the failed
handler on error, but retained for binary handler on error, but retained for binary
compatibility. */ compatibility. */
}; };
/* Declare the external functions we use; they are in obstack.c. */ /* Declare the external functions we use; they are in obstack.c. */
extern void _obstack_newchunk (struct obstack *, int); extern void _obstack_newchunk (struct obstack *, int);
extern int _obstack_begin (struct obstack *, int, int, extern int _obstack_begin (struct obstack *, int, int,
void *(*) (long), void (*) (void *)); void *(*)(long), void (*)(void *));
extern int _obstack_begin_1 (struct obstack *, int, int, extern int _obstack_begin_1 (struct obstack *, int, int,
void *(*) (void *, long), void *(*)(void *, long),
void (*) (void *, void *), void *); void (*)(void *, void *), void *);
extern int _obstack_memory_used (struct obstack *); extern int _obstack_memory_used (struct obstack *);
void obstack_free (struct obstack *__obstack, void *__glibc_block); void obstack_free (struct obstack *__obstack, void *__glibc_block);
/* Error handler called when `obstack_chunk_alloc' failed to allocate /* Error handler called when `obstack_chunk_alloc' failed to allocate
more memory. This can be set to a user defined function which more memory. This can be set to a user defined function which
should either abort gracefully or use longjump - but shouldn't should either abort gracefully or use longjump - but shouldn't
@ -196,7 +196,7 @@ extern void (*obstack_alloc_failed_handler) (void);
/* Exit value used when `print_and_abort' is used. */ /* Exit value used when `print_and_abort' is used. */
extern int obstack_exit_failure; extern int obstack_exit_failure;
/* Pointer to beginning of object being allocated or to be allocated next. /* Pointer to beginning of object being allocated or to be allocated next.
Note that this might not be the final address of the object Note that this might not be the final address of the object
because a new chunk might be needed to hold the final size. */ because a new chunk might be needed to hold the final size. */
@ -209,45 +209,45 @@ extern int obstack_exit_failure;
/* Pointer to next byte not yet allocated in current chunk. */ /* Pointer to next byte not yet allocated in current chunk. */
#define obstack_next_free(h) ((h)->next_free) #define obstack_next_free(h) ((h)->next_free)
/* Mask specifying low bits that should be clear in address of an object. */ /* Mask specifying low bits that should be clear in address of an object. */
#define obstack_alignment_mask(h) ((h)->alignment_mask) #define obstack_alignment_mask(h) ((h)->alignment_mask)
/* To prevent prototype warnings provide complete argument list. */ /* To prevent prototype warnings provide complete argument list. */
#define obstack_init(h) \ #define obstack_init(h) \
_obstack_begin ((h), 0, 0, \ _obstack_begin ((h), 0, 0, \
(void *(*) (long)) obstack_chunk_alloc, \ (void *(*)(long))obstack_chunk_alloc, \
(void (*) (void *)) obstack_chunk_free) (void (*)(void *))obstack_chunk_free)
#define obstack_begin(h, size) \ #define obstack_begin(h, size) \
_obstack_begin ((h), (size), 0, \ _obstack_begin ((h), (size), 0, \
(void *(*) (long)) obstack_chunk_alloc, \ (void *(*)(long))obstack_chunk_alloc, \
(void (*) (void *)) obstack_chunk_free) (void (*)(void *))obstack_chunk_free)
#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ #define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
_obstack_begin ((h), (size), (alignment), \ _obstack_begin ((h), (size), (alignment), \
(void *(*) (long)) (chunkfun), \ (void *(*)(long))(chunkfun), \
(void (*) (void *)) (freefun)) (void (*)(void *))(freefun))
#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ #define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
_obstack_begin_1 ((h), (size), (alignment), \ _obstack_begin_1 ((h), (size), (alignment), \
(void *(*) (void *, long)) (chunkfun), \ (void *(*)(void *, long))(chunkfun), \
(void (*) (void *, void *)) (freefun), (arg)) (void (*)(void *, void *))(freefun), (arg))
#define obstack_chunkfun(h, newchunkfun) \ #define obstack_chunkfun(h, newchunkfun) \
((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun)) ((h)->chunkfun = (struct _obstack_chunk *(*)(void *, long))(newchunkfun))
#define obstack_freefun(h, newfreefun) \ #define obstack_freefun(h, newfreefun) \
((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun)) ((h)->freefun = (void (*)(void *, struct _obstack_chunk *))(newfreefun))
#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = (achar)) #define obstack_1grow_fast(h, achar) (*((h)->next_free)++ = (achar))
#define obstack_blank_fast(h,n) ((h)->next_free += (n)) #define obstack_blank_fast(h, n) ((h)->next_free += (n))
#define obstack_memory_used(h) _obstack_memory_used (h) #define obstack_memory_used(h) _obstack_memory_used (h)
#if defined __GNUC__ #if defined __GNUC__
/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and /* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and
does not implement __extension__. But that compiler doesn't define does not implement __extension__. But that compiler doesn't define
@ -261,158 +261,158 @@ extern int obstack_exit_failure;
without using a global variable. without using a global variable.
Also, we can avoid using the `temp' slot, to make faster code. */ Also, we can avoid using the `temp' slot, to make faster code. */
# define obstack_object_size(OBSTACK) \ # define obstack_object_size(OBSTACK) \
__extension__ \ __extension__ \
({ struct obstack const *__o = (OBSTACK); \ ({ struct obstack const *__o = (OBSTACK); \
(unsigned) (__o->next_free - __o->object_base); }) (unsigned) (__o->next_free - __o->object_base); })
# define obstack_room(OBSTACK) \ # define obstack_room(OBSTACK) \
__extension__ \ __extension__ \
({ struct obstack const *__o = (OBSTACK); \ ({ struct obstack const *__o = (OBSTACK); \
(unsigned) (__o->chunk_limit - __o->next_free); }) (unsigned) (__o->chunk_limit - __o->next_free); })
# define obstack_make_room(OBSTACK,length) \ # define obstack_make_room(OBSTACK, length) \
__extension__ \ __extension__ \
({ struct obstack *__o = (OBSTACK); \ ({ struct obstack *__o = (OBSTACK); \
int __len = (length); \ int __len = (length); \
if (__o->chunk_limit - __o->next_free < __len) \ if (__o->chunk_limit - __o->next_free < __len) \
_obstack_newchunk (__o, __len); \ _obstack_newchunk (__o, __len); \
(void) 0; }) (void) 0; })
# define obstack_empty_p(OBSTACK) \ # define obstack_empty_p(OBSTACK) \
__extension__ \ __extension__ \
({ struct obstack const *__o = (OBSTACK); \ ({ struct obstack const *__o = (OBSTACK); \
(__o->chunk->prev == 0 \ (__o->chunk->prev == 0 \
&& __o->next_free == __PTR_ALIGN ((char *) __o->chunk, \ && __o->next_free == __PTR_ALIGN ((char *) __o->chunk, \
__o->chunk->contents, \ __o->chunk->contents, \
__o->alignment_mask)); }) __o->alignment_mask)); })
# define obstack_grow(OBSTACK,where,length) \ # define obstack_grow(OBSTACK, where, length) \
__extension__ \ __extension__ \
({ struct obstack *__o = (OBSTACK); \ ({ struct obstack *__o = (OBSTACK); \
int __len = (length); \ int __len = (length); \
if (__o->next_free + __len > __o->chunk_limit) \ if (__o->next_free + __len > __o->chunk_limit) \
_obstack_newchunk (__o, __len); \ _obstack_newchunk (__o, __len); \
memcpy (__o->next_free, where, __len); \ memcpy (__o->next_free, where, __len); \
__o->next_free += __len; \ __o->next_free += __len; \
(void) 0; }) (void) 0; })
# define obstack_grow0(OBSTACK,where,length) \ # define obstack_grow0(OBSTACK, where, length) \
__extension__ \ __extension__ \
({ struct obstack *__o = (OBSTACK); \ ({ struct obstack *__o = (OBSTACK); \
int __len = (length); \ int __len = (length); \
if (__o->next_free + __len + 1 > __o->chunk_limit) \ if (__o->next_free + __len + 1 > __o->chunk_limit) \
_obstack_newchunk (__o, __len + 1); \ _obstack_newchunk (__o, __len + 1); \
memcpy (__o->next_free, where, __len); \ memcpy (__o->next_free, where, __len); \
__o->next_free += __len; \ __o->next_free += __len; \
*(__o->next_free)++ = 0; \ *(__o->next_free)++ = 0; \
(void) 0; }) (void) 0; })
# define obstack_1grow(OBSTACK,datum) \ # define obstack_1grow(OBSTACK, datum) \
__extension__ \ __extension__ \
({ struct obstack *__o = (OBSTACK); \ ({ struct obstack *__o = (OBSTACK); \
if (__o->next_free + 1 > __o->chunk_limit) \ if (__o->next_free + 1 > __o->chunk_limit) \
_obstack_newchunk (__o, 1); \ _obstack_newchunk (__o, 1); \
obstack_1grow_fast (__o, datum); \ obstack_1grow_fast (__o, datum); \
(void) 0; }) (void) 0; })
/* These assume that the obstack alignment is good enough for pointers /* These assume that the obstack alignment is good enough for pointers
or ints, and that the data added so far to the current object or ints, and that the data added so far to the current object
shares that much alignment. */ shares that much alignment. */
# define obstack_ptr_grow(OBSTACK,datum) \ # define obstack_ptr_grow(OBSTACK, datum) \
__extension__ \ __extension__ \
({ struct obstack *__o = (OBSTACK); \ ({ struct obstack *__o = (OBSTACK); \
if (__o->next_free + sizeof (void *) > __o->chunk_limit) \ if (__o->next_free + sizeof (void *) > __o->chunk_limit) \
_obstack_newchunk (__o, sizeof (void *)); \ _obstack_newchunk (__o, sizeof (void *)); \
obstack_ptr_grow_fast (__o, datum); }) \ obstack_ptr_grow_fast (__o, datum); }) \
# define obstack_int_grow(OBSTACK,datum) \ # define obstack_int_grow(OBSTACK, datum) \
__extension__ \ __extension__ \
({ struct obstack *__o = (OBSTACK); \ ({ struct obstack *__o = (OBSTACK); \
if (__o->next_free + sizeof (int) > __o->chunk_limit) \ if (__o->next_free + sizeof (int) > __o->chunk_limit) \
_obstack_newchunk (__o, sizeof (int)); \ _obstack_newchunk (__o, sizeof (int)); \
obstack_int_grow_fast (__o, datum); }) obstack_int_grow_fast (__o, datum); })
# define obstack_ptr_grow_fast(OBSTACK,aptr) \ # define obstack_ptr_grow_fast(OBSTACK, aptr) \
__extension__ \ __extension__ \
({ struct obstack *__o1 = (OBSTACK); \ ({ struct obstack *__o1 = (OBSTACK); \
*(const void **) __o1->next_free = (aptr); \ *(const void **) __o1->next_free = (aptr); \
__o1->next_free += sizeof (const void *); \ __o1->next_free += sizeof (const void *); \
(void) 0; }) (void) 0; })
# define obstack_int_grow_fast(OBSTACK,aint) \ # define obstack_int_grow_fast(OBSTACK, aint) \
__extension__ \ __extension__ \
({ struct obstack *__o1 = (OBSTACK); \ ({ struct obstack *__o1 = (OBSTACK); \
*(int *) __o1->next_free = (aint); \ *(int *) __o1->next_free = (aint); \
__o1->next_free += sizeof (int); \ __o1->next_free += sizeof (int); \
(void) 0; }) (void) 0; })
# define obstack_blank(OBSTACK,length) \ # define obstack_blank(OBSTACK, length) \
__extension__ \ __extension__ \
({ struct obstack *__o = (OBSTACK); \ ({ struct obstack *__o = (OBSTACK); \
int __len = (length); \ int __len = (length); \
if (__o->chunk_limit - __o->next_free < __len) \ if (__o->chunk_limit - __o->next_free < __len) \
_obstack_newchunk (__o, __len); \ _obstack_newchunk (__o, __len); \
obstack_blank_fast (__o, __len); \ obstack_blank_fast (__o, __len); \
(void) 0; }) (void) 0; })
# define obstack_alloc(OBSTACK,length) \ # define obstack_alloc(OBSTACK, length) \
__extension__ \ __extension__ \
({ struct obstack *__h = (OBSTACK); \ ({ struct obstack *__h = (OBSTACK); \
obstack_blank (__h, (length)); \ obstack_blank (__h, (length)); \
obstack_finish (__h); }) obstack_finish (__h); })
# define obstack_copy(OBSTACK,where,length) \ # define obstack_copy(OBSTACK, where, length) \
__extension__ \ __extension__ \
({ struct obstack *__h = (OBSTACK); \ ({ struct obstack *__h = (OBSTACK); \
obstack_grow (__h, (where), (length)); \ obstack_grow (__h, (where), (length)); \
obstack_finish (__h); }) obstack_finish (__h); })
# define obstack_copy0(OBSTACK,where,length) \ # define obstack_copy0(OBSTACK, where, length) \
__extension__ \ __extension__ \
({ struct obstack *__h = (OBSTACK); \ ({ struct obstack *__h = (OBSTACK); \
obstack_grow0 (__h, (where), (length)); \ obstack_grow0 (__h, (where), (length)); \
obstack_finish (__h); }) obstack_finish (__h); })
/* The local variable is named __o1 to avoid a name conflict /* The local variable is named __o1 to avoid a name conflict
when obstack_blank is called. */ when obstack_blank is called. */
# define obstack_finish(OBSTACK) \ # define obstack_finish(OBSTACK) \
__extension__ \ __extension__ \
({ struct obstack *__o1 = (OBSTACK); \ ({ struct obstack *__o1 = (OBSTACK); \
void *__value = (void *) __o1->object_base; \ void *__value = (void *) __o1->object_base; \
if (__o1->next_free == __value) \ if (__o1->next_free == __value) \
__o1->maybe_empty_object = 1; \ __o1->maybe_empty_object = 1; \
__o1->next_free \ __o1->next_free \
= __PTR_ALIGN (__o1->object_base, __o1->next_free, \ = __PTR_ALIGN (__o1->object_base, __o1->next_free, \
__o1->alignment_mask); \ __o1->alignment_mask); \
if (__o1->next_free - (char *)__o1->chunk \ if (__o1->next_free - (char *) __o1->chunk \
> __o1->chunk_limit - (char *)__o1->chunk) \ > __o1->chunk_limit - (char *) __o1->chunk) \
__o1->next_free = __o1->chunk_limit; \ __o1->next_free = __o1->chunk_limit; \
__o1->object_base = __o1->next_free; \ __o1->object_base = __o1->next_free; \
__value; }) __value; })
# define obstack_free(OBSTACK, OBJ) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
void *__obj = (OBJ); \
if (__obj > (void *) __o->chunk && __obj < (void *) __o->chunk_limit) \
__o->next_free = __o->object_base = (char *) __obj; \
else (obstack_free) (__o, __obj); })
# define obstack_free(OBSTACK, OBJ) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
void *__obj = (OBJ); \
if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
__o->next_free = __o->object_base = (char *)__obj; \
else (obstack_free) (__o, __obj); })
#else /* not __GNUC__ */ #else /* not __GNUC__ */
# define obstack_object_size(h) \ # define obstack_object_size(h) \
(unsigned) ((h)->next_free - (h)->object_base) (unsigned) ((h)->next_free - (h)->object_base)
# define obstack_room(h) \ # define obstack_room(h) \
(unsigned) ((h)->chunk_limit - (h)->next_free) (unsigned) ((h)->chunk_limit - (h)->next_free)
# define obstack_empty_p(h) \ # define obstack_empty_p(h) \
((h)->chunk->prev == 0 \ ((h)->chunk->prev == 0 \
&& (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \ && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \
(h)->chunk->contents, \ (h)->chunk->contents, \
(h)->alignment_mask)) (h)->alignment_mask))
/* Note that the call to _obstack_newchunk is enclosed in (..., 0) /* Note that the call to _obstack_newchunk is enclosed in (..., 0)
so that we can avoid having void expressions so that we can avoid having void expressions
@ -420,88 +420,86 @@ __extension__ \
Casting the third operand to void was tried before, Casting the third operand to void was tried before,
but some compilers won't accept it. */ but some compilers won't accept it. */
# define obstack_make_room(h,length) \ # define obstack_make_room(h, length) \
( (h)->temp.tempint = (length), \ ((h)->temp.tempint = (length), \
(((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \ (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \
? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0)) ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0))
# define obstack_grow(h,where,length) \ # define obstack_grow(h, where, length) \
( (h)->temp.tempint = (length), \ ((h)->temp.tempint = (length), \
(((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \ (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \
? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \ ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \
memcpy ((h)->next_free, where, (h)->temp.tempint), \ memcpy ((h)->next_free, where, (h)->temp.tempint), \
(h)->next_free += (h)->temp.tempint) (h)->next_free += (h)->temp.tempint)
# define obstack_grow0(h,where,length) \ # define obstack_grow0(h, where, length) \
( (h)->temp.tempint = (length), \ ((h)->temp.tempint = (length), \
(((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit) \ (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit) \
? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0), \ ? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0), \
memcpy ((h)->next_free, where, (h)->temp.tempint), \ memcpy ((h)->next_free, where, (h)->temp.tempint), \
(h)->next_free += (h)->temp.tempint, \ (h)->next_free += (h)->temp.tempint, \
*((h)->next_free)++ = 0) *((h)->next_free)++ = 0)
# define obstack_1grow(h,datum) \ # define obstack_1grow(h, datum) \
( (((h)->next_free + 1 > (h)->chunk_limit) \ ((((h)->next_free + 1 > (h)->chunk_limit) \
? (_obstack_newchunk ((h), 1), 0) : 0), \ ? (_obstack_newchunk ((h), 1), 0) : 0), \
obstack_1grow_fast (h, datum)) obstack_1grow_fast (h, datum))
# define obstack_ptr_grow(h,datum) \ # define obstack_ptr_grow(h, datum) \
( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \ ((((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \ ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
obstack_ptr_grow_fast (h, datum)) obstack_ptr_grow_fast (h, datum))
# define obstack_int_grow(h,datum) \ # define obstack_int_grow(h, datum) \
( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \ ((((h)->next_free + sizeof (int) > (h)->chunk_limit) \
? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \ ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
obstack_int_grow_fast (h, datum)) obstack_int_grow_fast (h, datum))
# define obstack_ptr_grow_fast(h,aptr) \ # define obstack_ptr_grow_fast(h, aptr) \
(((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr)) (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr))
# define obstack_int_grow_fast(h,aint) \ # define obstack_int_grow_fast(h, aint) \
(((int *) ((h)->next_free += sizeof (int)))[-1] = (aint)) (((int *) ((h)->next_free += sizeof (int)))[-1] = (aint))
# define obstack_blank(h,length) \ # define obstack_blank(h, length) \
( (h)->temp.tempint = (length), \ ((h)->temp.tempint = (length), \
(((h)->chunk_limit - (h)->next_free < (h)->temp.tempint) \ (((h)->chunk_limit - (h)->next_free < (h)->temp.tempint) \
? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \ ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \
obstack_blank_fast (h, (h)->temp.tempint)) obstack_blank_fast (h, (h)->temp.tempint))
# define obstack_alloc(h,length) \ # define obstack_alloc(h, length) \
(obstack_blank ((h), (length)), obstack_finish ((h))) (obstack_blank ((h), (length)), obstack_finish ((h)))
# define obstack_copy(h,where,length) \ # define obstack_copy(h, where, length) \
(obstack_grow ((h), (where), (length)), obstack_finish ((h))) (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
# define obstack_copy0(h,where,length) \ # define obstack_copy0(h, where, length) \
(obstack_grow0 ((h), (where), (length)), obstack_finish ((h))) (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
# define obstack_finish(h) \ # define obstack_finish(h) \
( ((h)->next_free == (h)->object_base \ (((h)->next_free == (h)->object_base \
? (((h)->maybe_empty_object = 1), 0) \ ? (((h)->maybe_empty_object = 1), 0) \
: 0), \ : 0), \
(h)->temp.tempptr = (h)->object_base, \ (h)->temp.tempptr = (h)->object_base, \
(h)->next_free \ (h)->next_free \
= __PTR_ALIGN ((h)->object_base, (h)->next_free, \ = __PTR_ALIGN ((h)->object_base, (h)->next_free, \
(h)->alignment_mask), \ (h)->alignment_mask), \
(((h)->next_free - (char *) (h)->chunk \ (((h)->next_free - (char *) (h)->chunk \
> (h)->chunk_limit - (char *) (h)->chunk) \ > (h)->chunk_limit - (char *) (h)->chunk) \
? ((h)->next_free = (h)->chunk_limit) : 0), \ ? ((h)->next_free = (h)->chunk_limit) : 0), \
(h)->object_base = (h)->next_free, \ (h)->object_base = (h)->next_free, \
(h)->temp.tempptr) (h)->temp.tempptr)
# define obstack_free(h,obj) \ # define obstack_free(h, obj) \
( (h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk, \ ((h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk, \
((((h)->temp.tempint > 0 \ ((((h)->temp.tempint > 0 \
&& (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk)) \ && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk)) \
? (((h)->next_free = (h)->object_base \ ? (((h)->next_free = (h)->object_base \
= (h)->temp.tempint + (char *) (h)->chunk), 0) \ = (h)->temp.tempint + (char *) (h)->chunk), 0) \
: ((obstack_free) ((h), (h)->temp.tempint + (char *) (h)->chunk), 0))) : ((obstack_free) ((h), (h)->temp.tempint + (char *) (h)->chunk), 0)))
#endif /* not __GNUC__ */ #endif /* not __GNUC__ */
#ifdef __cplusplus #ifdef __cplusplus
} /* C++ */ } /* C++ */
#endif #endif
#endif /* obstack.h */ #endif /* obstack.h */

View File

@ -33,17 +33,17 @@ __libc_freeres (void)
protect for multiple executions since these are fatal. */ protect for multiple executions since these are fatal. */
static long int already_called; static long int already_called;
if (! atomic_compare_and_exchange_bool_acq (&already_called, 1, 0)) if (!atomic_compare_and_exchange_bool_acq (&already_called, 1, 0))
{ {
void * const *p; void *const *p;
_IO_cleanup (); _IO_cleanup ();
RUN_HOOK (__libc_subfreeres, ()); RUN_HOOK (__libc_subfreeres, ());
for (p = symbol_set_first_element (__libc_freeres_ptrs); for (p = symbol_set_first_element (__libc_freeres_ptrs);
! symbol_set_end_p (__libc_freeres_ptrs, p); ++p) !symbol_set_end_p (__libc_freeres_ptrs, p); ++p)
free (*p); free (*p);
} }
} }
libc_hidden_def (__libc_freeres) libc_hidden_def (__libc_freeres)

View File

@ -48,19 +48,19 @@ main (void)
free (malloc (10)); free (malloc (10));
for (i=0; i<100; ++i) for (i = 0; i < 100; ++i)
{ {
save_state = malloc_get_state (); save_state = malloc_get_state ();
if (save_state == NULL) if (save_state == NULL)
{ {
merror ("malloc_get_state () failed."); merror ("malloc_get_state () failed.");
break; break;
} }
/*free (malloc (10)); This could change the top chunk! */ /*free (malloc (10)); This could change the top chunk! */
malloc_set_state (save_state); malloc_set_state (save_state);
p1 = realloc (p1, i*4 + 4); p1 = realloc (p1, i * 4 + 4);
if (p1 == NULL) if (p1 == NULL)
merror ("realloc (i*4) failed."); merror ("realloc (i*4) failed.");
free (save_state); free (save_state);
} }

View File

@ -55,20 +55,20 @@ main (void)
ssize_t n = getline (&line, &linelen, fp); ssize_t n = getline (&line, &linelen, fp);
if (n < 0) if (n < 0)
break; break;
if (n == 0) if (n == 0)
continue; continue;
copy = strdup (line); copy = strdup (line);
if (copy == NULL) if (copy == NULL)
abort (); abort ();
p = (char **) tsearch (copy, &root, p = (char **) tsearch (copy, &root,
(int (*) (const void *, const void *)) strcmp); (int (*)(const void *, const void *))strcmp);
if (*p != copy) if (*p != copy)
/* This line wasn't added. */ /* This line wasn't added. */
free (copy); free (copy);
} }
fclose (fp); fclose (fp);

View File

@ -79,11 +79,11 @@ do_test (void)
for (i = 0; i < 20; i++) for (i = 0; i < 20; i++)
{ {
if (c[i] != 0) if (c[i] != 0)
ok = 0; ok = 0;
} }
if (ok == 0) if (ok == 0)
merror ("first 20 bytes were not cleared"); merror ("first 20 bytes were not cleared");
free (p); free (p);
@ -104,11 +104,11 @@ do_test (void)
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
{ {
if (c[i] != 0xff) if (c[i] != 0xff)
ok = 0; ok = 0;
} }
if (ok == 0) if (ok == 0)
merror ("first 16 bytes were not correct"); merror ("first 16 bytes were not correct");
/* Check failed realloc leaves original untouched (C89). */ /* Check failed realloc leaves original untouched (C89). */
c = realloc (p, -1); c = realloc (p, -1);
@ -121,11 +121,11 @@ do_test (void)
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
{ {
if (c[i] != 0xff) if (c[i] != 0xff)
ok = 0; ok = 0;
} }
if (ok == 0) if (ok == 0)
merror ("first 16 bytes were not correct after failed realloc"); merror ("first 16 bytes were not correct after failed realloc");
/* realloc (p, 0) frees p (C89) and returns NULL (glibc). */ /* realloc (p, 0) frees p (C89) and returns NULL (glibc). */
p = realloc (p, 0); p = realloc (p, 0);