prof.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <mach.h>
  5. typedef struct Data Data;
  6. typedef struct Pc Pc;
  7. typedef struct Acc Acc;
  8. struct Data
  9. {
  10. ushort down;
  11. ushort right;
  12. ulong pc;
  13. ulong count;
  14. ulong time;
  15. };
  16. struct Pc
  17. {
  18. Pc *next;
  19. ulong pc;
  20. };
  21. struct Acc
  22. {
  23. char *name;
  24. ulong pc;
  25. ulong ms;
  26. ulong calls;
  27. };
  28. Data* data;
  29. Acc* acc;
  30. ulong ms;
  31. long nsym;
  32. long ndata;
  33. int dflag;
  34. int rflag;
  35. Biobuf bout;
  36. int tabstop = 4;
  37. void syms(char*);
  38. void datas(char*);
  39. void graph(int, ulong, Pc*);
  40. void plot(void);
  41. char* name(ulong);
  42. void indent(int);
  43. char* defaout(void);
  44. void
  45. main(int argc, char *argv[])
  46. {
  47. char *s;
  48. s = getenv("tabstop");
  49. if(s!=nil && atoi(s)>0)
  50. tabstop = atoi(s);
  51. ARGBEGIN{
  52. case 'd':
  53. dflag = 1;
  54. break;
  55. case 'r':
  56. rflag = 1;
  57. break;
  58. default:
  59. fprint(2, "usage: prof [-dr] [8.out] [prof.out]\n");
  60. exits("usage");
  61. }ARGEND
  62. Binit(&bout, 1, OWRITE);
  63. if(argc > 0)
  64. syms(argv[0]);
  65. else
  66. syms(defaout());
  67. if(argc > 1)
  68. datas(argv[1]);
  69. else
  70. datas("prof.out");
  71. if(ndata){
  72. if(dflag)
  73. graph(0, data[0].down, 0);
  74. else
  75. plot();
  76. }
  77. exits(0);
  78. }
  79. void
  80. swapdata(Data *dp)
  81. {
  82. dp->down = beswab(dp->down);
  83. dp->right = beswab(dp->right);
  84. dp->pc = beswal(dp->pc);
  85. dp->count = beswal(dp->count);
  86. dp->time = beswal(dp->time);
  87. }
  88. int
  89. acmp(void *va, void *vb)
  90. {
  91. Acc *a, *b;
  92. ulong ua, ub;
  93. a = va;
  94. b = vb;
  95. ua = a->ms;
  96. ub = b->ms;
  97. if(ua > ub)
  98. return 1;
  99. if(ua < ub)
  100. return -1;
  101. return 0;
  102. }
  103. void
  104. syms(char *cout)
  105. {
  106. Fhdr f;
  107. int fd;
  108. if((fd = open(cout, 0)) < 0){
  109. perror(cout);
  110. exits("open");
  111. }
  112. if (!crackhdr(fd, &f)) {
  113. fprint(2, "can't read text file header\n");
  114. exits("read");
  115. }
  116. if (f.type == FNONE) {
  117. fprint(2, "text file not an a.out\n");
  118. exits("file type");
  119. }
  120. if (syminit(fd, &f) < 0) {
  121. fprint(2, "syminit: %r\n");
  122. exits("syms");
  123. }
  124. close(fd);
  125. }
  126. void
  127. datas(char *dout)
  128. {
  129. int fd;
  130. Dir *d;
  131. int i;
  132. if((fd = open(dout, 0)) < 0){
  133. perror(dout);
  134. exits("open");
  135. }
  136. d = dirfstat(fd);
  137. if(d == nil){
  138. perror(dout);
  139. exits("stat");
  140. }
  141. ndata = d->length/sizeof(data[0]);
  142. data = malloc(ndata*sizeof(Data));
  143. if(data == 0){
  144. fprint(2, "prof: can't malloc data\n");
  145. exits("data malloc");
  146. }
  147. if(read(fd, data, d->length) != d->length){
  148. fprint(2, "prof: can't read data file\n");
  149. exits("data read");
  150. }
  151. free(d);
  152. close(fd);
  153. for (i = 0; i < ndata; i++)
  154. swapdata(data+i);
  155. }
  156. char*
  157. name(ulong pc)
  158. {
  159. Symbol s;
  160. static char buf[16];
  161. if (findsym(pc, CTEXT, &s))
  162. return(s.name);
  163. sprint(buf, "#%lux", pc);
  164. return buf;
  165. }
  166. void
  167. graph(int ind, ulong i, Pc *pc)
  168. {
  169. long time, count, prgm;
  170. Pc lpc;
  171. if(i >= ndata){
  172. fprint(2, "prof: index out of range %ld [max %ld]\n", i, ndata);
  173. return;
  174. }
  175. count = data[i].count;
  176. time = data[i].time;
  177. prgm = data[i].pc;
  178. if(time < 0)
  179. time += data[0].time;
  180. if(data[i].right != 0xFFFF)
  181. graph(ind, data[i].right, pc);
  182. indent(ind);
  183. if(count == 1)
  184. Bprint(&bout, "%s:%lud\n", name(prgm), time);
  185. else
  186. Bprint(&bout, "%s:%lud/%lud\n", name(prgm), time, count);
  187. if(data[i].down == 0xFFFF)
  188. return;
  189. lpc.next = pc;
  190. lpc.pc = prgm;
  191. if(!rflag){
  192. while(pc){
  193. if(pc->pc == prgm){
  194. indent(ind+1);
  195. Bprint(&bout, "...\n");
  196. return;
  197. }
  198. pc = pc->next;
  199. }
  200. }
  201. graph(ind+1, data[i].down, &lpc);
  202. }
  203. /*
  204. * assume acc is ordered by increasing text address.
  205. */
  206. long
  207. symind(ulong pc)
  208. {
  209. int top, bot, mid;
  210. bot = 0;
  211. top = nsym;
  212. for (mid = (bot+top)/2; mid < top; mid = (bot+top)/2) {
  213. if (pc < acc[mid].pc)
  214. top = mid;
  215. else
  216. if (mid != nsym-1 && pc >= acc[mid+1].pc)
  217. bot = mid;
  218. else
  219. return mid;
  220. }
  221. return -1;
  222. }
  223. ulong
  224. sum(ulong i)
  225. {
  226. long j, dtime, time;
  227. if(i >= ndata){
  228. fprint(2, "prof: index out of range %ld [max %ld]\n", i, ndata);
  229. return 0;
  230. }
  231. time = data[i].time;
  232. if(time < 0)
  233. time += data[0].time;
  234. dtime = 0;
  235. if(data[i].down != 0xFFFF)
  236. dtime = sum(data[i].down);
  237. j = symind(data[i].pc);
  238. if (j >= 0) {
  239. acc[j].ms += time - dtime;
  240. ms += time - dtime;
  241. acc[j].calls += data[i].count;
  242. }
  243. if(data[i].right == 0xFFFF)
  244. return time;
  245. return time + sum(data[i].right);
  246. }
  247. void
  248. plot(void)
  249. {
  250. Symbol s;
  251. for (nsym = 0; textsym(&s, nsym); nsym++) {
  252. acc = realloc(acc, (nsym+1)*sizeof(Acc));
  253. if(acc == 0){
  254. fprint(2, "prof: malloc fail\n");
  255. exits("acc malloc");
  256. }
  257. acc[nsym].name = s.name;
  258. acc[nsym].pc = s.value;
  259. acc[nsym].calls = acc[nsym].ms = 0;
  260. }
  261. sum(data[0].down);
  262. qsort(acc, nsym, sizeof(Acc), acmp);
  263. Bprint(&bout, " %% Time\tCalls\tName\n");
  264. if(ms == 0)
  265. ms = 1;
  266. while (--nsym >= 0) {
  267. if(acc[nsym].calls)
  268. Bprint(&bout, "%4.1f%8.3f %8lud\t%s\n",
  269. (100.0*acc[nsym].ms)/ms,
  270. acc[nsym].ms/1000.0,
  271. acc[nsym].calls,
  272. acc[nsym].name);
  273. }
  274. }
  275. void
  276. indent(int ind)
  277. {
  278. int j;
  279. j = 2*ind;
  280. while(j >= tabstop){
  281. Bwrite(&bout, ".\t", 2);
  282. j -= tabstop;
  283. }
  284. if(j)
  285. Bwrite(&bout, ". ", j);
  286. }
  287. char* trans[] =
  288. {
  289. "386", "8.out",
  290. "68020", "2.out",
  291. "alpha", "7.out",
  292. "arm", "5.out",
  293. "mips", "v.out",
  294. "power", "q.out",
  295. "sparc", "k.out",
  296. "spim", "0.out",
  297. 0,0
  298. };
  299. char*
  300. defaout(void)
  301. {
  302. char *p;
  303. int i;
  304. p = getenv("objtype");
  305. if(p)
  306. for(i=0; trans[i]; i+=2)
  307. if(strcmp(p, trans[i]) == 0)
  308. return trans[i+1];
  309. return trans[1];
  310. }