source: trunk/third/kermit/ckcmdb.c @ 10780

Revision 10780, 7.7 KB checked in by brlewis, 27 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r10779, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2  C K C M D B . C  --  malloc debugger.
3*/
4
5/*
6  Author: Howie Kaye, Columbia University Center for Computing Activities.
7  Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
8  York.  Permission is granted to any individual or institution to use this
9  software as long as it is not sold for profit.  This copyright notice must be
10  retained.  This software may not be included in commercial products without
11  written permission of Columbia University.
12*/
13/* Use the real ones in this module! */
14#ifdef malloc
15#undef malloc
16#endif /* malloc */
17#ifdef calloc
18#undef calloc
19#endif /* calloc */
20#ifdef realloc
21#undef realloc
22#endif /* realloc */
23#ifdef free
24#undef free
25#endif /* free */
26
27#include "ckcsym.h"
28#include <stdio.h>
29#include "ckcdeb.h"
30
31#ifdef COHERENT
32_PROTOTYP ( FILE * fdopen, (int, char *) );
33#endif /* COHERENT */
34
35/*
36  memdebug:
37  variable to control memory debugging.
38  if memdebug ==  1, then action is always taken.
39  if memdebug ==  0, then no action is taken.
40  if memdebug == -1, then the user is asked (works well with gdb).
41*/
42int memdebug = -1;
43int disabled = 0;
44int inited = 0;
45/*
46  To use this package, compile your program with:
47  -Dmalloc=dmalloc -Dfree=dfree =Dcalloc=dcalloc ... -DMDEBUG
48  and then link it with ckcmdb.c.
49*/
50#ifdef MDEBUG
51
52#ifndef M_SIZE_T
53#ifdef NEXT
54#define M_SIZE_T size_t
55#else
56#ifdef SUNOS41
57#define M_SIZE_T unsigned
58#else
59#define M_SIZE_T int
60#endif /* SUNOS41 */
61#endif /* NEXT */
62#endif /* M_SIZE_T */
63
64#ifdef CK_ANSIC
65_PROTOTYP( void free, (void *) );
66_PROTOTYP( void * malloc, (size_t) );
67_PROTOTYP( void * realloc, (void *, size_t) );
68#else
69_PROTOTYP( VOID free, (char *) );
70_PROTOTYP( char * malloc, (M_SIZE_T) );
71_PROTOTYP( char * realloc, (char *, M_SIZE_T) );
72#endif /* NEXT */
73
74_PROTOTYP( VOID m_insert, (char *) );
75_PROTOTYP( int m_delete, (char *) );
76
77_PROTOTYP( char * dmalloc, (int) );
78_PROTOTYP( char * dcalloc, (int, int) );
79_PROTOTYP( char * drealloc, (char *, int) );
80
81_PROTOTYP( char *set_range_check, (char *, int) );
82_PROTOTYP( char *check_range, (char *) );
83_PROTOTYP( static char *maybe_check_range, (char *) );
84
85_PROTOTYP( static VOID maybe_quit, (char *) );
86_PROTOTYP( static int ask, (char *) );
87
88#define min(x,y) ((x) < (y) ? (x) : (y))
89#define RANGE "ABCDEFGHIJKLMNOP"
90#define INTSIZE  sizeof(int)
91#define LONGSIZE sizeof(long)
92#define RSIZE    sizeof(RANGE)
93#define RFRONT   min((RSIZE/2),LONGSIZE)
94#define RBACK    min((RSIZE-RFRONT),LONGSIZE)
95
96char *
97dmalloc(size) int size; {
98    char *cp;
99
100    cp = malloc(size + RSIZE + INTSIZE);
101    if (cp) {
102        cp = set_range_check(cp, size);
103        m_insert(cp);
104    }
105    return(cp);
106}
107
108char *
109dcalloc(nelem, elsize) int nelem, elsize; {
110    char *cp;
111
112    cp = dmalloc(nelem * elsize);
113    if (cp)
114        bzero(cp, nelem * elsize);
115    return(cp);
116}
117
118char *
119drealloc(bp,size) char *bp; int size; {
120    char *cp;
121
122    if (bp == NULL) {
123        maybe_quit("Freeing NULL pointer");
124    } else {
125        m_delete(bp);
126        cp = check_range(bp);
127    }
128    cp = realloc(cp, size + RSIZE + INTSIZE);
129    if (cp) {
130        cp = set_range_check(cp, size);
131        m_insert(cp);
132    }
133    return(cp);
134}
135
136VOID
137dfree(cp) char *cp; {
138    if (cp == NULL)
139        maybe_quit("Freeing NULL pointer");
140    else {
141        switch(m_delete(cp)) {
142        case 0:
143            cp = maybe_check_range(cp);
144            break;
145        case 1:
146            cp = check_range(cp);
147            break;
148        case 2:
149            break;
150        }
151    }
152#ifndef CK_ANSIC
153    return(free(cp));
154#endif /* CK_ANSIC */
155}
156
157char *
158set_range_check(cp,size) char *cp; int size; {
159    register int i;
160    int tmp = size;
161
162    for(i = 0; i < INTSIZE; i++) {      /* set the size in the string */
163        cp[i] = tmp & 0xff;
164        tmp >>= 8;
165    }
166    cp += INTSIZE;                      /* skip the size */
167
168    for(i = 0; i < RFRONT; i++)         /* set the front of the range check */
169        cp[i] = RANGE[i];               /* string */
170
171    cp += RFRONT;                       /* skip the front range check */
172
173    for(i = 0; i < RBACK; i++)          /* set the back odf the range check */
174        cp[i+size] = RANGE[i+RFRONT];
175
176    return(cp);
177}
178
179/*
180  Put calls to this routine in your code any place where you want to
181  check whether you've copied too many characters into a malloc'd space.
182*/
183char *
184check_range(cp) char *cp; {
185    register char *bp = cp - RFRONT - INTSIZE;
186    char *xp = bp;
187    register int i;
188    int size = 0;
189
190    for(i = 0 ; i < INTSIZE; i++) {     /* get the size out of the string */
191        size <<= 8;
192        size |= bp[INTSIZE-i-1] & 0xff;
193    }
194    bp += INTSIZE;
195
196    for(i = 0; i < RFRONT; i++)         /* check front range check */
197        if (bp[i] != RANGE[i]) {
198            maybe_quit("leftside malloc buffer overrun");
199            break;
200        }
201    bp += RFRONT;                       /* skip front range check */
202
203    for(i = 0; i < RBACK; i++)          /* check back range check */
204        if (bp[i+size] != RANGE[i+RFRONT]) {
205            maybe_quit("rightside malloc buffer overrun");
206            break;
207        }
208    return(xp);
209}
210
211static char *
212maybe_check_range(cp) char *cp; {
213    register char *bp = cp - RFRONT - INTSIZE;
214    char *xp = bp;
215    register int i;
216    int size = 0;
217
218    for(i = 0 ; i < INTSIZE; i++) {     /* get the size out of the string */
219        size <<= 8;
220        size |= bp[INTSIZE-i-1] & 0xff;
221    }
222    bp += INTSIZE;
223
224    for(i = 0; i < RFRONT; i++)         /* check front range check */
225        if (bp[i] != RANGE[i]) {
226            return(cp);
227        }
228    bp += RFRONT;                       /* skip front range check */
229
230    for(i = 0; i < RBACK; i++)          /* check back range check */
231        if (bp[i+size] != RANGE[i+RFRONT]) {
232            fprintf(stderr,"rightside malloc buffer overrun\n");
233            abort();
234            break;
235        }
236    return(xp);
237}
238
239#define BUCKETS 10000
240char *m_used[BUCKETS];
241char *m_used2[BUCKETS];
242
243VOID
244m_insert(cp) register char *cp; {
245    register int i;
246
247    if (disabled)
248        return;
249
250    for(i = 0; i < BUCKETS; i++)
251        if (m_used[i] == 0) {
252            m_used[i] = cp;
253            return;
254        }
255    disabled ++;
256}
257
258static
259m_insert2(cp) register char *cp; {
260    register int i;
261
262    if (disabled)
263        return;
264    for(i = 0; i < BUCKETS; i++)
265        if (m_used2[i] == 0) {
266            m_used2[i] = cp;
267            return;
268        }
269    disabled ++;
270}
271
272int
273m_delete(cp) register char *cp; {
274    register int i;
275
276    for(i = 0; i < BUCKETS; i++)
277        if (m_used[i] == cp) {
278            m_used[i] = 0;
279            return(1);
280        }
281    for(i = 0; i < BUCKETS; i++)
282        if (m_used2[i] == cp) {
283            m_used2[i] = 0;
284            return(2);
285        }
286    if (disabled)
287        return(0);
288
289    maybe_quit("Freeing unmalloc'ed pointer");
290    return(0);
291}
292
293VOID
294m_init() {
295    register int i;
296
297    inited = 1;
298    disabled = 0;
299#ifdef NEXT
300    malloc_debug(2+4+8+16);
301#endif /* NEXT */
302
303    for(i = 0; i < BUCKETS; i++)
304      m_used[i] = 0;
305}
306
307VOID
308m_done() {
309    register int i,j=0;
310
311    if (disabled)
312        return;
313    for(i = 0; i < BUCKETS; i++)
314        if (m_used[i] != 0) {
315            if (memdebug) {
316                if (j == 0)
317                    fprintf(stderr,"unfree'ed buffers, indices: ");
318                fprintf(stderr,"%d, ", i);
319                j++;
320            }
321        }
322    if (j)
323        fprintf(stderr,"\n");
324    for(i = 0; i < BUCKETS; i++)
325        if (m_used2[i] != 0) {
326            if (memdebug) {
327                if (j == 0)
328                    fprintf(stderr,"unfree'ed registered buffers, indices: ");
329                fprintf(stderr,"%d, ", i);
330                j++;
331            }
332        }
333    if (j)
334        fprintf(stderr,"\n");
335    if (j)
336        maybe_quit("Unfree'ed malloc buffers");
337}
338
339VOID
340m_checkranges() {
341    int i;
342
343    for ( i = 0; i < BUCKETS; i++)
344        if (m_used[i])
345            check_range(m_used[i]);
346}
347
348static VOID
349maybe_quit(str) char *str; {
350    debug(F100,"mdebug maybe_quit","",0);
351    if (memdebug == 0)
352        return;
353    fprintf(stderr,"%s\n",str);
354    if (memdebug == 1)
355        abort();
356    if (memdebug == -1)
357        if (ask("Quit? "))
358            abort();
359}
360
361static int
362ask(str) char *str; {
363    char buf[100];
364    FILE *in;
365    int fd;
366   
367    fd = dup(fileno(stdin));
368    in = fdopen(fd, "r");
369    while(1) {
370        fprintf(stderr,str);
371        fflush(stderr);
372        if (fgets(buf, 99, in) == NULL) /* EOF? */
373            return(0);
374        if (buf[0] == 'n' || buf[0] == 'N') {
375            fclose(in);
376            return(0);
377        }
378        if (buf[0] == 'y' || buf[0] == 'Y') {
379            fclose(in);
380            return(1);
381        }
382        fprintf(stderr,"please answer y/n.\n");
383    }
384}
385#endif /* MDEBUG */
Note: See TracBrowser for help on using the repository browser.