Commit | Line | Data |
---|---|---|
c0bc4ef7 DF |
1 | /* |
2 | * Copyright (c) 1983 Regents of the University of California. | |
ddb85eed KB |
3 | * All rights reserved. |
4 | * | |
6ecf3d85 | 5 | * %sccs.include.redist.c% |
c0bc4ef7 DF |
6 | */ |
7 | ||
8 | #ifndef lint | |
9 | char copyright[] = | |
10 | "@(#) Copyright (c) 1983 Regents of the University of California.\n\ | |
11 | All rights reserved.\n"; | |
ddb85eed | 12 | #endif /* not lint */ |
c0bc4ef7 | 13 | |
3966d652 | 14 | #ifndef lint |
6ecf3d85 | 15 | static char sccsid[] = "@(#)gprof.c 5.6 (Berkeley) %G%"; |
ddb85eed | 16 | #endif /* not lint */ |
3966d652 | 17 | |
31f0a970 | 18 | #include "gprof.h" |
3966d652 | 19 | |
ad3b82ad PK |
20 | char *whoami = "gprof"; |
21 | ||
a441395b PK |
22 | /* |
23 | * things which get -E excluded by default. | |
24 | */ | |
25 | char *defaultEs[] = { "mcount" , "__mcleanup" , 0 }; | |
7ec9eedc | 26 | |
3966d652 | 27 | main(argc, argv) |
7ec9eedc PK |
28 | int argc; |
29 | char **argv; | |
3966d652 | 30 | { |
7ec9eedc | 31 | char **sp; |
b461ee6c | 32 | nltype **timesortnlp; |
3966d652 PK |
33 | |
34 | --argc; | |
35 | argv++; | |
36 | debug = 0; | |
355ab5a4 | 37 | bflag = TRUE; |
3966d652 PK |
38 | while ( *argv != 0 && **argv == '-' ) { |
39 | (*argv)++; | |
0c0ac747 | 40 | switch ( **argv ) { |
7ec9eedc PK |
41 | case 'a': |
42 | aflag = TRUE; | |
43 | break; | |
44 | case 'b': | |
355ab5a4 | 45 | bflag = FALSE; |
7ec9eedc PK |
46 | break; |
47 | case 'c': | |
48 | cflag = TRUE; | |
49 | break; | |
0c0ac747 | 50 | case 'd': |
7ec9eedc | 51 | dflag = TRUE; |
3966d652 PK |
52 | (*argv)++; |
53 | debug |= atoi( *argv ); | |
54 | debug |= ANYDEBUG; | |
55 | # ifdef DEBUG | |
074671d4 KM |
56 | printf("[main] debug = %d\n", debug); |
57 | # else not DEBUG | |
58 | printf("%s: -d ignored\n", whoami); | |
3966d652 | 59 | # endif DEBUG |
0c0ac747 | 60 | break; |
a441395b PK |
61 | case 'E': |
62 | ++argv; | |
63 | addlist( Elist , *argv ); | |
64 | Eflag = TRUE; | |
65 | addlist( elist , *argv ); | |
66 | eflag = TRUE; | |
67 | break; | |
7ec9eedc | 68 | case 'e': |
a441395b | 69 | addlist( elist , *++argv ); |
7ec9eedc | 70 | eflag = TRUE; |
a441395b PK |
71 | break; |
72 | case 'F': | |
73 | ++argv; | |
74 | addlist( Flist , *argv ); | |
75 | Fflag = TRUE; | |
76 | addlist( flist , *argv ); | |
77 | fflag = TRUE; | |
0c0ac747 | 78 | break; |
7ec9eedc | 79 | case 'f': |
a441395b | 80 | addlist( flist , *++argv ); |
7ec9eedc | 81 | fflag = TRUE; |
0c0ac747 | 82 | break; |
3cdecae8 KM |
83 | case 'k': |
84 | addlist( kfromlist , *++argv ); | |
85 | addlist( ktolist , *++argv ); | |
86 | kflag = TRUE; | |
87 | break; | |
0c0ac747 | 88 | case 's': |
7ec9eedc | 89 | sflag = TRUE; |
0c0ac747 KM |
90 | break; |
91 | case 'z': | |
7ec9eedc | 92 | zflag = TRUE; |
0c0ac747 | 93 | break; |
3966d652 PK |
94 | } |
95 | argv++; | |
96 | } | |
97 | if ( *argv != 0 ) { | |
98 | a_outname = *argv; | |
99 | argv++; | |
100 | } else { | |
101 | a_outname = A_OUTNAME; | |
102 | } | |
103 | if ( *argv != 0 ) { | |
31f0a970 | 104 | gmonname = *argv; |
3966d652 PK |
105 | argv++; |
106 | } else { | |
31f0a970 | 107 | gmonname = GMONNAME; |
7ec9eedc PK |
108 | } |
109 | /* | |
110 | * turn off default functions | |
111 | */ | |
a441395b PK |
112 | for ( sp = &defaultEs[0] ; *sp ; sp++ ) { |
113 | Eflag = TRUE; | |
114 | addlist( Elist , *sp ); | |
7ec9eedc | 115 | eflag = TRUE; |
a441395b | 116 | addlist( elist , *sp ); |
3966d652 | 117 | } |
89bcca98 | 118 | /* |
82fa08a4 PK |
119 | * how many ticks per second? |
120 | * if we can't tell, report time in ticks. | |
89bcca98 PK |
121 | */ |
122 | hz = hertz(); | |
82fa08a4 PK |
123 | if (hz == 0) { |
124 | hz = 1; | |
125 | fprintf(stderr, "time is in ticks, not seconds\n"); | |
126 | } | |
3966d652 PK |
127 | /* |
128 | * get information about a.out file. | |
129 | */ | |
130 | getnfile(); | |
131 | /* | |
132 | * get information about mon.out file(s). | |
133 | */ | |
0c0ac747 KM |
134 | do { |
135 | getpfile( gmonname ); | |
136 | if ( *argv != 0 ) { | |
137 | gmonname = *argv; | |
138 | } | |
ad3b82ad | 139 | } while ( *argv++ != 0 ); |
0c0ac747 KM |
140 | /* |
141 | * dump out a gmon.sum file if requested | |
142 | */ | |
ad3b82ad PK |
143 | if ( sflag ) { |
144 | dumpsum( GMONSUM ); | |
145 | } | |
3966d652 PK |
146 | /* |
147 | * assign samples to procedures | |
148 | */ | |
149 | asgnsamples(); | |
150 | /* | |
b461ee6c KM |
151 | * assemble the dynamic profile |
152 | */ | |
153 | timesortnlp = doarcs(); | |
154 | /* | |
155 | * print the dynamic profile | |
156 | */ | |
157 | printgprof( timesortnlp ); | |
158 | /* | |
159 | * print the flat profile | |
3966d652 PK |
160 | */ |
161 | printprof(); | |
162 | /* | |
b461ee6c | 163 | * print the index |
3966d652 | 164 | */ |
b461ee6c | 165 | printindex(); |
3966d652 PK |
166 | done(); |
167 | } | |
168 | ||
ad3b82ad PK |
169 | /* |
170 | * Set up string and symbol tables from a.out. | |
171 | * and optionally the text space. | |
172 | * On return symbol table is sorted by value. | |
173 | */ | |
3966d652 PK |
174 | getnfile() |
175 | { | |
176 | FILE *nfile; | |
104ad219 | 177 | int valcmp(); |
3966d652 PK |
178 | |
179 | nfile = fopen( a_outname ,"r"); | |
180 | if (nfile == NULL) { | |
181 | perror( a_outname ); | |
182 | done(); | |
183 | } | |
184 | fread(&xbuf, 1, sizeof(xbuf), nfile); | |
185 | if (N_BADMAG(xbuf)) { | |
ad3b82ad | 186 | fprintf(stderr, "%s: %s: bad format\n", whoami , a_outname ); |
3966d652 PK |
187 | done(); |
188 | } | |
189 | getstrtab(nfile); | |
190 | getsymtab(nfile); | |
29da1d26 | 191 | gettextspace( nfile ); |
3966d652 PK |
192 | qsort(nl, nname, sizeof(nltype), valcmp); |
193 | fclose(nfile); | |
194 | # ifdef DEBUG | |
195 | if ( debug & AOUTDEBUG ) { | |
196 | register int j; | |
197 | ||
198 | for (j = 0; j < nname; j++){ | |
199 | printf("[getnfile] 0X%08x\t%s\n", nl[j].value, nl[j].name); | |
200 | } | |
201 | } | |
202 | # endif DEBUG | |
203 | } | |
204 | ||
205 | getstrtab(nfile) | |
206 | FILE *nfile; | |
207 | { | |
208 | ||
209 | fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0); | |
210 | if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0) { | |
ad3b82ad PK |
211 | fprintf(stderr, "%s: %s: no string table (old format?)\n" , |
212 | whoami , a_outname ); | |
3966d652 PK |
213 | done(); |
214 | } | |
215 | strtab = (char *)calloc(ssiz, 1); | |
216 | if (strtab == NULL) { | |
ad3b82ad PK |
217 | fprintf(stderr, "%s: %s: no room for %d bytes of string table", |
218 | whoami , a_outname , ssiz); | |
3966d652 PK |
219 | done(); |
220 | } | |
221 | if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) { | |
ad3b82ad PK |
222 | fprintf(stderr, "%s: %s: error reading string table\n", |
223 | whoami , a_outname ); | |
3966d652 PK |
224 | done(); |
225 | } | |
226 | } | |
227 | ||
228 | /* | |
229 | * Read in symbol table | |
230 | */ | |
231 | getsymtab(nfile) | |
232 | FILE *nfile; | |
233 | { | |
234 | register long i; | |
235 | int askfor; | |
236 | struct nlist nbuf; | |
237 | ||
238 | /* pass1 - count symbols */ | |
239 | fseek(nfile, (long)N_SYMOFF(xbuf), 0); | |
240 | nname = 0; | |
241 | for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { | |
242 | fread(&nbuf, sizeof(nbuf), 1, nfile); | |
3f722622 | 243 | if ( ! funcsymbol( &nbuf ) ) { |
3966d652 PK |
244 | continue; |
245 | } | |
246 | nname++; | |
247 | } | |
248 | if (nname == 0) { | |
ad3b82ad | 249 | fprintf(stderr, "%s: %s: no symbols\n", whoami , a_outname ); |
3966d652 PK |
250 | done(); |
251 | } | |
ad3b82ad | 252 | askfor = nname + 1; |
3966d652 PK |
253 | nl = (nltype *) calloc( askfor , sizeof(nltype) ); |
254 | if (nl == 0) { | |
ad3b82ad PK |
255 | fprintf(stderr, "%s: No room for %d bytes of symbol table\n", |
256 | whoami, askfor * sizeof(nltype) ); | |
3966d652 PK |
257 | done(); |
258 | } | |
259 | ||
260 | /* pass2 - read symbols */ | |
261 | fseek(nfile, (long)N_SYMOFF(xbuf), 0); | |
262 | npe = nl; | |
263 | nname = 0; | |
264 | for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { | |
265 | fread(&nbuf, sizeof(nbuf), 1, nfile); | |
3f722622 PK |
266 | if ( ! funcsymbol( &nbuf ) ) { |
267 | # ifdef DEBUG | |
268 | if ( debug & AOUTDEBUG ) { | |
269 | printf( "[getsymtab] rejecting: 0x%x %s\n" , | |
270 | nbuf.n_type , strtab + nbuf.n_un.n_strx ); | |
271 | } | |
272 | # endif DEBUG | |
3966d652 PK |
273 | continue; |
274 | } | |
275 | npe->value = nbuf.n_value; | |
276 | npe->name = strtab+nbuf.n_un.n_strx; | |
277 | # ifdef DEBUG | |
278 | if ( debug & AOUTDEBUG ) { | |
279 | printf( "[getsymtab] %d %s 0x%08x\n" , | |
280 | nname , npe -> name , npe -> value ); | |
281 | } | |
282 | # endif DEBUG | |
283 | npe++; | |
284 | nname++; | |
285 | } | |
286 | npe->value = -1; | |
3966d652 PK |
287 | } |
288 | ||
29da1d26 PK |
289 | /* |
290 | * read in the text space of an a.out file | |
291 | */ | |
292 | gettextspace( nfile ) | |
293 | FILE *nfile; | |
294 | { | |
104ad219 | 295 | char *malloc(); |
29da1d26 PK |
296 | |
297 | if ( cflag == 0 ) { | |
298 | return; | |
299 | } | |
104ad219 | 300 | textspace = (u_char *) malloc( xbuf.a_text ); |
29da1d26 | 301 | if ( textspace == 0 ) { |
ad3b82ad PK |
302 | fprintf( stderr , "%s: ran out room for %d bytes of text space: " , |
303 | whoami , xbuf.a_text ); | |
304 | fprintf( stderr , "can't do -c\n" ); | |
29da1d26 PK |
305 | return; |
306 | } | |
307 | (void) fseek( nfile , N_TXTOFF( xbuf ) , 0 ); | |
308 | if ( fread( textspace , 1 , xbuf.a_text , nfile ) != xbuf.a_text ) { | |
ad3b82ad PK |
309 | fprintf( stderr , "%s: couldn't read text space: " , whoami ); |
310 | fprintf( stderr , "can't do -c\n" ); | |
29da1d26 PK |
311 | free( textspace ); |
312 | textspace = 0; | |
313 | return; | |
314 | } | |
315 | } | |
3966d652 | 316 | /* |
31f0a970 | 317 | * information from a gmon.out file is in two parts: |
3966d652 PK |
318 | * an array of sampling hits within pc ranges, |
319 | * and the arcs. | |
320 | */ | |
321 | getpfile(filename) | |
322 | char *filename; | |
323 | { | |
324 | FILE *pfile; | |
325 | FILE *openpfile(); | |
326 | struct rawarc arc; | |
327 | ||
328 | pfile = openpfile(filename); | |
329 | readsamples(pfile); | |
330 | /* | |
331 | * the rest of the file consists of | |
332 | * a bunch of <from,self,count> tuples. | |
333 | */ | |
334 | while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) { | |
335 | # ifdef DEBUG | |
336 | if ( debug & SAMPLEDEBUG ) { | |
06ac0fb1 | 337 | printf( "[getpfile] frompc 0x%x selfpc 0x%x count %d\n" , |
3966d652 PK |
338 | arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); |
339 | } | |
340 | # endif DEBUG | |
341 | /* | |
342 | * add this arc | |
343 | */ | |
344 | tally( &arc ); | |
345 | } | |
346 | fclose(pfile); | |
347 | } | |
348 | ||
35e3e365 PK |
349 | FILE * |
350 | openpfile(filename) | |
3966d652 PK |
351 | char *filename; |
352 | { | |
0c0ac747 | 353 | struct hdr tmp; |
3966d652 PK |
354 | FILE *pfile; |
355 | ||
356 | if((pfile = fopen(filename, "r")) == NULL) { | |
357 | perror(filename); | |
358 | done(); | |
359 | } | |
0c0ac747 KM |
360 | fread(&tmp, sizeof(struct hdr), 1, pfile); |
361 | if ( s_highpc != 0 && ( tmp.lowpc != h.lowpc || | |
362 | tmp.highpc != h.highpc || tmp.ncnt != h.ncnt ) ) { | |
363 | fprintf(stderr, "%s: incompatible with first gmon file\n", filename); | |
364 | done(); | |
365 | } | |
366 | h = tmp; | |
06ac0fb1 PK |
367 | s_lowpc = (unsigned long) h.lowpc; |
368 | s_highpc = (unsigned long) h.highpc; | |
6d94fded KM |
369 | lowpc = (unsigned long)h.lowpc / sizeof(UNIT); |
370 | highpc = (unsigned long)h.highpc / sizeof(UNIT); | |
3966d652 | 371 | sampbytes = h.ncnt - sizeof(struct hdr); |
104ad219 | 372 | nsamples = sampbytes / sizeof (UNIT); |
33e41a83 PK |
373 | # ifdef DEBUG |
374 | if ( debug & SAMPLEDEBUG ) { | |
375 | printf( "[openpfile] hdr.lowpc 0x%x hdr.highpc 0x%x hdr.ncnt %d\n", | |
376 | h.lowpc , h.highpc , h.ncnt ); | |
377 | printf( "[openpfile] s_lowpc 0x%x s_highpc 0x%x\n" , | |
378 | s_lowpc , s_highpc ); | |
379 | printf( "[openpfile] lowpc 0x%x highpc 0x%x\n" , | |
380 | lowpc , highpc ); | |
381 | printf( "[openpfile] sampbytes %d nsamples %d\n" , | |
382 | sampbytes , nsamples ); | |
383 | } | |
384 | # endif DEBUG | |
3966d652 PK |
385 | return(pfile); |
386 | } | |
387 | ||
388 | tally( rawp ) | |
389 | struct rawarc *rawp; | |
390 | { | |
391 | nltype *parentp; | |
392 | nltype *childp; | |
3966d652 PK |
393 | |
394 | parentp = nllookup( rawp -> raw_frompc ); | |
395 | childp = nllookup( rawp -> raw_selfpc ); | |
3cdecae8 KM |
396 | if ( kflag |
397 | && onlist( kfromlist , parentp -> name ) | |
398 | && onlist( ktolist , childp -> name ) ) { | |
399 | return; | |
400 | } | |
3966d652 PK |
401 | childp -> ncall += rawp -> raw_count; |
402 | # ifdef DEBUG | |
403 | if ( debug & TALLYDEBUG ) { | |
404 | printf( "[tally] arc from %s to %s traversed %d times\n" , | |
405 | parentp -> name , childp -> name , rawp -> raw_count ); | |
406 | } | |
407 | # endif DEBUG | |
29da1d26 | 408 | addarc( parentp , childp , rawp -> raw_count ); |
3966d652 PK |
409 | } |
410 | ||
0c0ac747 KM |
411 | /* |
412 | * dump out the gmon.sum file | |
413 | */ | |
414 | dumpsum( sumfile ) | |
415 | char *sumfile; | |
416 | { | |
417 | register nltype *nlp; | |
418 | register arctype *arcp; | |
419 | struct rawarc arc; | |
420 | FILE *sfile; | |
421 | ||
422 | if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) { | |
423 | perror( sumfile ); | |
424 | done(); | |
425 | } | |
426 | /* | |
427 | * dump the header; use the last header read in | |
428 | */ | |
429 | if ( fwrite( &h , sizeof h , 1 , sfile ) != 1 ) { | |
430 | perror( sumfile ); | |
431 | done(); | |
432 | } | |
433 | /* | |
434 | * dump the samples | |
435 | */ | |
104ad219 | 436 | if (fwrite(samples, sizeof (UNIT), nsamples, sfile) != nsamples) { |
0c0ac747 KM |
437 | perror( sumfile ); |
438 | done(); | |
439 | } | |
440 | /* | |
441 | * dump the normalized raw arc information | |
442 | */ | |
074671d4 | 443 | for ( nlp = nl ; nlp < npe ; nlp++ ) { |
0c0ac747 KM |
444 | for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) { |
445 | arc.raw_frompc = arcp -> arc_parentp -> value; | |
446 | arc.raw_selfpc = arcp -> arc_childp -> value; | |
447 | arc.raw_count = arcp -> arc_count; | |
448 | if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 ) { | |
449 | perror( sumfile ); | |
450 | done(); | |
451 | } | |
452 | # ifdef DEBUG | |
453 | if ( debug & SAMPLEDEBUG ) { | |
454 | printf( "[dumpsum] frompc 0x%x selfpc 0x%x count %d\n" , | |
455 | arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); | |
456 | } | |
457 | # endif DEBUG | |
458 | } | |
459 | } | |
460 | fclose( sfile ); | |
461 | } | |
462 | ||
3966d652 PK |
463 | valcmp(p1, p2) |
464 | nltype *p1, *p2; | |
465 | { | |
466 | if ( p1 -> value < p2 -> value ) { | |
467 | return LESSTHAN; | |
468 | } | |
469 | if ( p1 -> value > p2 -> value ) { | |
470 | return GREATERTHAN; | |
471 | } | |
472 | return EQUALTO; | |
473 | } | |
474 | ||
475 | readsamples(pfile) | |
476 | FILE *pfile; | |
477 | { | |
478 | register i; | |
104ad219 | 479 | UNIT sample; |
3966d652 PK |
480 | |
481 | if (samples == 0) { | |
104ad219 | 482 | samples = (UNIT *) calloc(sampbytes, sizeof (UNIT)); |
3966d652 | 483 | if (samples == 0) { |
ad3b82ad | 484 | fprintf( stderr , "%s: No room for %d sample pc's\n", |
104ad219 | 485 | whoami , sampbytes / sizeof (UNIT)); |
3966d652 PK |
486 | done(); |
487 | } | |
488 | } | |
489 | for (i = 0; i < nsamples; i++) { | |
104ad219 | 490 | fread(&sample, sizeof (UNIT), 1, pfile); |
3966d652 PK |
491 | if (feof(pfile)) |
492 | break; | |
493 | samples[i] += sample; | |
494 | } | |
495 | if (i != nsamples) { | |
496 | fprintf(stderr, | |
ad3b82ad PK |
497 | "%s: unexpected EOF after reading %d/%d samples\n", |
498 | whoami , --i , nsamples ); | |
3966d652 PK |
499 | done(); |
500 | } | |
501 | } | |
502 | ||
503 | /* | |
4855b699 KM |
504 | * Assign samples to the procedures to which they belong. |
505 | * | |
506 | * There are three cases as to where pcl and pch can be | |
507 | * with respect to the routine entry addresses svalue0 and svalue1 | |
508 | * as shown in the following diagram. overlap computes the | |
509 | * distance between the arrows, the fraction of the sample | |
510 | * that is to be credited to the routine which starts at svalue0. | |
511 | * | |
512 | * svalue0 svalue1 | |
513 | * | | | |
514 | * v v | |
515 | * | |
516 | * +-----------------------------------------------+ | |
517 | * | | | |
518 | * | ->| |<- ->| |<- ->| |<- | | |
519 | * | | | | | | | |
520 | * +---------+ +---------+ +---------+ | |
521 | * | |
522 | * ^ ^ ^ ^ ^ ^ | |
523 | * | | | | | | | |
524 | * pcl pch pcl pch pcl pch | |
525 | * | |
526 | * For the vax we assert that samples will never fall in the first | |
074671d4 KM |
527 | * two bytes of any routine, since that is the entry mask, |
528 | * thus we give call alignentries() to adjust the entry points if | |
529 | * the entry mask falls in one bucket but the code for the routine | |
530 | * doesn't start until the next bucket. In conjunction with the | |
531 | * alignment of routine addresses, this should allow us to have | |
532 | * only one sample for every four bytes of text space and never | |
533 | * have any overlap (the two end cases, above). | |
3966d652 PK |
534 | */ |
535 | asgnsamples() | |
536 | { | |
537 | register int j; | |
104ad219 | 538 | UNIT ccnt; |
3966d652 PK |
539 | double time; |
540 | unsigned long pcl, pch; | |
541 | register int i; | |
35e3e365 | 542 | unsigned long overlap; |
3966d652 PK |
543 | unsigned long svalue0, svalue1; |
544 | ||
545 | /* read samples and assign to namelist symbols */ | |
546 | scale = highpc - lowpc; | |
547 | scale /= nsamples; | |
074671d4 | 548 | alignentries(); |
0fcb1e15 | 549 | for (i = 0, j = 1; i < nsamples; i++) { |
3966d652 PK |
550 | ccnt = samples[i]; |
551 | if (ccnt == 0) | |
552 | continue; | |
4855b699 KM |
553 | pcl = lowpc + scale * i; |
554 | pch = lowpc + scale * (i + 1); | |
3966d652 PK |
555 | time = ccnt; |
556 | # ifdef DEBUG | |
557 | if ( debug & SAMPLEDEBUG ) { | |
eb6d6a16 KM |
558 | printf( "[asgnsamples] pcl 0x%x pch 0x%x ccnt %d\n" , |
559 | pcl , pch , ccnt ); | |
3966d652 PK |
560 | } |
561 | # endif DEBUG | |
562 | totime += time; | |
16051da5 | 563 | for (j = j - 1; j < nname; j++) { |
074671d4 KM |
564 | svalue0 = nl[j].svalue; |
565 | svalue1 = nl[j+1].svalue; | |
566 | /* | |
567 | * if high end of tick is below entry address, | |
568 | * go for next tick. | |
569 | */ | |
3966d652 PK |
570 | if (pch < svalue0) |
571 | break; | |
074671d4 KM |
572 | /* |
573 | * if low end of tick into next routine, | |
574 | * go for next routine. | |
575 | */ | |
3966d652 PK |
576 | if (pcl >= svalue1) |
577 | continue; | |
074671d4 | 578 | overlap = min(pch, svalue1) - max(pcl, svalue0); |
4855b699 | 579 | if (overlap > 0) { |
3966d652 | 580 | # ifdef DEBUG |
4855b699 | 581 | if (debug & SAMPLEDEBUG) { |
074671d4 KM |
582 | printf("[asgnsamples] (0x%x->0x%x-0x%x) %s gets %f ticks %d overlap\n", |
583 | nl[j].value/sizeof(UNIT), svalue0, svalue1, | |
584 | nl[j].name, | |
585 | overlap * time / scale, overlap); | |
3966d652 PK |
586 | } |
587 | # endif DEBUG | |
4855b699 | 588 | nl[j].time += overlap * time / scale; |
3966d652 PK |
589 | } |
590 | } | |
591 | } | |
592 | # ifdef DEBUG | |
4855b699 KM |
593 | if (debug & SAMPLEDEBUG) { |
594 | printf("[asgnsamples] totime %f\n", totime); | |
3966d652 PK |
595 | } |
596 | # endif DEBUG | |
3966d652 PK |
597 | } |
598 | ||
599 | ||
35e3e365 | 600 | unsigned long |
3966d652 | 601 | min(a, b) |
35e3e365 | 602 | unsigned long a,b; |
3966d652 PK |
603 | { |
604 | if (a<b) | |
605 | return(a); | |
606 | return(b); | |
607 | } | |
608 | ||
35e3e365 | 609 | unsigned long |
3966d652 | 610 | max(a, b) |
35e3e365 | 611 | unsigned long a,b; |
3966d652 PK |
612 | { |
613 | if (a>b) | |
614 | return(a); | |
615 | return(b); | |
616 | } | |
617 | ||
074671d4 KM |
618 | /* |
619 | * calculate scaled entry point addresses (to save time in asgnsamples), | |
620 | * and possibly push the scaled entry points over the entry mask, | |
621 | * if it turns out that the entry point is in one bucket and the code | |
622 | * for a routine is in the next bucket. | |
623 | */ | |
624 | alignentries() | |
625 | { | |
626 | register struct nl *nlp; | |
627 | unsigned long bucket_of_entry; | |
628 | unsigned long bucket_of_code; | |
629 | ||
630 | for (nlp = nl; nlp < npe; nlp++) { | |
631 | nlp -> svalue = nlp -> value / sizeof(UNIT); | |
632 | bucket_of_entry = (nlp->svalue - lowpc) / scale; | |
633 | bucket_of_code = (nlp->svalue + UNITS_TO_CODE - lowpc) / scale; | |
634 | if (bucket_of_entry < bucket_of_code) { | |
635 | # ifdef DEBUG | |
636 | if (debug & SAMPLEDEBUG) { | |
637 | printf("[alignentries] pushing svalue 0x%x to 0x%x\n", | |
638 | nlp->svalue, nlp->svalue + UNITS_TO_CODE); | |
639 | } | |
640 | # endif DEBUG | |
641 | nlp->svalue += UNITS_TO_CODE; | |
642 | } | |
643 | } | |
644 | } | |
645 | ||
3f722622 PK |
646 | bool |
647 | funcsymbol( nlistp ) | |
648 | struct nlist *nlistp; | |
649 | { | |
650 | extern char *strtab; /* string table from a.out */ | |
d51dad81 | 651 | extern int aflag; /* if static functions aren't desired */ |
3f722622 PK |
652 | char *name; |
653 | ||
654 | /* | |
655 | * must be a text symbol, | |
d51dad81 | 656 | * and static text symbols don't qualify if aflag set. |
3f722622 PK |
657 | */ |
658 | if ( ! ( ( nlistp -> n_type == ( N_TEXT | N_EXT ) ) | |
d51dad81 | 659 | || ( ( nlistp -> n_type == N_TEXT ) && ( aflag == 0 ) ) ) ) { |
3f722622 PK |
660 | return FALSE; |
661 | } | |
662 | /* | |
ad3b82ad | 663 | * can't have any `funny' characters in name, |
3f722622 PK |
664 | * where `funny' includes `.', .o file names |
665 | * and `$', pascal labels. | |
666 | */ | |
667 | for ( name = strtab + nlistp -> n_un.n_strx ; *name ; name += 1 ) { | |
668 | if ( *name == '.' || *name == '$' ) { | |
669 | return FALSE; | |
670 | } | |
671 | } | |
672 | return TRUE; | |
673 | } | |
674 | ||
3966d652 PK |
675 | done() |
676 | { | |
677 | ||
678 | exit(0); | |
679 | } |