prof.c 5.9 KB

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