home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-07-25 | 44.0 KB | 2,026 lines |
- Newsgroups: comp.sources.misc
- From: Brandon S. Allbery KF8NH <allbery@NCoast.ORG>
- Subject: v21i041: malloc-debug - Debugging malloc package, Part01/01
- Message-ID: <1991Jul25.024036.28795@sparky.IMD.Sterling.COM>
- X-Md4-Signature: 653244e446b6a32e5d8b5f3545ca4ba5
- Date: Thu, 25 Jul 1991 02:40:36 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: Brandon S. Allbery KF8NH <allbery@NCoast.ORG>
- Posting-number: Volume 21, Issue 41
- Archive-name: malloc-debug/part01
- Environment: UNIX
-
- [ This supersedes X-Archive: comp.sources.misc/8707/59 -Kent+ ]
-
- Some years ago, I posted a debugging malloc package to the net. This is the
- latest version of that package.
-
- Features:
-
- * Catches writes to either side of malloc'ed memory.
- * Checks the malloc pool for consistency on each call to malloc, free, realloc,
- or calloc; prints a diagnostic dump if the pool is corrupted.
- * User checks can be made by calling _mallchk("string ID").
- * If MALLOC_TRACEBACK is defined, a stack trace will be printed when the pool
- check fails. Since the stack is often irrecoverably corrupted by the time
- a core file is generated, this traceback can sometimes be the only way to
- find out where the error was detected. Only tested on 386 SVR3.[12].
- * Traps SIGBUS and SIGSEGV and dumps the malloc pool; these often indicate
- "wild" pointers.
- * Environment $MALLOC_OPTS controls tracing:
- 'v' trace entry/exit of functions
- 't' stack traceback (if MALLOC_TRACEBACK) of functions
- 'V' trace entry/exit of utility functions
- 'T' stack traceback of utility functions
- 'm' fault program if malloc(0) or realloc(*, 0) called
- 'b' print details on allocated blocks
- 'f' fault program on free(0)
- 'u' attempt to release free()'d memory to system with sbrk()
- 'r' fault program if realloc(0, ...)
- 'S' dump malloc pool on SIGSEGV
- 'B' dump malloc pool on SIGBUS
- * Provides alternate versions of several utility functions if MALLOC_LIB is
- defined; these functions will trap many "wild pointer" or off-by-one errors
- before they trash memory, and will provide an immediate indication of the
- location of such bugs.
-
- ++Brandon
- -------------------------------------------------------------------------------
- # This is a shell archive. Save this into a file, edit it
- # and delete all lines above this comment. Then give this
- # file to sh by executing the command "sh file". The files
- # will be extracted into the current directory owned by
- # you with default permissions.
- #
- # The files contained herein are:
- # malloc.c malloc.h malltest.c
- #
- echo 'x - malloc.c'
- sed 's/^X//' <<'________This_Is_The_END________' >>malloc.c
- X/*
- X * malloc for debugging -- allocates via sbrk and tracks stuff, does diag dump
- X * if things appear to be screwed up
- X */
- X
- X#include <signal.h>
- X#include <fcntl.h>
- X#include "malloc.h"
- X
- X#ifndef MALLOC_DEFAULT
- X#define MALLOC_DEFAULT 0
- X#endif
- X
- X#ifndef MALLOC_LIMIT
- X#define MALLOC_LIMIT (char *) 0x80000000
- X#endif
- X
- X#ifndef sigbase_t
- X#define sigbase_t void
- X#endif
- X
- Xtypedef sigbase_t (*sighand_t)();
- X
- X#define PTRC(x) ((long) (char *) (x))
- X
- X#ifdef __STDC__
- Xextern char *sbrk(int);
- Xextern char *getenv(const char *);
- Xextern long strtol(const char *, char **, int);
- Xextern int kill(int, int);
- Xextern int getpid(void);
- Xextern int open(const char *, int, int);
- Xextern int write(int, const char *, int);
- X#else
- Xextern char *sbrk();
- Xextern char *getenv();
- Xextern long strtol();
- Xextern int kill();
- Xextern int getpid();
- Xextern int open();
- Xextern int write();
- X#endif
- Xextern char etext[];
- Xextern char edata[];
- Xextern char end[];
- X
- X#define SBRK_FAIL ((char *) -1)
- X#define MAGIC_COOKIE 0xa5271009
- X#define FENCE_COOKIE 0xe4057492
- X#define ARR_BYTES 8
- X#define FENCE (sizeof (long))
- X#define DPTR(blk) ((char *) (blk)->m_blk)
- Xstatic long __f__;
- X#define BLKFENCE(blk) \
- X (memcpy((char *) &__f__, DPTR(blk) + (blk)->m_rsize, FENCE), __f__)
- X#define SET_BLKFENCE(b) \
- X (__f__=FENCE_COOKIE,memcpy(DPTR(blk)+(blk)->m_rsize,(char *)&__f__,FENCE))
- X#define BLKSIZE(blk) \
- X (PTRC(DPTR((struct _Dmi *) 0)) + ARR_BYTES + (blk)->m_size)
- X#define BLKEND(blk) (DPTR(blk) + (blk)->m_size + ARR_BYTES)
- X#define NEWBLK(n) (PTRC(DPTR((struct _Dmi *) 0)) + ARR_BYTES + (n))
- X#define m_round(n) (((n) + ARR_BYTES - 1) & ~(ARR_BYTES - 1))
- X
- Xstruct _Dmi
- X{
- X long m_cookie;
- X struct _Dmi *m_next;
- X struct _Dmi *m_prev;
- X long m_size;
- X long m_rsize;
- X char m_blk[ARR_BYTES + FENCE];
- X};
- X
- X#define HEADSIZE ((sizeof(struct _Dmi)) - ARR_BYTES)
- X
- Xstatic struct _Dmi *_fab = 0;
- Xstatic struct _Dmi *_ffb = 0;
- Xstatic char *_xbrk = 0;
- Xstatic long _in_malloc = 0;
- Xstatic long _no_memcpy = 0;
- Xstatic long _st_malloc = 0;
- Xlong _mall_opt = 0;
- Xstatic sighand_t old_bus = SIG_DFL;
- Xstatic sighand_t old_segv = SIG_DFL;
- Xstatic int _mall_fd = -1;
- X#ifdef MALLOC_TRACEBACK
- Xstatic int *_mall_frame;
- X#endif
- X
- Xstatic void _mallchk();
- Xstatic void _mallerr();
- X
- X/*
- X * internal: dump a string
- X */
- X
- Xstatic void
- X_mall_open()
- X{
- X char buf[15];
- X int c, old;
- X char *cp;
- X
- X if (_st_malloc != getpid())
- X {
- X close(_mall_fd);
- X _mall_fd = -1;
- X }
- X if (_mall_fd == -1)
- X {
- X if (_st_malloc || !(cp = getenv("MALLOC_LOG")))
- X {
- X buf[0] = 'm', buf[1] = 'a', buf[2] = buf[3] = 'l', buf[4] = 'o';
- X buf[5] = 'c', buf[6] = '.', buf[12] = '\0';
- X _st_malloc = getpid();
- X c = 11;
- X while (_st_malloc && c > 6)
- X {
- X buf[c--] = _st_malloc % 10 + '0';
- X _st_malloc /= 10;
- X }
- X cp = buf;
- X }
- X if ((_mall_fd = open(cp,O_WRONLY|O_CREAT|O_TRUNC|O_APPEND,0666)) == -1)
- X _mall_fd = 2;
- X else if (_mall_fd < 3)
- X {
- X old = _mall_fd;
- X _mall_fd = fcntl(_mall_fd, F_DUPFD, 3);
- X close(old);
- X }
- X }
- X}
- X
- Xstatic void
- X#ifdef __STDC__
- X_malldstr(const char *s)
- X#else
- X_malldstr(s)
- X char *s;
- X#endif
- X{
- X register long len;
- X
- X _mall_open();
- X for (len = 0; s[len]; len++)
- X ;
- X write(_mall_fd, s, len);
- X}
- X
- X/*
- X * internal: write a pointer in hex without using stdio
- X */
- X
- Xstatic void
- X#ifdef __STDC__
- X_malldptr(register unsigned long x)
- X#else
- X_malldptr(x)
- X register unsigned long x;
- X#endif
- X{
- X char buf[20];
- X static const char hex[] = "0123456789abcdef";
- X register unsigned long dx;
- X register char *p;
- X
- X _mall_open();
- X if (!x)
- X {
- X write(_mall_fd, "0x0(0)", 6);
- X return;
- X }
- X write(_mall_fd, "0x", 2);
- X p = buf;
- X dx = x;
- X while (x != 0)
- X *p++ = hex[x % 16], x = x / 16;
- X while (p != buf)
- X write(_mall_fd, --p, 1);
- X write(_mall_fd, "(", 1);
- X p = buf;
- X x = dx;
- X while (x != 0)
- X *p++ = hex[x % 10], x /= 10;
- X while (p != buf)
- X write(_mall_fd, --p, 1);
- X write(_mall_fd, ")", 1);
- X}
- X
- X#ifdef MALLOC_TRACEBACK
- X
- X/*
- X * This is EXTREMELY NON-PORTABLE but very useful. I suggest you be familiar
- X * with debugger internals before hacking on this code.
- X */
- X
- Xstatic void
- X#ifdef __STDC__
- X_mall_chase(const int *stkptr)
- X#else
- X_mall_chase(stkptr)
- X int *stkptr;
- X#endif
- X{
- X _malldstr("traceback -\n");
- X /*
- X * We are given the address of an argument. Treating it as a pointer to
- X * an (int), we can then take ptr[-1] to get the caller's address. To go
- X * farther back, we must follow the stack frames. Basically, a stack
- X * frame looks like this, with descending addresses further in the list:
- X *
- X * return address
- X * saved frame pointer (ebp of caller)
- X * local vars
- X * saved registers for local register vars
- X *
- X * (N.B. This is for the i386/i486. Your mileage WILL differ.)
- X */
- X if (stkptr < (int *) &stkptr || (char *) stkptr > MALLOC_LIMIT)
- X {
- X _mallerr("_mall_chase", "stack corrupted - frame got ",
- X (long) stkptr);
- X }
- X while (*stkptr)
- X {
- X _malldstr("pc = ");
- X _malldptr(*stkptr);
- X _malldstr("\n");
- X if ((stkptr = (int *) stkptr[-1] + 1) < (int *) &stkptr ||
- X (char *) stkptr > MALLOC_LIMIT)
- X {
- X _mallerr("_mall_chase", "stack corrupted - frame got ",
- X (long) stkptr);
- X }
- X }
- X _malldstr("end traceback\n");
- X}
- X
- X#endif
- X
- X/*
- X * dump arena; can be called externally, and is non-destructive
- X */
- X
- Xvoid
- X_malldmp()
- X{
- X register struct _Dmi *blk;
- X long oldf, oldm;
- X
- X if ((oldf = _in_malloc))
- X {
- X _malldstr("malloc diagnostic dump\n");
- X#ifdef MALLOC_TRACEBACK
- X _mall_chase(_mall_frame - 1);
- X#endif
- X }
- X _in_malloc = 0;
- X oldm = _no_memcpy;
- X _no_memcpy = 1;
- X _malldstr("brk = ");
- X _malldptr(PTRC(sbrk(0)));
- X _malldstr(" xbrk = ");
- X _malldptr(PTRC(_xbrk));
- X _malldstr("\n_fab = ");
- X _malldptr(PTRC(_fab));
- X _malldstr(" _ffb = ");
- X _malldptr(PTRC(_ffb));
- X _malldstr(" blksiz = ");
- X _malldptr(HEADSIZE);
- X _malldstr("\netext = ");
- X _malldptr(PTRC(etext));
- X _malldstr(" edata = ");
- X _malldptr(PTRC(edata));
- X _malldstr(" end = ");
- X _malldptr(PTRC(end));
- X _malldstr("\n");
- X if (!_fab)
- X _malldstr("no allocated blocks\n");
- X else
- X {
- X _malldstr("\nallocated blocks\n");
- X for (blk = _fab;
- X blk && PTRC(blk) >= PTRC(_xbrk) && PTRC(blk) < PTRC(sbrk(0));
- X blk = blk->m_next)
- X {
- X _malldstr("(");
- X _malldptr(PTRC(blk));
- X _malldstr(") ");
- X _malldptr(PTRC(blk->m_prev));
- X _malldstr(" <");
- X _malldptr(blk->m_rsize);
- X _malldstr("/");
- X _malldptr(blk->m_size);
- X _malldstr("> ");
- X _malldptr(PTRC(blk->m_next));
- X if (MAGIC_COOKIE != blk->m_cookie)
- X {
- X _malldstr(" cookie==");
- X _malldptr(blk->m_cookie);
- X }
- X if (FENCE_COOKIE != BLKFENCE(blk))
- X {
- X _malldstr(" fence==");
- X _malldptr(BLKFENCE(blk));
- X }
- X _malldstr("\n");
- X }
- X if (blk)
- X _malldstr("(subsequent block pointers corrupted)\n");
- X }
- X if (!_ffb)
- X _malldstr("\nno free blocks\n");
- X else
- X {
- X _malldstr("\nfree blocks\n");
- X for (blk = _ffb;
- X blk && PTRC(blk) >= PTRC(_xbrk) && PTRC(blk) < PTRC(sbrk(0));
- X blk = blk->m_next)
- X {
- X _malldstr("(");
- X _malldptr(PTRC(blk));
- X _malldstr(") ");
- X _malldptr(PTRC(blk->m_prev));
- X _malldstr("< ");
- X _malldptr(blk->m_size);
- X _malldstr(" >");
- X _malldptr(PTRC(blk->m_next));
- X if (MAGIC_COOKIE != blk->m_cookie)
- X {
- X _malldstr("cookie==");
- X _malldptr(blk->m_cookie);
- X }
- X _malldstr("\n");
- X }
- X if (blk)
- X _malldstr("(subsequent block pointers corrupted)\n");
- X }
- X _no_memcpy = oldm;
- X _in_malloc = oldf;
- X}
- X
- X/*
- X * internal error routine: print error message (without using stdio) and
- X * drop core
- X */
- X
- Xstatic void
- X#ifdef __STDC__
- X_mallerr(const char *fn, const char *s, long ptr)
- X#else
- X_mallerr(fn, s, ptr)
- X char *fn, *s;
- X long ptr;
- X#endif
- X{
- X _malldstr(fn);
- X _malldstr(": ");
- X _malldstr(s);
- X _malldptr(ptr);
- X _malldstr("\n");
- X _malldmp();
- X signal(SIGQUIT, SIG_DFL);
- X kill(getpid(), SIGQUIT);
- X}
- X
- X/*
- X * initialize stuff, we want to _malldmp() on a bus/seg error
- X */
- X
- Xstatic void
- X#ifdef __STDC__
- X_mall_sig(int sig)
- X#else
- X_mall_sig(sig)
- X int sig;
- X#endif
- X{
- X if (sig == SIGSEGV)
- X {
- X _malldstr("\nsegmentation violation\n\n");
- X signal(SIGSEGV, old_segv);
- X }
- X else if (sig == SIGBUS)
- X {
- X _malldstr("\nbus error\n\n");
- X signal(SIGBUS, old_bus);
- X }
- X else if (sig == SIGSYS)
- X _malldstr("\ninvalid argument\n\n");
- X else {
- X _malldstr("\nsignal ");
- X _malldptr(sig);
- X _malldstr("\n\n");
- X }
- X#ifdef MALLOC_TRACEBACK
- X _mall_chase((int *) &sig - 1);
- X#endif
- X _in_malloc = 1; /* silence _mallchk's default header */
- X _mallchk("signal trap");
- X kill(getpid(), sig);
- X}
- X
- Xstatic void
- X_mall_init()
- X{
- X const char *cp;
- X sighand_t tmp;
- X
- X if (_mall_opt & _MALL_SEGV)
- X {
- X tmp = old_segv;
- X if ((old_segv = signal(SIGSEGV, _mall_sig)) == _mall_sig)
- X old_segv = tmp;
- X }
- X if (_mall_opt & _MALL_BUS)
- X {
- X tmp = old_bus;
- X if ((old_bus = signal(SIGBUS, _mall_sig)) == _mall_sig)
- X old_bus = tmp;
- X }
- X if (_st_malloc)
- X return;
- X _mall_opt = MALLOC_DEFAULT;
- X if ((cp = getenv("MALLOC_OPTS")))
- X {
- X while (*cp)
- X {
- X switch (*cp)
- X {
- X case 'v':
- X _mall_opt ^= _MALL_VFUNC;
- X break;
- X#ifdef MALLOC_TRACEBACK
- X case 't':
- X _mall_opt ^= _MALL_TFUNC;
- X break;
- X#endif
- X#ifdef MALLOC_LIB
- X case 'V':
- X _mall_opt ^= _MALL_VUTIL;
- X break;
- X#ifdef MALLOC_TRACEBACK
- X case 'T':
- X _mall_opt ^= _MALL_TUTIL;
- X break;
- X#endif
- X#endif
- X case 'm':
- X _mall_opt ^= _MALL_MALLOC_0;
- X break;
- X case 'b':
- X _mall_opt ^= _MALL_VBLK;
- X break;
- X case 'f':
- X _mall_opt ^= _MALL_FREE_0;
- X break;
- X case 'u':
- X _mall_opt ^= _MALL_UNBREAK;
- X break;
- X case 'r':
- X _mall_opt ^= _MALL_REALLOC_0;
- X break;
- X case 'S':
- X if ((_mall_opt ^= _MALL_SEGV) & _MALL_SEGV)
- X {
- X tmp = old_segv;
- X if ((old_segv = signal(SIGSEGV, _mall_sig))
- X == _mall_sig)
- X old_segv = tmp;
- X }
- X else
- X {
- X if ((tmp = signal(SIGSEGV, old_segv)) != _mall_sig)
- X signal(SIGSEGV, tmp);
- X }
- X break;
- X case 'B':
- X if ((_mall_opt ^= _MALL_BUS) & _MALL_BUS)
- X {
- X tmp = old_bus;
- X if ((old_bus = signal(SIGBUS, _mall_sig)) == _mall_sig)
- X old_bus = tmp;
- X }
- X else
- X {
- X if ((tmp = signal(SIGBUS, old_bus)) != _mall_sig)
- X signal(SIGBUS, tmp);
- X }
- X break;
- X default:
- X break;
- X }
- X cp++;
- X }
- X }
- X _st_malloc = getpid();
- X}
- X
- X/*
- X * figure out which allocation block this pointer came from
- X * return NULL if none
- X */
- X
- Xstatic struct _Dmi *
- X#ifdef __STDC__
- X_mallgb(const char *s)
- X#else
- X_mallgb(s)
- X char *s;
- X#endif
- X{
- X register struct _Dmi *blk;
- X
- X for (blk = _fab; blk; blk = blk->m_next)
- X {
- X if (blk->m_blk == s)
- X break;
- X }
- X return blk;
- X}
- X
- X/*
- X * _mallchk() is global, so external routines can do discreet checks on the
- X * arena. If the arena is detectably corrupted, it will abort().
- X */
- X
- Xvoid
- X#ifdef __STDC__
- X_mallchk(const char *fn)
- X#else
- X_mallchk(fn)
- X char *fn;
- X#endif
- X{
- X register struct _Dmi *blk, *cblk;
- X register char *send;
- X register long cnt;
- X long oldm;
- X#ifdef MALLOC_TRACEBACK
- X int *stkptr;
- X#endif
- X
- X if (!_in_malloc && (_mall_opt & _MALL_VFUNC))
- X {
- X _malldstr("called _mallchk(");
- X _malldptr((long) fn);
- X _malldstr(")\n");
- X#ifdef MALLOC_TRACEBACK
- X if (_mall_opt & _MALL_TFUNC)
- X _mall_chase((int *) &fn - 1);
- X#endif
- X }
- X oldm = _no_memcpy;
- X _no_memcpy = 1;
- X#ifdef MALLOC_TRACEBACK
- X if ((stkptr = (int *) &fn - 1) < (int *) &stkptr ||
- X (char *) stkptr > MALLOC_LIMIT)
- X {
- X _mallerr("mallchk", "stack corrupted - frame got ", (long) stkptr);
- X }
- X while (*stkptr)
- X {
- X if ((stkptr = (int *) stkptr[-1] + 1) < (int *) &stkptr ||
- X (char *) stkptr > MALLOC_LIMIT)
- X {
- X _mallerr("mallchk", "stack corrupted - frame got ", (long) stkptr);
- X }
- X }
- X#endif
- X send = sbrk(0);
- X cblk = 0;
- X for (blk = _fab; blk; cblk = blk, blk = blk->m_next)
- X {
- X if (PTRC(blk) < PTRC(_xbrk) || PTRC(blk) >= PTRC(send))
- X {
- X _mallerr(fn, "allocated block list corrupted: blkptr = ",
- X (long) blk);
- X }
- X if (blk->m_cookie != MAGIC_COOKIE)
- X {
- X _mallerr(fn, "allocated block list corrupted, bad magic cookie: ",
- X blk->m_cookie);
- X }
- X if (blk->m_prev != cblk)
- X {
- X _mallerr(fn, "allocated block list corrupted: bad backptr blk ",
- X (long) blk);
- X }
- X if (blk->m_size < 0)
- X {
- X _mallerr(fn, "allocated block list corrupted: blk->m_size = ",
- X blk->m_size);
- X }
- X if (blk->m_rsize < 0)
- X {
- X _mallerr(fn, "allocated block list corrupted: blk->m_rsize = ",
- X blk->m_rsize);
- X }
- X /* one for this block, one for the failed potential next block */
- X if (blk->m_rsize <= blk->m_size - 2 * NEWBLK(ARR_BYTES))
- X {
- X _mallerr(fn, "allocated block list corrupted: rsize too small = ",
- X blk->m_rsize);
- X }
- X if (blk->m_rsize > blk->m_size)
- X {
- X _mallerr(fn, "allocated block list corrupted: rsize too big = ",
- X blk->m_rsize);
- X }
- X if (BLKFENCE(blk) != FENCE_COOKIE)
- X {
- X _mallerr(fn, "allocated block list corrupted, bad fence cookie: ",
- X BLKFENCE(blk));
- X }
- X }
- X cblk = 0;
- X for (blk = _ffb; blk; cblk = blk, blk = blk->m_next)
- X {
- X if (PTRC(blk) < PTRC(_xbrk) || PTRC(blk) >= PTRC(send))
- X _mallerr(fn, "free block list corrupted: blkptr = ", (long) blk);
- X if (blk->m_cookie != MAGIC_COOKIE)
- X {
- X _mallerr(fn, "free block list corrupted, bad magic cookie",
- X blk->m_cookie);
- X }
- X if (blk->m_prev != cblk)
- X {
- X _mallerr(fn, "free block list corrupted: bad backptr blk ",
- X (long) blk);
- X }
- X if (blk->m_size < 0)
- X {
- X _mallerr(fn, "free block list corrupted: blk->m_size = ",
- X blk->m_size);
- X }
- X }
- X for (blk = _fab; blk; blk = blk->m_next)
- X {
- X if ((long) BLKEND(blk) > PTRC(send))
- X {
- X _malldstr("(brk = ");
- X _malldptr(PTRC(send));
- X _malldstr(", eblk = ");
- X _malldptr((long) BLKEND(blk));
- X _malldstr(")\n");
- X _mallerr(fn, "allocated block extends past brk: ", (long) blk);
- X }
- X cnt = 0;
- X for (cblk = _fab; cblk; cblk = cblk->m_next)
- X {
- X if (blk == cblk)
- X {
- X if (!cnt++)
- X continue;
- X _mallerr(fn, "block allocated twice: ", (long) blk);
- X }
- X if (blk > cblk && PTRC(blk) < (long) BLKEND(cblk))
- X {
- X _malldstr("(blk = ");
- X _malldptr(PTRC(blk));
- X _malldstr(", cblk = ");
- X _malldptr(PTRC(cblk));
- X _malldstr(")\n");
- X _mallerr(fn, "nested block in allocated list: ", (long) blk);
- X }
- X }
- X for (cblk = _ffb; cblk; cblk = cblk->m_next)
- X {
- X if (blk == cblk)
- X {
- X _mallerr(fn, "block on allocated and free lists: ",
- X (long) blk);
- X }
- X if (PTRC(blk) > PTRC(cblk) && PTRC(blk) < (long) BLKEND(cblk))
- X {
- X _malldstr("(blk = ");
- X _malldptr(PTRC(blk));
- X _malldstr(", cblk = ");
- X _malldptr(PTRC(cblk));
- X _malldstr(", ecblk = ");
- X _malldptr(PTRC(BLKEND(cblk)));
- X _malldstr(")\n");
- X _mallerr(fn, "alloced block nested in free block: ",
- X (long) blk);
- X }
- X }
- X }
- X for (blk = _ffb; blk; blk = blk->m_next)
- X {
- X if ((long) BLKEND(blk) > PTRC(send))
- X {
- X _malldstr("(brk = ");
- X _malldptr(PTRC(send));
- X _malldstr(", eblk = ");
- X _malldptr((long) BLKEND(blk));
- X _malldstr(")\n");
- X _mallerr(fn, "free block extends past brk: ", (long) blk);
- X }
- X cnt = 0;
- X for (cblk = _ffb; cblk; cblk = cblk->m_next)
- X {
- X if (blk == cblk)
- X {
- X if (!cnt++)
- X continue;
- X _mallerr(fn, "block freed twice: ", (long) blk);
- X }
- X if (blk > cblk && PTRC(blk) < (long) BLKEND(cblk))
- X {
- X _malldstr("(blk = ");
- X _malldptr(PTRC(blk));
- X _malldstr(", cblk = ");
- X _malldptr(PTRC(cblk));
- X _malldstr(")\n");
- X _mallerr(fn, "nested block in free list: ", (long) blk);
- X }
- X }
- X for (cblk = _fab; cblk; cblk = cblk->m_next)
- X {
- X if (blk == cblk)
- X {
- X _mallerr(fn, "block on allocated and free lists: ",
- X (long) blk);
- X }
- X if (blk > cblk && PTRC(blk) < (long) BLKEND(cblk))
- X {
- X _malldstr("(blk = ");
- X _malldptr(PTRC(blk));
- X _malldstr(", cblk = ");
- X _malldptr(PTRC(cblk));
- X _malldstr(")\n");
- X _mallerr(fn, "free block nested in alloced block: ",
- X (long) blk);
- X }
- X }
- X }
- X _no_memcpy = oldm;
- X}
- X
- Xchar *
- X#ifdef __STDC__
- Xmalloc(unsigned int size)
- X#else
- Xmalloc(size)
- X unsigned int size;
- X#endif
- X{
- X register struct _Dmi *blk;
- X register unsigned int n;
- X
- X#ifdef MALLOC_TRACEBACK
- X if (!_in_malloc)
- X _mall_frame = (int *) &size;
- X#endif
- X n = m_round(size);
- X _in_malloc = 1;
- X _mall_init();
- X if (_mall_opt & _MALL_VFUNC)
- X {
- X _malldstr("called malloc(");
- X _malldptr(size);
- X _malldstr(")\n");
- X#ifdef MALLOC_TRACEBACK
- X if (_mall_opt & _MALL_TFUNC)
- X _mall_chase(((int *) &size) - 1);
- X#endif
- X }
- X _mallchk("malloc");
- X if (!size)
- X {
- X if (_mall_opt & _MALL_MALLOC_0)
- X _malldstr("warning: malloc(0) is unsafe\n");
- X else
- X {
- X _malldstr("malloc(0) is illegal\n");
- X _mall_sig(SIGSYS);
- X }
- X }
- X for (blk = _ffb; blk; blk = blk->m_next)
- X {
- X if (blk->m_size >= n)
- X {
- X /* split a large block to save memory and enable some checking */
- X if (blk->m_size >= n + NEWBLK(ARR_BYTES))
- X {
- X blk->m_size -= n + NEWBLK(ARR_BYTES);
- X ((char *) blk) += BLKSIZE(blk);
- X blk->m_cookie = MAGIC_COOKIE;
- X blk->m_size = n;
- X }
- X else
- X {
- X if (blk->m_next)
- X blk->m_next->m_prev = blk->m_prev;
- X if (blk->m_prev)
- X blk->m_prev->m_next = blk->m_next;
- X if (blk == _ffb)
- X _ffb = blk->m_next;
- X }
- X blk->m_next = _fab;
- X blk->m_prev = 0;
- X blk->m_rsize = size;
- X SET_BLKFENCE(blk);
- X if (_fab)
- X _fab->m_prev = blk;
- X _fab = blk;
- X _in_malloc = 0;
- X if (_mall_opt & _MALL_VBLK)
- X {
- X _malldstr("returned block ");
- X _malldptr((long) blk);
- X _malldstr(" user ptr ");
- X _malldptr((long) blk->m_blk);
- X _malldstr("\n");
- X }
- X return blk->m_blk;
- X }
- X }
- X if ((char *) (blk = (struct _Dmi *) sbrk(NEWBLK(n))) == SBRK_FAIL)
- X {
- X _in_malloc = 0;
- X if (_mall_opt & _MALL_VBLK)
- X {
- X _malldstr("returned failure\n");
- X }
- X return 0; /* no space */
- X }
- X if (!_xbrk)
- X _xbrk = (char *) blk;
- X blk->m_next = _fab;
- X blk->m_prev = 0;
- X blk->m_cookie = MAGIC_COOKIE;
- X blk->m_size = n;
- X blk->m_rsize = size;
- X SET_BLKFENCE(blk);
- X if (_fab)
- X _fab->m_prev = blk;
- X _fab = blk;
- X _in_malloc = 0;
- X if (_mall_opt & _MALL_VBLK)
- X {
- X _malldstr("returned block ");
- X _malldptr((long) blk);
- X _malldstr(" user ptr ");
- X _malldptr((long) blk->m_blk);
- X _malldstr("\n");
- X }
- X return blk->m_blk;
- X}
- X
- Xvoid
- X#ifdef __STDC__
- Xfree(char *s)
- X#else
- Xfree(s)
- X char *s;
- X#endif
- X{
- X register struct _Dmi *blk, *fblk, *cblk;
- X int didit;
- X
- X#ifdef MALLOC_TRACEBACK
- X if (!_in_malloc)
- X _mall_frame = (int *) &s;
- X#endif
- X _in_malloc = 1;
- X _mall_init();
- X if (_mall_opt & _MALL_VFUNC)
- X {
- X _malldstr("called free(");
- X _malldptr(PTRC(s));
- X _malldstr(")\n");
- X#ifdef MALLOC_TRACEBACK
- X if (_mall_opt & _MALL_TFUNC)
- X _mall_chase(((int *) &s) - 1);
- X#endif
- X }
- X _mallchk("free");
- X if (!s)
- X {
- X if (_mall_opt & _MALL_FREE_0)
- X {
- X _malldstr("warning: free(0) is unsafe\n");
- X _in_malloc = 0;
- X return;
- X }
- X else
- X {
- X _malldstr("free(0) is illegal\n");
- X _mall_sig(SIGSYS);
- X }
- X }
- X if (!(blk = _mallgb(s)))
- X _mallerr("non-allocated pointer passed to free(): ", s, 0);
- X if (blk->m_prev)
- X blk->m_prev->m_next = blk->m_next;
- X if (blk->m_next)
- X blk->m_next->m_prev = blk->m_prev;
- X if (blk == _fab)
- X _fab = blk->m_next;
- X blk->m_prev = 0;
- X blk->m_next = _ffb;
- X if (_ffb)
- X _ffb->m_prev = blk;
- X _ffb = blk;
- X/*
- X * crunch the free list by coalescing consecutive free blocks
- X */
- X didit = 1;
- X while (didit)
- X {
- X didit = 0;
- X for (fblk = _ffb; fblk; fblk = fblk->m_next)
- X {
- X for (cblk = _ffb; cblk; cblk = cblk->m_next)
- X {
- X if (cblk == fblk)
- X continue;
- X if (PTRC(fblk) + BLKSIZE(fblk) == PTRC(cblk))
- X {
- X fblk->m_size += BLKSIZE(cblk);
- X if (cblk->m_prev)
- X cblk->m_prev->m_next = cblk->m_next;
- X if (cblk->m_next)
- X cblk->m_next->m_prev = cblk->m_prev;
- X if (_ffb == cblk)
- X _ffb = cblk->m_next;
- X didit = 1;
- X fblk = 0;
- X break;
- X }
- X }
- X if (!fblk)
- X break; /* force a recycle, since we zapped the chain */
- X }
- X }
- X if (!(_mall_opt & _MALL_UNBREAK))
- X {
- X _in_malloc = 0;
- X return;
- X }
- X for (fblk = _ffb; fblk; fblk = fblk->m_next)
- X {
- X if ((long) BLKEND(fblk) == PTRC(sbrk(0)))
- X {
- X if (fblk->m_next)
- X fblk->m_next->m_prev = fblk->m_prev;
- X if (fblk->m_prev)
- X fblk->m_prev->m_next = fblk->m_next;
- X if (fblk == _ffb)
- X _ffb = fblk->m_next;
- X sbrk(- fblk->m_size);
- X break; /* this can only happen once */
- X }
- X }
- X _in_malloc = 0;
- X}
- X
- Xchar *
- X#ifdef __STDC__
- Xrealloc(char *s, unsigned int size)
- X#else
- Xrealloc(s, size)
- X char *s;
- X unsigned int size;
- X#endif
- X{
- X register char *s1, *d, *d1;
- X register struct _Dmi *blk;
- X
- X if (_mall_opt & _MALL_VFUNC)
- X {
- X _malldstr("called realloc(");
- X _malldptr(PTRC(s));
- X _malldstr(", ");
- X _malldptr(size);
- X _malldstr(")\n");
- X#ifdef MALLOC_TRACEBACK
- X if (_mall_opt & _MALL_TFUNC)
- X _mall_chase(((int *) &s) - 1);
- X#endif
- X }
- X _mallchk("realloc");
- X if (!s)
- X {
- X if (_mall_opt & _MALL_REALLOC_0)
- X {
- X _malldstr("warning: realloc(0, size) is unsafe\n");
- X return malloc(size);
- X }
- X else
- X {
- X _malldstr("realloc(0, size) is illegal\n");
- X _mall_sig(SIGSYS);
- X }
- X }
- X if (!size)
- X {
- X if (_mall_opt & _MALL_REALLOC_0)
- X _malldstr("warning: realloc(ptr, 0) is unsafe\n");
- X else
- X {
- X _malldstr("realloc(ptr, 0) is illegal\n");
- X _mall_sig(SIGSYS);
- X }
- X }
- X if (!(blk = _mallgb(s)))
- X {
- X _mallerr("realloc", "non-allocated pointer passed to realloc(): ",
- X (long) s);
- X }
- X if (!(s1 = malloc(size)))
- X return 0;
- X if (blk->m_size < size)
- X size = blk->m_size;
- X d1 = s1;
- X d = s;
- X while (size--)
- X *((char *) d1)++ = *((char *) d)++;
- X free(s);
- X return s1;
- X}
- X
- X/*
- X * malloc objects and zero storage
- X */
- X
- Xchar *
- X#ifdef __STDC__
- Xcalloc(unsigned int n, unsigned int size)
- X#else
- Xcalloc(n, size)
- X unsigned int n, size;
- X#endif
- X{
- X register char *s, *s1;
- X
- X if (_mall_opt & _MALL_VFUNC)
- X {
- X _malldstr("called calloc(");
- X _malldptr(n);
- X _malldstr(", ");
- X _malldptr(size);
- X _malldstr(")\n");
- X#ifdef MALLOC_TRACEBACK
- X if (_mall_opt & _MALL_TFUNC)
- X _mall_chase(((int *) &n) - 1);
- X#endif
- X }
- X n *= size;
- X if (!(s = malloc(n)))
- X return 0;
- X for (s1 = s; n; n--)
- X *((char *) s1)++ = '\0';
- X return s;
- X}
- X
- X/*
- X * for some reason this is in /lib/libc.a(calloc.o)
- X */
- X
- Xvoid
- X#ifdef __STDC__
- Xcfree(char *s)
- X#else
- Xcfree(s)
- X char *s;
- X#endif
- X{
- X free(s);
- X}
- X
- X#ifdef MALLOC_LIB
- X
- X/*
- X * Reimplementations of some library functions that often take malloc'ed
- X * pointers as arguments. The idea is that we can head off a sizeable number
- X * of potential disasters before they happen, and hopefully pinpoint the
- X * location of a bug a little more closely than the next operation that uses
- X * malloc (or dumps core...).
- X */
- X
- Xlong
- X#ifdef __STDC__
- X_mallpchk(const char *c)
- X#else
- X_mallpchk(c)
- X char *c;
- X#endif
- X{
- X struct _Dmi *d; /* I'd like this to be register, but... */
- X
- X if (!_in_malloc && (_mall_opt & _MALL_VFUNC))
- X {
- X _malldstr("called _mallpchk(");
- X _malldptr((long) c);
- X _malldstr(")\n");
- X#ifdef MALLOC_TRACEBACK
- X if (_mall_opt & _MALL_TFUNC)
- X _mall_chase((int *) &c - 1);
- X#endif
- X }
- X if (c == 0)
- X {
- X _malldstr("mallpchk(");
- X _malldptr((long) c);
- X _malldstr(") null\n");
- X return -1;
- X }
- X /*
- X * Theory: things shouldn't stomp on segments they don't belong to.
- X * After all, how often does a data segment variable extend into bss?
- X */
- X if (c < etext)
- X return (long) etext - (long) c;
- X if (c < edata)
- X return (long) edata - (long) c;
- X if (c < end)
- X return (long) end - (long) c;
- X if (c < _xbrk)
- X return (long) _xbrk - (long) c;
- X if (c >= sbrk(0) && c < (char *) &d)
- X {
- X _malldstr("mallpchk(");
- X _malldptr((long) c);
- X _malldstr(") ptr outside brk\n");
- X return -1;
- X }
- X if (c >= (char *) &d && c <= MALLOC_LIMIT)
- X {
- X#ifndef MALLOC_TRACEBACK
- X return (long) MALLOC_LIMIT - (long) c;
- X#else
- X int *stkptr;
- X
- X if ((stkptr = (int *) &c - 1) < (int *) &d ||
- X (char *) stkptr > MALLOC_LIMIT)
- X {
- X _mallerr("mallpchk", "stack corrupted - frame got ",
- X (long) stkptr);
- X }
- X while (*stkptr)
- X {
- X if ((long) c >= (long) stkptr && (long) c < stkptr[-1])
- X return (long) c + (long) stkptr - stkptr[-1] - 1;
- X if ((stkptr = (int *) stkptr[-1] + 1) < (int *) &d ||
- X (char *) stkptr > MALLOC_LIMIT)
- X {
- X _mallerr("mallpchk", "stack corrupted - frame got ",
- X (long) stkptr);
- X }
- X }
- X if (c > (char *) stkptr) /* environ[] or argv[] */
- X return MALLOC_LIMIT - (char *) stkptr;
- X _malldstr("mallpchk(");
- X _malldptr((long) c);
- X _malldstr(") stack is damaged\n");
- X return -1;
- X#endif
- X }
- X if (c >= MALLOC_LIMIT)
- X {
- X _malldstr("mallpchk(");
- X _malldptr((long) c);
- X _malldstr(") ptr outside address space\n");
- X return -1;
- X }
- X for (d = _fab; d; d = d->m_next)
- X {
- X if (c >= d->m_blk && c < d->m_blk + d->m_size)
- X return d->m_size + (long) d->m_blk - (long) c;
- X }
- X _malldstr("mallpchk(");
- X _malldptr((long) c);
- X _malldstr(") found no valid block\n");
- X _malldmp();
- X return -1;
- X}
- X
- Xchar *
- X#ifdef __STDC__
- Xstrcpy(char *d, const char *s)
- X#else
- Xstrcpy(d, s)
- X char *d, *s;
- X#endif
- X{
- X register int c;
- X int l, m;
- X
- X _mall_init();
- X _in_malloc = 1;
- X#ifdef MALLOC_TRACEBACK
- X _mall_frame = (int *) &d;
- X#endif
- X if (_mall_opt & _MALL_VUTIL)
- X {
- X _malldstr("called strcpy(");
- X _malldptr((long) d);
- X _malldstr(", ");
- X _malldptr((long) s);
- X _malldstr(")\n");
- X#ifdef MALLOC_TRACEBACK
- X if (_mall_opt & _MALL_TUTIL)
- X _mall_chase(((int *) &d) - 1);
- X#endif
- X }
- X _mallchk("strcpy");
- X if (!d)
- X {
- X _malldstr("strcpy to null pointer\n");
- X _mall_sig(SIGSYS);
- X }
- X if (!s)
- X {
- X _malldstr("strcpy from null pointer\n");
- X _mall_sig(SIGSYS);
- X }
- X if ((m = _mallpchk(d)) < 0)
- X {
- X _malldstr("strcpy to invalid addr ");
- X _malldptr((long) d);
- X _malldstr("\n");
- X _mall_sig(SIGSYS);
- X }
- X if ((l = _mallpchk(s)) < 0)
- X {
- X _malldstr("strcpy from invalid addr ");
- X _malldptr((long) s);
- X _malldstr("\n");
- X _mall_sig(SIGSYS);
- X }
- X for (c = 0; s[c]; c++)
- X {
- X if (c == l)
- X {
- X _malldstr("strcpy src ");
- X _malldptr((long) s);
- X _malldstr(" too long\n");
- X _mall_sig(SIGSYS);
- X }
- X if (c == m)
- X {
- X _malldstr("strcpy dest ");
- X _malldptr((long) d);
- X _malldstr(" too short\n");
- X _mall_sig(SIGSYS);
- X }
- X d[c] = s[c];
- X }
- X if (c == m)
- X {
- X _malldstr("strcpy dest ");
- X _malldptr((long) d);
- X _malldstr(" too short\n");
- X _mall_sig(SIGSYS);
- X }
- X d[c] = 0;
- X _in_malloc = 0;
- X return d;
- X}
- X
- Xchar *
- X#ifdef __STDC__
- Xstrncpy(char *d, const char *s, int n)
- X#else
- Xstrncpy(d, s, n)
- X char *d, *s;
- X int n;
- X#endif
- X{
- X register int c;
- X int l, m;
- X
- X _mall_init();
- X _in_malloc = 1;
- X#ifdef MALLOC_TRACEBACK
- X _mall_frame = (int *) &d;
- X#endif
- X if (_mall_opt & _MALL_VUTIL)
- X {
- X _malldstr("called strncpy(");
- X _malldptr((long) d);
- X _malldstr(", ");
- X _malldptr((long) s);
- X _malldstr(", ");
- X _malldptr(n);
- X _malldstr(")\n");
- X#ifdef MALLOC_TRACEBACK
- X if (_mall_opt & _MALL_TUTIL)
- X _mall_chase(((int *) &d) - 1);
- X#endif
- X }
- X _mallchk("strncpy");
- X if (!d)
- X {
- X _malldstr("strncpy to null pointer\n");
- X _mall_sig(SIGSYS);
- X }
- X if (!s)
- X {
- X _malldstr("strncpy from null pointer\n");
- X _mall_sig(SIGSYS);
- X }
- X if (n < 0)
- X {
- X _malldstr("strncpy(dest, src, ");
- X _malldptr(n);
- X _malldstr(") negative count\n");
- X _mall_sig(SIGSYS);
- X }
- X if ((m = _mallpchk(d)) < 0)
- X {
- X _malldstr("strncpy to invalid addr ");
- X _malldptr((long) d);
- X _malldstr("\n");
- X _mall_sig(SIGSYS);
- X }
- X if (m < n)
- X {
- X _malldstr("strncpy dest ");
- X _malldptr((long) d);
- X _malldstr(" too short\n");
- X _mall_sig(SIGSYS);
- X }
- X if ((l = _mallpchk(s)) < 0)
- X {
- X _malldstr("strncpy from invalid addr ");
- X _malldptr((long) s);
- X _malldstr("\n");
- X _mall_sig(SIGSYS);
- X }
- X for (c = 0; s[c] && n--; c++)
- X {
- X if (c == l)
- X {
- X _malldstr("strncpy src ");
- X _malldptr((long) s);
- X _malldstr(" too long\n");
- X _mall_sig(SIGSYS);
- X }
- X d[c] = s[c];
- X }
- X while (n--)
- X d[c++] = 0;
- X _in_malloc = 0;
- X return d;
- X}
- X
- Xchar *
- X#ifdef __STDC__
- Xstrcat(char *d, const char *s)
- X#else
- Xstrcat(d, s)
- X char *d, *s;
- X#endif
- X{
- X register int c, a;
- X int l, m;
- X
- X _mall_init();
- X _in_malloc = 1;
- X#ifdef MALLOC_TRACEBACK
- X _mall_frame = (int *) &d;
- X#endif
- X if (_mall_opt & _MALL_VUTIL)
- X {
- X _malldstr("called strcat(");
- X _malldptr((long) d);
- X _malldstr(", ");
- X _malldptr((long) s);
- X _malldstr(")\n");
- X#ifdef MALLOC_TRACEBACK
- X if (_mall_opt & _MALL_TUTIL)
- X _mall_chase(((int *) &d) - 1);
- X#endif
- X }
- X _mallchk("strcat");
- X if (!d)
- X {
- X _malldstr("strcat to null pointer\n");
- X _mall_sig(SIGSYS);
- X }
- X if (!s)
- X {
- X _malldstr("strcat from null pointer\n");
- X _mall_sig(SIGSYS);
- X }
- X if ((m = _mallpchk(d)) < 0)
- X {
- X _malldstr("strcat to invalid addr ");
- X _malldptr((long) d);
- X _malldstr("\n");
- X _mall_sig(SIGSYS);
- X }
- X if ((l = _mallpchk(s)) < 0)
- X {
- X _malldstr("strcat from invalid addr ");
- X _malldptr((long) s);
- X _malldstr("\n");
- X _mall_sig(SIGSYS);
- X }
- X for (a = 0; a < m && d[a]; a++)
- X ;
- X if (a == m)
- X {
- X _malldstr("strcat dest ");
- X _malldptr((long) d);
- X _malldstr(" too short\n");
- X _mall_sig(SIGSYS);
- X }
- X for (c = 0; s[c]; c++)
- X {
- X if (c == l)
- X {
- X _malldstr("strcat src ");
- X _malldptr((long) s);
- X _malldstr(" too long\n");
- X _mall_sig(SIGSYS);
- X }
- X if (c + a == m)
- X {
- X _malldstr("strcat dest ");
- X _malldptr((long) d);
- X _malldstr(" too short\n");
- X _mall_sig(SIGSYS);
- X }
- X d[c + a] = s[c];
- X }
- X if (c + a == m)
- X {
- X _malldstr("strcat dest ");
- X _malldptr((long) d);
- X _malldstr(" too short\n");
- X _mall_sig(SIGSYS);
- X }
- X d[c + a] = 0;
- X _in_malloc = 0;
- X return d;
- X}
- X
- Xchar *
- X#ifdef __STDC__
- Xstrncat(char *d, const char *s, int n)
- X#else
- Xstrncat(d, s, n)
- X char *d, *s;
- X int n;
- X#endif
- X{
- X register int c, a;
- X int l, m;
- X
- X _mall_init();
- X _in_malloc = 1;
- X#ifdef MALLOC_TRACEBACK
- X _mall_frame = (int *) &d;
- X#endif
- X if (_mall_opt & _MALL_VUTIL)
- X {
- X _malldstr("called strncat(");
- X _malldptr((long) d);
- X _malldstr(", ");
- X _malldptr((long) s);
- X _malldstr(", ");
- X _malldptr(n);
- X _malldstr(")\n");
- X#ifdef MALLOC_TRACEBACK
- X if (_mall_opt & _MALL_TUTIL)
- X _mall_chase(((int *) &d) - 1);
- X#endif
- X }
- X _mallchk("strncat");
- X if (!d)
- X {
- X _malldstr("strncat to null pointer\n");
- X _mall_sig(SIGSYS);
- X }
- X if (!s)
- X {
- X _malldstr("strncat from null pointer\n");
- X _mall_sig(SIGSYS);
- X }
- X if (n < 0)
- X {
- X _malldstr("strncat(dest, src, ");
- X _malldptr(n);
- X _malldstr(") negative count\n");
- X _mall_sig(SIGSYS);
- X }
- X if ((m = _mallpchk(d)) < 0)
- X {
- X _malldstr("strncat to invalid addr ");
- X _malldptr((long) d);
- X _malldstr("\n");
- X _mall_sig(SIGSYS);
- X }
- X for (a = 0; a < m && d[a]; a++)
- X ;
- X if (a + n > m)
- X {
- X _malldstr("strncat dest ");
- X _malldptr((long) d);
- X _malldstr(" too short\n");
- X _mall_sig(SIGSYS);
- X }
- X if ((l = _mallpchk(s)) < 0)
- X {
- X _malldstr("strncat from invalid addr ");
- X _malldptr((long) s);
- X _malldstr("\n");
- X _mall_sig(SIGSYS);
- X }
- X for (c = 0; s[c] && n--; c++)
- X {
- X if (c == l)
- X {
- X _malldstr("strncat src ");
- X _malldptr((long) s);
- X _malldstr(" too long\n");
- X _mall_sig(SIGSYS);
- X }
- X d[c + a] = s[c];
- X }
- X while (n--)
- X d[c++ + a] = 0;
- X _in_malloc = 0;
- X return d;
- X}
- X
- Xchar *
- X#ifdef __STDC__
- Xmemcpy(char *d, const char *s, int n)
- X#else
- Xmemcpy(d, s, n)
- X char *d, *s;
- X int n;
- X#endif
- X{
- X register int c;
- X int l, m, o;
- X
- X if (!(o = _in_malloc) && !_no_memcpy)
- X {
- X _mall_init();
- X _in_malloc = 1;
- X#ifdef MALLOC_TRACEBACK
- X _mall_frame = (int *) &d;
- X#endif
- X if (_mall_opt & _MALL_VUTIL)
- X {
- X _malldstr("called memcpy(");
- X _malldptr((long) d);
- X _malldstr(", ");
- X _malldptr((long) s);
- X _malldstr(", ");
- X _malldptr(n);
- X _malldstr(")\n");
- X#ifdef MALLOC_TRACEBACK
- X if (_mall_opt & _MALL_TUTIL)
- X _mall_chase(((int *) &d) - 1);
- X#endif
- X }
- X _mallchk("memcpy");
- X if (!d)
- X {
- X _malldstr("memcpy to null pointer\n");
- X _mall_sig(SIGSYS);
- X }
- X if (!s)
- X {
- X _malldstr("memcpy from null pointer\n");
- X _mall_sig(SIGSYS);
- X }
- X if (n < 0)
- X {
- X _malldstr("memcpy(dest, src, ");
- X _malldptr(n);
- X _malldstr(") negative count\n");
- X _mall_sig(SIGSYS);
- X }
- X if ((m = _mallpchk(d)) < 0)
- X {
- X _malldstr("memcpy to invalid addr ");
- X _malldptr((long) d);
- X _malldstr("\n");
- X _mall_sig(SIGSYS);
- X }
- X if (m < n)
- X {
- X _malldstr("memcpy dest ");
- X _malldptr((long) d);
- X _malldstr(" too short\n");
- X _mall_sig(SIGSYS);
- X }
- X if ((l = _mallpchk(s)) < 0)
- X {
- X _malldstr("memcpy from invalid addr ");
- X _malldptr((long) s);
- X _malldstr("\n");
- X _mall_sig(SIGSYS);
- X }
- X if (l < n)
- X {
- X _malldstr("memcpy src ");
- X _malldptr((long) s);
- X _malldstr(" too short\n");
- X _mall_sig(SIGSYS);
- X }
- X }
- X for (c = 0; n--; c++)
- X d[c] = s[c];
- X _in_malloc = o;
- X return d;
- X}
- X
- Xchar *
- X#ifdef __STDC__
- Xmemset(char *d, int s, int n)
- X#else
- Xmemset(d, s, n)
- X char *d;
- X int s, n;
- X#endif
- X{
- X register int c;
- X int m;
- X
- X _mall_init();
- X _in_malloc = 1;
- X#ifdef MALLOC_TRACEBACK
- X _mall_frame = (int *) &s;
- X#endif
- X if (_mall_opt & _MALL_VUTIL)
- X {
- X _malldstr("called memset(");
- X _malldptr((long) d);
- X _malldstr(", ");
- X _malldptr(s);
- X _malldstr(", ");
- X _malldptr(n);
- X _malldstr(")\n");
- X#ifdef MALLOC_TRACEBACK
- X if (_mall_opt & _MALL_TUTIL)
- X _mall_chase(((int *) &d) - 1);
- X#endif
- X }
- X _mallchk("memset");
- X if (!d)
- X {
- X _malldstr("memset to null pointer\n");
- X _mall_sig(SIGSYS);
- X }
- X if (n < 0)
- X {
- X _malldstr("memset(dest, src, ");
- X _malldptr(n);
- X _malldstr(") negative count\n");
- X _mall_sig(SIGSYS);
- X }
- X if ((m = _mallpchk(d)) < 0)
- X {
- X _malldstr("memset to invalid addr ");
- X _malldptr((long) d);
- X _malldstr("\n");
- X _mall_sig(SIGSYS);
- X }
- X if (m < n)
- X {
- X _malldstr("memset dest ");
- X _malldptr((long) d);
- X _malldstr(" too short\n");
- X _mall_sig(SIGSYS);
- X }
- X for (c = 0; n--; c++)
- X d[c] = s;
- X _in_malloc = 0;
- X return d;
- X}
- X
- X/*
- X * Validate a STDIO pointer. User-invoked diagnostic routine, I am not
- X * going to rewrite stdio just to do pointer checks!
- X */
- X
- X#include <stdio.h>
- X
- Xvoid
- X_mallschk(fp)
- X FILE *fp;
- X{
- X if (_mall_opt & _MALL_VFUNC)
- X {
- X _malldstr("called _mallschk(");
- X _malldptr((long) fp);
- X _malldstr(")\n");
- X#ifdef MALLOC_TRACEBACK
- X if (_mall_opt & _MALL_TFUNC)
- X _mall_chase((int *) &fp - 1);
- X#endif
- X }
- X _in_malloc = 1;
- X if (_mallpchk((char *) fp) == -1)
- X _mallerr("mallschk", "stdio FILE * out of range", (long) fp);
- X _malldstr("stdio ptr ");
- X _malldptr((long) fp);
- X _malldstr(" {ptr=");
- X _malldptr((long) fp->_ptr);
- X _malldstr(", cnt=");
- X _malldptr((long) fp->_cnt);
- X _malldstr(", base=");
- X _malldptr((long) fp->_base);
- X _malldstr(", bufend=");
- X _malldptr((long) _bufend(fp));
- X _malldstr(", file=");
- X _malldptr((long) fp->_file);
- X _malldstr(", flag=");
- X _malldptr((long) fp->_flag);
- X _malldstr("}\n");
- X if (_mallpchk((char *) fp->_ptr) == -1)
- X _mallerr("mallschk", "stdio buf ptr out of range", (long) fp->_ptr);
- X if (_mallpchk((char *) fp->_base) == -1)
- X _mallerr("mallschk", "stdio base ptr out of range", (long) fp->_base);
- X if (_mallpchk((char *) _bufend(fp)) == -1)
- X {
- X _mallerr("mallschk", "stdio bufend ptr out of range",
- X (long) _bufend(fp));
- X }
- X if (fp->_base + fp->_cnt >= _bufend(fp))
- X _mallerr("mallschk", "stdio bufcnt out of range", fp->_cnt);
- X _in_malloc = 0;
- X}
- X
- X#endif
- ________This_Is_The_END________
- echo 'x - malloc.h'
- sed 's/^X//' <<'________This_Is_The_END________' >>malloc.h
- X/*
- X * malloc for debugging -- allocates via sbrk and tracks stuff, does diag dump
- X * if things appear to be screwed up. (bsa)
- X */
- X
- X#if defined(__STDC__)
- Xextern void _malldmp(void);
- Xextern char *malloc(unsigned int);
- Xextern void free(char *);
- Xextern char *realloc(char *, unsigned int);
- Xextern void _mallchk(const char *);
- Xextern char *calloc(unsigned int, unsigned int);
- Xextern void cfree(char *);
- Xextern char *strcpy(char *, const char *);
- Xextern char *strncpy(char *, const char *, int);
- Xextern char *strcat(char *, const char *);
- Xextern char *strncat(char *, const char *, int);
- Xextern char *memcpy(char *, const char *, int);
- Xextern char *memset(char *, int, int);
- X#else
- Xextern void _malldmp();
- Xextern char *malloc();
- Xextern void free();
- Xextern char *realloc();
- Xextern void _mallchk();
- Xextern char *calloc();
- Xextern void cfree();
- Xextern char *strcpy();
- Xextern char *strncpy();
- Xextern char *strcat();
- Xextern char *strncat();
- Xextern char *memcpy();
- Xextern char *memset();
- X#endif
- X
- X#define _MALL_VFUNC 0x00000001 /* v */
- X#define _MALL_TFUNC 0x00000002 /* t */
- X#define _MALL_VUTIL 0x00000004 /* V */
- X#define _MALL_TUTIL 0x00000008 /* T */
- X#define _MALL_MALLOC_0 0x00000010 /* m */
- X#define _MALL_VBLK 0x00000020 /* b */
- X#define _MALL_FREE_0 0x00000040 /* f */
- X#define _MALL_UNBREAK 0x00000080 /* u */
- X#define _MALL_REALLOC_0 0x00000100 /* r */
- X#define _MALL_SEGV 0x00000200 /* S */
- X#define _MALL_BUS 0x00000400 /* B */
- ________This_Is_The_END________
- echo 'x - malltest.c'
- sed 's/^X//' <<'________This_Is_The_END________' >>malltest.c
- X#include <stdio.h>
- X
- Xextern void setbuf();
- Xextern char *strrchr();
- Xextern char *malloc();
- Xextern char *realloc();
- Xextern void free();
- Xextern int getopt();
- Xextern void exit();
- Xextern void srand48();
- Xextern double drand48();
- Xextern long time();
- Xextern int getpid();
- Xextern int printf();
- Xextern int fprintf();
- Xextern long strtol();
- X
- Xextern char *optarg;
- Xextern int optind;
- X
- Xint
- Xrnd(l, h)
- X int l, h;
- X{
- X static int initialized = 0;
- X
- X if (l == h)
- X return l;
- X if (!initialized)
- X {
- X srand48(getpid() ^ time((long *) 0));
- X initialized = 1;
- X }
- X return (int) (drand48() * (h - l + 1) + l);
- X}
- X
- Xint
- Xmain(argc, argv)
- X int argc;
- X char **argv;
- X{
- X char **allocs;
- X int cnt, opt, repeats, low, high, errs, slots;
- X char *myname, *cp;
- X
- X setbuf(stderr, (char *) 0);
- X if ((myname = strrchr(argv[0], '/')))
- X myname++;
- X else
- X myname = argv[0];
- X repeats = 1;
- X slots = 100;
- X low = 1;
- X high = 32768;
- X while ((opt = getopt(argc, argv, "r:l:h:s:")) != EOF)
- X {
- X switch (opt)
- X {
- X case 'r':
- X cnt = strtol(optarg, &cp, 0);
- X if (cp == optarg || *cp)
- X {
- X fprintf(stderr, "%s: invalid number \"%s\" for -r\n", myname,
- X optarg);
- X errs++;
- X }
- X else if (cnt <= 0)
- X {
- X fprintf(stderr, "%s: -r repeat count must be positive\n",
- X myname);
- X errs++;
- X }
- X else
- X repeats = cnt;
- X break;
- X case 'l':
- X cnt = strtol(optarg, &cp, 0);
- X if (cp == optarg || *cp)
- X {
- X fprintf(stderr, "%s: invalid number \"%s\" for -l\n", myname,
- X optarg);
- X errs++;
- X }
- X else if (cnt <= 0)
- X {
- X fprintf(stderr, "%s: -l lower limit must be positive\n",
- X myname);
- X errs++;
- X }
- X else
- X low = cnt;
- X break;
- X case 'h':
- X cnt = strtol(optarg, &cp, 0);
- X if (cp == optarg || *cp)
- X {
- X fprintf(stderr, "%s: invalid number \"%s\" for -h\n", myname,
- X optarg);
- X errs++;
- X }
- X else if (cnt <= 0)
- X {
- X fprintf(stderr, "%s: -h higher limit must be positive\n",
- X myname);
- X errs++;
- X }
- X else
- X high = cnt;
- X break;
- X case 's':
- X cnt = strtol(optarg, &cp, 0);
- X if (cp == optarg || *cp)
- X {
- X fprintf(stderr, "%s: invalid number \"%s\" for -s\n", myname,
- X optarg);
- X errs++;
- X }
- X else if (cnt <= 0)
- X {
- X fprintf(stderr, "%s: -s slot count must be positive\n",
- X myname);
- X errs++;
- X }
- X else
- X slots = cnt;
- X break;
- X default:
- X errs++;
- X break;
- X }
- X }
- X if (errs)
- X {
- X fprintf(stderr,
- X "usage: malloc_test [-r repeat] [-l lowlim] [-h highlim]\n");
- X exit(1);
- X }
- X while (repeats--)
- X {
- X if (!(allocs = (char **) malloc(slots * sizeof *allocs)))
- X {
- X fprintf(stderr, "%s: can't allocate %d slots\n", myname, slots);
- X exit(1);
- X }
- X for (cnt = 0; cnt < slots; cnt++)
- X {
- X if (!(allocs[cnt] = malloc(errs = rnd(low, high))))
- X {
- X fprintf(stderr, "%s: can't allocate %d bytes for slot %d\n",
- X myname, errs, cnt);
- X exit(1);
- X }
- X }
- X for (cnt = 0; cnt < slots; cnt++)
- X {
- X if (!(allocs[cnt] = realloc(allocs[cnt], errs = rnd(low, high))))
- X {
- X fprintf(stderr, "%s: can't reallocate %d bytes for slot %d\n",
- X myname, errs, cnt);
- X exit(1);
- X }
- X }
- X for (cnt = 0; cnt < slots; cnt++)
- X free(allocs[cnt]);
- X free(allocs);
- X }
- X printf("%s: test completed successfully\n", myname);
- X return 0;
- X}
- ________This_Is_The_END________
- exit
- --
- Me: Brandon S. Allbery KF8NH: DC to LIGHT! [44.70.4.88]
- Internet: allbery@NCoast.ORG Delphi: ALLBERY
- uunet!usenet.ins.cwru.edu!ncoast!allbery
-
- exit 0 # Just in case...
-