acidleak.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <bio.h>
  12. void*
  13. emalloc(uint32_t sz)
  14. {
  15. void *v;
  16. v = malloc(sz);
  17. if(v == nil)
  18. sysfatal("malloc %lu fails", sz);
  19. memset(v, 0, sz);
  20. return v;
  21. }
  22. void*
  23. erealloc(void *v, uint32_t sz)
  24. {
  25. v = realloc(v, sz);
  26. if(v == nil)
  27. sysfatal("realloc %lu fails", sz);
  28. return v;
  29. }
  30. char*
  31. estrdup(char* s)
  32. {
  33. char *r;
  34. r = strdup(s);
  35. if(r == nil)
  36. sysfatal("strdup fails");
  37. return r;
  38. }
  39. typedef struct Block Block;
  40. typedef struct Data Data;
  41. struct Block {
  42. uint32_t addr;
  43. uint32_t size;
  44. uint32_t w0;
  45. uint32_t w1;
  46. char *s0;
  47. char *s1;
  48. int mark;
  49. int free;
  50. Data *d;
  51. };
  52. struct Data {
  53. uint32_t addr;
  54. uint32_t val;
  55. uint8_t type;
  56. Block *b;
  57. };
  58. Block *block;
  59. uint nblock;
  60. uint ablock;
  61. Data *data;
  62. Data *edata;
  63. uint ndata;
  64. uint adata;
  65. int
  66. addrcmp(const void *va, const void *vb)
  67. {
  68. const uint32_t *a = (const uint32_t*)va;
  69. const uint32_t *b = (const uint32_t*)vb;
  70. if(*a < *b)
  71. return -1;
  72. if(*a > *b)
  73. return 1;
  74. return 0;
  75. }
  76. Block*
  77. findblock(uint32_t addr)
  78. {
  79. int lo, hi, m;
  80. lo = 0;
  81. hi = nblock;
  82. while(lo < hi) {
  83. m = (lo+hi)/2;
  84. if(block[m].addr < addr)
  85. lo = m+1;
  86. else if(addr < block[m].addr)
  87. hi = m;
  88. else
  89. return &block[m];
  90. }
  91. return nil;
  92. }
  93. Data*
  94. finddata(uint32_t addr)
  95. {
  96. int lo, hi, m;
  97. lo = 0;
  98. hi = ndata;
  99. while(lo < hi) {
  100. m = (lo+hi)/2;
  101. if(data[m].addr < addr)
  102. lo = m+1;
  103. else if(addr < data[m].addr)
  104. hi = m;
  105. else
  106. return &data[m];
  107. }
  108. if(0 <= lo && lo < ndata)
  109. return &data[lo];
  110. return nil;
  111. }
  112. int nmark;
  113. int
  114. markblock(uint32_t from, uint32_t fromval, Block *b)
  115. {
  116. Data *d;
  117. uint32_t top;
  118. Block *nb;
  119. USED(from); USED(fromval);
  120. //print("trace 0x%.8lux from 0x%.8lux (%d)\n", b->addr, from, b->mark);
  121. if(b->free){
  122. // fprint(2, "possible dangling pointer *0x%.8lux = 0x%.8lux\n", from, fromval);
  123. return 0;
  124. }
  125. if(b->mark)
  126. return 0;
  127. b->mark = 1;
  128. nmark++;
  129. if(d = finddata(b->addr)) {
  130. assert(d->addr >= b->addr);
  131. b->d = d;
  132. top = b->addr+b->size;
  133. for(; d < edata && d->addr < top; d++) {
  134. assert(d->b == 0);
  135. d->b = b;
  136. if((nb = findblock(d->val-8)) || (nb = findblock(d->val-8-8)))
  137. markblock(d->addr, d->val, nb);
  138. }
  139. return 1;
  140. }
  141. return 0;
  142. }
  143. enum {
  144. AllocColor = 2, // dark blue: completely allocated region
  145. HdrColor = 54, // bright blue: region with header
  146. LeakColor = 205, // dark red: region with leak
  147. LeakHdrColor = 240, // bright red: region with leaked header
  148. FreeColor = 252, // bright yellow: completely free region
  149. NoColor = 255, // padding, white
  150. };
  151. int
  152. rXr(int as, int ae, int bs, int be)
  153. {
  154. return bs < ae && as < be;
  155. }
  156. void
  157. main(int argc, char **argv)
  158. {
  159. Biobuf bio;
  160. char *p, *f[10];
  161. int bitmap, c, nf, resolution, n8, n16, hdr, nhdr, nlhdr, nleak, x, y, nb;
  162. uint32_t allocstart, allocend, len, u;
  163. Data *d, *ed;
  164. Block *b, *eb;
  165. bitmap = 0;
  166. resolution = 8;
  167. x = 512;
  168. ARGBEGIN{
  169. case 'b':
  170. bitmap=1;
  171. break;
  172. case 'r':
  173. resolution = atoi(EARGF(sysfatal("usage")));
  174. break;
  175. case 'x':
  176. x = atoi(EARGF(sysfatal("usage")));
  177. break;
  178. }ARGEND
  179. n8 = n16 = 0;
  180. allocstart = allocend = 0;
  181. Binit(&bio, 0, OREAD);
  182. while(p=Brdline(&bio, '\n')) {
  183. p[Blinelen(&bio)-1] = '\0';
  184. nf = tokenize(p, f, nelem(f));
  185. if(nf >= 4 && strcmp(f[0], "data") == 0) {
  186. if(ndata >= adata){
  187. if(adata == 0)
  188. adata = 4096;
  189. else
  190. adata += adata / 4; /* increase 25% */
  191. data = erealloc(data, adata * sizeof(Data));
  192. }
  193. data[ndata].addr = strtoul(f[1], nil, 0);
  194. data[ndata].val = strtoul(f[2], nil, 0);
  195. data[ndata].type = f[3][0];
  196. data[ndata].b = 0;
  197. ndata++;
  198. }
  199. if(nf >= 5 &&
  200. (strcmp(f[0], "block") == 0 || strcmp(f[0], "free") == 0)) {
  201. if(nblock >= ablock){
  202. if(ablock == 0)
  203. ablock = 4096;
  204. else
  205. ablock += ablock / 4; /* increase 25% */
  206. block = erealloc(block, ablock * sizeof(Block));
  207. }
  208. block[nblock].addr = strtoul(f[1], nil, 0);
  209. block[nblock].size = strtoul(f[2], nil, 0);
  210. block[nblock].w0 = strtoul(f[3], nil, 0);
  211. block[nblock].w1 = strtoul(f[4], nil, 0);
  212. if (nf >= 7) {
  213. block[nblock].s0 = estrdup(f[5]);
  214. block[nblock].s1 = estrdup(f[6]);
  215. } else {
  216. block[nblock].s0 = "";
  217. block[nblock].s1 = "";
  218. }
  219. block[nblock].mark = 0;
  220. block[nblock].d = 0;
  221. block[nblock].free = strcmp(f[0], "free") == 0;
  222. nblock++;
  223. }
  224. if(nf >= 4 && strcmp(f[0], "range") == 0 && strcmp(f[1], "alloc") == 0) {
  225. allocstart = strtoul(f[2], 0, 0)&~15;
  226. allocend = strtoul(f[3], 0, 0);
  227. }
  228. }
  229. qsort(block, nblock, sizeof(Block), addrcmp);
  230. qsort(data, ndata, sizeof(Data), addrcmp);
  231. ed = edata = data+ndata;
  232. for(d=data; d<ed; d++) {
  233. if(d->type == 'a')
  234. continue;
  235. if(b = findblock(d->val-8)) // pool header 2 words
  236. n8 += markblock(d->addr, d->val, b);
  237. else if(b = findblock(d->val-8-8)) // sometimes malloc header 2 words
  238. n16 += markblock(d->addr, d->val, b);
  239. else
  240. {}//print("noblock %.8lux\n", d->val);
  241. }
  242. Binit(&bio, 1, OWRITE);
  243. if(bitmap){
  244. if(n8 > n16) // guess size of header
  245. hdr = 8;
  246. else
  247. hdr = 16;
  248. for(d=data; d<ed; d++)
  249. if(d->type=='a')
  250. break;
  251. if(d==ed)
  252. sysfatal("no allocated data region");
  253. len = (allocend-allocstart+resolution-1)/resolution;
  254. y = (len+x-1)/x;
  255. Bprint(&bio, "%11s %11d %11d %11d %11d ", "m8", 0, 0, x, y);
  256. //fprint(2, "alloc %lx %lx x %d y %d res %d\n", allocstart, allocend, x, y, resolution);
  257. b = block;
  258. eb = block+nblock;
  259. for(u = allocstart; u<allocend; u+=resolution){
  260. //fprint(2, "u %lx %lx baddr %lx\n", u, u+resolution, b->addr);
  261. while(b->addr+b->size <= u && b < eb)
  262. //{
  263. //fprint(2, "\tskip %lx %lx\n", b->addr, b->addr+b->size);
  264. b++;
  265. //}
  266. nhdr = 0;
  267. nleak = 0;
  268. nb = 0;
  269. nlhdr = 0;
  270. if(block < b && u < (b-1)->addr+(b-1)->size)
  271. b--;
  272. for(; b->addr < u+resolution && b < eb; b++){
  273. //fprint(2, "\tblock %lx %lx %d\n", b->addr, b->addr+b->size, b->mark);
  274. if(rXr(b->addr, b->addr+hdr, u, u+resolution)
  275. || rXr(b->addr+b->size-8, b->addr+b->size, u, u+resolution)){
  276. if(b->mark == 0 && !b->free)
  277. nlhdr++;
  278. else
  279. nhdr++;
  280. }
  281. if(b->mark == 0 && !b->free)
  282. nleak++;
  283. nb++;
  284. }
  285. if(nhdr)
  286. c = HdrColor;
  287. else if(nlhdr)
  288. c = LeakHdrColor;
  289. else if(nleak)
  290. c = LeakColor;
  291. else if(nb)
  292. c = AllocColor;
  293. else
  294. c = FreeColor;
  295. //fprint(2, "\t%d\n", c);
  296. Bputc(&bio, c);
  297. }
  298. allocend = allocstart+x*y*resolution;
  299. for(; u < allocend; u+=resolution)
  300. Bputc(&bio, NoColor);
  301. }else{
  302. eb = block+nblock;
  303. for(b=block; b<eb; b++)
  304. if(b->mark == 0 && !b->free)
  305. Bprint(&bio, "block 0x%.8lux 0x%.8lux 0x%.8lux 0x%.8lux %s %s\n", b->addr, b->size, b->w0, b->w1, b->s0, b->s1);
  306. }
  307. Bterm(&bio);
  308. exits(nil);
  309. }