acidleak.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  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 %lud 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 %lud 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. uint32_t *a, *b;
  69. a = va;
  70. b = vb;
  71. if(*a < *b)
  72. return -1;
  73. if(*a > *b)
  74. return 1;
  75. return 0;
  76. }
  77. Block*
  78. findblock(uint32_t addr)
  79. {
  80. int lo, hi, m;
  81. lo = 0;
  82. hi = nblock;
  83. while(lo < hi) {
  84. m = (lo+hi)/2;
  85. if(block[m].addr < addr)
  86. lo = m+1;
  87. else if(addr < block[m].addr)
  88. hi = m;
  89. else
  90. return &block[m];
  91. }
  92. return nil;
  93. }
  94. Data*
  95. finddata(uint32_t addr)
  96. {
  97. int lo, hi, m;
  98. lo = 0;
  99. hi = ndata;
  100. while(lo < hi) {
  101. m = (lo+hi)/2;
  102. if(data[m].addr < addr)
  103. lo = m+1;
  104. else if(addr < data[m].addr)
  105. hi = m;
  106. else
  107. return &data[m];
  108. }
  109. if(0 <= lo && lo < ndata)
  110. return &data[lo];
  111. return nil;
  112. }
  113. int nmark;
  114. int
  115. markblock(uint32_t from, uint32_t fromval, Block *b)
  116. {
  117. Data *d;
  118. uint32_t top;
  119. Block *nb;
  120. USED(from); USED(fromval);
  121. //print("trace 0x%.8lux from 0x%.8lux (%d)\n", b->addr, from, b->mark);
  122. if(b->free){
  123. // fprint(2, "possible dangling pointer *0x%.8lux = 0x%.8lux\n", from, fromval);
  124. return 0;
  125. }
  126. if(b->mark)
  127. return 0;
  128. b->mark = 1;
  129. nmark++;
  130. if(d = finddata(b->addr)) {
  131. assert(d->addr >= b->addr);
  132. b->d = d;
  133. top = b->addr+b->size;
  134. for(; d < edata && d->addr < top; d++) {
  135. assert(d->b == 0);
  136. d->b = b;
  137. if((nb = findblock(d->val-8)) || (nb = findblock(d->val-8-8)))
  138. markblock(d->addr, d->val, nb);
  139. }
  140. return 1;
  141. }
  142. return 0;
  143. }
  144. enum {
  145. AllocColor = 2, // dark blue: completely allocated region
  146. HdrColor = 54, // bright blue: region with header
  147. LeakColor = 205, // dark red: region with leak
  148. LeakHdrColor = 240, // bright red: region with leaked header
  149. FreeColor = 252, // bright yellow: completely free region
  150. NoColor = 255, // padding, white
  151. };
  152. int
  153. rXr(int as, int ae, int bs, int be)
  154. {
  155. return bs < ae && as < be;
  156. }
  157. void
  158. main(int argc, char **argv)
  159. {
  160. Biobuf bio;
  161. char *p, *f[10];
  162. int bitmap, c, nf, resolution, n8, n16, hdr, nhdr, nlhdr, nleak, x, y, nb;
  163. uint32_t allocstart, allocend, len, u;
  164. Data *d, *ed;
  165. Block *b, *eb;
  166. bitmap = 0;
  167. resolution = 8;
  168. x = 512;
  169. ARGBEGIN{
  170. case 'b':
  171. bitmap=1;
  172. break;
  173. case 'r':
  174. resolution = atoi(EARGF(sysfatal("usage")));
  175. break;
  176. case 'x':
  177. x = atoi(EARGF(sysfatal("usage")));
  178. break;
  179. }ARGEND
  180. n8 = n16 = 0;
  181. allocstart = allocend = 0;
  182. Binit(&bio, 0, OREAD);
  183. while(p=Brdline(&bio, '\n')) {
  184. p[Blinelen(&bio)-1] = '\0';
  185. nf = tokenize(p, f, nelem(f));
  186. if(nf >= 4 && strcmp(f[0], "data") == 0) {
  187. if(ndata >= adata){
  188. if(adata == 0)
  189. adata = 4096;
  190. else
  191. adata += adata / 4; /* increase 25% */
  192. data = erealloc(data, adata * sizeof(Data));
  193. }
  194. data[ndata].addr = strtoul(f[1], nil, 0);
  195. data[ndata].val = strtoul(f[2], nil, 0);
  196. data[ndata].type = f[3][0];
  197. data[ndata].b = 0;
  198. ndata++;
  199. }
  200. if(nf >= 5 &&
  201. (strcmp(f[0], "block") == 0 || strcmp(f[0], "free") == 0)) {
  202. if(nblock >= ablock){
  203. if(ablock == 0)
  204. ablock = 4096;
  205. else
  206. ablock += ablock / 4; /* increase 25% */
  207. block = erealloc(block, ablock * sizeof(Block));
  208. }
  209. block[nblock].addr = strtoul(f[1], nil, 0);
  210. block[nblock].size = strtoul(f[2], nil, 0);
  211. block[nblock].w0 = strtoul(f[3], nil, 0);
  212. block[nblock].w1 = strtoul(f[4], nil, 0);
  213. if (nf >= 7) {
  214. block[nblock].s0 = estrdup(f[5]);
  215. block[nblock].s1 = estrdup(f[6]);
  216. } else {
  217. block[nblock].s0 = "";
  218. block[nblock].s1 = "";
  219. }
  220. block[nblock].mark = 0;
  221. block[nblock].d = 0;
  222. block[nblock].free = strcmp(f[0], "free") == 0;
  223. nblock++;
  224. }
  225. if(nf >= 4 && strcmp(f[0], "range") == 0 && strcmp(f[1], "alloc") == 0) {
  226. allocstart = strtoul(f[2], 0, 0)&~15;
  227. allocend = strtoul(f[3], 0, 0);
  228. }
  229. }
  230. qsort(block, nblock, sizeof(Block), addrcmp);
  231. qsort(data, ndata, sizeof(Data), addrcmp);
  232. ed = edata = data+ndata;
  233. for(d=data; d<ed; d++) {
  234. if(d->type == 'a')
  235. continue;
  236. if(b = findblock(d->val-8)) // pool header 2 words
  237. n8 += markblock(d->addr, d->val, b);
  238. else if(b = findblock(d->val-8-8)) // sometimes malloc header 2 words
  239. n16 += markblock(d->addr, d->val, b);
  240. else
  241. {}//print("noblock %.8lux\n", d->val);
  242. }
  243. Binit(&bio, 1, OWRITE);
  244. if(bitmap){
  245. if(n8 > n16) // guess size of header
  246. hdr = 8;
  247. else
  248. hdr = 16;
  249. for(d=data; d<ed; d++)
  250. if(d->type=='a')
  251. break;
  252. if(d==ed)
  253. sysfatal("no allocated data region");
  254. len = (allocend-allocstart+resolution-1)/resolution;
  255. y = (len+x-1)/x;
  256. Bprint(&bio, "%11s %11d %11d %11d %11d ", "m8", 0, 0, x, y);
  257. //fprint(2, "alloc %lux %lux x %d y %d res %d\n", allocstart, allocend, x, y, resolution);
  258. b = block;
  259. eb = block+nblock;
  260. for(u = allocstart; u<allocend; u+=resolution){
  261. //fprint(2, "u %lux %lux baddr %lux\n", u, u+resolution, b->addr);
  262. while(b->addr+b->size <= u && b < eb)
  263. //{
  264. //fprint(2, "\tskip %lux %lux\n", b->addr, b->addr+b->size);
  265. b++;
  266. //}
  267. nhdr = 0;
  268. nleak = 0;
  269. nb = 0;
  270. nlhdr = 0;
  271. if(block < b && u < (b-1)->addr+(b-1)->size)
  272. b--;
  273. for(; b->addr < u+resolution && b < eb; b++){
  274. //fprint(2, "\tblock %lux %lux %d\n", b->addr, b->addr+b->size, b->mark);
  275. if(rXr(b->addr, b->addr+hdr, u, u+resolution)
  276. || rXr(b->addr+b->size-8, b->addr+b->size, u, u+resolution)){
  277. if(b->mark == 0 && !b->free)
  278. nlhdr++;
  279. else
  280. nhdr++;
  281. }
  282. if(b->mark == 0 && !b->free)
  283. nleak++;
  284. nb++;
  285. }
  286. if(nhdr)
  287. c = HdrColor;
  288. else if(nlhdr)
  289. c = LeakHdrColor;
  290. else if(nleak)
  291. c = LeakColor;
  292. else if(nb)
  293. c = AllocColor;
  294. else
  295. c = FreeColor;
  296. //fprint(2, "\t%d\n", c);
  297. Bputc(&bio, c);
  298. }
  299. allocend = allocstart+x*y*resolution;
  300. for(; u < allocend; u+=resolution)
  301. Bputc(&bio, NoColor);
  302. }else{
  303. eb = block+nblock;
  304. for(b=block; b<eb; b++)
  305. if(b->mark == 0 && !b->free)
  306. 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);
  307. }
  308. Bterm(&bio);
  309. exits(nil);
  310. }