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