xref: /original-bsd/usr.sbin/kgmon/kgmon.c (revision 8ac6efdd)
1736e8269Sdist /*
2*8ac6efddSbostic  * Copyright (c) 1983, 1992, 1993
3*8ac6efddSbostic  *	The Regents of the University of California.  All rights reserved.
4728bdb68Sbostic  *
5447c8eceSbostic  * %sccs.include.redist.c%
6736e8269Sdist  */
7736e8269Sdist 
8f48eab6eSmckusick #ifndef lint
9*8ac6efddSbostic static char copyright[] =
10*8ac6efddSbostic "@(#) Copyright (c) 1983, 1992, 1993\n\
11*8ac6efddSbostic 	The Regents of the University of California.  All rights reserved.\n";
127a8fb47cSbostic #endif /* not lint */
13736e8269Sdist 
14736e8269Sdist #ifndef lint
15*8ac6efddSbostic static char sccsid[] = "@(#)kgmon.c	8.1 (Berkeley) 06/06/93";
167a8fb47cSbostic #endif /* not lint */
17f48eab6eSmckusick 
18e5da617bSbostic #include <sys/param.h>
1928575745Ssam #include <sys/file.h>
20db37f21cSmckusick #include <sys/sysctl.h>
210628f878Smckusick #include <sys/gmon.h>
22a6612fadStorek #include <errno.h>
23a6612fadStorek #include <kvm.h>
24a6612fadStorek #include <limits.h>
25f48eab6eSmckusick #include <stdio.h>
26a6612fadStorek #include <stdlib.h>
27a6612fadStorek #include <string.h>
28f48eab6eSmckusick #include <nlist.h>
29f48eab6eSmckusick #include <ctype.h>
3017748e04Sbostic #include <paths.h>
31f48eab6eSmckusick 
32f48eab6eSmckusick struct nlist nl[] = {
330628f878Smckusick #define	N_GMONPARAM	0
340628f878Smckusick 	{ "__gmonparam" },
35532b2012Smckusick #define	N_PROFHZ	1
360628f878Smckusick 	{ "_profhz" },
37f48eab6eSmckusick 	0,
38f48eab6eSmckusick };
39f48eab6eSmckusick 
400b5c8bafSmckusick struct kvmvars {
41a6612fadStorek 	kvm_t	*kd;
420b5c8bafSmckusick 	struct gmonparam gpm;
430b5c8bafSmckusick };
440b5c8bafSmckusick 
456f37e4c3Smckusick int	bflag, hflag, kflag, rflag, pflag;
4656144cd9Smckusick int	debug = 0;
470b5c8bafSmckusick void	setprof __P((struct kvmvars *kvp, int state));
480b5c8bafSmckusick void	dumpstate __P((struct kvmvars *kvp));
490b5c8bafSmckusick void	reset __P((struct kvmvars *kvp));
500628f878Smckusick 
510628f878Smckusick int
main(int argc,char ** argv)520628f878Smckusick main(int argc, char **argv)
53f48eab6eSmckusick {
547a8fb47cSbostic 	extern char *optarg;
557a8fb47cSbostic 	extern int optind;
560b5c8bafSmckusick 	int ch, mode, disp, accessmode;
570b5c8bafSmckusick 	struct kvmvars kvmvars;
58a6612fadStorek 	char *system, *kmemf;
59f48eab6eSmckusick 
600b5c8bafSmckusick 	seteuid(getuid());
61a6612fadStorek 	kmemf = NULL;
62a6612fadStorek 	system = NULL;
630628f878Smckusick 	while ((ch = getopt(argc, argv, "M:N:bhpr")) != EOF) {
647a8fb47cSbostic 		switch((char)ch) {
650628f878Smckusick 
6696bcac15Sbostic 		case 'M':
6796bcac15Sbostic 			kmemf = optarg;
6896bcac15Sbostic 			kflag = 1;
6996bcac15Sbostic 			break;
700628f878Smckusick 
7196bcac15Sbostic 		case 'N':
7296bcac15Sbostic 			system = optarg;
7396bcac15Sbostic 			break;
740628f878Smckusick 
7556144cd9Smckusick 		case 'b':
7696bcac15Sbostic 			bflag = 1;
7756144cd9Smckusick 			break;
780628f878Smckusick 
7956144cd9Smckusick 		case 'h':
8096bcac15Sbostic 			hflag = 1;
8156144cd9Smckusick 			break;
820628f878Smckusick 
836f37e4c3Smckusick 		case 'p':
8496bcac15Sbostic 			pflag = 1;
857a8fb47cSbostic 			break;
860628f878Smckusick 
877a8fb47cSbostic 		case 'r':
8896bcac15Sbostic 			rflag = 1;
8956144cd9Smckusick 			break;
900628f878Smckusick 
9156144cd9Smckusick 		default:
92e5da617bSbostic 			(void)fprintf(stderr,
9396bcac15Sbostic 			    "usage: kgmon [-bhrp] [-M core] [-N system]\n");
9456144cd9Smckusick 			exit(1);
9556144cd9Smckusick 		}
960628f878Smckusick 	}
97104133aeSbostic 	argc -= optind;
98104133aeSbostic 	argv += optind;
997a8fb47cSbostic 
10096bcac15Sbostic #define BACKWARD_COMPATIBILITY
10196bcac15Sbostic #ifdef	BACKWARD_COMPATIBILITY
102104133aeSbostic 	if (*argv) {
103f48eab6eSmckusick 		system = *argv;
104104133aeSbostic 		if (*++argv) {
105f48eab6eSmckusick 			kmemf = *argv;
106104133aeSbostic 			++kflag;
107f48eab6eSmckusick 		}
1087a8fb47cSbostic 	}
10996bcac15Sbostic #endif
110a6612fadStorek 	if (system == NULL)
111a6612fadStorek 		system = _PATH_UNIX;
1120b5c8bafSmckusick 	accessmode = openfiles(system, kmemf, &kvmvars);
1130b5c8bafSmckusick 	mode = getprof(&kvmvars);
11456144cd9Smckusick 	if (hflag)
1150628f878Smckusick 		disp = GMON_PROF_OFF;
11656144cd9Smckusick 	else if (bflag)
1170628f878Smckusick 		disp = GMON_PROF_ON;
11856144cd9Smckusick 	else
119f45bb3e4Smckusick 		disp = mode;
1200b5c8bafSmckusick 	if (pflag)
1210b5c8bafSmckusick 		dumpstate(&kvmvars);
12256144cd9Smckusick 	if (rflag)
1230b5c8bafSmckusick 		reset(&kvmvars);
1240b5c8bafSmckusick 	if (accessmode == O_RDWR)
1250b5c8bafSmckusick 		setprof(&kvmvars, disp);
1260b5c8bafSmckusick 	(void)fprintf(stdout, "kgmon: kernel profiling is %s.\n",
1270628f878Smckusick 		      disp == GMON_PROF_OFF ? "off" : "running");
128a6612fadStorek 	return (0);
129a6612fadStorek }
1300b5c8bafSmckusick 
1310b5c8bafSmckusick /*
1320b5c8bafSmckusick  * Check that profiling is enabled and open any ncessary files.
1330b5c8bafSmckusick  */
openfiles(system,kmemf,kvp)1340b5c8bafSmckusick openfiles(system, kmemf, kvp)
1350b5c8bafSmckusick 	char *system;
1360b5c8bafSmckusick 	char *kmemf;
1370b5c8bafSmckusick 	struct kvmvars *kvp;
1380b5c8bafSmckusick {
1390b5c8bafSmckusick 	int mib[3], state, size, openmode;
1400b5c8bafSmckusick 	char errbuf[_POSIX2_LINE_MAX];
1410b5c8bafSmckusick 
1420b5c8bafSmckusick 	if (!kflag) {
1430b5c8bafSmckusick 		mib[0] = CTL_KERN;
1440b5c8bafSmckusick 		mib[1] = KERN_PROF;
1450b5c8bafSmckusick 		mib[2] = GPROF_STATE;
1460b5c8bafSmckusick 		size = sizeof state;
1470b5c8bafSmckusick 		if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) {
1480b5c8bafSmckusick 			(void)fprintf(stderr,
1490b5c8bafSmckusick 			    "kgmon: profiling not defined in kernel.\n");
1500b5c8bafSmckusick 			exit(20);
1510b5c8bafSmckusick 		}
1520b5c8bafSmckusick 		if (!(bflag || hflag || rflag ||
1530b5c8bafSmckusick 		    (pflag && state == GMON_PROF_ON)))
1540b5c8bafSmckusick 			return (O_RDONLY);
1550b5c8bafSmckusick 		(void)seteuid(0);
1560b5c8bafSmckusick 		if (sysctl(mib, 3, NULL, NULL, &state, size) >= 0)
1570b5c8bafSmckusick 			return (O_RDWR);
1580b5c8bafSmckusick 		(void)seteuid(getuid());
1590b5c8bafSmckusick 		kern_readonly(state);
1600b5c8bafSmckusick 		return (O_RDONLY);
1610b5c8bafSmckusick 	}
1620b5c8bafSmckusick 	openmode = (bflag || hflag || pflag || rflag) ? O_RDWR : O_RDONLY;
1630b5c8bafSmckusick 	kvp->kd = kvm_openfiles(system, kmemf, NULL, openmode, errbuf);
1640b5c8bafSmckusick 	if (kvp->kd == NULL) {
1650b5c8bafSmckusick 		if (openmode == O_RDWR) {
1660b5c8bafSmckusick 			openmode = O_RDONLY;
1670b5c8bafSmckusick 			kvp->kd = kvm_openfiles(system, kmemf, NULL, O_RDONLY,
1680b5c8bafSmckusick 			    errbuf);
1690b5c8bafSmckusick 		}
1700b5c8bafSmckusick 		if (kvp->kd == NULL) {
1710b5c8bafSmckusick 			(void)fprintf(stderr, "kgmon: kvm_openfiles: %s\n",
1720b5c8bafSmckusick 			    errbuf);
1730b5c8bafSmckusick 			exit(2);
1740b5c8bafSmckusick 		}
1750b5c8bafSmckusick 		kern_readonly(GMON_PROF_ON);
1760b5c8bafSmckusick 	}
1770b5c8bafSmckusick 	if (kvm_nlist(kvp->kd, nl) < 0) {
1780b5c8bafSmckusick 		(void)fprintf(stderr, "kgmon: %s: no namelist\n", system);
1790b5c8bafSmckusick 		exit(3);
1800b5c8bafSmckusick 	}
1810b5c8bafSmckusick 	if (!nl[N_GMONPARAM].n_value) {
1820b5c8bafSmckusick 		(void)fprintf(stderr,
1830b5c8bafSmckusick 		    "kgmon: profiling not defined in kernel.\n");
1840b5c8bafSmckusick 		exit(20);
1850b5c8bafSmckusick 	}
1860b5c8bafSmckusick 	return (openmode);
1870b5c8bafSmckusick }
1880b5c8bafSmckusick 
1890b5c8bafSmckusick /*
1900b5c8bafSmckusick  * Suppress options that require a writable kernel.
1910b5c8bafSmckusick  */
kern_readonly(mode)1920b5c8bafSmckusick kern_readonly(mode)
1930b5c8bafSmckusick 	int mode;
1940b5c8bafSmckusick {
1950b5c8bafSmckusick 
1960b5c8bafSmckusick 	(void)fprintf(stderr, "kgmon: kernel read-only: ");
1970b5c8bafSmckusick 	if (pflag && mode == GMON_PROF_ON)
1980b5c8bafSmckusick 		(void)fprintf(stderr, "data may be inconsistent\n");
1990b5c8bafSmckusick 	if (rflag)
2000b5c8bafSmckusick 		(void)fprintf(stderr, "-r supressed\n");
2010b5c8bafSmckusick 	if (bflag)
2020b5c8bafSmckusick 		(void)fprintf(stderr, "-b supressed\n");
2030b5c8bafSmckusick 	if (hflag)
2040b5c8bafSmckusick 		(void)fprintf(stderr, "-h supressed\n");
2050b5c8bafSmckusick 	rflag = bflag = hflag = 0;
2060b5c8bafSmckusick }
2070b5c8bafSmckusick 
2080b5c8bafSmckusick /*
2090b5c8bafSmckusick  * Get the state of kernel profiling.
2100b5c8bafSmckusick  */
2110b5c8bafSmckusick getprof(kvp)
2120b5c8bafSmckusick 	struct kvmvars *kvp;
2130b5c8bafSmckusick {
2140b5c8bafSmckusick 	int mib[3], size;
2150b5c8bafSmckusick 
2160b5c8bafSmckusick 	if (kflag) {
2170b5c8bafSmckusick 		size = kvm_read(kvp->kd, nl[N_GMONPARAM].n_value, &kvp->gpm,
2180b5c8bafSmckusick 		    sizeof kvp->gpm);
2190b5c8bafSmckusick 	} else {
2200b5c8bafSmckusick 		mib[0] = CTL_KERN;
2210b5c8bafSmckusick 		mib[1] = KERN_PROF;
2220b5c8bafSmckusick 		mib[2] = GPROF_GMONPARAM;
2230b5c8bafSmckusick 		size = sizeof kvp->gpm;
2240b5c8bafSmckusick 		if (sysctl(mib, 3, &kvp->gpm, &size, NULL, 0) < 0)
2250b5c8bafSmckusick 			size = 0;
2260b5c8bafSmckusick 	}
2270b5c8bafSmckusick 	if (size != sizeof kvp->gpm) {
2280b5c8bafSmckusick 		(void)fprintf(stderr, "kgmon: cannot get gmonparam: %s\n",
2290b5c8bafSmckusick 		    kflag ? kvm_geterr(kvp->kd) : strerror(errno));
2300b5c8bafSmckusick 		exit (4);
2310b5c8bafSmckusick 	}
2320b5c8bafSmckusick 	return (kvp->gpm.state);
2330b5c8bafSmckusick }
2340b5c8bafSmckusick 
2350b5c8bafSmckusick /*
2360b5c8bafSmckusick  * Enable or disable kernel profiling according to the state variable.
2370b5c8bafSmckusick  */
2380b5c8bafSmckusick void
setprof(kvp,state)2390b5c8bafSmckusick setprof(kvp, state)
2400b5c8bafSmckusick 	struct kvmvars *kvp;
2410b5c8bafSmckusick 	int state;
2420b5c8bafSmckusick {
2430b5c8bafSmckusick 	struct gmonparam *p = (struct gmonparam *)nl[N_GMONPARAM].n_value;
2440b5c8bafSmckusick 	int mib[3], sz, oldstate;
2450b5c8bafSmckusick 
2460b5c8bafSmckusick 	sz = sizeof(state);
2470b5c8bafSmckusick 	if (!kflag) {
2480b5c8bafSmckusick 		mib[0] = CTL_KERN;
2490b5c8bafSmckusick 		mib[1] = KERN_PROF;
2500b5c8bafSmckusick 		mib[2] = GPROF_STATE;
2510b5c8bafSmckusick 		if (sysctl(mib, 3, &oldstate, &sz, NULL, 0) < 0)
2520b5c8bafSmckusick 			goto bad;
2530b5c8bafSmckusick 		if (oldstate == state)
2540b5c8bafSmckusick 			return;
2550b5c8bafSmckusick 		(void)seteuid(0);
2560b5c8bafSmckusick 		if (sysctl(mib, 3, NULL, NULL, &state, sz) >= 0) {
2570b5c8bafSmckusick 			(void)seteuid(getuid());
2580b5c8bafSmckusick 			return;
2590b5c8bafSmckusick 		}
2600b5c8bafSmckusick 		(void)seteuid(getuid());
2610b5c8bafSmckusick 	} else if (kvm_write(kvp->kd, (u_long)&p->state, (void *)&state, sz)
2620b5c8bafSmckusick 	    == sz)
2630b5c8bafSmckusick 		return;
2640b5c8bafSmckusick bad:
2650b5c8bafSmckusick 	(void)fprintf(stderr, "kgmon: warning: cannot turn profiling %s\n",
2660b5c8bafSmckusick 	    state == GMON_PROF_OFF ? "off" : "on");
2670b5c8bafSmckusick }
2680b5c8bafSmckusick 
2690b5c8bafSmckusick /*
2700b5c8bafSmckusick  * Build the gmon.out file.
2710b5c8bafSmckusick  */
2720b5c8bafSmckusick void
dumpstate(kvp)2730b5c8bafSmckusick dumpstate(kvp)
2740b5c8bafSmckusick 	struct kvmvars *kvp;
2750b5c8bafSmckusick {
2760b5c8bafSmckusick 	register FILE *fp;
2770b5c8bafSmckusick 	struct rawarc rawarc;
2780b5c8bafSmckusick 	struct tostruct *tos;
2790b5c8bafSmckusick 	u_long frompc, addr;
2800b5c8bafSmckusick 	u_short *froms, *tickbuf;
2810b5c8bafSmckusick 	int mib[3], i;
2820b5c8bafSmckusick 	struct gmonhdr h;
2830b5c8bafSmckusick 	int fromindex, endfrom, toindex;
2840b5c8bafSmckusick 
2850b5c8bafSmckusick 	setprof(kvp, GMON_PROF_OFF);
2860b5c8bafSmckusick 	fp = fopen("gmon.out", "w");
2870b5c8bafSmckusick 	if (fp == 0) {
2880b5c8bafSmckusick 		perror("gmon.out");
2890b5c8bafSmckusick 		return;
2900b5c8bafSmckusick 	}
2910b5c8bafSmckusick 
2920b5c8bafSmckusick 	/*
2930b5c8bafSmckusick 	 * Build the gmon header and write it to a file.
2940b5c8bafSmckusick 	 */
2950b5c8bafSmckusick 	bzero(&h, sizeof(h));
2960b5c8bafSmckusick 	h.lpc = kvp->gpm.lowpc;
2970b5c8bafSmckusick 	h.hpc = kvp->gpm.highpc;
2980b5c8bafSmckusick 	h.ncnt = kvp->gpm.kcountsize + sizeof(h);
2990b5c8bafSmckusick 	h.version = GMONVERSION;
3000b5c8bafSmckusick 	h.profrate = getprofhz(kvp);
3010b5c8bafSmckusick 	fwrite((char *)&h, sizeof(h), 1, fp);
3020b5c8bafSmckusick 
3030b5c8bafSmckusick 	/*
3040b5c8bafSmckusick 	 * Write out the tick buffer.
3050b5c8bafSmckusick 	 */
3060b5c8bafSmckusick 	mib[0] = CTL_KERN;
3070b5c8bafSmckusick 	mib[1] = KERN_PROF;
3080b5c8bafSmckusick 	if ((tickbuf = (u_short *)malloc(kvp->gpm.kcountsize)) == NULL) {
3090b5c8bafSmckusick 		fprintf(stderr, "kgmon: cannot allocate kcount space\n");
3100b5c8bafSmckusick 		exit (5);
3110b5c8bafSmckusick 	}
3120b5c8bafSmckusick 	if (kflag) {
3130b5c8bafSmckusick 		i = kvm_read(kvp->kd, (u_long)kvp->gpm.kcount, (void *)tickbuf,
3140b5c8bafSmckusick 		    kvp->gpm.kcountsize);
3150b5c8bafSmckusick 	} else {
3160b5c8bafSmckusick 		mib[2] = GPROF_COUNT;
3170b5c8bafSmckusick 		i = kvp->gpm.kcountsize;
3180b5c8bafSmckusick 		if (sysctl(mib, 3, tickbuf, &i, NULL, 0) < 0)
3190b5c8bafSmckusick 			i = 0;
3200b5c8bafSmckusick 	}
3210b5c8bafSmckusick 	if (i != kvp->gpm.kcountsize) {
3220b5c8bafSmckusick 		(void)fprintf(stderr, "kgmon: read ticks: read %u, got %d: %s",
3230b5c8bafSmckusick 		    kvp->gpm.kcountsize, i,
3240b5c8bafSmckusick 		    kflag ? kvm_geterr(kvp->kd) : strerror(errno));
3250b5c8bafSmckusick 		exit(6);
3260b5c8bafSmckusick 	}
3270b5c8bafSmckusick 	if ((fwrite(tickbuf, kvp->gpm.kcountsize, 1, fp)) != 1) {
3280b5c8bafSmckusick 		perror("kgmon: writing tocks to gmon.out");
3290b5c8bafSmckusick 		exit(7);
3300b5c8bafSmckusick 	}
3310b5c8bafSmckusick 	free(tickbuf);
3320b5c8bafSmckusick 
3330b5c8bafSmckusick 	/*
3340b5c8bafSmckusick 	 * Write out the arc info.
3350b5c8bafSmckusick 	 */
3360b5c8bafSmckusick 	if ((froms = (u_short *)malloc(kvp->gpm.fromssize)) == NULL) {
3370b5c8bafSmckusick 		fprintf(stderr, "kgmon: cannot allocate froms space\n");
3380b5c8bafSmckusick 		exit (8);
3390b5c8bafSmckusick 	}
3400b5c8bafSmckusick 	if (kflag) {
3410b5c8bafSmckusick 		i = kvm_read(kvp->kd, (u_long)kvp->gpm.froms, (void *)froms,
3420b5c8bafSmckusick 		    kvp->gpm.fromssize);
3430b5c8bafSmckusick 	} else {
3440b5c8bafSmckusick 		mib[2] = GPROF_FROMS;
3450b5c8bafSmckusick 		i = kvp->gpm.fromssize;
3460b5c8bafSmckusick 		if (sysctl(mib, 3, froms, &i, NULL, 0) < 0)
3470b5c8bafSmckusick 			i = 0;
3480b5c8bafSmckusick 	}
3490b5c8bafSmckusick 	if (i != kvp->gpm.fromssize) {
3500b5c8bafSmckusick 		(void)fprintf(stderr, "kgmon: read froms: read %u, got %d: %s",
3510b5c8bafSmckusick 		    kvp->gpm.fromssize, i,
3520b5c8bafSmckusick 		    kflag ? kvm_geterr(kvp->kd) : strerror(errno));
3530b5c8bafSmckusick 		exit(9);
3540b5c8bafSmckusick 	}
3550b5c8bafSmckusick 	if ((tos = (struct tostruct *)malloc(kvp->gpm.tossize)) == NULL) {
3560b5c8bafSmckusick 		fprintf(stderr, "kgmon: cannot allocate tos space\n");
3570b5c8bafSmckusick 		exit(10);
3580b5c8bafSmckusick 	}
3590b5c8bafSmckusick 	if (kflag) {
3600b5c8bafSmckusick 		i = kvm_read(kvp->kd, (u_long)kvp->gpm.tos, (void *)tos,
3610b5c8bafSmckusick 		    kvp->gpm.tossize);
3620b5c8bafSmckusick 	} else {
3630b5c8bafSmckusick 		mib[2] = GPROF_TOS;
3640b5c8bafSmckusick 		i = kvp->gpm.tossize;
3650b5c8bafSmckusick 		if (sysctl(mib, 3, tos, &i, NULL, 0) < 0)
3660b5c8bafSmckusick 			i = 0;
3670b5c8bafSmckusick 	}
3680b5c8bafSmckusick 	if (i != kvp->gpm.tossize) {
3690b5c8bafSmckusick 		(void)fprintf(stderr, "kgmon: read tos: read %u, got %d: %s",
3700b5c8bafSmckusick 		    kvp->gpm.tossize, i,
3710b5c8bafSmckusick 		    kflag ? kvm_geterr(kvp->kd) : strerror(errno));
3720b5c8bafSmckusick 		exit(11);
3730b5c8bafSmckusick 	}
3740b5c8bafSmckusick 	if (debug)
3750b5c8bafSmckusick 		(void)fprintf(stderr, "kgmon: lowpc 0x%x, textsize 0x%x\n",
3760b5c8bafSmckusick 			      kvp->gpm.lowpc, kvp->gpm.textsize);
3770b5c8bafSmckusick 	endfrom = kvp->gpm.fromssize / sizeof(*froms);
3780b5c8bafSmckusick 	for (fromindex = 0; fromindex < endfrom; ++fromindex) {
3790b5c8bafSmckusick 		if (froms[fromindex] == 0)
3800b5c8bafSmckusick 			continue;
3810b5c8bafSmckusick 		frompc = (u_long)kvp->gpm.lowpc +
3820b5c8bafSmckusick 		    (fromindex * kvp->gpm.hashfraction * sizeof(*froms));
3830b5c8bafSmckusick 		for (toindex = froms[fromindex]; toindex != 0;
3840b5c8bafSmckusick 		   toindex = tos[toindex].link) {
3850b5c8bafSmckusick 			if (debug)
3860b5c8bafSmckusick 			    (void)fprintf(stderr,
3870b5c8bafSmckusick 			    "%s: [mcleanup] frompc 0x%x selfpc 0x%x count %d\n",
3880b5c8bafSmckusick 			    "kgmon", frompc, tos[toindex].selfpc,
3890b5c8bafSmckusick 			    tos[toindex].count);
3900b5c8bafSmckusick 			rawarc.raw_frompc = frompc;
3910b5c8bafSmckusick 			rawarc.raw_selfpc = (u_long)tos[toindex].selfpc;
3920b5c8bafSmckusick 			rawarc.raw_count = tos[toindex].count;
3930b5c8bafSmckusick 			fwrite((char *)&rawarc, sizeof(rawarc), 1, fp);
3940b5c8bafSmckusick 		}
3950b5c8bafSmckusick 	}
3960b5c8bafSmckusick 	fclose(fp);
3970b5c8bafSmckusick }
3980b5c8bafSmckusick 
3990b5c8bafSmckusick /*
4000b5c8bafSmckusick  * Get the profiling rate.
4010b5c8bafSmckusick  */
4020b5c8bafSmckusick int
getprofhz(kvp)4030b5c8bafSmckusick getprofhz(kvp)
4040b5c8bafSmckusick 	struct kvmvars *kvp;
4050b5c8bafSmckusick {
4060b5c8bafSmckusick 	int mib[2], size, profrate;
4070b5c8bafSmckusick 	struct clockinfo clockrate;
4080b5c8bafSmckusick 
4090b5c8bafSmckusick 	if (kflag) {
4100b5c8bafSmckusick 		profrate = 1;
4110b5c8bafSmckusick 		if (kvm_read(kvp->kd, nl[N_PROFHZ].n_value, &profrate,
4120b5c8bafSmckusick 		    sizeof profrate) != sizeof profrate)
4130b5c8bafSmckusick 			(void)fprintf(stderr, "kgmon: get clockrate: %s\n",
4140b5c8bafSmckusick 				kvm_geterr(kvp->kd));
4150b5c8bafSmckusick 		return (profrate);
4160b5c8bafSmckusick 	}
4170b5c8bafSmckusick 	mib[0] = CTL_KERN;
4180b5c8bafSmckusick 	mib[1] = KERN_CLOCKRATE;
4190b5c8bafSmckusick 	clockrate.profhz = 1;
4200b5c8bafSmckusick 	size = sizeof clockrate;
4210b5c8bafSmckusick 	if (sysctl(mib, 2, &clockrate, &size, NULL, 0) < 0)
4220b5c8bafSmckusick 		(void)fprintf(stderr, "kgmon: get clockrate: %s\n",
4230b5c8bafSmckusick 			strerror(errno));
4240b5c8bafSmckusick 	return (clockrate.profhz);
4250b5c8bafSmckusick }
4260b5c8bafSmckusick 
4270b5c8bafSmckusick /*
4280b5c8bafSmckusick  * Reset the kernel profiling date structures.
4290b5c8bafSmckusick  */
4300b5c8bafSmckusick void
reset(kvp)4310b5c8bafSmckusick reset(kvp)
4320b5c8bafSmckusick 	struct kvmvars *kvp;
4330b5c8bafSmckusick {
4340b5c8bafSmckusick 	char *zbuf;
4350b5c8bafSmckusick 	u_long biggest;
4360b5c8bafSmckusick 	int mib[3];
4370b5c8bafSmckusick 
4380b5c8bafSmckusick 	setprof(kvp, GMON_PROF_OFF);
4390b5c8bafSmckusick 
4400b5c8bafSmckusick 	biggest = kvp->gpm.kcountsize;
4410b5c8bafSmckusick 	if (kvp->gpm.fromssize > biggest)
4420b5c8bafSmckusick 		biggest = kvp->gpm.fromssize;
4430b5c8bafSmckusick 	if (kvp->gpm.tossize > biggest)
4440b5c8bafSmckusick 		biggest = kvp->gpm.tossize;
4450b5c8bafSmckusick 	if ((zbuf = (char *)malloc(biggest)) == NULL) {
4460b5c8bafSmckusick 		fprintf(stderr, "kgmon: cannot allocate zbuf space\n");
4470b5c8bafSmckusick 		exit(12);
4480b5c8bafSmckusick 	}
4490b5c8bafSmckusick 	bzero(zbuf, biggest);
4500b5c8bafSmckusick 	if (kflag) {
4510b5c8bafSmckusick 		if (kvm_write(kvp->kd, (u_long)kvp->gpm.kcount, zbuf,
4520b5c8bafSmckusick 		    kvp->gpm.kcountsize) != kvp->gpm.kcountsize) {
4530b5c8bafSmckusick 			(void)fprintf(stderr, "kgmon: tickbuf zero: %s\n",
4540b5c8bafSmckusick 			    kvm_geterr(kvp->kd));
4550b5c8bafSmckusick 			exit(13);
4560b5c8bafSmckusick 		}
4570b5c8bafSmckusick 		if (kvm_write(kvp->kd, (u_long)kvp->gpm.froms, zbuf,
4580b5c8bafSmckusick 		    kvp->gpm.fromssize) != kvp->gpm.fromssize) {
4590b5c8bafSmckusick 			(void)fprintf(stderr, "kgmon: froms zero: %s\n",
4600b5c8bafSmckusick 			    kvm_geterr(kvp->kd));
4610b5c8bafSmckusick 			exit(14);
4620b5c8bafSmckusick 		}
4630b5c8bafSmckusick 		if (kvm_write(kvp->kd, (u_long)kvp->gpm.tos, zbuf,
4640b5c8bafSmckusick 		    kvp->gpm.tossize) != kvp->gpm.tossize) {
4650b5c8bafSmckusick 			(void)fprintf(stderr, "kgmon: tos zero: %s\n",
4660b5c8bafSmckusick 			    kvm_geterr(kvp->kd));
4670b5c8bafSmckusick 			exit(15);
4680b5c8bafSmckusick 		}
4690b5c8bafSmckusick 		return;
4700b5c8bafSmckusick 	}
4710b5c8bafSmckusick 	(void)seteuid(0);
4720b5c8bafSmckusick 	mib[0] = CTL_KERN;
4730b5c8bafSmckusick 	mib[1] = KERN_PROF;
4740b5c8bafSmckusick 	mib[2] = GPROF_COUNT;
4750b5c8bafSmckusick 	if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.kcountsize) < 0) {
4760b5c8bafSmckusick 		(void)fprintf(stderr, "kgmon: tickbuf zero: %s\n",
4770b5c8bafSmckusick 		    strerror(errno));
4780b5c8bafSmckusick 		exit(13);
4790b5c8bafSmckusick 	}
4800b5c8bafSmckusick 	mib[2] = GPROF_FROMS;
4810b5c8bafSmckusick 	if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.fromssize) < 0) {
4820b5c8bafSmckusick 		(void)fprintf(stderr, "kgmon: froms zero: %s\n",
4830b5c8bafSmckusick 		    strerror(errno));
4840b5c8bafSmckusick 		exit(14);
4850b5c8bafSmckusick 	}
4860b5c8bafSmckusick 	mib[2] = GPROF_TOS;
4870b5c8bafSmckusick 	if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.tossize) < 0) {
4880b5c8bafSmckusick 		(void)fprintf(stderr, "kgmon: tos zero: %s\n",
4890b5c8bafSmckusick 		    strerror(errno));
4900b5c8bafSmckusick 		exit(15);
4910b5c8bafSmckusick 	}
4920b5c8bafSmckusick 	(void)seteuid(getuid());
4930b5c8bafSmckusick 	free(zbuf);
4940b5c8bafSmckusick }
495