1 /*
2  * mpatrol
3  * A library for controlling and tracing dynamic memory allocations.
4  * Copyright (C) 1997-2002 Graeme S. Roy <graeme.roy@analog.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the Free
18  * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19  * MA 02111-1307, USA.
20  */
21 
22 
23 /*
24  * Release version of library interface.  This module defines the visible
25  * interface for the mpatrol library in release mode.  These functions
26  * should not normally be required if all of the source files that use
27  * mpatrol.h were recompiled with NDEBUG, but they are defined here just
28  * in case.
29  */
30 
31 
32 #include "inter.h"
33 #include "mpalloc.h"
34 #include "version.h"
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <stdarg.h>
39 #if TARGET == TARGET_UNIX
40 #include <unistd.h>
41 #if SYSTEM == SYSTEM_LINUX
42 #include <malloc.h>
43 #endif /* SYSTEM */
44 #elif TARGET == TARGET_WINDOWS
45 #include <windows.h>
46 #include <winbase.h>
47 #elif TARGET == TARGET_NETWARE
48 #include <nwthread.h>
49 #include <nks/memory.h>
50 #endif /* TARGET */
51 
52 
53 #if MP_IDENT_SUPPORT
54 #ident "$Id: mpalloc.c,v 1.44 2002/01/08 20:13:59 graeme Exp $"
55 #else /* MP_IDENT_SUPPORT */
56 static MP_CONST MP_VOLATILE char *mpalloc_id = "$Id: mpalloc.c,v 1.44 2002/01/08 20:13:59 graeme Exp $";
57 #endif /* MP_IDENT_SUPPORT */
58 
59 
60 /* An allocaheader belongs to a stack of memory allocations that were made
61  * by the alloca() and related functions.  Some memory allocations at the
62  * top of the stack may be automatically freed when the next call to allocate
63  * memory is made and the stack has been unwound.
64  */
65 
66 typedef union allocaheader
67 {
68 #if MP_LONGLONG_SUPPORT
69   long long integer;            /* type with most restrictive alignment */
70 #else /* MP_LONGLONG_SUPPORT */
71   long integer;                 /* type with most restrictive alignment */
72 #endif /* MP_LONGLONG_SUPPORT */
73   long double real;             /* type with most restrictive alignment */
74   struct
75   {
76       union allocaheader *next; /* pointer to next allocaheader */
77       void *frame;              /* pointer to stack frame */
78   }
79   data;
80 }
81 allocaheader;
82 
83 
84 #ifdef __cplusplus
85 extern "C"
86 {
87 #endif /* __cplusplus */
88 
89 
90 /* The stack of allocaheaders that is used to keep track of the details of
91  * (and when to free) memory allocated with alloca() and related functions.
92  */
93 
94 static allocaheader *allocastack;
95 
96 
97 /* Terminate the program after an mpatrol function has been called with an
98  * illegal function type.
99  */
100 
101 static
102 void
illegalfunction(char * f,char * s,char * t,unsigned long u)103 illegalfunction(char *f, char *s, char *t, unsigned long u)
104 {
105     fputs("fatal error", stderr);
106     if (s != NULL)
107         fprintf(stderr, " in %s", s);
108     if ((t != NULL) && (u != 0))
109         fprintf(stderr, " in %s line %lu", t, u);
110     fputc('\n', stderr);
111     fprintf(stderr, "mpatrol function %s called with illegal function type\n",
112             f);
113     fflush(NULL);
114     exit(EXIT_FAILURE);
115 }
116 
117 
118 /* Round an unsigned integer up to the nearest power of two.
119  */
120 
121 static
122 unsigned long
poweroftwo(unsigned long n)123 poweroftwo(unsigned long n)
124 {
125     unsigned char l;
126 
127     if ((n == 0) || ((n & (n - 1)) == 0))
128         return n;
129     for (l = 0; n > 0; l++, n >>= 1);
130     return (unsigned long) (2 << (l - 1));
131 }
132 
133 
134 /* Return the system page size.
135  */
136 
137 static
138 size_t
pagesize(void)139 pagesize(void)
140 {
141     static size_t s;
142 #if TARGET == TARGET_WINDOWS
143     SYSTEM_INFO i;
144 #endif /* TARGET */
145 
146     if (s == 0)
147     {
148 #if TARGET == TARGET_UNIX
149         /* This call could also be getpagesize() but it is more POSIX-conforming
150          * to call sysconf().  Unfortunately, SunOS and the BSD systems only
151          * have getpagesize().
152          */
153 #if SYSTEM == SYSTEM_FREEBSD || SYSTEM == SYSTEM_NETBSD || \
154     SYSTEM == SYSTEM_OPENBSD || SYSTEM == SYSTEM_SUNOS
155         s = getpagesize();
156 #else /* SYSTEM */
157         s = sysconf(_SC_PAGESIZE);
158 #endif /* SYSTEM */
159 #elif TARGET == TARGET_AMIGA
160         /* The Amiga has no virtual memory system (at least not supplied with
161          * AmigaOS), so we return a fixed value here because it doesn't really
162          * matter what the page size is.
163          */
164         s = 4096;
165 #elif TARGET == TARGET_WINDOWS
166         GetSystemInfo(&i);
167         s = i.dwPageSize;
168 #elif TARGET == TARGET_NETWARE
169         s = NXGetPageSize();
170 #else /* TARGET */
171     /* We just assume that any other operating systems have no virtual
172      * memory support and so anything we return here is irrelevant.
173      */
174     return 1024;
175 #endif /* TARGET */
176     }
177     return s;
178 }
179 
180 
181 /* Determine the stack direction on this system.
182  */
183 
184 static
185 int
stackdirection(void * p)186 stackdirection(void *p)
187 {
188     static int d;
189     unsigned long n;
190 
191     if (d == 0)
192     {
193         n = (unsigned long) &p;
194         if (p == NULL)
195             return stackdirection(&n);
196         else if (&n < (unsigned long *) p)
197             d = -1;
198         else
199             d = 1;
200     }
201     return d;
202 }
203 
204 
205 /* Check the alloca allocation stack for any allocations that should be freed.
206  */
207 
208 static
209 void
checkalloca(void * p)210 checkalloca(void *p)
211 {
212     allocaheader *m, *n;
213     int d;
214 
215     d = stackdirection(NULL);
216     for (n = allocastack; n != NULL; n = m)
217     {
218         m = n->data.next;
219         if (((d > 0) && ((char *) n->data.frame > (char *) p + 32)) ||
220             ((d < 0) && ((char *) n->data.frame + 32 < (char *) p)))
221         {
222             free(n);
223             allocastack = m;
224         }
225         else
226             break;
227     }
228 }
229 
230 
231 /* The last error encountered by the mpatrol library.
232  */
233 
234 MP_API errortype __mp_errno;
235 
236 
237 /* Initialise the mpatrol library.
238  */
239 
240 MP_API
241 void
__mp_init(void)242 __mp_init(void)
243 {
244 }
245 
246 
247 /* Reinitialise the mpatrol library.
248  */
249 
250 MP_API
251 void
__mp_reinit(void)252 __mp_reinit(void)
253 {
254 }
255 
256 
257 /* Finalise the mpatrol library.
258  */
259 
260 MP_API
261 void
__mp_fini(void)262 __mp_fini(void)
263 {
264 }
265 
266 
267 /* Provide a function which can be used as a breakpoint target in a debugger.
268  */
269 
270 MP_API
271 void
__mp_trap(void)272 __mp_trap(void)
273 {
274 }
275 
276 
277 /* Register a finalisation function to be called when __mp_fini() is called.
278  */
279 
280 MP_API
281 int
__mp_atexit(void (* f)(void))282 __mp_atexit(void (*f)(void))
283 {
284     if (atexit(f) == -1)
285         return 0;
286     return 1;
287 }
288 
289 
290 /* Set an mpatrol option after the library has been initialised.
291  */
292 
293 MP_API
294 unsigned long
__mp_setoption(long o,unsigned long v)295 __mp_setoption(long o, unsigned long v)
296 {
297     return ~0L;
298 }
299 
300 
301 /* Get an mpatrol option after the library has been initialised.
302  */
303 
304 MP_API
305 int
__mp_getoption(long o,unsigned long * v)306 __mp_getoption(long o, unsigned long *v)
307 {
308     return 0;
309 }
310 
311 
312 /* Return the memory header structure.
313  */
314 
315 MP_API
316 infohead *
__mp_memhead(void)317 __mp_memhead(void)
318 {
319     return NULL;
320 }
321 
322 
323 /* Allocate a new block of memory of a specified size and alignment.
324  */
325 
326 MP_API
327 void *
__mp_alloc(size_t l,size_t a,alloctype f,char * s,char * t,unsigned long u,char * g,size_t h,size_t k)328 __mp_alloc(size_t l, size_t a, alloctype f, char *s, char *t, unsigned long u,
329            char *g, size_t h, size_t k)
330 {
331     void *p;
332     size_t n;
333 
334     checkalloca(&l);
335     if (l == 0)
336         l = 1;
337     switch (f)
338     {
339       case AT_MALLOC:
340         p = malloc(l);
341         break;
342       case AT_CALLOC:
343         if (p = malloc(l))
344             memset(p, 0, l);
345         break;
346       case AT_MEMALIGN:
347       case AT_VALLOC:
348       case AT_PVALLOC:
349         /* We cannot rely on any system having implementations of memalign(),
350          * valloc() or pvalloc() and so we must either implement them with
351          * malloc() or with memalign() if it exists.  For the former
352          * implementation, this is done by allocating extra space and then
353          * rounding up the start address of the new allocation to the specified
354          * alignment.  This means that there is likely to be some space wasted
355          * for each allocation and the memory allocated by such functions
356          * cannot be freed with free().  The latter point is also likely to be
357          * true even if we allocated the memory with memalign().
358          */
359         n = pagesize();
360         if (f == AT_PVALLOC)
361             l = ((l - 1) & ~(n - 1)) + n;
362         if ((f == AT_VALLOC) || (f == AT_PVALLOC) || (a > n))
363             a = n;
364         else if (a < sizeof(long))
365             a = sizeof(long);
366         else
367             a = poweroftwo(a);
368 #if MP_MEMALIGN_SUPPORT
369         p = memalign(a, l);
370 #else /* MP_MEMALIGN_SUPPORT */
371         if (p = malloc(l + a - 1))
372             p = (void *) ((((unsigned long) p - 1) & ~(a - 1)) + a);
373 #endif /* MP_MEMALIGN_SUPPORT */
374         break;
375       case AT_ALLOCA:
376         p = __mp_xmalloc(l + sizeof(allocaheader), s, t, u, g, h);
377         ((allocaheader *) p)->data.next = allocastack;
378         ((allocaheader *) p)->data.frame = (void *) &l;
379         allocastack = (allocaheader *) p;
380         p = (char *) p + sizeof(allocaheader);
381         break;
382       case AT_XMALLOC:
383         p = __mp_xmalloc(l, s, t, u, g, h);
384         break;
385       case AT_XCALLOC:
386         p = __mp_xcalloc(l, s, t, u, g, h);
387         break;
388       case AT_NEW:
389       case AT_NEWVEC:
390         /* This implementation should really call the new handler if it
391          * has been installed, but for now just abort if no memory can be
392          * allocated.
393          */
394         p = __mp_xmalloc(l, s, t, u, g, h);
395         break;
396       default:
397         illegalfunction("__mp_alloc", s, t, u);
398         break;
399     }
400     return p;
401 }
402 
403 
404 /* Allocate a new block of memory to duplicate a string.
405  */
406 
407 MP_API
408 char *
__mp_strdup(char * p,size_t l,alloctype f,char * s,char * t,unsigned long u,size_t k)409 __mp_strdup(char *p, size_t l, alloctype f, char *s, char *t, unsigned long u,
410             size_t k)
411 {
412     char *r;
413     size_t i;
414 
415     checkalloca(&p);
416     if (f == AT_XSTRDUP)
417         return __mp_xstrdup(p, s, t, u);
418     i = strlen(p);
419     if ((f == AT_STRNDUP) || (f == AT_STRNSAVE) || (f == AT_STRNDUPA))
420     {
421         if (i > l)
422             i = l;
423     }
424     else if ((f != AT_STRDUP) && (f != AT_STRSAVE) && (f != AT_STRDUPA))
425         illegalfunction("__mp_strdup", s, t, u);
426     if ((f == AT_STRDUPA) || (f == AT_STRNDUPA))
427     {
428         r = (char *) __mp_xmalloc(i + sizeof(allocaheader) + 1, s, t, u, "char",
429                                   sizeof(char));
430         ((allocaheader *) r)->data.next = allocastack;
431         ((allocaheader *) r)->data.frame = (void *) &p;
432         allocastack = (allocaheader *) r;
433         r += sizeof(allocaheader);
434     }
435     else
436         r = (char *) malloc(i + 1);
437     if (r != NULL)
438     {
439         memcpy(r, p, i);
440         r[i] = '\0';
441     }
442     return r;
443 }
444 
445 
446 /* Resize an existing block of memory to a new size and alignment.
447  */
448 
449 MP_API
450 void *
__mp_realloc(void * p,size_t l,size_t a,alloctype f,char * s,char * t,unsigned long u,char * g,size_t h,size_t k)451 __mp_realloc(void *p, size_t l, size_t a, alloctype f, char *s, char *t,
452              unsigned long u, char *g, size_t h, size_t k)
453 {
454     void *q;
455 
456     checkalloca(&p);
457     if (f == AT_XREALLOC)
458         return __mp_xrealloc(p, l, s, t, u, g, h);
459     else if ((f != AT_REALLOC) && (f != AT_REALLOCF) && (f != AT_RECALLOC) &&
460              (f != AT_EXPAND))
461         illegalfunction("__mp_realloc", s, t, u);
462     /* There is a major limitation here in that we don't know the size of
463      * the existing memory allocation.  This means that we can't implement
464      * recalloc() or expand() properly, and in the latter case means that
465      * we must always return NULL.  If you have existing implementations
466      * of these functions on your system then you could make calls to them
467      * here.
468      */
469     if (p == NULL)
470     {
471         if (l == 0)
472             l = 1;
473         if ((p = malloc(l)) && (f == AT_RECALLOC))
474             memset(p, 0, l);
475     }
476     else if (l == 0)
477     {
478         free(p);
479         p = NULL;
480     }
481     else if (f == AT_REALLOCF)
482     {
483         if ((q = realloc(p, l)) == NULL)
484             free(p);
485         p = q;
486     }
487     else if (f != AT_EXPAND)
488         p = realloc(p, l);
489     else
490         p = NULL;
491     return p;
492 }
493 
494 
495 /* Free an existing block of memory.
496  */
497 
498 MP_API
499 void
__mp_free(void * p,alloctype f,char * s,char * t,unsigned long u,size_t k)500 __mp_free(void *p, alloctype f, char *s, char *t, unsigned long u, size_t k)
501 {
502     checkalloca(&p);
503     if ((f != AT_FREE) && (f != AT_CFREE) && (f != AT_DEALLOCA) &&
504         (f != AT_XFREE) && (f != AT_DELETE) && (f != AT_DELETEVEC))
505         illegalfunction("__mp_free", s, t, u);
506     if (f != AT_DEALLOCA)
507         free(p);
508 }
509 
510 
511 /* Set a block of memory to contain a specific byte.
512  */
513 
514 MP_API
515 void *
__mp_setmem(void * p,size_t l,unsigned char c,alloctype f,char * s,char * t,unsigned long u,size_t k)516 __mp_setmem(void *p, size_t l, unsigned char c, alloctype f, char *s, char *t,
517             unsigned long u, size_t k)
518 {
519     if ((f != AT_MEMSET) && (f != AT_BZERO))
520         illegalfunction("__mp_setmem", s, t, u);
521     return memset(p, (int) c, l);
522 }
523 
524 
525 /* Copy a block of memory from one address to another.
526  */
527 
528 MP_API
529 void *
__mp_copymem(void * p,void * q,size_t l,unsigned char c,alloctype f,char * s,char * t,unsigned long u,size_t k)530 __mp_copymem(void *p, void *q, size_t l, unsigned char c, alloctype f, char *s,
531              char *t, unsigned long u, size_t k)
532 {
533     void *r;
534 
535     switch (f)
536     {
537       case AT_MEMCCPY:
538         if (r = memchr(p, (int) c, l))
539             l = (size_t) ((char *) r - (char *) p) + 1;
540         memcpy(q, p, l);
541         if (r != NULL)
542             q = (char *) q + l;
543         else
544             q = NULL;
545         break;
546       case AT_MEMCPY:
547         memcpy(q, p, l);
548         break;
549       case AT_MEMMOVE:
550       case AT_BCOPY:
551         memmove(q, p, l);
552         break;
553       default:
554         illegalfunction("__mp_copymem", s, t, u);
555         break;
556     }
557     return q;
558 }
559 
560 
561 /* Attempt to locate the position of one block of memory in another block.
562  */
563 
564 MP_API
565 void *
__mp_locatemem(void * p,size_t l,void * q,size_t m,alloctype f,char * s,char * t,unsigned long u,size_t k)566 __mp_locatemem(void *p, size_t l, void *q, size_t m, alloctype f, char *s,
567                char *t, unsigned long u, size_t k)
568 {
569     if (f == AT_MEMCHR)
570         return memchr(p, (int) (m & 0xFF), l);
571     else if (f == AT_MEMMEM)
572     {
573         if (m > 0)
574             while (l >= m)
575             {
576                 if ((*((char *) p) == *((char *) q)) && ((m == 1) ||
577                      !memcmp((char *) p + 1, (char *) q + 1, m - 1)))
578                     return p;
579                 p = (char *) p + 1;
580                 l--;
581             }
582         return NULL;
583     }
584     illegalfunction("__mp_locatemem", s, t, u);
585     return NULL;
586 }
587 
588 
589 /* Compare two blocks of memory.
590  */
591 
592 MP_API
593 int
__mp_comparemem(void * p,void * q,size_t l,alloctype f,char * s,char * t,unsigned long u,size_t k)594 __mp_comparemem(void *p, void *q, size_t l, alloctype f, char *s, char *t,
595                 unsigned long u, size_t k)
596 {
597     if ((f != AT_MEMCMP) && (f != AT_BCMP))
598         illegalfunction("__mp_comparemem", s, t, u);
599     return memcmp(p, q, l);
600 }
601 
602 
603 /* Return the full version number of the mpatrol library.
604  */
605 
606 MP_API
607 unsigned long
__mp_libversion(void)608 __mp_libversion(void)
609 {
610     return MP_VERNUM;
611 }
612 
613 
614 /* Return an error message corresponding to a given error type.
615  */
616 
617 MP_API
618 char *
__mp_strerror(errortype e)619 __mp_strerror(errortype e)
620 {
621     return NULL;
622 }
623 
624 
625 /* Return the name of the function corresponding to a given allocation type.
626  */
627 
628 MP_API
629 char *
__mp_function(alloctype f)630 __mp_function(alloctype f)
631 {
632     return NULL;
633 }
634 
635 
636 /* Set the user data for a given memory allocation.
637  */
638 
639 MP_API
640 int
__mp_setuser(void * p,void * d)641 __mp_setuser(void *p, void *d)
642 {
643     return 0;
644 }
645 
646 
647 /* Set the marked flag for a given memory allocation.
648  */
649 
650 MP_API
651 int
__mp_setmark(void * p)652 __mp_setmark(void *p)
653 {
654     return 0;
655 }
656 
657 
658 /* Obtain any details about the memory block that contains a given address.
659  */
660 
661 MP_API
662 int
__mp_info(void * p,allocinfo * d)663 __mp_info(void *p, allocinfo *d)
664 {
665     return 0;
666 }
667 
668 
669 /* Obtain any details about the function symbol that contains a given address.
670  */
671 
672 MP_API
673 int
__mp_syminfo(void * p,symbolinfo * d)674 __mp_syminfo(void *p, symbolinfo *d)
675 {
676     return 0;
677 }
678 
679 
680 /* Obtain the name of the function symbol that contains a given address.
681  */
682 
683 MP_API
684 char *
__mp_symbol(void * p)685 __mp_symbol(void *p)
686 {
687     return NULL;
688 }
689 
690 
691 /* Display any details about the memory block that contains a given address.
692  * This is for calling within a symbolic debugger and will result in output to
693  * the standard error file stream instead of the log file.
694  */
695 
696 MP_API
697 int
__mp_printinfo(void * p)698 __mp_printinfo(void *p)
699 {
700     return 0;
701 }
702 
703 
704 /* Return the current allocation event count for later use when examining
705  * the difference in the list of allocations between now and a future point.
706  */
707 
708 MP_API
709 unsigned long
__mp_snapshot(void)710 __mp_snapshot(void)
711 {
712     return 0;
713 }
714 
715 
716 /* Iterate over all of the allocated and freed memory blocks, calling a
717  * user-supplied function for each one encountered.
718  */
719 
720 MP_API
721 size_t
__mp_iterate(int (* f)(void *,void *),void * d,unsigned long s)722 __mp_iterate(int (*f)(void *, void *), void *d, unsigned long s)
723 {
724     return 0;
725 }
726 
727 
728 /* Iterate over all of the allocated, freed and free memory blocks, calling
729  * a user-supplied function for each one encountered.
730  */
731 
732 MP_API
733 size_t
__mp_iterateall(int (* f)(void *,void *),void * d)734 __mp_iterateall(int (*f)(void *, void *), void *d)
735 {
736     return 0;
737 }
738 
739 
740 /* Add a memory allocation to the leak table.
741  */
742 
743 MP_API
744 int
__mp_addallocentry(char * f,unsigned long l,size_t c)745 __mp_addallocentry(char *f, unsigned long l, size_t c)
746 {
747     return 0;
748 }
749 
750 
751 /* Remove a memory allocation from the leak table.
752  */
753 
754 MP_API
755 int
__mp_addfreeentry(char * f,unsigned long l,size_t c)756 __mp_addfreeentry(char *f, unsigned long l, size_t c)
757 {
758     return 0;
759 }
760 
761 
762 /* Clear the leak table.
763  */
764 
765 MP_API
766 void
__mp_clearleaktable(void)767 __mp_clearleaktable(void)
768 {
769 }
770 
771 
772 /* Start recording memory allocation events in the leak table.
773  */
774 
775 MP_API
776 int
__mp_startleaktable(void)777 __mp_startleaktable(void)
778 {
779     return 0;
780 }
781 
782 
783 /* Stop recording memory allocation events in the leak table.
784  */
785 
786 MP_API
787 int
__mp_stopleaktable(void)788 __mp_stopleaktable(void)
789 {
790     return 0;
791 }
792 
793 
794 /* Display the leak table.
795  */
796 
797 MP_API
798 void
__mp_leaktable(size_t l,int o,unsigned char f)799 __mp_leaktable(size_t l, int o, unsigned char f)
800 {
801 }
802 
803 
804 /* Display a complete memory map of the heap and (optionally) a summary of
805  * all mpatrol library settings and statistics.
806  */
807 
808 MP_API
809 void
__mp_memorymap(int s)810 __mp_memorymap(int s)
811 {
812 }
813 
814 
815 /* Display a summary of all mpatrol library settings and statistics.
816  */
817 
818 MP_API
819 void
__mp_summary(void)820 __mp_summary(void)
821 {
822 }
823 
824 
825 /* Return statistics about the current state of the heap.
826  */
827 
828 MP_API
829 int
__mp_stats(heapinfo * d)830 __mp_stats(heapinfo *d)
831 {
832     return 0;
833 }
834 
835 
836 /* Check the validity of all memory blocks that have been filled with
837  * a predefined pattern.
838  */
839 
840 MP_API
841 void
__mp_checkheap(char * s,char * t,unsigned long u)842 __mp_checkheap(char *s, char *t, unsigned long u)
843 {
844 }
845 
846 
847 /* Check the validity of all memory blocks that have been filled with
848  * a predefined pattern.
849  */
850 
851 MP_API
852 void
__mp_check(void)853 __mp_check(void)
854 {
855 }
856 
857 
858 /* Set the prologue function and return the previous setting.
859  */
860 
861 MP_API
862 prologuehandler
__mp_prologue(prologuehandler h)863 __mp_prologue(prologuehandler h)
864 {
865     return NULL;
866 }
867 
868 
869 /* Set the epilogue function and return the previous setting.
870  */
871 
872 MP_API
873 epiloguehandler
__mp_epilogue(epiloguehandler h)874 __mp_epilogue(epiloguehandler h)
875 {
876     return NULL;
877 }
878 
879 
880 /* Set the low-memory handler and return the previous setting.
881  */
882 
883 MP_API
884 nomemoryhandler
__mp_nomemory(nomemoryhandler h)885 __mp_nomemory(nomemoryhandler h)
886 {
887     return NULL;
888 }
889 
890 
891 /* Push source level information onto the top of the delete stack.
892  */
893 
894 MP_API
895 void
__mp_pushdelstack(char * s,char * t,unsigned long u)896 __mp_pushdelstack(char *s, char *t, unsigned long u)
897 {
898 }
899 
900 
901 /* Pop source level information off the top of the delete stack.
902  */
903 
904 MP_API
905 void
__mp_popdelstack(char ** s,char ** t,unsigned long * u)906 __mp_popdelstack(char **s, char **t, unsigned long *u)
907 {
908     *s = *t = NULL;
909     *u = 0;
910 }
911 
912 
913 /* Write user data to the mpatrol log file.
914  */
915 
916 MP_API
917 int
__mp_printf(char * s,...)918 __mp_printf(char *s, ...)
919 {
920     return 0;
921 }
922 
923 
924 /* Write user data to the mpatrol log file.
925  */
926 
927 MP_API
928 int
__mp_vprintf(char * s,va_list v)929 __mp_vprintf(char *s, va_list v)
930 {
931     return 0;
932 }
933 
934 
935 /* Write user data to the mpatrol log file along with location information.
936  */
937 
938 MP_API
939 void
__mp_printfwithloc(char * s,char * t,unsigned long u,char * m,...)940 __mp_printfwithloc(char *s, char *t, unsigned long u, char *m, ...)
941 {
942 }
943 
944 
945 /* Write user data to the mpatrol log file along with location information.
946  */
947 
948 MP_API
949 void
__mp_vprintfwithloc(char * s,char * t,unsigned long u,char * m,va_list v)950 __mp_vprintfwithloc(char *s, char *t, unsigned long u, char *m, va_list v)
951 {
952 }
953 
954 
955 /* Write a hex dump for a specified memory location to the mpatrol log file.
956  */
957 
958 MP_API
959 void
__mp_logmemory(void * p,size_t l)960 __mp_logmemory(void *p, size_t l)
961 {
962 }
963 
964 
965 /* Write the current call stack to the mpatrol log file.
966  */
967 
968 MP_API
969 int
__mp_logstack(size_t k)970 __mp_logstack(size_t k)
971 {
972     return 0;
973 }
974 
975 
976 /* Write the details about the memory block that contains a given address to
977  * the mpatrol log file.
978  */
979 
980 MP_API
981 int
__mp_logaddr(void * p)982 __mp_logaddr(void *p)
983 {
984     return 0;
985 }
986 
987 
988 /* Invoke a text editor on a given source file at a specific line.
989  */
990 
991 MP_API
992 int
__mp_edit(char * f,unsigned long l)993 __mp_edit(char *f, unsigned long l)
994 {
995     return 0;
996 }
997 
998 
999 /* List a given source file at a specific line.
1000  */
1001 
1002 MP_API
1003 int
__mp_list(char * f,unsigned long l)1004 __mp_list(char *f, unsigned long l)
1005 {
1006     return 0;
1007 }
1008 
1009 
1010 /* Edit or list a given source file at a specific line, but only if the EDIT
1011  * or LIST options are in effect.
1012  */
1013 
1014 MP_API
1015 int
__mp_view(char * f,unsigned long l)1016 __mp_view(char *f, unsigned long l)
1017 {
1018     return 0;
1019 }
1020 
1021 
1022 /* Read in an allocation contents file.
1023  */
1024 
1025 MP_API
1026 int
__mp_readcontents(char * s,void * p)1027 __mp_readcontents(char *s, void *p)
1028 {
1029     return 0;
1030 }
1031 
1032 
1033 /* Write out an allocation contents file.
1034  */
1035 
1036 MP_API
1037 int
__mp_writecontents(char * s,void * p)1038 __mp_writecontents(char *s, void *p)
1039 {
1040     return 0;
1041 }
1042 
1043 
1044 /* Compare an allocation contents file with the contents currently in memory.
1045  */
1046 
1047 MP_API
1048 long
__mp_cmpcontents(char * s,void * p)1049 __mp_cmpcontents(char *s, void *p)
1050 {
1051     return -1;
1052 }
1053 
1054 
1055 /* Remove an allocation contents file.
1056  */
1057 
1058 MP_API
1059 int
__mp_remcontents(char * s,void * p)1060 __mp_remcontents(char *s, void *p)
1061 {
1062     return 0;
1063 }
1064 
1065 
1066 /* The function that is called at every function prologue.
1067  */
1068 
1069 MP_API
1070 void
__cyg_profile_func_enter(void * a,void * p)1071 __cyg_profile_func_enter(void *a, void *p)
1072 {
1073 }
1074 
1075 
1076 /* The function that is called at every function epilogue.
1077  */
1078 
1079 MP_API
1080 void
__cyg_profile_func_exit(void * a,void * p)1081 __cyg_profile_func_exit(void *a, void *p)
1082 {
1083 }
1084 
1085 
1086 /* Set the access rights for a block of memory using the checker interface.
1087  */
1088 
1089 MP_API
1090 void
chkr_set_right(void * p,size_t l,unsigned char a)1091 chkr_set_right(void *p, size_t l, unsigned char a)
1092 {
1093 }
1094 
1095 
1096 /* Copy the access rights for a block of memory to another block using the
1097  * checker interface.
1098  */
1099 
1100 MP_API
1101 void
chkr_copy_bitmap(void * p,void * q,size_t l)1102 chkr_copy_bitmap(void *p, void *q, size_t l)
1103 {
1104 }
1105 
1106 
1107 /* Check a block of memory using the checker interface.
1108  */
1109 
1110 MP_API
1111 void
chkr_check_addr(void * p,size_t l,unsigned char a)1112 chkr_check_addr(void *p, size_t l, unsigned char a)
1113 {
1114 }
1115 
1116 
1117 /* Check a string using the checker interface.
1118  */
1119 
1120 MP_API
1121 void
chkr_check_str(char * p,unsigned char a)1122 chkr_check_str(char *p, unsigned char a)
1123 {
1124 }
1125 
1126 
1127 /* Check a function pointer using the checker interface.
1128  */
1129 
1130 MP_API
1131 void
chkr_check_exec(void * p)1132 chkr_check_exec(void *p)
1133 {
1134 }
1135 
1136 
1137 #ifdef __cplusplus
1138 }
1139 #endif /* __cplusplus */
1140