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

📄 kgmon.c

📁 早期freebsd实现
💻 C
字号:
/* * Copyright (c) 1983, 1992, 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 * 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. */#ifndef lintstatic char copyright[] ="@(#) Copyright (c) 1983, 1992, 1993\n\	The Regents of the University of California.  All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)kgmon.c	8.1 (Berkeley) 6/6/93";#endif /* not lint */#include <sys/param.h>#include <sys/file.h>#include <sys/sysctl.h>#include <sys/gmon.h>#include <errno.h>#include <kvm.h>#include <limits.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <nlist.h>#include <ctype.h>#include <paths.h>struct nlist nl[] = {#define	N_GMONPARAM	0	{ "__gmonparam" },#define	N_PROFHZ	1	{ "_profhz" },	0,};struct kvmvars {	kvm_t	*kd;	struct gmonparam gpm;};int	bflag, hflag, kflag, rflag, pflag;int	debug = 0;void	setprof __P((struct kvmvars *kvp, int state));void	dumpstate __P((struct kvmvars *kvp));void	reset __P((struct kvmvars *kvp));intmain(int argc, char **argv){	extern char *optarg;	extern int optind;	int ch, mode, disp, accessmode;	struct kvmvars kvmvars;	char *system, *kmemf;	seteuid(getuid());	kmemf = NULL;	system = NULL;	while ((ch = getopt(argc, argv, "M:N:bhpr")) != EOF) {		switch((char)ch) {		case 'M':			kmemf = optarg;			kflag = 1;			break;		case 'N':			system = optarg;			break;		case 'b':			bflag = 1;			break;		case 'h':			hflag = 1;			break;		case 'p':			pflag = 1;			break;		case 'r':			rflag = 1;			break;		default:			(void)fprintf(stderr,			    "usage: kgmon [-bhrp] [-M core] [-N system]\n");			exit(1);		}	}	argc -= optind;	argv += optind;#define BACKWARD_COMPATIBILITY#ifdef	BACKWARD_COMPATIBILITY	if (*argv) {		system = *argv;		if (*++argv) {			kmemf = *argv;			++kflag;		}	}#endif	if (system == NULL)		system = _PATH_UNIX;	accessmode = openfiles(system, kmemf, &kvmvars);	mode = getprof(&kvmvars);	if (hflag)		disp = GMON_PROF_OFF;	else if (bflag)		disp = GMON_PROF_ON;	else		disp = mode;	if (pflag)		dumpstate(&kvmvars);	if (rflag)		reset(&kvmvars);	if (accessmode == O_RDWR)		setprof(&kvmvars, disp);	(void)fprintf(stdout, "kgmon: kernel profiling is %s.\n",		      disp == GMON_PROF_OFF ? "off" : "running");	return (0);}/* * Check that profiling is enabled and open any ncessary files. */openfiles(system, kmemf, kvp)	char *system;	char *kmemf;	struct kvmvars *kvp;{	int mib[3], state, size, openmode;	char errbuf[_POSIX2_LINE_MAX];	if (!kflag) {		mib[0] = CTL_KERN;		mib[1] = KERN_PROF;		mib[2] = GPROF_STATE;		size = sizeof state;		if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) {			(void)fprintf(stderr,			    "kgmon: profiling not defined in kernel.\n");			exit(20);		}		if (!(bflag || hflag || rflag ||		    (pflag && state == GMON_PROF_ON)))			return (O_RDONLY);		(void)seteuid(0);		if (sysctl(mib, 3, NULL, NULL, &state, size) >= 0)			return (O_RDWR);		(void)seteuid(getuid());		kern_readonly(state);		return (O_RDONLY);	}	openmode = (bflag || hflag || pflag || rflag) ? O_RDWR : O_RDONLY;	kvp->kd = kvm_openfiles(system, kmemf, NULL, openmode, errbuf);	if (kvp->kd == NULL) {		if (openmode == O_RDWR) {			openmode = O_RDONLY;			kvp->kd = kvm_openfiles(system, kmemf, NULL, O_RDONLY,			    errbuf);		}		if (kvp->kd == NULL) {			(void)fprintf(stderr, "kgmon: kvm_openfiles: %s\n",			    errbuf);			exit(2);		}		kern_readonly(GMON_PROF_ON);	}	if (kvm_nlist(kvp->kd, nl) < 0) {		(void)fprintf(stderr, "kgmon: %s: no namelist\n", system);		exit(3);	}	if (!nl[N_GMONPARAM].n_value) {		(void)fprintf(stderr,		    "kgmon: profiling not defined in kernel.\n");		exit(20);	}	return (openmode);}/* * Suppress options that require a writable kernel. */kern_readonly(mode)	int mode;{	(void)fprintf(stderr, "kgmon: kernel read-only: ");	if (pflag && mode == GMON_PROF_ON)		(void)fprintf(stderr, "data may be inconsistent\n");	if (rflag)		(void)fprintf(stderr, "-r supressed\n");	if (bflag)		(void)fprintf(stderr, "-b supressed\n");	if (hflag)		(void)fprintf(stderr, "-h supressed\n");	rflag = bflag = hflag = 0;}/* * Get the state of kernel profiling. */getprof(kvp)	struct kvmvars *kvp;{	int mib[3], size;	if (kflag) {		size = kvm_read(kvp->kd, nl[N_GMONPARAM].n_value, &kvp->gpm,		    sizeof kvp->gpm);	} else {		mib[0] = CTL_KERN;		mib[1] = KERN_PROF;		mib[2] = GPROF_GMONPARAM;		size = sizeof kvp->gpm;		if (sysctl(mib, 3, &kvp->gpm, &size, NULL, 0) < 0)			size = 0;	}	if (size != sizeof kvp->gpm) {		(void)fprintf(stderr, "kgmon: cannot get gmonparam: %s\n",		    kflag ? kvm_geterr(kvp->kd) : strerror(errno));		exit (4);	}	return (kvp->gpm.state);}/* * Enable or disable kernel profiling according to the state variable. */voidsetprof(kvp, state)	struct kvmvars *kvp;	int state;{	struct gmonparam *p = (struct gmonparam *)nl[N_GMONPARAM].n_value;	int mib[3], sz, oldstate;	sz = sizeof(state);	if (!kflag) {		mib[0] = CTL_KERN;		mib[1] = KERN_PROF;		mib[2] = GPROF_STATE;		if (sysctl(mib, 3, &oldstate, &sz, NULL, 0) < 0)			goto bad;		if (oldstate == state)			return;		(void)seteuid(0);		if (sysctl(mib, 3, NULL, NULL, &state, sz) >= 0) {			(void)seteuid(getuid());			return;		}		(void)seteuid(getuid());	} else if (kvm_write(kvp->kd, (u_long)&p->state, (void *)&state, sz) 	    == sz)		return;bad:	(void)fprintf(stderr, "kgmon: warning: cannot turn profiling %s\n",	    state == GMON_PROF_OFF ? "off" : "on");}/* * Build the gmon.out file. */voiddumpstate(kvp)	struct kvmvars *kvp;{	register FILE *fp;	struct rawarc rawarc;	struct tostruct *tos;	u_long frompc, addr;	u_short *froms, *tickbuf;	int mib[3], i;	struct gmonhdr h;	int fromindex, endfrom, toindex;	setprof(kvp, GMON_PROF_OFF);	fp = fopen("gmon.out", "w");	if (fp == 0) {		perror("gmon.out");		return;	}	/*	 * Build the gmon header and write it to a file.	 */	bzero(&h, sizeof(h));	h.lpc = kvp->gpm.lowpc;	h.hpc = kvp->gpm.highpc;	h.ncnt = kvp->gpm.kcountsize + sizeof(h);	h.version = GMONVERSION;	h.profrate = getprofhz(kvp);	fwrite((char *)&h, sizeof(h), 1, fp);	/*	 * Write out the tick buffer.	 */	mib[0] = CTL_KERN;	mib[1] = KERN_PROF;	if ((tickbuf = (u_short *)malloc(kvp->gpm.kcountsize)) == NULL) {		fprintf(stderr, "kgmon: cannot allocate kcount space\n");		exit (5);	}	if (kflag) {		i = kvm_read(kvp->kd, (u_long)kvp->gpm.kcount, (void *)tickbuf,		    kvp->gpm.kcountsize);	} else {		mib[2] = GPROF_COUNT;		i = kvp->gpm.kcountsize;		if (sysctl(mib, 3, tickbuf, &i, NULL, 0) < 0)			i = 0;	}	if (i != kvp->gpm.kcountsize) {		(void)fprintf(stderr, "kgmon: read ticks: read %u, got %d: %s",		    kvp->gpm.kcountsize, i,		    kflag ? kvm_geterr(kvp->kd) : strerror(errno));		exit(6);	}	if ((fwrite(tickbuf, kvp->gpm.kcountsize, 1, fp)) != 1) {		perror("kgmon: writing tocks to gmon.out");		exit(7);	}	free(tickbuf);	/*	 * Write out the arc info.	 */	if ((froms = (u_short *)malloc(kvp->gpm.fromssize)) == NULL) {		fprintf(stderr, "kgmon: cannot allocate froms space\n");		exit (8);	}	if (kflag) {		i = kvm_read(kvp->kd, (u_long)kvp->gpm.froms, (void *)froms,		    kvp->gpm.fromssize);	} else {		mib[2] = GPROF_FROMS;		i = kvp->gpm.fromssize;		if (sysctl(mib, 3, froms, &i, NULL, 0) < 0)			i = 0;	}	if (i != kvp->gpm.fromssize) {		(void)fprintf(stderr, "kgmon: read froms: read %u, got %d: %s",		    kvp->gpm.fromssize, i,		    kflag ? kvm_geterr(kvp->kd) : strerror(errno));		exit(9);	}	if ((tos = (struct tostruct *)malloc(kvp->gpm.tossize)) == NULL) {		fprintf(stderr, "kgmon: cannot allocate tos space\n");		exit(10);	}	if (kflag) {		i = kvm_read(kvp->kd, (u_long)kvp->gpm.tos, (void *)tos,		    kvp->gpm.tossize);	} else {		mib[2] = GPROF_TOS;		i = kvp->gpm.tossize;		if (sysctl(mib, 3, tos, &i, NULL, 0) < 0)			i = 0;	}	if (i != kvp->gpm.tossize) {		(void)fprintf(stderr, "kgmon: read tos: read %u, got %d: %s",		    kvp->gpm.tossize, i,		    kflag ? kvm_geterr(kvp->kd) : strerror(errno));		exit(11);	}	if (debug)		(void)fprintf(stderr, "kgmon: lowpc 0x%x, textsize 0x%x\n",			      kvp->gpm.lowpc, kvp->gpm.textsize);	endfrom = kvp->gpm.fromssize / sizeof(*froms);	for (fromindex = 0; fromindex < endfrom; ++fromindex) {		if (froms[fromindex] == 0)			continue;		frompc = (u_long)kvp->gpm.lowpc +		    (fromindex * kvp->gpm.hashfraction * sizeof(*froms));		for (toindex = froms[fromindex]; toindex != 0;		   toindex = tos[toindex].link) {			if (debug)			    (void)fprintf(stderr,			    "%s: [mcleanup] frompc 0x%x selfpc 0x%x count %d\n",			    "kgmon", frompc, tos[toindex].selfpc,			    tos[toindex].count);			rawarc.raw_frompc = frompc;			rawarc.raw_selfpc = (u_long)tos[toindex].selfpc;			rawarc.raw_count = tos[toindex].count;			fwrite((char *)&rawarc, sizeof(rawarc), 1, fp);		}	}	fclose(fp);}/* * Get the profiling rate. */intgetprofhz(kvp)	struct kvmvars *kvp;{	int mib[2], size, profrate;	struct clockinfo clockrate;	if (kflag) {		profrate = 1;		if (kvm_read(kvp->kd, nl[N_PROFHZ].n_value, &profrate,		    sizeof profrate) != sizeof profrate)			(void)fprintf(stderr, "kgmon: get clockrate: %s\n",				kvm_geterr(kvp->kd));		return (profrate);	}	mib[0] = CTL_KERN;	mib[1] = KERN_CLOCKRATE;	clockrate.profhz = 1;	size = sizeof clockrate;	if (sysctl(mib, 2, &clockrate, &size, NULL, 0) < 0)		(void)fprintf(stderr, "kgmon: get clockrate: %s\n",			strerror(errno));	return (clockrate.profhz);}/* * Reset the kernel profiling date structures. */voidreset(kvp)	struct kvmvars *kvp;{	char *zbuf;	u_long biggest;	int mib[3];	setprof(kvp, GMON_PROF_OFF);	biggest = kvp->gpm.kcountsize;	if (kvp->gpm.fromssize > biggest)		biggest = kvp->gpm.fromssize;	if (kvp->gpm.tossize > biggest)		biggest = kvp->gpm.tossize;	if ((zbuf = (char *)malloc(biggest)) == NULL) {		fprintf(stderr, "kgmon: cannot allocate zbuf space\n");		exit(12);	}	bzero(zbuf, biggest);	if (kflag) {		if (kvm_write(kvp->kd, (u_long)kvp->gpm.kcount, zbuf,		    kvp->gpm.kcountsize) != kvp->gpm.kcountsize) {			(void)fprintf(stderr, "kgmon: tickbuf zero: %s\n",			    kvm_geterr(kvp->kd));			exit(13);		}		if (kvm_write(kvp->kd, (u_long)kvp->gpm.froms, zbuf,		    kvp->gpm.fromssize) != kvp->gpm.fromssize) {			(void)fprintf(stderr, "kgmon: froms zero: %s\n",			    kvm_geterr(kvp->kd));			exit(14);		}		if (kvm_write(kvp->kd, (u_long)kvp->gpm.tos, zbuf,		    kvp->gpm.tossize) != kvp->gpm.tossize) {			(void)fprintf(stderr, "kgmon: tos zero: %s\n",			    kvm_geterr(kvp->kd));			exit(15);		}		return;	}	(void)seteuid(0);	mib[0] = CTL_KERN;	mib[1] = KERN_PROF;	mib[2] = GPROF_COUNT;	if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.kcountsize) < 0) {		(void)fprintf(stderr, "kgmon: tickbuf zero: %s\n",		    strerror(errno));		exit(13);	}	mib[2] = GPROF_FROMS;	if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.fromssize) < 0) {		(void)fprintf(stderr, "kgmon: froms zero: %s\n",		    strerror(errno));		exit(14);	}	mib[2] = GPROF_TOS;	if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.tossize) < 0) {		(void)fprintf(stderr, "kgmon: tos zero: %s\n",		    strerror(errno));		exit(15);	}	(void)seteuid(getuid());	free(zbuf);}

⌨️ 快捷键说明

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