static char *sccsid
= "@(#)gprof.c 1.11 (Berkeley) %G%";
while ( *argv
!= 0 && **argv
== '-' ) {
printf( "[main] debug = %d\n" , debug
);
* get information about a.out file.
* get information about mon.out file(s).
} while ( *argv
++ != 0 );
* dump out a gmon.sum file if requested
* assign samples to procedures
* print the usual profile
* assemble and print the dynamic profile
* Set up string and symbol tables from a.out.
* and optionally the text space.
* On return symbol table is sorted by value.
nfile
= fopen( a_outname
,"r");
fread(&xbuf
, 1, sizeof(xbuf
), nfile
);
fprintf(stderr
, "%s: %s: bad format\n", whoami
, a_outname
);
qsort(nl
, nname
, sizeof(nltype
), valcmp
);
if ( debug
& AOUTDEBUG
) {
for (j
= 0; j
< nname
; j
++){
printf("[getnfile] 0X%08x\t%s\n", nl
[j
].value
, nl
[j
].name
);
fseek(nfile
, (long)(N_SYMOFF(xbuf
) + xbuf
.a_syms
), 0);
if (fread(&ssiz
, sizeof (ssiz
), 1, nfile
) == 0) {
fprintf(stderr
, "%s: %s: no string table (old format?)\n" ,
strtab
= (char *)calloc(ssiz
, 1);
fprintf(stderr
, "%s: %s: no room for %d bytes of string table",
whoami
, a_outname
, ssiz
);
if (fread(strtab
+sizeof(ssiz
), ssiz
-sizeof(ssiz
), 1, nfile
) != 1) {
fprintf(stderr
, "%s: %s: error reading string table\n",
/* pass1 - count symbols */
fseek(nfile
, (long)N_SYMOFF(xbuf
), 0);
for (i
= xbuf
.a_syms
; i
> 0; i
-= sizeof(struct nlist
)) {
fread(&nbuf
, sizeof(nbuf
), 1, nfile
);
if ( ! funcsymbol( &nbuf
) ) {
fprintf(stderr
, "%s: %s: no symbols\n", whoami
, a_outname
);
nl
= (nltype
*) calloc( askfor
, sizeof(nltype
) );
fprintf(stderr
, "%s: No room for %d bytes of symbol table\n",
whoami
, askfor
* sizeof(nltype
) );
/* pass2 - read symbols */
fseek(nfile
, (long)N_SYMOFF(xbuf
), 0);
for (i
= xbuf
.a_syms
; i
> 0; i
-= sizeof(struct nlist
)) {
fread(&nbuf
, sizeof(nbuf
), 1, nfile
);
if ( ! funcsymbol( &nbuf
) ) {
if ( debug
& AOUTDEBUG
) {
printf( "[getsymtab] rejecting: 0x%x %s\n" ,
nbuf
.n_type
, strtab
+ nbuf
.n_un
.n_strx
);
npe
->value
= nbuf
.n_value
;
npe
->name
= strtab
+nbuf
.n_un
.n_strx
;
if ( debug
& AOUTDEBUG
) {
printf( "[getsymtab] %d %s 0x%08x\n" ,
nname
, npe
-> name
, npe
-> value
);
* read in the text space of an a.out file
textspace
= malloc( xbuf
.a_text
);
fprintf( stderr
, "%s: ran out room for %d bytes of text space: " ,
fprintf( stderr
, "can't do -c\n" );
(void) fseek( nfile
, N_TXTOFF( xbuf
) , 0 );
if ( fread( textspace
, 1 , xbuf
.a_text
, nfile
) != xbuf
.a_text
) {
fprintf( stderr
, "%s: couldn't read text space: " , whoami
);
fprintf( stderr
, "can't do -c\n" );
* information from a gmon.out file is in two parts:
* an array of sampling hits within pc ranges,
pfile
= openpfile(filename
);
* the rest of the file consists of
* a bunch of <from,self,count> tuples.
while ( fread( &arc
, sizeof arc
, 1 , pfile
) == 1 ) {
if ( debug
& SAMPLEDEBUG
) {
printf( "[getpfile] frompc 0x%x selfpc 0x%x count %d\n" ,
arc
.raw_frompc
, arc
.raw_selfpc
, arc
.raw_count
);
if((pfile
= fopen(filename
, "r")) == NULL
) {
fread(&tmp
, sizeof(struct hdr
), 1, pfile
);
if ( s_highpc
!= 0 && ( tmp
.lowpc
!= h
.lowpc
||
tmp
.highpc
!= h
.highpc
|| tmp
.ncnt
!= h
.ncnt
) ) {
fprintf(stderr
, "%s: incompatible with first gmon file\n", filename
);
s_lowpc
= (unsigned long) h
.lowpc
;
s_highpc
= (unsigned long) h
.highpc
;
lowpc
= h
.lowpc
- (UNIT
*)0;
highpc
= h
.highpc
- (UNIT
*)0;
sampbytes
= h
.ncnt
- sizeof(struct hdr
);
nsamples
= sampbytes
/ sizeof (unsigned UNIT
);
parentp
= nllookup( rawp
-> raw_frompc
);
childp
= nllookup( rawp
-> raw_selfpc
);
childp
-> ncall
+= rawp
-> raw_count
;
if ( debug
& TALLYDEBUG
) {
printf( "[tally] arc from %s to %s traversed %d times\n" ,
parentp
-> name
, childp
-> name
, rawp
-> raw_count
);
addarc( parentp
, childp
, rawp
-> raw_count
);
* dump out the gmon.sum file
if ( ( sfile
= fopen ( sumfile
, "w" ) ) == NULL
) {
* dump the header; use the last header read in
if ( fwrite( &h
, sizeof h
, 1 , sfile
) != 1 ) {
if (fwrite(samples
, sizeof(unsigned UNIT
), nsamples
, sfile
) != nsamples
) {
* dump the normalized raw arc information
for ( nlp
= nl
; nlp
< npe
- 1 ; nlp
++ ) {
for ( arcp
= nlp
-> children
; arcp
; arcp
= arcp
-> arc_childlist
) {
arc
.raw_frompc
= arcp
-> arc_parentp
-> value
;
arc
.raw_selfpc
= arcp
-> arc_childp
-> value
;
arc
.raw_count
= arcp
-> arc_count
;
if ( fwrite ( &arc
, sizeof arc
, 1 , sfile
) != 1 ) {
if ( debug
& SAMPLEDEBUG
) {
printf( "[dumpsum] frompc 0x%x selfpc 0x%x count %d\n" ,
arc
.raw_frompc
, arc
.raw_selfpc
, arc
.raw_count
);
if ( p1
-> value
< p2
-> value
) {
if ( p1
-> value
> p2
-> value
) {
samples
= (unsigned UNIT
*) calloc(sampbytes
, sizeof (unsigned UNIT
));
fprintf( stderr
, "%s: No room for %d sample pc's\n",
whoami
, sampbytes
/ sizeof (unsigned UNIT
));
for (i
= 0; i
< nsamples
; i
++) {
fread(&sample
, sizeof (unsigned UNIT
), 1, pfile
);
"%s: unexpected EOF after reading %d/%d samples\n",
whoami
, --i
, nsamples
);
* Assign samples to the procedures to which they belong.
unsigned long svalue0
, svalue1
;
/* read samples and assign to namelist symbols */
for (i
=0; i
< nsamples
; i
++) {
pch
= lowpc
+ scale
*(i
+1);
if ( debug
& SAMPLEDEBUG
) {
printf( "[asgnsamples] pcl 0x%x pch 0x%x ccnt %d\n" ,
for (j
=0; j
<nname
; j
++) {
svalue0
= nl
[j
].value
/ sizeof(UNIT
);
svalue1
= nl
[j
+1].value
/ sizeof(UNIT
);
overlap
=min(pch
,svalue1
) - max(pcl
,svalue0
);
if ( debug
& SAMPLEDEBUG
) {
printf( "[asgnsamples] (0x%x-0x%x) %s gets %f ticks\n" ,
svalue0
, svalue1
, nl
[j
].name
,
nl
[j
].time
+= overlap
*time
/scale
;
if ( debug
& SAMPLEDEBUG
) {
printf( "[asgnsamples] totime %f\n" , totime
);
fprintf( stderr
, "No time accumulated\n" );
extern char *strtab
; /* string table from a.out */
extern int aflag
; /* if static functions aren't desired */
* and static text symbols don't qualify if aflag set.
if ( ! ( ( nlistp
-> n_type
== ( N_TEXT
| N_EXT
) )
|| ( ( nlistp
-> n_type
== N_TEXT
) && ( aflag
== 0 ) ) ) ) {
* can't have any `funny' characters in name,
* where `funny' includes `.', .o file names
* and `$', pascal labels.
for ( name
= strtab
+ nlistp
-> n_un
.n_strx
; *name
; name
+= 1 ) {
if ( *name
== '.' || *name
== '$' ) {