1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <mach.h> 5 6 #define PCRES 8 7 8 struct COUNTER 9 { 10 char *name; /* function name */ 11 long time; /* ticks spent there */ 12 }; 13 14 void 15 error(int perr, char *s) 16 { 17 fprint(2, "kprof: %s", s); 18 if(perr){ 19 fprint(2, ": "); 20 perror(0); 21 }else 22 fprint(2, "\n"); 23 exits(s); 24 } 25 26 int 27 compar(struct COUNTER *a, struct COUNTER *b) 28 { 29 if(a->time < b->time) 30 return -1; 31 if(a->time == b->time) 32 return 0; 33 return 1; 34 } 35 void 36 main(int argc, char *argv[]) 37 { 38 int fd; 39 long i, j, k, n; 40 Dir d; 41 char *name; 42 ulong *data; 43 ulong tbase, sum; 44 long delta; 45 Symbol s; 46 Biobuf outbuf; 47 Fhdr f; 48 struct COUNTER *cp; 49 50 if(argc != 3) 51 error(0, "usage: kprof text data"); 52 /* 53 * Read symbol table 54 */ 55 fd = open(argv[1], OREAD); 56 if(fd < 0) 57 error(1, argv[1]); 58 if (!crackhdr(fd, &f)) 59 error(1, "read text header"); 60 if (f.type == FNONE) 61 error(0, "text file not an a.out"); 62 if (syminit(fd, &f) < 0) 63 error(1, "syminit"); 64 close(fd); 65 /* 66 * Read timing data 67 */ 68 fd = open(argv[2], OREAD); 69 if(fd < 0) 70 error(1, argv[2]); 71 if(dirfstat(fd, &d) < 0) 72 error(1, "stat"); 73 n = d.length/sizeof(data[0]); 74 if(n < 2) 75 error(0, "data file too short"); 76 data = malloc(d.length); 77 if(data == 0) 78 error(1, "malloc"); 79 if(read(fd, data, d.length) < 0) 80 error(1, "text read"); 81 close(fd); 82 for(i=0; i<n; i++) 83 data[i] = beswal(data[i]); 84 delta = data[0]-data[1]; 85 print("total: %ld in kernel text: %ld outside kernel text: %ld\n", 86 data[0], delta, data[1]); 87 if(data[0] == 0) 88 exits(0); 89 if (!textsym(&s, 0)) 90 error(0, "no text symbols"); 91 tbase = s.value & ~(mach->pgsize-1); /* align down to page */ 92 print("KTZERO %.8lux\n", tbase); 93 /* 94 * Accumulate counts for each function 95 */ 96 cp = 0; 97 k = 0; 98 for (i = 0, j = (s.value-tbase)/PCRES+2; j < n; i++) { 99 name = s.name; /* save name */ 100 if (!textsym(&s, i)) /* get next symbol */ 101 break; 102 sum = 0; 103 while (j < n && j*PCRES < s.value-tbase) 104 sum += data[j++]; 105 if (sum) { 106 cp = realloc(cp, (k+1)*sizeof(struct COUNTER)); 107 if (cp == 0) 108 error(1, "realloc"); 109 cp[k].name = name; 110 cp[k].time = sum; 111 k++; 112 } 113 } 114 if (!k) 115 error(0, "no counts"); 116 cp[k].time = 0; /* "etext" can take no time */ 117 /* 118 * Sort by time and print 119 */ 120 qsort(cp, k, sizeof(struct COUNTER), compar); 121 Binit(&outbuf, 1, OWRITE); 122 Bprint(&outbuf, "ms %% sym\n"); 123 while(--k>=0) 124 Bprint(&outbuf, "%ld\t%3ld.%d\t%s\n", 125 cp[k].time, 126 100*cp[k].time/delta, 127 (1000*cp[k].time/delta)%10, 128 cp[k].name); 129 exits(0); 130 } 131