smap.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /*+-------------------------------------------------------------------------
  2. smap.c -- memeory debugging aid
  3. Defined functions:
  4. _abort(s1, s2)
  5. _blkend()
  6. _blkignore(ptr)
  7. _blkstart()
  8. _calloc(nel, size)
  9. _dump_malloc()
  10. _free(ptr)
  11. _malloc(size)
  12. _realloc(ptr, size)
  13. * Copyright 1988, Joypace Ltd., UK. This product is "careware".
  14. * If you find it useful, I suggest that you send what you think
  15. * it is worth to the charity of your choice.
  16. *
  17. * Alistair G. Crooks, +44 5805 3114
  18. * Joypace Ltd.,
  19. * 2 Vale Road,
  20. * Hawkhurst,
  21. * Kent TN18 4BU,
  22. * UK.
  23. *
  24. * UUCP Europe ...!mcvax!unido!nixpbe!nixbln!agc
  25. * UUCP everywhere else ...!uunet!linus!nixbur!nixpbe!nixbln!agc
  26. --------------------------------------------------------------------------*/
  27. /*+:EDITS:*/
  28. /*:04-26-2000-11:16-wht@bob-RELEASE 4.42 */
  29. /*:01-24-1997-02:38-wht@yuriatin-SOURCE RELEASE 4.00 */
  30. /*:09-11-1996-20:01-wht@yuriatin-3.48-major telnet,curses,structural overhaul */
  31. /*:11-23-1995-11:20-wht@kepler-source control 3.37 for tsx-11 */
  32. /*:11-14-1995-10:23-wht@kepler-3.37.80-source control point: SOCKETS */
  33. /*:05-04-1994-04:40-wht@n4hgf-ECU release 3.30 */
  34. /*:04-17-1994-17:54-wht@n4hgf-creation */
  35. /*+:EDITS:*/
  36. /*:09-10-1992-14:00-wht@n4hgf-ECU release 3.20 */
  37. /*:08-22-1992-15:39-wht@n4hgf-ECU release 3.20 BETA */
  38. /*:11-30-1991-13:46-wht@n4hgf-smap conditional compilation reorg */
  39. /*:07-25-1991-12:59-wht@n4hgf-ECU release 3.10 */
  40. /*:04-19-1990-03:08-wht@n4hgf-GCC run found unused vars -- rm them */
  41. /*:03-25-1990-14:12-wht@n4hgf------ x2.70 ------- */
  42. /*:07-03-1989-22:57-wht------ x2.00 ----- */
  43. /*:06-24-1989-16:52-wht-flush edits --- ecu 1.95 */
  44. #ifdef MEMCHECK
  45. #include <stdio.h>
  46. #include <signal.h>
  47. typedef struct _slotstr
  48. {
  49. char *s_ptr; /* the allocated area */
  50. unsigned int s_size; /* its size */
  51. char s_freed; /* whether it's been freed yet */
  52. char s_blkno; /* program block reference number */
  53. }
  54. SLOT;
  55. #ifndef MAXSLOTS
  56. #define MAXSLOTS 4096
  57. #endif /* MAXSLOTS */
  58. static SLOT slots[MAXSLOTS];
  59. static int slotc;
  60. static int blkno;
  61. #define WARNING(s1, s2) (void) fprintf(stderr, s1, s2)
  62. /* __STDC__ dependency hasn't invaded this module yet */
  63. char *malloc();
  64. char *calloc();
  65. char *realloc();
  66. void _abort();
  67. /*+-------------------------------------------------------------------------
  68. _dump_malloc()
  69. --------------------------------------------------------------------------*/
  70. void
  71. _dump_malloc()
  72. {
  73. int islot;
  74. slot_count = 0;
  75. char dfile[32];
  76. char title[64];
  77. FILE *fp;
  78. SLOT *slot;
  79. sprintf(dfile, "/tmp/m%05d.dmp", getpid());
  80. fp = fopen(dfile, "w");
  81. fprintf(stderr, "\r\n\n\ndumping malloc status to %s\r\n", dfile);
  82. for (islot = 0, slot = slots; islot < slotc; islot++, slot++)
  83. {
  84. if (slot->s_freed)
  85. continue;
  86. sprintf(title, "%d (%d) %08x size %u",
  87. slot_count, islot, slot->s_ptr, slot->s_size);
  88. hex_dump_fp(fp, slot->s_ptr, slot->s_size, title, 0);
  89. slot_count++;
  90. }
  91. fclose(fp);
  92. fprintf(stderr, "done\r\n");
  93. } /* end of _dump_malloc */
  94. /*
  95. * _malloc - wrapper around malloc. Warns if unusual size given, or the
  96. * real malloc returns a 0 pointer. Returns a pointer to the
  97. * malloc'd area
  98. */
  99. char *
  100. _malloc(size)
  101. unsigned int size;
  102. {
  103. SLOT *sp;
  104. char *ptr;
  105. int i;
  106. if (size == 0)
  107. WARNING("_malloc: unusual size %d bytes\r\n", size);
  108. if ((ptr = (char *)malloc(size)) == (char *)0)
  109. _abort("_malloc: unable to malloc %u bytes\r\n", size);
  110. for (i = 0, sp = slots; i < slotc; i++, sp++)
  111. if (sp->s_ptr == ptr)
  112. break;
  113. if (i == slotc)
  114. {
  115. if (slotc == MAXSLOTS - 1)
  116. {
  117. _dump_malloc();
  118. _abort("_malloc: run out of slots\r\n", "");
  119. }
  120. sp = &slots[slotc++];
  121. }
  122. else if (!sp->s_freed)
  123. WARNING("_malloc: malloc returned a non-freed pointer\r\n", "");
  124. sp->s_size = size;
  125. sp->s_freed = 0;
  126. sp->s_ptr = ptr;
  127. sp->s_blkno = blkno;
  128. #ifndef NO_EXTRA_HELP
  129. memset(sp->s_ptr, 0x12, sp->s_size);
  130. #endif
  131. return (sp->s_ptr);
  132. }
  133. /*
  134. * _calloc - wrapper for calloc. Calls _malloc to allocate the area, and
  135. * then sets the contents of the area to NUL bytes. Returns its address.
  136. */
  137. char *
  138. _calloc(nel, size)
  139. int nel;
  140. unsigned int size;
  141. {
  142. unsigned int tot;
  143. char *ptr;
  144. tot = nel * size;
  145. ptr = _malloc(tot);
  146. if (ptr == (char *)0)
  147. return ((char *)0);
  148. memset(ptr, 0, tot);
  149. return (ptr);
  150. }
  151. /*
  152. * _realloc - wrapper for realloc. Checks area already alloc'd and
  153. * not freed. Returns its address
  154. */
  155. char *
  156. _realloc(ptr, size)
  157. char *ptr;
  158. unsigned int size;
  159. {
  160. SLOT *sp;
  161. int i;
  162. for (i = 0, sp = slots; i < slotc; i++, sp++)
  163. if (sp->s_ptr == ptr)
  164. break;
  165. if (i == slotc)
  166. _abort("_realloc: realloc on unallocated area\r\n", "");
  167. if (sp->s_freed)
  168. WARNING("_realloc: realloc on freed area\r\n", "");
  169. if ((sp->s_ptr = (char *)realloc(ptr, size)) == (char *)0)
  170. WARNING("_realloc: realloc failure %d bytes\r\n", size);
  171. sp->s_size = size;
  172. sp->s_blkno = blkno;
  173. return (sp->s_ptr);
  174. }
  175. /*
  176. * _free - wrapper for free. Loop through allocated slots, until you
  177. * find the one corresponding to pointer. If none, then it's an attempt
  178. * to free an unallocated area. If it's already freed, then tell user.
  179. */
  180. void
  181. _free(ptr)
  182. char *ptr;
  183. {
  184. SLOT *sp;
  185. int i;
  186. for (i = 0, sp = slots; i < slotc; i++, sp++)
  187. if (sp->s_ptr == ptr)
  188. break;
  189. if (i == slotc)
  190. _abort("_free: free not previously malloc'd\r\n", "");
  191. if (sp->s_freed)
  192. _abort("_free: free after previous freeing\r\n", "");
  193. (void)free(sp->s_ptr);
  194. sp->s_freed = 1;
  195. }
  196. /*
  197. * _blkstart - start of a program block. Increase the block reference
  198. * number by one.
  199. */
  200. void
  201. _blkstart()
  202. {
  203. blkno += 1;
  204. }
  205. /*
  206. * _blkend - end of a program block. Check all areas allocated in this
  207. * block have been freed. Decrease the block number by one.
  208. */
  209. void
  210. _blkend()
  211. {
  212. SLOT *sp;
  213. int i;
  214. if (blkno == 0)
  215. {
  216. WARNING("_blkend: unmatched call to _blkend\r\n", "");
  217. return;
  218. }
  219. for (i = 0, sp = slots; i < slotc; i++, sp++)
  220. if (sp->s_blkno == blkno && !sp->s_freed)
  221. WARNING("_blkend: %d bytes unfreed\r\n", sp->s_size);
  222. blkno -= 1;
  223. }
  224. /*
  225. * _blkignore - find the slot corresponding to ptr, and set its block
  226. * number to zero, to avoid _blkend picking it up when checking.
  227. */
  228. void
  229. _blkignore(ptr)
  230. char *ptr;
  231. {
  232. SLOT *sp;
  233. int i;
  234. for (i = 0, sp = slots; i < slotc; i++, sp++)
  235. if (sp->s_ptr == ptr)
  236. break;
  237. if (i == slotc)
  238. WARNING("_blkignore: pointer has not been allocated\r\n", "");
  239. else
  240. sp->s_blkno = 0;
  241. }
  242. /*
  243. * _abort - print a warning on stderr, and send a SIGQUIT to ourself
  244. */
  245. #if !defined(BUILDING_LINT_ARGS)
  246. static void
  247. _abort(s1, s2)
  248. char *s1;
  249. char *s2;
  250. {
  251. #ifdef M_I386
  252. char *kaboom = (char *)90000000;
  253. WARNING(s1, s2);
  254. *kaboom = 1;
  255. #else
  256. WARNING(s1, s2);
  257. (void)kill((CFG_PidType) getpid(), SIGIOT); /* core dump here */
  258. #endif
  259. }
  260. #endif /* !defined(BUILDING_LINT_ARGS) */
  261. #endif /* MEMCHECK */
  262. /* vi: set tabstop=4 shiftwidth=4: */
  263. /* end of smap.c */