diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2000-09-22 14:33:37 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2000-09-22 14:33:37 +0000 |
commit | b501a54cf959bc549810fb24ca6f9584dc5c9cf3 (patch) | |
tree | b78fbbc5c0f6959529f2553e3bbb83b077eaa17c /dmake/dbug/malloc | |
parent | 17e0108b4e8d91f9acfe376ee231418830392460 (diff) |
initial import
Diffstat (limited to 'dmake/dbug/malloc')
-rw-r--r-- | dmake/dbug/malloc/_changes | 9 | ||||
-rw-r--r-- | dmake/dbug/malloc/_readme | 133 | ||||
-rw-r--r-- | dmake/dbug/malloc/calloc.c | 91 | ||||
-rw-r--r-- | dmake/dbug/malloc/debug.h | 129 | ||||
-rw-r--r-- | dmake/dbug/malloc/dump.c | 142 | ||||
-rw-r--r-- | dmake/dbug/malloc/free.c | 206 | ||||
-rw-r--r-- | dmake/dbug/malloc/m_init.c | 121 | ||||
-rw-r--r-- | dmake/dbug/malloc/m_perror.c | 111 | ||||
-rw-r--r-- | dmake/dbug/malloc/makefile | 77 | ||||
-rw-r--r-- | dmake/dbug/malloc/malloc.3 | 223 | ||||
-rw-r--r-- | dmake/dbug/malloc/malloc.c | 672 | ||||
-rw-r--r-- | dmake/dbug/malloc/malloc.h | 121 | ||||
-rw-r--r-- | dmake/dbug/malloc/mallopt.c | 143 | ||||
-rw-r--r-- | dmake/dbug/malloc/memory.c | 243 | ||||
-rw-r--r-- | dmake/dbug/malloc/mlc_chk.c | 297 | ||||
-rw-r--r-- | dmake/dbug/malloc/mlc_chn.c | 188 | ||||
-rw-r--r-- | dmake/dbug/malloc/patchlev | 1 | ||||
-rw-r--r-- | dmake/dbug/malloc/realloc.c | 233 | ||||
-rw-r--r-- | dmake/dbug/malloc/string.c | 581 | ||||
-rw-r--r-- | dmake/dbug/malloc/testmem.c | 646 | ||||
-rw-r--r-- | dmake/dbug/malloc/testmlc.c | 176 | ||||
-rw-r--r-- | dmake/dbug/malloc/tostring.c | 169 | ||||
-rw-r--r-- | dmake/dbug/malloc/tostring.h | 43 |
23 files changed, 4755 insertions, 0 deletions
diff --git a/dmake/dbug/malloc/_changes b/dmake/dbug/malloc/_changes new file mode 100644 index 000000000000..888a47a8dfb5 --- /dev/null +++ b/dmake/dbug/malloc/_changes @@ -0,0 +1,9 @@ +I made the following changes to the malloc package as found in +comp.sources.unix: + + 1. created this file _changes. + 2. moved README to _readme (facilitates transfer to DOS and back to + unix) + 3. renamed testmalloc.c, malloc_chk.c, and malloc_chn.c to testmlc.c, + mlc_chk.c, and mlc_chn.c respectively. Again DOS has trouble with + long basenames in filenames. diff --git a/dmake/dbug/malloc/_readme b/dmake/dbug/malloc/_readme new file mode 100644 index 000000000000..b78b1fd6bbcd --- /dev/null +++ b/dmake/dbug/malloc/_readme @@ -0,0 +1,133 @@ +# (c) Copyright 1990 Conor P. Cahill. (uunet!virtech!cpcahil) +# You may copy, distribute, and use this software as long as this +# copyright statement is not removed. + +This package is a collection of routines which are a drop-in replacement +for the malloc(3), memory(3), string(3), and bstring(3) library functions. + +The purpose of these programs is to aid the development and/or debugging +of programs using these functions by providing a high level of consistancy +checking whenever a malloc pointer is used. Due to this increased +level of consistancy checking, these functions have a considerably larger +overhead than the standard functions, but the extra checking should be +well worth it in a development environment. + +To use these functions all you need to do is compile the library and +include it on your loader command line. You do not need to recompile +your code, only a relink is necessary. + +Features of this library: + + 1. The malloced area returned from each call to malloc is filled with + non-null bytes. This should catch any use of uninitialized malloc + area. The fill pattern for malloced area is 0x01. + + 2. When free is called numerous validity checks are made on the + pointer it is passed. In addition, the data in the malloc block + beyound the size requested on the initial malloc is checked to + verify that it is still filled with the original fill characters. + + This is usefull for catching things like: + + ptr = malloc(5); + ptr[5] = '\0'; + + /* + * You should not that this will be caught when it is + * freed not when it is done + */ + + And finally, the freed block is filled with a different fill pattern + so that you can easily determine if you are still using free'd space. + The fill pattern for free'd areas is 0x02. + + This is usefull for catching things like: + + ptr = malloc(20); + + bptr = ptr+10; + + /* do something usefule with bptr */ + + free(ptr); + + /* + * now try to do something useful with bptr, it should + * be trashed enough that it would cause real problems + * and when you went to debug the problem it would be + * filled with 0x02's and you would then know to look + * for something free'ing what bptr points to. + */ + + + 3. Whenever a bstring(3)/string(3)/memory(3) function is called, it's + parameters are checked as follows: + + If they point somewhere in the malloc arena + If the operation goes beyond requested malloc space + call malloc_warning() + + This is usefull for catching things like: + + ptr = malloc(5); + strcpy(ptr,"abcde"); + + + 4. Malloc_warning() and malloc_fatal() are used when an error condition + is detected. If the error is severe, malloc_fatal is called. + Malloc_warning is used otherwise. The decision about what is fatal + and what is a warning was made somewhat arbitrarily. + + Warning messages include: + + Calling free with a bad pointer + Calling a bstring/string/memory (3) function which will go beyond + the end of a malloc block (Note that the library function is + not modified to refuse the operation. If malloc warnings are + in the default IGNORE case, the operation will continue and + at some point cause a real problem). + + Fatal errors are: + + Detectable corruption to the malloc chain. + + + 5. The operations to perform when an error is detected are specified at + run time by the use of environment variables. + + MALLOC_WARN - specifies the warning error message handling + MALLOC_FATAL - specifies the fatal error handling + + + When one of these error conditions occur you will get an error + message and the handler will execute based upon what setting + is in the environment variables. Currently understood settings + are as follows: + + 0 - continue operations + 1 - drop core and exit + 2 - just exit + 3 - drop core, but continue executing. Core files will + be placed into core.[PID].[counter] i.e: core.00123.001 + 128 - dump malloc chain and continue + 129 - dump malloc chain, dump core, and exit + 130 - dump malloc chain, exit + 131 - dump malloc chain, dump core, continue processing + + + There is an additional environment variable MALLOC_ERRFILE which + is used to indicate the name of the file for error message output. + + For example, to set up the session to generate a core file for + every malloc warning, to drop core and exit on a malloc fatal, and + to log all messages to the file "malloc_log" do the following: + + MALLOC_WARN=131 + MALLOC_FATAL=1 + MALLOC_ERRFILE=malloc_log + + export MALLOC_WARN MALLOC_FATAL MALLOC_ERRFILE + + 6. The function malloc_dump() is available to dump the malloc chain whenever + you might want. It's only argument is a file descriptor to use to write + the data. Review the code if you need to know what data is printed. diff --git a/dmake/dbug/malloc/calloc.c b/dmake/dbug/malloc/calloc.c new file mode 100644 index 000000000000..6d1e0f84b626 --- /dev/null +++ b/dmake/dbug/malloc/calloc.c @@ -0,0 +1,91 @@ +/* + * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). + * You may copy, distribute, and use this software as long as this + * copyright statement is not removed. + */ +#include <stdio.h> + +/* + * Function: calloc() + * + * Purpose: to allocate and nullify a data area + * + * Arguments: nelem - number of elements + * elsize - size of each element + * + * Returns: NULL - if malloc fails + * or pointer to allocated space + * + * Narrative: determine size of area to malloc + * malloc area. + * if malloc succeeds + * fill area with nulls + * return ptr to malloc'd region + */ +#ifndef lint +static char rcs_header[] = "$Id: calloc.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $"; +#endif + +char * +calloc(nelem,elsize) + unsigned int nelem; + unsigned int elsize; +{ + char * malloc(); + char * memset(); + char * ptr; + unsigned int size; + + size = elsize * nelem; + + if( (ptr = malloc(size)) != NULL) + { + (void) memset(ptr,'\0',(int)size); + } + + return(ptr); +} + + +/* + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1997/09/22 14:51:10 hjs + * dmake 4.1 orginal sourcen + * + * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura + * dmake gold 4.1.00 initial import + * + * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura + * Dmake 4.1 Initial Import + * + * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura + * Initial import for final release of dmake 4.1 + * + * Revision 1.1 1994/10/06 17:43:08 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1994/10/06 03:45:17 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1992/01/24 03:28:58 dvadura + * dmake Version 3.8, Initial revision + * + * Revision 1.6 90/05/11 00:13:07 cpcahil + * added copyright statment + * + * Revision 1.5 90/02/24 20:41:57 cpcahil + * lint changes. + * + * Revision 1.4 90/02/24 17:25:47 cpcahil + * changed $header to $id so full path isn't included. + * + * Revision 1.3 90/02/24 13:32:24 cpcahil + * added function header. moved log to end of file. + * + * Revision 1.2 90/02/22 23:08:26 cpcahil + * fixed rcs_header line + * + * Revision 1.1 90/02/22 23:07:38 cpcahil + * Initial revision + * + */ diff --git a/dmake/dbug/malloc/debug.h b/dmake/dbug/malloc/debug.h new file mode 100644 index 000000000000..1a206d242936 --- /dev/null +++ b/dmake/dbug/malloc/debug.h @@ -0,0 +1,129 @@ +/* + * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). + * You may copy, distribute, and use this software as long as this + * copyright statement is not removed. + */ +/************************************************************************/ +/* */ +/* this include sets up some macro functions which can be used while */ +/* debugging the program, and then left in the code, but turned of by */ +/* just not defining "DEBUG". This way your production version of */ +/* the program will not be filled with bunches of debugging junk */ +/* */ +/************************************************************************/ +/* + * $Id: debug.h,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $ + */ + +#ifdef DEBUG + +#if DEBUG == 1 /* if default level */ +#undef DEBUG +#define DEBUG 100 /* use level 100 */ +#endif + +#include <stdio.h> + +#define DEBUG0(val,str)\ + {\ + if( DEBUG > val ) \ + fprintf(stderr,"%s(%d): %s\n",\ + __FILE__,__LINE__,str);\ + } +#define DEBUG1(val,str,a1)\ + {\ + char _debugbuf[100];\ + if( DEBUG > val )\ + {\ + sprintf(_debugbuf,str,a1);\ + fprintf(stderr,"%s(%d): %s\n",\ + __FILE__,__LINE__,_debugbuf);\ + }\ + } + +#define DEBUG2(val,str,a1,a2)\ + {\ + char _debugbuf[100];\ + if( DEBUG > val )\ + {\ + sprintf(_debugbuf,str,a1,a2);\ + fprintf(stderr,"%s(%d): %s\n",\ + __FILE__,__LINE__,_debugbuf);\ + }\ + } + +#define DEBUG3(val,str,a1,a2,a3)\ + {\ + char _debugbuf[100];\ + if( DEBUG > val )\ + {\ + sprintf(_debugbuf,str,a1,a2,a3);\ + fprintf(stderr,"%s(%d): %s\n",\ + __FILE__,__LINE__,_debugbuf);\ + }\ + } + +#define DEBUG4(val,str,a1,a2,a3,a4)\ + {\ + char _debugbuf[100];\ + if( DEBUG > val )\ + {\ + sprintf(_debugbuf,str,a1,a2,a3,a4);\ + fprintf(stderr,"%s(%d): %s\n",\ + __FILE__,__LINE__,_debugbuf);\ + }\ + } + +#define DEBUG5(val,str,a1,a2,a3,a4,a5)\ + {\ + char _debugbuf[100];\ + if( DEBUG > val )\ + {\ + sprintf(_debugbuf,str,a1,a2,a3,a4,a5);\ + fprintf(stderr,"%s(%d): %s\n",\ + __FILE__,__LINE__,_debugbuf);\ + }\ + } + +#else + +#define DEBUG0(val,s) +#define DEBUG1(val,s,a1) +#define DEBUG2(val,s,a1,a2) +#define DEBUG3(val,s,a1,a2,a3) +#define DEBUG4(val,s,a1,a2,a3,a4) +#define DEBUG5(val,s,a1,a2,a3,a4,a5) + +#endif /* DEBUG */ + + +/* + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1997/09/22 14:51:11 hjs + * dmake 4.1 orginal sourcen + * + * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura + * dmake gold 4.1.00 initial import + * + * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura + * Dmake 4.1 Initial Import + * + * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura + * Initial import for final release of dmake 4.1 + * + * Revision 1.1 1994/10/06 17:43:09 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1994/10/06 03:45:18 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1992/01/24 03:28:59 dvadura + * dmake Version 3.8, Initial revision + * + * Revision 1.2 90/05/11 00:13:08 cpcahil + * added copyright statment + * + * Revision 1.1 90/02/23 07:09:01 cpcahil + * Initial revision + * + */ diff --git a/dmake/dbug/malloc/dump.c b/dmake/dbug/malloc/dump.c new file mode 100644 index 000000000000..7ac79ccc884f --- /dev/null +++ b/dmake/dbug/malloc/dump.c @@ -0,0 +1,142 @@ +/* + * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). + * You may copy, distribute, and use this software as long as this + * copyright statement is not removed. + */ +#include <stdio.h> +#include "malloc.h" +#include "tostring.h" + +/* + * Function: malloc_dump() + * + * Purpose: to dump a printed copy of the malloc chain and + * associated data elements + * + * Arguments: fd - file descriptor to write data to + * + * Returns: nothing of any use + * + * Narrative: Just print out all the junk + * + * Notes: This function is implemented using low level calls because + * of the likelyhood that the malloc tree is damaged when it + * is called. (Lots of things in the c library use malloc and + * we don't want to get into a catch-22). + * + */ + +#ifndef lint +static +char rcs_hdr[] = "$Id: dump.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $"; +#endif + + +#define ERRSTR "I/O Error on malloc dump file descriptor\n" + +#define WRITEOUT(fd,str,len) if( write(fd,str,(unsigned)len) != len ) \ + { \ + (void) write(2,ERRSTR,\ + (unsigned)strlen(ERRSTR));\ + exit(120); \ + } + +void +malloc_dump(fd) + int fd; +{ + char buffer[512]; + void exit(); + int i; + extern char * malloc_data_end; + extern char * malloc_data_start; + extern struct mlist * malloc_end; + extern struct mlist malloc_start; + struct mlist * ptr; + + WRITEOUT(fd,"MALLOC CHAIN:\n",14); + WRITEOUT(fd,"-------------------- START ----------------\n",44); + + for(i=0; i < 80; i++) + { + buffer[i] = ' '; + } + + for(ptr = &malloc_start; ptr; ptr = ptr->next) + { + (void) tostring(buffer, (int)ptr, 8, B_HEX, '0'); + (void) tostring(buffer+9, (int)ptr->next, 8, B_HEX, '0'); + (void) tostring(buffer+18, (int)ptr->prev, 8, B_HEX, '0'); + (void) tostring(buffer+27, (int)ptr->flag, 10, B_HEX, '0'); + (void) tostring(buffer+38, (int)ptr->s.size, 8, B_DEC, ' '); + (void) tostring(buffer+47, (int)ptr->s.size, 8, B_HEX, '0'); + (void) tostring(buffer+57, (int)ptr->data, 8, B_HEX, '0'); + buffer[46] = '('; + buffer[55] = ')'; + buffer[65] = '\n'; + WRITEOUT(fd,buffer,66); + } + WRITEOUT(fd,"-------------------- DONE -----------------\n",44); + + WRITEOUT(fd,"Malloc start: ",19); + (void) tostring(buffer, (int) &malloc_start, 8, B_HEX, '0'); + buffer[8] = '\n'; + WRITEOUT(fd,buffer,9); + + WRITEOUT(fd,"Malloc end: ", 19); + (void) tostring(buffer, (int) malloc_end, 8, B_HEX, '0'); + buffer[8] = '\n'; + WRITEOUT(fd,buffer,9); + + WRITEOUT(fd,"Malloc data start: ", 19); + (void) tostring(buffer, (int) malloc_data_start, 8, B_HEX, '0'); + buffer[8] = '\n'; + WRITEOUT(fd,buffer,9); + + WRITEOUT(fd,"Malloc data end: ", 19); + (void) tostring(buffer, (int) malloc_data_end, 8, B_HEX, '0'); + buffer[8] = '\n'; + WRITEOUT(fd,buffer,9); + +} /* malloc_dump(... */ + + +/* + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1997/09/22 14:51:11 hjs + * dmake 4.1 orginal sourcen + * + * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura + * dmake gold 4.1.00 initial import + * + * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura + * Dmake 4.1 Initial Import + * + * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura + * Initial import for final release of dmake 4.1 + * + * Revision 1.1 1994/10/06 17:43:09 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1994/10/06 03:45:19 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1992/01/24 03:29:01 dvadura + * dmake Version 3.8, Initial revision + * + * Revision 1.5 90/08/29 21:22:37 cpcahil + * miscellaneous lint fixes + * + * Revision 1.4 90/05/11 00:13:08 cpcahil + * added copyright statment + * + * Revision 1.3 90/02/24 21:50:07 cpcahil + * lots of lint fixes + * + * Revision 1.2 90/02/24 17:27:48 cpcahil + * changed $header to $Id to remove full path from rcs id string + * + * Revision 1.1 90/02/22 23:17:43 cpcahil + * Initial revision + * + */ diff --git a/dmake/dbug/malloc/free.c b/dmake/dbug/malloc/free.c new file mode 100644 index 000000000000..5eb139d6fcb8 --- /dev/null +++ b/dmake/dbug/malloc/free.c @@ -0,0 +1,206 @@ +/* + * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). + * You may copy, distribute, and use this software as long as this + * copyright statement is not removed. + */ +#include <stdio.h> +#include "malloc.h" +#include "debug.h" + +/* + * Function: free() + * + * Purpose: to deallocate malloced data + * + * Arguments: ptr - pointer to data area to deallocate + * + * Returns: nothing of any value + * + * Narrative: + * verify pointer is within malloc region + * get mlist pointer from passed address + * verify magic number + * verify inuse flag + * verify pointer connections with surrounding segments + * turn off inuse flag + * verify no data overrun into non-malloced area at end of segment + * IF possible join segment with next segment + * IF possible join segment with previous segment + * Clear all data in segment (to make sure it isn't reused) + * + */ +#ifndef lint +static +char rcs_hdr[] = "$Id: free.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $"; +#endif + +void +free(cptr) + char * cptr; +{ + char * func = "free"; + int i; + extern int malloc_checking; + extern struct mlist * malloc_end; + extern int malloc_errno; + extern char * malloc_data_end; + extern char * malloc_data_start; + void malloc_join(); + void malloc_memset(); + struct mlist * oldptr; + struct mlist * ptr; + + /* + * IF malloc chain checking is on, go do it. + */ + if( malloc_checking ) + { + (void) malloc_chain_check(1); + } + + /* + * verify that cptr is within the malloc region... + */ + if( cptr < malloc_data_start || cptr > malloc_data_end ) + { + malloc_errno = M_CODE_BAD_PTR; + malloc_warning(func); + return; + } + + /* + * convert pointer to mlist struct pointer. To do this we must + * move the pointer backwards the correct number of bytes... + */ + + ptr = (struct mlist *) (cptr - M_SIZE); + + if( (ptr->flag&M_MAGIC) != M_MAGIC ) + { + malloc_errno = M_CODE_BAD_MAGIC; + malloc_warning(func); + return; + } + + if( ! (ptr->flag & M_INUSE) ) + { + malloc_errno = M_CODE_NOT_INUSE; + malloc_warning(func); + return; + } + + if( (ptr->prev && (ptr->prev->next != ptr) ) || + (ptr->next && (ptr->next->prev != ptr) ) || + ((ptr->next == NULL) && (ptr->prev == NULL)) ) + { + malloc_errno = M_CODE_BAD_CONNECT; + malloc_warning(func); + return; + } + + ptr->flag &= ~M_INUSE; + + /* + * verify that the user did not overrun the requested number of bytes. + */ + for(i=ptr->r_size; i < ptr->s.size; i++) + { + if( ptr->data[i] != M_FILL ) + { + malloc_errno = M_CODE_OVERRUN; + malloc_warning(func); + break; + } + } + + DEBUG3(10,"pointers: prev: 0x%.7x, ptr: 0x%.7x, next: 0x%.7x", + ptr->prev, ptr, ptr->next); + + DEBUG3(10,"size: prev: %9d, ptr: %9d, next: %9d", + ptr->prev->s.size, ptr->s.size, ptr->next->s.size); + + DEBUG3(10,"flags: prev: 0x%.7x, ptr: 0x%.7x, next: 0x%.7x", + ptr->prev->flag, ptr->flag, ptr->next->flag); + + /* + * check to see if this block can be combined with the next and/or + * previous block. Since it may be joined with the previous block + * we will save a pointer to the previous block and test to verify + * if it is joined (it's next ptr will no longer point to ptr). + */ + malloc_join(ptr,ptr->next,0,0); + + oldptr = ptr->prev; + + malloc_join(ptr->prev, ptr,0,0); + + if( oldptr->next != ptr ) + { + DEBUG0(10,"Oldptr was changed"); + ptr = oldptr; + } + + /* + * fill this block with '\02's to ensure that nobody is using a + * pointer to already freed data... + */ + malloc_memset(ptr->data,M_FREE_FILL,(int)ptr->s.size); + +} + +/* + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1997/09/22 14:51:11 hjs + * dmake 4.1 orginal sourcen + * + * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura + * dmake gold 4.1.00 initial import + * + * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura + * Dmake 4.1 Initial Import + * + * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura + * Initial import for final release of dmake 4.1 + * + * Revision 1.1 1994/10/06 17:43:10 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1994/10/06 03:45:19 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1992/01/24 03:29:02 dvadura + * dmake Version 3.8, Initial revision + * + * Revision 1.9 90/08/29 21:22:48 cpcahil + * miscellaneous lint fixes + * + * Revision 1.8 90/05/11 00:13:08 cpcahil + * added copyright statment + * + * Revision 1.7 90/02/25 11:00:18 cpcahil + * added support for malloc chain checking. + * + * Revision 1.6 90/02/24 21:50:18 cpcahil + * lots of lint fixes + * + * Revision 1.5 90/02/24 17:29:13 cpcahil + * changed $Header to $Id so full path wouldnt be included as part of rcs + * id string + * + * Revision 1.4 90/02/24 15:15:32 cpcahil + * 1. changed ALREADY_FREE errno to NOT_INUSE so that the same errno could + * be used by both free and realloc (since it was the same error). + * 2. fixed coding bug + * + * Revision 1.3 90/02/24 14:23:45 cpcahil + * fixed malloc_warning calls + * + * Revision 1.2 90/02/24 13:59:10 cpcahil + * added function header. + * Modified calls to malloc_warning/malloc_fatal to use new code error messages + * Added support for malloc_errno setting of error codes. + * + * Revision 1.1 90/02/22 23:17:43 cpcahil + * Initial revision + * + */ diff --git a/dmake/dbug/malloc/m_init.c b/dmake/dbug/malloc/m_init.c new file mode 100644 index 000000000000..cef558319340 --- /dev/null +++ b/dmake/dbug/malloc/m_init.c @@ -0,0 +1,121 @@ +/* + * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). + * You may copy, distribute, and use this software as long as this + * copyright statement is not removed. + */ +#include <stdio.h> +#include "malloc.h" + +/* + * Function: malloc_init() + * + * Purpose: to initialize the pointers and variables use by the + * malloc() debugging library + * + * Arguments: none + * + * Returns: nothing of any value + * + * Narrative: Just initialize all the needed variables. Use mallopt + * to set options taken from the environment. + * + */ +#ifndef lint +static +char rcs_hdr[] = "$Id: m_init.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $"; +#endif + +void +malloc_init() +{ + char * cptr; + char * getenv(); + union malloptarg m; + extern char * malloc_data_end; + extern char * malloc_data_start; + extern struct mlist * malloc_end; + extern struct mlist malloc_start; + char * sbrk(); + + /* + * If already initialized... + */ + if( malloc_data_start != (char *) 0) + { + return; + } + + + malloc_data_start = sbrk(0); + malloc_data_end = malloc_data_start; + malloc_start.s.size = 0; + malloc_end = &malloc_start; + + if( (cptr=getenv("MALLOC_WARN")) != NULL ) + { + m.i = atoi(cptr); + (void) mallopt(MALLOC_WARN,m); + } + + if( (cptr=getenv("MALLOC_FATAL")) != NULL) + { + m.i = atoi(cptr); + (void) mallopt(MALLOC_FATAL,m); + } + + if( (cptr=getenv("MALLOC_CKCHAIN")) != NULL) + { + m.i = atoi(cptr); + (void) mallopt(MALLOC_CKCHAIN,m); + } + + if( (cptr=getenv("MALLOC_ERRFILE")) != NULL) + { + m.str = cptr; + (void) mallopt(MALLOC_ERRFILE,m); + } + +} + +/* + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1997/09/22 14:51:11 hjs + * dmake 4.1 orginal sourcen + * + * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura + * dmake gold 4.1.00 initial import + * + * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura + * Dmake 4.1 Initial Import + * + * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura + * Initial import for final release of dmake 4.1 + * + * Revision 1.1 1994/10/06 17:43:11 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1994/10/06 03:45:20 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1992/01/24 03:29:03 dvadura + * dmake Version 3.8, Initial revision + * + * Revision 1.6 90/08/29 22:23:21 cpcahil + * fixed mallopt to use a union as an argument. + * + * Revision 1.5 90/08/29 21:22:50 cpcahil + * miscellaneous lint fixes + * + * Revision 1.4 90/05/11 15:53:35 cpcahil + * fixed bug in initialization code. + * + * Revision 1.3 90/05/11 00:13:08 cpcahil + * added copyright statment + * + * Revision 1.2 90/02/24 21:50:20 cpcahil + * lots of lint fixes + * + * Revision 1.1 90/02/24 17:10:53 cpcahil + * Initial revision + * + */ diff --git a/dmake/dbug/malloc/m_perror.c b/dmake/dbug/malloc/m_perror.c new file mode 100644 index 000000000000..ad582acea37c --- /dev/null +++ b/dmake/dbug/malloc/m_perror.c @@ -0,0 +1,111 @@ +/* + * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). + * You may copy, distribute, and use this software as long as this + * copyright statement is not removed. + */ + +#ifndef lint +static +char rcsid[] = "$Id: m_perror.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $"; +#endif + +/* + * malloc errno error strings... + */ + +char *malloc_err_strings[] = +{ + "No errors", + "Malloc chain is corrupted, pointers out of order", + "Malloc chain is corrupted, end before end pointer", + "Pointer is not within malloc area", + "Malloc region does not have valid magic number in header", + "Pointers between this segment and ajoining segments are invalid", + "Data has overrun beyond requested number of bytes", + "Data in free'd area has been modified", + "Data are is not in use (can't be freed or realloced)", + "Unable to get additional memory from the system", + "Pointer within malloc region, but outside of malloc data bounds", + (char *) 0 +}; + +/* + * Function: malloc_perror() + * + * Purpose: to print malloc_errno error message + * + * Arguments: str - string to print with error message + * + * Returns: nothing of any value + * + * Narrative: + */ +void +malloc_perror(str) + char * str; +{ + extern int malloc_errno; + register char * s; + register char * t; + + if( str && *str) + { + for(s=str; *s; s++) + { + /* do nothing */; + } + + (void) write(2,str,(unsigned)(s-str)); + (void) write(2,": ",(unsigned)2); + } + + t = malloc_err_strings[malloc_errno]; + + for(s=t; *s; s++) + { + /* do nothing */; + } + + (void) write(2,t,(unsigned)(s-t)); + + (void) write(2,"\n",(unsigned)1); +} + +/* + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1997/09/22 14:51:11 hjs + * dmake 4.1 orginal sourcen + * + * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura + * dmake gold 4.1.00 initial import + * + * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura + * Dmake 4.1 Initial Import + * + * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura + * Initial import for final release of dmake 4.1 + * + * Revision 1.1 1994/10/06 17:43:12 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1994/10/06 03:45:21 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1992/01/24 03:29:04 dvadura + * dmake Version 3.8, Initial revision + * + * Revision 1.5 90/08/29 21:25:08 cpcahil + * added additional error message that was missing (and + * caused a core dump) + * + * Revision 1.4 90/05/11 00:13:08 cpcahil + * added copyright statment + * + * Revision 1.3 90/02/24 21:50:21 cpcahil + * lots of lint fixes + * + * Revision 1.2 90/02/24 17:39:55 cpcahil + * 1. added function header + * 2. added rcs id and log strings. + * + */ diff --git a/dmake/dbug/malloc/makefile b/dmake/dbug/malloc/makefile new file mode 100644 index 000000000000..88395c7b8f6c --- /dev/null +++ b/dmake/dbug/malloc/makefile @@ -0,0 +1,77 @@ +# +# (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). +# You may copy, distribute, and use this software as long as this +# copyright statement is not removed. +# +# +# This is the Makefile for the malloc debugging library +# +# $Id: makefile,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $ +# +CC=cc +# for System V systems use this CFLAGS +#CFLAGS=-g -DSYS5 +# else for BSD use: +#CFLAGS=-g +LINT=lint +SHARCMD=shar -o mallocshar -l50 -x -a -n Malloclib +SHELL=/bin/sh + +LIB=libmalloc.a + +SRCS= malloc.c \ + free.c \ + realloc.c \ + calloc.c \ + string.c \ + mlc_chk.c \ + mlc_chn.c \ + memory.c \ + tostring.c \ + m_perror.c \ + m_init.c \ + mallopt.c \ + dump.c + +OBJS= malloc.o \ + free.o \ + realloc.o \ + calloc.o \ + string.o \ + mlc_chk.o \ + mlc_chn.o \ + memory.o \ + tostring.o \ + m_perror.o \ + m_init.o \ + mallopt.o \ + dump.o + +TESTS=testmlc testmem + +all: $(LIB) $(TESTS) + +clean: + rm -f $(TESTS) pgm $(LIB) *.o *.ln + +sharfile: + $(SHARCMD) Makefile README patchlevel *.[ch3] + +$(LIB): $(OBJS) + ar ru $(LIB) $(OBJS) + -if test -s /bin/ranlib; then /bin/ranlib $(LIB); else exit 0; fi + -if test -s /usr/bin/ranlib; then /usr/bin/ranlib $(LIB); else exit 0; fi + +testmlc: $(LIB) testmlc.o + $(CC) -o $@ testmlc.o $(LIB) + +testmem: $(LIB) testmem.o + $(CC) -o $@ testmem.o $(LIB) + +lint: + $(LINT) $(CFLAGS) $(SRCS) testmlc.c testmem.c + + +$(OBJS): malloc.h + +tostring.o malloc.o dump.o: tostring.h diff --git a/dmake/dbug/malloc/malloc.3 b/dmake/dbug/malloc/malloc.3 new file mode 100644 index 000000000000..f5e1d2dc0dab --- /dev/null +++ b/dmake/dbug/malloc/malloc.3 @@ -0,0 +1,223 @@ +.TH MALLOC 3 "" "" "1.0" +.ds ]T +.\"/* +.\" * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). +.\" * You may copy, distribute, and use this software as long as this +.\" * copyright statement is not removed. +.\" */ +.\" $Id: malloc.3,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $ +.SH NAME +malloc \t- debugging malloc library +.SH SYNOPSIS +.ft B +.nf +#include <malloc.h> + +char * calloc(nelem,elsize); +void free(ptr); +char * malloc(size); +int malloc_chain_check(flag); +void malloc_dump(fd); +int mallopt(cmd,val) +char * realloc(ptr,size); + +int cmd,fd,flag; +unsigned elsize,nelem,size; +char * ptr; +union malloptarg val; + +.fi +.ft R +.SH DESCRIPTION +This malloc library is a replacement for the standard library to be used +during software development/debugging. See the standard malloc(3) pages +for more information on the use of the following functions: +.nf +.in +.5i +calloc(), free(), malloc(), realloc() +.in -.5i +.fi +.sp +This library differs from the standard malloc library in the +following ways: +.P +1. Each malloc segment contains a magic number so that free can +verify that the pointer passed points to a valid malloc segment. +.P +2. Each malloc segment is filled with a non-zero pattern so that code that +depends upon malloc segments being null will fail. +.P +3. The size of each segment will be at least 1 byte larger than requested +and the extra bytes will be filled with a non-zero pattern. When free is +called, it will verify that you did not go beyond the number of bytes +you asked for. +.P +4. When a segment is freed, it will be filled with a different non-zero pattern +to ensure that the program doesn't depend upon the use of already freed data. +.P +5. Whenever any of the string or memory functions (str*, b*, mem*) are +called with a pointer that is within the malloc arena, the operation is +checked to verify that it does not overrun the malloced segment. A failure +of this check is considered a "warning level error" (described later) and +is handled accordingly. +.P +7. Run time checking can include verification of the malloc chain at each +and every call to one of the malloc functions or manually by calling the +malloc_chain_check function. +.P +6. When a problem is found, the action taken is specified at runtime by +environment variables or at compile time by the use of the mallopt() +function. +.P +There are two arbitrary levels of errors, warning and fatal, that this +library will detect. They are broken down as follows: +.P +.nf +.in +.25i +Warning messages include: +.sp +.in +.5i +.ti -.25i +Calling free with a bad pointer +.br +.ti -.25i +Calling a bstring/string/memory (3) function which will go beyond +the end of a malloc block. Note that the library function is +not modified to refuse the operation. +.sp +.in -.5i +Fatal errors are: +.in +.5i +.ti -.25i +Detectable corruption to the malloc chain. +.in -.5i +.in -.25i +.P +The error handling for each level (warning or fatal) are specified using +environment variables or mallopt(). The coding for the error handling is +as follows: +.sp +.nf +.in +.5i +.ti -.25i + 0 - continue operations +.ti -.25i + 1 - drop core and exit +.ti -.25i + 2 - just exit +.ti -.25i + 3 - drop core, but continue executing. Core files will +be placed into core.[PID].[counter] i.e: core.00123.001 +.ti -.25i +128 - dump malloc chain and continue +.ti -.25i +129 - dump malloc chain, dump core, and exit +.ti -.25i +130 - dump malloc chain, exit +.ti -.25i +131 - dump malloc chain, dump core, continue processing +.in -.5i +.P +In addition error messages can be placed into an error file. +.P +\fBmalloc_opt\fP() is used to set the malloc debugging options. The +following options can be set: +.br +.sp +.in +.5i +MALLOC_WARN - set the error handling for warning level errors. \fBval.i\fP is +an integer that can contain any one of the following values: +.sp +.in +.5i +M_HANDLE_IGNORE - ignore error +.br +M_HANDLE_ABORT - drop core and exit +.br +M_HANDLE_EXIT - just exit (no core drop) +.br +M_HANDLE_CORE - drop core, but keep on going +.br +.in -.5i +.sp +In addition, M_HANDLE_DUMP may be or'd in to cause a dump of the current +malloc chain. +.br +.sp +MALLOC_FATAL - set the error handling for fatal level errors. \fBval.i\fP is +equivalent to \fBval.i\fP for MALLOC_WARN. +.br +.sp +MALLOC_ERRFILE - set the destination for malloc error messages. \fBval.str\fP +is a pointer to a character string containing the name of the file to be used +for error messages. +.br +.sp +MALLOC_CKCHAIN - set the malloc chain checking flag. If \fBval.i\fP is +non-zero, chain checking at every call to malloc is turned on. +.br +.sp +For example, to set up the session to generate a core file for +every malloc warning, to drop core and exit on a malloc fatal, and +to log all messages to the file "malloc_log" do the following: +.sp +.nf +.in +.5i +#include <malloc.h> +malloc_opt(MALLOC_WARN,131); +malloc_opt(MALLOC_FATAL,1); +malloc_opt(MALLOC_ERRFILE,"malloc_log"); +.in -.5i +.fi +.in -.5i +.sp +\fBmalloc_opt\fP() can be used to set/alter the debugging options at any +time. +.P +\fBmalloc_dump\fP() will dump a table of the malloc arena showing all +allocated/freed segments and the first few bytes of data in each segment. +\fBfd\fP is the file descriptor to write the data to. +.P +\fBmalloc_chain_check\fP() will check the status of the malloc arena. +If \fBflag\fP is non-zero, an error found in the chain will cause a +fatal error. \fBmalloc_chain_check\fP() returns zero when there are no +problems found in the malloc chain, non-zero otherwise. +.SH "ENVIRONMENT VARIABLES" +Environment variables can be used to control error handling, error logging +and malloc chain checking at run time. The following environment variables +are used: +.P +MALLOC_WARN - specifies the error handling for warning errors +.br +MALLOC_FATAL - specifies the error handling for fatal errors +.br +MALLOC_ERRFILE - specifies the error log file for error messages. +.br +MALLOC_CKCHAIN - if 1, turns on malloc chain checking at every call to any +of the malloc functions. +.P +For example, to set up the session to generate a core file for +every malloc warning, to drop core and exit on a malloc fatal, and +to log all messages to the file "malloc_log" do the following: +.sp +.nf +.in +.5i +MALLOC_WARN=131 +MALLOC_FATAL=1 +MALLOC_ERRFILE=malloc_log + +export MALLOC_WARN MALLOC_FATAL MALLOC_ERRFILE +.in -.5i +.fi +.SH WARNINGS +This malloc library and it's associated string and memory functions are +much less efficient than the standard functions due in part to the extra +error checking. You do not want to use this library when generating a +production (i.e. releasable) version of your software. It should only +be used during development and testing. +.SH SEE ALSO +stat(2) +.SH AUTHOR +Conor P. Cahill +Virtual Technologies Incorporated +.sp +uunet!virtech!cpcahil diff --git a/dmake/dbug/malloc/malloc.c b/dmake/dbug/malloc/malloc.c new file mode 100644 index 000000000000..e2f060f1d0ac --- /dev/null +++ b/dmake/dbug/malloc/malloc.c @@ -0,0 +1,672 @@ +/* + * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). + * You may copy, distribute, and use this software as long as this + * copyright statement is not removed. + */ +#include <stdio.h> +#include <fcntl.h> +#include "malloc.h" +#include "tostring.h" + +/* + * Function: malloc() + * + * Purpose: memory allocator + * + * Arguments: size - size of data area needed + * + * Returns: pointer to allocated area, or NULL if unable + * to allocate addtional data. + * + * Narrative: + * + */ +#ifndef lint +static +char rcs_hdr[] = "$Id: malloc.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $"; +#endif + +extern int malloc_checking; +char * malloc_data_start; +char * malloc_data_end; +struct mlist * malloc_end; +int malloc_errfd = 2; +int malloc_errno; +int malloc_fatal_level = M_HANDLE_CORE; +struct mlist malloc_start; +int malloc_warn_level; +void malloc_memset(); + +char * +malloc(size) + unsigned int size; +{ + char * func = "malloc"; + char * getenv(); + void malloc_fatal(); + void malloc_init(); + void malloc_split(); + void malloc_warning(); + unsigned int need; + struct mlist * oldptr; + struct mlist * ptr; + char * sbrk(); + + /* + * If this is the first call to malloc... + */ + if( malloc_data_start == (char *) 0 ) + { + malloc_init(); + } + + /* + * If malloc chain checking is on, go do it. + */ + if( malloc_checking ) + { + (void) malloc_chain_check(1); + } + + /* + * always make sure there is at least on extra byte in the malloc + * area so that we can verify that the user does not overrun the + * data area. + */ + size++; + + /* + * Now look for a free area of memory of size bytes... + */ + oldptr = NULL; + for(ptr = &malloc_start; ; ptr = ptr->next) + { + /* + * Since the malloc chain is a forward only chain, any + * pointer that we get should always be positioned in + * memory following the previous pointer. If this is not + * so, we must have a corrupted chain. + */ + if( ptr ) + { + if( ptr<oldptr ) + { + malloc_errno = M_CODE_CHAIN_BROKE; + malloc_fatal(func); + return(NULL); + } + oldptr = ptr; + } + else if( oldptr != malloc_end ) + { + /* + * This should never happen. If it does, then + * we got a real problem. + */ + malloc_errno = M_CODE_NO_END; + malloc_fatal(func); + return(NULL); + } + + + /* + * if this element is already in use... + */ + if( ptr && ((ptr->flag & M_INUSE) != 0) ) + { + continue; + } + + /* + * if there isn't room for this block.. + */ + if( ptr && (ptr->s.size < size) ) + { + continue; + } + + /* + * If ptr is null, we have run out of memory and must sbrk more + */ + if( ptr == NULL ) + { + need = (size + M_SIZE) * (size > 10*1024 ? 1:2); + if( need < M_BLOCKSIZE ) + { + need = M_BLOCKSIZE; + } + else if( need & (M_BLOCKSIZE-1) ) + { + need &= ~(M_BLOCKSIZE-1); + need += M_BLOCKSIZE; + } + ptr = (struct mlist *) sbrk((int)need); + if( ptr == (struct mlist *) -1 ) + { + malloc_errno = M_CODE_NOMORE_MEM; + malloc_fatal(func); + } + malloc_data_end = sbrk((int)0); + + ptr->prev = oldptr; + ptr->next = (struct mlist *) 0; + ptr->s.size = need - M_SIZE; + ptr->flag = M_MAGIC; + + oldptr->next = ptr; + malloc_end = ptr; + + + } /* if( ptr ==... */ + + /* + * Now ptr points to a memory location that can store + * this data, so lets go to work. + */ + + ptr->r_size = size; /* save requested size */ + ptr->flag |= M_INUSE; + + /* + * split off unneeded data area in this block, if possible... + */ + malloc_split(ptr); + + /* + * re-adjust the requested size so that it is what the user + * actually requested... + */ + + ptr->r_size--; + + /* + * just to make sure that noone is misusing malloced + * memory without initializing it, lets set it to + * all '\01's. We call local_memset() because memset() + * may be checking for malloc'd ptrs and this isn't + * a malloc'd ptr yet. + */ + malloc_memset(ptr->data,M_FILL,(int)ptr->s.size); + + return( ptr->data); + + } /* for(... */ + +} /* malloc(... */ + +/* + * Function: malloc_split() + * + * Purpose: to split a malloc segment if there is enough room at the + * end of the segment that isn't being used + * + * Arguments: ptr - pointer to segment to split + * + * Returns: nothing of any use. + * + * Narrative: + * get the needed size of the module + * round the size up to appropriat boundry + * calculate amount of left over space + * if there is enough left over space + * create new malloc block out of remainder + * if next block is free + * join the two blocks together + * fill new empty block with free space filler + * re-adjust pointers and size of current malloc block + * + * + * + * Mod History: + * 90/01/27 cpcahil Initial revision. + */ +void +malloc_split(ptr) + struct mlist * ptr; +{ + extern struct mlist * malloc_end; + void malloc_join(); + int rest; + int size; + struct mlist * tptr; + + size = ptr->r_size; + + /* + * roundup size to the appropriate boundry + */ + + M_ROUNDUP(size); + + /* + * figure out how much room is left in the array. + * if there is enough room, create a new mlist + * structure there. + */ + + if( ptr->s.size > size ) + { + rest = ptr->s.size - size; + } + else + { + rest = 0; + } + + if( rest > (M_SIZE+M_RND) ) + { + tptr = (struct mlist *) (ptr->data+size); + tptr->prev = ptr; + tptr->next = ptr->next; + tptr->flag = M_MAGIC; + tptr->s.size = rest - M_SIZE; + + /* + * If possible, join this segment with the next one + */ + + malloc_join(tptr, tptr->next,0,0); + + if( tptr->next ) + { + tptr->next->prev = tptr; + } + + malloc_memset(tptr->data,M_FREE_FILL, (int)tptr->s.size); + + ptr->next = tptr; + ptr->s.size = size; + + if( malloc_end == ptr ) + { + malloc_end = tptr; + } + } + +} /* malloc_split(... */ + +/* + * Function: malloc_join() + * + * Purpose: to join two malloc segments together (if possible) + * + * Arguments: ptr - pointer to segment to join to. + * nextptr - pointer to next segment to join to ptr. + * + * Returns: nothing of any values. + * + * Narrative: + * + * Mod History: + * 90/01/27 cpcahil Initial revision. + */ +void +malloc_join(ptr,nextptr, inuse_override, fill_flag) + struct mlist * ptr; + struct mlist * nextptr; + int inuse_override; + int fill_flag; +{ + unsigned int newsize; + + if( ptr && ! (inuse_override || (ptr->flag & M_INUSE)) && + nextptr && ! (nextptr->flag & M_INUSE) && + ((ptr->data+ptr->s.size) == (char *) nextptr) ) + { + if( malloc_end == nextptr ) + { + malloc_end = ptr; + } + ptr->next = nextptr->next; + newsize = nextptr->s.size + M_SIZE; + + /* + * if we are to fill and this segment is in use, + * fill in with M_FILL newly added space... + */ + + if(fill_flag && (ptr->flag & M_INUSE) ) + { + malloc_memset(ptr->data+ptr->s.size, + M_FILL, (int)(nextptr->s.size + M_SIZE)); + } + + ptr->s.size += newsize; + if( ptr->next ) + { + ptr->next->prev = ptr; + } + } + +} /* malloc_join(... */ + + +/* + * The following mess is just to ensure that the versions of these functions in + * the current library are included (to make sure that we don't accidentaly get + * the libc versions. (This is the lazy man's -u ld directive) + */ + +void free(); +int strcmp(); +int memcmp(); +char * realloc(); + +void (*malloc_void_funcs[])() = +{ + free, +}; + +int (*malloc_int_funcs[])() = +{ + strcmp, + memcmp, +}; + +char * (*malloc_char_star_funcs[])() = +{ + realloc, +}; + +/* + * This is malloc's own memset which is used without checking the parameters. + */ + +void +malloc_memset(ptr,byte,len) + char * ptr; + char byte; + int len; +{ + + while(len-- > 0) + { + *ptr++ = byte; + } + +} /* malloc_memset(... */ + +/* + * Function: malloc_fatal() + * + * Purpose: to display fatal error message and take approrpriate action + * + * Arguments: funcname - name of function calling this routine + * + * Returns: nothing of any value + * + * Narrative: + * + * Notes: This routine does not make use of any libc functions to build + * and/or disply the error message. This is due to the fact that + * we are probably at a point where malloc is having a real problem + * and we don't want to call any function that may use malloc. + */ +void +malloc_fatal(funcname) + char * funcname; +{ + char errbuf[128]; + void exit(); + void malloc_err_handler(); + extern char * malloc_err_strings[]; + extern int malloc_errno; + extern int malloc_fatal_level; + char * s; + char * t; + + s = errbuf; + t = "Fatal error: "; + while( *s = *t++) + { + s++; + } + t = funcname; + while( *s = *t++) + { + s++; + } + + t = "(): "; + while( *s = *t++) + { + s++; + } + + t = malloc_err_strings[malloc_errno]; + while( *s = *t++) + { + s++; + } + + *(s++) = '\n'; + + if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf)) + { + (void) write(2,"I/O error to error file\n",(unsigned)24); + exit(110); + } + malloc_err_handler(malloc_fatal_level); + +} /* malloc_fatal(... */ + +/* + * Function: malloc_warning() + * + * Purpose: to display warning error message and take approrpriate action + * + * Arguments: funcname - name of function calling this routine + * + * Returns: nothing of any value + * + * Narrative: + * + * Notes: This routine does not make use of any libc functions to build + * and/or disply the error message. This is due to the fact that + * we are probably at a point where malloc is having a real problem + * and we don't want to call any function that may use malloc. + */ +void +malloc_warning(funcname) + char * funcname; +{ + char errbuf[128]; + void exit(); + void malloc_err_handler(); + extern char * malloc_err_strings[]; + extern int malloc_errno; + extern int malloc_warn_level; + char * s; + char * t; + + s = errbuf; + t = "Warning: "; + while( *s = *t++) + { + s++; + } + t = funcname; + while( *s = *t++) + { + s++; + } + + t = "(): "; + while( *s = *t++) + { + s++; + } + + t = malloc_err_strings[malloc_errno]; + while( *s = *t++) + { + s++; + } + + *(s++) = '\n'; + + if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf)) + { + (void) write(2,"I/O error to error file\n",(unsigned)24); + exit(110); + } + + malloc_err_handler(malloc_warn_level); + +} /* malloc_warning(... */ + +/* + * Function: malloc_err_handler() + * + * Purpose: to take the appropriate action for warning and/or fatal + * error conditions. + * + * Arguments: level - error handling level + * + * Returns: nothing of any value + * + * Narrative: + * + * Notes: This routine does not make use of any libc functions to build + * and/or disply the error message. This is due to the fact that + * we are probably at a point where malloc is having a real problem + * and we don't want to call any function that may use malloc. + */ +void +malloc_err_handler(level) +{ + void exit(); + void malloc_dump(); + extern int malloc_errfd; + + if( level & M_HANDLE_DUMP ) + { + malloc_dump(malloc_errfd); + } + + switch( level & ~M_HANDLE_DUMP ) + { + /* + * If we are to drop a core file and exit + */ + case M_HANDLE_ABORT: + (void) abort(); + break; + + /* + * If we are to exit.. + */ + case M_HANDLE_EXIT: + exit(200); + break; + +#ifndef __MSDOS__ + /* + * If we are to dump a core, but keep going on our merry way + */ + case M_HANDLE_CORE: + { + int pid; + + /* + * fork so child can abort (and dump core) + */ + if( (pid = fork()) == 0 ) + { + (void) write(2,"Child dumping core\n", + (unsigned)9); + (void) abort(); + } + + /* + * wait for child to finish dumping core + */ + while( wait((int *)0) != pid) + { + } + + /* + * Move core file to core.pid.cnt so + * multiple cores don't overwrite each + * other. + */ + if( access("core",0) == 0 ) + { + static int corecnt; + char filenam[32]; + filenam[0] = 'c'; + filenam[1] = 'o'; + filenam[2] = 'r'; + filenam[3] = 'e'; + filenam[4] = '.'; + (void)tostring(filenam+5,getpid(), + 5, B_DEC, '0'); + filenam[10] = '.'; + (void)tostring(filenam+11,corecnt++, + 3, B_DEC, '0'); + filenam[14] = '\0'; + (void) unlink(filenam); + if( link("core",filenam) == 0) + { + (void) unlink("core"); + } + } + } +#endif + + + /* + * If we are to just ignore the error and keep on processing + */ + case M_HANDLE_IGNORE: + break; + + } /* switch(... */ + +} /* malloc_err_handler(... */ + +/* + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1997/09/22 14:51:11 hjs + * dmake 4.1 orginal sourcen + * + * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura + * dmake gold 4.1.00 initial import + * + * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura + * Dmake 4.1 Initial Import + * + * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura + * Initial import for final release of dmake 4.1 + * + * Revision 1.1 1994/10/06 17:43:12 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1994/10/06 03:45:22 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1992/01/24 03:29:05 dvadura + * dmake Version 3.8, Initial revision + * + * Revision 1.6 90/05/11 00:13:09 cpcahil + * added copyright statment + * + * Revision 1.5 90/02/25 11:01:18 cpcahil + * added support for malloc chain checking. + * + * Revision 1.4 90/02/24 21:50:21 cpcahil + * lots of lint fixes + * + * Revision 1.3 90/02/24 14:51:18 cpcahil + * 1. changed malloc_fatal and malloc_warn to use malloc_errno and be passed + * the function name as a parameter. + * 2. Added several function headers. + * 3. Changed uses of malloc_fatal/warning to conform to new usage. + * + * Revision 1.2 90/02/23 18:05:23 cpcahil + * fixed open of error log to use append mode. + * + * Revision 1.1 90/02/22 23:17:43 cpcahil + * Initial revision + * + */ diff --git a/dmake/dbug/malloc/malloc.h b/dmake/dbug/malloc/malloc.h new file mode 100644 index 000000000000..0f34d49e1b72 --- /dev/null +++ b/dmake/dbug/malloc/malloc.h @@ -0,0 +1,121 @@ +/* + * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). + * You may copy, distribute, and use this software as long as this + * copyright statement is not removed. + */ +/* + * $Id: malloc.h,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $ + */ +struct mlist +{ + struct mlist * next; /* next entry in chain */ + struct mlist * prev; /* prev entry in chain */ + int flag; /* inuse flag */ + unsigned int r_size; /* requested size */ + union + { + unsigned int size; /* actual size */ + double unused_just_for_alignment; + } s; + char data[4]; +}; + +#define M_SIZE ((int)(char *)((struct mlist *)0)->data) +#define M_RND 0x08 + +#define M_INUSE 0x01 +#define M_MAGIC 0x03156100 + +#define M_BLOCKSIZE (1024*8) + +#define M_FILL '\01' +#define M_FREE_FILL '\02' + +#define M_ROUNDUP(size) {\ + if( size & (M_RND-1) ) \ + { \ + size &= ~(M_RND-1); \ + size += M_RND; \ + } \ + } + +/* + * Malloc warning/fatal error handler defines... + */ +#define M_HANDLE_DUMP 0x80 /* 128 */ +#define M_HANDLE_IGNORE 0 +#define M_HANDLE_ABORT 1 +#define M_HANDLE_EXIT 2 +#define M_HANDLE_CORE 3 + +/* + * Mallopt commands and defaults + */ + +#define MALLOC_WARN 1 /* set malloc warning handling */ +#define MALLOC_FATAL 2 /* set malloc fatal handling */ +#define MALLOC_ERRFILE 3 /* specify malloc error file */ +#define MALLOC_CKCHAIN 4 /* turn on chain checking */ +union malloptarg +{ + int i; + char * str; +}; + +/* + * Malloc warning/fatal error codes + */ + +#define M_CODE_CHAIN_BROKE 1 /* malloc chain is broken */ +#define M_CODE_NO_END 2 /* chain end != endptr */ +#define M_CODE_BAD_PTR 3 /* pointer not in malloc area */ +#define M_CODE_BAD_MAGIC 4 /* bad magic number in header */ +#define M_CODE_BAD_CONNECT 5 /* chain poingers corrupt */ +#define M_CODE_OVERRUN 6 /* data overrun in malloc seg */ +#define M_CODE_REUSE 7 /* reuse of freed area */ +#define M_CODE_NOT_INUSE 8 /* pointer is not in use */ +#define M_CODE_NOMORE_MEM 9 /* no more memory available */ +#define M_CODE_OUTOF_BOUNDS 10 /* gone beyound bounds */ + +void malloc_warning(); +void malloc_fatal(); +void malloc_check_data(); +void malloc_check_str(); +void malloc_verify(); + +/* + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1997/09/22 14:51:11 hjs + * dmake 4.1 orginal sourcen + * + * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura + * dmake gold 4.1.00 initial import + * + * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura + * Dmake 4.1 Initial Import + * + * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura + * Initial import for final release of dmake 4.1 + * + * Revision 1.1 1994/10/06 17:43:13 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1994/10/06 03:45:22 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1992/01/24 03:29:06 dvadura + * dmake Version 3.8, Initial revision + * + * Revision 1.4 90/08/29 22:23:38 cpcahil + * fixed mallopt to use a union as an argument. + * + * Revision 1.3 90/05/11 11:04:10 cpcahil + * took out some extraneous lines + * + * Revision 1.2 90/05/11 00:13:09 cpcahil + * added copyright statment + * + * Revision 1.1 90/02/23 07:09:03 cpcahil + * Initial revision + * + */ diff --git a/dmake/dbug/malloc/mallopt.c b/dmake/dbug/malloc/mallopt.c new file mode 100644 index 000000000000..a3151d4730ac --- /dev/null +++ b/dmake/dbug/malloc/mallopt.c @@ -0,0 +1,143 @@ +/* + * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). + * You may copy, distribute, and use this software as long as this + * copyright statement is not removed. + */ +#include <stdio.h> +#include <fcntl.h> +#include "malloc.h" + +/* + * Function: mallopt() + * + * Purpose: to set options for the malloc debugging library + * + * Arguments: none + * + * Returns: nothing of any value + * + * Narrative: + * + */ + +#ifndef lint +static +char rcs_hdr[] = "$Id: mallopt.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $"; +#endif + +int +mallopt(cmd,value) + int cmd; + union malloptarg value; +{ + int i; + extern int malloc_checking; + extern char * malloc_data_start; + extern int malloc_errfd; + extern int malloc_fatal_level; + void malloc_init(); + extern int malloc_warn_level; + register char * s; + + /* + * If not initialized... + */ + if( malloc_data_start == (char *) 0) + { + malloc_init(); + } + + + switch(cmd) + { + case MALLOC_WARN: + malloc_warn_level = value.i; + break; + + case MALLOC_FATAL: + malloc_fatal_level = value.i; + break; + + case MALLOC_CKCHAIN: + malloc_checking = value.i; + break; + + case MALLOC_ERRFILE: + + i = open(value.str,O_CREAT|O_APPEND|O_WRONLY,0666); + if( i == -1 ) + { + (void) write(2, + "Unable to open malloc error file: ", + (unsigned) 34); + for(s=value.str; *s; s++) + { + /* do nothing */; + } + (void) write(2,value.str, + (unsigned)(s-value.str)); + (void) write(2,"\n",(unsigned)1); + } + else + { + if( malloc_errfd != 2 ) + { + (void) close(malloc_errfd); + } + malloc_errfd = i; + } + + break; + + default: + return(1); + } + + return(0); +} + +/* + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1997/09/22 14:51:11 hjs + * dmake 4.1 orginal sourcen + * + * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura + * dmake gold 4.1.00 initial import + * + * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura + * Dmake 4.1 Initial Import + * + * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura + * Initial import for final release of dmake 4.1 + * + * Revision 1.1 1994/10/06 17:43:14 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1994/10/06 03:45:23 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1992/01/24 03:29:07 dvadura + * dmake Version 3.8, Initial revision + * + * Revision 1.6 90/08/29 22:23:36 cpcahil + * fixed mallopt to use a union as an argument. + * + * Revision 1.5 90/08/29 21:22:51 cpcahil + * miscellaneous lint fixes + * + * Revision 1.4 90/05/11 00:13:10 cpcahil + * added copyright statment + * + * Revision 1.3 90/02/25 11:03:26 cpcahil + * changed to return int so that it agrees with l libmalloc.a's mallopt() + * + * Revision 1.2 90/02/25 11:01:21 cpcahil + * added support for malloc chain checking. + * + * Revision 1.1 90/02/24 21:50:24 cpcahil + * Initial revision + * + * Revision 1.1 90/02/24 17:10:53 cpcahil + * Initial revision + * + */ diff --git a/dmake/dbug/malloc/memory.c b/dmake/dbug/malloc/memory.c new file mode 100644 index 000000000000..986007b1b77f --- /dev/null +++ b/dmake/dbug/malloc/memory.c @@ -0,0 +1,243 @@ +/* + * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). + * You may copy, distribute, and use this software as long as this + * copyright statement is not removed. + */ + +#ifndef lint +static +char rcs_hdr[] = "$Id: memory.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $"; +#endif + +void malloc_check_data(); + +char * +memccpy(ptr1, ptr2, ch, len) + register char * ptr1; + register char * ptr2; + int len; + int ch; +{ + int check; + register int i; + char * rtn; + + /* + * I know that the assignment could be done in the following, but + * I wanted to perform a check before any assignment, so first I + * determine the length, check the pointers and then do the assignment. + */ + for( i=0; (i < len) && (ptr2[i] != ch); i++) + { + } + if( ptr2[i] == ch ) + { + check = i+1; + } + else + { + check = len; + } + + malloc_check_data("memccpy", ptr1, check); + malloc_check_data("memccpy", ptr2, check); + + /* + * if we found the character... + */ + + if( i < len ) + { + rtn = ptr1+i+1; + i++; + } + else + { + rtn = (char *) 0; + } + + while( i-- ) + { + *(ptr1++) = *(ptr2++); + } + + return(rtn); +} + +char * +memchr(ptr1,ch,len) + register char * ptr1; + register int ch; + int len; +{ + int i; + + for( i=0; (i < len) && (ptr1[i] != (char) ch); i++) + { + } + + malloc_check_data("memchr", ptr1, i); + + if( i < len ) + { + return( ptr1+i ); + } + else + { + return( (char *) 0); + } +} + +char * +memcpy(ptr1, ptr2, len) + register char * ptr1; + register char * ptr2; + register int len; +{ + char * rtn = ptr1; + + malloc_check_data("memcpy", ptr1, len); + malloc_check_data("memcpy", ptr2, len); + + /* + * while the normal memcpy does not guarrantee that it will + * handle overlapping memory correctly, we will try... + */ + if( ptr1 > ptr2 && ptr1 < (ptr2+len)) + { + ptr1 += (len-1); + ptr2 += (len-1); + while( len-- > 0 ) + { + *(ptr1--) = *(ptr2--); + } + } + else + { + while( len-- > 0 ) + { + *(ptr1++) = *(ptr2++); + } + } + + return(rtn); +} + +int +memcmp(ptr1, ptr2, len) + register char * ptr1; + register char * ptr2; + register int len; +{ + malloc_check_data("memcpy", ptr1, len); + malloc_check_data("memcpy", ptr2, len); + + while( --len >= 0 && (*ptr1 == *ptr2) ) + { + ptr1++; + ptr2++; + } + + /* + * If stopped by len, return zero + */ + if( len < 0 ) + { + return(0); + } + + return( *ptr1 - *ptr2 ); +} + +char * +memset(ptr1, ch, len) + register char * ptr1; + register int ch; + register int len; +{ + char * rtn = ptr1; + + malloc_check_data("memcpy", ptr1, len); + + while( len-- ) + { + *(ptr1++) = ch; + } + + return(rtn); +} + +char * +bcopy(ptr2,ptr1,len) + char * ptr2; + char * ptr1; + int len; +{ + return(memcpy(ptr1,ptr2,len)); +} + +char * +bzero(ptr1,len) + char * ptr1; + int len; +{ + return(memset(ptr1,'\0',len)); +} + +int +bcmp(ptr2, ptr1, len) + char * ptr1; + char * ptr2; + int len; +{ + return( memcmp(ptr1,ptr2,len) ); +} + +/* + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1997/09/22 14:51:11 hjs + * dmake 4.1 orginal sourcen + * + * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura + * dmake gold 4.1.00 initial import + * + * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura + * Dmake 4.1 Initial Import + * + * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura + * Initial import for final release of dmake 4.1 + * + * Revision 1.1 1994/10/06 17:43:14 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1994/10/06 03:45:23 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1992/01/24 03:29:08 dvadura + * dmake Version 3.8, Initial revision + * + * Revision 1.7 90/08/29 21:27:58 cpcahil + * fixed value of check in memccpy when character was not found. + * + * Revision 1.6 90/07/16 20:06:26 cpcahil + * fixed several minor bugs found with Henry Spencer's string/mem tester + * program. + * + * + * Revision 1.5 90/05/11 15:39:36 cpcahil + * fixed bug in memccpy(). + * + * Revision 1.4 90/05/11 00:13:10 cpcahil + * added copyright statment + * + * Revision 1.3 90/02/24 21:50:29 cpcahil + * lots of lint fixes + * + * Revision 1.2 90/02/24 17:29:41 cpcahil + * changed $Header to $Id so full path wouldnt be included as part of rcs + * id string + * + * Revision 1.1 90/02/22 23:17:43 cpcahil + * Initial revision + * + */ diff --git a/dmake/dbug/malloc/mlc_chk.c b/dmake/dbug/malloc/mlc_chk.c new file mode 100644 index 000000000000..077e675240bf --- /dev/null +++ b/dmake/dbug/malloc/mlc_chk.c @@ -0,0 +1,297 @@ +/* + * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). + * You may copy, distribute, and use this software as long as this + * copyright statement is not removed. + */ + +#include <stdio.h> +#include "malloc.h" +#include "debug.h" + +#ifndef lint +static +char rcs_hdr[] = "$Id: mlc_chk.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $"; +#endif + +extern struct mlist malloc_start; +extern struct mlist * malloc_end; +extern char * malloc_data_start; +extern char * malloc_data_end; + +/* + * Function: malloc_in_arena() + * + * Purpose: to verify address is within malloc arena. + * + * Arguments: ptr - pointer to verify + * + * Returns: TRUE - if pointer is within malloc area + * FALSE - otherwise + * + * Narrative: + * IF pointer is >= malloc area start AND <= malloc area end + * return TRUE + * ELSE + * return FALSE + * + * Mod History: + * 90/01/24 cpcahil Initial revision. + */ +int +malloc_in_arena(ptr) + char * ptr; +{ + extern char * malloc_data_start; + extern char * malloc_data_end; + int rtn = 0; + + if( ptr >= malloc_data_start && ptr <= malloc_data_end ) + { + rtn = 1; + } + + return(rtn); +} + +/* + * Function: malloc_check_str() + * + * Arguments: func - name of function calling this routine + * str - pointer to area to check + * + * Purpose: to verify that if str is within the malloc arena, the data + * it points to does not extend beyond the applicable region. + * + * Returns: Nothing of any use (function is void). + * + * Narrative: + * IF pointer is within malloc arena + * determin length of string + * call malloc_verify() to verify data is withing applicable region + * return + * + * Mod History: + * 90/01/24 cpcahil Initial revision. + * 90/01/29 cpcahil Added code to ignore recursive calls. + */ +void +malloc_check_str(func,str) + char * func; + char * str; +{ + static int layers; + register char * s; + + if( (layers++ == 0) && malloc_in_arena(str) ) + { + for( s=str; *s; s++) + { + } + + malloc_verify(func,str,s-str+1); + } + + layers--; +} + +/* + * Function: malloc_check_strn() + * + * Arguments: func - name of function calling this routine + * str - pointer to area to check + * len - max length of string + * + * Purpose: to verify that if str is within the malloc arena, the data + * it points to does not extend beyond the applicable region. + * + * Returns: Nothing of any use (function is void). + * + * Narrative: + * IF pointer is within malloc arena + * determin length of string + * call malloc_verify() to verify data is withing applicable region + * return + * + * Mod History: + * 90/01/24 cpcahil Initial revision. + * 90/01/29 cpcahil Added code to ignore recursive calls. + * 90/08/29 cpcahil added length (for strn* functions) + */ +void +malloc_check_strn(func,str,len) + char * func; + char * str; + int len; +{ + register int i; + static int layers; + register char * s; + + if( (layers++ == 0) && malloc_in_arena(str) ) + { + for( s=str,i=0; (i < len) && *s; s++) + { + } + + malloc_verify(func,str,s-str+1); + } + + layers--; +} + +/* + * Function: malloc_check_data() + * + * Arguments: func - name of function calling this routine + * ptr - pointer to area to check + * len - length to verify + * + * Purpose: to verify that if ptr is within the malloc arena, the data + * it points to does not extend beyond the applicable region. + * + * Returns: Nothing of any use (function is void). + * + * Narrative: + * IF pointer is within malloc arena + * call malloc_verify() to verify data is withing applicable region + * return + * + * Mod History: + * 90/01/24 cpcahil Initial revision. + * 90/01/29 cpcahil Added code to ignore recursive calls. + */ +void +malloc_check_data(func,ptr,len) + char * func; + char * ptr; + int len; +{ + static int layers; + + if( layers++ == 0 ) + { + DEBUG3(40,"malloc_check_data(%s,0x%x,%d) called...", + func,ptr,len); + if( malloc_in_arena(ptr) ) + { + DEBUG0(10,"pointer in malloc arena, verifying..."); + malloc_verify(func,ptr,len); + } + } + + layers--; +} + +/* + * Function: malloc_verify() + * + * Arguments: func - name of function calling the malloc check routines + * ptr - pointer to area to check + * len - length to verify + * + * Purpose: to verify that the data ptr points to does not extend beyond + * the applicable malloc region. This function is only called + * if it has been determined that ptr points into the malloc arena. + * + * Returns: Nothing of any use (function is void). + * + * Narrative: + * + * Mod History: + * 90/01/24 cpcahil Initial revision. + */ +void +malloc_verify(func,ptr,len) + char * func; + char * ptr; + int len; +{ + extern struct mlist * malloc_end; + extern int malloc_errno; + extern struct mlist malloc_start; + struct mlist * mptr; + + DEBUG3(40,"malloc_verify(%s,0x%x,%d) called...", func,ptr,len); + /* + * Find the malloc block that includes this pointer + */ + mptr = &malloc_start; + while( mptr && + ! (((char *)mptr < ptr) && ((mptr->data+mptr->s.size) > ptr) ) ) + { + mptr = mptr->next; + } + + /* + * if ptr was not in a malloc block, it must be part of + * some direct sbrk() stuff, so just return. + */ + if( ! mptr ) + { + DEBUG1(10,"ptr (0x%x) not found in malloc search", ptr); + return; + } + + /* + * Now we have a valid malloc block that contains the indicated + * pointer. We must verify that it is withing the requested block + * size (as opposed to the real block size which is rounded up to + * allow for correct alignment). + */ + + DEBUG4(60,"Checking 0x%x-0x%x, 0x%x-0x%x", + ptr, ptr+len, mptr->data, mptr->data+mptr->r_size); + + if( (ptr < mptr->data) || ((ptr+len) > (mptr->data+mptr->r_size)) ) + { + DEBUG4(0,"pointer not within region 0x%x-0x%x, 0x%x-0x%x", + ptr, ptr+len, mptr->data, mptr->data+mptr->r_size); + + malloc_errno = M_CODE_OUTOF_BOUNDS; + malloc_warning(func); + } + + return; +} + +/* + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1997/09/22 14:51:11 hjs + * dmake 4.1 orginal sourcen + * + * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura + * dmake gold 4.1.00 initial import + * + * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura + * Dmake 4.1 Initial Import + * + * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura + * Initial import for final release of dmake 4.1 + * + * Revision 1.1 1994/10/06 17:43:15 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1994/10/06 03:45:24 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1992/01/24 03:29:09 dvadura + * dmake Version 3.8, Initial revision + * + * Revision 1.5 90/08/29 22:23:48 cpcahil + * added new function to check on strings up to a specified length + * and used it within several strn* functions. + * + * Revision 1.4 90/05/11 00:13:09 cpcahil + * added copyright statment + * + * Revision 1.3 90/02/24 21:50:22 cpcahil + * lots of lint fixes + * + * Revision 1.2 90/02/24 17:29:38 cpcahil + * changed $Header to $Id so full path wouldnt be included as part of rcs + * id string + * + * Revision 1.1 90/02/24 14:57:03 cpcahil + * Initial revision + * + */ diff --git a/dmake/dbug/malloc/mlc_chn.c b/dmake/dbug/malloc/mlc_chn.c new file mode 100644 index 000000000000..3f24333611f9 --- /dev/null +++ b/dmake/dbug/malloc/mlc_chn.c @@ -0,0 +1,188 @@ +/* + * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). + * You may copy, distribute, and use this software as long as this + * copyright statement is not removed. + */ +#include <stdio.h> +#include <fcntl.h> +#include "malloc.h" + +/* + * Function: malloc_chain_check() + * + * Purpose: to verify malloc chain is intact + * + * Arguments: todo - 0 - just check and return status + * 1 - call malloc_warn if error detected + * + * Returns: 0 - malloc chain intact & no overflows + * other - problems detected in malloc chain + * + * Narrative: + * + * Notes: If todo is non-zero the malloc_warn function, when called + * may not return (i.e. it may exit) + * + */ +#ifndef lint +static +char rcs_hdr[] = "$Id: mlc_chn.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $"; +#endif + + +int +malloc_chain_check(todo) + int todo; +{ + char * func = "malloc_chain_check"; + int i; + extern char * malloc_data_start; + extern char * malloc_data_end; + extern struct mlist * malloc_end; + extern int malloc_errno; + extern struct mlist malloc_start; + struct mlist * oldptr; + struct mlist * ptr; + int rtn = 0; + + oldptr = &malloc_start; + for(ptr = malloc_start.next; ; ptr = ptr->next) + { + /* + * Since the malloc chain is a forward only chain, any + * pointer that we get should always be positioned in + * memory following the previous pointer. If this is not + * so, we must have a corrupted chain. + */ + if( ptr ) + { + if(ptr < oldptr ) + { + malloc_errno = M_CODE_CHAIN_BROKE; + if( todo ) + { + malloc_fatal(func); + } + rtn++; + break; + } + oldptr = ptr; + } + else + { + if( oldptr != malloc_end ) + { + /* + * This should never happen. If it does, then + * we got a real problem. + */ + malloc_errno = M_CODE_NO_END; + if( todo ) + { + malloc_fatal(func); + } + rtn++; + } + break; + } + + /* + * verify that ptr is within the malloc region... + * since we started within the malloc chain this should never + * happen. + */ + + if( ((char *)ptr < malloc_data_start) || + ((char *)ptr > malloc_data_end) ) + { + malloc_errno = M_CODE_BAD_PTR; + if( todo ) + { + malloc_fatal(func); + } + rtn++; + break; + } + + /* + * verify magic flag is set + */ + + if( (ptr->flag&M_MAGIC) != M_MAGIC ) + { + malloc_errno = M_CODE_BAD_MAGIC; + if( todo ) + { + malloc_warning(func); + } + rtn++; + continue; + } + + /* + * verify segments are correctly linked together + */ + + if( (ptr->prev && (ptr->prev->next != ptr) ) || + (ptr->next && (ptr->next->prev != ptr) ) || + ((ptr->next == NULL) && (ptr->prev == NULL)) ) + { + malloc_errno = M_CODE_BAD_CONNECT; + if( todo ) + { + malloc_warning(func); + } + rtn++; + continue; + } + + /* + * If this segment is allocated + */ + + if( (ptr->flag & M_INUSE) != 0 ) + { + /* + * verify no overflow of data area + */ + + for(i=ptr->r_size; i < ptr->s.size; i++) + { + if( ptr->data[i] != M_FILL ) + { + malloc_errno = M_CODE_OVERRUN; + if( todo ) + { + malloc_warning(func); + } + rtn++; + break; + } + } + } + else /* it's not allocated so */ + { + /* + * verify no reuse of freed data blocks + */ + + for(i=0; i < ptr->s.size; i++) + { + if( ptr->data[i] != M_FREE_FILL ) + { + malloc_errno = M_CODE_REUSE; + if( todo ) + { + malloc_warning(func); + } + rtn++; + break; + } + } + } + + } /* for(... */ + + return(rtn); + +} /* malloc_chain_check(... */ diff --git a/dmake/dbug/malloc/patchlev b/dmake/dbug/malloc/patchlev new file mode 100644 index 000000000000..00750edc07d6 --- /dev/null +++ b/dmake/dbug/malloc/patchlev @@ -0,0 +1 @@ +3 diff --git a/dmake/dbug/malloc/realloc.c b/dmake/dbug/malloc/realloc.c new file mode 100644 index 000000000000..43bc20fa7841 --- /dev/null +++ b/dmake/dbug/malloc/realloc.c @@ -0,0 +1,233 @@ +/* + * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). + * You may copy, distribute, and use this software as long as this + * copyright statement is not removed. + */ +#include <stdio.h> +#include "malloc.h" + +/* + * Function: realloc() + * + * Purpose: to re-allocate a data area. + * + * Arguments: cptr - pointer to area to reallocate + * size - size to change area to + * + * Returns: pointer to new area (may be same area) + * + * Narrative: verify pointer is within malloc region + * obtain mlist pointer from cptr + * verify magic number is correct + * verify inuse flag is set + * verify connection to adjoining segments is correct + * save requested size + * round-up size to appropriate boundry + * IF size is bigger than what is in this segment + * try to join next segment to this segment + * IF size is less than what is is this segment + * determine leftover amount of space + * ELSE + * allocate new segment of size bites + * IF allocation failed + * return NULL + * copy previous data to new segment + * free previous segment + * return new pointer + * split of extra space in this segment (if any) + * clear bytes beyound what they had before + * return pointer to data + */ +#ifndef lint +static +char rcs_hdr[] = "$Id: realloc.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $"; +#endif + +char * +realloc(cptr,size) + char * cptr; + unsigned int size; +{ + void free(); + char * func = "realloc"; + int i; + char * malloc(); + extern int malloc_checking; + extern struct mlist * malloc_end; + extern int malloc_errno; + extern char * malloc_data_end; + extern char * malloc_data_start; + void malloc_join(); + void malloc_memset(); + void malloc_split(); + char * memcpy(); + char * new_cptr; + struct mlist * ptr; + int r_size; + + /* + * IF malloc chain checking is on, go do it. + */ + if( malloc_checking ) + { + (void) malloc_chain_check(1); + } + + /* + * verify that cptr is within the malloc region... + */ + if( cptr < malloc_data_start || cptr > malloc_data_end ) + { + malloc_errno = M_CODE_BAD_PTR; + malloc_warning(func); + return (NULL); + } + + /* + * convert pointer to mlist struct pointer. To do this we must + * move the pointer backwards the correct number of bytes... + */ + + ptr = (struct mlist *) (cptr - M_SIZE); + + if( (ptr->flag&M_MAGIC) != M_MAGIC ) + { + malloc_errno = M_CODE_BAD_MAGIC; + malloc_warning(func); + return(NULL); + } + + if( ! (ptr->flag & M_INUSE) ) + { + malloc_errno = M_CODE_NOT_INUSE ; + malloc_warning(func); + return(NULL); + } + + if( (ptr->prev && (ptr->prev->next != ptr) ) || + (ptr->next && (ptr->next->prev != ptr) ) || + ((ptr->next == NULL) && (ptr->prev == NULL)) ) + { + malloc_errno = M_CODE_BAD_CONNECT; + malloc_warning(func); + return(NULL); + } + + r_size = ++size; + + M_ROUNDUP(size); + + if( size > ptr->s.size ) + { + malloc_join(ptr,ptr->next,1,1); + } + + if( size > ptr->s.size ) + { + /* + * else we can't combine it, so lets allocate a new chunk, + * copy the data and free the old chunk... + */ + new_cptr = malloc(size); + + if( new_cptr == (char *) 0) + { + return(new_cptr); + } + + if( r_size < ptr->r_size ) + { + i = r_size; + } + else + { + i = ptr->r_size; + } + (void)memcpy(new_cptr,ptr->data,i); + free(cptr); + return(new_cptr); + + } /* else... */ + + /* + * save amount of real data in new segment (this will be used in the + * memset later) and then save requested size of this segment. + */ + + if( ptr->r_size < r_size ) + { + i = ptr->r_size; + } + else + { + i = r_size; + } + + ptr->r_size = r_size; + + /* + * split off extra free space at end of this segment, if possible... + */ + + malloc_split(ptr); + + malloc_memset( ptr->data+i, M_FILL, (int) (ptr->s.size - i)); + + return(ptr->data); + +} /* realloc(... */ + + +/* + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1997/09/22 14:51:11 hjs + * dmake 4.1 orginal sourcen + * + * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura + * dmake gold 4.1.00 initial import + * + * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura + * Dmake 4.1 Initial Import + * + * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura + * Initial import for final release of dmake 4.1 + * + * Revision 1.1 1994/10/06 17:43:17 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1994/10/06 03:45:26 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1992/01/24 03:29:11 dvadura + * dmake Version 3.8, Initial revision + * + * Revision 1.8 90/08/29 21:22:52 cpcahil + * miscellaneous lint fixes + * + * Revision 1.7 90/05/11 00:13:10 cpcahil + * added copyright statment + * + * Revision 1.6 90/02/25 11:01:20 cpcahil + * added support for malloc chain checking. + * + * Revision 1.5 90/02/24 21:50:31 cpcahil + * lots of lint fixes + * + * Revision 1.4 90/02/24 17:29:39 cpcahil + * changed $Header to $Id so full path wouldnt be included as part of rcs + * id string + * + * Revision 1.3 90/02/24 17:20:00 cpcahil + * attempt to get rid of full path in rcs header. + * + * Revision 1.2 90/02/24 15:14:20 cpcahil + * 1. added function header + * 2. changed calls to malloc_warning to conform to new usage + * 3. added setting of malloc_errno + * 4. broke up bad pointer determination so that errno's would be more + * descriptive + * + * Revision 1.1 90/02/22 23:17:43 cpcahil + * Initial revision + * + */ diff --git a/dmake/dbug/malloc/string.c b/dmake/dbug/malloc/string.c new file mode 100644 index 000000000000..8ca3a1eee167 --- /dev/null +++ b/dmake/dbug/malloc/string.c @@ -0,0 +1,581 @@ +/* + * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). + * You may copy, distribute, and use this software as long as this + * copyright statement is not removed. + */ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include "malloc.h" + +#ifndef lint +static +char rcs_hdr[] = "$Id: string.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $"; +#endif + +int malloc_checking = 0; + +char * +strcat(str1,str2) + register char * str1; + register char * str2; +{ + char * rtn; + int len; + + /* + * check pointers agains malloc region. The malloc* functions + * will properly handle the case where a pointer does not + * point into malloc space. + */ + malloc_checking = 1; + + len = strlen(str2); + malloc_check_str("strcat", str2); + + len += strlen(str1) + 1; + malloc_checking = 0; + + malloc_check_data("strcat", str1, len); + + rtn = str1; + + while( *str1 ) + { + str1++; + } + + while( (*str1 = *str2) != '\0' ) + { + str1++; + str2++; + } + + return(rtn); +} + +char * +strdup(str1) + register char * str1; +{ + char * malloc(); + char * rtn; + register char * str2; + + malloc_check_str("strdup", str1); + + rtn = str2 = malloc((unsigned)strlen(str1)+1); + + if( rtn != (char *) 0) + { + while( (*str2 = *str1) != '\0' ) + { + str1++; + str2++; + } + } + + return(rtn); +} + +char * +strncat(str1,str2,len) + register char * str1; + register char * str2; + register int len; +{ + int len1; + int len2; + char * rtn; + + malloc_check_strn("strncat", str2, len); + + malloc_checking = 1; + + len2 = strlen(str2) + 1; + len1 = strlen(str1); + + malloc_checking = 0; + + + if( (len+1) < len2 ) + { + len1 += len + 1; + } + else + { + len1 += len2; + } + malloc_check_data("strncat", str1, len1); + + rtn = str1; + + while( *str1 ) + { + str1++; + } + + while( len-- && ((*str1++ = *str2++) != '\0') ) + { + } + + if( ! len ) + { + *str1 = '\0'; + } + + return(rtn); +} + +int +strcmp(str1,str2) + register char * str1; + register char * str2; +{ + malloc_check_str("strcmp", str1); + malloc_check_str("strcmp", str2); + + while( *str1 && (*str1 == *str2) ) + { + str1++; + str2++; + } + + + /* + * in order to deal with the case of a negative last char of either + * string when the other string has a null + */ + if( (*str2 == '\0') && (*str1 == '\0') ) + { + return(0); + } + else if( *str2 == '\0' ) + { + return(1); + } + else if( *str1 == '\0' ) + { + return(-1); + } + + return( *str1 - *str2 ); +} + +int +strncmp(str1,str2,len) + register char * str1; + register char * str2; + register int len; +{ + malloc_check_strn("strncmp", str1, len); + malloc_check_strn("strncmp", str2, len); + + while( --len >= 0 && *str1 && (*str1 == *str2) ) + { + str1++; + str2++; + } + + if( len < 0 ) + { + return(0); + } + /* + * in order to deal with the case of a negative last char of either + * string when the other string has a null + */ + if( (*str2 == '\0') && (*str1 == '\0') ) + { + return(0); + } + else if( *str2 == '\0' ) + { + return(1); + } + else if( *str1 == '\0' ) + { + return(-1); + } + + return( *str1 - *str2 ); +} + +char * +strcpy(str1,str2) + register char * str1; + register char * str2; +{ + char * rtn; + int len; + + malloc_checking = 1; + len = strlen(str2) + 1; + malloc_checking = 0; + + malloc_check_data("strcpy", str1, len); + malloc_check_data("strcpy", str2, len); + + rtn = str1; + + while( (*str1++ = *str2++) != '\0') + { + } + + return(rtn); +} + +char * +strncpy(str1,str2,len) + register char * str1; + register char * str2; + register int len; +{ + extern int malloc_checking; + char * rtn; + + malloc_check_data("strncpy", str1, len); + malloc_check_strn("strncpy", str2, len); + + rtn = str1; + + while((len-- > 0) && (*str1++ = *str2++) != '\0') + { + } + while( (len-- > 0) ) + { + *str1++ = '\0'; + } + + return(rtn); +} + +int +strlen(str1) + register char * str1; +{ + register char * s; + + if(! malloc_checking ) + { + malloc_check_str("strlen", str1); + } + + for( s = str1; *s; s++) + { + } + + return( s - str1 ); +} + +char * +strchr(str1,c) + register char * str1; + register int c; +{ + malloc_check_str("strchr", str1); + + while( *str1 && (*str1 != (char) c) ) + { + str1++; + } + + if(*str1 != (char) c) + { + str1 = (char *) 0; + } + + return(str1); +} + +char * +strrchr(str1,c) + register char * str1; + register int c; +{ + register char * rtn = (char *) 0; + + malloc_check_str("strrchr", str1); + + while( *str1 ) + { + if(*str1 == (char) c ) + { + rtn = str1; + } + str1++; + } + + if( *str1 == (char) c) + { + rtn = str1; + } + + return(rtn); +} + +char * +index(str1,c) + char * str1; + char c; +{ + return( strchr(str1,c) ); +} + +char * +rindex(str1,c) + char * str1; + char c; +{ + return( strrchr(str1,c) ); +} + +char * +strpbrk(str1,str2) + register char * str1; + register char * str2; +{ + register char * tmp; + + malloc_check_str("strpbrk", str1); + malloc_check_str("strpbrk", str2); + + while(*str1) + { + for( tmp=str2; *tmp && *tmp != *str1; tmp++) + { + } + if( *tmp ) + { + break; + } + str1++; + } + + if( ! *str1 ) + { + str1 = (char *) 0; + } + + return(str1); +} + +int +strspn(str1,str2) + register char * str1; + register char * str2; +{ + register char * tmp; + char * orig = str1; + + malloc_check_str("strspn", str1); + malloc_check_str("strspn", str2); + + while(*str1) + { + for( tmp=str2; *tmp && *tmp != *str1; tmp++) + { + } + if(! *tmp ) + { + break; + } + str1++; + } + + return( (int) (str1 - orig) ); +} + +int +strcspn(str1,str2) + register char * str1; + register char * str2; +{ + register char * tmp; + char * orig = str1; + + malloc_check_str("strcspn", str1); + malloc_check_str("strcspn", str2); + + while(*str1) + { + for( tmp=str2; *tmp && *tmp != *str1; tmp++) + { + } + if( *tmp ) + { + break; + } + str1++; + } + + return( (int) (str1 - orig) ); +} + +/* + * strtok() source taken from that posted to comp.lang.c by Chris Torek + * in Jan 1990. + */ + +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * Get next token from string s (NULL on 2nd, 3rd, etc. calls), + * where tokens are nonempty strings separated by runs of + * chars from delim. Writes NULs into s to end tokens. delim need not + * remain constant from call to call. + * + * Modified by cpc: changed variable names to conform with naming + * conventions used in rest of code. Added malloc pointer + * check calls. + */ +char * +strtok(str1, str2) + char * str1; + char * str2; +{ + static char * last; + char * strtoken(); + + if( str1 ) + { + malloc_check_str("strtok", str1); + last = str1; + } + malloc_check_str("strtok", str2); + + return (strtoken(&last, str2, 1)); +} + + +/* + * Get next token from string *stringp, where tokens are (possibly empty) + * strings separated by characters from delim. Tokens are separated + * by exactly one delimiter iff the skip parameter is false; otherwise + * they are separated by runs of characters from delim, because we + * skip over any initial `delim' characters. + * + * Writes NULs into the string at *stringp to end tokens. + * delim will usually, but need not, remain constant from call to call. + * On return, *stringp points past the last NUL written (if there might + * be further tokens), or is NULL (if there are definitely no more tokens). + * + * If *stringp is NULL, strtoken returns NULL. + */ +char * +strtoken(stringp, delim, skip) + register char **stringp; + register char *delim; + int skip; +{ + register char *s; + register char *spanp; + register int c, sc; + char *tok; + + if ((s = *stringp) == NULL) + return (NULL); + + if (skip) { + /* + * Skip (span) leading delimiters (s += strspn(s, delim)). + */ + cont: + c = *s; + for (spanp = delim; (sc = *spanp++) != 0;) { + if (c == sc) { + s++; + goto cont; + } + } + if (c == 0) { /* no token found */ + *stringp = NULL; + return (NULL); + } + } + + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for (tok = s;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *stringp = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} + +/* + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1997/09/22 14:51:11 hjs + * dmake 4.1 orginal sourcen + * + * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura + * dmake gold 4.1.00 initial import + * + * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura + * Dmake 4.1 Initial Import + * + * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura + * Initial import for final release of dmake 4.1 + * + * Revision 1.1 1994/10/06 17:43:17 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1994/10/06 03:45:27 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1992/01/24 03:29:13 dvadura + * dmake Version 3.8, Initial revision + * + * Revision 1.7 90/08/29 22:24:19 cpcahil + * added new function to check on strings up to a specified length + * and used it within several strn* functions. + * + * Revision 1.6 90/07/16 20:06:56 cpcahil + * fixed several minor bugs found with Henry Spencer's string/mem function + * tester program. + * + * Revision 1.5 90/06/10 14:59:49 cpcahil + * Fixed a couple of bugs in strncpy & strdup + * + * Revision 1.4 90/05/11 00:13:10 cpcahil + * added copyright statment + * + * Revision 1.3 90/02/24 21:50:32 cpcahil + * lots of lint fixes + * + * Revision 1.2 90/02/24 17:29:40 cpcahil + * changed $Header to $Id so full path wouldnt be included as part of rcs + * id string + * + * Revision 1.1 90/02/22 23:17:44 cpcahil + * Initial revision + * + */ diff --git a/dmake/dbug/malloc/testmem.c b/dmake/dbug/malloc/testmem.c new file mode 100644 index 000000000000..46fba912f8c0 --- /dev/null +++ b/dmake/dbug/malloc/testmem.c @@ -0,0 +1,646 @@ +/* + * This stuff is all stolen (with permission, since it was in the public + * domain) from Henry Spencer's string and memory library. Thanks Henry. + */ + +/* + * Test program for string(3) routines. + * + * Note that at least one Bell Labs implementation of the string + * routines flunks a couple of these tests -- the ones which test + * behavior on "negative" characters. + */ + +#include <stdio.h> +#include <string.h> + +char * index(); +char * rindex(); + +#define STREQ(a, b) (strcmp((a), (b)) == 0) + +char *it = "<UNSET>"; /* Routine name for message routines. */ +int waserror = 0; /* For exit status. */ + +char uctest[] = "\004\203"; /* For testing signedness of chars. */ +int charsigned; /* Result. */ + +/* + - check - complain if condition is not true + */ +void +check(thing, number) +int thing; +int number; /* Test number for error message. */ +{ + if (!thing) { + printf("%s flunked test %d\n", it, number); + waserror = 1; + } +} + +/* + - equal - complain if first two args don't strcmp as equal + */ +void +equal(a, b, number) +char *a; +char *b; +int number; /* Test number for error message. */ +{ + check(a != NULL && b != NULL && STREQ(a, b), number); +} + +char one[50]; +char two[50]; + +#ifdef UNIXERR +#define ERR 1 +#endif +#ifdef BERKERR +#define ERR 1 +#endif +#ifdef ERR +int f; +extern char *sys_errlist[]; +extern int sys_nerr; +extern int errno; +#endif + +/* ARGSUSED */ +main(argc, argv) +int argc; +char *argv[]; +{ + /* + * First, establish whether chars are signed. + */ + if (uctest[0] < uctest[1]) + charsigned = 0; + else + charsigned = 1; + + /* + * Then, do the rest of the work. Split into two functions because + * some compilers get unhappy about a single immense function. + */ + first(); + second(); + + exit((waserror) ? 1 : 0); +} + +first() +{ + /* + * Test strcmp first because we use it to test other things. + */ + it = "strcmp"; + check(strcmp("", "") == 0, 1); /* Trivial case. */ + check(strcmp("a", "a") == 0, 2); /* Identity. */ + check(strcmp("abc", "abc") == 0, 3); /* Multicharacter. */ + check(strcmp("abc", "abcd") < 0, 4); /* Length mismatches. */ + check(strcmp("abcd", "abc") > 0, 5); + check(strcmp("abcd", "abce") < 0, 6); /* Honest miscompares. */ + check(strcmp("abce", "abcd") > 0, 7); + check(strcmp("a\203", "a") > 0, 8); /* Tricky if char signed. */ + if (charsigned) /* Sign-bit comparison. */ + check(strcmp("a\203", "a\003") < 0, 9); + else + check(strcmp("a\203", "a\003") > 0, 9); + check(strcmp("a", "a\203") < 0, 10); /* Tricky if char signed. */ + + /* + * Test strcpy next because we need it to set up other tests. + */ + it = "strcpy"; + check(strcpy(one, "abcd") == one, 1); /* Returned value. */ + equal(one, "abcd", 2); /* Basic test. */ + + (void) strcpy(one, "x"); + equal(one, "x", 3); /* Writeover. */ + equal(one+2, "cd", 4); /* Wrote too much? */ + + (void) strcpy(two, "hi there"); + (void) strcpy(one, two); + equal(one, "hi there", 5); /* Basic test encore. */ + equal(two, "hi there", 6); /* Stomped on source? */ + + (void) strcpy(one, ""); + equal(one, "", 7); /* Boundary condition. */ + + /* + * strcat + */ + it = "strcat"; + (void) strcpy(one, "ijk"); + check(strcat(one, "lmn") == one, 1); /* Returned value. */ + equal(one, "ijklmn", 2); /* Basic test. */ + + (void) strcpy(one, "x"); + (void) strcat(one, "yz"); + equal(one, "xyz", 3); /* Writeover. */ + equal(one+4, "mn", 4); /* Wrote too much? */ + + (void) strcpy(one, "gh"); + (void) strcpy(two, "ef"); + (void) strcat(one, two); + equal(one, "ghef", 5); /* Basic test encore. */ + equal(two, "ef", 6); /* Stomped on source? */ + + (void) strcpy(one, ""); + (void) strcat(one, ""); + equal(one, "", 7); /* Boundary conditions. */ + (void) strcpy(one, "ab"); + (void) strcat(one, ""); + equal(one, "ab", 8); + (void) strcpy(one, ""); + (void) strcat(one, "cd"); + equal(one, "cd", 9); + + /* + * strncat - first test it as strcat, with big counts, then + * test the count mechanism. + */ + it = "strncat"; + (void) strcpy(one, "ijk"); + check(strncat(one, "lmn", 99) == one, 1); /* Returned value. */ + equal(one, "ijklmn", 2); /* Basic test. */ + + (void) strcpy(one, "x"); + (void) strncat(one, "yz", 99); + equal(one, "xyz", 3); /* Writeover. */ + equal(one+4, "mn", 4); /* Wrote too much? */ + + (void) strcpy(one, "gh"); + (void) strcpy(two, "ef"); + (void) strncat(one, two, 99); + equal(one, "ghef", 5); /* Basic test encore. */ + equal(two, "ef", 6); /* Stomped on source? */ + + (void) strcpy(one, ""); + (void) strncat(one, "", 99); + equal(one, "", 7); /* Boundary conditions. */ + (void) strcpy(one, "ab"); + (void) strncat(one, "", 99); + equal(one, "ab", 8); + (void) strcpy(one, ""); + (void) strncat(one, "cd", 99); + equal(one, "cd", 9); + + (void) strcpy(one, "ab"); + (void) strncat(one, "cdef", 2); + equal(one, "abcd", 10); /* Count-limited. */ + + (void) strncat(one, "gh", 0); + equal(one, "abcd", 11); /* Zero count. */ + + (void) strncat(one, "gh", 2); + equal(one, "abcdgh", 12); /* Count and length equal. */ + + /* + * strncmp - first test as strcmp with big counts, then test + * count code. + */ + it = "strncmp"; + check(strncmp("", "", 99) == 0, 1); /* Trivial case. */ + check(strncmp("a", "a", 99) == 0, 2); /* Identity. */ + check(strncmp("abc", "abc", 99) == 0, 3); /* Multicharacter. */ + check(strncmp("abc", "abcd", 99) < 0, 4); /* Length unequal. */ + check(strncmp("abcd", "abc", 99) > 0, 5); + check(strncmp("abcd", "abce", 99) < 0, 6); /* Honestly unequal. */ + check(strncmp("abce", "abcd", 99) > 0, 7); + check(strncmp("a\203", "a", 2) > 0, 8); /* Tricky if '\203' < 0 */ + if (charsigned) /* Sign-bit comparison. */ + check(strncmp("a\203", "a\003", 2) < 0, 9); + else + check(strncmp("a\203", "a\003", 2) > 0, 9); + check(strncmp("abce", "abcd", 3) == 0, 10); /* Count limited. */ + check(strncmp("abce", "abc", 3) == 0, 11); /* Count == length. */ + check(strncmp("abcd", "abce", 4) < 0, 12); /* Nudging limit. */ + check(strncmp("abc", "def", 0) == 0, 13); /* Zero count. */ + + /* + * strncpy - testing is a bit different because of odd semantics + */ + it = "strncpy"; + check(strncpy(one, "abc", 4) == one, 1); /* Returned value. */ + equal(one, "abc", 2); /* Did the copy go right? */ + + (void) strcpy(one, "abcdefgh"); + (void) strncpy(one, "xyz", 2); + equal(one, "xycdefgh", 3); /* Copy cut by count. */ + + (void) strcpy(one, "abcdefgh"); + (void) strncpy(one, "xyz", 3); /* Copy cut just before NUL. */ + equal(one, "xyzdefgh", 4); + + (void) strcpy(one, "abcdefgh"); + (void) strncpy(one, "xyz", 4); /* Copy just includes NUL. */ + equal(one, "xyz", 5); + equal(one+4, "efgh", 6); /* Wrote too much? */ + + (void) strcpy(one, "abcdefgh"); + (void) strncpy(one, "xyz", 5); /* Copy includes padding. */ + equal(one, "xyz", 7); + equal(one+4, "", 8); + equal(one+5, "fgh", 9); + + (void) strcpy(one, "abc"); + (void) strncpy(one, "xyz", 0); /* Zero-length copy. */ + equal(one, "abc", 10); + + (void) strncpy(one, "", 2); /* Zero-length source. */ + equal(one, "", 11); + equal(one+1, "", 12); + equal(one+2, "c", 13); + + (void) strcpy(one, "hi there"); + (void) strncpy(two, one, 9); + equal(two, "hi there", 14); /* Just paranoia. */ + equal(one, "hi there", 15); /* Stomped on source? */ + + /* + * strlen + */ + it = "strlen"; + check(strlen("") == 0, 1); /* Empty. */ + check(strlen("a") == 1, 2); /* Single char. */ + check(strlen("abcd") == 4, 3); /* Multiple chars. */ + + /* + * strchr + */ + it = "strchr"; + check(strchr("abcd", 'z') == NULL, 1); /* Not found. */ + (void) strcpy(one, "abcd"); + check(strchr(one, 'c') == one+2, 2); /* Basic test. */ + check(strchr(one, 'd') == one+3, 3); /* End of string. */ + check(strchr(one, 'a') == one, 4); /* Beginning. */ + check(strchr(one, '\0') == one+4, 5); /* Finding NUL. */ + (void) strcpy(one, "ababa"); + check(strchr(one, 'b') == one+1, 6); /* Finding first. */ + (void) strcpy(one, ""); + check(strchr(one, 'b') == NULL, 7); /* Empty string. */ + check(strchr(one, '\0') == one, 8); /* NUL in empty string. */ + + /* + * index - just like strchr + */ + it = "index"; + check(index("abcd", 'z') == NULL, 1); /* Not found. */ + (void) strcpy(one, "abcd"); + check(index(one, 'c') == one+2, 2); /* Basic test. */ + check(index(one, 'd') == one+3, 3); /* End of string. */ + check(index(one, 'a') == one, 4); /* Beginning. */ + check(index(one, '\0') == one+4, 5); /* Finding NUL. */ + (void) strcpy(one, "ababa"); + check(index(one, 'b') == one+1, 6); /* Finding first. */ + (void) strcpy(one, ""); + check(index(one, 'b') == NULL, 7); /* Empty string. */ + check(index(one, '\0') == one, 8); /* NUL in empty string. */ + + /* + * strrchr + */ + it = "strrchr"; + check(strrchr("abcd", 'z') == NULL, 1); /* Not found. */ + (void) strcpy(one, "abcd"); + check(strrchr(one, 'c') == one+2, 2); /* Basic test. */ + check(strrchr(one, 'd') == one+3, 3); /* End of string. */ + check(strrchr(one, 'a') == one, 4); /* Beginning. */ + check(strrchr(one, '\0') == one+4, 5); /* Finding NUL. */ + (void) strcpy(one, "ababa"); + check(strrchr(one, 'b') == one+3, 6); /* Finding last. */ + (void) strcpy(one, ""); + check(strrchr(one, 'b') == NULL, 7); /* Empty string. */ + check(strrchr(one, '\0') == one, 8); /* NUL in empty string. */ + + /* + * rindex - just like strrchr + */ + it = "rindex"; + check(rindex("abcd", 'z') == NULL, 1); /* Not found. */ + (void) strcpy(one, "abcd"); + check(rindex(one, 'c') == one+2, 2); /* Basic test. */ + check(rindex(one, 'd') == one+3, 3); /* End of string. */ + check(rindex(one, 'a') == one, 4); /* Beginning. */ + check(rindex(one, '\0') == one+4, 5); /* Finding NUL. */ + (void) strcpy(one, "ababa"); + check(rindex(one, 'b') == one+3, 6); /* Finding last. */ + (void) strcpy(one, ""); + check(rindex(one, 'b') == NULL, 7); /* Empty string. */ + check(rindex(one, '\0') == one, 8); /* NUL in empty string. */ +} + +second() +{ + /* + * strpbrk - somewhat like strchr + */ + it = "strpbrk"; + check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */ + (void) strcpy(one, "abcd"); + check(strpbrk(one, "c") == one+2, 2); /* Basic test. */ + check(strpbrk(one, "d") == one+3, 3); /* End of string. */ + check(strpbrk(one, "a") == one, 4); /* Beginning. */ + check(strpbrk(one, "") == NULL, 5); /* Empty search list. */ + check(strpbrk(one, "cb") == one+1, 6); /* Multiple search. */ + (void) strcpy(one, "abcabdea"); + check(strpbrk(one, "b") == one+1, 7); /* Finding first. */ + check(strpbrk(one, "cb") == one+1, 8); /* With multiple search. */ + check(strpbrk(one, "db") == one+1, 9); /* Another variant. */ + (void) strcpy(one, ""); + check(strpbrk(one, "bc") == NULL, 10); /* Empty string. */ + check(strpbrk(one, "") == NULL, 11); /* Both strings empty. */ + +#if 0 + /* + * strstr - somewhat like strchr + */ + it = "strstr"; + check(strstr("abcd", "z") == NULL, 1); /* Not found. */ + check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */ + (void) strcpy(one, "abcd"); + check(strstr(one, "c") == one+2, 3); /* Basic test. */ + check(strstr(one, "bc") == one+1, 4); /* Multichar. */ + check(strstr(one, "d") == one+3, 5); /* End of string. */ + check(strstr(one, "cd") == one+2, 6); /* Tail of string. */ + check(strstr(one, "abc") == one, 7); /* Beginning. */ + check(strstr(one, "abcd") == one, 8); /* Exact match. */ + check(strstr(one, "abcde") == NULL, 9); /* Too long. */ + check(strstr(one, "de") == NULL, 10); /* Past end. */ + check(strstr(one, "") == one+4, 11); /* Finding empty. */ + (void) strcpy(one, "ababa"); + check(strstr(one, "ba") == one+1, 12); /* Finding first. */ + (void) strcpy(one, ""); + check(strstr(one, "b") == NULL, 13); /* Empty string. */ + check(strstr(one, "") == one, 14); /* Empty in empty string. */ + (void) strcpy(one, "bcbca"); + check(strstr(one, "bca") == one+2, 15); /* False start. */ + (void) strcpy(one, "bbbcabbca"); + check(strstr(one, "bbca") == one+1, 16); /* With overlap. */ +#endif + + /* + * strspn + */ + it = "strspn"; + check(strspn("abcba", "abc") == 5, 1); /* Whole string. */ + check(strspn("abcba", "ab") == 2, 2); /* Partial. */ + check(strspn("abc", "qx") == 0, 3); /* None. */ + check(strspn("", "ab") == 0, 4); /* Null string. */ + check(strspn("abc", "") == 0, 5); /* Null search list. */ + + /* + * strcspn + */ + it = "strcspn"; + check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */ + check(strcspn("abcba", "cx") == 2, 2); /* Partial. */ + check(strcspn("abc", "abc") == 0, 3); /* None. */ + check(strcspn("", "ab") == 0, 4); /* Null string. */ + check(strcspn("abc", "") == 3, 5); /* Null search list. */ + + /* + * strtok - the hard one + */ + it = "strtok"; + (void) strcpy(one, "first, second, third"); + equal(strtok(one, ", "), "first", 1); /* Basic test. */ + equal(one, "first", 2); + equal(strtok((char *)NULL, ", "), "second", 3); + equal(strtok((char *)NULL, ", "), "third", 4); + check(strtok((char *)NULL, ", ") == NULL, 5); + (void) strcpy(one, ", first, "); + equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */ + check(strtok((char *)NULL, ", ") == NULL, 7); + (void) strcpy(one, "1a, 1b; 2a, 2b"); + equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */ + equal(strtok((char *)NULL, "; "), "1b", 9); + equal(strtok((char *)NULL, ", "), "2a", 10); + (void) strcpy(two, "x-y"); + equal(strtok(two, "-"), "x", 11); /* New string before done. */ + equal(strtok((char *)NULL, "-"), "y", 12); + check(strtok((char *)NULL, "-") == NULL, 13); + (void) strcpy(one, "a,b, c,, ,d"); + equal(strtok(one, ", "), "a", 14); /* Different separators. */ + equal(strtok((char *)NULL, ", "), "b", 15); + equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */ + equal(strtok((char *)NULL, " ,"), "d", 17); + check(strtok((char *)NULL, ", ") == NULL, 18); + check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */ + (void) strcpy(one, ", "); + check(strtok(one, ", ") == NULL, 20); /* No tokens. */ + (void) strcpy(one, ""); + check(strtok(one, ", ") == NULL, 21); /* Empty string. */ + (void) strcpy(one, "abc"); + equal(strtok(one, ", "), "abc", 22); /* No delimiters. */ + check(strtok((char *)NULL, ", ") == NULL, 23); + (void) strcpy(one, "abc"); + equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */ + check(strtok((char *)NULL, "") == NULL, 25); + (void) strcpy(one, "abcdefgh"); + (void) strcpy(one, "a,b,c"); + equal(strtok(one, ","), "a", 26); /* Basics again... */ + equal(strtok((char *)NULL, ","), "b", 27); + equal(strtok((char *)NULL, ","), "c", 28); + check(strtok((char *)NULL, ",") == NULL, 29); + equal(one+6, "gh", 30); /* Stomped past end? */ + equal(one, "a", 31); /* Stomped old tokens? */ + equal(one+2, "b", 32); + equal(one+4, "c", 33); + + /* + * memcmp + */ + it = "memcmp"; + check(memcmp("a", "a", 1) == 0, 1); /* Identity. */ + check(memcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */ + check(memcmp("abcd", "abce", 4) < 0, 3); /* Honestly unequal. */ + check(memcmp("abce", "abcd", 4) > 0, 4); + check(memcmp("alph", "beta", 4) < 0, 5); + if (charsigned) /* Sign-bit comparison. */ + check(memcmp("a\203", "a\003", 2) < 0, 6); + else + check(memcmp("a\203", "a\003", 2) > 0, 6); + check(memcmp("abce", "abcd", 3) == 0, 7); /* Count limited. */ + check(memcmp("abc", "def", 0) == 0, 8); /* Zero count. */ + + /* + * memchr + */ + it = "memchr"; + check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */ + (void) strcpy(one, "abcd"); + check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */ + check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */ + check(memchr(one, 'a', 4) == one, 4); /* Beginning. */ + check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */ + (void) strcpy(one, "ababa"); + check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */ + check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */ + check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */ + (void) strcpy(one, "a\203b"); + check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */ + + /* + * memcpy + * + * Note that X3J11 says memcpy must work regardless of overlap. + * The SVID says it might fail. + */ + it = "memcpy"; + check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */ + equal(one, "abc", 2); /* Did the copy go right? */ + + (void) strcpy(one, "abcdefgh"); + (void) memcpy(one+1, "xyz", 2); + equal(one, "axydefgh", 3); /* Basic test. */ + + (void) strcpy(one, "abc"); + (void) memcpy(one, "xyz", 0); + equal(one, "abc", 4); /* Zero-length copy. */ + + (void) strcpy(one, "hi there"); + (void) strcpy(two, "foo"); + (void) memcpy(two, one, 9); + equal(two, "hi there", 5); /* Just paranoia. */ + equal(one, "hi there", 6); /* Stomped on source? */ + + (void) strcpy(one, "abcdefgh"); + (void) memcpy(one+1, one, 9); + equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */ + + (void) strcpy(one, "abcdefgh"); + (void) memcpy(one+1, one+2, 7); + equal(one, "acdefgh", 8); /* Overlap, left-to-right. */ + + (void) strcpy(one, "abcdefgh"); + (void) memcpy(one, one, 9); + equal(one, "abcdefgh", 9); /* 100% overlap. */ + + /* + * memccpy - first test like memcpy, then the search part + * + * The SVID, the only place where memccpy is mentioned, says + * overlap might fail, so we don't try it. Besides, it's hard + * to see the rationale for a non-left-to-right memccpy. + */ + it = "memccpy"; + check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */ + equal(one, "abc", 2); /* Did the copy go right? */ + + (void) strcpy(one, "abcdefgh"); + (void) memccpy(one+1, "xyz", 'q', 2); + equal(one, "axydefgh", 3); /* Basic test. */ + + (void) strcpy(one, "abc"); + (void) memccpy(one, "xyz", 'q', 0); + equal(one, "abc", 4); /* Zero-length copy. */ + + (void) strcpy(one, "hi there"); + (void) strcpy(two, "foo"); + (void) memccpy(two, one, 'q', 9); + equal(two, "hi there", 5); /* Just paranoia. */ + equal(one, "hi there", 6); /* Stomped on source? */ + + (void) strcpy(one, "abcdefgh"); + (void) strcpy(two, "horsefeathers"); + check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */ + equal(one, "abcdefgh", 8); /* Source intact? */ + equal(two, "abcdefeathers", 9); /* Copy correct? */ + + (void) strcpy(one, "abcd"); + (void) strcpy(two, "bumblebee"); + check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */ + equal(two, "aumblebee", 11); + check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */ + equal(two, "abcdlebee", 13); + (void) strcpy(one, "xyz"); + check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */ + equal(two, "xbcdlebee", 15); + + /* + * memset + */ + it = "memset"; + (void) strcpy(one, "abcdefgh"); + check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */ + equal(one, "axxxefgh", 2); /* Basic test. */ + + (void) memset(one+2, 'y', 0); + equal(one, "axxxefgh", 3); /* Zero-length set. */ + + (void) memset(one+5, 0, 1); + equal(one, "axxxe", 4); /* Zero fill. */ + equal(one+6, "gh", 5); /* And the leftover. */ + + (void) memset(one+2, 010045, 1); + equal(one, "ax\045xe", 6); /* Unsigned char convert. */ + + /* + * bcopy - much like memcpy + * + * Berklix manual is silent about overlap, so don't test it. + */ + it = "bcopy"; + (void) bcopy("abc", one, 4); + equal(one, "abc", 1); /* Simple copy. */ + + (void) strcpy(one, "abcdefgh"); + (void) bcopy("xyz", one+1, 2); + equal(one, "axydefgh", 2); /* Basic test. */ + + (void) strcpy(one, "abc"); + (void) bcopy("xyz", one, 0); + equal(one, "abc", 3); /* Zero-length copy. */ + + (void) strcpy(one, "hi there"); + (void) strcpy(two, "foo"); + (void) bcopy(one, two, 9); + equal(two, "hi there", 4); /* Just paranoia. */ + equal(one, "hi there", 5); /* Stomped on source? */ + + /* + * bzero + */ + it = "bzero"; + (void) strcpy(one, "abcdef"); + bzero(one+2, 2); + equal(one, "ab", 1); /* Basic test. */ + equal(one+3, "", 2); + equal(one+4, "ef", 3); + + (void) strcpy(one, "abcdef"); + bzero(one+2, 0); + equal(one, "abcdef", 4); /* Zero-length copy. */ + + /* + * bcmp - somewhat like memcmp + */ + it = "bcmp"; + check(bcmp("a", "a", 1) == 0, 1); /* Identity. */ + check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */ + check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */ + check(bcmp("abce", "abcd", 4) != 0, 4); + check(bcmp("alph", "beta", 4) != 0, 5); + check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */ + check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */ + +#ifdef ERR + /* + * strerror - VERY system-dependent + */ + it = "strerror"; + f = open("/", 1); /* Should always fail. */ + check(f < 0 && errno > 0 && errno < sys_nerr, 1); + equal(strerror(errno), sys_errlist[errno], 2); +#ifdef UNIXERR + equal(strerror(errno), "Is a directory", 3); +#endif +#ifdef BERKERR + equal(strerror(errno), "Permission denied", 3); +#endif +#endif +} diff --git a/dmake/dbug/malloc/testmlc.c b/dmake/dbug/malloc/testmlc.c new file mode 100644 index 000000000000..16e11736cc18 --- /dev/null +++ b/dmake/dbug/malloc/testmlc.c @@ -0,0 +1,176 @@ +/* NOT copyright by SoftQuad Inc. -- msb, 1988 */ +#ifndef lint +static char *SQ_SccsId = "@(#)mtest3.c 1.2 88/08/25"; +#endif +#include <stdio.h> +/* +** looptest.c -- intensive allocator tester +** +** Usage: looptest +** +** History: +** 4-Feb-1987 rtech!daveb +*/ + +# ifdef SYS5 +# define random rand +# else +# include <sys/vadvise.h> +# endif + +# include <stdio.h> +# include <signal.h> +# include <setjmp.h> + +# define MAXITER 1000000 /* main loop iterations */ +# define MAXOBJS 1000 /* objects in pool */ +# define BIGOBJ 90000 /* max size of a big object */ +# define TINYOBJ 80 /* max size of a small object */ +# define BIGMOD 100 /* 1 in BIGMOD is a BIGOBJ */ +# define STATMOD 10000 /* interation interval for status */ + +main( argc, argv ) +int argc; +char **argv; +{ + register int **objs; /* array of objects */ + register int *sizes; /* array of object sizes */ + register int n; /* iteration counter */ + register int i; /* object index */ + register int size; /* object size */ + register int r; /* random number */ + + int objmax; /* max size this iteration */ + int cnt; /* number of allocated objects */ + int nm = 0; /* number of mallocs */ + int nre = 0; /* number of reallocs */ + int nal; /* number of allocated objects */ + int nfre; /* number of free list objects */ + long alm; /* memory in allocated objects */ + long frem; /* memory in free list */ + long startsize; /* size at loop start */ + long endsize; /* size at loop exit */ + long maxiter = 0; /* real max # iterations */ + + extern char end; /* memory before heap */ + char *calloc(); + char *malloc(); + char *sbrk(); + long atol(); + +# ifndef SYS5 + /* your milage may vary... */ + vadvise( VA_ANOM ); +# endif + + if (argc > 1) + maxiter = atol (argv[1]); + if (maxiter <= 0) + maxiter = MAXITER; + + printf("MAXITER %d MAXOBJS %d ", maxiter, MAXOBJS ); + printf("BIGOBJ %d, TINYOBJ %d, nbig/ntiny 1/%d\n", + BIGOBJ, TINYOBJ, BIGMOD ); + fflush( stdout ); + + if( NULL == (objs = (int **)calloc( MAXOBJS, sizeof( *objs ) ) ) ) + { + fprintf(stderr, "Can't allocate memory for objs array\n"); + exit(1); + } + + if( NULL == ( sizes = (int *)calloc( MAXOBJS, sizeof( *sizes ) ) ) ) + { + fprintf(stderr, "Can't allocate memory for sizes array\n"); + exit(1); + } + + /* as per recent discussion on net.lang.c, calloc does not + ** necessarily fill in NULL pointers... + */ + for( i = 0; i < MAXOBJS; i++ ) + objs[ i ] = NULL; + + startsize = sbrk(0) - &end; + printf( "Memory use at start: %d bytes\n", startsize ); + fflush(stdout); + + printf("Starting the test...\n"); + fflush(stdout); + for( n = 0; n < maxiter ; n++ ) + { + if( !(n % STATMOD) ) + { + printf("%d iterations\n", n); + fflush(stdout); + } + + /* determine object of interst and it's size */ + + r = random(); + objmax = ( r % BIGMOD ) ? TINYOBJ : BIGOBJ; + size = r % objmax; + i = r % (MAXOBJS - 1); + + /* either replace the object of get a new one */ + + if( objs[ i ] == NULL ) + { + objs[ i ] = (int *)malloc( size ); + nm++; + } + else + { + /* don't keep bigger objects around */ + if( size > sizes[ i ] ) + { + objs[ i ] = (int *)realloc( objs[ i ], size ); + nre++; + } + else + { + free( objs[ i ] ); + objs[ i ] = (int *)malloc( size ); + nm++; + } + } + + sizes[ i ] = size; + if( objs[ i ] == NULL ) + { + printf("\nCouldn't allocate %d byte object!\n", + size ); + break; + } + } /* for() */ + + printf( "\n" ); + cnt = 0; + for( i = 0; i < MAXOBJS; i++ ) + if( objs[ i ] ) + cnt++; + + printf( "Did %d iterations, %d objects, %d mallocs, %d reallocs\n", + n, cnt, nm, nre ); + printf( "Memory use at end: %d bytes\n", sbrk(0) - &end ); + fflush( stdout ); + + /* free all the objects */ + for( i = 0; i < MAXOBJS; i++ ) + if( objs[ i ] != NULL ) + free( objs[ i ] ); + + endsize = sbrk(0) - &end; + printf( "Memory use after free: %d bytes\n", endsize ); + fflush( stdout ); + + if( startsize != endsize ) + printf("startsize %d != endsize %d\n", startsize, endsize ); + + free( objs ); + free( sizes ); + + malloc_dump(2); + exit( 0 ); +} + diff --git a/dmake/dbug/malloc/tostring.c b/dmake/dbug/malloc/tostring.c new file mode 100644 index 000000000000..5d04a1e7e282 --- /dev/null +++ b/dmake/dbug/malloc/tostring.c @@ -0,0 +1,169 @@ +/* + * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). + * You may copy, distribute, and use this software as long as this + * copyright statement is not removed. + */ +#include "tostring.h" + +/* + * Function: tostring() + * + * Purpose: to convert an integer to an ascii display string + * + * Arguments: buf - place to put the + * val - integer to convert + * len - length of output field (0 if just enough to hold data) + * base - base for number conversion (only works for base <= 16) + * fill - fill char when len > # digits + * + * Returns: length of string + * + * Narrative: IF fill character is non-blank + * Determine base + * If base is HEX + * add "0x" to begining of string + * IF base is OCTAL + * add "0" to begining of string + * + * While value is greater than zero + * use val % base as index into xlation str to get cur char + * divide val by base + * + * Determine fill-in length + * + * Fill in fill chars + * + * Copy in number + * + * + * Mod History: + * 90/01/24 cpcahil Initial revision. + */ + +#ifndef lint +static +char rcs_hdr[] = "$Id: tostring.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $"; +#endif + +#define T_LEN 10 + +int +tostring(buf,val,len,base,fill) + int base; + char * buf; + char fill; + int len; + int val; + +{ + char * bufstart = buf; + int i = T_LEN; + char * xbuf = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + char tbuf[T_LEN]; + + /* + * if we are filling with non-blanks, make sure the + * proper start string is added + */ + if( fill != ' ' ) + { + switch(base) + { + case B_HEX: + *(buf++) = '0'; + *(buf++) = 'x'; + if( len ) + { + len -= 2; + } + break; + case B_OCTAL: + *(buf++) = fill; + if( len ) + { + len--; + } + break; + default: + break; + } + } + + while( val > 0 ) + { + tbuf[--i] = xbuf[val % base]; + val = val / base; + } + + if( len ) + { + len -= (T_LEN - i); + + if( len > 0 ) + { + while(len-- > 0) + { + *(buf++) = fill; + } + } + else + { + /* + * string is too long so we must truncate + * off some characters. We do this the easiest + * way by just incrementing i. This means the + * most significant digits are lost. + */ + while( len++ < 0 ) + { + i++; + } + } + } + + while( i < T_LEN ) + { + *(buf++) = tbuf[i++]; + } + + return( (int) (buf - bufstart) ); + +} /* tostring(... */ + +/* + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1997/09/22 14:51:11 hjs + * dmake 4.1 orginal sourcen + * + * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura + * dmake gold 4.1.00 initial import + * + * Revision 1.1.1.1 1996/10/27 07:30:15 dvadura + * Dmake 4.1 Initial Import + * + * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura + * Initial import for final release of dmake 4.1 + * + * Revision 1.1 1994/10/06 17:43:20 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1994/10/06 03:45:29 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1992/01/24 03:29:16 dvadura + * dmake Version 3.8, Initial revision + * + * Revision 1.4 90/05/11 00:13:11 cpcahil + * added copyright statment + * + * Revision 1.3 90/02/24 21:50:33 cpcahil + * lots of lint fixes + * + * Revision 1.2 90/02/24 17:29:42 cpcahil + * changed $Header to $Id so full path wouldnt be included as part of rcs + * id string + * + * Revision 1.1 90/02/22 23:17:44 cpcahil + * Initial revision + * + */ diff --git a/dmake/dbug/malloc/tostring.h b/dmake/dbug/malloc/tostring.h new file mode 100644 index 000000000000..566ae2bedf77 --- /dev/null +++ b/dmake/dbug/malloc/tostring.h @@ -0,0 +1,43 @@ +/* + * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil). + * You may copy, distribute, and use this software as long as this + * copyright statement is not removed. + */ +/* + * $Id: tostring.h,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $ + */ +#define B_BIN 2 +#define B_DEC 10 +#define B_HEX 16 +#define B_OCTAL 8 + +/* + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1997/09/22 14:51:11 hjs + * dmake 4.1 orginal sourcen + * + * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura + * dmake gold 4.1.00 initial import + * + * Revision 1.1.1.1 1996/10/27 07:30:15 dvadura + * Dmake 4.1 Initial Import + * + * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura + * Initial import for final release of dmake 4.1 + * + * Revision 1.1 1994/10/06 17:43:20 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1994/10/06 03:45:30 dvadura + * dmake Release Version 4.0, Initial revision + * + * Revision 1.1 1992/01/24 03:29:17 dvadura + * dmake Version 3.8, Initial revision + * + * Revision 1.2 90/05/11 00:13:11 cpcahil + * added copyright statment + * + * Revision 1.1 90/02/23 07:09:05 cpcahil + * Initial revision + * + */ |