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