gprof/ 775 22 12 0 4611253540 5106 gprof/Makefile 444 14 12 5404 4341434366 6642 # # Copyright (c) 1987 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific written prior permission. This software # is provided ``as is'' without express or implied warranty. # # @(#)Makefile 5.10 (Berkeley) 1/2/88 # CFLAGS= -O LIBC= /lib/libc.a HDRS= gprof.h ${MACHINE}.h SRCS= gprof.c arcs.c dfn.c lookup.c ${MACHINE}.c hertz.c \ printgprof.c printlist.c OBJS= gprof.o arcs.o dfn.o lookup.o ${MACHINE}.o hertz.o \ printgprof.o printlist.o LIBDIR= ../../lib all: gprof gprof: ${OBJS} ${LIBC} ${CC} -o $@ ${CFLAGS} ${OBJS} gcrt0.h: FRC -if [ -r gcrt0.h ] && \ cmp -s gcrt0.h ${LIBDIR}/libc/${MACHINE}/csu/gmon.h; then \ :; \ else \ rm -f gcrt0.h; \ cp ${LIBDIR}/libc/${MACHINE}/csu/gmon.h gcrt0.h; \ fi clean: FRC rm -f ${OBJS} core gprof depend: FRC mkdep ${CFLAGS} ${SRCS} install: FRC install -s -m 755 gprof ${DESTDIR}/usr/ucb/gprof install -c -m 644 gprof.flat ${DESTDIR}/usr/lib install -c -m 644 gprof.callg ${DESTDIR}/usr/lib lint: FRC lint ${CFLAGS} ${SRCS} tags: FRC ctags ${SRCS} FRC: # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. gprof.o: gprof.c gprof.h /usr/include/stdio.h /usr/include/sys/types.h gprof.o: /usr/include/sys/stat.h /usr/include/a.out.h /usr/include/sys/exec.h gprof.o: gcrt0.h tahoe.h arcs.o: arcs.c gprof.h /usr/include/stdio.h /usr/include/sys/types.h arcs.o: /usr/include/sys/stat.h /usr/include/a.out.h /usr/include/sys/exec.h arcs.o: gcrt0.h tahoe.h dfn.o: dfn.c /usr/include/stdio.h gprof.h /usr/include/stdio.h dfn.o: /usr/include/sys/types.h /usr/include/sys/stat.h /usr/include/a.out.h dfn.o: /usr/include/sys/exec.h gcrt0.h tahoe.h lookup.o: lookup.c gprof.h /usr/include/stdio.h /usr/include/sys/types.h lookup.o: /usr/include/sys/stat.h /usr/include/a.out.h /usr/include/sys/exec.h lookup.o: gcrt0.h tahoe.h tahoe.o: tahoe.c gprof.h /usr/include/stdio.h /usr/include/sys/types.h tahoe.o: /usr/include/sys/stat.h /usr/include/a.out.h /usr/include/sys/exec.h tahoe.o: gcrt0.h tahoe.h hertz.o: hertz.c /usr/include/sys/time.h /usr/include/time.h printgprof.o: printgprof.c gprof.h /usr/include/stdio.h printgprof.o: /usr/include/sys/types.h /usr/include/sys/stat.h printgprof.o: /usr/include/a.out.h /usr/include/sys/exec.h gcrt0.h tahoe.h printlist.o: printlist.c gprof.h /usr/include/stdio.h /usr/include/sys/types.h printlist.o: /usr/include/sys/stat.h /usr/include/a.out.h printlist.o: /usr/include/sys/exec.h gcrt0.h tahoe.h # IF YOU PUT ANYTHING HERE IT WILL GO AWAY gprof/tags 664 22 12 5307 4167370176 6074 Mgprof gprof.c /^main(argc, argv)$/ addarc arcs.c /^addarc( parentp , childp , count )$/ addlist printlist.c /^addlist( listp , funcname )$/ alignentries gprof.c /^alignentries()$/ arccmp printgprof.c /^arccmp( thisp , thatp )$/ arclookup lookup.c /^arclookup( parentp , childp )$/ asgnsamples gprof.c /^asgnsamples()$/ cyclelink arcs.c /^cyclelink()$/ cycletime arcs.c /^cycletime()$/ dfn dfn.c /^dfn( parentp )$/ dfn_busy dfn.c /^dfn_busy( childp )$/ dfn_findcycle dfn.c /^dfn_findcycle( childp )$/ dfn_numbered dfn.c /^dfn_numbered( childp )$/ dfn_post_visit dfn.c /^dfn_post_visit( parentp )$/ dfn_pre_visit dfn.c /^dfn_pre_visit( parentp )$/ dfn_self_cycle dfn.c /^dfn_self_cycle( parentp )$/ doarcs arcs.c /^doarcs()$/ doflags arcs.c /^doflags()$/ done gprof.c /^done()$/ dotime arcs.c /^dotime()$/ dumpsum gprof.c /^dumpsum( sumfile )$/ findcall tahoe.c /^findcall( parentp , p_lowpc , p_highpc )$/ flatprofheader printgprof.c /^flatprofheader()$/ flatprofline printgprof.c /^flatprofline( np )$/ funcsymbol gprof.c /^funcsymbol( nlistp )$/ getnfile gprof.c /^getnfile()$/ getpfile gprof.c /^getpfile(filename)$/ getstrtab gprof.c /^getstrtab(nfile)$/ getsymtab gprof.c /^getsymtab(nfile)$/ gettextspace gprof.c /^gettextspace( nfile )$/ gprofheader printgprof.c /^gprofheader()$/ gprofline printgprof.c /^gprofline( np )$/ hertz hertz.c /^hertz()$/ inheritflags arcs.c /^inheritflags( childp )$/ max gprof.c /^max(a, b)$/ membercmp printgprof.c /^membercmp( this , that )$/ min gprof.c /^min(a, b)$/ namecmp printgprof.c /^namecmp( npp1 , npp2 )$/ nllookup lookup.c /^nllookup( address )$/ onlist printlist.c /^onlist( listp , funcname )$/ openpfile gprof.c /^openpfile(filename)$/ operandlength tahoe.c /^operandlength( modep )$/ operandmode tahoe.c /^operandmode( modep )$/ operandname tahoe.c /^operandname( mode )$/ printblurb printgprof.c /^printblurb( blurbname )$/ printchildren printgprof.c /^printchildren( parentp )$/ printcycle printgprof.c /^printcycle( cyclep )$/ printgprof printgprof.c /^printgprof(timesortnlp)$/ printindex printgprof.c /^printindex()$/ printmembers printgprof.c /^printmembers( cyclep )$/ printname printgprof.c /^printname( selfp )$/ printparents printgprof.c /^printparents( childp )$/ printprof printgprof.c /^printprof()$/ readsamples gprof.c /^readsamples(pfile)$/ reladdr tahoe.c /^reladdr( modep )$/ sortchildren printgprof.c /^sortchildren( parentp )$/ sortmembers printgprof.c /^sortmembers( cyclep )$/ sortparents printgprof.c /^sortparents( childp )$/ tally gprof.c /^tally( rawp )$/ timecmp printgprof.c /^timecmp( npp1 , npp2 )$/ timepropagate arcs.c /^timepropagate( parentp )$/ topcmp arcs.c /^topcmp( npp1 , npp2 )$/ totalcmp printgprof.c /^totalcmp( npp1 , npp2 )$/ valcmp gprof.c /^valcmp(p1, p2)$/ gcrt0.h tahoe.h # IF YOU PUT ANYTHING HERE IT WILL GO AWAY gprof/printlist.c 444 22 12 3250 4044774075 7376 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)printlist.c 5.2 (Berkeley) 4/27/87"; #endif not lint #include "gprof.h" /* * these are the lists of names: * there is the list head and then the listname * is a pointer to the list head * (for ease of passing to stringlist functions). */ struct stringlist kfromhead = { 0 , 0 }; struct stringlist *kfromlist = &kfromhead; struct stringlist ktohead = { 0 , 0 }; struct stringlist *ktolist = &ktohead; struct stringlist fhead = { 0 , 0 }; struct stringlist *flist = &fhead; struct stringlist Fhead = { 0 , 0 }; struct stringlist *Flist = &Fhead; struct stringlist ehead = { 0 , 0 }; struct stringlist *elist = &ehead; struct stringlist Ehead = { 0 , 0 }; struct stringlist *Elist = &Ehead; addlist( listp , funcname ) struct stringlist *listp; char *funcname; { struct stringlist *slp; slp = (struct stringlist *) malloc( sizeof(struct stringlist)); if ( slp == (struct stringlist *) 0 ) { fprintf( stderr, "gprof: ran out room for printlist\n" ); done(); } slp -> next = listp -> next; slp -> string = funcname; listp -> next = slp; } bool onlist( listp , funcname ) struct stringlist *listp; char *funcname; { struct stringlist *slp; for ( slp = listp -> next ; slp ; slp = slp -> next ) { if ( ! strcmp( slp -> string , funcname ) ) { return TRUE; } if ( funcname[0] == '_' && ! strcmp( slp -> string , &funcname[1] ) ) { return TRUE; } } return FALSE; } tahoe.c /^operandlength( modep )$/ operandmode tahoe.c /^operandmode( modep )$/ operandname tahoe.c /^operandname( mode )$/ printblurb printgprof.c /^printblurb( blurbname )$/ printchildren printgprof.c /^printchildren( parentp )$/ printcycle printgprof.c /^printcycle( cyclep )$/ printgprof printgprof.c /^printgprof(timesortnlp)$/ printindex gprof/gprof.c 444 33 12 36756 4436154435 6523 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n"; #endif not lint #ifndef lint static char sccsid[] = "@(#)gprof.c 5.3 (Berkeley) 1/2/88"; #endif not lint #include "gprof.h" char *whoami = "gprof"; /* * things which get -E excluded by default. */ char *defaultEs[] = { "mcount" , "__mcleanup" , 0 }; main(argc, argv) int argc; char **argv; { char **sp; nltype **timesortnlp; --argc; argv++; debug = 0; bflag = TRUE; while ( *argv != 0 && **argv == '-' ) { (*argv)++; switch ( **argv ) { case 'a': aflag = TRUE; break; case 'b': bflag = FALSE; break; case 'c': #if hp300 fprintf(stderr, "gprof -c isn't supported on hp300s yet\n"); exit(1); #endif cflag = TRUE; break; case 'd': dflag = TRUE; (*argv)++; debug |= atoi( *argv ); debug |= ANYDEBUG; # ifdef DEBUG printf("[main] debug = %d\n", debug); # else not DEBUG printf("%s: -d ignored\n", whoami); # endif DEBUG break; case 'E': ++argv; addlist( Elist , *argv ); Eflag = TRUE; addlist( elist , *argv ); eflag = TRUE; break; case 'e': addlist( elist , *++argv ); eflag = TRUE; break; case 'F': ++argv; addlist( Flist , *argv ); Fflag = TRUE; addlist( flist , *argv ); fflag = TRUE; break; case 'f': addlist( flist , *++argv ); fflag = TRUE; break; case 'H': hz = atoi( *++argv ); if (hz < 0 || hz > 100000) { fprintf(stderr, "unreasonable HZ value, using default\n"); hz = 0; } break; case 'k': addlist( kfromlist , *++argv ); addlist( ktolist , *++argv ); kflag = TRUE; break; case 's': sflag = TRUE; break; case 'z': zflag = TRUE; break; } argv++; } if ( *argv != 0 ) { a_outname = *argv; argv++; } else { a_outname = A_OUTNAME; } if ( *argv != 0 ) { gmonname = *argv; argv++; } else { gmonname = GMONNAME; } /* * turn off default functions */ for ( sp = &defaultEs[0] ; *sp ; sp++ ) { Eflag = TRUE; addlist( Elist , *sp ); eflag = TRUE; addlist( elist , *sp ); } /* * how many ticks per second? * if we can't tell, report time in ticks. */ if (hz == 0) hz = hertz(); if (hz == 0) { hz = 1; fprintf(stderr, "time is in ticks, not seconds\n"); } /* * get information about a.out file. */ getnfile(); /* * get information about mon.out file(s). */ do { getpfile( gmonname ); if ( *argv != 0 ) { gmonname = *argv; } } while ( *argv++ != 0 ); /* * dump out a gmon.sum file if requested */ if ( sflag ) { dumpsum( GMONSUM ); } /* * assign samples to procedures */ asgnsamples(); /* * assemble the dynamic profile */ timesortnlp = doarcs(); /* * print the dynamic profile */ printgprof( timesortnlp ); /* * print the flat profile */ printprof(); /* * print the index */ printindex(); done(); } /* * Set up string and symbol tables from a.out. * and optionally the text space. * On return symbol table is sorted by value. */ getnfile() { FILE *nfile; int valcmp(); nfile = fopen( a_outname ,"r"); if (nfile == NULL) { perror( a_outname ); done(); } fread(&xbuf, 1, sizeof(xbuf), nfile); if (N_BADMAG(xbuf)) { fprintf(stderr, "%s: %s: bad format\n", whoami , a_outname ); done(); } getstrtab(nfile); getsymtab(nfile); gettextspace( nfile ); qsort(nl, nname, sizeof(nltype), valcmp); fclose(nfile); # ifdef DEBUG if ( debug & AOUTDEBUG ) { register int j; for (j = 0; j < nname; j++){ printf("[getnfile] 0X%08x\t%s\n", nl[j].value, nl[j].name); } } # endif DEBUG } getstrtab(nfile) FILE *nfile; { 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" , whoami , a_outname ); done(); } strtab = (char *)calloc(ssiz, 1); if (strtab == NULL) { fprintf(stderr, "%s: %s: no room for %d bytes of string table", whoami , a_outname , ssiz); done(); } if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) { fprintf(stderr, "%s: %s: error reading string table\n", whoami , a_outname ); done(); } } /* * Read in symbol table */ getsymtab(nfile) FILE *nfile; { register long i; int askfor; struct nlist nbuf; /* pass1 - count symbols */ fseek(nfile, (long)N_SYMOFF(xbuf), 0); nname = 0; for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { fread(&nbuf, sizeof(nbuf), 1, nfile); if ( ! funcsymbol( &nbuf ) ) { continue; } nname++; } if (nname == 0) { fprintf(stderr, "%s: %s: no symbols\n", whoami , a_outname ); done(); } askfor = nname + 1; nl = (nltype *) calloc( askfor , sizeof(nltype) ); if (nl == 0) { fprintf(stderr, "%s: No room for %d bytes of symbol table\n", whoami, askfor * sizeof(nltype) ); done(); } /* pass2 - read symbols */ fseek(nfile, (long)N_SYMOFF(xbuf), 0); npe = nl; nname = 0; for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { fread(&nbuf, sizeof(nbuf), 1, nfile); if ( ! funcsymbol( &nbuf ) ) { # ifdef DEBUG if ( debug & AOUTDEBUG ) { printf( "[getsymtab] rejecting: 0x%x %s\n" , nbuf.n_type , strtab + nbuf.n_un.n_strx ); } # endif DEBUG continue; } npe->value = nbuf.n_value; npe->name = strtab+nbuf.n_un.n_strx; # ifdef DEBUG if ( debug & AOUTDEBUG ) { printf( "[getsymtab] %d %s 0x%08x\n" , nname , npe -> name , npe -> value ); } # endif DEBUG npe++; nname++; } npe->value = -1; } /* * read in the text space of an a.out file */ gettextspace( nfile ) FILE *nfile; { char *malloc(); if ( cflag == 0 ) { return; } textspace = (u_char *) malloc( xbuf.a_text ); if ( textspace == 0 ) { fprintf( stderr , "%s: ran out room for %d bytes of text space: " , whoami , xbuf.a_text ); fprintf( stderr , "can't do -c\n" ); return; } (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" ); free( textspace ); textspace = 0; return; } } /* * information from a gmon.out file is in two parts: * an array of sampling hits within pc ranges, * and the arcs. */ getpfile(filename) char *filename; { FILE *pfile; FILE *openpfile(); struct rawarc arc; pfile = openpfile(filename); readsamples(pfile); /* * the rest of the file consists of * a bunch of <from,self,count> tuples. */ while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) { # ifdef DEBUG if ( debug & SAMPLEDEBUG ) { printf( "[getpfile] frompc 0x%x selfpc 0x%x count %d\n" , arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); } # endif DEBUG /* * add this arc */ tally( &arc ); } fclose(pfile); } FILE * openpfile(filename) char *filename; { struct hdr tmp; FILE *pfile; if((pfile = fopen(filename, "r")) == NULL) { perror(filename); done(); } 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); done(); } h = tmp; s_lowpc = (unsigned long) h.lowpc; s_highpc = (unsigned long) h.highpc; lowpc = (unsigned long)h.lowpc / sizeof(UNIT); highpc = (unsigned long)h.highpc / sizeof(UNIT); sampbytes = h.ncnt - sizeof(struct hdr); nsamples = sampbytes / sizeof (UNIT); # ifdef DEBUG if ( debug & SAMPLEDEBUG ) { printf( "[openpfile] hdr.lowpc 0x%x hdr.highpc 0x%x hdr.ncnt %d\n", h.lowpc , h.highpc , h.ncnt ); printf( "[openpfile] s_lowpc 0x%x s_highpc 0x%x\n" , s_lowpc , s_highpc ); printf( "[openpfile] lowpc 0x%x highpc 0x%x\n" , lowpc , highpc ); printf( "[openpfile] sampbytes %d nsamples %d\n" , sampbytes , nsamples ); } # endif DEBUG return(pfile); } tally( rawp ) struct rawarc *rawp; { nltype *parentp; nltype *childp; parentp = nllookup( rawp -> raw_frompc ); childp = nllookup( rawp -> raw_selfpc ); if ( kflag && onlist( kfromlist , parentp -> name ) && onlist( ktolist , childp -> name ) ) { return; } childp -> ncall += rawp -> raw_count; # ifdef DEBUG if ( debug & TALLYDEBUG ) { printf( "[tally] arc from %s to %s traversed %d times\n" , parentp -> name , childp -> name , rawp -> raw_count ); } # endif DEBUG addarc( parentp , childp , rawp -> raw_count ); } /* * dump out the gmon.sum file */ dumpsum( sumfile ) char *sumfile; { register nltype *nlp; register arctype *arcp; struct rawarc arc; FILE *sfile; if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) { perror( sumfile ); done(); } /* * dump the header; use the last header read in */ if ( fwrite( &h , sizeof h , 1 , sfile ) != 1 ) { perror( sumfile ); done(); } /* * dump the samples */ if (fwrite(samples, sizeof (UNIT), nsamples, sfile) != nsamples) { perror( sumfile ); done(); } /* * dump the normalized raw arc information */ for ( nlp = nl ; nlp < npe ; 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 ) { perror( sumfile ); done(); } # ifdef DEBUG if ( debug & SAMPLEDEBUG ) { printf( "[dumpsum] frompc 0x%x selfpc 0x%x count %d\n" , arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); } # endif DEBUG } } fclose( sfile ); } valcmp(p1, p2) nltype *p1, *p2; { if ( p1 -> value < p2 -> value ) { return LESSTHAN; } if ( p1 -> value > p2 -> value ) { return GREATERTHAN; } return EQUALTO; } readsamples(pfile) FILE *pfile; { register i; UNIT sample; if (samples == 0) { samples = (UNIT *) calloc(sampbytes, sizeof (UNIT)); if (samples == 0) { fprintf( stderr , "%s: No room for %d sample pc's\n", whoami , sampbytes / sizeof (UNIT)); done(); } } for (i = 0; i < nsamples; i++) { fread(&sample, sizeof (UNIT), 1, pfile); if (feof(pfile)) break; samples[i] += sample; } if (i != nsamples) { fprintf(stderr, "%s: unexpected EOF after reading %d/%d samples\n", whoami , --i , nsamples ); done(); } } /* * Assign samples to the procedures to which they belong. * * There are three cases as to where pcl and pch can be * with respect to the routine entry addresses svalue0 and svalue1 * as shown in the following diagram. overlap computes the * distance between the arrows, the fraction of the sample * that is to be credited to the routine which starts at svalue0. * * svalue0 svalue1 * | | * v v * * +-----------------------------------------------+ * | | * | ->| |<- ->| |<- ->| |<- | * | | | | | | * +---------+ +---------+ +---------+ * * ^ ^ ^ ^ ^ ^ * | | | | | | * pcl pch pcl pch pcl pch * * For the vax we assert that samples will never fall in the first * two bytes of any routine, since that is the entry mask, * thus we give call alignentries() to adjust the entry points if * the entry mask falls in one bucket but the code for the routine * doesn't start until the next bucket. In conjunction with the * alignment of routine addresses, this should allow us to have * only one sample for every four bytes of text space and never * have any overlap (the two end cases, above). */ asgnsamples() { register int j; UNIT ccnt; double time; unsigned long pcl, pch; register int i; unsigned long overlap; unsigned long svalue0, svalue1; /* read samples and assign to namelist symbols */ scale = highpc - lowpc; scale /= nsamples; alignentries(); for (i = 0, j = 1; i < nsamples; i++) { ccnt = samples[i]; if (ccnt == 0) continue; pcl = lowpc + scale * i; pch = lowpc + scale * (i + 1); time = ccnt; # ifdef DEBUG if ( debug & SAMPLEDEBUG ) { printf( "[asgnsamples] pcl 0x%x pch 0x%x ccnt %d\n" , pcl , pch , ccnt ); } # endif DEBUG totime += time; for (j = j - 1; j < nname; j++) { svalue0 = nl[j].svalue; svalue1 = nl[j+1].svalue; /* * if high end of tick is below entry address, * go for next tick. */ if (pch < svalue0) break; /* * if low end of tick into next routine, * go for next routine. */ if (pcl >= svalue1) continue; overlap = min(pch, svalue1) - max(pcl, svalue0); if (overlap > 0) { # ifdef DEBUG if (debug & SAMPLEDEBUG) { printf("[asgnsamples] (0x%x->0x%x-0x%x) %s gets %f ticks %d overlap\n", nl[j].value/sizeof(UNIT), svalue0, svalue1, nl[j].name, overlap * time / scale, overlap); } # endif DEBUG nl[j].time += overlap * time / scale; } } } # ifdef DEBUG if (debug & SAMPLEDEBUG) { printf("[asgnsamples] totime %f\n", totime); } # endif DEBUG } unsigned long min(a, b) unsigned long a,b; { if (a<b) return(a); return(b); } unsigned long max(a, b) unsigned long a,b; { if (a>b) return(a); return(b); } /* * calculate scaled entry point addresses (to save time in asgnsamples), * and possibly push the scaled entry points over the entry mask, * if it turns out that the entry point is in one bucket and the code * for a routine is in the next bucket. */ alignentries() { register struct nl *nlp; unsigned long bucket_of_entry; unsigned long bucket_of_code; for (nlp = nl; nlp < npe; nlp++) { nlp -> svalue = nlp -> value / sizeof(UNIT); bucket_of_entry = (nlp->svalue - lowpc) / scale; bucket_of_code = (nlp->svalue + UNITS_TO_CODE - lowpc) / scale; if (bucket_of_entry < bucket_of_code) { # ifdef DEBUG if (debug & SAMPLEDEBUG) { printf("[alignentries] pushing svalue 0x%x to 0x%x\n", nlp->svalue, nlp->svalue + UNITS_TO_CODE); } # endif DEBUG nlp->svalue += UNITS_TO_CODE; } } } bool funcsymbol( nlistp ) struct nlist *nlistp; { extern char *strtab; /* string table from a.out */ extern int aflag; /* if static functions aren't desired */ char *name; /* * must be a text symbol, * 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 ) ) ) ) { return FALSE; } /* * 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 == '$' ) { return FALSE; } } return TRUE; } done() { exit(0); } -------+ * gprof/gprof.h 444 22 12 15325 4230312011 6465 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)gprof.h 5.4 (Berkeley) 1/2/88 */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <a.out.h> #include "gcrt0.h" #if vax # include "vax.h" #endif #if sun # include "sun.h" #endif #if tahoe # include "tahoe.h" #endif #if hp300 # include "hp300.h" #endif /* * who am i, for error messages. */ char *whoami; /* * booleans */ typedef int bool; #define FALSE 0 #define TRUE 1 /* * ticks per second */ long hz; typedef u_short UNIT; /* unit of profiling */ char *a_outname; #define A_OUTNAME "a.out" char *gmonname; #define GMONNAME "gmon.out" #define GMONSUM "gmon.sum" /* * blurbs on the flat and graph profiles. */ #define FLAT_BLURB "/usr/lib/gprof.flat" #define CALLG_BLURB "/usr/lib/gprof.callg" /* * a constructed arc, * with pointers to the namelist entry of the parent and the child, * a count of how many times this arc was traversed, * and pointers to the next parent of this child and * the next child of this parent. */ struct arcstruct { struct nl *arc_parentp; /* pointer to parent's nl entry */ struct nl *arc_childp; /* pointer to child's nl entry */ long arc_count; /* how calls from parent to child */ double arc_time; /* time inherited along arc */ double arc_childtime; /* childtime inherited along arc */ struct arcstruct *arc_parentlist; /* parents-of-this-child list */ struct arcstruct *arc_childlist; /* children-of-this-parent list */ }; typedef struct arcstruct arctype; /* * The symbol table; * for each external in the specified file we gather * its address, the number of calls and compute its share of cpu time. */ struct nl { char *name; /* the name */ unsigned long value; /* the pc entry point */ unsigned long svalue; /* entry point aligned to histograms */ double time; /* ticks in this routine */ double childtime; /* cumulative ticks in children */ long ncall; /* how many times called */ long selfcalls; /* how many calls to self */ double propfraction; /* what % of time propagates */ double propself; /* how much self time propagates */ double propchild; /* how much child time propagates */ bool printflag; /* should this be printed? */ int index; /* index in the graph list */ int toporder; /* graph call chain top-sort order */ int cycleno; /* internal number of cycle on */ struct nl *cyclehead; /* pointer to head of cycle */ struct nl *cnext; /* pointer to next member of cycle */ arctype *parents; /* list of caller arcs */ arctype *children; /* list of callee arcs */ }; typedef struct nl nltype; nltype *nl; /* the whole namelist */ nltype *npe; /* the virtual end of the namelist */ int nname; /* the number of function names */ /* * flag which marks a nl entry as topologically ``busy'' * flag which marks a nl entry as topologically ``not_numbered'' */ #define DFN_BUSY -1 #define DFN_NAN 0 /* * namelist entries for cycle headers. * the number of discovered cycles. */ nltype *cyclenl; /* cycle header namelist */ int ncycle; /* number of cycles discovered */ /* * The header on the gmon.out file. * gmon.out consists of one of these headers, * and then an array of ncnt samples * representing the discretized program counter values. * this should be a struct phdr, but since everything is done * as UNITs, this is in UNITs too. */ struct hdr { UNIT *lowpc; UNIT *highpc; int ncnt; }; struct hdr h; int debug; /* * Each discretized pc sample has * a count of the number of samples in its range */ UNIT *samples; unsigned long s_lowpc; /* lowpc from the profile file */ unsigned long s_highpc; /* highpc from the profile file */ unsigned lowpc, highpc; /* range profiled, in UNIT's */ unsigned sampbytes; /* number of bytes of samples */ int nsamples; /* number of samples */ double actime; /* accumulated time thus far for putprofline */ double totime; /* total time for all routines */ double printtime; /* total of time being printed */ double scale; /* scale factor converting samples to pc values: each sample covers scale bytes */ char *strtab; /* string table in core */ off_t ssiz; /* size of the string table */ struct exec xbuf; /* exec header of a.out */ unsigned char *textspace; /* text space of a.out in core */ /* * option flags, from a to z. */ bool aflag; /* suppress static functions */ bool bflag; /* blurbs, too */ bool cflag; /* discovered call graph, too */ bool dflag; /* debugging options */ bool eflag; /* specific functions excluded */ bool Eflag; /* functions excluded with time */ bool fflag; /* specific functions requested */ bool Fflag; /* functions requested with time */ bool kflag; /* arcs to be deleted */ bool sflag; /* sum multiple gmon.out files */ bool zflag; /* zero time/called functions, too */ /* * structure for various string lists */ struct stringlist { struct stringlist *next; char *string; }; struct stringlist *elist; struct stringlist *Elist; struct stringlist *flist; struct stringlist *Flist; struct stringlist *kfromlist; struct stringlist *ktolist; /* * function declarations */ /* addarc(); */ int arccmp(); arctype *arclookup(); /* asgnsamples(); printblurb(); cyclelink(); dfn(); */ bool dfn_busy(); /* dfn_findcycle(); */ bool dfn_numbered(); /* dfn_post_visit(); dfn_pre_visit(); dfn_self_cycle(); */ nltype **doarcs(); /* done(); findcalls(); flatprofheader(); flatprofline(); */ bool funcsymbol(); /* getnfile(); getpfile(); getstrtab(); getsymtab(); gettextspace(); gprofheader(); gprofline(); main(); */ unsigned long max(); int membercmp(); unsigned long min(); nltype *nllookup(); FILE *openpfile(); long operandlength(); operandenum operandmode(); char *operandname(); /* printchildren(); printcycle(); printgprof(); printmembers(); printname(); printparents(); printprof(); readsamples(); */ unsigned long reladdr(); /* sortchildren(); sortmembers(); sortparents(); tally(); timecmp(); topcmp(); */ int totalcmp(); /* valcmp(); */ #define LESSTHAN -1 #define EQUALTO 0 #define GREATERTHAN 1 #define DFNDEBUG 1 #define CYCLEDEBUG 2 #define ARCDEBUG 4 #define TALLYDEBUG 8 #define TIMEDEBUG 16 #define SAMPLEDEBUG 32 #define AOUTDEBUG 64 #define CALLDEBUG 128 #define LOOKUPDEBUG 256 #define PROPDEBUG 512 #define ANYDEBUG 1024 ext; /* pointer to next member of cycle */ arctype *parents; /* list of caller arcs */ arctype *children; /* list of callee arcs */ }; typedef struct nl nltype; nltype *nl; /* the whole namelist */ nltype *npe; /* the virtual end of the namelist */ int nname; /* the number of funcgprof/dfn.c 444 22 12 14644 3500670430 6130 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)dfn.c 5.1 (Berkeley) 6/4/85"; #endif not lint #include <stdio.h> #include "gprof.h" #define DFN_DEPTH 100 struct dfnstruct { nltype *nlentryp; int cycletop; }; typedef struct dfnstruct dfntype; dfntype dfn_stack[ DFN_DEPTH ]; int dfn_depth = 0; int dfn_counter = DFN_NAN; /* * given this parent, depth first number its children. */ dfn( parentp ) nltype *parentp; { arctype *arcp; # ifdef DEBUG if ( debug & DFNDEBUG ) { printf( "[dfn] dfn(" ); printname( parentp ); printf( ")\n" ); } # endif DEBUG /* * if we're already numbered, no need to look any furthur. */ if ( dfn_numbered( parentp ) ) { return; } /* * if we're already busy, must be a cycle */ if ( dfn_busy( parentp ) ) { dfn_findcycle( parentp ); return; } /* * visit yourself before your children */ dfn_pre_visit( parentp ); /* * visit children */ for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { dfn( arcp -> arc_childp ); } /* * visit yourself after your children */ dfn_post_visit( parentp ); } /* * push a parent onto the stack and mark it busy */ dfn_pre_visit( parentp ) nltype *parentp; { dfn_depth += 1; if ( dfn_depth >= DFN_DEPTH ) { fprintf( stderr , "[dfn] out of my depth (dfn_stack overflow)\n" ); exit( 1 ); } dfn_stack[ dfn_depth ].nlentryp = parentp; dfn_stack[ dfn_depth ].cycletop = dfn_depth; parentp -> toporder = DFN_BUSY; # ifdef DEBUG if ( debug & DFNDEBUG ) { printf( "[dfn_pre_visit]\t\t%d:" , dfn_depth ); printname( parentp ); printf( "\n" ); } # endif DEBUG } /* * are we already numbered? */ bool dfn_numbered( childp ) nltype *childp; { return ( childp -> toporder != DFN_NAN && childp -> toporder != DFN_BUSY ); } /* * are we already busy? */ bool dfn_busy( childp ) nltype *childp; { if ( childp -> toporder == DFN_NAN ) { return FALSE; } return TRUE; } /* * MISSING: an explanation */ dfn_findcycle( childp ) nltype *childp; { int cycletop; nltype *cycleheadp; nltype *tailp; int index; for ( cycletop = dfn_depth ; cycletop > 0 ; cycletop -= 1 ) { cycleheadp = dfn_stack[ cycletop ].nlentryp; if ( childp == cycleheadp ) { break; } if ( childp -> cyclehead != childp && childp -> cyclehead == cycleheadp ) { break; } } if ( cycletop <= 0 ) { fprintf( stderr , "[dfn_findcycle] couldn't find head of cycle\n" ); exit( 1 ); } # ifdef DEBUG if ( debug & DFNDEBUG ) { printf( "[dfn_findcycle] dfn_depth %d cycletop %d " , dfn_depth , cycletop ); printname( cycleheadp ); printf( "\n" ); } # endif DEBUG if ( cycletop == dfn_depth ) { /* * this is previous function, e.g. this calls itself * sort of boring */ dfn_self_cycle( childp ); } else { /* * glom intervening functions that aren't already * glommed into this cycle. * things have been glommed when their cyclehead field * points to the head of the cycle they are glommed into. */ for ( tailp = cycleheadp ; tailp -> cnext ; tailp = tailp -> cnext ) { /* void: chase down to tail of things already glommed */ # ifdef DEBUG if ( debug & DFNDEBUG ) { printf( "[dfn_findcycle] tail " ); printname( tailp ); printf( "\n" ); } # endif DEBUG } /* * if what we think is the top of the cycle * has a cyclehead field, then it's not really the * head of the cycle, which is really what we want */ if ( cycleheadp -> cyclehead != cycleheadp ) { cycleheadp = cycleheadp -> cyclehead; # ifdef DEBUG if ( debug & DFNDEBUG ) { printf( "[dfn_findcycle] new cyclehead " ); printname( cycleheadp ); printf( "\n" ); } # endif DEBUG } for ( index = cycletop + 1 ; index <= dfn_depth ; index += 1 ) { childp = dfn_stack[ index ].nlentryp; if ( childp -> cyclehead == childp ) { /* * not yet glommed anywhere, glom it * and fix any children it has glommed */ tailp -> cnext = childp; childp -> cyclehead = cycleheadp; # ifdef DEBUG if ( debug & DFNDEBUG ) { printf( "[dfn_findcycle] glomming " ); printname( childp ); printf( " onto " ); printname( cycleheadp ); printf( "\n" ); } # endif DEBUG for ( tailp = childp ; tailp->cnext ; tailp = tailp->cnext ) { tailp -> cnext -> cyclehead = cycleheadp; # ifdef DEBUG if ( debug & DFNDEBUG ) { printf( "[dfn_findcycle] and its tail " ); printname( tailp -> cnext ); printf( " onto " ); printname( cycleheadp ); printf( "\n" ); } # endif DEBUG } } else if ( childp -> cyclehead != cycleheadp /* firewall */ ) { fprintf( stderr , "[dfn_busy] glommed, but not to cyclehead\n" ); } } } } /* * deal with self-cycles * for lint: ARGSUSED */ dfn_self_cycle( parentp ) nltype *parentp; { /* * since we are taking out self-cycles elsewhere * no need for the special case, here. */ # ifdef DEBUG if ( debug & DFNDEBUG ) { printf( "[dfn_self_cycle] " ); printname( parentp ); printf( "\n" ); } # endif DEBUG } /* * visit a node after all its children * [MISSING: an explanation] * and pop it off the stack */ dfn_post_visit( parentp ) nltype *parentp; { nltype *memberp; # ifdef DEBUG if ( debug & DFNDEBUG ) { printf( "[dfn_post_visit]\t%d: " , dfn_depth ); printname( parentp ); printf( "\n" ); } # endif DEBUG /* * number functions and things in their cycles * unless the function is itself part of a cycle */ if ( parentp -> cyclehead == parentp ) { dfn_counter += 1; for ( memberp = parentp ; memberp ; memberp = memberp -> cnext ) { memberp -> toporder = dfn_counter; # ifdef DEBUG if ( debug & DFNDEBUG ) { printf( "[dfn_post_visit]\t\tmember " ); printname( memberp ); printf( " -> toporder = %d\n" , dfn_counter ); } # endif DEBUG } } else { # ifdef DEBUG if ( debug & DFNDEBUG ) { printf( "[dfn_post_visit]\t\tis part of a cycle\n" ); } # endif DEBUG } dfn_depth -= 1; } cycletop > 0 ; cycletop -= 1 ) { cycleheadp = dfn_stack[ cycletop ].nlentryp; if ( childp gprof/arcs.c 444 22 12 35645 4044770454 6330 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)arcs.c 5.3 (Berkeley) 1/7/86"; #endif not lint #include "gprof.h" /* * add (or just increment) an arc */ addarc( parentp , childp , count ) nltype *parentp; nltype *childp; long count; { arctype *calloc(); arctype *arcp; # ifdef DEBUG if ( debug & TALLYDEBUG ) { printf( "[addarc] %d arcs from %s to %s\n" , count , parentp -> name , childp -> name ); } # endif DEBUG arcp = arclookup( parentp , childp ); if ( arcp != 0 ) { /* * a hit: just increment the count. */ # ifdef DEBUG if ( debug & TALLYDEBUG ) { printf( "[tally] hit %d += %d\n" , arcp -> arc_count , count ); } # endif DEBUG arcp -> arc_count += count; return; } arcp = calloc( 1 , sizeof *arcp ); arcp -> arc_parentp = parentp; arcp -> arc_childp = childp; arcp -> arc_count = count; /* * prepend this child to the children of this parent */ arcp -> arc_childlist = parentp -> children; parentp -> children = arcp; /* * prepend this parent to the parents of this child */ arcp -> arc_parentlist = childp -> parents; childp -> parents = arcp; } /* * the code below topologically sorts the graph (collapsing cycles), * and propagates time bottom up and flags top down. */ /* * the topologically sorted name list pointers */ nltype **topsortnlp; topcmp( npp1 , npp2 ) nltype **npp1; nltype **npp2; { return (*npp1) -> toporder - (*npp2) -> toporder; } nltype ** doarcs() { nltype *parentp, **timesortnlp; arctype *arcp; long index; /* * initialize various things: * zero out child times. * count self-recursive calls. * indicate that nothing is on cycles. */ for ( parentp = nl ; parentp < npe ; parentp++ ) { parentp -> childtime = 0.0; arcp = arclookup( parentp , parentp ); if ( arcp != 0 ) { parentp -> ncall -= arcp -> arc_count; parentp -> selfcalls = arcp -> arc_count; } else { parentp -> selfcalls = 0; } parentp -> propfraction = 0.0; parentp -> propself = 0.0; parentp -> propchild = 0.0; parentp -> printflag = FALSE; parentp -> toporder = DFN_NAN; parentp -> cycleno = 0; parentp -> cyclehead = parentp; parentp -> cnext = 0; if ( cflag ) { findcall( parentp , parentp -> value , (parentp+1) -> value ); } } /* * topologically order things * if any node is unnumbered, * number it and any of its descendents. */ for ( parentp = nl ; parentp < npe ; parentp++ ) { if ( parentp -> toporder == DFN_NAN ) { dfn( parentp ); } } /* * link together nodes on the same cycle */ cyclelink(); /* * Sort the symbol table in reverse topological order */ topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) ); if ( topsortnlp == (nltype **) 0 ) { fprintf( stderr , "[doarcs] ran out of memory for topo sorting\n" ); } for ( index = 0 ; index < nname ; index += 1 ) { topsortnlp[ index ] = &nl[ index ]; } qsort( topsortnlp , nname , sizeof(nltype *) , topcmp ); # ifdef DEBUG if ( debug & DFNDEBUG ) { printf( "[doarcs] topological sort listing\n" ); for ( index = 0 ; index < nname ; index += 1 ) { printf( "[doarcs] " ); printf( "%d:" , topsortnlp[ index ] -> toporder ); printname( topsortnlp[ index ] ); printf( "\n" ); } } # endif DEBUG /* * starting from the topological top, * propagate print flags to children. * also, calculate propagation fractions. * this happens before time propagation * since time propagation uses the fractions. */ doflags(); /* * starting from the topological bottom, * propogate children times up to parents. */ dotime(); /* * Now, sort by propself + propchild. * sorting both the regular function names * and cycle headers. */ timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); if ( timesortnlp == (nltype **) 0 ) { fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami ); } for ( index = 0 ; index < nname ; index++ ) { timesortnlp[index] = &nl[index]; } for ( index = 1 ; index <= ncycle ; index++ ) { timesortnlp[nname+index-1] = &cyclenl[index]; } qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp ); for ( index = 0 ; index < nname + ncycle ; index++ ) { timesortnlp[ index ] -> index = index + 1; } return( timesortnlp ); } dotime() { int index; cycletime(); for ( index = 0 ; index < nname ; index += 1 ) { timepropagate( topsortnlp[ index ] ); } } timepropagate( parentp ) nltype *parentp; { arctype *arcp; nltype *childp; double share; double propshare; if ( parentp -> propfraction == 0.0 ) { return; } /* * gather time from children of this parent. */ for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { childp = arcp -> arc_childp; if ( arcp -> arc_count == 0 ) { continue; } if ( childp == parentp ) { continue; } if ( childp -> propfraction == 0.0 ) { continue; } if ( childp -> cyclehead != childp ) { if ( parentp -> cycleno == childp -> cycleno ) { continue; } if ( parentp -> toporder <= childp -> toporder ) { fprintf( stderr , "[propagate] toporder botches\n" ); } childp = childp -> cyclehead; } else { if ( parentp -> toporder <= childp -> toporder ) { fprintf( stderr , "[propagate] toporder botches\n" ); continue; } } if ( childp -> ncall == 0 ) { continue; } /* * distribute time for this arc */ arcp -> arc_time = childp -> time * ( ( (double) arcp -> arc_count ) / ( (double) childp -> ncall ) ); arcp -> arc_childtime = childp -> childtime * ( ( (double) arcp -> arc_count ) / ( (double) childp -> ncall ) ); share = arcp -> arc_time + arcp -> arc_childtime; parentp -> childtime += share; /* * ( 1 - propfraction ) gets lost along the way */ propshare = parentp -> propfraction * share; /* * fix things for printing */ parentp -> propchild += propshare; arcp -> arc_time *= parentp -> propfraction; arcp -> arc_childtime *= parentp -> propfraction; /* * add this share to the parent's cycle header, if any. */ if ( parentp -> cyclehead != parentp ) { parentp -> cyclehead -> childtime += share; parentp -> cyclehead -> propchild += propshare; } # ifdef DEBUG if ( debug & PROPDEBUG ) { printf( "[dotime] child \t" ); printname( childp ); printf( " with %f %f %d/%d\n" , childp -> time , childp -> childtime , arcp -> arc_count , childp -> ncall ); printf( "[dotime] parent\t" ); printname( parentp ); printf( "\n[dotime] share %f\n" , share ); } # endif DEBUG } } cyclelink() { register nltype *nlp; register nltype *cyclenlp; int cycle; nltype *memberp; arctype *arcp; /* * Count the number of cycles, and initialze the cycle lists */ ncycle = 0; for ( nlp = nl ; nlp < npe ; nlp++ ) { /* * this is how you find unattached cycles */ if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) { ncycle += 1; } } /* * cyclenl is indexed by cycle number: * i.e. it is origin 1, not origin 0. */ cyclenl = (nltype *) calloc( ncycle + 1 , sizeof( nltype ) ); if ( cyclenl == 0 ) { fprintf( stderr , "%s: No room for %d bytes of cycle headers\n" , whoami , ( ncycle + 1 ) * sizeof( nltype ) ); done(); } /* * now link cycles to true cycleheads, * number them, accumulate the data for the cycle */ cycle = 0; for ( nlp = nl ; nlp < npe ; nlp++ ) { if ( !( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) ) { continue; } cycle += 1; cyclenlp = &cyclenl[cycle]; cyclenlp -> name = 0; /* the name */ cyclenlp -> value = 0; /* the pc entry point */ cyclenlp -> time = 0.0; /* ticks in this routine */ cyclenlp -> childtime = 0.0; /* cumulative ticks in children */ cyclenlp -> ncall = 0; /* how many times called */ cyclenlp -> selfcalls = 0; /* how many calls to self */ cyclenlp -> propfraction = 0.0; /* what % of time propagates */ cyclenlp -> propself = 0.0; /* how much self time propagates */ cyclenlp -> propchild = 0.0; /* how much child time propagates */ cyclenlp -> printflag = TRUE; /* should this be printed? */ cyclenlp -> index = 0; /* index in the graph list */ cyclenlp -> toporder = DFN_NAN; /* graph call chain top-sort order */ cyclenlp -> cycleno = cycle; /* internal number of cycle on */ cyclenlp -> cyclehead = cyclenlp; /* pointer to head of cycle */ cyclenlp -> cnext = nlp; /* pointer to next member of cycle */ cyclenlp -> parents = 0; /* list of caller arcs */ cyclenlp -> children = 0; /* list of callee arcs */ # ifdef DEBUG if ( debug & CYCLEDEBUG ) { printf( "[cyclelink] " ); printname( nlp ); printf( " is the head of cycle %d\n" , cycle ); } # endif DEBUG /* * link members to cycle header */ for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { memberp -> cycleno = cycle; memberp -> cyclehead = cyclenlp; } /* * count calls from outside the cycle * and those among cycle members */ for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { for ( arcp=memberp->parents ; arcp ; arcp=arcp->arc_parentlist ) { if ( arcp -> arc_parentp == memberp ) { continue; } if ( arcp -> arc_parentp -> cycleno == cycle ) { cyclenlp -> selfcalls += arcp -> arc_count; } else { cyclenlp -> ncall += arcp -> arc_count; } } } } } cycletime() { int cycle; nltype *cyclenlp; nltype *childp; for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) { cyclenlp = &cyclenl[ cycle ]; for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) { if ( childp -> propfraction == 0.0 ) { /* * all members have the same propfraction except those * that were excluded with -E */ continue; } cyclenlp -> time += childp -> time; } cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time; } } /* * in one top to bottom pass over the topologically sorted namelist * propagate: * printflag as the union of parents' printflags * propfraction as the sum of fractional parents' propfractions * and while we're here, sum time for functions. */ doflags() { int index; nltype *childp; nltype *oldhead; oldhead = 0; for ( index = nname-1 ; index >= 0 ; index -= 1 ) { childp = topsortnlp[ index ]; /* * if we haven't done this function or cycle, * inherit things from parent. * this way, we are linear in the number of arcs * since we do all members of a cycle (and the cycle itself) * as we hit the first member of the cycle. */ if ( childp -> cyclehead != oldhead ) { oldhead = childp -> cyclehead; inheritflags( childp ); } # ifdef DEBUG if ( debug & PROPDEBUG ) { printf( "[doflags] " ); printname( childp ); printf( " inherits printflag %d and propfraction %f\n" , childp -> printflag , childp -> propfraction ); } # endif DEBUG if ( ! childp -> printflag ) { /* * printflag is off * it gets turned on by * being on -f list, * or there not being any -f list and not being on -e list. */ if ( onlist( flist , childp -> name ) || ( !fflag && !onlist( elist , childp -> name ) ) ) { childp -> printflag = TRUE; } } else { /* * this function has printing parents: * maybe someone wants to shut it up * by putting it on -e list. (but favor -f over -e) */ if ( ( !onlist( flist , childp -> name ) ) && onlist( elist , childp -> name ) ) { childp -> printflag = FALSE; } } if ( childp -> propfraction == 0.0 ) { /* * no parents to pass time to. * collect time from children if * its on -F list, * or there isn't any -F list and its not on -E list. */ if ( onlist( Flist , childp -> name ) || ( !Fflag && !onlist( Elist , childp -> name ) ) ) { childp -> propfraction = 1.0; } } else { /* * it has parents to pass time to, * but maybe someone wants to shut it up * by puttting it on -E list. (but favor -F over -E) */ if ( !onlist( Flist , childp -> name ) && onlist( Elist , childp -> name ) ) { childp -> propfraction = 0.0; } } childp -> propself = childp -> time * childp -> propfraction; printtime += childp -> propself; # ifdef DEBUG if ( debug & PROPDEBUG ) { printf( "[doflags] " ); printname( childp ); printf( " ends up with printflag %d and propfraction %f\n" , childp -> printflag , childp -> propfraction ); printf( "time %f propself %f printtime %f\n" , childp -> time , childp -> propself , printtime ); } # endif DEBUG } } /* * check if any parent of this child * (or outside parents of this cycle) * have their print flags on and set the * print flag of the child (cycle) appropriately. * similarly, deal with propagation fractions from parents. */ inheritflags( childp ) nltype *childp; { nltype *headp; arctype *arcp; nltype *parentp; nltype *memp; headp = childp -> cyclehead; if ( childp == headp ) { /* * just a regular child, check its parents */ childp -> printflag = FALSE; childp -> propfraction = 0.0; for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) { parentp = arcp -> arc_parentp; if ( childp == parentp ) { continue; } childp -> printflag |= parentp -> printflag; /* * if the child was never actually called * (e.g. this arc is static (and all others are, too)) * no time propagates along this arc. */ if ( childp -> ncall ) { childp -> propfraction += parentp -> propfraction * ( ( (double) arcp -> arc_count ) / ( (double) childp -> ncall ) ); } } } else { /* * its a member of a cycle, look at all parents from * outside the cycle */ headp -> printflag = FALSE; headp -> propfraction = 0.0; for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) { for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) { if ( arcp -> arc_parentp -> cyclehead == headp ) { continue; } parentp = arcp -> arc_parentp; headp -> printflag |= parentp -> printflag; /* * if the cycle was never actually called * (e.g. this arc is static (and all others are, too)) * no time propagates along this arc. */ if ( headp -> ncall ) { headp -> propfraction += parentp -> propfraction * ( ( (double) arcp -> arc_count ) / ( (double) headp -> ncall ) ); } } } for ( memp = headp ; memp ; memp = memp -> cnext ) { memp -> printflag = headp -> printflag; memp -> propfraction = headp -> propfraction; } } } if ( childp -> cyclehead != oldhead ) { oldhead = childp -> cyclehead; inheritfgprof/printgprof.c 444 22 12 42731 4167372703 7565 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)printgprof.c 5.3 (Berkeley) 1/2/88"; #endif not lint #include "gprof.h" printprof() { register nltype *np; nltype **sortednlp; int index, timecmp(); actime = 0.0; printf( "\f\n" ); flatprofheader(); /* * Sort the symbol table in by time */ sortednlp = (nltype **) calloc( nname , sizeof(nltype *) ); if ( sortednlp == (nltype **) 0 ) { fprintf( stderr , "[printprof] ran out of memory for time sorting\n" ); } for ( index = 0 ; index < nname ; index += 1 ) { sortednlp[ index ] = &nl[ index ]; } qsort( sortednlp , nname , sizeof(nltype *) , timecmp ); for ( index = 0 ; index < nname ; index += 1 ) { np = sortednlp[ index ]; flatprofline( np ); } actime = 0.0; cfree( sortednlp ); } timecmp( npp1 , npp2 ) nltype **npp1, **npp2; { double timediff; long calldiff; timediff = (*npp2) -> time - (*npp1) -> time; if ( timediff > 0.0 ) return 1 ; if ( timediff < 0.0 ) return -1; calldiff = (*npp2) -> ncall - (*npp1) -> ncall; if ( calldiff > 0 ) return 1; if ( calldiff < 0 ) return -1; return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); } /* * header for flatprofline */ flatprofheader() { if ( bflag ) { printblurb( FLAT_BLURB ); } printf( "\ngranularity: each sample hit covers %d byte(s)" , (long) scale * sizeof(UNIT) ); if ( totime > 0.0 ) { printf( " for %.2f%% of %.2f seconds\n\n" , 100.0/totime , totime / hz ); } else { printf( " no time accumulated\n\n" ); /* * this doesn't hurt sinc eall the numerators will be zero. */ totime = 1.0; } printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" , "% " , "cumulative" , "self " , "" , "self " , "total " , "" ); printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" , "time" , "seconds " , "seconds" , "calls" , "ms/call" , "ms/call" , "name" ); } flatprofline( np ) register nltype *np; { if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 ) { return; } actime += np -> time; printf( "%5.1f %10.2f %8.2f" , 100 * np -> time / totime , actime / hz , np -> time / hz ); if ( np -> ncall != 0 ) { printf( " %8d %8.2f %8.2f " , np -> ncall , 1000 * np -> time / hz / np -> ncall , 1000 * ( np -> time + np -> childtime ) / hz / np -> ncall ); } else { printf( " %8.8s %8.8s %8.8s " , "" , "" , "" ); } printname( np ); printf( "\n" ); } gprofheader() { if ( bflag ) { printblurb( CALLG_BLURB ); } printf( "\ngranularity: each sample hit covers %d byte(s)" , (long) scale * sizeof(UNIT) ); if ( printtime > 0.0 ) { printf( " for %.2f%% of %.2f seconds\n\n" , 100.0/printtime , printtime / hz ); } else { printf( " no time propagated\n\n" ); /* * this doesn't hurt, since all the numerators will be 0.0 */ printtime = 1.0; } printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , "" , "" , "" , "" , "called" , "total" , "parents"); printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" , "index" , "%time" , "self" , "descendents" , "called" , "self" , "name" , "index" ); printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , "" , "" , "" , "" , "called" , "total" , "children"); printf( "\n" ); } gprofline( np ) register nltype *np; { char kirkbuffer[ BUFSIZ ]; sprintf( kirkbuffer , "[%d]" , np -> index ); printf( "%-6.6s %5.1f %7.2f %11.2f" , kirkbuffer , 100 * ( np -> propself + np -> propchild ) / printtime , np -> propself / hz , np -> propchild / hz ); if ( ( np -> ncall + np -> selfcalls ) != 0 ) { printf( " %7d" , np -> ncall ); if ( np -> selfcalls != 0 ) { printf( "+%-7d " , np -> selfcalls ); } else { printf( " %7.7s " , "" ); } } else { printf( " %7.7s %7.7s " , "" , "" ); } printname( np ); printf( "\n" ); } printgprof(timesortnlp) nltype **timesortnlp; { int index; nltype *parentp; /* * Print out the structured profiling list */ gprofheader(); for ( index = 0 ; index < nname + ncycle ; index ++ ) { parentp = timesortnlp[ index ]; if ( zflag == 0 && parentp -> ncall == 0 && parentp -> selfcalls == 0 && parentp -> propself == 0 && parentp -> propchild == 0 ) { continue; } if ( ! parentp -> printflag ) { continue; } if ( parentp -> name == 0 && parentp -> cycleno != 0 ) { /* * cycle header */ printcycle( parentp ); printmembers( parentp ); } else { printparents( parentp ); gprofline( parentp ); printchildren( parentp ); } printf( "\n" ); printf( "-----------------------------------------------\n" ); printf( "\n" ); } cfree( timesortnlp ); } /* * sort by decreasing propagated time * if times are equal, but one is a cycle header, * say that's first (e.g. less, i.e. -1). * if one's name doesn't have an underscore and the other does, * say the one is first. * all else being equal, sort by names. */ int totalcmp( npp1 , npp2 ) nltype **npp1; nltype **npp2; { register nltype *np1 = *npp1; register nltype *np2 = *npp2; double diff; diff = ( np1 -> propself + np1 -> propchild ) - ( np2 -> propself + np2 -> propchild ); if ( diff < 0.0 ) return 1; if ( diff > 0.0 ) return -1; if ( np1 -> name == 0 && np1 -> cycleno != 0 ) return -1; if ( np2 -> name == 0 && np2 -> cycleno != 0 ) return 1; if ( np1 -> name == 0 ) return -1; if ( np2 -> name == 0 ) return 1; if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' ) return -1; if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' ) return 1; if ( np1 -> ncall > np2 -> ncall ) return -1; if ( np1 -> ncall < np2 -> ncall ) return 1; return strcmp( np1 -> name , np2 -> name ); } printparents( childp ) nltype *childp; { nltype *parentp; arctype *arcp; nltype *cycleheadp; if ( childp -> cyclehead != 0 ) { cycleheadp = childp -> cyclehead; } else { cycleheadp = childp; } if ( childp -> parents == 0 ) { printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n" , "" , "" , "" , "" , "" , "" ); return; } sortparents( childp ); for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) { parentp = arcp -> arc_parentp; if ( childp == parentp || ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) { /* * selfcall or call among siblings */ printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " , "" , "" , "" , "" , arcp -> arc_count , "" ); printname( parentp ); printf( "\n" ); } else { /* * regular parent of child */ printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " , "" , "" , arcp -> arc_time / hz , arcp -> arc_childtime / hz , arcp -> arc_count , cycleheadp -> ncall ); printname( parentp ); printf( "\n" ); } } } printchildren( parentp ) nltype *parentp; { nltype *childp; arctype *arcp; sortchildren( parentp ); arcp = parentp -> children; for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { childp = arcp -> arc_childp; if ( childp == parentp || ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) { /* * self call or call to sibling */ printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " , "" , "" , "" , "" , arcp -> arc_count , "" ); printname( childp ); printf( "\n" ); } else { /* * regular child of parent */ printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " , "" , "" , arcp -> arc_time / hz , arcp -> arc_childtime / hz , arcp -> arc_count , childp -> cyclehead -> ncall ); printname( childp ); printf( "\n" ); } } } printname( selfp ) nltype *selfp; { if ( selfp -> name != 0 ) { printf( "%s" , selfp -> name ); # ifdef DEBUG if ( debug & DFNDEBUG ) { printf( "{%d} " , selfp -> toporder ); } if ( debug & PROPDEBUG ) { printf( "%5.2f%% " , selfp -> propfraction ); } # endif DEBUG } if ( selfp -> cycleno != 0 ) { printf( " <cycle %d>" , selfp -> cycleno ); } if ( selfp -> index != 0 ) { if ( selfp -> printflag ) { printf( " [%d]" , selfp -> index ); } else { printf( " (%d)" , selfp -> index ); } } } sortchildren( parentp ) nltype *parentp; { arctype *arcp; arctype *detachedp; arctype sorted; arctype *prevp; /* * unlink children from parent, * then insertion sort back on to sorted's children. * *arcp the arc you have detached and are inserting. * *detachedp the rest of the arcs to be sorted. * sorted arc list onto which you insertion sort. * *prevp arc before the arc you are comparing. */ sorted.arc_childlist = 0; for ( (arcp = parentp -> children)&&(detachedp = arcp -> arc_childlist); arcp ; (arcp = detachedp)&&(detachedp = detachedp -> arc_childlist)) { /* * consider *arcp as disconnected * insert it into sorted */ for ( prevp = &sorted ; prevp -> arc_childlist ; prevp = prevp -> arc_childlist ) { if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) { break; } } arcp -> arc_childlist = prevp -> arc_childlist; prevp -> arc_childlist = arcp; } /* * reattach sorted children to parent */ parentp -> children = sorted.arc_childlist; } sortparents( childp ) nltype *childp; { arctype *arcp; arctype *detachedp; arctype sorted; arctype *prevp; /* * unlink parents from child, * then insertion sort back on to sorted's parents. * *arcp the arc you have detached and are inserting. * *detachedp the rest of the arcs to be sorted. * sorted arc list onto which you insertion sort. * *prevp arc before the arc you are comparing. */ sorted.arc_parentlist = 0; for ( (arcp = childp -> parents)&&(detachedp = arcp -> arc_parentlist); arcp ; (arcp = detachedp)&&(detachedp = detachedp -> arc_parentlist)) { /* * consider *arcp as disconnected * insert it into sorted */ for ( prevp = &sorted ; prevp -> arc_parentlist ; prevp = prevp -> arc_parentlist ) { if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) { break; } } arcp -> arc_parentlist = prevp -> arc_parentlist; prevp -> arc_parentlist = arcp; } /* * reattach sorted arcs to child */ childp -> parents = sorted.arc_parentlist; } /* * print a cycle header */ printcycle( cyclep ) nltype *cyclep; { char kirkbuffer[ BUFSIZ ]; sprintf( kirkbuffer , "[%d]" , cyclep -> index ); printf( "%-6.6s %5.1f %7.2f %11.2f %7d" , kirkbuffer , 100 * ( cyclep -> propself + cyclep -> propchild ) / printtime , cyclep -> propself / hz , cyclep -> propchild / hz , cyclep -> ncall ); if ( cyclep -> selfcalls != 0 ) { printf( "+%-7d" , cyclep -> selfcalls ); } else { printf( " %7.7s" , "" ); } printf( " <cycle %d as a whole>\t[%d]\n" , cyclep -> cycleno , cyclep -> index ); } /* * print the members of a cycle */ printmembers( cyclep ) nltype *cyclep; { nltype *memberp; sortmembers( cyclep ); for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) { printf( "%6.6s %5.5s %7.2f %11.2f %7d" , "" , "" , memberp -> propself / hz , memberp -> propchild / hz , memberp -> ncall ); if ( memberp -> selfcalls != 0 ) { printf( "+%-7d" , memberp -> selfcalls ); } else { printf( " %7.7s" , "" ); } printf( " " ); printname( memberp ); printf( "\n" ); } } /* * sort members of a cycle */ sortmembers( cyclep ) nltype *cyclep; { nltype *todo; nltype *doing; nltype *prev; /* * detach cycle members from cyclehead, * and insertion sort them back on. */ todo = cyclep -> cnext; cyclep -> cnext = 0; for ( (doing = todo)&&(todo = doing -> cnext); doing ; (doing = todo )&&(todo = doing -> cnext )){ for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) { if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) { break; } } doing -> cnext = prev -> cnext; prev -> cnext = doing; } } /* * major sort is on propself + propchild, * next is sort on ncalls + selfcalls. */ int membercmp( this , that ) nltype *this; nltype *that; { double thistime = this -> propself + this -> propchild; double thattime = that -> propself + that -> propchild; long thiscalls = this -> ncall + this -> selfcalls; long thatcalls = that -> ncall + that -> selfcalls; if ( thistime > thattime ) { return GREATERTHAN; } if ( thistime < thattime ) { return LESSTHAN; } if ( thiscalls > thatcalls ) { return GREATERTHAN; } if ( thiscalls < thatcalls ) { return LESSTHAN; } return EQUALTO; } /* * compare two arcs to/from the same child/parent. * - if one arc is a self arc, it's least. * - if one arc is within a cycle, it's less than. * - if both arcs are within a cycle, compare arc counts. * - if neither arc is within a cycle, compare with * arc_time + arc_childtime as major key * arc count as minor key */ int arccmp( thisp , thatp ) arctype *thisp; arctype *thatp; { nltype *thisparentp = thisp -> arc_parentp; nltype *thischildp = thisp -> arc_childp; nltype *thatparentp = thatp -> arc_parentp; nltype *thatchildp = thatp -> arc_childp; double thistime; double thattime; # ifdef DEBUG if ( debug & TIMEDEBUG ) { printf( "[arccmp] " ); printname( thisparentp ); printf( " calls " ); printname ( thischildp ); printf( " %f + %f %d/%d\n" , thisp -> arc_time , thisp -> arc_childtime , thisp -> arc_count , thischildp -> ncall ); printf( "[arccmp] " ); printname( thatparentp ); printf( " calls " ); printname( thatchildp ); printf( " %f + %f %d/%d\n" , thatp -> arc_time , thatp -> arc_childtime , thatp -> arc_count , thatchildp -> ncall ); printf( "\n" ); } # endif DEBUG if ( thisparentp == thischildp ) { /* this is a self call */ return LESSTHAN; } if ( thatparentp == thatchildp ) { /* that is a self call */ return GREATERTHAN; } if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 && thisparentp -> cycleno == thischildp -> cycleno ) { /* this is a call within a cycle */ if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && thatparentp -> cycleno == thatchildp -> cycleno ) { /* that is a call within the cycle, too */ if ( thisp -> arc_count < thatp -> arc_count ) { return LESSTHAN; } if ( thisp -> arc_count > thatp -> arc_count ) { return GREATERTHAN; } return EQUALTO; } else { /* that isn't a call within the cycle */ return LESSTHAN; } } else { /* this isn't a call within a cycle */ if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && thatparentp -> cycleno == thatchildp -> cycleno ) { /* that is a call within a cycle */ return GREATERTHAN; } else { /* neither is a call within a cycle */ thistime = thisp -> arc_time + thisp -> arc_childtime; thattime = thatp -> arc_time + thatp -> arc_childtime; if ( thistime < thattime ) return LESSTHAN; if ( thistime > thattime ) return GREATERTHAN; if ( thisp -> arc_count < thatp -> arc_count ) return LESSTHAN; if ( thisp -> arc_count > thatp -> arc_count ) return GREATERTHAN; return EQUALTO; } } } printblurb( blurbname ) char *blurbname; { FILE *blurbfile; int input; blurbfile = fopen( blurbname , "r" ); if ( blurbfile == NULL ) { perror( blurbname ); return; } while ( ( input = getc( blurbfile ) ) != EOF ) { putchar( input ); } fclose( blurbfile ); } int namecmp( npp1 , npp2 ) nltype **npp1, **npp2; { return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); } printindex() { nltype **namesortnlp; register nltype *nlp; int index, nnames, todo, i, j; char peterbuffer[ BUFSIZ ]; /* * Now, sort regular function name alphbetically * to create an index. */ namesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); if ( namesortnlp == (nltype **) 0 ) { fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami ); } for ( index = 0 , nnames = 0 ; index < nname ; index++ ) { if ( zflag == 0 && nl[index].ncall == 0 && nl[index].time == 0 ) continue; namesortnlp[nnames++] = &nl[index]; } qsort( namesortnlp , nnames , sizeof(nltype *) , namecmp ); for ( index = 1 , todo = nnames ; index <= ncycle ; index++ ) { namesortnlp[todo++] = &cyclenl[index]; } printf( "\f\nIndex by function name\n\n" ); index = ( todo + 2 ) / 3; for ( i = 0; i < index ; i++ ) { for ( j = i; j < todo ; j += index ) { nlp = namesortnlp[ j ]; if ( nlp -> printflag ) { sprintf( peterbuffer , "[%d]" , nlp -> index ); } else { sprintf( peterbuffer , "(%d)" , nlp -> index ); } if ( j < nnames ) { printf( "%6.6s %-19.19s" , peterbuffer , nlp -> name ); } else { printf( "%6.6s " , peterbuffer ); sprintf( peterbuffer , "<cycle %d>" , nlp -> cycleno ); printf( "%-19.19s" , peterbuffer ); } } printf( "\n" ); } cfree( namesortnlp ); } thisp -> arc_parentp; nltype *thisgprof/hertz.c 444 22 12 1405 3500670604 6467 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)hertz.c 5.1 (Berkeley) 6/4/85"; #endif not lint #include <sys/time.h> /* * discover the tick frequency of the machine * if something goes wrong, we return 0, an impossible hertz. */ #define HZ_WRONG 0 hertz() { struct itimerval tim; tim.it_interval.tv_sec = 0; tim.it_interval.tv_usec = 1; tim.it_value.tv_sec = 0; tim.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &tim, 0); setitimer(ITIMER_REAL, 0, &tim); if (tim.it_interval.tv_usec < 2) return(HZ_WRONG); return (1000000 / tim.it_interval.tv_usec); } gprof/lookup.c 444 22 12 3642 3500670643 6654 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)lookup.c 5.1 (Berkeley) 6/4/85"; #endif not lint #include "gprof.h" /* * look up an address in a sorted-by-address namelist * this deals with misses by mapping them to the next lower * entry point. */ nltype * nllookup( address ) unsigned long address; { register long low; register long middle; register long high; # ifdef DEBUG register int probes; probes = 0; # endif DEBUG for ( low = 0 , high = nname - 1 ; low != high ; ) { # ifdef DEBUG probes += 1; # endif DEBUG middle = ( high + low ) >> 1; if ( nl[ middle ].value <= address && nl[ middle+1 ].value > address ) { # ifdef DEBUG if ( debug & LOOKUPDEBUG ) { printf( "[nllookup] %d (%d) probes\n" , probes , nname-1 ); } # endif DEBUG return &nl[ middle ]; } if ( nl[ middle ].value > address ) { high = middle; } else { low = middle + 1; } } fprintf( stderr , "[nllookup] binary search fails???\n" ); return 0; } arctype * arclookup( parentp , childp ) nltype *parentp; nltype *childp; { arctype *arcp; if ( parentp == 0 || childp == 0 ) { fprintf( "[arclookup] parentp == 0 || childp == 0\n" ); return 0; } # ifdef DEBUG if ( debug & LOOKUPDEBUG ) { printf( "[arclookup] parent %s child %s\n" , parentp -> name , childp -> name ); } # endif DEBUG for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { # ifdef DEBUG if ( debug & LOOKUPDEBUG ) { printf( "[arclookup]\t arc_parent %s arc_child %s\n" , arcp -> arc_parentp -> name , arcp -> arc_childp -> name ); } # endif DEBUG if ( arcp -> arc_childp == childp ) { return arcp; } } return 0; } } printf( "\n" ); } cfree( namesortnlp ); } thisp -> arc_parentp; nltype *thisgprof/tahoe.c 444 22 12 16405 3610154261 6457 #ifndef lint static char *sccsid = "@(#)tahoe.c 1.2 (Berkeley) 1/7/86"; #endif not lint #include "gprof.h" /* * a namelist entry to be the child of indirect callf */ nltype indirectchild = { "(*)" , /* the name */ (unsigned long) 0 , /* the pc entry point */ (unsigned long) 0 , /* entry point aligned to histogram */ (double) 0.0 , /* ticks in this routine */ (double) 0.0 , /* cumulative ticks in children */ (long) 0 , /* how many times called */ (long) 0 , /* how many calls to self */ (double) 1.0 , /* propagation fraction */ (double) 0.0 , /* self propagation time */ (double) 0.0 , /* child propagation time */ (bool) 0 , /* print flag */ (int) 0 , /* index in the graph list */ (int) 0 , /* graph call chain top-sort order */ (int) 0 , /* internal number of cycle on */ (struct nl *) &indirectchild , /* pointer to head of cycle */ (struct nl *) 0 , /* pointer to next member of cycle */ (arctype *) 0 , /* list of caller arcs */ (arctype *) 0 /* list of callee arcs */ }; operandenum operandmode( modep ) unsigned char *modep; { long usesreg = ((long)*modep) & 0xf; switch ( ((long)*modep) >> 4 ) { case 0: case 1: case 2: case 3: return literal; case 4: return indexed; case 5: return reg; case 6: return regdef; case 7: return autodec; case 8: return ( usesreg != 0xe ? autoinc : immediate ); case 9: return ( usesreg != PC ? autoincdef : absolute ); case 10: return ( usesreg != PC ? bytedisp : byterel ); case 11: return ( usesreg != PC ? bytedispdef : bytereldef ); case 12: return ( usesreg != PC ? worddisp : wordrel ); case 13: return ( usesreg != PC ? worddispdef : wordreldef ); case 14: return ( usesreg != PC ? longdisp : longrel ); case 15: return ( usesreg != PC ? longdispdef : longreldef ); } /* NOTREACHED */ } char * operandname( mode ) operandenum mode; { switch ( mode ) { case literal: return "literal"; case indexed: return "indexed"; case reg: return "register"; case regdef: return "register deferred"; case autodec: return "autodecrement"; case autoinc: return "autoincrement"; case autoincdef: return "autoincrement deferred"; case bytedisp: return "byte displacement"; case bytedispdef: return "byte displacement deferred"; case byterel: return "byte relative"; case bytereldef: return "byte relative deferred"; case worddisp: return "word displacement"; case worddispdef: return "word displacement deferred"; case wordrel: return "word relative"; case wordreldef: return "word relative deferred"; case immediate: return "immediate"; case absolute: return "absolute"; case longdisp: return "long displacement"; case longdispdef: return "long displacement deferred"; case longrel: return "long relative"; case longreldef: return "long relative deferred"; } /* NOTREACHED */ } long operandlength( modep ) unsigned char *modep; { switch ( operandmode( modep ) ) { case literal: case reg: case regdef: case autodec: case autoinc: case autoincdef: return 1; case bytedisp: case bytedispdef: case byterel: case bytereldef: return 2; case worddisp: case worddispdef: case wordrel: case wordreldef: return 3; case immediate: case absolute: case longdisp: case longdispdef: case longrel: case longreldef: return 5; case indexed: return 1+operandlength( modep + 1 ); } /* NOTREACHED */ } unsigned long reladdr( modep ) char *modep; { operandenum mode = operandmode( modep ); char *cp; short *sp; long *lp; int i; long value = 0; cp = modep; cp += 1; /* skip over the mode */ switch ( mode ) { default: fprintf( stderr , "[reladdr] not relative address\n" ); return (unsigned long) modep; case byterel: return (unsigned long) ( cp + sizeof *cp + *cp ); case wordrel: for (i = 0; i < sizeof *sp; i++) value = (value << 8) + (cp[i] & 0xff); return (unsigned long) ( cp + sizeof *sp + value ); case longrel: for (i = 0; i < sizeof *lp; i++) value = (value << 8) + (cp[i] & 0xff); return (unsigned long) ( cp + sizeof *lp + value ); } } findcall( parentp , p_lowpc , p_highpc ) nltype *parentp; unsigned long p_lowpc; unsigned long p_highpc; { unsigned char *instructp; long length; nltype *childp; operandenum mode; operandenum firstmode; unsigned long destpc; if ( textspace == 0 ) { return; } if ( p_lowpc < s_lowpc ) { p_lowpc = s_lowpc; } if ( p_highpc > s_highpc ) { p_highpc = s_highpc; } # ifdef DEBUG if ( debug & CALLDEBUG ) { printf( "[findcall] %s: 0x%x to 0x%x\n" , parentp -> name , p_lowpc , p_highpc ); } # endif DEBUG for ( instructp = textspace + p_lowpc ; instructp < textspace + p_highpc ; instructp += length ) { length = 1; if ( *instructp == CALLF ) { /* * maybe a callf, better check it out. * skip the count of the number of arguments. */ # ifdef DEBUG if ( debug & CALLDEBUG ) { printf( "[findcall]\t0x%x:callf" , instructp - textspace ); } # endif DEBUG firstmode = operandmode( instructp+length ); switch ( firstmode ) { case literal: case immediate: break; default: goto botched; } length += operandlength( instructp+length ); mode = operandmode( instructp + length ); # ifdef DEBUG if ( debug & CALLDEBUG ) { printf( "\tfirst operand is %s", operandname( firstmode ) ); printf( "\tsecond operand is %s\n" , operandname( mode ) ); } # endif DEBUG switch ( mode ) { case regdef: case bytedispdef: case worddispdef: case longdispdef: case bytereldef: case wordreldef: case longreldef: /* * indirect call: call through pointer * either *d(r) as a parameter or local * (r) as a return value * *f as a global pointer * [are there others that we miss?, * e.g. arrays of pointers to functions???] */ addarc( parentp , &indirectchild , (long) 0 ); length += operandlength( instructp + length ); continue; case byterel: case wordrel: case longrel: /* * regular pc relative addressing * check that this is the address of * a function. */ destpc = reladdr( instructp+length ) - (unsigned long) textspace; if ( destpc >= s_lowpc && destpc <= s_highpc ) { childp = nllookup( destpc ); # ifdef DEBUG if ( debug & CALLDEBUG ) { printf( "[findcall]\tdestpc 0x%x" , destpc ); printf( " childp->name %s" , childp -> name ); printf( " childp->value 0x%x\n" , childp -> value ); } # endif DEBUG if ( childp -> value == destpc ) { /* * a hit */ addarc( parentp , childp , (long) 0 ); length += operandlength( instructp + length ); continue; } goto botched; } /* * else: * it looked like a callf, * but it wasn't to anywhere. */ goto botched; default: botched: /* * something funny going on. */ # ifdef DEBUG if ( debug & CALLDEBUG ) { printf( "[findcall]\tbut it's a botch\n" ); } # endif DEBUG length = 1; continue; } } } } rddisp: case worddispdef: case wordrel: case wordreldef: return 3; case immediate: case absolute: case longdisp: case longdispdef: case longrel: case longreldef: return 5; case indexed: return 1+operandlength( modep + 1 ); gprof/gprof.flat 444 22 12 2050 3335276057 7163 flat profile: % the percentage of the total running time of the time program used by this function. cumulative a running sum of the number of seconds accounted seconds for by this function and those listed above it. self the number of seconds accounted for by this seconds function alone. This is the major sort for this listing. calls the number of times this function was invoked, if this function is profiled, else blank. self the average number of milliseconds spent in this ms/call function per call, if this function is profiled, else blank. total the average number of milliseconds spent in this ms/call function and its descendents per call, if this function is profiled, else blank. name the name of the function. This is the minor sort for this listing. The index shows the location of the function in the gprof listing. If the index is in parenthesis it shows where it would appear in the gprof listing if it were to be printed. all]\tdestpc 0x%x" , destpc ); printf( " childp->name %s" , childp -> name ); printf( " childp->value 0x%x\n" , childp -> value ); } # endif DEBUG if ( childp -> value == destpc ) { /* * a hit */ addarc( parentp , childp , (long) 0 ); length += operandlength( instructp + length ); continue; } goto botched; } /* * else: * it looked like a callf, * but it wasn't to anywhere. */ gprof/vax.h 444 22 12 1711 3500671075 6141 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vax.h 5.1 (Berkeley) 6/4/85 */ /* * opcode of the `calls' instruction */ #define CALLS 0xfb /* * offset (in bytes) of the code from the entry address of a routine. * (see asgnsamples for use and explanation.) */ #define OFFSET_OF_CODE 2 #define UNITS_TO_CODE (OFFSET_OF_CODE / sizeof(UNIT)) /* * register for pc relative addressing */ #define PC 0xf enum opermodes { literal, indexed, reg, regdef, autodec, autoinc, autoincdef, bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef, immediate, absolute, byterel, bytereldef, wordrel, wordreldef, longrel, longreldef }; typedef enum opermodes operandenum; struct modebyte { unsigned int regfield:4; unsigned int modefield:4; }; gprof/gprof.callg 444 22 12 6303 3002376446 7316 call graph profile: The sum of self and descendents is the major sort for this listing. function entries: index the index of the function in the call graph listing, as an aid to locating it (see below). %time the percentage of the total time of the program accounted for by this function and its descendents. self the number of seconds spent in this function itself. descendents the number of seconds spent in the descendents of this function on behalf of this function. called the number of times this function is called (other than recursive calls). self the number of times this function calls itself recursively. name the name of the function, with an indication of its membership in a cycle, if any. index the index of the function in the call graph listing, as an aid to locating it. parent listings: self* the number of seconds of this function's self time which is due to calls from this parent. descendents* the number of seconds of this function's descendent time which is due to calls from this parent. called** the number of times this function is called by this parent. This is the numerator of the fraction which divides up the function's time to its parents. total* the number of times this function was called by all of its parents. This is the denominator of the propagation fraction. parents the name of this parent, with an indication of the parent's membership in a cycle, if any. index the index of this parent in the call graph listing, as an aid in locating it. children listings: self* the number of seconds of this child's self time which is due to being called by this function. descendent* the number of seconds of this child's descendent's time which is due to being called by this function. called** the number of times this child is called by this function. This is the numerator of the propagation fraction for this child. total* the number of times this child is called by all functions. This is the denominator of the propagation fraction. children the name of this child, and an indication of its membership in a cycle, if any. index the index of this child in the call graph listing, as an aid to locating it. * these fields are omitted for parents (or children) in the same cycle as the function. If the function (or child) is a member of a cycle, the propagated times and propagation denominator represent the self time and descendent time of the cycle as a whole. ** static-only parents and children are indicated by a call count of 0. cycle listings: the cycle as a whole is listed with the same fields as a function entry. Below it are listed the members of the cycle, and their contributions to the time and call counts of the cycle. om this parent. called** the number of times this function is called by this parent. This is the numerator of the fraction which divides up the function's time to its parents. total* the number of times this function was called by all of its parents. This is gprof/tahoe.h 444 22 12 1253 3610153710 6435 /* tahoe.h 1.1 86/01/07 */ /* * opcode of the `callf' instruction */ #define CALLF 0xfe /* * offset (in bytes) of the code from the entry address of a routine. * (see asgnsamples for use and explanation.) */ #define OFFSET_OF_CODE 2 #define UNITS_TO_CODE (OFFSET_OF_CODE / sizeof(UNIT)) /* * register for pc relative addressing */ #define PC 0xf enum opermodes { literal, indexed, reg, regdef, autodec, autoinc, autoincdef, bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef, immediate, absolute, byterel, bytereldef, wordrel, wordreldef, longrel, longreldef }; typedef enum opermodes operandenum; gprof/vax.c 444 22 12 16774 3610154261 6166 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)vax.c 5.3 (Berkeley) 1/7/86"; #endif not lint #include "gprof.h" /* * a namelist entry to be the child of indirect calls */ nltype indirectchild = { "(*)" , /* the name */ (unsigned long) 0 , /* the pc entry point */ (unsigned long) 0 , /* entry point aligned to histogram */ (double) 0.0 , /* ticks in this routine */ (double) 0.0 , /* cumulative ticks in children */ (long) 0 , /* how many times called */ (long) 0 , /* how many calls to self */ (double) 1.0 , /* propagation fraction */ (double) 0.0 , /* self propagation time */ (double) 0.0 , /* child propagation time */ (bool) 0 , /* print flag */ (int) 0 , /* index in the graph list */ (int) 0 , /* graph call chain top-sort order */ (int) 0 , /* internal number of cycle on */ (struct nl *) &indirectchild , /* pointer to head of cycle */ (struct nl *) 0 , /* pointer to next member of cycle */ (arctype *) 0 , /* list of caller arcs */ (arctype *) 0 /* list of callee arcs */ }; operandenum operandmode( modep ) struct modebyte *modep; { long usesreg = modep -> regfield; switch ( modep -> modefield ) { case 0: case 1: case 2: case 3: return literal; case 4: return indexed; case 5: return reg; case 6: return regdef; case 7: return autodec; case 8: return ( usesreg != PC ? autoinc : immediate ); case 9: return ( usesreg != PC ? autoincdef : absolute ); case 10: return ( usesreg != PC ? bytedisp : byterel ); case 11: return ( usesreg != PC ? bytedispdef : bytereldef ); case 12: return ( usesreg != PC ? worddisp : wordrel ); case 13: return ( usesreg != PC ? worddispdef : wordreldef ); case 14: return ( usesreg != PC ? longdisp : longrel ); case 15: return ( usesreg != PC ? longdispdef : longreldef ); } /* NOTREACHED */ } char * operandname( mode ) operandenum mode; { switch ( mode ) { case literal: return "literal"; case indexed: return "indexed"; case reg: return "register"; case regdef: return "register deferred"; case autodec: return "autodecrement"; case autoinc: return "autoincrement"; case autoincdef: return "autoincrement deferred"; case bytedisp: return "byte displacement"; case bytedispdef: return "byte displacement deferred"; case byterel: return "byte relative"; case bytereldef: return "byte relative deferred"; case worddisp: return "word displacement"; case worddispdef: return "word displacement deferred"; case wordrel: return "word relative"; case wordreldef: return "word relative deferred"; case immediate: return "immediate"; case absolute: return "absolute"; case longdisp: return "long displacement"; case longdispdef: return "long displacement deferred"; case longrel: return "long relative"; case longreldef: return "long relative deferred"; } /* NOTREACHED */ } long operandlength( modep ) struct modebyte *modep; { switch ( operandmode( modep ) ) { case literal: case reg: case regdef: case autodec: case autoinc: case autoincdef: return 1; case bytedisp: case bytedispdef: case byterel: case bytereldef: return 2; case worddisp: case worddispdef: case wordrel: case wordreldef: return 3; case immediate: case absolute: case longdisp: case longdispdef: case longrel: case longreldef: return 5; case indexed: return 1+operandlength( (struct modebyte *) ((char *) modep) + 1 ); } /* NOTREACHED */ } unsigned long reladdr( modep ) struct modebyte *modep; { operandenum mode = operandmode( modep ); char *cp; short *sp; long *lp; cp = (char *) modep; cp += 1; /* skip over the mode */ switch ( mode ) { default: fprintf( stderr , "[reladdr] not relative address\n" ); return (unsigned long) modep; case byterel: return (unsigned long) ( cp + sizeof *cp + *cp ); case wordrel: sp = (short *) cp; return (unsigned long) ( cp + sizeof *sp + *sp ); case longrel: lp = (long *) cp; return (unsigned long) ( cp + sizeof *lp + *lp ); } } findcall( parentp , p_lowpc , p_highpc ) nltype *parentp; unsigned long p_lowpc; unsigned long p_highpc; { unsigned char *instructp; long length; nltype *childp; operandenum mode; operandenum firstmode; unsigned long destpc; if ( textspace == 0 ) { return; } if ( p_lowpc < s_lowpc ) { p_lowpc = s_lowpc; } if ( p_highpc > s_highpc ) { p_highpc = s_highpc; } # ifdef DEBUG if ( debug & CALLDEBUG ) { printf( "[findcall] %s: 0x%x to 0x%x\n" , parentp -> name , p_lowpc , p_highpc ); } # endif DEBUG for ( instructp = textspace + p_lowpc ; instructp < textspace + p_highpc ; instructp += length ) { length = 1; if ( *instructp == CALLS ) { /* * maybe a calls, better check it out. * skip the count of the number of arguments. */ # ifdef DEBUG if ( debug & CALLDEBUG ) { printf( "[findcall]\t0x%x:calls" , instructp - textspace ); } # endif DEBUG firstmode = operandmode( (struct modebyte *) (instructp+length) ); switch ( firstmode ) { case literal: case immediate: break; default: goto botched; } length += operandlength( (struct modebyte *) (instructp+length) ); mode = operandmode( (struct modebyte *) ( instructp + length ) ); # ifdef DEBUG if ( debug & CALLDEBUG ) { printf( "\tfirst operand is %s", operandname( firstmode ) ); printf( "\tsecond operand is %s\n" , operandname( mode ) ); } # endif DEBUG switch ( mode ) { case regdef: case bytedispdef: case worddispdef: case longdispdef: case bytereldef: case wordreldef: case longreldef: /* * indirect call: call through pointer * either *d(r) as a parameter or local * (r) as a return value * *f as a global pointer * [are there others that we miss?, * e.g. arrays of pointers to functions???] */ addarc( parentp , &indirectchild , (long) 0 ); length += operandlength( (struct modebyte *) ( instructp + length ) ); continue; case byterel: case wordrel: case longrel: /* * regular pc relative addressing * check that this is the address of * a function. */ destpc = reladdr( (struct modebyte *) (instructp+length) ) - (unsigned long) textspace; if ( destpc >= s_lowpc && destpc <= s_highpc ) { childp = nllookup( destpc ); # ifdef DEBUG if ( debug & CALLDEBUG ) { printf( "[findcall]\tdestpc 0x%x" , destpc ); printf( " childp->name %s" , childp -> name ); printf( " childp->value 0x%x\n" , childp -> value ); } # endif DEBUG if ( childp -> value == destpc ) { /* * a hit */ addarc( parentp , childp , (long) 0 ); length += operandlength( (struct modebyte *) ( instructp + length ) ); continue; } goto botched; } /* * else: * it looked like a calls, * but it wasn't to anywhere. */ goto botched; default: botched: /* * something funny going on. */ # ifdef DEBUG if ( debug & CALLDEBUG ) { printf( "[findcall]\tbut it's a botch\n" ); } # endif DEBUG length = 1; continue; } } } } def:gprof/hp300.h 444 22 12 465 4230222453 6153 /* hp300.h 1.1 88/04/08 */ /* * offset (in bytes) of the code from the entry address of a routine. * (see asgnsamples for use and explanation.) */ #define OFFSET_OF_CODE 0 #define UNITS_TO_CODE (OFFSET_OF_CODE / sizeof(UNIT)) enum opermodes { dummy }; typedef enum opermodes operandenum; ÃD hp300.h r3 RCS ÃE makefile ÃF hp300.c ÃG Œ gcrt0.h ä gprof.o Ã¥ arcs.o æ dfn.o ç lookup.o è hp300.o é hertz.o ê printgprof.o gprof/RCS/ 775 14 12 0 4436154436 5547 gprof/RCS/Makefile,v 444 14 12 12541 4341434416 7547 head 1.3; access ; symbols ; locks ; strict; comment @# @; 1.3 date 88.04.14.00.19.51; author lepreau; state Exp; branches ; next 1.2; 1.2 date 88.04.11.21.50.07; author donn; state Exp; branches ; next 1.1; 1.1 date 88.04.08.16.53.49; author donn; state Rel; branches 1.1.1.1; next ; 1.1.1.1 date 88.11.19.20.14.41; author lepreau; state Exp; branches ; next ; desc @Makefile for gprof, 4.3a BSD. @ 1.3 log @We don't have a group "bin" yet @ text @# # Copyright (c) 1987 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific written prior permission. This software # is provided ``as is'' without express or implied warranty. # # @@(#)Makefile 5.10 (Berkeley) 1/2/88 # CFLAGS= -O LIBC= /lib/libc.a HDRS= gprof.h ${MACHINE}.h SRCS= gprof.c arcs.c dfn.c lookup.c ${MACHINE}.c hertz.c \ printgprof.c printlist.c OBJS= gprof.o arcs.o dfn.o lookup.o ${MACHINE}.o hertz.o \ printgprof.o printlist.o LIBDIR= ../../lib all: gprof gprof: ${OBJS} ${LIBC} ${CC} -o $@@ ${CFLAGS} ${OBJS} gcrt0.h: FRC -if [ -r gcrt0.h ] && \ cmp -s gcrt0.h ${LIBDIR}/libc/${MACHINE}/csu/gmon.h; then \ :; \ else \ rm -f gcrt0.h; \ cp ${LIBDIR}/libc/${MACHINE}/csu/gmon.h gcrt0.h; \ fi clean: FRC rm -f ${OBJS} core gprof depend: FRC mkdep ${CFLAGS} ${SRCS} install: FRC install -s -m 755 gprof ${DESTDIR}/usr/ucb/gprof install -c -m 644 gprof.flat ${DESTDIR}/usr/lib install -c -m 644 gprof.callg ${DESTDIR}/usr/lib lint: FRC lint ${CFLAGS} ${SRCS} tags: FRC ctags ${SRCS} FRC: # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. gprof.o: gprof.c gprof.h /usr/include/stdio.h /usr/include/sys/types.h gprof.o: /usr/include/sys/stat.h /usr/include/a.out.h /usr/include/sys/exec.h gprof.o: gcrt0.h tahoe.h arcs.o: arcs.c gprof.h /usr/include/stdio.h /usr/include/sys/types.h arcs.o: /usr/include/sys/stat.h /usr/include/a.out.h /usr/include/sys/exec.h arcs.o: gcrt0.h tahoe.h dfn.o: dfn.c /usr/include/stdio.h gprof.h /usr/include/stdio.h dfn.o: /usr/include/sys/types.h /usr/include/sys/stat.h /usr/include/a.out.h dfn.o: /usr/include/sys/exec.h gcrt0.h tahoe.h lookup.o: lookup.c gprof.h /usr/include/stdio.h /usr/include/sys/types.h lookup.o: /usr/include/sys/stat.h /usr/include/a.out.h /usr/include/sys/exec.h lookup.o: gcrt0.h tahoe.h tahoe.o: tahoe.c gprof.h /usr/include/stdio.h /usr/include/sys/types.h tahoe.o: /usr/include/sys/stat.h /usr/include/a.out.h /usr/include/sys/exec.h tahoe.o: gcrt0.h tahoe.h hertz.o: hertz.c /usr/include/sys/time.h /usr/include/time.h printgprof.o: printgprof.c gprof.h /usr/include/stdio.h printgprof.o: /usr/include/sys/types.h /usr/include/sys/stat.h printgprof.o: /usr/include/a.out.h /usr/include/sys/exec.h gcrt0.h tahoe.h printlist.o: printlist.c gprof.h /usr/include/stdio.h /usr/include/sys/types.h printlist.o: /usr/include/sys/stat.h /usr/include/a.out.h printlist.o: /usr/include/sys/exec.h gcrt0.h tahoe.h # IF YOU PUT ANYTHING HERE IT WILL GO AWAY @ 1.2 log @Make it possible to build gprof outside /usr/src. @ text @d44 3 a46 3 install -s -o bin -g bin -m 755 gprof ${DESTDIR}/usr/ucb/gprof install -c -o bin -g bin -m 644 gprof.flat ${DESTDIR}/usr/lib install -c -o bin -g bin -m 644 gprof.callg ${DESTDIR}/usr/lib @ 1.1 log @ucb sid 5.10, 1/2/88. @ text @d21 1 d30 1 a30 1 cmp -s gcrt0.h ../../lib/libc/${MACHINE}/csu/gmon.h; then \ d34 1 a34 1 cp ../../lib/libc/${MACHINE}/csu/gmon.h gcrt0.h; \ @ 1.1.1.1 log @4.3 release, sid 5.2, 6/18/85. The odd placement of this rev is because it got left out earlier. @ text @d2 2 a3 3 # Copyright (c) 1983 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. d5 6 a10 1 # @@(#)Makefile 5.2 (Berkeley) 6/18/85 d12 9 a20 1 SCCSID = @@(#)Makefile 5.2 (Berkeley) 6/18/85 d22 1 a22 3 DFLAGS = CFLAGS = -O ${DFLAGS} LINTFLAGS = -x -a -n ${DFLAGS} d24 2 a25 3 RM= /bin/rm -f INSTALL=install PR=pr d27 8 a34 5 GPROFHDRS = gprof.h vax.h GPROFSRCS = gprof.c arcs.c dfn.c lookup.c calls.c hertz.c \ printgprof.c printlist.c GPROFOBJS = gprof.o arcs.o dfn.o lookup.o calls.o hertz.o \ printgprof.o printlist.o d36 2 a37 2 gprof: ${GPROFOBJS} cc -o gprof ${CFLAGS} ${GPROFOBJS} d39 2 a40 4 install: gprof gprof.flat gprof.callg install -s -g kmem -m 2755 gprof ${DESTDIR}/usr/ucb/gprof install -c -m 644 gprof.flat ${DESTDIR}/usr/lib install -c -m 644 gprof.callg ${DESTDIR}/usr/lib d42 4 a45 2 clean: ${RM} ${GPROFOBJS} errs gprof d47 2 a48 2 gcrt0.h: cp /usr/src/libc/csu/gcrt0.h gcrt0.h d50 2 a51 6 print: @@ ls -l | ${PR} @@ ${PR} makefile @@ ${PR} gcrt0.h @@ ${PR} ${GPROFHDRS} ${GPROFSRCS} @@ ${PR} gprof.flat gprof.callg d53 1 a53 2 lint: lint ${LINTFLAGS} ${DFLAGS} ${GPROFSRCS} d55 27 a81 8 gprof.o: gprof.c gprof.h vax.h gcrt0.h arcs.o: arcs.c gprof.h vax.h gcrt0.h lookup.o: lookup.c gprof.h vax.h gcrt0.h dfn.o: dfn.c gprof.h vax.h gcrt0.h calls.o: calls.c gprof.h vax.h gcrt0.h hertz.o: gprof.h vax.h hertz.c printgprof.o: printgprof.c gprof.h vax.h gcrt0.h printlist.o: printlist.c gprof.h vax.h gcrt0.h @ r/include/sys/stat.h /usr/include/a.out.h dfn.o: /usr/include/sys/exec.h gcrt0.h tahoe.h lookup.o: lookup.c gprof.h /usr/include/stdio.h /usr/include/sys/typesgprof/RCS/arcs.c,v 444 14 12 36636 4341433707 7220 head 1.2; access ; symbols ; locks ; strict; comment @ * @; 1.2 date 88.11.19.20.10.46; author lepreau; state Exp; branches ; next 1.1; 1.1 date 88.11.19.19.57.28; author lepreau; state Rel; branches ; next ; desc @@ 1.2 log @ucb sid 5.3, 1/7/86. Went out in hpbsd 1.0. @ text @/* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@@(#)arcs.c 5.3 (Berkeley) 1/7/86"; #endif not lint #include "gprof.h" /* * add (or just increment) an arc */ addarc( parentp , childp , count ) nltype *parentp; nltype *childp; long count; { arctype *calloc(); arctype *arcp; # ifdef DEBUG if ( debug & TALLYDEBUG ) { printf( "[addarc] %d arcs from %s to %s\n" , count , parentp -> name , childp -> name ); } # endif DEBUG arcp = arclookup( parentp , childp ); if ( arcp != 0 ) { /* * a hit: just increment the count. */ # ifdef DEBUG if ( debug & TALLYDEBUG ) { printf( "[tally] hit %d += %d\n" , arcp -> arc_count , count ); } # endif DEBUG arcp -> arc_count += count; return; } arcp = calloc( 1 , sizeof *arcp ); arcp -> arc_parentp = parentp; arcp -> arc_childp = childp; arcp -> arc_count = count; /* * prepend this child to the children of this parent */ arcp -> arc_childlist = parentp -> children; parentp -> children = arcp; /* * prepend this parent to the parents of this child */ arcp -> arc_parentlist = childp -> parents; childp -> parents = arcp; } /* * the code below topologically sorts the graph (collapsing cycles), * and propagates time bottom up and flags top down. */ /* * the topologically sorted name list pointers */ nltype **topsortnlp; topcmp( npp1 , npp2 ) nltype **npp1; nltype **npp2; { return (*npp1) -> toporder - (*npp2) -> toporder; } nltype ** doarcs() { nltype *parentp, **timesortnlp; arctype *arcp; long index; /* * initialize various things: * zero out child times. * count self-recursive calls. * indicate that nothing is on cycles. */ for ( parentp = nl ; parentp < npe ; parentp++ ) { parentp -> childtime = 0.0; arcp = arclookup( parentp , parentp ); if ( arcp != 0 ) { parentp -> ncall -= arcp -> arc_count; parentp -> selfcalls = arcp -> arc_count; } else { parentp -> selfcalls = 0; } parentp -> propfraction = 0.0; parentp -> propself = 0.0; parentp -> propchild = 0.0; parentp -> printflag = FALSE; parentp -> toporder = DFN_NAN; parentp -> cycleno = 0; parentp -> cyclehead = parentp; parentp -> cnext = 0; if ( cflag ) { findcall( parentp , parentp -> value , (parentp+1) -> value ); } } /* * topologically order things * if any node is unnumbered, * number it and any of its descendents. */ for ( parentp = nl ; parentp < npe ; parentp++ ) { if ( parentp -> toporder == DFN_NAN ) { dfn( parentp ); } } /* * link together nodes on the same cycle */ cyclelink(); /* * Sort the symbol table in reverse topological order */ topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) ); if ( topsortnlp == (nltype **) 0 ) { fprintf( stderr , "[doarcs] ran out of memory for topo sorting\n" ); } for ( index = 0 ; index < nname ; index += 1 ) { topsortnlp[ index ] = &nl[ index ]; } qsort( topsortnlp , nname , sizeof(nltype *) , topcmp ); # ifdef DEBUG if ( debug & DFNDEBUG ) { printf( "[doarcs] topological sort listing\n" ); for ( index = 0 ; index < nname ; index += 1 ) { printf( "[doarcs] " ); printf( "%d:" , topsortnlp[ index ] -> toporder ); printname( topsortnlp[ index ] ); printf( "\n" ); } } # endif DEBUG /* * starting from the topological top, * propagate print flags to children. * also, calculate propagation fractions. * this happens before time propagation * since time propagation uses the fractions. */ doflags(); /* * starting from the topological bottom, * propogate children times up to parents. */ dotime(); /* * Now, sort by propself + propchild. * sorting both the regular function names * and cycle headers. */ timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); if ( timesortnlp == (nltype **) 0 ) { fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami ); } for ( index = 0 ; index < nname ; index++ ) { timesortnlp[index] = &nl[index]; } for ( index = 1 ; index <= ncycle ; index++ ) { timesortnlp[nname+index-1] = &cyclenl[index]; } qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp ); for ( index = 0 ; index < nname + ncycle ; index++ ) { timesortnlp[ index ] -> index = index + 1; } return( timesortnlp ); } dotime() { int index; cycletime(); for ( index = 0 ; index < nname ; index += 1 ) { timepropagate( topsortnlp[ index ] ); } } timepropagate( parentp ) nltype *parentp; { arctype *arcp; nltype *childp; double share; double propshare; if ( parentp -> propfraction == 0.0 ) { return; } /* * gather time from children of this parent. */ for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { childp = arcp -> arc_childp; if ( arcp -> arc_count == 0 ) { continue; } if ( childp == parentp ) { continue; } if ( childp -> propfraction == 0.0 ) { continue; } if ( childp -> cyclehead != childp ) { if ( parentp -> cycleno == childp -> cycleno ) { continue; } if ( parentp -> toporder <= childp -> toporder ) { fprintf( stderr , "[propagate] toporder botches\n" ); } childp = childp -> cyclehead; } else { if ( parentp -> toporder <= childp -> toporder ) { fprintf( stderr , "[propagate] toporder botches\n" ); continue; } } if ( childp -> ncall == 0 ) { continue; } /* * distribute time for this arc */ arcp -> arc_time = childp -> time * ( ( (double) arcp -> arc_count ) / ( (double) childp -> ncall ) ); arcp -> arc_childtime = childp -> childtime * ( ( (double) arcp -> arc_count ) / ( (double) childp -> ncall ) ); share = arcp -> arc_time + arcp -> arc_childtime; parentp -> childtime += share; /* * ( 1 - propfraction ) gets lost along the way */ propshare = parentp -> propfraction * share; /* * fix things for printing */ parentp -> propchild += propshare; arcp -> arc_time *= parentp -> propfraction; arcp -> arc_childtime *= parentp -> propfraction; /* * add this share to the parent's cycle header, if any. */ if ( parentp -> cyclehead != parentp ) { parentp -> cyclehead -> childtime += share; parentp -> cyclehead -> propchild += propshare; } # ifdef DEBUG if ( debug & PROPDEBUG ) { printf( "[dotime] child \t" ); printname( childp ); printf( " with %f %f %d/%d\n" , childp -> time , childp -> childtime , arcp -> arc_count , childp -> ncall ); printf( "[dotime] parent\t" ); printname( parentp ); printf( "\n[dotime] share %f\n" , share ); } # endif DEBUG } } cyclelink() { register nltype *nlp; register nltype *cyclenlp; int cycle; nltype *memberp; arctype *arcp; /* * Count the number of cycles, and initialze the cycle lists */ ncycle = 0; for ( nlp = nl ; nlp < npe ; nlp++ ) { /* * this is how you find unattached cycles */ if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) { ncycle += 1; } } /* * cyclenl is indexed by cycle number: * i.e. it is origin 1, not origin 0. */ cyclenl = (nltype *) calloc( ncycle + 1 , sizeof( nltype ) ); if ( cyclenl == 0 ) { fprintf( stderr , "%s: No room for %d bytes of cycle headers\n" , whoami , ( ncycle + 1 ) * sizeof( nltype ) ); done(); } /* * now link cycles to true cycleheads, * number them, accumulate the data for the cycle */ cycle = 0; for ( nlp = nl ; nlp < npe ; nlp++ ) { if ( !( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) ) { continue; } cycle += 1; cyclenlp = &cyclenl[cycle]; cyclenlp -> name = 0; /* the name */ cyclenlp -> value = 0; /* the pc entry point */ cyclenlp -> time = 0.0; /* ticks in this routine */ cyclenlp -> childtime = 0.0; /* cumulative ticks in children */ cyclenlp -> ncall = 0; /* how many times called */ cyclenlp -> selfcalls = 0; /* how many calls to self */ cyclenlp -> propfraction = 0.0; /* what % of time propagates */ cyclenlp -> propself = 0.0; /* how much self time propagates */ cyclenlp -> propchild = 0.0; /* how much child time propagates */ cyclenlp -> printflag = TRUE; /* should this be printed? */ cyclenlp -> index = 0; /* index in the graph list */ cyclenlp -> toporder = DFN_NAN; /* graph call chain top-sort order */ cyclenlp -> cycleno = cycle; /* internal number of cycle on */ cyclenlp -> cyclehead = cyclenlp; /* pointer to head of cycle */ cyclenlp -> cnext = nlp; /* pointer to next member of cycle */ cyclenlp -> parents = 0; /* list of caller arcs */ cyclenlp -> children = 0; /* list of callee arcs */ # ifdef DEBUG if ( debug & CYCLEDEBUG ) { printf( "[cyclelink] " ); printname( nlp ); printf( " is the head of cycle %d\n" , cycle ); } # endif DEBUG /* * link members to cycle header */ for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { memberp -> cycleno = cycle; memberp -> cyclehead = cyclenlp; } /* * count calls from outside the cycle * and those among cycle members */ for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { for ( arcp=memberp->parents ; arcp ; arcp=arcp->arc_parentlist ) { if ( arcp -> arc_parentp == memberp ) { continue; } if ( arcp -> arc_parentp -> cycleno == cycle ) { cyclenlp -> selfcalls += arcp -> arc_count; } else { cyclenlp -> ncall += arcp -> arc_count; } } } } } cycletime() { int cycle; nltype *cyclenlp; nltype *childp; for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) { cyclenlp = &cyclenl[ cycle ]; for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) { if ( childp -> propfraction == 0.0 ) { /* * all members have the same propfraction except those * that were excluded with -E */ continue; } cyclenlp -> time += childp -> time; } cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time; } } /* * in one top to bottom pass over the topologically sorted namelist * propagate: * printflag as the union of parents' printflags * propfraction as the sum of fractional parents' propfractions * and while we're here, sum time for functions. */ doflags() { int index; nltype *childp; nltype *oldhead; oldhead = 0; for ( index = nname-1 ; index >= 0 ; index -= 1 ) { childp = topsortnlp[ index ]; /* * if we haven't done this function or cycle, * inherit things from parent. * this way, we are linear in the number of arcs * since we do all members of a cycle (and the cycle itself) * as we hit the first member of the cycle. */ if ( childp -> cyclehead != oldhead ) { oldhead = childp -> cyclehead; inheritflags( childp ); } # ifdef DEBUG if ( debug & PROPDEBUG ) { printf( "[doflags] " ); printname( childp ); printf( " inherits printflag %d and propfraction %f\n" , childp -> printflag , childp -> propfraction ); } # endif DEBUG if ( ! childp -> printflag ) { /* * printflag is off * it gets turned on by * being on -f list, * or there not being any -f list and not being on -e list. */ if ( onlist( flist , childp -> name ) || ( !fflag && !onlist( elist , childp -> name ) ) ) { childp -> printflag = TRUE; } } else { /* * this function has printing parents: * maybe someone wants to shut it up * by putting it on -e list. (but favor -f over -e) */ if ( ( !onlist( flist , childp -> name ) ) && onlist( elist , childp -> name ) ) { childp -> printflag = FALSE; } } if ( childp -> propfraction == 0.0 ) { /* * no parents to pass time to. * collect time from children if * its on -F list, * or there isn't any -F list and its not on -E list. */ if ( onlist( Flist , childp -> name ) || ( !Fflag && !onlist( Elist , childp -> name ) ) ) { childp -> propfraction = 1.0; } } else { /* * it has parents to pass time to, * but maybe someone wants to shut it up * by puttting it on -E list. (but favor -F over -E) */ if ( !onlist( Flist , childp -> name ) && onlist( Elist , childp -> name ) ) { childp -> propfraction = 0.0; } } childp -> propself = childp -> time * childp -> propfraction; printtime += childp -> propself; # ifdef DEBUG if ( debug & PROPDEBUG ) { printf( "[doflags] " ); printname( childp ); printf( " ends up with printflag %d and propfraction %f\n" , childp -> printflag , childp -> propfraction ); printf( "time %f propself %f printtime %f\n" , childp -> time , childp -> propself , printtime ); } # endif DEBUG } } /* * check if any parent of this child * (or outside parents of this cycle) * have their print flags on and set the * print flag of the child (cycle) appropriately. * similarly, deal with propagation fractions from parents. */ inheritflags( childp ) nltype *childp; { nltype *headp; arctype *arcp; nltype *parentp; nltype *memp; headp = childp -> cyclehead; if ( childp == headp ) { /* * just a regular child, check its parents */ childp -> printflag = FALSE; childp -> propfraction = 0.0; for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) { parentp = arcp -> arc_parentp; if ( childp == parentp ) { continue; } childp -> printflag |= parentp -> printflag; /* * if the child was never actually called * (e.g. this arc is static (and all others are, too)) * no time propagates along this arc. */ if ( childp -> ncall ) { childp -> propfraction += parentp -> propfraction * ( ( (double) arcp -> arc_count ) / ( (double) childp -> ncall ) ); } } } else { /* * its a member of a cycle, look at all parents from * outside the cycle */ headp -> printflag = FALSE; headp -> propfraction = 0.0; for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) { for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) { if ( arcp -> arc_parentp -> cyclehead == headp ) { continue; } parentp = arcp -> arc_parentp; headp -> printflag |= parentp -> printflag; /* * if the cycle was never actually called * (e.g. this arc is static (and all others are, too)) * no time propagates along this arc. */ if ( headp -> ncall ) { headp -> propfraction += parentp -> propfraction * ( ( (double) arcp -> arc_count ) / ( (double) headp -> ncall ) ); } } } for ( memp = headp ; memp ; memp = memp -> cnext ) { memp -> printflag = headp -> printflag; memp -> propfraction = headp -> propfraction; } } } @ 1.1 log @4.3 release @ text @d8 1 a8 1 static char sccsid[] = "@@(#)arcs.c 5.2 (Berkeley) 6/4/85"; d108 1 a108 1 findcalls( parentp , parentp -> value , (parentp+1) -> value ); @ tname( childp ); printf( " inherits printflag %d and propfraction %f\n" , childp -> printflaggprof/RCS/gprof.c,v 444 33 12 42045 4436154434 7377 head 1.4; access ; symbols ; locks ; strict; comment @ * @; 1.4 date 89.05.22.22.07.18; author mike; state Exp; branches ; next 1.3; 1.3 date 88.11.19.20.20.04; author lepreau; state Exp; branches ; next 1.2; 1.2 date 88.11.19.20.18.45; author lepreau; state Exp; branches ; next 1.1; 1.1 date 88.11.19.19.57.30; author lepreau; state Rel; branches ; next ; desc @@ 1.4 log @added -H option to specify hertz value for machine with alternate profiling timer running at a rate different from the default clock @ text @/* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint char copyright[] = "@@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n"; #endif not lint #ifndef lint static char sccsid[] = "@@(#)gprof.c 5.3 (Berkeley) 1/2/88"; #endif not lint #include "gprof.h" char *whoami = "gprof"; /* * things which get -E excluded by default. */ char *defaultEs[] = { "mcount" , "__mcleanup" , 0 }; main(argc, argv) int argc; char **argv; { char **sp; nltype **timesortnlp; --argc; argv++; debug = 0; bflag = TRUE; while ( *argv != 0 && **argv == '-' ) { (*argv)++; switch ( **argv ) { case 'a': aflag = TRUE; break; case 'b': bflag = FALSE; break; case 'c': #if hp300 fprintf(stderr, "gprof -c isn't supported on hp300s yet\n"); exit(1); #endif cflag = TRUE; break; case 'd': dflag = TRUE; (*argv)++; debug |= atoi( *argv ); debug |= ANYDEBUG; # ifdef DEBUG printf("[main] debug = %d\n", debug); # else not DEBUG printf("%s: -d ignored\n", whoami); # endif DEBUG break; case 'E': ++argv; addlist( Elist , *argv ); Eflag = TRUE; addlist( elist , *argv ); eflag = TRUE; break; case 'e': addlist( elist , *++argv ); eflag = TRUE; break; case 'F': ++argv; addlist( Flist , *argv ); Fflag = TRUE; addlist( flist , *argv ); fflag = TRUE; break; case 'f': addlist( flist , *++argv ); fflag = TRUE; break; case 'H': hz = atoi( *++argv ); if (hz < 0 || hz > 100000) { fprintf(stderr, "unreasonable HZ value, using default\n"); hz = 0; } break; case 'k': addlist( kfromlist , *++argv ); addlist( ktolist , *++argv ); kflag = TRUE; break; case 's': sflag = TRUE; break; case 'z': zflag = TRUE; break; } argv++; } if ( *argv != 0 ) { a_outname = *argv; argv++; } else { a_outname = A_OUTNAME; } if ( *argv != 0 ) { gmonname = *argv; argv++; } else { gmonname = GMONNAME; } /* * turn off default functions */ for ( sp = &defaultEs[0] ; *sp ; sp++ ) { Eflag = TRUE; addlist( Elist , *sp ); eflag = TRUE; addlist( elist , *sp ); } /* * how many ticks per second? * if we can't tell, report time in ticks. */ if (hz == 0) hz = hertz(); if (hz == 0) { hz = 1; fprintf(stderr, "time is in ticks, not seconds\n"); } /* * get information about a.out file. */ getnfile(); /* * get information about mon.out file(s). */ do { getpfile( gmonname ); if ( *argv != 0 ) { gmonname = *argv; } } while ( *argv++ != 0 ); /* * dump out a gmon.sum file if requested */ if ( sflag ) { dumpsum( GMONSUM ); } /* * assign samples to procedures */ asgnsamples(); /* * assemble the dynamic profile */ timesortnlp = doarcs(); /* * print the dynamic profile */ printgprof( timesortnlp ); /* * print the flat profile */ printprof(); /* * print the index */ printindex(); done(); } /* * Set up string and symbol tables from a.out. * and optionally the text space. * On return symbol table is sorted by value. */ getnfile() { FILE *nfile; int valcmp(); nfile = fopen( a_outname ,"r"); if (nfile == NULL) { perror( a_outname ); done(); } fread(&xbuf, 1, sizeof(xbuf), nfile); if (N_BADMAG(xbuf)) { fprintf(stderr, "%s: %s: bad format\n", whoami , a_outname ); done(); } getstrtab(nfile); getsymtab(nfile); gettextspace( nfile ); qsort(nl, nname, sizeof(nltype), valcmp); fclose(nfile); # ifdef DEBUG if ( debug & AOUTDEBUG ) { register int j; for (j = 0; j < nname; j++){ printf("[getnfile] 0X%08x\t%s\n", nl[j].value, nl[j].name); } } # endif DEBUG } getstrtab(nfile) FILE *nfile; { 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" , whoami , a_outname ); done(); } strtab = (char *)calloc(ssiz, 1); if (strtab == NULL) { fprintf(stderr, "%s: %s: no room for %d bytes of string table", whoami , a_outname , ssiz); done(); } if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) { fprintf(stderr, "%s: %s: error reading string table\n", whoami , a_outname ); done(); } } /* * Read in symbol table */ getsymtab(nfile) FILE *nfile; { register long i; int askfor; struct nlist nbuf; /* pass1 - count symbols */ fseek(nfile, (long)N_SYMOFF(xbuf), 0); nname = 0; for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { fread(&nbuf, sizeof(nbuf), 1, nfile); if ( ! funcsymbol( &nbuf ) ) { continue; } nname++; } if (nname == 0) { fprintf(stderr, "%s: %s: no symbols\n", whoami , a_outname ); done(); } askfor = nname + 1; nl = (nltype *) calloc( askfor , sizeof(nltype) ); if (nl == 0) { fprintf(stderr, "%s: No room for %d bytes of symbol table\n", whoami, askfor * sizeof(nltype) ); done(); } /* pass2 - read symbols */ fseek(nfile, (long)N_SYMOFF(xbuf), 0); npe = nl; nname = 0; for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { fread(&nbuf, sizeof(nbuf), 1, nfile); if ( ! funcsymbol( &nbuf ) ) { # ifdef DEBUG if ( debug & AOUTDEBUG ) { printf( "[getsymtab] rejecting: 0x%x %s\n" , nbuf.n_type , strtab + nbuf.n_un.n_strx ); } # endif DEBUG continue; } npe->value = nbuf.n_value; npe->name = strtab+nbuf.n_un.n_strx; # ifdef DEBUG if ( debug & AOUTDEBUG ) { printf( "[getsymtab] %d %s 0x%08x\n" , nname , npe -> name , npe -> value ); } # endif DEBUG npe++; nname++; } npe->value = -1; } /* * read in the text space of an a.out file */ gettextspace( nfile ) FILE *nfile; { char *malloc(); if ( cflag == 0 ) { return; } textspace = (u_char *) malloc( xbuf.a_text ); if ( textspace == 0 ) { fprintf( stderr , "%s: ran out room for %d bytes of text space: " , whoami , xbuf.a_text ); fprintf( stderr , "can't do -c\n" ); return; } (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" ); free( textspace ); textspace = 0; return; } } /* * information from a gmon.out file is in two parts: * an array of sampling hits within pc ranges, * and the arcs. */ getpfile(filename) char *filename; { FILE *pfile; FILE *openpfile(); struct rawarc arc; pfile = openpfile(filename); readsamples(pfile); /* * the rest of the file consists of * a bunch of <from,self,count> tuples. */ while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) { # ifdef DEBUG if ( debug & SAMPLEDEBUG ) { printf( "[getpfile] frompc 0x%x selfpc 0x%x count %d\n" , arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); } # endif DEBUG /* * add this arc */ tally( &arc ); } fclose(pfile); } FILE * openpfile(filename) char *filename; { struct hdr tmp; FILE *pfile; if((pfile = fopen(filename, "r")) == NULL) { perror(filename); done(); } 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); done(); } h = tmp; s_lowpc = (unsigned long) h.lowpc; s_highpc = (unsigned long) h.highpc; lowpc = (unsigned long)h.lowpc / sizeof(UNIT); highpc = (unsigned long)h.highpc / sizeof(UNIT); sampbytes = h.ncnt - sizeof(struct hdr); nsamples = sampbytes / sizeof (UNIT); # ifdef DEBUG if ( debug & SAMPLEDEBUG ) { printf( "[openpfile] hdr.lowpc 0x%x hdr.highpc 0x%x hdr.ncnt %d\n", h.lowpc , h.highpc , h.ncnt ); printf( "[openpfile] s_lowpc 0x%x s_highpc 0x%x\n" , s_lowpc , s_highpc ); printf( "[openpfile] lowpc 0x%x highpc 0x%x\n" , lowpc , highpc ); printf( "[openpfile] sampbytes %d nsamples %d\n" , sampbytes , nsamples ); } # endif DEBUG return(pfile); } tally( rawp ) struct rawarc *rawp; { nltype *parentp; nltype *childp; parentp = nllookup( rawp -> raw_frompc ); childp = nllookup( rawp -> raw_selfpc ); if ( kflag && onlist( kfromlist , parentp -> name ) && onlist( ktolist , childp -> name ) ) { return; } childp -> ncall += rawp -> raw_count; # ifdef DEBUG if ( debug & TALLYDEBUG ) { printf( "[tally] arc from %s to %s traversed %d times\n" , parentp -> name , childp -> name , rawp -> raw_count ); } # endif DEBUG addarc( parentp , childp , rawp -> raw_count ); } /* * dump out the gmon.sum file */ dumpsum( sumfile ) char *sumfile; { register nltype *nlp; register arctype *arcp; struct rawarc arc; FILE *sfile; if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) { perror( sumfile ); done(); } /* * dump the header; use the last header read in */ if ( fwrite( &h , sizeof h , 1 , sfile ) != 1 ) { perror( sumfile ); done(); } /* * dump the samples */ if (fwrite(samples, sizeof (UNIT), nsamples, sfile) != nsamples) { perror( sumfile ); done(); } /* * dump the normalized raw arc information */ for ( nlp = nl ; nlp < npe ; 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 ) { perror( sumfile ); done(); } # ifdef DEBUG if ( debug & SAMPLEDEBUG ) { printf( "[dumpsum] frompc 0x%x selfpc 0x%x count %d\n" , arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); } # endif DEBUG } } fclose( sfile ); } valcmp(p1, p2) nltype *p1, *p2; { if ( p1 -> value < p2 -> value ) { return LESSTHAN; } if ( p1 -> value > p2 -> value ) { return GREATERTHAN; } return EQUALTO; } readsamples(pfile) FILE *pfile; { register i; UNIT sample; if (samples == 0) { samples = (UNIT *) calloc(sampbytes, sizeof (UNIT)); if (samples == 0) { fprintf( stderr , "%s: No room for %d sample pc's\n", whoami , sampbytes / sizeof (UNIT)); done(); } } for (i = 0; i < nsamples; i++) { fread(&sample, sizeof (UNIT), 1, pfile); if (feof(pfile)) break; samples[i] += sample; } if (i != nsamples) { fprintf(stderr, "%s: unexpected EOF after reading %d/%d samples\n", whoami , --i , nsamples ); done(); } } /* * Assign samples to the procedures to which they belong. * * There are three cases as to where pcl and pch can be * with respect to the routine entry addresses svalue0 and svalue1 * as shown in the following diagram. overlap computes the * distance between the arrows, the fraction of the sample * that is to be credited to the routine which starts at svalue0. * * svalue0 svalue1 * | | * v v * * +-----------------------------------------------+ * | | * | ->| |<- ->| |<- ->| |<- | * | | | | | | * +---------+ +---------+ +---------+ * * ^ ^ ^ ^ ^ ^ * | | | | | | * pcl pch pcl pch pcl pch * * For the vax we assert that samples will never fall in the first * two bytes of any routine, since that is the entry mask, * thus we give call alignentries() to adjust the entry points if * the entry mask falls in one bucket but the code for the routine * doesn't start until the next bucket. In conjunction with the * alignment of routine addresses, this should allow us to have * only one sample for every four bytes of text space and never * have any overlap (the two end cases, above). */ asgnsamples() { register int j; UNIT ccnt; double time; unsigned long pcl, pch; register int i; unsigned long overlap; unsigned long svalue0, svalue1; /* read samples and assign to namelist symbols */ scale = highpc - lowpc; scale /= nsamples; alignentries(); for (i = 0, j = 1; i < nsamples; i++) { ccnt = samples[i]; if (ccnt == 0) continue; pcl = lowpc + scale * i; pch = lowpc + scale * (i + 1); time = ccnt; # ifdef DEBUG if ( debug & SAMPLEDEBUG ) { printf( "[asgnsamples] pcl 0x%x pch 0x%x ccnt %d\n" , pcl , pch , ccnt ); } # endif DEBUG totime += time; for (j = j - 1; j < nname; j++) { svalue0 = nl[j].svalue; svalue1 = nl[j+1].svalue; /* * if high end of tick is below entry address, * go for next tick. */ if (pch < svalue0) break; /* * if low end of tick into next routine, * go for next routine. */ if (pcl >= svalue1) continue; overlap = min(pch, svalue1) - max(pcl, svalue0); if (overlap > 0) { # ifdef DEBUG if (debug & SAMPLEDEBUG) { printf("[asgnsamples] (0x%x->0x%x-0x%x) %s gets %f ticks %d overlap\n", nl[j].value/sizeof(UNIT), svalue0, svalue1, nl[j].name, overlap * time / scale, overlap); } # endif DEBUG nl[j].time += overlap * time / scale; } } } # ifdef DEBUG if (debug & SAMPLEDEBUG) { printf("[asgnsamples] totime %f\n", totime); } # endif DEBUG } unsigned long min(a, b) unsigned long a,b; { if (a<b) return(a); return(b); } unsigned long max(a, b) unsigned long a,b; { if (a>b) return(a); return(b); } /* * calculate scaled entry point addresses (to save time in asgnsamples), * and possibly push the scaled entry points over the entry mask, * if it turns out that the entry point is in one bucket and the code * for a routine is in the next bucket. */ alignentries() { register struct nl *nlp; unsigned long bucket_of_entry; unsigned long bucket_of_code; for (nlp = nl; nlp < npe; nlp++) { nlp -> svalue = nlp -> value / sizeof(UNIT); bucket_of_entry = (nlp->svalue - lowpc) / scale; bucket_of_code = (nlp->svalue + UNITS_TO_CODE - lowpc) / scale; if (bucket_of_entry < bucket_of_code) { # ifdef DEBUG if (debug & SAMPLEDEBUG) { printf("[alignentries] pushing svalue 0x%x to 0x%x\n", nlp->svalue, nlp->svalue + UNITS_TO_CODE); } # endif DEBUG nlp->svalue += UNITS_TO_CODE; } } } bool funcsymbol( nlistp ) struct nlist *nlistp; { extern char *strtab; /* string table from a.out */ extern int aflag; /* if static functions aren't desired */ char *name; /* * must be a text symbol, * 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 ) ) ) ) { return FALSE; } /* * 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 == '$' ) { return FALSE; } } return TRUE; } done() { exit(0); } @ 1.3 log @orignally done by donn, ifdef'ed on hp300, went out with hpbsd 1.0. date: 88/04/11 21:50:52; author: donn; state: Exp; lines added/del: 4/0 It'd take a hell of a lot of work to get gprof -c working, probably not worth the effort. @ text @d86 7 d132 2 a133 1 hz = hertz(); @ 1.2 log @ucb sid 5.3, 1/2/88. @ text @d47 4 @ 1.1 log @4.3 release @ text @d14 1 a14 1 static char sccsid[] = "@@(#)gprof.c 5.1 (Berkeley) 6/4/85"; d82 5 d176 1 d294 1 a294 1 unsigned char *malloc(); d299 1 a299 1 textspace = malloc( xbuf.a_text ); d371 1 a371 1 nsamples = sampbytes / sizeof (unsigned UNIT); d395 5 d435 1 a435 1 if (fwrite(samples, sizeof(unsigned UNIT), nsamples, sfile) != nsamples) { d478 1 a478 1 unsigned UNIT sample; d481 1 a481 1 samples = (unsigned UNIT *) calloc(sampbytes, sizeof (unsigned UNIT)); d484 1 a484 1 whoami , sampbytes / sizeof (unsigned UNIT)); d489 1 a489 1 fread(&sample, sizeof (unsigned UNIT), 1, pfile); d537 1 a537 1 unsigned UNIT ccnt; @ /* read samples and assign to namelist symbols */ scale = highpc - lowpc; scale /= nsamples; alignentries(); for (i = 0, j = 1; i < nsamples; i++) { ccnt = samples[i]; if (ccnt == 0) continue; pcl = lowpc + scale * i; pch = lowpc + scale * (i + 1); time = ccnt; # ifdef DEBUG if ( debug & SAMPLEDEBUG ) { printf( "[asgnsamples] pcl 0x%x pch 0x%x ccnt %d\n" , pcl , pch , ccnt ); } # endif DEBUG totime += time; for (j = j - 1; j gprof/RCS/gprof.h,v 444 14 12 17117 4341435175 7404 head 1.3; access ; symbols ; locks ; strict; comment @ * @; 1.3 date 88.11.19.20.22.09; author lepreau; state Exp; branches ; next 1.2; 1.2 date 88.11.19.20.21.29; author lepreau; state Exp; branches ; next 1.1; 1.1 date 88.11.19.19.57.31; author lepreau; state Rel; branches ; next ; desc @@ 1.3 log @add hp300.h, originally done by Donn on 4/11/88; went out with hpbsd 1.0. @ text @/* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @@(#)gprof.h 5.4 (Berkeley) 1/2/88 */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <a.out.h> #include "gcrt0.h" #if vax # include "vax.h" #endif #if sun # include "sun.h" #endif #if tahoe # include "tahoe.h" #endif #if hp300 # include "hp300.h" #endif /* * who am i, for error messages. */ char *whoami; /* * booleans */ typedef int bool; #define FALSE 0 #define TRUE 1 /* * ticks per second */ long hz; typedef u_short UNIT; /* unit of profiling */ char *a_outname; #define A_OUTNAME "a.out" char *gmonname; #define GMONNAME "gmon.out" #define GMONSUM "gmon.sum" /* * blurbs on the flat and graph profiles. */ #define FLAT_BLURB "/usr/lib/gprof.flat" #define CALLG_BLURB "/usr/lib/gprof.callg" /* * a constructed arc, * with pointers to the namelist entry of the parent and the child, * a count of how many times this arc was traversed, * and pointers to the next parent of this child and * the next child of this parent. */ struct arcstruct { struct nl *arc_parentp; /* pointer to parent's nl entry */ struct nl *arc_childp; /* pointer to child's nl entry */ long arc_count; /* how calls from parent to child */ double arc_time; /* time inherited along arc */ double arc_childtime; /* childtime inherited along arc */ struct arcstruct *arc_parentlist; /* parents-of-this-child list */ struct arcstruct *arc_childlist; /* children-of-this-parent list */ }; typedef struct arcstruct arctype; /* * The symbol table; * for each external in the specified file we gather * its address, the number of calls and compute its share of cpu time. */ struct nl { char *name; /* the name */ unsigned long value; /* the pc entry point */ unsigned long svalue; /* entry point aligned to histograms */ double time; /* ticks in this routine */ double childtime; /* cumulative ticks in children */ long ncall; /* how many times called */ long selfcalls; /* how many calls to self */ double propfraction; /* what % of time propagates */ double propself; /* how much self time propagates */ double propchild; /* how much child time propagates */ bool printflag; /* should this be printed? */ int index; /* index in the graph list */ int toporder; /* graph call chain top-sort order */ int cycleno; /* internal number of cycle on */ struct nl *cyclehead; /* pointer to head of cycle */ struct nl *cnext; /* pointer to next member of cycle */ arctype *parents; /* list of caller arcs */ arctype *children; /* list of callee arcs */ }; typedef struct nl nltype; nltype *nl; /* the whole namelist */ nltype *npe; /* the virtual end of the namelist */ int nname; /* the number of function names */ /* * flag which marks a nl entry as topologically ``busy'' * flag which marks a nl entry as topologically ``not_numbered'' */ #define DFN_BUSY -1 #define DFN_NAN 0 /* * namelist entries for cycle headers. * the number of discovered cycles. */ nltype *cyclenl; /* cycle header namelist */ int ncycle; /* number of cycles discovered */ /* * The header on the gmon.out file. * gmon.out consists of one of these headers, * and then an array of ncnt samples * representing the discretized program counter values. * this should be a struct phdr, but since everything is done * as UNITs, this is in UNITs too. */ struct hdr { UNIT *lowpc; UNIT *highpc; int ncnt; }; struct hdr h; int debug; /* * Each discretized pc sample has * a count of the number of samples in its range */ UNIT *samples; unsigned long s_lowpc; /* lowpc from the profile file */ unsigned long s_highpc; /* highpc from the profile file */ unsigned lowpc, highpc; /* range profiled, in UNIT's */ unsigned sampbytes; /* number of bytes of samples */ int nsamples; /* number of samples */ double actime; /* accumulated time thus far for putprofline */ double totime; /* total time for all routines */ double printtime; /* total of time being printed */ double scale; /* scale factor converting samples to pc values: each sample covers scale bytes */ char *strtab; /* string table in core */ off_t ssiz; /* size of the string table */ struct exec xbuf; /* exec header of a.out */ unsigned char *textspace; /* text space of a.out in core */ /* * option flags, from a to z. */ bool aflag; /* suppress static functions */ bool bflag; /* blurbs, too */ bool cflag; /* discovered call graph, too */ bool dflag; /* debugging options */ bool eflag; /* specific functions excluded */ bool Eflag; /* functions excluded with time */ bool fflag; /* specific functions requested */ bool Fflag; /* functions requested with time */ bool kflag; /* arcs to be deleted */ bool sflag; /* sum multiple gmon.out files */ bool zflag; /* zero time/called functions, too */ /* * structure for various string lists */ struct stringlist { struct stringlist *next; char *string; }; struct stringlist *elist; struct stringlist *Elist; struct stringlist *flist; struct stringlist *Flist; struct stringlist *kfromlist; struct stringlist *ktolist; /* * function declarations */ /* addarc(); */ int arccmp(); arctype *arclookup(); /* asgnsamples(); printblurb(); cyclelink(); dfn(); */ bool dfn_busy(); /* dfn_findcycle(); */ bool dfn_numbered(); /* dfn_post_visit(); dfn_pre_visit(); dfn_self_cycle(); */ nltype **doarcs(); /* done(); findcalls(); flatprofheader(); flatprofline(); */ bool funcsymbol(); /* getnfile(); getpfile(); getstrtab(); getsymtab(); gettextspace(); gprofheader(); gprofline(); main(); */ unsigned long max(); int membercmp(); unsigned long min(); nltype *nllookup(); FILE *openpfile(); long operandlength(); operandenum operandmode(); char *operandname(); /* printchildren(); printcycle(); printgprof(); printmembers(); printname(); printparents(); printprof(); readsamples(); */ unsigned long reladdr(); /* sortchildren(); sortmembers(); sortparents(); tally(); timecmp(); topcmp(); */ int totalcmp(); /* valcmp(); */ #define LESSTHAN -1 #define EQUALTO 0 #define GREATERTHAN 1 #define DFNDEBUG 1 #define CYCLEDEBUG 2 #define ARCDEBUG 4 #define TALLYDEBUG 8 #define TIMEDEBUG 16 #define SAMPLEDEBUG 32 #define AOUTDEBUG 64 #define CALLDEBUG 128 #define LOOKUPDEBUG 256 #define PROPDEBUG 512 #define ANYDEBUG 1024 @ 1.2 log @ucb sid 5.4, 1/2/88. @ text @d24 3 @ 1.1 log @4.3 release @ text @d6 1 a6 1 * @@(#)gprof.h 5.1 (Berkeley) 6/4/85 d19 1 a19 1 # include "sun.h" d21 3 d43 1 a43 1 typedef short UNIT; /* unit of profiling */ d50 1 a50 1 d142 1 a142 1 unsigned UNIT *samples; d170 1 d185 2 d191 1 d193 1 d196 1 d201 1 d203 1 d205 1 d207 1 d211 1 d213 1 d218 1 d220 1 d229 1 d238 1 d247 1 d249 1 d256 1 d258 1 d260 1 d273 1 a273 1 #define CALLSDEBUG 128 @ */ #define DFN_BUSY -1 #define DFN_NAN 0 /* * namelist entries for cycle headers. * the number of discovered cycles. */ nltype *cyclenl; /* cycle header namelist */ int ncycle; /* number of cycles discovered */ /* * The header on the gmon.out file. * gmon.out consists of one of these headers, * and then an array of ncnt samples * representing the discretized program counter valuesgprof/RCS/printgprof.c,v 444 14 12 44067 4341433537 10460 head 1.2; access ; symbols ; locks ; strict; comment @ * @; 1.2 date 88.11.19.20.08.36; author lepreau; state Exp; branches ; next 1.1; 1.1 date 88.11.19.19.57.32; author lepreau; state Rel; branches ; next ; desc @@ 1.2 log @ucb sid 5.3, 1/2/88. went out in hpbsd 1.0 @ text @/* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@@(#)printgprof.c 5.3 (Berkeley) 1/2/88"; #endif not lint #include "gprof.h" printprof() { register nltype *np; nltype **sortednlp; int index, timecmp(); actime = 0.0; printf( "\f\n" ); flatprofheader(); /* * Sort the symbol table in by time */ sortednlp = (nltype **) calloc( nname , sizeof(nltype *) ); if ( sortednlp == (nltype **) 0 ) { fprintf( stderr , "[printprof] ran out of memory for time sorting\n" ); } for ( index = 0 ; index < nname ; index += 1 ) { sortednlp[ index ] = &nl[ index ]; } qsort( sortednlp , nname , sizeof(nltype *) , timecmp ); for ( index = 0 ; index < nname ; index += 1 ) { np = sortednlp[ index ]; flatprofline( np ); } actime = 0.0; cfree( sortednlp ); } timecmp( npp1 , npp2 ) nltype **npp1, **npp2; { double timediff; long calldiff; timediff = (*npp2) -> time - (*npp1) -> time; if ( timediff > 0.0 ) return 1 ; if ( timediff < 0.0 ) return -1; calldiff = (*npp2) -> ncall - (*npp1) -> ncall; if ( calldiff > 0 ) return 1; if ( calldiff < 0 ) return -1; return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); } /* * header for flatprofline */ flatprofheader() { if ( bflag ) { printblurb( FLAT_BLURB ); } printf( "\ngranularity: each sample hit covers %d byte(s)" , (long) scale * sizeof(UNIT) ); if ( totime > 0.0 ) { printf( " for %.2f%% of %.2f seconds\n\n" , 100.0/totime , totime / hz ); } else { printf( " no time accumulated\n\n" ); /* * this doesn't hurt sinc eall the numerators will be zero. */ totime = 1.0; } printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" , "% " , "cumulative" , "self " , "" , "self " , "total " , "" ); printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" , "time" , "seconds " , "seconds" , "calls" , "ms/call" , "ms/call" , "name" ); } flatprofline( np ) register nltype *np; { if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 ) { return; } actime += np -> time; printf( "%5.1f %10.2f %8.2f" , 100 * np -> time / totime , actime / hz , np -> time / hz ); if ( np -> ncall != 0 ) { printf( " %8d %8.2f %8.2f " , np -> ncall , 1000 * np -> time / hz / np -> ncall , 1000 * ( np -> time + np -> childtime ) / hz / np -> ncall ); } else { printf( " %8.8s %8.8s %8.8s " , "" , "" , "" ); } printname( np ); printf( "\n" ); } gprofheader() { if ( bflag ) { printblurb( CALLG_BLURB ); } printf( "\ngranularity: each sample hit covers %d byte(s)" , (long) scale * sizeof(UNIT) ); if ( printtime > 0.0 ) { printf( " for %.2f%% of %.2f seconds\n\n" , 100.0/printtime , printtime / hz ); } else { printf( " no time propagated\n\n" ); /* * this doesn't hurt, since all the numerators will be 0.0 */ printtime = 1.0; } printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , "" , "" , "" , "" , "called" , "total" , "parents"); printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" , "index" , "%time" , "self" , "descendents" , "called" , "self" , "name" , "index" ); printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , "" , "" , "" , "" , "called" , "total" , "children"); printf( "\n" ); } gprofline( np ) register nltype *np; { char kirkbuffer[ BUFSIZ ]; sprintf( kirkbuffer , "[%d]" , np -> index ); printf( "%-6.6s %5.1f %7.2f %11.2f" , kirkbuffer , 100 * ( np -> propself + np -> propchild ) / printtime , np -> propself / hz , np -> propchild / hz ); if ( ( np -> ncall + np -> selfcalls ) != 0 ) { printf( " %7d" , np -> ncall ); if ( np -> selfcalls != 0 ) { printf( "+%-7d " , np -> selfcalls ); } else { printf( " %7.7s " , "" ); } } else { printf( " %7.7s %7.7s " , "" , "" ); } printname( np ); printf( "\n" ); } printgprof(timesortnlp) nltype **timesortnlp; { int index; nltype *parentp; /* * Print out the structured profiling list */ gprofheader(); for ( index = 0 ; index < nname + ncycle ; index ++ ) { parentp = timesortnlp[ index ]; if ( zflag == 0 && parentp -> ncall == 0 && parentp -> selfcalls == 0 && parentp -> propself == 0 && parentp -> propchild == 0 ) { continue; } if ( ! parentp -> printflag ) { continue; } if ( parentp -> name == 0 && parentp -> cycleno != 0 ) { /* * cycle header */ printcycle( parentp ); printmembers( parentp ); } else { printparents( parentp ); gprofline( parentp ); printchildren( parentp ); } printf( "\n" ); printf( "-----------------------------------------------\n" ); printf( "\n" ); } cfree( timesortnlp ); } /* * sort by decreasing propagated time * if times are equal, but one is a cycle header, * say that's first (e.g. less, i.e. -1). * if one's name doesn't have an underscore and the other does, * say the one is first. * all else being equal, sort by names. */ int totalcmp( npp1 , npp2 ) nltype **npp1; nltype **npp2; { register nltype *np1 = *npp1; register nltype *np2 = *npp2; double diff; diff = ( np1 -> propself + np1 -> propchild ) - ( np2 -> propself + np2 -> propchild ); if ( diff < 0.0 ) return 1; if ( diff > 0.0 ) return -1; if ( np1 -> name == 0 && np1 -> cycleno != 0 ) return -1; if ( np2 -> name == 0 && np2 -> cycleno != 0 ) return 1; if ( np1 -> name == 0 ) return -1; if ( np2 -> name == 0 ) return 1; if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' ) return -1; if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' ) return 1; if ( np1 -> ncall > np2 -> ncall ) return -1; if ( np1 -> ncall < np2 -> ncall ) return 1; return strcmp( np1 -> name , np2 -> name ); } printparents( childp ) nltype *childp; { nltype *parentp; arctype *arcp; nltype *cycleheadp; if ( childp -> cyclehead != 0 ) { cycleheadp = childp -> cyclehead; } else { cycleheadp = childp; } if ( childp -> parents == 0 ) { printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n" , "" , "" , "" , "" , "" , "" ); return; } sortparents( childp ); for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) { parentp = arcp -> arc_parentp; if ( childp == parentp || ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) { /* * selfcall or call among siblings */ printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " , "" , "" , "" , "" , arcp -> arc_count , "" ); printname( parentp ); printf( "\n" ); } else { /* * regular parent of child */ printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " , "" , "" , arcp -> arc_time / hz , arcp -> arc_childtime / hz , arcp -> arc_count , cycleheadp -> ncall ); printname( parentp ); printf( "\n" ); } } } printchildren( parentp ) nltype *parentp; { nltype *childp; arctype *arcp; sortchildren( parentp ); arcp = parentp -> children; for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { childp = arcp -> arc_childp; if ( childp == parentp || ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) { /* * self call or call to sibling */ printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " , "" , "" , "" , "" , arcp -> arc_count , "" ); printname( childp ); printf( "\n" ); } else { /* * regular child of parent */ printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " , "" , "" , arcp -> arc_time / hz , arcp -> arc_childtime / hz , arcp -> arc_count , childp -> cyclehead -> ncall ); printname( childp ); printf( "\n" ); } } } printname( selfp ) nltype *selfp; { if ( selfp -> name != 0 ) { printf( "%s" , selfp -> name ); # ifdef DEBUG if ( debug & DFNDEBUG ) { printf( "{%d} " , selfp -> toporder ); } if ( debug & PROPDEBUG ) { printf( "%5.2f%% " , selfp -> propfraction ); } # endif DEBUG } if ( selfp -> cycleno != 0 ) { printf( " <cycle %d>" , selfp -> cycleno ); } if ( selfp -> index != 0 ) { if ( selfp -> printflag ) { printf( " [%d]" , selfp -> index ); } else { printf( " (%d)" , selfp -> index ); } } } sortchildren( parentp ) nltype *parentp; { arctype *arcp; arctype *detachedp; arctype sorted; arctype *prevp; /* * unlink children from parent, * then insertion sort back on to sorted's children. * *arcp the arc you have detached and are inserting. * *detachedp the rest of the arcs to be sorted. * sorted arc list onto which you insertion sort. * *prevp arc before the arc you are comparing. */ sorted.arc_childlist = 0; for ( (arcp = parentp -> children)&&(detachedp = arcp -> arc_childlist); arcp ; (arcp = detachedp)&&(detachedp = detachedp -> arc_childlist)) { /* * consider *arcp as disconnected * insert it into sorted */ for ( prevp = &sorted ; prevp -> arc_childlist ; prevp = prevp -> arc_childlist ) { if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) { break; } } arcp -> arc_childlist = prevp -> arc_childlist; prevp -> arc_childlist = arcp; } /* * reattach sorted children to parent */ parentp -> children = sorted.arc_childlist; } sortparents( childp ) nltype *childp; { arctype *arcp; arctype *detachedp; arctype sorted; arctype *prevp; /* * unlink parents from child, * then insertion sort back on to sorted's parents. * *arcp the arc you have detached and are inserting. * *detachedp the rest of the arcs to be sorted. * sorted arc list onto which you insertion sort. * *prevp arc before the arc you are comparing. */ sorted.arc_parentlist = 0; for ( (arcp = childp -> parents)&&(detachedp = arcp -> arc_parentlist); arcp ; (arcp = detachedp)&&(detachedp = detachedp -> arc_parentlist)) { /* * consider *arcp as disconnected * insert it into sorted */ for ( prevp = &sorted ; prevp -> arc_parentlist ; prevp = prevp -> arc_parentlist ) { if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) { break; } } arcp -> arc_parentlist = prevp -> arc_parentlist; prevp -> arc_parentlist = arcp; } /* * reattach sorted arcs to child */ childp -> parents = sorted.arc_parentlist; } /* * print a cycle header */ printcycle( cyclep ) nltype *cyclep; { char kirkbuffer[ BUFSIZ ]; sprintf( kirkbuffer , "[%d]" , cyclep -> index ); printf( "%-6.6s %5.1f %7.2f %11.2f %7d" , kirkbuffer , 100 * ( cyclep -> propself + cyclep -> propchild ) / printtime , cyclep -> propself / hz , cyclep -> propchild / hz , cyclep -> ncall ); if ( cyclep -> selfcalls != 0 ) { printf( "+%-7d" , cyclep -> selfcalls ); } else { printf( " %7.7s" , "" ); } printf( " <cycle %d as a whole>\t[%d]\n" , cyclep -> cycleno , cyclep -> index ); } /* * print the members of a cycle */ printmembers( cyclep ) nltype *cyclep; { nltype *memberp; sortmembers( cyclep ); for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) { printf( "%6.6s %5.5s %7.2f %11.2f %7d" , "" , "" , memberp -> propself / hz , memberp -> propchild / hz , memberp -> ncall ); if ( memberp -> selfcalls != 0 ) { printf( "+%-7d" , memberp -> selfcalls ); } else { printf( " %7.7s" , "" ); } printf( " " ); printname( memberp ); printf( "\n" ); } } /* * sort members of a cycle */ sortmembers( cyclep ) nltype *cyclep; { nltype *todo; nltype *doing; nltype *prev; /* * detach cycle members from cyclehead, * and insertion sort them back on. */ todo = cyclep -> cnext; cyclep -> cnext = 0; for ( (doing = todo)&&(todo = doing -> cnext); doing ; (doing = todo )&&(todo = doing -> cnext )){ for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) { if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) { break; } } doing -> cnext = prev -> cnext; prev -> cnext = doing; } } /* * major sort is on propself + propchild, * next is sort on ncalls + selfcalls. */ int membercmp( this , that ) nltype *this; nltype *that; { double thistime = this -> propself + this -> propchild; double thattime = that -> propself + that -> propchild; long thiscalls = this -> ncall + this -> selfcalls; long thatcalls = that -> ncall + that -> selfcalls; if ( thistime > thattime ) { return GREATERTHAN; } if ( thistime < thattime ) { return LESSTHAN; } if ( thiscalls > thatcalls ) { return GREATERTHAN; } if ( thiscalls < thatcalls ) { return LESSTHAN; } return EQUALTO; } /* * compare two arcs to/from the same child/parent. * - if one arc is a self arc, it's least. * - if one arc is within a cycle, it's less than. * - if both arcs are within a cycle, compare arc counts. * - if neither arc is within a cycle, compare with * arc_time + arc_childtime as major key * arc count as minor key */ int arccmp( thisp , thatp ) arctype *thisp; arctype *thatp; { nltype *thisparentp = thisp -> arc_parentp; nltype *thischildp = thisp -> arc_childp; nltype *thatparentp = thatp -> arc_parentp; nltype *thatchildp = thatp -> arc_childp; double thistime; double thattime; # ifdef DEBUG if ( debug & TIMEDEBUG ) { printf( "[arccmp] " ); printname( thisparentp ); printf( " calls " ); printname ( thischildp ); printf( " %f + %f %d/%d\n" , thisp -> arc_time , thisp -> arc_childtime , thisp -> arc_count , thischildp -> ncall ); printf( "[arccmp] " ); printname( thatparentp ); printf( " calls " ); printname( thatchildp ); printf( " %f + %f %d/%d\n" , thatp -> arc_time , thatp -> arc_childtime , thatp -> arc_count , thatchildp -> ncall ); printf( "\n" ); } # endif DEBUG if ( thisparentp == thischildp ) { /* this is a self call */ return LESSTHAN; } if ( thatparentp == thatchildp ) { /* that is a self call */ return GREATERTHAN; } if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 && thisparentp -> cycleno == thischildp -> cycleno ) { /* this is a call within a cycle */ if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && thatparentp -> cycleno == thatchildp -> cycleno ) { /* that is a call within the cycle, too */ if ( thisp -> arc_count < thatp -> arc_count ) { return LESSTHAN; } if ( thisp -> arc_count > thatp -> arc_count ) { return GREATERTHAN; } return EQUALTO; } else { /* that isn't a call within the cycle */ return LESSTHAN; } } else { /* this isn't a call within a cycle */ if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && thatparentp -> cycleno == thatchildp -> cycleno ) { /* that is a call within a cycle */ return GREATERTHAN; } else { /* neither is a call within a cycle */ thistime = thisp -> arc_time + thisp -> arc_childtime; thattime = thatp -> arc_time + thatp -> arc_childtime; if ( thistime < thattime ) return LESSTHAN; if ( thistime > thattime ) return GREATERTHAN; if ( thisp -> arc_count < thatp -> arc_count ) return LESSTHAN; if ( thisp -> arc_count > thatp -> arc_count ) return GREATERTHAN; return EQUALTO; } } } printblurb( blurbname ) char *blurbname; { FILE *blurbfile; int input; blurbfile = fopen( blurbname , "r" ); if ( blurbfile == NULL ) { perror( blurbname ); return; } while ( ( input = getc( blurbfile ) ) != EOF ) { putchar( input ); } fclose( blurbfile ); } int namecmp( npp1 , npp2 ) nltype **npp1, **npp2; { return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); } printindex() { nltype **namesortnlp; register nltype *nlp; int index, nnames, todo, i, j; char peterbuffer[ BUFSIZ ]; /* * Now, sort regular function name alphbetically * to create an index. */ namesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); if ( namesortnlp == (nltype **) 0 ) { fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami ); } for ( index = 0 , nnames = 0 ; index < nname ; index++ ) { if ( zflag == 0 && nl[index].ncall == 0 && nl[index].time == 0 ) continue; namesortnlp[nnames++] = &nl[index]; } qsort( namesortnlp , nnames , sizeof(nltype *) , namecmp ); for ( index = 1 , todo = nnames ; index <= ncycle ; index++ ) { namesortnlp[todo++] = &cyclenl[index]; } printf( "\f\nIndex by function name\n\n" ); index = ( todo + 2 ) / 3; for ( i = 0; i < index ; i++ ) { for ( j = i; j < todo ; j += index ) { nlp = namesortnlp[ j ]; if ( nlp -> printflag ) { sprintf( peterbuffer , "[%d]" , nlp -> index ); } else { sprintf( peterbuffer , "(%d)" , nlp -> index ); } if ( j < nnames ) { printf( "%6.6s %-19.19s" , peterbuffer , nlp -> name ); } else { printf( "%6.6s " , peterbuffer ); sprintf( peterbuffer , "<cycle %d>" , nlp -> cycleno ); printf( "%-19.19s" , peterbuffer ); } } printf( "\n" ); } cfree( namesortnlp ); } @ 1.1 log @4.3 release @ text @d8 1 a8 1 static char sccsid[] = "@@(#)printgprof.c 5.1 (Berkeley) 6/4/85"; d17 1 a17 1 int index; d128 1 a128 1 "" , "" , "" , "" , "called" , "total" , "parents" , "" ); d133 1 a133 1 "" , "" , "" , "" , "called" , "total" , "children" , "" ); @ ame( thisparentp ); printf( " calls " ); printname ( thischildp ); printf( " %f + %f %d/%d\n" , thisp -> arc_time , thisp -> arc_childtime , thisp -> arc_count , thischildp -> ncall ); printf( "[arccmp] " ); printname( thatparentp ); printf( " calls " ); printname( thatchildp ); printf( " %f + %f %d/%d\n" , thatp -> arc_time , thatp -> arc_childtime , thatp -> arc_count , thatchildp -> ncalgprof/RCS/printlist.c,v 444 14 12 4133 4341433623 10260 head 1.2; access ; symbols ; locks ; strict; comment @ * @; 1.2 date 88.11.19.20.09.47; author lepreau; state Exp; branches ; next 1.1; 1.1 date 88.11.19.19.57.33; author lepreau; state Rel; branches ; next ; desc @@ 1.2 log @ucb sid 5.2, 4/27/87. Went out in hpbsd 1.0. @ text @/* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@@(#)printlist.c 5.2 (Berkeley) 4/27/87"; #endif not lint #include "gprof.h" /* * these are the lists of names: * there is the list head and then the listname * is a pointer to the list head * (for ease of passing to stringlist functions). */ struct stringlist kfromhead = { 0 , 0 }; struct stringlist *kfromlist = &kfromhead; struct stringlist ktohead = { 0 , 0 }; struct stringlist *ktolist = &ktohead; struct stringlist fhead = { 0 , 0 }; struct stringlist *flist = &fhead; struct stringlist Fhead = { 0 , 0 }; struct stringlist *Flist = &Fhead; struct stringlist ehead = { 0 , 0 }; struct stringlist *elist = &ehead; struct stringlist Ehead = { 0 , 0 }; struct stringlist *Elist = &Ehead; addlist( listp , funcname ) struct stringlist *listp; char *funcname; { struct stringlist *slp; slp = (struct stringlist *) malloc( sizeof(struct stringlist)); if ( slp == (struct stringlist *) 0 ) { fprintf( stderr, "gprof: ran out room for printlist\n" ); done(); } slp -> next = listp -> next; slp -> string = funcname; listp -> next = slp; } bool onlist( listp , funcname ) struct stringlist *listp; char *funcname; { struct stringlist *slp; for ( slp = listp -> next ; slp ; slp = slp -> next ) { if ( ! strcmp( slp -> string , funcname ) ) { return TRUE; } if ( funcname[0] == '_' && ! strcmp( slp -> string , &funcname[1] ) ) { return TRUE; } } return FALSE; } @ 1.1 log @4.3 release @ text @d8 1 a8 1 static char sccsid[] = "@@(#)printlist.c 5.1 (Berkeley) 6/4/85"; d19 4 @ y * to create an index. */ namesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); if ( namesortnlp == (nltype **) 0 ) { fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami ); } for ( index = 0 , nnames = 0 ; index < nname ; index++ ) { if ( zflag == 0 && nl[index].ncall == 0 && nl[index].time == 0 ) continue; namesortnlp[nnames++] = &nl[index]; } qsort( namgprof/RCS/vax.c,v 444 14 12 20716 4341433744 7057 head 1.2; access ; symbols ; locks ; strict; comment @ * @; 1.2 date 88.11.19.20.11.13; author lepreau; state Exp; branches ; next 1.1; 1.1 date 88.11.19.19.57.29; author lepreau; state Rel; branches ; next ; desc @In 4.3bsd called "calls.c", now renamed to <machine>.c @ 1.2 log @ucb sid 5.3. 1/7/86. went out in hpbsd 1.0. @ text @/* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@@(#)vax.c 5.3 (Berkeley) 1/7/86"; #endif not lint #include "gprof.h" /* * a namelist entry to be the child of indirect calls */ nltype indirectchild = { "(*)" , /* the name */ (unsigned long) 0 , /* the pc entry point */ (unsigned long) 0 , /* entry point aligned to histogram */ (double) 0.0 , /* ticks in this routine */ (double) 0.0 , /* cumulative ticks in children */ (long) 0 , /* how many times called */ (long) 0 , /* how many calls to self */ (double) 1.0 , /* propagation fraction */ (double) 0.0 , /* self propagation time */ (double) 0.0 , /* child propagation time */ (bool) 0 , /* print flag */ (int) 0 , /* index in the graph list */ (int) 0 , /* graph call chain top-sort order */ (int) 0 , /* internal number of cycle on */ (struct nl *) &indirectchild , /* pointer to head of cycle */ (struct nl *) 0 , /* pointer to next member of cycle */ (arctype *) 0 , /* list of caller arcs */ (arctype *) 0 /* list of callee arcs */ }; operandenum operandmode( modep ) struct modebyte *modep; { long usesreg = modep -> regfield; switch ( modep -> modefield ) { case 0: case 1: case 2: case 3: return literal; case 4: return indexed; case 5: return reg; case 6: return regdef; case 7: return autodec; case 8: return ( usesreg != PC ? autoinc : immediate ); case 9: return ( usesreg != PC ? autoincdef : absolute ); case 10: return ( usesreg != PC ? bytedisp : byterel ); case 11: return ( usesreg != PC ? bytedispdef : bytereldef ); case 12: return ( usesreg != PC ? worddisp : wordrel ); case 13: return ( usesreg != PC ? worddispdef : wordreldef ); case 14: return ( usesreg != PC ? longdisp : longrel ); case 15: return ( usesreg != PC ? longdispdef : longreldef ); } /* NOTREACHED */ } char * operandname( mode ) operandenum mode; { switch ( mode ) { case literal: return "literal"; case indexed: return "indexed"; case reg: return "register"; case regdef: return "register deferred"; case autodec: return "autodecrement"; case autoinc: return "autoincrement"; case autoincdef: return "autoincrement deferred"; case bytedisp: return "byte displacement"; case bytedispdef: return "byte displacement deferred"; case byterel: return "byte relative"; case bytereldef: return "byte relative deferred"; case worddisp: return "word displacement"; case worddispdef: return "word displacement deferred"; case wordrel: return "word relative"; case wordreldef: return "word relative deferred"; case immediate: return "immediate"; case absolute: return "absolute"; case longdisp: return "long displacement"; case longdispdef: return "long displacement deferred"; case longrel: return "long relative"; case longreldef: return "long relative deferred"; } /* NOTREACHED */ } long operandlength( modep ) struct modebyte *modep; { switch ( operandmode( modep ) ) { case literal: case reg: case regdef: case autodec: case autoinc: case autoincdef: return 1; case bytedisp: case bytedispdef: case byterel: case bytereldef: return 2; case worddisp: case worddispdef: case wordrel: case wordreldef: return 3; case immediate: case absolute: case longdisp: case longdispdef: case longrel: case longreldef: return 5; case indexed: return 1+operandlength( (struct modebyte *) ((char *) modep) + 1 ); } /* NOTREACHED */ } unsigned long reladdr( modep ) struct modebyte *modep; { operandenum mode = operandmode( modep ); char *cp; short *sp; long *lp; cp = (char *) modep; cp += 1; /* skip over the mode */ switch ( mode ) { default: fprintf( stderr , "[reladdr] not relative address\n" ); return (unsigned long) modep; case byterel: return (unsigned long) ( cp + sizeof *cp + *cp ); case wordrel: sp = (short *) cp; return (unsigned long) ( cp + sizeof *sp + *sp ); case longrel: lp = (long *) cp; return (unsigned long) ( cp + sizeof *lp + *lp ); } } findcall( parentp , p_lowpc , p_highpc ) nltype *parentp; unsigned long p_lowpc; unsigned long p_highpc; { unsigned char *instructp; long length; nltype *childp; operandenum mode; operandenum firstmode; unsigned long destpc; if ( textspace == 0 ) { return; } if ( p_lowpc < s_lowpc ) { p_lowpc = s_lowpc; } if ( p_highpc > s_highpc ) { p_highpc = s_highpc; } # ifdef DEBUG if ( debug & CALLDEBUG ) { printf( "[findcall] %s: 0x%x to 0x%x\n" , parentp -> name , p_lowpc , p_highpc ); } # endif DEBUG for ( instructp = textspace + p_lowpc ; instructp < textspace + p_highpc ; instructp += length ) { length = 1; if ( *instructp == CALLS ) { /* * maybe a calls, better check it out. * skip the count of the number of arguments. */ # ifdef DEBUG if ( debug & CALLDEBUG ) { printf( "[findcall]\t0x%x:calls" , instructp - textspace ); } # endif DEBUG firstmode = operandmode( (struct modebyte *) (instructp+length) ); switch ( firstmode ) { case literal: case immediate: break; default: goto botched; } length += operandlength( (struct modebyte *) (instructp+length) ); mode = operandmode( (struct modebyte *) ( instructp + length ) ); # ifdef DEBUG if ( debug & CALLDEBUG ) { printf( "\tfirst operand is %s", operandname( firstmode ) ); printf( "\tsecond operand is %s\n" , operandname( mode ) ); } # endif DEBUG switch ( mode ) { case regdef: case bytedispdef: case worddispdef: case longdispdef: case bytereldef: case wordreldef: case longreldef: /* * indirect call: call through pointer * either *d(r) as a parameter or local * (r) as a return value * *f as a global pointer * [are there others that we miss?, * e.g. arrays of pointers to functions???] */ addarc( parentp , &indirectchild , (long) 0 ); length += operandlength( (struct modebyte *) ( instructp + length ) ); continue; case byterel: case wordrel: case longrel: /* * regular pc relative addressing * check that this is the address of * a function. */ destpc = reladdr( (struct modebyte *) (instructp+length) ) - (unsigned long) textspace; if ( destpc >= s_lowpc && destpc <= s_highpc ) { childp = nllookup( destpc ); # ifdef DEBUG if ( debug & CALLDEBUG ) { printf( "[findcall]\tdestpc 0x%x" , destpc ); printf( " childp->name %s" , childp -> name ); printf( " childp->value 0x%x\n" , childp -> value ); } # endif DEBUG if ( childp -> value == destpc ) { /* * a hit */ addarc( parentp , childp , (long) 0 ); length += operandlength( (struct modebyte *) ( instructp + length ) ); continue; } goto botched; } /* * else: * it looked like a calls, * but it wasn't to anywhere. */ goto botched; default: botched: /* * something funny going on. */ # ifdef DEBUG if ( debug & CALLDEBUG ) { printf( "[findcall]\tbut it's a botch\n" ); } # endif DEBUG length = 1; continue; } } } } @ 1.1 log @4.3 release @ text @d8 1 a8 1 static char sccsid[] = "@@(#)calls.c 5.1 (Berkeley) 6/4/85"; d191 1 a191 1 findcalls( parentp , p_lowpc , p_highpc ) d213 2 a214 2 if ( debug & CALLSDEBUG ) { printf( "[findcalls] %s: 0x%x to 0x%x\n" , d228 2 a229 2 if ( debug & CALLSDEBUG ) { printf( "[findcalls]\t0x%x:calls" , instructp - textspace ); d243 1 a243 1 if ( debug & CALLSDEBUG ) { d281 2 a282 2 if ( debug & CALLSDEBUG ) { printf( "[findcalls]\tdestpc 0x%x" , destpc ); d311 2 a312 2 if ( debug & CALLSDEBUG ) { printf( "[findcalls]\tbut it's a botch\n" ); @ terel: return (unsigned long) ( cp + sizeof *gprof/makefile 444 22 12 770 4227233605 6656 # # Copyright (c) 1983 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)makefile 5.1 (Berkeley) 10/14/86 # DESTDIR= MACHINE=`machine` .c.o: make -f Makefile ${MFLAGS} MACHINE=${MACHINE} $*.o all: FRC make -f Makefile ${MFLAGS} MACHINE=${MACHINE} FRC: install: make -f Makefile ${MFLAGS} MACHINE=${MACHINE} install clean: make -f Makefile ${MFLAGS} MACHINE=${MACHINE} clean of.o gprof/hp300.c 444 22 12 276 4230223517 6150 #include "gprof.h" /* * gprof -c isn't currently supported... */ findcall( parentp , p_lowpc , p_highpc ) nltype *parentp; unsigned long p_lowpc; unsigned long p_highpc; { } lookup.c Ã>