diff --git a/usr.bin/gprof/Makefile b/usr.bin/gprof/Makefile index 238a9bfe7ae7..c1c76367cba0 100644 --- a/usr.bin/gprof/Makefile +++ b/usr.bin/gprof/Makefile @@ -1,5 +1,5 @@ -# from: @(#)Makefile 5.17 (Berkeley) 5/11/90 -# $Id: Makefile,v 1.9 1994/05/14 06:26:06 cgd Exp $ +# from: @(#)Makefile 8.1 (Berkeley) 6/29/93 +# $Id: Makefile,v 1.10 1994/05/17 03:35:48 cgd Exp $ PROG= gprof SRCS= gprof.c arcs.c dfn.c lookup.c ${MACHINE_ARCH}.c hertz.c \ diff --git a/usr.bin/gprof/arcs.c b/usr.bin/gprof/arcs.c index c96a91356acb..3466efdcb712 100644 --- a/usr.bin/gprof/arcs.c +++ b/usr.bin/gprof/arcs.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,12 +32,19 @@ */ #ifndef lint -/*static char sccsid[] = "from: @(#)arcs.c 5.6 (Berkeley) 6/1/90";*/ -static char rcsid[] = "$Id: arcs.c,v 1.3 1993/08/01 18:15:13 mycroft Exp $"; +/* from: static char sccsid[] = "@(#)arcs.c 8.1 (Berkeley) 6/6/93"; */ +static char *rcsid = "$Id: arcs.c,v 1.4 1994/05/17 03:35:53 cgd Exp $"; #endif /* not lint */ #include "gprof.h" +#ifdef DEBUG +int visited; +int viable; +int newcycle; +int oldcycle; +#endif DEBUG + /* * add (or just increment) an arc */ @@ -68,7 +75,7 @@ addarc( parentp , childp , count ) arcp -> arc_count += count; return; } - arcp = calloc( 1 , sizeof *arcp ); + arcp = (arctype *)calloc( 1 , sizeof *arcp ); arcp -> arc_parentp = parentp; arcp -> arc_childp = childp; arcp -> arc_count = count; @@ -107,6 +114,7 @@ doarcs() nltype *parentp, **timesortnlp; arctype *arcp; long index; + long pass; /* * initialize various things: @@ -123,6 +131,7 @@ doarcs() } else { parentp -> selfcalls = 0; } + parentp -> npropcall = parentp -> ncall; parentp -> propfraction = 0.0; parentp -> propself = 0.0; parentp -> propchild = 0.0; @@ -135,20 +144,56 @@ doarcs() 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 ); + for ( pass = 1 ; ; pass++ ) { + /* + * topologically order things + * if any node is unnumbered, + * number it and any of its descendents. + */ + for ( dfn_init() , parentp = nl ; parentp < npe ; parentp++ ) { + if ( parentp -> toporder == DFN_NAN ) { + dfn( parentp ); + } + } + /* + * link together nodes on the same cycle + */ + cyclelink(); + /* + * if no cycles to break up, proceed + */ + if ( ! Cflag ) + break; + /* + * analyze cycles to determine breakup + */ +# ifdef DEBUG + if ( debug & BREAKCYCLE ) { + printf("[doarcs] pass %d, cycle(s) %d\n" , pass , ncycle ); + } +# endif DEBUG + if ( pass == 1 ) { + printf( "\n\n%s %s\n%s %d:\n" , + "The following arcs were deleted" , + "from the propagation calculation" , + "to reduce the maximum cycle size to", cyclethreshold ); + } + if ( cycleanalyze() ) + break; + free ( cyclenl ); + ncycle = 0; + for ( parentp = nl ; parentp < npe ; parentp++ ) { + parentp -> toporder = DFN_NAN; + parentp -> cycleno = 0; + parentp -> cyclehead = parentp; + parentp -> cnext = 0; } } - /* - * link together nodes on the same cycle - */ - cyclelink(); + if ( pass > 1 ) { + printf( "\f\n" ); + } else { + printf( "\tNone\n\n" ); + } /* * Sort the symbol table in reverse topological order */ @@ -232,6 +277,9 @@ timepropagate( parentp ) */ for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { childp = arcp -> arc_childp; + if ( arcp -> arc_flags & DEADARC ) { + continue; + } if ( arcp -> arc_count == 0 ) { continue; } @@ -255,7 +303,7 @@ timepropagate( parentp ) continue; } } - if ( childp -> ncall == 0 ) { + if ( childp -> npropcall == 0 ) { continue; } /* @@ -263,10 +311,10 @@ timepropagate( parentp ) */ arcp -> arc_time = childp -> time * ( ( (double) arcp -> arc_count ) / - ( (double) childp -> ncall ) ); + ( (double) childp -> npropcall ) ); arcp -> arc_childtime = childp -> childtime * ( ( (double) arcp -> arc_count ) / - ( (double) childp -> ncall ) ); + ( (double) childp -> npropcall ) ); share = arcp -> arc_time + arcp -> arc_childtime; parentp -> childtime += share; /* @@ -292,7 +340,7 @@ timepropagate( parentp ) printname( childp ); printf( " with %f %f %d/%d\n" , childp -> time , childp -> childtime , - arcp -> arc_count , childp -> ncall ); + arcp -> arc_count , childp -> npropcall ); printf( "[dotime] parent\t" ); printname( parentp ); printf( "\n[dotime] share %f\n" , share ); @@ -385,13 +433,329 @@ cyclelink() if ( arcp -> arc_parentp -> cycleno == cycle ) { cyclenlp -> selfcalls += arcp -> arc_count; } else { - cyclenlp -> ncall += arcp -> arc_count; + cyclenlp -> npropcall += arcp -> arc_count; } } } } } + /* + * analyze cycles to determine breakup + */ +cycleanalyze() +{ + arctype **cyclestack; + arctype **stkp; + arctype **arcpp; + arctype **endlist; + arctype *arcp; + nltype *nlp; + cltype *clp; + bool ret; + bool done; + int size; + int cycleno; + + /* + * calculate the size of the cycle, and find nodes that + * exit the cycle as they are desirable targets to cut + * some of their parents + */ + for ( done = TRUE , cycleno = 1 ; cycleno <= ncycle ; cycleno++ ) { + size = 0; + for (nlp = cyclenl[ cycleno ] . cnext; nlp; nlp = nlp -> cnext) { + size += 1; + nlp -> parentcnt = 0; + nlp -> flags &= ~HASCYCLEXIT; + for ( arcp = nlp -> parents; arcp; arcp = arcp -> arc_parentlist ) { + nlp -> parentcnt += 1; + if ( arcp -> arc_parentp -> cycleno != cycleno ) + nlp -> flags |= HASCYCLEXIT; + } + } + if ( size <= cyclethreshold ) + continue; + done = FALSE; + cyclestack = (arctype **) calloc( size + 1 , sizeof( arctype *) ); + if ( cyclestack == 0 ) { + fprintf( stderr , "%s: No room for %d bytes of cycle stack\n" , + whoami , ( size + 1 ) * sizeof( arctype * ) ); + return; + } +# ifdef DEBUG + if ( debug & BREAKCYCLE ) { + printf( "[cycleanalyze] starting cycle %d of %d, size %d\n" , + cycleno , ncycle , size ); + } +# endif DEBUG + for ( nlp = cyclenl[ cycleno ] . cnext ; nlp ; nlp = nlp -> cnext ) { + stkp = &cyclestack[0]; + nlp -> flags |= CYCLEHEAD; + ret = descend ( nlp , cyclestack , stkp ); + nlp -> flags &= ~CYCLEHEAD; + if ( ret == FALSE ) + break; + } + free( cyclestack ); + if ( cyclecnt > 0 ) { + compresslist(); + for ( clp = cyclehead ; clp ; ) { + endlist = &clp -> list[ clp -> size ]; + for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) + (*arcpp) -> arc_cyclecnt--; + cyclecnt--; + clp = clp -> next; + free( clp ); + } + cyclehead = 0; + } + } +# ifdef DEBUG + if ( debug & BREAKCYCLE ) { + printf("%s visited %d, viable %d, newcycle %d, oldcycle %d\n", + "[doarcs]" , visited , viable , newcycle , oldcycle); + } +# endif DEBUG + return( done ); +} + +descend( node , stkstart , stkp ) + nltype *node; + arctype **stkstart; + arctype **stkp; +{ + arctype *arcp; + bool ret; + + for ( arcp = node -> children ; arcp ; arcp = arcp -> arc_childlist ) { +# ifdef DEBUG + visited++; +# endif DEBUG + if ( arcp -> arc_childp -> cycleno != node -> cycleno + || ( arcp -> arc_childp -> flags & VISITED ) + || ( arcp -> arc_flags & DEADARC ) ) + continue; +# ifdef DEBUG + viable++; +# endif DEBUG + *stkp = arcp; + if ( arcp -> arc_childp -> flags & CYCLEHEAD ) { + if ( addcycle( stkstart , stkp ) == FALSE ) + return( FALSE ); + continue; + } + arcp -> arc_childp -> flags |= VISITED; + ret = descend( arcp -> arc_childp , stkstart , stkp + 1 ); + arcp -> arc_childp -> flags &= ~VISITED; + if ( ret == FALSE ) + return( FALSE ); + } +} + +addcycle( stkstart , stkend ) + arctype **stkstart; + arctype **stkend; +{ + arctype **arcpp; + arctype **stkloc; + arctype **stkp; + arctype **endlist; + arctype *minarc; + arctype *arcp; + cltype *clp; + int size; + + size = stkend - stkstart + 1; + if ( size <= 1 ) + return( TRUE ); + for ( arcpp = stkstart , minarc = *arcpp ; arcpp <= stkend ; arcpp++ ) { + if ( *arcpp > minarc ) + continue; + minarc = *arcpp; + stkloc = arcpp; + } + for ( clp = cyclehead ; clp ; clp = clp -> next ) { + if ( clp -> size != size ) + continue; + stkp = stkloc; + endlist = &clp -> list[ size ]; + for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) { + if ( *stkp++ != *arcpp ) + break; + if ( stkp > stkend ) + stkp = stkstart; + } + if ( arcpp == endlist ) { +# ifdef DEBUG + oldcycle++; +# endif DEBUG + return( TRUE ); + } + } + clp = (cltype *) + calloc( 1 , sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) ); + if ( clp == 0 ) { + fprintf( stderr , "%s: No room for %d bytes of subcycle storage\n" , + whoami , sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) ); + return( FALSE ); + } + stkp = stkloc; + endlist = &clp -> list[ size ]; + for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) { + arcp = *arcpp = *stkp++; + if ( stkp > stkend ) + stkp = stkstart; + arcp -> arc_cyclecnt++; + if ( ( arcp -> arc_flags & ONLIST ) == 0 ) { + arcp -> arc_flags |= ONLIST; + arcp -> arc_next = archead; + archead = arcp; + } + } + clp -> size = size; + clp -> next = cyclehead; + cyclehead = clp; +# ifdef DEBUG + newcycle++; + if ( debug & SUBCYCLELIST ) { + printsubcycle( clp ); + } +# endif DEBUG + cyclecnt++; + if ( cyclecnt >= CYCLEMAX ) + return( FALSE ); + return( TRUE ); +} + +compresslist() +{ + cltype *clp; + cltype **prev; + arctype **arcpp; + arctype **endlist; + arctype *arcp; + arctype *maxarcp; + arctype *maxexitarcp; + arctype *maxwithparentarcp; + arctype *maxnoparentarcp; + int maxexitcnt; + int maxwithparentcnt; + int maxnoparentcnt; + char *type; + + maxexitcnt = 0; + maxwithparentcnt = 0; + maxnoparentcnt = 0; + for ( endlist = &archead , arcp = archead ; arcp ; ) { + if ( arcp -> arc_cyclecnt == 0 ) { + arcp -> arc_flags &= ~ONLIST; + *endlist = arcp -> arc_next; + arcp -> arc_next = 0; + arcp = *endlist; + continue; + } + if ( arcp -> arc_childp -> flags & HASCYCLEXIT ) { + if ( arcp -> arc_cyclecnt > maxexitcnt || + ( arcp -> arc_cyclecnt == maxexitcnt && + arcp -> arc_cyclecnt < maxexitarcp -> arc_count ) ) { + maxexitcnt = arcp -> arc_cyclecnt; + maxexitarcp = arcp; + } + } else if ( arcp -> arc_childp -> parentcnt > 1 ) { + if ( arcp -> arc_cyclecnt > maxwithparentcnt || + ( arcp -> arc_cyclecnt == maxwithparentcnt && + arcp -> arc_cyclecnt < maxwithparentarcp -> arc_count ) ) { + maxwithparentcnt = arcp -> arc_cyclecnt; + maxwithparentarcp = arcp; + } + } else { + if ( arcp -> arc_cyclecnt > maxnoparentcnt || + ( arcp -> arc_cyclecnt == maxnoparentcnt && + arcp -> arc_cyclecnt < maxnoparentarcp -> arc_count ) ) { + maxnoparentcnt = arcp -> arc_cyclecnt; + maxnoparentarcp = arcp; + } + } + endlist = &arcp -> arc_next; + arcp = arcp -> arc_next; + } + if ( maxexitcnt > 0 ) { + /* + * first choice is edge leading to node with out-of-cycle parent + */ + maxarcp = maxexitarcp; +# ifdef DEBUG + type = "exit"; +# endif DEBUG + } else if ( maxwithparentcnt > 0 ) { + /* + * second choice is edge leading to node with at least one + * other in-cycle parent + */ + maxarcp = maxwithparentarcp; +# ifdef DEBUG + type = "internal"; +# endif DEBUG + } else { + /* + * last choice is edge leading to node with only this arc as + * a parent (as it will now be orphaned) + */ + maxarcp = maxnoparentarcp; +# ifdef DEBUG + type = "orphan"; +# endif DEBUG + } + maxarcp -> arc_flags |= DEADARC; + maxarcp -> arc_childp -> parentcnt -= 1; + maxarcp -> arc_childp -> npropcall -= maxarcp -> arc_count; +# ifdef DEBUG + if ( debug & BREAKCYCLE ) { + printf( "%s delete %s arc: %s (%d) -> %s from %d cycle(s)\n" , + "[compresslist]" , type , maxarcp -> arc_parentp -> name , + maxarcp -> arc_count , maxarcp -> arc_childp -> name , + maxarcp -> arc_cyclecnt ); + } +# endif DEBUG + printf( "\t%s to %s with %d calls\n" , maxarcp -> arc_parentp -> name , + maxarcp -> arc_childp -> name , maxarcp -> arc_count ); + prev = &cyclehead; + for ( clp = cyclehead ; clp ; ) { + endlist = &clp -> list[ clp -> size ]; + for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) + if ( (*arcpp) -> arc_flags & DEADARC ) + break; + if ( arcpp == endlist ) { + prev = &clp -> next; + clp = clp -> next; + continue; + } + for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) + (*arcpp) -> arc_cyclecnt--; + cyclecnt--; + *prev = clp -> next; + clp = clp -> next; + free( clp ); + } +} + +#ifdef DEBUG +printsubcycle( clp ) + cltype *clp; +{ + arctype **arcpp; + arctype **endlist; + + arcpp = clp -> list; + printf( "%s \n" , (*arcpp) -> arc_parentp -> name , + (*arcpp) -> arc_parentp -> cycleno ) ; + for ( endlist = &clp -> list[ clp -> size ]; arcpp < endlist ; arcpp++ ) + printf( "\t(%d) -> %s\n" , (*arcpp) -> arc_count , + (*arcpp) -> arc_childp -> name ) ; +} +#endif DEBUG + cycletime() { int cycle; @@ -541,10 +905,13 @@ inheritflags( childp ) * (e.g. this arc is static (and all others are, too)) * no time propagates along this arc. */ - if ( childp -> ncall ) { + if ( arcp -> arc_flags & DEADARC ) { + continue; + } + if ( childp -> npropcall ) { childp -> propfraction += parentp -> propfraction - * ( ( (double) arcp -> arc_count ) - / ( (double) childp -> ncall ) ); + * ( ( (double) arcp -> arc_count ) + / ( (double) childp -> npropcall ) ); } } } else { @@ -566,10 +933,13 @@ inheritflags( childp ) * (e.g. this arc is static (and all others are, too)) * no time propagates along this arc. */ - if ( headp -> ncall ) { + if ( arcp -> arc_flags & DEADARC ) { + continue; + } + if ( headp -> npropcall ) { headp -> propfraction += parentp -> propfraction - * ( ( (double) arcp -> arc_count ) - / ( (double) headp -> ncall ) ); + * ( ( (double) arcp -> arc_count ) + / ( (double) headp -> npropcall ) ); } } } diff --git a/usr.bin/gprof/dfn.c b/usr.bin/gprof/dfn.c index 2c5194907bf2..347d5ea8794b 100644 --- a/usr.bin/gprof/dfn.c +++ b/usr.bin/gprof/dfn.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,8 +32,8 @@ */ #ifndef lint -/*static char sccsid[] = "from: @(#)dfn.c 5.4 (Berkeley) 6/1/90";*/ -static char rcsid[] = "$Id: dfn.c,v 1.2 1993/08/01 18:15:12 mycroft Exp $"; +/* from: static char sccsid[] = "@(#)dfn.c 8.1 (Berkeley) 6/6/93"; */ +static char *rcsid = "$Id: dfn.c,v 1.3 1994/05/17 03:35:58 cgd Exp $"; #endif /* not lint */ #include @@ -47,9 +47,16 @@ struct dfnstruct { typedef struct dfnstruct dfntype; dfntype dfn_stack[ DFN_DEPTH ]; -int dfn_depth = 0; +int dfn_depth; -int dfn_counter = DFN_NAN; +int dfn_counter; + +dfn_init() +{ + + dfn_depth = 0; + dfn_counter = DFN_NAN; +} /* * given this parent, depth first number its children. @@ -87,6 +94,8 @@ dfn( parentp ) * visit children */ for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { + if ( arcp -> arc_flags & DEADARC ) + continue; dfn( arcp -> arc_childp ); } /* diff --git a/usr.bin/gprof/gprof.1 b/usr.bin/gprof/gprof.1 index 75eebef7ecd5..71aa6ff74806 100644 --- a/usr.bin/gprof/gprof.1 +++ b/usr.bin/gprof/gprof.1 @@ -1,5 +1,5 @@ -.\" Copyright (c) 1983, 1990 The Regents of the University of California. -.\" All rights reserved. +.\" Copyright (c) 1983, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -29,10 +29,10 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" from: @(#)gprof.1 6.8 (Berkeley) 7/24/91 -.\" $Id: gprof.1,v 1.3 1994/01/11 02:26:28 jtc Exp $ +.\" from: @(#)gprof.1 8.1 (Berkeley) 6/6/93 +.\" $Id: gprof.1,v 1.4 1994/05/17 03:35:59 cgd Exp $ .\" -.Dd July 24, 1991 +.Dd June 6, 1993 .Dt GPROF 1 .Os BSD 4.2 .Sh NAME @@ -78,11 +78,11 @@ Cycles are discovered, and calls into a cycle are made to share the time of the cycle. The first listing shows the functions sorted according to the time they represent -including the time of their call graph descendants. +including the time of their call graph descendents. Below each function entry is shown its (direct) call graph children, and how their times are propagated to this function. A similar display above the function shows how this function's time and the -time of its descendants is propagated to its (direct) call graph parents. +time of its descendents is propagated to its (direct) call graph parents. .Pp Cycles are also shown, with an entry for the cycle as a whole and a listing of the members of the cycle and their contributions to the @@ -92,9 +92,9 @@ Second, a flat profile is given, similar to that provided by .Xr prof 1 . This listing gives the total execution times, the call counts, -the time in milliseconds the call spent in the routine itself, and -the time in milliseconds the call spent in the routine itself including -its descendants. +the time in milleseconds the call spent in the routine itself, and +the time in milleseconds the call spent in the routine itself including +its descendents. .Pp Finally, an index of the function names is provided. .Pp @@ -114,6 +114,14 @@ The static call graph of the program is discovered by a heuristic that examines the text space of the object file. Static-only parents or children are shown with call counts of 0. +.It Fl C Ar count +Find a minimal set of arcs that can be broken to eliminate all cycles with +.Ar count +or more members. +Caution: the algorithm used to break cycles is exponential, +so using this option may cause +.Nm gprof +to run for a very long time. .It Fl e Ar name Suppresses the printing of the graph profile entry for routine .Ar name diff --git a/usr.bin/gprof/gprof.c b/usr.bin/gprof/gprof.c index f820e0861d13..4f88430a0f64 100644 --- a/usr.bin/gprof/gprof.c +++ b/usr.bin/gprof/gprof.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,14 +32,14 @@ */ #ifndef lint -char copyright[] = -"@(#) Copyright (c) 1983 Regents of the University of California.\n\ - All rights reserved.\n"; +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint -/*static char sccsid[] = "from: @(#)gprof.c 5.7 (Berkeley) 4/24/91";*/ -static char rcsid[] = "$Id: gprof.c,v 1.3 1993/08/01 18:15:11 mycroft Exp $"; +/* from: static char sccsid[] = "@(#)gprof.c 8.1 (Berkeley) 6/6/93"; */ +static char *rcsid = "$Id: gprof.c,v 1.4 1994/05/17 03:36:01 cgd Exp $"; #endif /* not lint */ #include "gprof.h" @@ -51,6 +51,8 @@ char *whoami = "gprof"; */ char *defaultEs[] = { "mcount" , "__mcleanup" , 0 }; +static struct gmonhdr gmonhdr; + main(argc, argv) int argc; char **argv; @@ -71,6 +73,10 @@ main(argc, argv) case 'b': bflag = FALSE; break; + case 'C': + Cflag = TRUE; + cyclethreshold = atoi( *++argv ); + break; case 'c': #if defined(vax) || defined(tahoe) cflag = TRUE; @@ -81,8 +87,8 @@ main(argc, argv) break; case 'd': dflag = TRUE; - (*argv)++; - debug |= atoi( *argv ); + setlinebuf(stdout); + debug |= atoi( *++argv ); debug |= ANYDEBUG; # ifdef DEBUG printf("[main] debug = %d\n", debug); @@ -146,15 +152,6 @@ main(argc, argv) addlist( Elist , *sp ); eflag = TRUE; addlist( elist , *sp ); - } - /* - * how many ticks per second? - * if we can't tell, report time in ticks. - */ - hz = hertz(); - if (hz == 0) { - hz = 1; - fprintf(stderr, "time is in ticks, not seconds\n"); } /* * get information about a.out file. @@ -169,6 +166,14 @@ main(argc, argv) gmonname = *argv; } } while ( *argv++ != 0 ); + /* + * how many ticks per second? + * if we can't tell, report time in ticks. + */ + if (hz == 0) { + hz = 1; + fprintf(stderr, "time is in ticks, not seconds\n"); + } /* * dump out a gmon.sum file if requested */ @@ -244,9 +249,9 @@ getstrtab(nfile) whoami , a_outname ); done(); } - strtab = (char *)calloc(ssiz, 1); + strtab = calloc(ssiz, 1); if (strtab == NULL) { - fprintf(stderr, "%s: %s: no room for %d bytes of string table", + fprintf(stderr, "%s: %s: no room for %d bytes of string table\n", whoami , a_outname , ssiz); done(); } @@ -324,6 +329,7 @@ getsymtab(nfile) gettextspace( nfile ) FILE *nfile; { + if ( cflag == 0 ) { return; } @@ -380,36 +386,56 @@ FILE * openpfile(filename) char *filename; { - struct hdr tmp; - FILE *pfile; + struct gmonhdr tmp; + FILE *pfile; + int size; + int rate; 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 ) ) { + fread(&tmp, sizeof(struct gmonhdr), 1, pfile); + if ( s_highpc != 0 && ( tmp.lpc != gmonhdr.lpc || + tmp.hpc != gmonhdr.hpc || tmp.ncnt != gmonhdr.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); + gmonhdr = tmp; + if ( gmonhdr.version == GMONVERSION ) { + rate = gmonhdr.profrate; + size = sizeof(struct gmonhdr); + } else { + fseek(pfile, sizeof(struct ophdr), SEEK_SET); + size = sizeof(struct ophdr); + gmonhdr.profrate = rate = hertz(); + gmonhdr.version = GMONVERSION; + } + if (hz == 0) { + hz = rate; + } else if (hz != rate) { + fprintf(stderr, + "%s: profile clock rate (%d) %s (%d) in first gmon file\n", + filename, rate, "incompatible with clock rate", hz); + done(); + } + s_lowpc = (unsigned long) gmonhdr.lpc; + s_highpc = (unsigned long) gmonhdr.hpc; + lowpc = (unsigned long)gmonhdr.lpc / sizeof(UNIT); + highpc = (unsigned long)gmonhdr.hpc / sizeof(UNIT); + sampbytes = gmonhdr.ncnt - size; 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] hdr.lpc 0x%x hdr.hpc 0x%x hdr.ncnt %d\n", + gmonhdr.lpc , gmonhdr.hpc , gmonhdr.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 ); + printf( "[openpfile] sample rate %d\n" , hz ); } # endif DEBUG return(pfile); @@ -423,6 +449,8 @@ tally( rawp ) parentp = nllookup( rawp -> raw_frompc ); childp = nllookup( rawp -> raw_selfpc ); + if ( parentp == 0 || childp == 0 ) + return; if ( kflag && onlist( kfromlist , parentp -> name ) && onlist( ktolist , childp -> name ) ) { @@ -456,7 +484,7 @@ dumpsum( sumfile ) /* * dump the header; use the last header read in */ - if ( fwrite( &h , sizeof h , 1 , sfile ) != 1 ) { + if ( fwrite( &gmonhdr , sizeof gmonhdr , 1 , sfile ) != 1 ) { perror( sumfile ); done(); } @@ -679,7 +707,7 @@ funcsymbol( nlistp ) { extern char *strtab; /* string table from a.out */ extern int aflag; /* if static functions aren't desired */ - char *name; + char *name, c; /* * must be a text symbol, @@ -693,9 +721,22 @@ funcsymbol( nlistp ) * can't have any `funny' characters in name, * where `funny' includes `.', .o file names * and `$', pascal labels. + * need to make an exception for sparc .mul & co. + * perhaps we should just drop this code entirely... */ - for ( name = strtab + nlistp -> n_un.n_strx ; *name ; name += 1 ) { - if ( *name == '.' || *name == '$' ) { + name = strtab + nlistp -> n_un.n_strx; +#ifdef sparc + if ( *name == '.' ) { + char *p = name + 1; + if ( *p == 'u' ) + p++; + if ( strcmp ( p, "mul" ) == 0 || strcmp ( p, "div" ) == 0 || + strcmp ( p, "rem" ) == 0 ) + return TRUE; + } +#endif + while ( c = *name++ ) { + if ( c == '.' || c == '$' ) { return FALSE; } } diff --git a/usr.bin/gprof/gprof.h b/usr.bin/gprof/gprof.h index 39ebcfdff8c6..c0aa041dfcf2 100644 --- a/usr.bin/gprof/gprof.h +++ b/usr.bin/gprof/gprof.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,38 +30,40 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)gprof.h 5.10 (Berkeley) 4/24/91 - * $Id: gprof.h,v 1.8 1994/05/14 06:26:07 cgd Exp $ + * from: @(#)gprof.h 8.1 (Berkeley) 6/6/93 + * $Id: gprof.h,v 1.9 1994/05/17 03:36:02 cgd Exp $ */ #include #include #include + #include #include #include -#ifdef vax +#if vax # include "vax.h" #endif -#ifdef sun -# include "sun.h" -#endif -#ifdef tahoe -# include "tahoe.h" -#endif -#ifdef m68k -# include "m68k.h" -#endif -#ifdef i386 -# include "i386.h" -#endif -#ifdef sparc +#if sparc # include "sparc.h" #endif -#ifdef ns32k -# include "ns32k.h" +#if tahoe +# include "tahoe.h" #endif +#if m68k +# include "m68k.h" +#endif +#if i386 +# include "i386.h" +#endif +#if mips +# include "mips.h" +#endif +#if pmax +# include "pmax.h" +#endif + /* * who am i, for error messages. @@ -98,14 +100,23 @@ char *gmonname; 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 */ + long arc_count; /* num 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 */ + struct arcstruct *arc_next; /* list of arcs on cycle */ + unsigned short arc_cyclecnt; /* num cycles involved in */ + unsigned short arc_flags; /* see below */ }; typedef struct arcstruct arctype; + /* + * arc flags + */ +#define DEADARC 0x01 /* time should not propagate across the arc */ +#define ONLIST 0x02 /* arc is on list of arcs in cycles */ + /* * The symbol table; * for each external in the specified file we gather @@ -118,14 +129,17 @@ struct nl { double time; /* ticks in this routine */ double childtime; /* cumulative ticks in children */ long ncall; /* how many times called */ + long npropcall; /* times called by live arcs */ 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? */ + short printflag; /* should this be printed? */ + short flags; /* see below */ int index; /* index in the graph list */ int toporder; /* graph call chain top-sort order */ int cycleno; /* internal number of cycle on */ + int parentcnt; /* number of live parent arcs */ struct nl *cyclehead; /* pointer to head of cycle */ struct nl *cnext; /* pointer to next member of cycle */ arctype *parents; /* list of caller arcs */ @@ -137,6 +151,28 @@ nltype *nl; /* the whole namelist */ nltype *npe; /* the virtual end of the namelist */ int nname; /* the number of function names */ +#define HASCYCLEXIT 0x08 /* node has arc exiting from cycle */ +#define CYCLEHEAD 0x10 /* node marked as head of a cycle */ +#define VISITED 0x20 /* node visited during a cycle */ + + /* + * The cycle list. + * for each subcycle within an identified cycle, we gather + * its size and the list of included arcs. + */ +struct cl { + int size; /* length of cycle */ + struct cl *next; /* next member of list */ + arctype *list[1]; /* list of arcs in cycle */ + /* actually longer */ +}; +typedef struct cl cltype; + +arctype *archead; /* the head of arcs in current cycle list */ +cltype *cyclehead; /* the head of the list */ +int cyclecnt; /* the number of cycles found */ +#define CYCLEMAX 100 /* maximum cycles before cutting one of them */ + /* * flag which marks a nl entry as topologically ``busy'' * flag which marks a nl entry as topologically ``not_numbered'' @@ -153,20 +189,18 @@ 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. + * gmon.out consists of a struct phdr (defined in gmon.h) + * and then an array of ncnt samples representing the + * discretized program counter values. + * + * Backward compatible old style header */ -struct hdr { - UNIT *lowpc; - UNIT *highpc; - int ncnt; +struct ophdr { + UNIT *lpc; + UNIT *hpc; + int ncnt; }; -struct hdr h; - int debug; /* @@ -186,9 +220,10 @@ 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 */ +long ssiz; /* size of the string table */ struct exec xbuf; /* exec header of a.out */ -unsigned char *textspace; /* text space of a.out in core */ +unsigned char *textspace; /* text space of a.out in core */ +int cyclethreshold; /* with -C, minimum cycle size to ignore */ /* * option flags, from a to z. @@ -196,6 +231,7 @@ unsigned char *textspace; /* text space of a.out in core */ bool aflag; /* suppress static functions */ bool bflag; /* blurbs, too */ bool cflag; /* discovered call graph, too */ +bool Cflag; /* find cut-set to eliminate cycles */ bool dflag; /* debugging options */ bool eflag; /* specific functions excluded */ bool Eflag; /* functions excluded with time */ @@ -307,4 +343,6 @@ int totalcmp(); #define CALLDEBUG 128 #define LOOKUPDEBUG 256 #define PROPDEBUG 512 -#define ANYDEBUG 1024 +#define BREAKCYCLE 1024 +#define SUBCYCLELIST 2048 +#define ANYDEBUG 4096 diff --git a/usr.bin/gprof/hertz.c b/usr.bin/gprof/hertz.c index 8855aede0126..b80f91f54557 100644 --- a/usr.bin/gprof/hertz.c +++ b/usr.bin/gprof/hertz.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,8 +32,8 @@ */ #ifndef lint -/*static char sccsid[] = "from: @(#)hertz.c 5.4 (Berkeley) 6/1/90";*/ -static char rcsid[] = "$Id: hertz.c,v 1.2 1993/08/01 18:15:10 mycroft Exp $"; +/* from: static char sccsid[] = "@(#)hertz.c 8.1 (Berkeley) 6/6/93"; */ +static char *rcsid = "$Id: hertz.c,v 1.3 1994/05/17 03:36:03 cgd Exp $"; #endif /* not lint */ #include diff --git a/usr.bin/gprof/i386.c b/usr.bin/gprof/i386.c index 2b0f3c999297..2ddbc81a1c85 100644 --- a/usr.bin/gprof/i386.c +++ b/usr.bin/gprof/i386.c @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "$Id: i386.c,v 1.2 1993/08/02 17:54:33 mycroft Exp $"; +static char rcsid[] = "$Id: i386.c,v 1.3 1994/05/17 03:36:05 cgd Exp $"; #endif /* not lint */ #include "gprof.h" diff --git a/usr.bin/gprof/i386.h b/usr.bin/gprof/i386.h index f05be48fd7e7..f29b29cd2ad9 100644 --- a/usr.bin/gprof/i386.h +++ b/usr.bin/gprof/i386.h @@ -1,6 +1,6 @@ /*- - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,8 +30,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)i386.h 5.1 (Berkeley) 4/18/91 - * $Id: i386.h,v 1.2 1993/08/01 18:15:17 mycroft Exp $ + * from: @(#)i386.h 8.1 (Berkeley) 6/6/93 + * $Id: i386.h,v 1.3 1994/05/17 03:36:07 cgd Exp $ */ /* diff --git a/usr.bin/gprof/lookup.c b/usr.bin/gprof/lookup.c index 1dd723a3e73b..14b58f6501f4 100644 --- a/usr.bin/gprof/lookup.c +++ b/usr.bin/gprof/lookup.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,8 +32,8 @@ */ #ifndef lint -/*static char sccsid[] = "from: @(#)lookup.c 5.5 (Berkeley) 2/6/91";*/ -static char rcsid[] = "$Id: lookup.c,v 1.2 1993/08/01 18:15:09 mycroft Exp $"; +/* from: static char sccsid[] = "@(#)lookup.c 8.1 (Berkeley) 6/6/93"; */ +static char *rcsid = "$Id: lookup.c,v 1.3 1994/05/17 03:36:09 cgd Exp $"; #endif /* not lint */ #include "gprof.h" @@ -74,7 +74,12 @@ nllookup( address ) low = middle + 1; } } - fprintf( stderr , "[nllookup] binary search fails???\n" ); +# ifdef DEBUG + if ( debug & LOOKUPDEBUG ) { + fprintf( stderr , "[nllookup] (%d) binary search fails\n" , + nname-1 ); + } +# endif DEBUG return 0; } diff --git a/usr.bin/gprof/m68k.c b/usr.bin/gprof/m68k.c index dda32aa22338..2c3974c5962c 100644 --- a/usr.bin/gprof/m68k.c +++ b/usr.bin/gprof/m68k.c @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "$Id: m68k.c,v 1.1 1993/12/06 05:28:42 cgd Exp $"; +static char rcsid[] = "$Id: m68k.c,v 1.2 1994/05/17 03:36:10 cgd Exp $"; #endif /* not lint */ #include "gprof.h" diff --git a/usr.bin/gprof/m68k.h b/usr.bin/gprof/m68k.h index d1988bcd8f1f..3ccf8b09d43c 100644 --- a/usr.bin/gprof/m68k.h +++ b/usr.bin/gprof/m68k.h @@ -1,6 +1,6 @@ /*- - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,8 +30,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)hp300.h 5.1 (Berkeley) 4/18/91 - * $Id: m68k.h,v 1.1 1993/12/06 05:28:43 cgd Exp $ + * from: @(#)hp300.h 8.1 (Berkeley) 6/6/93 + * $Id: m68k.h,v 1.2 1994/05/17 03:36:12 cgd Exp $ */ /* diff --git a/usr.bin/gprof/mips.c b/usr.bin/gprof/mips.c index 295d64ecffed..ca0df28dbb6e 100644 --- a/usr.bin/gprof/mips.c +++ b/usr.bin/gprof/mips.c @@ -38,7 +38,8 @@ */ #ifndef lint -static char sccsid[] = "@(#)mips.c 8.1 (Berkeley) 6/6/93"; +/* from: static char sccsid[] = "@(#)mips.c 8.1 (Berkeley) 6/6/93"; */ +static char *rcsid = "$Id: mips.c,v 1.2 1994/05/17 03:36:15 cgd Exp $"; #endif /* not lint */ #include "gprof.h" diff --git a/usr.bin/gprof/mips.h b/usr.bin/gprof/mips.h index cd67a43677ca..e164a8021ae1 100644 --- a/usr.bin/gprof/mips.h +++ b/usr.bin/gprof/mips.h @@ -34,9 +34,10 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mips.h 8.1 (Berkeley) 6/6/93 - * * From: @(#)sparc.h 5.1 (Berkeley) 7/8/92 + * + * from: @(#)mips.h 8.1 (Berkeley) 6/6/93 + * $Id: mips.h,v 1.2 1994/05/17 03:36:20 cgd Exp $ */ /* diff --git a/usr.bin/gprof/pathnames.h b/usr.bin/gprof/pathnames.h index 87378c9a7d03..efa08d793eb5 100644 --- a/usr.bin/gprof/pathnames.h +++ b/usr.bin/gprof/pathnames.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 1989 The Regents of the University of California. - * All rights reserved. + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,8 +30,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)pathnames.h 5.2 (Berkeley) 6/1/90 - * $Id: pathnames.h,v 1.2 1993/08/01 18:15:16 mycroft Exp $ + * from: @(#)pathnames.h 8.1 (Berkeley) 6/6/93 + * $Id: pathnames.h,v 1.3 1994/05/17 03:36:22 cgd Exp $ */ #define _PATH_FLAT_BLURB "/usr/share/misc/gprof.flat" diff --git a/usr.bin/gprof/pmax.c b/usr.bin/gprof/pmax.c new file mode 100644 index 000000000000..54515c5dac08 --- /dev/null +++ b/usr.bin/gprof/pmax.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. Modified by Ralph Campbell for mips. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * From: sparc.c 5.1 (Berkeley) 7/7/92 + */ + +#ifndef lint +/* from: static char sccsid[] = "@(#)mips.c 8.1 (Berkeley) 6/6/93"; */ +static char *rcsid = "$Id: pmax.c,v 1.1 1994/05/17 03:36:23 cgd Exp $"; +#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 , /* times called by live arcs */ + (long) 0 , /* how many calls to self */ + (double) 1.0 , /* propagation fraction */ + (double) 0.0 , /* self propagation time */ + (double) 0.0 , /* child propagation time */ + (short) 0 , /* print flag */ + (short) 0 , /* flags */ + (int) 0 , /* index in the graph list */ + (int) 0 , /* graph call chain top-sort order */ + (int) 0 , /* internal number of cycle on */ + (int) 0 , /* number of live parent arcs */ + (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 */ +}; + +findcall(parentp, p_lowpc, p_highpc) + nltype *parentp; + unsigned long p_lowpc; + unsigned long p_highpc; +{ + register u_long pc; + nltype *childp; + unsigned long destpc; + register long op; + register int off; + + if (textspace == 0) + return; + if (p_lowpc < s_lowpc) + p_lowpc = s_lowpc; + if (p_highpc > s_highpc) + p_highpc = s_highpc; + + for (pc = p_lowpc; pc < p_highpc; pc += 4) { + off = pc - s_lowpc; + op = *(u_long *)&textspace[off]; + if ((op & 0xfc000000) == 0x0c000000) { + /* + * a jal insn -- check that this + * is the address of a function. + */ + off = (op & 0x03ffffff) << 2; + destpc = (pc & 0xf0000000) | off; + if (destpc >= s_lowpc && destpc <= s_highpc) { + childp = nllookup(destpc); + if (childp != 0 && childp->value == destpc) + addarc(parentp, childp, 0L); + } + } else if ((op & 0xfc00f83f) == 0x0000f809) + /* + * A jalr -- an indirect call. + */ + addarc(parentp, &indirectchild, 0L); + } +} diff --git a/usr.bin/gprof/pmax.h b/usr.bin/gprof/pmax.h new file mode 100644 index 000000000000..05976e5149a2 --- /dev/null +++ b/usr.bin/gprof/pmax.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. Modified by Ralph Campbell for mips. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * From: @(#)sparc.h 5.1 (Berkeley) 7/8/92 + * + * from: @(#)mips.h 8.1 (Berkeley) 6/6/93 + * $Id: pmax.h,v 1.1 1994/05/17 03:36:24 cgd Exp $ + */ + +/* + * 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; diff --git a/usr.bin/gprof/printgprof.c b/usr.bin/gprof/printgprof.c index aec87bfb6144..cfe4a45218a3 100644 --- a/usr.bin/gprof/printgprof.c +++ b/usr.bin/gprof/printgprof.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,8 +32,8 @@ */ #ifndef lint -/*static char sccsid[] = "from: @(#)printgprof.c 5.7 (Berkeley) 6/1/90";*/ -static char rcsid[] = "$Id: printgprof.c,v 1.2 1993/08/01 18:15:08 mycroft Exp $"; +/* from: static char sccsid[] = "@(#)printgprof.c 8.1 (Berkeley) 6/6/93"; */ +static char *rcsid = "$Id: printgprof.c,v 1.3 1994/05/17 03:36:27 cgd Exp $"; #endif /* not lint */ #include "gprof.h" @@ -64,7 +64,7 @@ printprof() flatprofline( np ); } actime = 0.0; - cfree( sortednlp ); + free( sortednlp ); } timecmp( npp1 , npp2 ) @@ -175,7 +175,7 @@ gprofline( np ) np -> propself / hz , np -> propchild / hz ); if ( ( np -> ncall + np -> selfcalls ) != 0 ) { - printf( " %7d" , np -> ncall ); + printf( " %7d" , np -> npropcall ); if ( np -> selfcalls != 0 ) { printf( "+%-7d " , np -> selfcalls ); } else { @@ -225,7 +225,7 @@ printgprof(timesortnlp) printf( "-----------------------------------------------\n" ); printf( "\n" ); } - cfree( timesortnlp ); + free( timesortnlp ); } /* @@ -290,7 +290,7 @@ printparents( childp ) sortparents( childp ); for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) { parentp = arcp -> arc_parentp; - if ( childp == parentp || + if ( childp == parentp || ( arcp -> arc_flags & DEADARC ) || ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) { /* * selfcall or call among siblings @@ -307,7 +307,7 @@ printparents( childp ) printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " , "" , "" , arcp -> arc_time / hz , arcp -> arc_childtime / hz , - arcp -> arc_count , cycleheadp -> ncall ); + arcp -> arc_count , cycleheadp -> npropcall ); printname( parentp ); printf( "\n" ); } @@ -324,7 +324,7 @@ printchildren( parentp ) arcp = parentp -> children; for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { childp = arcp -> arc_childp; - if ( childp == parentp || + if ( childp == parentp || ( arcp -> arc_flags & DEADARC ) || ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) { /* * self call or call to sibling @@ -340,7 +340,7 @@ printchildren( parentp ) 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 ); + arcp -> arc_count , childp -> cyclehead -> npropcall ); printname( childp ); printf( "\n" ); } @@ -468,7 +468,7 @@ printcycle( cyclep ) 100 * ( cyclep -> propself + cyclep -> propchild ) / printtime , cyclep -> propself / hz , cyclep -> propchild / hz , - cyclep -> ncall ); + cyclep -> npropcall ); if ( cyclep -> selfcalls != 0 ) { printf( "+%-7d" , cyclep -> selfcalls ); } else { @@ -490,7 +490,7 @@ printmembers( 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 ); + memberp -> npropcall ); if ( memberp -> selfcalls != 0 ) { printf( "+%-7d" , memberp -> selfcalls ); } else { @@ -715,5 +715,5 @@ printindex() } printf( "\n" ); } - cfree( namesortnlp ); + free( namesortnlp ); } diff --git a/usr.bin/gprof/printlist.c b/usr.bin/gprof/printlist.c index 18058039cbcf..b922ea0780d9 100644 --- a/usr.bin/gprof/printlist.c +++ b/usr.bin/gprof/printlist.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,8 +32,8 @@ */ #ifndef lint -/*static char sccsid[] = "from: @(#)printlist.c 5.5 (Berkeley) 6/1/90";*/ -static char rcsid[] = "$Id: printlist.c,v 1.2 1993/08/01 18:15:07 mycroft Exp $"; +/* from: static char sccsid[] = "@(#)printlist.c 8.1 (Berkeley) 6/6/93"; */ +static char *rcsid = "$Id: printlist.c,v 1.3 1994/05/17 03:36:29 cgd Exp $"; #endif /* not lint */ #include "gprof.h" diff --git a/usr.bin/gprof/sparc.c b/usr.bin/gprof/sparc.c index 513a5253bfc8..51f304ebdb63 100644 --- a/usr.bin/gprof/sparc.c +++ b/usr.bin/gprof/sparc.c @@ -36,7 +36,8 @@ */ #ifndef lint -static char sccsid[] = "@(#)sparc.c 8.1 (Berkeley) 6/6/93"; +/* from: static char sccsid[] = "@(#)sparc.c 8.1 (Berkeley) 6/6/93"; */ +static char *rcsid = "$Id: sparc.c,v 1.2 1994/05/17 03:36:31 cgd Exp $"; #endif /* not lint */ #include "gprof.h" diff --git a/usr.bin/gprof/sparc.h b/usr.bin/gprof/sparc.h index e2455eaa9f8a..0c03b0d4bc17 100644 --- a/usr.bin/gprof/sparc.h +++ b/usr.bin/gprof/sparc.h @@ -34,7 +34,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)sparc.h 8.1 (Berkeley) 6/6/93 + * from: @(#)sparc.h 8.1 (Berkeley) 6/6/93 + * $Id: sparc.h,v 1.2 1994/05/17 03:36:33 cgd Exp $ */ /* diff --git a/usr.bin/gprof/tahoe.c b/usr.bin/gprof/tahoe.c index bdc6147eb208..24f4a9a064e5 100644 --- a/usr.bin/gprof/tahoe.c +++ b/usr.bin/gprof/tahoe.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,8 +32,8 @@ */ #ifndef lint -/*static char sccsid[] = "from: @(#)tahoe.c 1.5 (Berkeley) 6/1/90";*/ -static char rcsid[] = "$Id: tahoe.c,v 1.2 1993/08/01 18:15:06 mycroft Exp $"; +/* from: static char sccsid[] = "@(#)tahoe.c 8.1 (Berkeley) 6/6/93"; */ +static char *rcsid = "$Id: tahoe.c,v 1.3 1994/05/17 03:36:34 cgd Exp $"; #endif /* not lint */ #include "gprof.h" diff --git a/usr.bin/gprof/tahoe.h b/usr.bin/gprof/tahoe.h index 80708feb92d6..c4244fbd1905 100644 --- a/usr.bin/gprof/tahoe.h +++ b/usr.bin/gprof/tahoe.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,8 +30,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)tahoe.h 1.4 (Berkeley) 6/1/90 - * $Id: tahoe.h,v 1.2 1993/08/01 18:15:15 mycroft Exp $ + * from: @(#)tahoe.h 8.1 (Berkeley) 6/6/93 + * $Id: tahoe.h,v 1.3 1994/05/17 03:36:36 cgd Exp $ */ /* diff --git a/usr.bin/gprof/vax.c b/usr.bin/gprof/vax.c index c1cc97b25de6..534f7a75501b 100644 --- a/usr.bin/gprof/vax.c +++ b/usr.bin/gprof/vax.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,8 +32,8 @@ */ #ifndef lint -/*static char sccsid[] = "from: @(#)vax.c 5.6 (Berkeley) 6/1/90";*/ -static char rcsid[] = "$Id: vax.c,v 1.2 1993/08/01 18:15:04 mycroft Exp $"; +/* from: static char sccsid[] = "@(#)vax.c 8.1 (Berkeley) 6/6/93"; */ +static char *rcsid = "$Id: vax.c,v 1.3 1994/05/17 03:36:37 cgd Exp $"; #endif /* not lint */ #include "gprof.h" diff --git a/usr.bin/gprof/vax.h b/usr.bin/gprof/vax.h index b193cb389996..683689e12b69 100644 --- a/usr.bin/gprof/vax.h +++ b/usr.bin/gprof/vax.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,8 +30,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)vax.h 5.4 (Berkeley) 6/1/90 - * $Id: vax.h,v 1.2 1993/08/01 18:15:14 mycroft Exp $ + * from: @(#)vax.h 8.1 (Berkeley) 6/6/93 + * $Id: vax.h,v 1.3 1994/05/17 03:36:39 cgd Exp $ */ /*