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