diff options
| author | svn2git <svn2git@FreeBSD.org> | 1994-07-01 08:00:00 +0000 |
|---|---|---|
| committer | svn2git <svn2git@FreeBSD.org> | 1994-07-01 08:00:00 +0000 |
| commit | 5e0e9b99dc3fc0ecd49d929db0d57c784b66f481 (patch) | |
| tree | e779b5a6edddbb949b7990751b12d6f25304ba86 /gnu/usr.bin/gdb/mmalloc | |
| parent | a16f65c7d117419bd266c28a1901ef129a337569 (diff) | |
Release FreeBSD 1.1.5.1upstream/1.1.5.1_cvsrelease/1.1.5.1_cvsreleng/1
This commit was manufactured to restore the state of the 1.1.5.1-RELEASE image.
Releases prior to 5.3-RELEASE are omitting the secure/ and crypto/ subdirs.
Diffstat (limited to 'gnu/usr.bin/gdb/mmalloc')
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/Makefile | 10 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/README.FreeBSD | 7 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/attach.c | 218 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/detach.c | 71 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/keys.c | 66 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/mcalloc.c | 53 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/mfree.c | 247 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/mmalloc.c | 334 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/mmalloc.h | 390 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/mmalloc.texi | 258 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/mmap-sup.c | 144 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/mmcheck.c | 196 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/mmemalign.c | 64 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/mmstats.c | 46 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/mmtrace.c | 166 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/mrealloc.c | 160 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/mvalloc.c | 40 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/mmalloc/sbrk-sup.c | 96 |
18 files changed, 2566 insertions, 0 deletions
diff --git a/gnu/usr.bin/gdb/mmalloc/Makefile b/gnu/usr.bin/gdb/mmalloc/Makefile new file mode 100644 index 000000000000..1ef0d1dd0e37 --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/Makefile @@ -0,0 +1,10 @@ +LIB= mmalloc +SRCS= mcalloc.c mfree.c mmalloc.c mmcheck.c mmemalign.c mmstats.c \ + mmtrace.c mrealloc.c mvalloc.c mmap-sup.c attach.c detach.c keys.c \ + sbrk-sup.c + +NOPROFILE=no +NOPIC=no +install: + @echo -n +.include <bsd.lib.mk> diff --git a/gnu/usr.bin/gdb/mmalloc/README.FreeBSD b/gnu/usr.bin/gdb/mmalloc/README.FreeBSD new file mode 100644 index 000000000000..338400ffa885 --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/README.FreeBSD @@ -0,0 +1,7 @@ +This is a greatly pared down libmmalloc directory. Only what's required to build +gdb-4.12 on FreeBSD was kept. + +This is temporary. In FreeBSD 2.0 a fully ported libmmalloc will likely appear +as a system library for use by all the build tools. + +paul@freefall.cdrom.com diff --git a/gnu/usr.bin/gdb/mmalloc/attach.c b/gnu/usr.bin/gdb/mmalloc/attach.c new file mode 100644 index 000000000000..6737fca38723 --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/attach.c @@ -0,0 +1,218 @@ +/* Initialization for access to a mmap'd malloc managed region. + Copyright 1992 Free Software Foundation, Inc. + + Contributed by Fred Fish at Cygnus Support. fnf@cygnus.com + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <sys/types.h> +#include <fcntl.h> /* After sys/types.h, at least for dpx/2. */ +#include <sys/stat.h> +#include <string.h> +#include "mmalloc.h" + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + + +#if defined(HAVE_MMAP) + +/* Forward declarations/prototypes for local functions */ + +static struct mdesc *reuse PARAMS ((int)); + +/* Initialize access to a mmalloc managed region. + + If FD is a valid file descriptor for an open file then data for the + mmalloc managed region is mapped to that file, otherwise "/dev/zero" + is used and the data will not exist in any filesystem object. + + If the open file corresponding to FD is from a previous use of + mmalloc and passes some basic sanity checks to ensure that it is + compatible with the current mmalloc package, then it's data is + mapped in and is immediately accessible at the same addresses in + the current process as the process that created the file. + + If BASEADDR is not NULL, the mapping is established starting at the + specified address in the process address space. If BASEADDR is NULL, + the mmalloc package chooses a suitable address at which to start the + mapped region, which will be the value of the previous mapping if + opening an existing file which was previously built by mmalloc, or + for new files will be a value chosen by mmap. + + Specifying BASEADDR provides more control over where the regions + start and how big they can be before bumping into existing mapped + regions or future mapped regions. + + On success, returns a "malloc descriptor" which is used in subsequent + calls to other mmalloc package functions. It is explicitly "void *" + ("char *" for systems that don't fully support void) so that users + of the package don't have to worry about the actual implementation + details. + + On failure returns NULL. */ + +PTR +mmalloc_attach (fd, baseaddr) + int fd; + PTR baseaddr; +{ + struct mdesc mtemp; + struct mdesc *mdp; + PTR mbase; + struct stat sbuf; + + /* First check to see if FD is a valid file descriptor, and if so, see + if the file has any current contents (size > 0). If it does, then + attempt to reuse the file. If we can't reuse the file, either + because it isn't a valid mmalloc produced file, was produced by an + obsolete version, or any other reason, then we fail to attach to + this file. */ + + if (fd >= 0) + { + if (fstat (fd, &sbuf) < 0) + { + return (NULL); + } + else if (sbuf.st_size > 0) + { + return ((PTR) reuse (fd)); + } + } + + /* We start off with the malloc descriptor allocated on the stack, until + we build it up enough to call _mmalloc_mmap_morecore() to allocate the + first page of the region and copy it there. Ensure that it is zero'd and + then initialize the fields that we know values for. */ + + mdp = &mtemp; + memset ((char *) mdp, 0, sizeof (mtemp)); + strncpy (mdp -> magic, MMALLOC_MAGIC, MMALLOC_MAGIC_SIZE); + mdp -> headersize = sizeof (mtemp); + mdp -> version = MMALLOC_VERSION; + mdp -> morecore = __mmalloc_mmap_morecore; + mdp -> fd = fd; + mdp -> base = mdp -> breakval = mdp -> top = baseaddr; + + /* If we have not been passed a valid open file descriptor for the file + to map to, then open /dev/zero and use that to map to. */ + + if (mdp -> fd < 0) + { + if ((mdp -> fd = open ("/dev/zero", O_RDWR)) < 0) + { + return (NULL); + } + else + { + mdp -> flags |= MMALLOC_DEVZERO; + } + } + + /* Now try to map in the first page, copy the malloc descriptor structure + there, and arrange to return a pointer to this new copy. If the mapping + fails, then close the file descriptor if it was opened by us, and arrange + to return a NULL. */ + + if ((mbase = mdp -> morecore (mdp, sizeof (mtemp))) != NULL) + { + memcpy (mbase, mdp, sizeof (mtemp)); + mdp = (struct mdesc *) mbase; + } + else + { + if (mdp -> flags & MMALLOC_DEVZERO) + { + close (mdp -> fd); + } + mdp = NULL; + } + + return ((PTR) mdp); +} + +/* Given an valid file descriptor on an open file, test to see if that file + is a valid mmalloc produced file, and if so, attempt to remap it into the + current process at the same address to which it was previously mapped. + + Note that we have to update the file descriptor number in the malloc- + descriptor read from the file to match the current valid one, before + trying to map the file in, and again after a successful mapping and + after we've switched over to using the mapped in malloc descriptor + rather than the temporary one on the stack. + + Once we've switched over to using the mapped in malloc descriptor, we + have to update the pointer to the morecore function, since it almost + certainly will be at a different address if the process reusing the + mapped region is from a different executable. + + Also note that if the heap being remapped previously used the mmcheck() + routines, we need to update the hooks since their target functions + will have certainly moved if the executable has changed in any way. + We do this by calling mmcheck() internally. + + Returns a pointer to the malloc descriptor if successful, or NULL if + unsuccessful for some reason. */ + +static struct mdesc * +reuse (fd) + int fd; +{ + struct mdesc mtemp; + struct mdesc *mdp = NULL; + + if ((lseek (fd, 0L, SEEK_SET) == 0) && + (read (fd, (char *) &mtemp, sizeof (mtemp)) == sizeof (mtemp)) && + (mtemp.headersize == sizeof (mtemp)) && + (strcmp (mtemp.magic, MMALLOC_MAGIC) == 0) && + (mtemp.version <= MMALLOC_VERSION)) + { + mtemp.fd = fd; + if (__mmalloc_remap_core (&mtemp) == mtemp.base) + { + mdp = (struct mdesc *) mtemp.base; + mdp -> fd = fd; + mdp -> morecore = __mmalloc_mmap_morecore; + if (mdp -> mfree_hook != NULL) + { + mmcheck ((PTR) mdp, (void (*) PARAMS ((void))) NULL); + } + } + } + return (mdp); +} + +#else /* !defined (HAVE_MMAP) */ + +/* For systems without mmap, the library still supplies an entry point + to link to, but trying to initialize access to an mmap'd managed region + always fails. */ + +/* ARGSUSED */ +PTR +mmalloc_attach (fd, baseaddr) + int fd; + PTR baseaddr; +{ + return (NULL); +} + +#endif /* defined (HAVE_MMAP) */ + diff --git a/gnu/usr.bin/gdb/mmalloc/detach.c b/gnu/usr.bin/gdb/mmalloc/detach.c new file mode 100644 index 000000000000..03d632c20609 --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/detach.c @@ -0,0 +1,71 @@ +/* Finish access to a mmap'd malloc managed region. + Copyright 1992 Free Software Foundation, Inc. + + Contributed by Fred Fish at Cygnus Support. fnf@cygnus.com + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <sys/types.h> +#include <fcntl.h> /* After sys/types.h, at least for dpx/2. */ +#include "mmalloc.h" + +/* Terminate access to a mmalloc managed region by unmapping all memory pages + associated with the region, and closing the file descriptor if it is one + that we opened. + + Returns NULL on success. + + Returns the malloc descriptor on failure, which can subsequently be used + for further action, such as obtaining more information about the nature of + the failure by examining the preserved errno value. + + Note that the malloc descriptor that we are using is currently located in + region we are about to unmap, so we first make a local copy of it on the + stack and use the copy. */ + +PTR +mmalloc_detach (md) + PTR md; +{ + struct mdesc mtemp; + + if (md != NULL) + { + + mtemp = *(struct mdesc *) md; + + /* Now unmap all the pages associated with this region by asking for a + negative increment equal to the current size of the region. */ + + if ((mtemp.morecore (&mtemp, mtemp.base - mtemp.top)) == NULL) + { + /* Update the original malloc descriptor with any changes */ + *(struct mdesc *) md = mtemp; + } + else + { + if (mtemp.flags & MMALLOC_DEVZERO) + { + close (mtemp.fd); + } + md = NULL; + } + } + + return (md); +} diff --git a/gnu/usr.bin/gdb/mmalloc/keys.c b/gnu/usr.bin/gdb/mmalloc/keys.c new file mode 100644 index 000000000000..69d41b977395 --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/keys.c @@ -0,0 +1,66 @@ +/* Access for application keys in mmap'd malloc managed region. + Copyright 1992 Free Software Foundation, Inc. + + Contributed by Fred Fish at Cygnus Support. fnf@cygnus.com + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* This module provides access to some keys that the application can use to + provide persistent access to locations in the mapped memory section. + The intent is that these keys are to be used sparingly as sort of + persistent global variables which the application can use to reinitialize + access to data in the mapped region. + + For the moment, these keys are simply stored in the malloc descriptor + itself, in an array of fixed length. This should be fixed so that there + can be an unlimited number of keys, possibly using a multilevel access + scheme of some sort. */ + +#include "mmalloc.h" + +int +mmalloc_setkey (md, keynum, key) + PTR md; + int keynum; + PTR key; +{ + struct mdesc *mdp = (struct mdesc *) md; + int result = 0; + + if ((mdp != NULL) && (keynum >= 0) && (keynum < MMALLOC_KEYS)) + { + mdp -> keys [keynum] = key; + result++; + } + return (result); +} + +PTR +mmalloc_getkey (md, keynum) + PTR md; + int keynum; +{ + struct mdesc *mdp = (struct mdesc *) md; + PTR keyval = NULL; + + if ((mdp != NULL) && (keynum >= 0) && (keynum < MMALLOC_KEYS)) + { + keyval = mdp -> keys [keynum]; + } + return (keyval); +} diff --git a/gnu/usr.bin/gdb/mmalloc/mcalloc.c b/gnu/usr.bin/gdb/mmalloc/mcalloc.c new file mode 100644 index 000000000000..08f07bfe1c79 --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/mcalloc.c @@ -0,0 +1,53 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <string.h> /* Prototypes for memcpy, memmove, memset, etc */ + +#include "mmalloc.h" + +/* Allocate an array of NMEMB elements each SIZE bytes long. + The entire array is initialized to zeros. */ + +PTR +mcalloc (md, nmemb, size) + PTR md; + register size_t nmemb; + register size_t size; +{ + register PTR result; + + if ((result = mmalloc (md, nmemb * size)) != NULL) + { + memset (result, 0, nmemb * size); + } + return (result); +} + +/* When using this package, provide a version of malloc/realloc/free built + on top of it, so that if we use the default sbrk() region we will not + collide with another malloc package trying to do the same thing, if + the application contains any "hidden" calls to malloc/realloc/free (such + as inside a system library). */ + +PTR +calloc (nmemb, size) + size_t nmemb; + size_t size; +{ + return (mcalloc ((PTR) NULL, nmemb, size)); +} diff --git a/gnu/usr.bin/gdb/mmalloc/mfree.c b/gnu/usr.bin/gdb/mmalloc/mfree.c new file mode 100644 index 000000000000..aee43aad15bf --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/mfree.c @@ -0,0 +1,247 @@ +/* Free a block of memory allocated by `mmalloc'. + Copyright 1990, 1991, 1992 Free Software Foundation + + Written May 1989 by Mike Haertel. + Heavily modified Mar 1992 by Fred Fish. (fnf@cygnus.com) + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#include "mmalloc.h" + +/* Return memory to the heap. + Like `mfree' but don't call a mfree_hook if there is one. */ + +void +__mmalloc_free (mdp, ptr) + struct mdesc *mdp; + PTR ptr; +{ + int type; + size_t block, blocks; + register size_t i; + struct list *prev, *next; + + block = BLOCK (ptr); + + type = mdp -> heapinfo[block].busy.type; + switch (type) + { + case 0: + /* Get as many statistics as early as we can. */ + mdp -> heapstats.chunks_used--; + mdp -> heapstats.bytes_used -= + mdp -> heapinfo[block].busy.info.size * BLOCKSIZE; + mdp -> heapstats.bytes_free += + mdp -> heapinfo[block].busy.info.size * BLOCKSIZE; + + /* Find the free cluster previous to this one in the free list. + Start searching at the last block referenced; this may benefit + programs with locality of allocation. */ + i = mdp -> heapindex; + if (i > block) + { + while (i > block) + { + i = mdp -> heapinfo[i].free.prev; + } + } + else + { + do + { + i = mdp -> heapinfo[i].free.next; + } + while ((i != 0) && (i < block)); + i = mdp -> heapinfo[i].free.prev; + } + + /* Determine how to link this block into the free list. */ + if (block == i + mdp -> heapinfo[i].free.size) + { + /* Coalesce this block with its predecessor. */ + mdp -> heapinfo[i].free.size += + mdp -> heapinfo[block].busy.info.size; + block = i; + } + else + { + /* Really link this block back into the free list. */ + mdp -> heapinfo[block].free.size = + mdp -> heapinfo[block].busy.info.size; + mdp -> heapinfo[block].free.next = mdp -> heapinfo[i].free.next; + mdp -> heapinfo[block].free.prev = i; + mdp -> heapinfo[i].free.next = block; + mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block; + mdp -> heapstats.chunks_free++; + } + + /* Now that the block is linked in, see if we can coalesce it + with its successor (by deleting its successor from the list + and adding in its size). */ + if (block + mdp -> heapinfo[block].free.size == + mdp -> heapinfo[block].free.next) + { + mdp -> heapinfo[block].free.size + += mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.size; + mdp -> heapinfo[block].free.next + = mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.next; + mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block; + mdp -> heapstats.chunks_free--; + } + + /* Now see if we can return stuff to the system. */ + blocks = mdp -> heapinfo[block].free.size; + if (blocks >= FINAL_FREE_BLOCKS && block + blocks == mdp -> heaplimit + && mdp -> morecore (mdp, 0) == ADDRESS (block + blocks)) + { + register size_t bytes = blocks * BLOCKSIZE; + mdp -> heaplimit -= blocks; + mdp -> morecore (mdp, -bytes); + mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next + = mdp -> heapinfo[block].free.next; + mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev + = mdp -> heapinfo[block].free.prev; + block = mdp -> heapinfo[block].free.prev; + mdp -> heapstats.chunks_free--; + mdp -> heapstats.bytes_free -= bytes; + } + + /* Set the next search to begin at this block. */ + mdp -> heapindex = block; + break; + + default: + /* Do some of the statistics. */ + mdp -> heapstats.chunks_used--; + mdp -> heapstats.bytes_used -= 1 << type; + mdp -> heapstats.chunks_free++; + mdp -> heapstats.bytes_free += 1 << type; + + /* Get the address of the first free fragment in this block. */ + prev = (struct list *) + ((char *) ADDRESS(block) + + (mdp -> heapinfo[block].busy.info.frag.first << type)); + + if (mdp -> heapinfo[block].busy.info.frag.nfree == + (BLOCKSIZE >> type) - 1) + { + /* If all fragments of this block are free, remove them + from the fragment list and free the whole block. */ + next = prev; + for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i) + { + next = next -> next; + } + prev -> prev -> next = next; + if (next != NULL) + { + next -> prev = prev -> prev; + } + mdp -> heapinfo[block].busy.type = 0; + mdp -> heapinfo[block].busy.info.size = 1; + + /* Keep the statistics accurate. */ + mdp -> heapstats.chunks_used++; + mdp -> heapstats.bytes_used += BLOCKSIZE; + mdp -> heapstats.chunks_free -= BLOCKSIZE >> type; + mdp -> heapstats.bytes_free -= BLOCKSIZE; + + mfree ((PTR) mdp, (PTR) ADDRESS(block)); + } + else if (mdp -> heapinfo[block].busy.info.frag.nfree != 0) + { + /* If some fragments of this block are free, link this + fragment into the fragment list after the first free + fragment of this block. */ + next = (struct list *) ptr; + next -> next = prev -> next; + next -> prev = prev; + prev -> next = next; + if (next -> next != NULL) + { + next -> next -> prev = next; + } + ++mdp -> heapinfo[block].busy.info.frag.nfree; + } + else + { + /* No fragments of this block are free, so link this + fragment into the fragment list and announce that + it is the first free fragment of this block. */ + prev = (struct list *) ptr; + mdp -> heapinfo[block].busy.info.frag.nfree = 1; + mdp -> heapinfo[block].busy.info.frag.first = + RESIDUAL (ptr, BLOCKSIZE) >> type; + prev -> next = mdp -> fraghead[type].next; + prev -> prev = &mdp -> fraghead[type]; + prev -> prev -> next = prev; + if (prev -> next != NULL) + { + prev -> next -> prev = prev; + } + } + break; + } +} + +/* Return memory to the heap. */ + +void +mfree (md, ptr) + PTR md; + PTR ptr; +{ + struct mdesc *mdp; + register struct alignlist *l; + + if (ptr != NULL) + { + mdp = MD_TO_MDP (md); + for (l = mdp -> aligned_blocks; l != NULL; l = l -> next) + { + if (l -> aligned == ptr) + { + l -> aligned = NULL; /* Mark the slot in the list as free. */ + ptr = l -> exact; + break; + } + } + if (mdp -> mfree_hook != NULL) + { + (*mdp -> mfree_hook) (md, ptr); + } + else + { + __mmalloc_free (mdp, ptr); + } + } +} + +/* When using this package, provide a version of malloc/realloc/free built + on top of it, so that if we use the default sbrk() region we will not + collide with another malloc package trying to do the same thing, if + the application contains any "hidden" calls to malloc/realloc/free (such + as inside a system library). */ + +void +free (ptr) + PTR ptr; +{ + mfree ((PTR) NULL, ptr); +} diff --git a/gnu/usr.bin/gdb/mmalloc/mmalloc.c b/gnu/usr.bin/gdb/mmalloc/mmalloc.c new file mode 100644 index 000000000000..46b450e8513d --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/mmalloc.c @@ -0,0 +1,334 @@ +/* Memory allocator `malloc'. + Copyright 1990, 1991, 1992 Free Software Foundation + + Written May 1989 by Mike Haertel. + Heavily modified Mar 1992 by Fred Fish for mmap'd version. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#include <string.h> /* Prototypes for memcpy, memmove, memset, etc */ + +#include "mmalloc.h" + +/* Prototypes for local functions */ + +static int initialize PARAMS ((struct mdesc *)); +static PTR morecore PARAMS ((struct mdesc *, size_t)); +static PTR align PARAMS ((struct mdesc *, size_t)); + +/* Aligned allocation. */ + +static PTR +align (mdp, size) + struct mdesc *mdp; + size_t size; +{ + PTR result; + unsigned long int adj; + + result = mdp -> morecore (mdp, size); + adj = RESIDUAL (result, BLOCKSIZE); + if (adj != 0) + { + adj = BLOCKSIZE - adj; + mdp -> morecore (mdp, adj); + result = (char *) result + adj; + } + return (result); +} + +/* Set everything up and remember that we have. */ + +static int +initialize (mdp) + struct mdesc *mdp; +{ + mdp -> heapsize = HEAP / BLOCKSIZE; + mdp -> heapinfo = (malloc_info *) + align (mdp, mdp -> heapsize * sizeof (malloc_info)); + if (mdp -> heapinfo == NULL) + { + return (0); + } + memset ((PTR)mdp -> heapinfo, 0, mdp -> heapsize * sizeof (malloc_info)); + mdp -> heapinfo[0].free.size = 0; + mdp -> heapinfo[0].free.next = mdp -> heapinfo[0].free.prev = 0; + mdp -> heapindex = 0; + mdp -> heapbase = (char *) mdp -> heapinfo; + mdp -> flags |= MMALLOC_INITIALIZED; + return (1); +} + +/* Get neatly aligned memory, initializing or + growing the heap info table as necessary. */ + +static PTR +morecore (mdp, size) + struct mdesc *mdp; + size_t size; +{ + PTR result; + malloc_info *newinfo, *oldinfo; + size_t newsize; + + result = align (mdp, size); + if (result == NULL) + { + return (NULL); + } + + /* Check if we need to grow the info table. */ + if ((size_t) BLOCK ((char *) result + size) > mdp -> heapsize) + { + newsize = mdp -> heapsize; + while ((size_t) BLOCK ((char *) result + size) > newsize) + { + newsize *= 2; + } + newinfo = (malloc_info *) align (mdp, newsize * sizeof (malloc_info)); + if (newinfo == NULL) + { + mdp -> morecore (mdp, -size); + return (NULL); + } + memset ((PTR) newinfo, 0, newsize * sizeof (malloc_info)); + memcpy ((PTR) newinfo, (PTR) mdp -> heapinfo, + mdp -> heapsize * sizeof (malloc_info)); + oldinfo = mdp -> heapinfo; + newinfo[BLOCK (oldinfo)].busy.type = 0; + newinfo[BLOCK (oldinfo)].busy.info.size + = BLOCKIFY (mdp -> heapsize * sizeof (malloc_info)); + mdp -> heapinfo = newinfo; + __mmalloc_free (mdp, (PTR)oldinfo); + mdp -> heapsize = newsize; + } + + mdp -> heaplimit = BLOCK ((char *) result + size); + return (result); +} + +/* Allocate memory from the heap. */ + +PTR +mmalloc (md, size) + PTR md; + size_t size; +{ + struct mdesc *mdp; + PTR result; + size_t block, blocks, lastblocks, start; + register size_t i; + struct list *next; + register size_t log; + + if (size == 0) + { + return (NULL); + } + + mdp = MD_TO_MDP (md); + + if (mdp -> mmalloc_hook != NULL) + { + return ((*mdp -> mmalloc_hook) (md, size)); + } + + if (!(mdp -> flags & MMALLOC_INITIALIZED)) + { + if (!initialize (mdp)) + { + return (NULL); + } + } + + if (size < sizeof (struct list)) + { + size = sizeof (struct list); + } + + /* Determine the allocation policy based on the request size. */ + if (size <= BLOCKSIZE / 2) + { + /* Small allocation to receive a fragment of a block. + Determine the logarithm to base two of the fragment size. */ + log = 1; + --size; + while ((size /= 2) != 0) + { + ++log; + } + + /* Look in the fragment lists for a + free fragment of the desired size. */ + next = mdp -> fraghead[log].next; + if (next != NULL) + { + /* There are free fragments of this size. + Pop a fragment out of the fragment list and return it. + Update the block's nfree and first counters. */ + result = (PTR) next; + next -> prev -> next = next -> next; + if (next -> next != NULL) + { + next -> next -> prev = next -> prev; + } + block = BLOCK (result); + if (--mdp -> heapinfo[block].busy.info.frag.nfree != 0) + { + mdp -> heapinfo[block].busy.info.frag.first = + RESIDUAL (next -> next, BLOCKSIZE) >> log; + } + + /* Update the statistics. */ + mdp -> heapstats.chunks_used++; + mdp -> heapstats.bytes_used += 1 << log; + mdp -> heapstats.chunks_free--; + mdp -> heapstats.bytes_free -= 1 << log; + } + else + { + /* No free fragments of the desired size, so get a new block + and break it into fragments, returning the first. */ + result = mmalloc (md, BLOCKSIZE); + if (result == NULL) + { + return (NULL); + } + + /* Link all fragments but the first into the free list. */ + for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i) + { + next = (struct list *) ((char *) result + (i << log)); + next -> next = mdp -> fraghead[log].next; + next -> prev = &mdp -> fraghead[log]; + next -> prev -> next = next; + if (next -> next != NULL) + { + next -> next -> prev = next; + } + } + + /* Initialize the nfree and first counters for this block. */ + block = BLOCK (result); + mdp -> heapinfo[block].busy.type = log; + mdp -> heapinfo[block].busy.info.frag.nfree = i - 1; + mdp -> heapinfo[block].busy.info.frag.first = i - 1; + + mdp -> heapstats.chunks_free += (BLOCKSIZE >> log) - 1; + mdp -> heapstats.bytes_free += BLOCKSIZE - (1 << log); + mdp -> heapstats.bytes_used -= BLOCKSIZE - (1 << log); + } + } + else + { + /* Large allocation to receive one or more blocks. + Search the free list in a circle starting at the last place visited. + If we loop completely around without finding a large enough + space we will have to get more memory from the system. */ + blocks = BLOCKIFY(size); + start = block = MALLOC_SEARCH_START; + while (mdp -> heapinfo[block].free.size < blocks) + { + block = mdp -> heapinfo[block].free.next; + if (block == start) + { + /* Need to get more from the system. Check to see if + the new core will be contiguous with the final free + block; if so we don't need to get as much. */ + block = mdp -> heapinfo[0].free.prev; + lastblocks = mdp -> heapinfo[block].free.size; + if (mdp -> heaplimit != 0 && + block + lastblocks == mdp -> heaplimit && + mdp -> morecore (mdp, 0) == ADDRESS(block + lastblocks) && + (morecore (mdp, (blocks - lastblocks) * BLOCKSIZE)) != NULL) + { + /* Which block we are extending (the `final free + block' referred to above) might have changed, if + it got combined with a freed info table. */ + block = mdp -> heapinfo[0].free.prev; + + mdp -> heapinfo[block].free.size += (blocks - lastblocks); + mdp -> heapstats.bytes_free += + (blocks - lastblocks) * BLOCKSIZE; + continue; + } + result = morecore(mdp, blocks * BLOCKSIZE); + if (result == NULL) + { + return (NULL); + } + block = BLOCK (result); + mdp -> heapinfo[block].busy.type = 0; + mdp -> heapinfo[block].busy.info.size = blocks; + mdp -> heapstats.chunks_used++; + mdp -> heapstats.bytes_used += blocks * BLOCKSIZE; + return (result); + } + } + + /* At this point we have found a suitable free list entry. + Figure out how to remove what we need from the list. */ + result = ADDRESS(block); + if (mdp -> heapinfo[block].free.size > blocks) + { + /* The block we found has a bit left over, + so relink the tail end back into the free list. */ + mdp -> heapinfo[block + blocks].free.size + = mdp -> heapinfo[block].free.size - blocks; + mdp -> heapinfo[block + blocks].free.next + = mdp -> heapinfo[block].free.next; + mdp -> heapinfo[block + blocks].free.prev + = mdp -> heapinfo[block].free.prev; + mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next + = mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev + = mdp -> heapindex = block + blocks; + } + else + { + /* The block exactly matches our requirements, + so just remove it from the list. */ + mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev + = mdp -> heapinfo[block].free.prev; + mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next + = mdp -> heapindex = mdp -> heapinfo[block].free.next; + mdp -> heapstats.chunks_free--; + } + + mdp -> heapinfo[block].busy.type = 0; + mdp -> heapinfo[block].busy.info.size = blocks; + mdp -> heapstats.chunks_used++; + mdp -> heapstats.bytes_used += blocks * BLOCKSIZE; + mdp -> heapstats.bytes_free -= blocks * BLOCKSIZE; + } + + return (result); +} + +/* When using this package, provide a version of malloc/realloc/free built + on top of it, so that if we use the default sbrk() region we will not + collide with another malloc package trying to do the same thing, if + the application contains any "hidden" calls to malloc/realloc/free (such + as inside a system library). */ + +PTR +malloc (size) + size_t size; +{ + return (mmalloc ((PTR) NULL, size)); +} diff --git a/gnu/usr.bin/gdb/mmalloc/mmalloc.h b/gnu/usr.bin/gdb/mmalloc/mmalloc.h new file mode 100644 index 000000000000..54b6ed654dcd --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/mmalloc.h @@ -0,0 +1,390 @@ +/* Declarations for `mmalloc' and friends. + Copyright 1990, 1991, 1992 Free Software Foundation + + Written May 1989 by Mike Haertel. + Heavily modified Mar 1992 by Fred Fish. (fnf@cygnus.com) + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + + +#ifndef __MMALLOC_H +#define __MMALLOC_H 1 + +#ifdef __STDC__ +# include <stddef.h> +# define PTR void * +# define CONST const +# define PARAMS(paramlist) paramlist +# include <limits.h> +# ifndef NULL +# define NULL (void *) 0 +# endif +#else +# define PTR char * +# define CONST /* nothing */ +# define PARAMS(paramlist) () +# ifndef size_t +# define size_t unsigned int +# endif +# ifndef CHAR_BIT +# define CHAR_BIT 8 +# endif +# ifndef NULL +# define NULL 0 +# endif +#endif + +#ifndef MIN +# define MIN(A, B) ((A) < (B) ? (A) : (B)) +#endif + +#define MMALLOC_MAGIC "mmalloc" /* Mapped file magic number */ +#define MMALLOC_MAGIC_SIZE 8 /* Size of magic number buf */ +#define MMALLOC_VERSION 1 /* Current mmalloc version */ +#define MMALLOC_KEYS 16 /* Keys for application use */ + +/* The allocator divides the heap into blocks of fixed size; large + requests receive one or more whole blocks, and small requests + receive a fragment of a block. Fragment sizes are powers of two, + and all fragments of a block are the same size. When all the + fragments in a block have been freed, the block itself is freed. */ + +#define INT_BIT (CHAR_BIT * sizeof(int)) +#define BLOCKLOG (INT_BIT > 16 ? 12 : 9) +#define BLOCKSIZE ((unsigned int) 1 << BLOCKLOG) +#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE) + +/* The difference between two pointers is a signed int. On machines where + the data addresses have the high bit set, we need to ensure that the + difference becomes an unsigned int when we are using the address as an + integral value. In addition, when using with the '%' operator, the + sign of the result is machine dependent for negative values, so force + it to be treated as an unsigned int. */ + +#define ADDR2UINT(addr) ((unsigned int) ((char *) (addr) - (char *) NULL)) +#define RESIDUAL(addr,bsize) ((unsigned int) (ADDR2UINT (addr) % (bsize))) + +/* Determine the amount of memory spanned by the initial heap table + (not an absolute limit). */ + +#define HEAP (INT_BIT > 16 ? 4194304 : 65536) + +/* Number of contiguous free blocks allowed to build up at the end of + memory before they will be returned to the system. */ + +#define FINAL_FREE_BLOCKS 8 + +/* Where to start searching the free list when looking for new memory. + The two possible values are 0 and heapindex. Starting at 0 seems + to reduce total memory usage, while starting at heapindex seems to + run faster. */ + +#define MALLOC_SEARCH_START mdp -> heapindex + +/* Address to block number and vice versa. */ + +#define BLOCK(A) (((char *) (A) - mdp -> heapbase) / BLOCKSIZE + 1) + +#define ADDRESS(B) ((PTR) (((B) - 1) * BLOCKSIZE + mdp -> heapbase)) + +/* Data structure giving per-block information. */ + +typedef union + { + /* Heap information for a busy block. */ + struct + { + /* Zero for a large block, or positive giving the + logarithm to the base two of the fragment size. */ + int type; + union + { + struct + { + size_t nfree; /* Free fragments in a fragmented block. */ + size_t first; /* First free fragment of the block. */ + } frag; + /* Size (in blocks) of a large cluster. */ + size_t size; + } info; + } busy; + /* Heap information for a free block (that may be the first of + a free cluster). */ + struct + { + size_t size; /* Size (in blocks) of a free cluster. */ + size_t next; /* Index of next free cluster. */ + size_t prev; /* Index of previous free cluster. */ + } free; + } malloc_info; + +/* List of blocks allocated with `mmemalign' (or `mvalloc'). */ + +struct alignlist + { + struct alignlist *next; + PTR aligned; /* The address that mmemaligned returned. */ + PTR exact; /* The address that malloc returned. */ + }; + +/* Doubly linked lists of free fragments. */ + +struct list + { + struct list *next; + struct list *prev; + }; + +/* Statistics available to the user. + FIXME: By design, the internals of the malloc package are no longer + exported to the user via an include file, so access to this data needs + to be via some other mechanism, such as mmstat_<something> where the + return value is the <something> the user is interested in. */ + +struct mstats + { + size_t bytes_total; /* Total size of the heap. */ + size_t chunks_used; /* Chunks allocated by the user. */ + size_t bytes_used; /* Byte total of user-allocated chunks. */ + size_t chunks_free; /* Chunks in the free list. */ + size_t bytes_free; /* Byte total of chunks in the free list. */ + }; + +/* Internal structure that defines the format of the malloc-descriptor. + This gets written to the base address of the region that mmalloc is + managing, and thus also becomes the file header for the mapped file, + if such a file exists. */ + +struct mdesc +{ + /* The "magic number" for an mmalloc file. */ + + char magic[MMALLOC_MAGIC_SIZE]; + + /* The size in bytes of this structure, used as a sanity check when reusing + a previously created mapped file. */ + + unsigned int headersize; + + /* The version number of the mmalloc package that created this file. */ + + unsigned char version; + + /* Some flag bits to keep track of various internal things. */ + + unsigned int flags; + + /* If a system call made by the mmalloc package fails, the errno is + preserved for future examination. */ + + int saved_errno; + + /* Pointer to the function that is used to get more core, or return core + to the system, for requests using this malloc descriptor. For memory + mapped regions, this is the mmap() based routine. There may also be + a single malloc descriptor that points to an sbrk() based routine + for systems without mmap() or for applications that call the mmalloc() + package with a NULL malloc descriptor. + + FIXME: For mapped regions shared by more than one process, this + needs to be maintained on a per-process basis. */ + + PTR (*morecore) PARAMS ((struct mdesc *, int)); + + /* Pointer to the function that causes an abort when the memory checking + features are activated. By default this is set to abort(), but can + be set to another function by the application using mmalloc(). + + FIXME: For mapped regions shared by more than one process, this + needs to be maintained on a per-process basis. */ + + void (*abortfunc) PARAMS ((void)); + + /* Debugging hook for free. + + FIXME: For mapped regions shared by more than one process, this + needs to be maintained on a per-process basis. */ + + void (*mfree_hook) PARAMS ((PTR, PTR)); + + /* Debugging hook for `malloc'. + + FIXME: For mapped regions shared by more than one process, this + needs to be maintained on a per-process basis. */ + + PTR (*mmalloc_hook) PARAMS ((PTR, size_t)); + + /* Debugging hook for realloc. + + FIXME: For mapped regions shared by more than one process, this + needs to be maintained on a per-process basis. */ + + PTR (*mrealloc_hook) PARAMS ((PTR, PTR, size_t)); + + /* Number of info entries. */ + + size_t heapsize; + + /* Pointer to first block of the heap (base of the first block). */ + + char *heapbase; + + /* Current search index for the heap table. */ + /* Search index in the info table. */ + + size_t heapindex; + + /* Limit of valid info table indices. */ + + size_t heaplimit; + + /* Block information table. + Allocated with malign/__mmalloc_free (not mmalloc/mfree). */ + /* Table indexed by block number giving per-block information. */ + + malloc_info *heapinfo; + + /* Instrumentation. */ + + struct mstats heapstats; + + /* Free list headers for each fragment size. */ + /* Free lists for each fragment size. */ + + struct list fraghead[BLOCKLOG]; + + /* List of blocks allocated by memalign. */ + + struct alignlist *aligned_blocks; + + /* The base address of the memory region for this malloc heap. This + is the location where the bookkeeping data for mmap and for malloc + begins. */ + + char *base; + + /* The current location in the memory region for this malloc heap which + represents the end of memory in use. */ + + char *breakval; + + /* The end of the current memory region for this malloc heap. This is + the first location past the end of mapped memory. */ + + char *top; + + /* Open file descriptor for the file to which this malloc heap is mapped. + This will always be a valid file descriptor, since /dev/zero is used + by default if no open file is supplied by the client. Also note that + it may change each time the region is mapped and unmapped. */ + + int fd; + + /* An array of keys to data within the mapped region, for use by the + application. */ + + PTR keys[MMALLOC_KEYS]; + +}; + +/* Bits to look at in the malloc descriptor flags word */ + +#define MMALLOC_DEVZERO (1 << 0) /* Have mapped to /dev/zero */ +#define MMALLOC_INITIALIZED (1 << 1) /* Initialized mmalloc */ +#define MMALLOC_MMCHECK_USED (1 << 2) /* mmcheck() called already */ + +/* Allocate SIZE bytes of memory. */ + +extern PTR mmalloc PARAMS ((PTR, size_t)); + +/* Re-allocate the previously allocated block in PTR, making the new block + SIZE bytes long. */ + +extern PTR mrealloc PARAMS ((PTR, PTR, size_t)); + +/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ + +extern PTR mcalloc PARAMS ((PTR, size_t, size_t)); + +/* Free a block allocated by `mmalloc', `mrealloc' or `mcalloc'. */ + +extern void mfree PARAMS ((PTR, PTR)); + +/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ + +extern PTR mmemalign PARAMS ((PTR, size_t, size_t)); + +/* Allocate SIZE bytes on a page boundary. */ + +extern PTR mvalloc PARAMS ((PTR, size_t)); + +/* Activate a standard collection of debugging hooks. */ + +extern int mmcheck PARAMS ((PTR, void (*) (void))); + +/* Pick up the current statistics. (see FIXME elsewhere) */ + +extern struct mstats mmstats PARAMS ((PTR)); + +/* Internal version of `mfree' used in `morecore'. */ + +extern void __mmalloc_free PARAMS ((struct mdesc *, PTR)); + +/* Hooks for debugging versions. */ + +extern void (*__mfree_hook) PARAMS ((PTR, PTR)); +extern PTR (*__mmalloc_hook) PARAMS ((PTR, size_t)); +extern PTR (*__mrealloc_hook) PARAMS ((PTR, PTR, size_t)); + +/* A default malloc descriptor for the single sbrk() managed region. */ + +extern struct mdesc *__mmalloc_default_mdp; + +/* Initialize the first use of the default malloc descriptor, which uses + an sbrk() region. */ + +extern struct mdesc *__mmalloc_sbrk_init PARAMS ((void)); + +/* Grow or shrink a contiguous mapped region using mmap(). + Works much like sbrk() */ + +#if defined(HAVE_MMAP) + +extern PTR __mmalloc_mmap_morecore PARAMS ((struct mdesc *, int)); + +#endif + +/* Remap a mmalloc region that was previously mapped. */ + +extern PTR __mmalloc_remap_core PARAMS ((struct mdesc *)); + +/* Macro to convert from a user supplied malloc descriptor to pointer to the + internal malloc descriptor. If the user supplied descriptor is NULL, then + use the default internal version, initializing it if necessary. Otherwise + just cast the user supplied version (which is void *) to the proper type + (struct mdesc *). */ + +#define MD_TO_MDP(md) \ + ((md) == NULL \ + ? (__mmalloc_default_mdp == NULL \ + ? __mmalloc_sbrk_init () \ + : __mmalloc_default_mdp) \ + : (struct mdesc *) (md)) + +#endif /* __MMALLOC_H */ diff --git a/gnu/usr.bin/gdb/mmalloc/mmalloc.texi b/gnu/usr.bin/gdb/mmalloc/mmalloc.texi new file mode 100644 index 000000000000..f70ae68621ee --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/mmalloc.texi @@ -0,0 +1,258 @@ +\input texinfo @c -*- Texinfo -*- +@setfilename mmalloc.info + +@ifinfo +@format +START-INFO-DIR-ENTRY +* Mmalloc: (mmalloc). The GNU mapped-malloc package. +END-INFO-DIR-ENTRY +@end format + +This file documents the GNU mmalloc (mapped-malloc) package, written by +fnf@@cygnus.com, based on GNU malloc written by mike@@ai.mit.edu. + +Copyright (C) 1992 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +@ignore +Permission is granted to process this file through Tex and print the +results, provided the printed document carries copying permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). + +@end ignore +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions. +@end ifinfo +@iftex +@c @finalout +@setchapternewpage odd +@settitle MMALLOC, the GNU memory-mapped malloc package +@titlepage +@title mmalloc +@subtitle The GNU memory-mapped malloc package +@author Fred Fish +@author Cygnus Support +@author Mike Haertel +@author Free Software Foundation +@page + +@tex +\def\$#1${{#1}} % Kluge: collect RCS revision info without $...$ +\xdef\manvers{\$Revision: 1.1 $} % For use in headers, footers too +{\parskip=0pt +\hfill Cygnus Support\par +\hfill fnf\@cygnus.com\par +\hfill {\it MMALLOC, the GNU memory-mapped malloc package}, \manvers\par +\hfill \TeX{}info \texinfoversion\par +} +@end tex + +@vskip 0pt plus 1filll +Copyright @copyright{} 1992 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions. +@end titlepage +@end iftex + +@ifinfo +@node Top, Overview, (dir), (dir) +@top mmalloc +This file documents the GNU memory-mapped malloc package mmalloc. + +@menu +* Overview:: Overall Description +* Implementation:: Implementation + + --- The Detailed Node Listing --- + +Implementation + +* Compatibility:: Backwards Compatibility +* Functions:: Function Descriptions +@end menu + +@end ifinfo + +@node Overview, Implementation, Top, Top +@chapter Overall Description + +This is a heavily modified version of GNU @code{malloc}. It uses +@code{mmap} as the basic mechanism for for obtaining memory from the +system, rather than @code{sbrk}. This gives it several advantages over the +more traditional malloc: + +@itemize @bullet +@item +Several different heaps can be used, each of them growing +or shinking under control of @code{mmap}, with the @code{mmalloc} functions +using a specific heap on a call by call basis. + +@item +By using @code{mmap}, it is easy to create heaps which are intended to +be persistent and exist as a filesystem object after the creating +process has gone away. + +@item +Because multiple heaps can be managed, data used for a +specific purpose can be allocated into its own heap, making +it easier to allow applications to ``dump'' and ``restore'' initialized +malloc-managed memory regions. For example, the ``unexec'' hack popularized +by GNU Emacs could potentially go away. +@end itemize + +@node Implementation, , Overview, Top +@chapter Implementation + +The @code{mmalloc} functions contain no internal static state. All +@code{mmalloc} internal data is allocated in the mapped in region, along +with the user data that it manages. This allows it to manage multiple +such regions and to ``pick up where it left off'' when such regions are +later dynamically mapped back in. + +In some sense, malloc has been ``purified'' to contain no internal state +information and generalized to use multiple memory regions rather than a +single region managed by @code{sbrk}. However the new routines now need an +extra parameter which informs @code{mmalloc} which memory region it is dealing +with (along with other information). This parameter is called the +@dfn{malloc descriptor}. + +The functions initially provided by @code{mmalloc} are: + +@example +void *mmalloc_attach (int fd, void *baseaddr); +void *mmalloc_detach (void *md); +int mmalloc_errno (void *md); +int mmalloc_setkey (void *md, int keynum, void *key); +void *mmalloc_getkey (void *md, int keynum); + +void *mmalloc (void *md, size_t size); +void *mrealloc (void *md, void *ptr, size_t size); +void *mvalloc (void *md, size_t size); +void mfree (void *md, void *ptr); +@end example + +@menu +* Compatibility:: Backwards Compatibility +* Functions:: Function Descriptions +@end menu + +@node Compatibility, Functions, Implementation, Implementation +@section Backwards Compatibility + +To allow a single malloc package to be used in a given application, +provision is made for the traditional @code{malloc}, @code{realloc}, and +@code{free} functions to be implemented as special cases of the +@code{mmalloc} functions. In particular, if any of the functions that +expect malloc descriptors are called with a @code{NULL} pointer rather than a +valid malloc descriptor, then they default to using an @code{sbrk} managed +region. +The @code{mmalloc} package provides compatible @code{malloc}, @code{realloc}, +and @code{free} functions using this mechanism internally. +Applications can avoid this extra interface layer by simply including the +following defines: + +@example +#define malloc(size) mmalloc ((void *)0, (size)) +#define realloc(ptr,size) mrealloc ((void *)0, (ptr), (size)); +#define free(ptr) mfree ((void *)0, (ptr)) +@end example + +@noindent +or replace the existing @code{malloc}, @code{realloc}, and @code{free} +calls with the above patterns if using @code{#define} causes problems. + +@node Functions, , Compatibility, Implementation +@section Function Descriptions + +These are the details on the functions that make up the @code{mmalloc} +package. + +@table @code +@item void *mmalloc_attach (int @var{fd}, void *@var{baseaddr}); +Initialize access to a @code{mmalloc} managed region. + +If @var{fd} is a valid file descriptor for an open file, then data for the +@code{mmalloc} managed region is mapped to that file. Otherwise +@file{/dev/zero} is used and the data will not exist in any filesystem object. + +If the open file corresponding to @var{fd} is from a previous use of +@code{mmalloc} and passes some basic sanity checks to ensure that it is +compatible with the current @code{mmalloc} package, then its data is +mapped in and is immediately accessible at the same addresses in +the current process as the process that created the file. + +If @var{baseaddr} is not @code{NULL}, the mapping is established +starting at the specified address in the process address space. If +@var{baseaddr} is @code{NULL}, the @code{mmalloc} package chooses a +suitable address at which to start the mapped region, which will be the +value of the previous mapping if opening an existing file which was +previously built by @code{mmalloc}, or for new files will be a value +chosen by @code{mmap}. + +Specifying @var{baseaddr} provides more control over where the regions +start and how big they can be before bumping into existing mapped +regions or future mapped regions. + +On success, returns a malloc descriptor which is used in subsequent +calls to other @code{mmalloc} package functions. It is explicitly +@samp{void *} (@samp{char *} for systems that don't fully support +@code{void}) so that users of the package don't have to worry about the +actual implementation details. + +On failure returns @code{NULL}. + +@item void *mmalloc_detach (void *@var{md}); +Terminate access to a @code{mmalloc} managed region identified by the +descriptor @var{md}, by closing the base file and unmapping all memory +pages associated with the region. + +Returns @code{NULL} on success. + +Returns the malloc descriptor on failure, which can subsequently +be used for further action (such as obtaining more information about +the nature of the failure). + +@item void *mmalloc (void *@var{md}, size_t @var{size}); +Given an @code{mmalloc} descriptor @var{md}, allocate additional memory of +@var{size} bytes in the associated mapped region. + +@item *mrealloc (void *@var{md}, void *@var{ptr}, size_t @var{size}); +Given an @code{mmalloc} descriptor @var{md} and a pointer to memory +previously allocated by @code{mmalloc} in @var{ptr}, reallocate the +memory to be @var{size} bytes long, possibly moving the existing +contents of memory if necessary. + +@item void *mvalloc (void *@var{md}, size_t @var{size}); +Like @code{mmalloc} but the resulting memory is aligned on a page boundary. + +@item void mfree (void *@var{md}, void *@var{ptr}); +Given an @code{mmalloc} descriptor @var{md} and a pointer to memory previously +allocated by @code{mmalloc} in @var{ptr}, free the previously allocated memory. + +@item int mmalloc_errno (void *@var{md}); +Given a @code{mmalloc} descriptor, if the last @code{mmalloc} operation +failed for some reason due to a system call failure, then +returns the associated @code{errno}. Returns 0 otherwise. +(This function is not yet implemented). +@end table + +@bye diff --git a/gnu/usr.bin/gdb/mmalloc/mmap-sup.c b/gnu/usr.bin/gdb/mmalloc/mmap-sup.c new file mode 100644 index 000000000000..37b307905c5b --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/mmap-sup.c @@ -0,0 +1,144 @@ +/* Support for an sbrk-like function that uses mmap. + Copyright 1992 Free Software Foundation, Inc. + + Contributed by Fred Fish at Cygnus Support. fnf@cygnus.com + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#if defined(HAVE_MMAP) + +#include <stdio.h> +#include <fcntl.h> +#include <sys/mman.h> + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#include "mmalloc.h" + +extern int munmap PARAMS ((caddr_t, size_t)); /* Not in any header file */ + +/* Cache the pagesize for the current host machine. Note that if the host + does not readily provide a getpagesize() function, we need to emulate it + elsewhere, not clutter up this file with lots of kluges to try to figure + it out. */ + +static size_t pagesize; +extern int getpagesize PARAMS ((void)); + +#define PAGE_ALIGN(addr) (caddr_t) (((long)(addr) + pagesize - 1) & \ + ~(pagesize - 1)) + +/* Get core for the memory region specified by MDP, using SIZE as the + amount to either add to or subtract from the existing region. Works + like sbrk(), but using mmap(). */ + +PTR +__mmalloc_mmap_morecore (mdp, size) + struct mdesc *mdp; + int size; +{ + PTR result = NULL; + off_t foffset; /* File offset at which new mapping will start */ + size_t mapbytes; /* Number of bytes to map */ + caddr_t moveto; /* Address where we wish to move "break value" to */ + caddr_t mapto; /* Address we actually mapped to */ + char buf = 0; /* Single byte to write to extend mapped file */ + + if (pagesize == 0) + { + pagesize = getpagesize (); + } + if (size == 0) + { + /* Just return the current "break" value. */ + result = mdp -> breakval; + } + else if (size < 0) + { + /* We are deallocating memory. If the amount requested would cause + us to try to deallocate back past the base of the mmap'd region + then do nothing, and return NULL. Otherwise, deallocate the + memory and return the old break value. */ + if (mdp -> breakval + size >= mdp -> base) + { + result = (PTR) mdp -> breakval; + mdp -> breakval += size; + moveto = PAGE_ALIGN (mdp -> breakval); + munmap (moveto, (size_t) (mdp -> top - moveto)); + mdp -> top = moveto; + } + } + else + { + /* We are allocating memory. Make sure we have an open file + descriptor and then go on to get the memory. */ + if (mdp -> fd < 0) + { + result = NULL; + } + else if (mdp -> breakval + size > mdp -> top) + { + /* The request would move us past the end of the currently + mapped memory, so map in enough more memory to satisfy + the request. This means we also have to grow the mapped-to + file by an appropriate amount, since mmap cannot be used + to extend a file. */ + moveto = PAGE_ALIGN (mdp -> breakval + size); + mapbytes = moveto - mdp -> top; + foffset = mdp -> top - mdp -> base; + /* FIXME: Test results of lseek() and write() */ + lseek (mdp -> fd, foffset + mapbytes - 1, SEEK_SET); + write (mdp -> fd, &buf, 1); + mapto = mmap (mdp -> top, mapbytes, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_FIXED, mdp -> fd, foffset); + if (mapto == mdp -> top) + { + mdp -> top = moveto; + result = (PTR) mdp -> breakval; + mdp -> breakval += size; + } + } + else + { + result = (PTR) mdp -> breakval; + mdp -> breakval += size; + } + } + return (result); +} + +PTR +__mmalloc_remap_core (mdp) + struct mdesc *mdp; +{ + caddr_t base; + + /* FIXME: Quick hack, needs error checking and other attention. */ + + base = mmap (mdp -> base, mdp -> top - mdp -> base, + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, + mdp -> fd, 0); + return ((PTR) base); +} + +#else /* defined(HAVE_MMAP) */ +/* Prevent "empty translation unit" warnings from the idiots at X3J11. */ +static char ansi_c_idiots = 69; +#endif /* defined(HAVE_MMAP) */ diff --git a/gnu/usr.bin/gdb/mmalloc/mmcheck.c b/gnu/usr.bin/gdb/mmalloc/mmcheck.c new file mode 100644 index 000000000000..c3e29d3b3d75 --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/mmcheck.c @@ -0,0 +1,196 @@ +/* Standard debugging hooks for `mmalloc'. + Copyright 1990, 1991, 1992 Free Software Foundation + + Written May 1989 by Mike Haertel. + Heavily modified Mar 1992 by Fred Fish (fnf@cygnus.com) + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#include "mmalloc.h" + +/* Default function to call when something awful happens. The application + can specify an alternate function to be called instead (and probably will + want to). */ + +extern void abort PARAMS ((void)); + +/* Arbitrary magical numbers. */ + +#define MAGICWORD (unsigned int) 0xfedabeeb /* Active chunk */ +#define MAGICWORDFREE (unsigned int) 0xdeadbeef /* Inactive chunk */ +#define MAGICBYTE ((char) 0xd7) + +/* Each memory allocation is bounded by a header structure and a trailer + byte. I.E. + + <size><magicword><user's allocation><magicbyte> + + The pointer returned to the user points to the first byte in the + user's allocation area. The magic word can be tested to detect + buffer underruns and the magic byte can be tested to detect overruns. */ + +struct hdr + { + size_t size; /* Exact size requested by user. */ + unsigned long int magic; /* Magic number to check header integrity. */ + }; + +/* Check the magicword and magicbyte, and if either is corrupted then + call the emergency abort function specified for the heap in use. */ + +static void +checkhdr (mdp, hdr) + struct mdesc *mdp; + CONST struct hdr *hdr; +{ + if (hdr -> magic != MAGICWORD || + ((char *) &hdr[1])[hdr -> size] != MAGICBYTE) + { + (*mdp -> abortfunc)(); + } +} + +static void +mfree_check (md, ptr) + PTR md; + PTR ptr; +{ + struct hdr *hdr = ((struct hdr *) ptr) - 1; + struct mdesc *mdp; + + mdp = MD_TO_MDP (md); + checkhdr (mdp, hdr); + hdr -> magic = MAGICWORDFREE; + mdp -> mfree_hook = NULL; + mfree (md, (PTR)hdr); + mdp -> mfree_hook = mfree_check; +} + +static PTR +mmalloc_check (md, size) + PTR md; + size_t size; +{ + struct hdr *hdr; + struct mdesc *mdp; + size_t nbytes; + + mdp = MD_TO_MDP (md); + mdp -> mmalloc_hook = NULL; + nbytes = sizeof (struct hdr) + size + 1; + hdr = (struct hdr *) mmalloc (md, nbytes); + mdp -> mmalloc_hook = mmalloc_check; + if (hdr != NULL) + { + hdr -> size = size; + hdr -> magic = MAGICWORD; + hdr++; + *((char *) hdr + size) = MAGICBYTE; + } + return ((PTR) hdr); +} + +static PTR +mrealloc_check (md, ptr, size) + PTR md; + PTR ptr; + size_t size; +{ + struct hdr *hdr = ((struct hdr *) ptr) - 1; + struct mdesc *mdp; + size_t nbytes; + + mdp = MD_TO_MDP (md); + checkhdr (mdp, hdr); + mdp -> mfree_hook = NULL; + mdp -> mmalloc_hook = NULL; + mdp -> mrealloc_hook = NULL; + nbytes = sizeof (struct hdr) + size + 1; + hdr = (struct hdr *) mrealloc (md, (PTR) hdr, nbytes); + mdp -> mfree_hook = mfree_check; + mdp -> mmalloc_hook = mmalloc_check; + mdp -> mrealloc_hook = mrealloc_check; + if (hdr != NULL) + { + hdr -> size = size; + hdr++; + *((char *) hdr + size) = MAGICBYTE; + } + return ((PTR) hdr); +} + +/* Turn on default checking for mmalloc/mrealloc/mfree, for the heap specified + by MD. If FUNC is non-NULL, it is a pointer to the function to call + to abort whenever memory corruption is detected. By default, this is the + standard library function abort(). + + Note that we disallow installation of initial checking hooks if mmalloc + has been called at any time for this particular heap, since if any region + that is allocated prior to installation of the hooks is subsequently + reallocated or freed after installation of the hooks, it is guaranteed + to trigger a memory corruption error. We do this by checking the state + of the MMALLOC_INITIALIZED flag. + + However, we can call this function at any time after the initial call, + to update the function pointers to the checking routines and to the + user defined corruption handler routine, as long as these function pointers + have been previously extablished by the initial call. Note that we + do this automatically when remapping an previously used heap, to ensure + that the hooks get updated to the correct values, although the corruption + handler pointer gets set back to the default. The application can then + call mmcheck to use a different corruption handler if desired. + + Returns non-zero if checking is successfully enabled, zero otherwise. */ + +int +mmcheck (md, func) + PTR md; + void (*func) PARAMS ((void)); +{ + struct mdesc *mdp; + int rtnval; + + mdp = MD_TO_MDP (md); + + /* We can safely set or update the abort function at any time, regardless + of whether or not we successfully do anything else. */ + + mdp -> abortfunc = (func != NULL ? func : abort); + + /* If we haven't yet called mmalloc the first time for this heap, or if we + have hooks that were previously installed, then allow the hooks to be + initialized or updated. */ + + if (1 /* FIXME: Always allow installation for now. */ || + !(mdp -> flags & MMALLOC_INITIALIZED) || + (mdp -> mfree_hook != NULL)) + { + mdp -> mfree_hook = mfree_check; + mdp -> mmalloc_hook = mmalloc_check; + mdp -> mrealloc_hook = mrealloc_check; + mdp -> flags |= MMALLOC_MMCHECK_USED; + rtnval = 1; + } + else + { + rtnval = 0; + } + + return (rtnval); +} diff --git a/gnu/usr.bin/gdb/mmalloc/mmemalign.c b/gnu/usr.bin/gdb/mmalloc/mmemalign.c new file mode 100644 index 000000000000..63350a215cd3 --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/mmemalign.c @@ -0,0 +1,64 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include "mmalloc.h" + +PTR +mmemalign (md, alignment, size) + PTR md; + size_t alignment; + size_t size; +{ + PTR result; + unsigned long int adj; + struct alignlist *l; + struct mdesc *mdp; + + size = ((size + alignment - 1) / alignment) * alignment; + + if ((result = mmalloc (md, size)) != NULL) + { + adj = RESIDUAL (result, alignment); + if (adj != 0) + { + mdp = MD_TO_MDP (md); + for (l = mdp -> aligned_blocks; l != NULL; l = l -> next) + { + if (l -> aligned == NULL) + { + /* This slot is free. Use it. */ + break; + } + } + if (l == NULL) + { + l = (struct alignlist *) mmalloc (md, sizeof (struct alignlist)); + if (l == NULL) + { + mfree (md, result); + return (NULL); + } + } + l -> exact = result; + result = l -> aligned = (char *) result + alignment - adj; + l -> next = mdp -> aligned_blocks; + mdp -> aligned_blocks = l; + } + } + return (result); +} diff --git a/gnu/usr.bin/gdb/mmalloc/mmstats.c b/gnu/usr.bin/gdb/mmalloc/mmstats.c new file mode 100644 index 000000000000..d3846eb2dbe5 --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/mmstats.c @@ -0,0 +1,46 @@ +/* Access the statistics maintained by `mmalloc'. + Copyright 1990, 1991, 1992 Free Software Foundation + + Written May 1989 by Mike Haertel. + Modified Mar 1992 by Fred Fish. (fnf@cygnus.com) + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#include "mmalloc.h" + +/* FIXME: See the comment in mmalloc.h where struct mstats is defined. + None of the internal mmalloc structures should be externally visible + outside the library. */ + +struct mstats +mmstats (md) + PTR md; +{ + struct mstats result; + struct mdesc *mdp; + + mdp = MD_TO_MDP (md); + result.bytes_total = + (char *) mdp -> morecore (mdp, 0) - mdp -> heapbase; + result.chunks_used = mdp -> heapstats.chunks_used; + result.bytes_used = mdp -> heapstats.bytes_used; + result.chunks_free = mdp -> heapstats.chunks_free; + result.bytes_free = mdp -> heapstats.bytes_free; + return (result); +} diff --git a/gnu/usr.bin/gdb/mmalloc/mmtrace.c b/gnu/usr.bin/gdb/mmalloc/mmtrace.c new file mode 100644 index 000000000000..73368a1b57aa --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/mmtrace.c @@ -0,0 +1,166 @@ +/* More debugging hooks for `mmalloc'. + Copyright 1991, 1992 Free Software Foundation + + Written April 2, 1991 by John Gilmore of Cygnus Support + Based on mcheck.c by Mike Haertel. + Modified Mar 1992 by Fred Fish. (fnf@cygnus.com) + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <stdio.h> +#include "mmalloc.h" + +#ifndef __GNU_LIBRARY__ +extern char *getenv (); +#endif + +static FILE *mallstream; + +#if 0 /* FIXME: Disabled for now. */ +static char mallenv[] = "MALLOC_TRACE"; +static char mallbuf[BUFSIZ]; /* Buffer for the output. */ +#endif + +/* Address to breakpoint on accesses to... */ +static PTR mallwatch; + +/* Old hook values. */ + +static void (*old_mfree_hook) PARAMS ((PTR, PTR)); +static PTR (*old_mmalloc_hook) PARAMS ((PTR, size_t)); +static PTR (*old_mrealloc_hook) PARAMS ((PTR, PTR, size_t)); + +/* This function is called when the block being alloc'd, realloc'd, or + freed has an address matching the variable "mallwatch". In a debugger, + set "mallwatch" to the address of interest, then put a breakpoint on + tr_break. */ + +static void +tr_break () +{ +} + +static void +tr_freehook (md, ptr) + PTR md; + PTR ptr; +{ + struct mdesc *mdp; + + mdp = MD_TO_MDP (md); + /* Be sure to print it first. */ + fprintf (mallstream, "- %08x\n", (unsigned int) ptr); + if (ptr == mallwatch) + tr_break (); + mdp -> mfree_hook = old_mfree_hook; + mfree (md, ptr); + mdp -> mfree_hook = tr_freehook; +} + +static PTR +tr_mallochook (md, size) + PTR md; + size_t size; +{ + PTR hdr; + struct mdesc *mdp; + + mdp = MD_TO_MDP (md); + mdp -> mmalloc_hook = old_mmalloc_hook; + hdr = (PTR) mmalloc (md, size); + mdp -> mmalloc_hook = tr_mallochook; + + /* We could be printing a NULL here; that's OK. */ + fprintf (mallstream, "+ %08x %x\n", (unsigned int) hdr, size); + + if (hdr == mallwatch) + tr_break (); + + return (hdr); +} + +static PTR +tr_reallochook (md, ptr, size) + PTR md; + PTR ptr; + size_t size; +{ + PTR hdr; + struct mdesc *mdp; + + mdp = MD_TO_MDP (md); + + if (ptr == mallwatch) + tr_break (); + + mdp -> mfree_hook = old_mfree_hook; + mdp -> mmalloc_hook = old_mmalloc_hook; + mdp -> mrealloc_hook = old_mrealloc_hook; + hdr = (PTR) mrealloc (md, ptr, size); + mdp -> mfree_hook = tr_freehook; + mdp -> mmalloc_hook = tr_mallochook; + mdp -> mrealloc_hook = tr_reallochook; + if (hdr == NULL) + /* Failed realloc. */ + fprintf (mallstream, "! %08x %x\n", (unsigned int) ptr, size); + else + fprintf (mallstream, "< %08x\n> %08x %x\n", (unsigned int) ptr, + (unsigned int) hdr, size); + + if (hdr == mallwatch) + tr_break (); + + return hdr; +} + +/* We enable tracing if either the environment variable MALLOC_TRACE + is set, or if the variable mallwatch has been patched to an address + that the debugging user wants us to stop on. When patching mallwatch, + don't forget to set a breakpoint on tr_break! */ + +int +mmtrace () +{ +#if 0 /* FIXME! This is disabled for now until we figure out how to + maintain a stack of hooks per heap, since we might have other + hooks (such as set by mmcheck) active also. */ + char *mallfile; + + mallfile = getenv (mallenv); + if (mallfile != NULL || mallwatch != NULL) + { + mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "w"); + if (mallstream != NULL) + { + /* Be sure it doesn't mmalloc its buffer! */ + setbuf (mallstream, mallbuf); + fprintf (mallstream, "= Start\n"); + old_mfree_hook = mdp -> mfree_hook; + mdp -> mfree_hook = tr_freehook; + old_mmalloc_hook = mdp -> mmalloc_hook; + mdp -> mmalloc_hook = tr_mallochook; + old_mrealloc_hook = mdp -> mrealloc_hook; + mdp -> mrealloc_hook = tr_reallochook; + } + } + +#endif /* 0 */ + + return (1); +} + diff --git a/gnu/usr.bin/gdb/mmalloc/mrealloc.c b/gnu/usr.bin/gdb/mmalloc/mrealloc.c new file mode 100644 index 000000000000..85bec565dadb --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/mrealloc.c @@ -0,0 +1,160 @@ +/* Change the size of a block allocated by `mmalloc'. + Copyright 1990, 1991 Free Software Foundation + Written May 1989 by Mike Haertel. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#include <string.h> /* Prototypes for memcpy, memmove, memset, etc */ + +#include "mmalloc.h" + +/* Resize the given region to the new size, returning a pointer + to the (possibly moved) region. This is optimized for speed; + some benchmarks seem to indicate that greater compactness is + achieved by unconditionally allocating and copying to a + new region. This module has incestuous knowledge of the + internals of both mfree and mmalloc. */ + +PTR +mrealloc (md, ptr, size) + PTR md; + PTR ptr; + size_t size; +{ + struct mdesc *mdp; + PTR result; + int type; + size_t block, blocks, oldlimit; + + if (size == 0) + { + mfree (md, ptr); + return (mmalloc (md, 0)); + } + else if (ptr == NULL) + { + return (mmalloc (md, size)); + } + + mdp = MD_TO_MDP (md); + + if (mdp -> mrealloc_hook != NULL) + { + return ((*mdp -> mrealloc_hook) (md, ptr, size)); + } + + block = BLOCK (ptr); + + type = mdp -> heapinfo[block].busy.type; + switch (type) + { + case 0: + /* Maybe reallocate a large block to a small fragment. */ + if (size <= BLOCKSIZE / 2) + { + result = mmalloc (md, size); + if (result != NULL) + { + memcpy (result, ptr, size); + mfree (md, ptr); + return (result); + } + } + + /* The new size is a large allocation as well; + see if we can hold it in place. */ + blocks = BLOCKIFY (size); + if (blocks < mdp -> heapinfo[block].busy.info.size) + { + /* The new size is smaller; return excess memory to the free list. */ + mdp -> heapinfo[block + blocks].busy.type = 0; + mdp -> heapinfo[block + blocks].busy.info.size + = mdp -> heapinfo[block].busy.info.size - blocks; + mdp -> heapinfo[block].busy.info.size = blocks; + mfree (md, ADDRESS (block + blocks)); + result = ptr; + } + else if (blocks == mdp -> heapinfo[block].busy.info.size) + { + /* No size change necessary. */ + result = ptr; + } + else + { + /* Won't fit, so allocate a new region that will. + Free the old region first in case there is sufficient + adjacent free space to grow without moving. */ + blocks = mdp -> heapinfo[block].busy.info.size; + /* Prevent free from actually returning memory to the system. */ + oldlimit = mdp -> heaplimit; + mdp -> heaplimit = 0; + mfree (md, ptr); + mdp -> heaplimit = oldlimit; + result = mmalloc (md, size); + if (result == NULL) + { + mmalloc (md, blocks * BLOCKSIZE); + return (NULL); + } + if (ptr != result) + { + memmove (result, ptr, blocks * BLOCKSIZE); + } + } + break; + + default: + /* Old size is a fragment; type is logarithm + to base two of the fragment size. */ + if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type)) + { + /* The new size is the same kind of fragment. */ + result = ptr; + } + else + { + /* The new size is different; allocate a new space, + and copy the lesser of the new size and the old. */ + result = mmalloc (md, size); + if (result == NULL) + { + return (NULL); + } + memcpy (result, ptr, MIN (size, (size_t) 1 << type)); + mfree (md, ptr); + } + break; + } + + return (result); +} + +/* When using this package, provide a version of malloc/realloc/free built + on top of it, so that if we use the default sbrk() region we will not + collide with another malloc package trying to do the same thing, if + the application contains any "hidden" calls to malloc/realloc/free (such + as inside a system library). */ + +PTR +realloc (ptr, size) + PTR ptr; + size_t size; +{ + return (mrealloc ((PTR) NULL, ptr, size)); +} diff --git a/gnu/usr.bin/gdb/mmalloc/mvalloc.c b/gnu/usr.bin/gdb/mmalloc/mvalloc.c new file mode 100644 index 000000000000..1ffba7865cf7 --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/mvalloc.c @@ -0,0 +1,40 @@ +/* Allocate memory on a page boundary. + Copyright (C) 1991 Free Software Foundation, Inc. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include "mmalloc.h" + +/* Cache the pagesize for the current host machine. Note that if the host + does not readily provide a getpagesize() function, we need to emulate it + elsewhere, not clutter up this file with lots of kluges to try to figure + it out. */ + +static size_t pagesize; +extern int getpagesize PARAMS ((void)); + +PTR +mvalloc (md, size) + PTR md; + size_t size; +{ + if (pagesize == 0) + { + pagesize = getpagesize (); + } + + return (mmemalign (md, pagesize, size)); +} diff --git a/gnu/usr.bin/gdb/mmalloc/sbrk-sup.c b/gnu/usr.bin/gdb/mmalloc/sbrk-sup.c new file mode 100644 index 000000000000..e6a57d6ccad2 --- /dev/null +++ b/gnu/usr.bin/gdb/mmalloc/sbrk-sup.c @@ -0,0 +1,96 @@ +/* Support for sbrk() regions. + Copyright 1992 Free Software Foundation, Inc. + Contributed by Fred Fish at Cygnus Support. fnf@cygnus.com + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <string.h> /* Prototypes for memcpy, memmove, memset, etc */ + +#include "mmalloc.h" + +extern PTR sbrk (); + +/* The mmalloc() package can use a single implicit malloc descriptor + for mmalloc/mrealloc/mfree operations which do not supply an explicit + descriptor. For these operations, sbrk() is used to obtain more core + from the system, or return core. This allows mmalloc() to provide + backwards compatibility with the non-mmap'd version. */ + +struct mdesc *__mmalloc_default_mdp; + +/* Use sbrk() to get more core. */ + +static PTR +sbrk_morecore (mdp, size) + struct mdesc *mdp; + int size; +{ + PTR result; + + if ((result = sbrk (size)) == (PTR) -1) + { + result = NULL; + } + else + { + mdp -> breakval += size; + mdp -> top += size; + } + return (result); +} + +/* Initialize the default malloc descriptor if this is the first time + a request has been made to use the default sbrk'd region. + + Since no alignment guarantees are made about the initial value returned + by sbrk, test the initial value and (if necessary) sbrk enough additional + memory to start off with alignment to BLOCKSIZE. We actually only need + it aligned to an alignment suitable for any object, so this is overkill. + But at most it wastes just part of one BLOCKSIZE chunk of memory and + minimizes portability problems by avoiding us having to figure out + what the actual minimal alignment is. The rest of the malloc code + avoids this as well, by always aligning to the minimum of the requested + size rounded up to a power of two, or to BLOCKSIZE. + + Note that we are going to use some memory starting at this initial sbrk + address for the sbrk region malloc descriptor, which is a struct, so the + base address must be suitably aligned. */ + +struct mdesc * +__mmalloc_sbrk_init () +{ + PTR base; + unsigned int adj; + + base = sbrk (0); + adj = RESIDUAL (base, BLOCKSIZE); + if (adj != 0) + { + sbrk (BLOCKSIZE - adj); + base = sbrk (0); + } + __mmalloc_default_mdp = (struct mdesc *) sbrk (sizeof (struct mdesc)); + memset ((char *) __mmalloc_default_mdp, 0, sizeof (struct mdesc)); + __mmalloc_default_mdp -> morecore = sbrk_morecore; + __mmalloc_default_mdp -> base = base; + __mmalloc_default_mdp -> breakval = __mmalloc_default_mdp -> top = sbrk (0); + __mmalloc_default_mdp -> fd = -1; + return (__mmalloc_default_mdp); +} + + |
