⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gprof.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	    /*	     *	add this arc	     */	tally( &arc );    }    fclose(pfile);}FILE *openpfile(filename)    char *filename;{    struct gmonhdr	tmp;    FILE		*pfile;    int			size;    int			rate;    if((pfile = fopen(filename, "r")) == NULL) {	perror(filename);	done();    }    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();    }    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.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);}tally( rawp )    struct rawarc	*rawp;{    nltype		*parentp;    nltype		*childp;    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 ) ) {	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( &gmonhdr , sizeof gmonhdr , 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 longmin(a, b)    unsigned long a,b;{    if (a<b)	return(a);    return(b);}unsigned longmax(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;	}    }}boolfuncsymbol( nlistp )    struct nlist	*nlistp;{    extern char	*strtab;	/* string table from a.out */    extern int	aflag;		/* if static functions aren't desired */    char	*name, c;	/*	 *	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.	 *	need to make an exception for sparc .mul & co.	 *	perhaps we should just drop this code entirely...	 */    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;	}    }    return TRUE;}done(){    exit(0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -