1
0

acidleak.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. void*
  5. emalloc(ulong sz)
  6. {
  7. void *v;
  8. v = malloc(sz);
  9. if(v == nil)
  10. sysfatal("malloc %lud fails\n", sz);
  11. memset(v, 0, sz);
  12. return v;
  13. }
  14. void*
  15. erealloc(void *v, ulong sz)
  16. {
  17. v = realloc(v, sz);
  18. if(v == nil)
  19. sysfatal("realloc %lud fails\n", sz);
  20. return v;
  21. }
  22. typedef struct Block Block;
  23. typedef struct Data Data;
  24. struct Block {
  25. ulong addr;
  26. ulong size;
  27. ulong w0;
  28. ulong w1;
  29. int mark;
  30. Data *d;
  31. };
  32. struct Data {
  33. ulong addr;
  34. ulong val;
  35. uchar type;
  36. Block *b;
  37. };
  38. Block *block;
  39. int nblock;
  40. Data *data;
  41. Data *edata;
  42. int ndata;
  43. int
  44. addrcmp(void *va, void *vb)
  45. {
  46. ulong *a, *b;
  47. a = va;
  48. b = vb;
  49. if(*a < *b)
  50. return -1;
  51. if(*a > *b)
  52. return 1;
  53. return 0;
  54. }
  55. Block*
  56. findblock(ulong addr)
  57. {
  58. int lo, hi, m;
  59. lo = 0;
  60. hi = nblock;
  61. while(lo < hi) {
  62. m = (lo+hi)/2;
  63. if(block[m].addr < addr)
  64. lo = m+1;
  65. else if(addr < block[m].addr)
  66. hi = m;
  67. else
  68. return &block[m];
  69. }
  70. return nil;
  71. }
  72. Data*
  73. finddata(ulong addr)
  74. {
  75. int lo, hi, m;
  76. lo = 0;
  77. hi = ndata;
  78. while(lo < hi) {
  79. m = (lo+hi)/2;
  80. if(data[m].addr < addr)
  81. lo = m+1;
  82. else if(addr < data[m].addr)
  83. hi = m;
  84. else
  85. return &data[m];
  86. }
  87. if(0 <= lo && lo < ndata)
  88. return &data[lo];
  89. }
  90. int nmark;
  91. int
  92. markblock(Block *b, ulong from)
  93. {
  94. Data *d;
  95. ulong top;
  96. Block *nb;
  97. USED(from);
  98. //print("trace 0x%.8lux from 0x%.8lux (%d)\n", b->addr, from, b->mark);
  99. if(b->mark)
  100. return 0;
  101. b->mark = 1;
  102. nmark++;
  103. if(d = finddata(b->addr)) {
  104. assert(d->addr >= b->addr);
  105. b->d = d;
  106. top = b->addr+b->size;
  107. for(; d < edata && d->addr < top; d++) {
  108. assert(d->b == 0);
  109. d->b = b;
  110. if((nb = findblock(d->val-8)) || (nb = findblock(d->val-8-8)))
  111. markblock(nb, b->addr);
  112. }
  113. return 1;
  114. }
  115. return 0;
  116. }
  117. enum {
  118. AllocColor = 2, // dark blue: completely allocated region
  119. HdrColor = 54, // bright blue: region with header
  120. LeakColor = 205, // dark red: region with leak
  121. LeakHdrColor = 240, // bright red: region with leaked header
  122. FreeColor = 252, // bright yellow: completely free region
  123. NoColor = 255, // padding, white
  124. };
  125. int
  126. rXr(int as, int ae, int bs, int be)
  127. {
  128. return bs < ae && as < be;
  129. }
  130. void
  131. main(int argc, char **argv)
  132. {
  133. Biobuf bio;
  134. char *p, *f[10];
  135. int bitmap, c, nf, resolution, n8, n16, hdr, nhdr, nlhdr, nleak, x, y, nb;
  136. ulong allocstart, allocend, len, u;
  137. Data *d, *ed;
  138. Block *b, *eb;
  139. bitmap = 0;
  140. resolution = 8;
  141. x = 512;
  142. ARGBEGIN{
  143. case 'b':
  144. bitmap=1;
  145. break;
  146. case 'r':
  147. resolution = atoi(EARGF(sysfatal("usage")));
  148. break;
  149. case 'x':
  150. x = atoi(EARGF(sysfatal("usage")));
  151. break;
  152. }ARGEND
  153. n8 = n16 = 0;
  154. allocstart = allocend = 0;
  155. Binit(&bio, 0, OREAD);
  156. while(p=Brdline(&bio, '\n')) {
  157. p[Blinelen(&bio)-1] = '\0';
  158. nf = tokenize(p, f, nelem(f));
  159. if(nf >= 4 && strcmp(f[0], "data") == 0) {
  160. if(ndata%64==0)
  161. data = erealloc(data, (ndata+64)*sizeof(Data));
  162. data[ndata].addr = strtoul(f[1], nil, 0);
  163. data[ndata].val = strtoul(f[2], nil, 0);
  164. data[ndata].type = f[3][0];
  165. data[ndata].b = 0;
  166. ndata++;
  167. }
  168. if(nf >= 5 && strcmp(f[0], "block") == 0) {
  169. if(nblock%64 == 0)
  170. block = erealloc(block, (nblock+64)*sizeof(Block));
  171. block[nblock].addr = strtoul(f[1], nil, 0);
  172. block[nblock].size = strtoul(f[2], nil, 0);
  173. block[nblock].w0 = strtoul(f[3], nil, 0);
  174. block[nblock].w1 = strtoul(f[4], nil, 0);
  175. block[nblock].mark = 0;
  176. block[nblock].d = 0;
  177. nblock++;
  178. }
  179. if(nf >= 4 && strcmp(f[0], "range") == 0 && strcmp(f[1], "alloc") == 0) {
  180. allocstart = strtoul(f[2], 0, 0)&~15;
  181. allocend = strtoul(f[3], 0, 0);
  182. }
  183. }
  184. qsort(block, nblock, sizeof(Block), addrcmp);
  185. qsort(data, ndata, sizeof(Data), addrcmp);
  186. ed = edata = data+ndata;
  187. for(d=data; d<ed; d++) {
  188. if(d->type == 'a')
  189. continue;
  190. if(b = findblock(d->val-8)) // pool header 2 words
  191. n8 += markblock(b, d->addr);
  192. else if(b = findblock(d->val-8-8)) // sometimes malloc header 2 words
  193. n16 += markblock(b, d->addr);
  194. else
  195. {}//print("noblock %.8lux\n", d->val);
  196. }
  197. Binit(&bio, 1, OWRITE);
  198. if(bitmap){
  199. if(n8 > n16) // guess size of header
  200. hdr = 8;
  201. else
  202. hdr = 16;
  203. for(d=data; d<ed; d++)
  204. if(d->type=='a')
  205. break;
  206. if(d==ed)
  207. sysfatal("no allocated data region");
  208. len = (allocend-allocstart+resolution-1)/resolution;
  209. y = (len+x-1)/x;
  210. Bprint(&bio, "%11s %11d %11d %11d %11d ", "m8", 0, 0, x, y);
  211. //fprint(2, "alloc %lux %lux x %d y %d res %d\n", allocstart, allocend, x, y, resolution);
  212. b = block;
  213. eb = block+nblock;
  214. for(u = allocstart; u<allocend; u+=resolution){
  215. //fprint(2, "u %lux %lux baddr %lux\n", u, u+resolution, b->addr);
  216. while(b->addr+b->size <= u && b < eb)
  217. //{
  218. //fprint(2, "\tskip %lux %lux\n", b->addr, b->addr+b->size);
  219. b++;
  220. //}
  221. nhdr = 0;
  222. nleak = 0;
  223. nb = 0;
  224. nlhdr = 0;
  225. if(block < b && u < (b-1)->addr+(b-1)->size)
  226. b--;
  227. for(; b->addr < u+resolution && b < eb; b++){
  228. //fprint(2, "\tblock %lux %lux %d\n", b->addr, b->addr+b->size, b->mark);
  229. if(rXr(b->addr, b->addr+hdr, u, u+resolution)
  230. || rXr(b->addr+b->size-8, b->addr+b->size, u, u+resolution)){
  231. if(b->mark == 0)
  232. nlhdr++;
  233. else
  234. nhdr++;
  235. }
  236. if(b->mark == 0)
  237. nleak++;
  238. nb++;
  239. }
  240. if(nhdr)
  241. c = HdrColor;
  242. else if(nlhdr)
  243. c = LeakHdrColor;
  244. else if(nleak)
  245. c = LeakColor;
  246. else if(nb)
  247. c = AllocColor;
  248. else
  249. c = FreeColor;
  250. //fprint(2, "\t%d\n", c);
  251. Bputc(&bio, c);
  252. }
  253. allocend = allocstart+x*y*resolution;
  254. for(; u < allocend; u+=resolution)
  255. Bputc(&bio, NoColor);
  256. }else{
  257. eb = block+nblock;
  258. for(b=block; b<eb; b++)
  259. if(b->mark == 0)
  260. Bprint(&bio, "block 0x%.8lux 0x%.8lux 0x%.8lux 0x%.8lux\n", b->addr, b->size, b->w0, b->w1);
  261. }
  262. Bterm(&bio);
  263. }