prof.c 5.4 KB

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