kgmon.c revision 134505
11553Srgrimes/* 21553Srgrimes * Copyright (c) 1983, 1992, 1993 31553Srgrimes * The Regents of the University of California. All rights reserved. 41553Srgrimes * 51553Srgrimes * Redistribution and use in source and binary forms, with or without 61553Srgrimes * modification, are permitted provided that the following conditions 71553Srgrimes * are met: 81553Srgrimes * 1. Redistributions of source code must retain the above copyright 91553Srgrimes * notice, this list of conditions and the following disclaimer. 101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111553Srgrimes * notice, this list of conditions and the following disclaimer in the 121553Srgrimes * documentation and/or other materials provided with the distribution. 131553Srgrimes * 4. Neither the name of the University nor the names of its contributors 141553Srgrimes * may be used to endorse or promote products derived from this software 151553Srgrimes * without specific prior written permission. 161553Srgrimes * 171553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271553Srgrimes * SUCH DAMAGE. 281553Srgrimes */ 291553Srgrimes 301553Srgrimes#ifndef lint 3129736Scharnierstatic const char copyright[] = 321553Srgrimes"@(#) Copyright (c) 1983, 1992, 1993\n\ 331553Srgrimes The Regents of the University of California. All rights reserved.\n"; 341553Srgrimes#endif /* not lint */ 351553Srgrimes 361553Srgrimes#ifndef lint 3729736Scharnier#if 0 381553Srgrimesstatic char sccsid[] = "@(#)kgmon.c 8.1 (Berkeley) 6/6/93"; 3929736Scharnier#endif 4029736Scharnierstatic const char rcsid[] = 4150479Speter "$FreeBSD: head/usr.sbin/kgmon/kgmon.c 134505 2004-08-30 03:11:46Z marcel $"; 421553Srgrimes#endif /* not lint */ 431553Srgrimes 441553Srgrimes#include <sys/param.h> 451553Srgrimes#include <sys/file.h> 4611937Sphk#include <sys/time.h> 471553Srgrimes#include <sys/sysctl.h> 481553Srgrimes#include <sys/gmon.h> 4929736Scharnier#include <ctype.h> 5029736Scharnier#include <err.h> 511553Srgrimes#include <errno.h> 521553Srgrimes#include <kvm.h> 531553Srgrimes#include <limits.h> 5429736Scharnier#include <nlist.h> 5529736Scharnier#include <paths.h> 5691009Sbde#include <stddef.h> 571553Srgrimes#include <stdio.h> 581553Srgrimes#include <stdlib.h> 591553Srgrimes#include <string.h> 6029736Scharnier#include <unistd.h> 611553Srgrimes 621553Srgrimesstruct nlist nl[] = { 631553Srgrimes#define N_GMONPARAM 0 641553Srgrimes { "__gmonparam" }, 651553Srgrimes#define N_PROFHZ 1 661553Srgrimes { "_profhz" }, 6729736Scharnier { NULL }, 681553Srgrimes}; 691553Srgrimes 701553Srgrimesstruct kvmvars { 711553Srgrimes kvm_t *kd; 721553Srgrimes struct gmonparam gpm; 731553Srgrimes}; 741553Srgrimes 7513107Sbdeint Bflag, bflag, hflag, kflag, rflag, pflag; 761553Srgrimesint debug = 0; 7799800Salfredint getprof(struct kvmvars *); 7899800Salfredint getprofhz(struct kvmvars *); 7999800Salfredvoid kern_readonly(int); 8099800Salfredint openfiles(char *, char *, struct kvmvars *); 8199800Salfredvoid setprof(struct kvmvars *kvp, int state); 8299800Salfredvoid dumpstate(struct kvmvars *kvp); 8399800Salfredvoid reset(struct kvmvars *kvp); 8499800Salfredstatic void usage(void); 851553Srgrimes 861553Srgrimesint 871553Srgrimesmain(int argc, char **argv) 881553Srgrimes{ 891553Srgrimes int ch, mode, disp, accessmode; 901553Srgrimes struct kvmvars kvmvars; 911553Srgrimes char *system, *kmemf; 921553Srgrimes 931553Srgrimes seteuid(getuid()); 941553Srgrimes kmemf = NULL; 951553Srgrimes system = NULL; 9624428Simp while ((ch = getopt(argc, argv, "M:N:Bbhpr")) != -1) { 971553Srgrimes switch((char)ch) { 981553Srgrimes 991553Srgrimes case 'M': 1001553Srgrimes kmemf = optarg; 1011553Srgrimes kflag = 1; 1021553Srgrimes break; 1031553Srgrimes 1041553Srgrimes case 'N': 1051553Srgrimes system = optarg; 1061553Srgrimes break; 1071553Srgrimes 10813107Sbde case 'B': 10913107Sbde Bflag = 1; 11013107Sbde break; 11113107Sbde 1121553Srgrimes case 'b': 1131553Srgrimes bflag = 1; 1141553Srgrimes break; 1151553Srgrimes 1161553Srgrimes case 'h': 1171553Srgrimes hflag = 1; 1181553Srgrimes break; 1191553Srgrimes 1201553Srgrimes case 'p': 1211553Srgrimes pflag = 1; 1221553Srgrimes break; 1231553Srgrimes 1241553Srgrimes case 'r': 1251553Srgrimes rflag = 1; 1261553Srgrimes break; 1271553Srgrimes 1281553Srgrimes default: 12929736Scharnier usage(); 1301553Srgrimes } 1311553Srgrimes } 1321553Srgrimes argc -= optind; 1331553Srgrimes argv += optind; 1341553Srgrimes 1351553Srgrimes#define BACKWARD_COMPATIBILITY 1361553Srgrimes#ifdef BACKWARD_COMPATIBILITY 1371553Srgrimes if (*argv) { 1381553Srgrimes system = *argv; 1391553Srgrimes if (*++argv) { 1401553Srgrimes kmemf = *argv; 1411553Srgrimes ++kflag; 1421553Srgrimes } 1431553Srgrimes } 1441553Srgrimes#endif 1451553Srgrimes if (system == NULL) 1463041Swollman system = (char *)getbootfile(); 1471553Srgrimes accessmode = openfiles(system, kmemf, &kvmvars); 1481553Srgrimes mode = getprof(&kvmvars); 1491553Srgrimes if (hflag) 1501553Srgrimes disp = GMON_PROF_OFF; 15113107Sbde else if (Bflag) 15213107Sbde disp = GMON_PROF_HIRES; 1531553Srgrimes else if (bflag) 1541553Srgrimes disp = GMON_PROF_ON; 1551553Srgrimes else 1561553Srgrimes disp = mode; 1571553Srgrimes if (pflag) 1581553Srgrimes dumpstate(&kvmvars); 1591553Srgrimes if (rflag) 1601553Srgrimes reset(&kvmvars); 1611553Srgrimes if (accessmode == O_RDWR) 1621553Srgrimes setprof(&kvmvars, disp); 1631553Srgrimes (void)fprintf(stdout, "kgmon: kernel profiling is %s.\n", 16413107Sbde disp == GMON_PROF_OFF ? "off" : 16513107Sbde disp == GMON_PROF_HIRES ? "running (high resolution)" : 16613107Sbde disp == GMON_PROF_ON ? "running" : 16713107Sbde disp == GMON_PROF_BUSY ? "busy" : 16813107Sbde disp == GMON_PROF_ERROR ? "off (error)" : 16913107Sbde "in an unknown state"); 1701553Srgrimes return (0); 1711553Srgrimes} 1721553Srgrimes 17329736Scharnierstatic void 17429736Scharnierusage() 17529736Scharnier{ 17629736Scharnier fprintf(stderr, "usage: kgmon [-Bbhrp] [-M core] [-N system]\n"); 17729736Scharnier exit(1); 17829736Scharnier} 17929736Scharnier 1801553Srgrimes/* 1811553Srgrimes * Check that profiling is enabled and open any ncessary files. 1821553Srgrimes */ 18329736Scharnierint 1841553Srgrimesopenfiles(system, kmemf, kvp) 1851553Srgrimes char *system; 1861553Srgrimes char *kmemf; 1871553Srgrimes struct kvmvars *kvp; 1881553Srgrimes{ 189100904Sjake size_t size; 190100904Sjake int mib[3], state, openmode; 1911553Srgrimes char errbuf[_POSIX2_LINE_MAX]; 1921553Srgrimes 1931553Srgrimes if (!kflag) { 1941553Srgrimes mib[0] = CTL_KERN; 1951553Srgrimes mib[1] = KERN_PROF; 1961553Srgrimes mib[2] = GPROF_STATE; 1971553Srgrimes size = sizeof state; 19829736Scharnier if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) 19929736Scharnier errx(20, "profiling not defined in kernel"); 20013107Sbde if (!(Bflag || bflag || hflag || rflag || 20113107Sbde (pflag && 20213107Sbde (state == GMON_PROF_HIRES || state == GMON_PROF_ON)))) 2031553Srgrimes return (O_RDONLY); 2041553Srgrimes (void)seteuid(0); 2051553Srgrimes if (sysctl(mib, 3, NULL, NULL, &state, size) >= 0) 2061553Srgrimes return (O_RDWR); 2071553Srgrimes (void)seteuid(getuid()); 2081553Srgrimes kern_readonly(state); 2091553Srgrimes return (O_RDONLY); 2101553Srgrimes } 21113107Sbde openmode = (Bflag || bflag || hflag || pflag || rflag) 21213107Sbde ? O_RDWR : O_RDONLY; 2131553Srgrimes kvp->kd = kvm_openfiles(system, kmemf, NULL, openmode, errbuf); 2141553Srgrimes if (kvp->kd == NULL) { 2151553Srgrimes if (openmode == O_RDWR) { 2161553Srgrimes openmode = O_RDONLY; 2171553Srgrimes kvp->kd = kvm_openfiles(system, kmemf, NULL, O_RDONLY, 2181553Srgrimes errbuf); 2191553Srgrimes } 22029736Scharnier if (kvp->kd == NULL) 22129736Scharnier errx(2, "kvm_openfiles: %s", errbuf); 2221553Srgrimes kern_readonly(GMON_PROF_ON); 2231553Srgrimes } 22429736Scharnier if (kvm_nlist(kvp->kd, nl) < 0) 22529736Scharnier errx(3, "%s: no namelist", system); 22629736Scharnier if (!nl[N_GMONPARAM].n_value) 22729736Scharnier errx(20, "profiling not defined in kernel"); 2281553Srgrimes return (openmode); 2291553Srgrimes} 2301553Srgrimes 2311553Srgrimes/* 2321553Srgrimes * Suppress options that require a writable kernel. 2331553Srgrimes */ 23429736Scharniervoid 2351553Srgrimeskern_readonly(mode) 2361553Srgrimes int mode; 2371553Srgrimes{ 2381553Srgrimes 2391553Srgrimes (void)fprintf(stderr, "kgmon: kernel read-only: "); 24013107Sbde if (pflag && (mode == GMON_PROF_HIRES || mode == GMON_PROF_ON)) 2411553Srgrimes (void)fprintf(stderr, "data may be inconsistent\n"); 2421553Srgrimes if (rflag) 2431553Srgrimes (void)fprintf(stderr, "-r supressed\n"); 24413107Sbde if (Bflag) 24513107Sbde (void)fprintf(stderr, "-B supressed\n"); 2461553Srgrimes if (bflag) 2471553Srgrimes (void)fprintf(stderr, "-b supressed\n"); 2481553Srgrimes if (hflag) 2491553Srgrimes (void)fprintf(stderr, "-h supressed\n"); 25013107Sbde rflag = Bflag = bflag = hflag = 0; 2511553Srgrimes} 2521553Srgrimes 2531553Srgrimes/* 2541553Srgrimes * Get the state of kernel profiling. 2551553Srgrimes */ 25629736Scharnierint 2571553Srgrimesgetprof(kvp) 2581553Srgrimes struct kvmvars *kvp; 2591553Srgrimes{ 260100904Sjake size_t size; 261100904Sjake int mib[3]; 2621553Srgrimes 2631553Srgrimes if (kflag) { 2641553Srgrimes size = kvm_read(kvp->kd, nl[N_GMONPARAM].n_value, &kvp->gpm, 2651553Srgrimes sizeof kvp->gpm); 2661553Srgrimes } else { 2671553Srgrimes mib[0] = CTL_KERN; 2681553Srgrimes mib[1] = KERN_PROF; 2691553Srgrimes mib[2] = GPROF_GMONPARAM; 2701553Srgrimes size = sizeof kvp->gpm; 2711553Srgrimes if (sysctl(mib, 3, &kvp->gpm, &size, NULL, 0) < 0) 2721553Srgrimes size = 0; 2731553Srgrimes } 27491009Sbde 27591009Sbde /* 27691009Sbde * Accept certain undersized "structs" from old kernels. We need 27791009Sbde * everything up to hashfraction, and want profrate and 27891009Sbde * histcounter_type. Assume that the kernel doesn't put garbage 27991009Sbde * in any padding that is returned instead of profrate and 28091009Sbde * histcounter_type. This is a bad assumption for dead kernels, 28191009Sbde * since kvm_read() will normally return garbage for bytes beyond 28291009Sbde * the end of the actual kernel struct, if any. 28391009Sbde */ 28491009Sbde if (size < offsetof(struct gmonparam, hashfraction) + 28591009Sbde sizeof(kvp->gpm.hashfraction) || size > sizeof(kvp->gpm)) 28629736Scharnier errx(4, "cannot get gmonparam: %s", 2871553Srgrimes kflag ? kvm_geterr(kvp->kd) : strerror(errno)); 28891009Sbde bzero((char *)&kvp->gpm + size, sizeof(kvp->gpm) - size); 28991009Sbde if (kvp->gpm.profrate == 0) 29091009Sbde kvp->gpm.profrate = getprofhz(kvp); 29191009Sbde#ifdef __i386__ 29291009Sbde if (kvp->gpm.histcounter_type == 0) { 29391009Sbde /* 29491009Sbde * This fixup only works for not-so-old i386 kernels. The 29591009Sbde * magic 16 is the kernel FUNCTION_ALIGNMENT. 64-bit 29691009Sbde * counters are signed; smaller counters are unsigned. 29791009Sbde */ 29891009Sbde kvp->gpm.histcounter_type = 16 / 29991009Sbde (kvp->gpm.textsize / kvp->gpm.kcountsize) * CHAR_BIT; 30091009Sbde if (kvp->gpm.histcounter_type == 64) 30191009Sbde kvp->gpm.histcounter_type = -64; 30291009Sbde } 30391009Sbde#endif 30491009Sbde 3051553Srgrimes return (kvp->gpm.state); 3061553Srgrimes} 3071553Srgrimes 3081553Srgrimes/* 3091553Srgrimes * Enable or disable kernel profiling according to the state variable. 3101553Srgrimes */ 3111553Srgrimesvoid 3121553Srgrimessetprof(kvp, state) 3131553Srgrimes struct kvmvars *kvp; 3141553Srgrimes int state; 3151553Srgrimes{ 3161553Srgrimes struct gmonparam *p = (struct gmonparam *)nl[N_GMONPARAM].n_value; 317100904Sjake size_t sz; 318100904Sjake int mib[3], oldstate; 3191553Srgrimes 3201553Srgrimes sz = sizeof(state); 3211553Srgrimes if (!kflag) { 3221553Srgrimes mib[0] = CTL_KERN; 3231553Srgrimes mib[1] = KERN_PROF; 3241553Srgrimes mib[2] = GPROF_STATE; 3251553Srgrimes if (sysctl(mib, 3, &oldstate, &sz, NULL, 0) < 0) 3261553Srgrimes goto bad; 3271553Srgrimes if (oldstate == state) 3281553Srgrimes return; 3291553Srgrimes (void)seteuid(0); 3301553Srgrimes if (sysctl(mib, 3, NULL, NULL, &state, sz) >= 0) { 3311553Srgrimes (void)seteuid(getuid()); 3321553Srgrimes return; 3331553Srgrimes } 3341553Srgrimes (void)seteuid(getuid()); 3358857Srgrimes } else if (kvm_write(kvp->kd, (u_long)&p->state, (void *)&state, sz) 3361553Srgrimes == sz) 3371553Srgrimes return; 3381553Srgrimesbad: 33929736Scharnier warnx("warning: cannot turn profiling %s", 3401553Srgrimes state == GMON_PROF_OFF ? "off" : "on"); 3411553Srgrimes} 3421553Srgrimes 3431553Srgrimes/* 3441553Srgrimes * Build the gmon.out file. 3451553Srgrimes */ 3461553Srgrimesvoid 3471553Srgrimesdumpstate(kvp) 3481553Srgrimes struct kvmvars *kvp; 3491553Srgrimes{ 3501553Srgrimes register FILE *fp; 3511553Srgrimes struct rawarc rawarc; 3521553Srgrimes struct tostruct *tos; 35329736Scharnier u_long frompc; 3541553Srgrimes u_short *froms, *tickbuf; 355100904Sjake size_t i; 356100904Sjake int mib[3]; 3571553Srgrimes struct gmonhdr h; 3581553Srgrimes int fromindex, endfrom, toindex; 3591553Srgrimes 3601553Srgrimes setprof(kvp, GMON_PROF_OFF); 3611553Srgrimes fp = fopen("gmon.out", "w"); 3621553Srgrimes if (fp == 0) { 36329736Scharnier warn("gmon.out"); 3641553Srgrimes return; 3651553Srgrimes } 3661553Srgrimes 3671553Srgrimes /* 3681553Srgrimes * Build the gmon header and write it to a file. 3691553Srgrimes */ 3701553Srgrimes bzero(&h, sizeof(h)); 3711553Srgrimes h.lpc = kvp->gpm.lowpc; 3721553Srgrimes h.hpc = kvp->gpm.highpc; 3731553Srgrimes h.ncnt = kvp->gpm.kcountsize + sizeof(h); 3741553Srgrimes h.version = GMONVERSION; 37513107Sbde h.profrate = kvp->gpm.profrate; 37691009Sbde h.histcounter_type = kvp->gpm.histcounter_type; 3771553Srgrimes fwrite((char *)&h, sizeof(h), 1, fp); 3781553Srgrimes 3791553Srgrimes /* 3801553Srgrimes * Write out the tick buffer. 3811553Srgrimes */ 3821553Srgrimes mib[0] = CTL_KERN; 3831553Srgrimes mib[1] = KERN_PROF; 38429736Scharnier if ((tickbuf = (u_short *)malloc(kvp->gpm.kcountsize)) == NULL) 38529736Scharnier errx(5, "cannot allocate kcount space"); 3861553Srgrimes if (kflag) { 3871553Srgrimes i = kvm_read(kvp->kd, (u_long)kvp->gpm.kcount, (void *)tickbuf, 3881553Srgrimes kvp->gpm.kcountsize); 3891553Srgrimes } else { 3901553Srgrimes mib[2] = GPROF_COUNT; 3911553Srgrimes i = kvp->gpm.kcountsize; 3921553Srgrimes if (sysctl(mib, 3, tickbuf, &i, NULL, 0) < 0) 3931553Srgrimes i = 0; 3941553Srgrimes } 39529736Scharnier if (i != kvp->gpm.kcountsize) 396134505Smarcel errx(6, "read ticks: read %lu, got %ld: %s", 397134505Smarcel kvp->gpm.kcountsize, (long)i, 3981553Srgrimes kflag ? kvm_geterr(kvp->kd) : strerror(errno)); 39929736Scharnier if ((fwrite(tickbuf, kvp->gpm.kcountsize, 1, fp)) != 1) 40029736Scharnier err(7, "writing tocks to gmon.out"); 4011553Srgrimes free(tickbuf); 4021553Srgrimes 4031553Srgrimes /* 4041553Srgrimes * Write out the arc info. 4051553Srgrimes */ 40629736Scharnier if ((froms = (u_short *)malloc(kvp->gpm.fromssize)) == NULL) 40729736Scharnier errx(8, "cannot allocate froms space"); 4081553Srgrimes if (kflag) { 4091553Srgrimes i = kvm_read(kvp->kd, (u_long)kvp->gpm.froms, (void *)froms, 4101553Srgrimes kvp->gpm.fromssize); 4111553Srgrimes } else { 4121553Srgrimes mib[2] = GPROF_FROMS; 4131553Srgrimes i = kvp->gpm.fromssize; 4141553Srgrimes if (sysctl(mib, 3, froms, &i, NULL, 0) < 0) 4151553Srgrimes i = 0; 4161553Srgrimes } 41729736Scharnier if (i != kvp->gpm.fromssize) 418134505Smarcel errx(9, "read froms: read %lu, got %ld: %s", 419134505Smarcel kvp->gpm.fromssize, (long)i, 4201553Srgrimes kflag ? kvm_geterr(kvp->kd) : strerror(errno)); 42129736Scharnier if ((tos = (struct tostruct *)malloc(kvp->gpm.tossize)) == NULL) 42229736Scharnier errx(10, "cannot allocate tos space"); 4231553Srgrimes if (kflag) { 4241553Srgrimes i = kvm_read(kvp->kd, (u_long)kvp->gpm.tos, (void *)tos, 4251553Srgrimes kvp->gpm.tossize); 4261553Srgrimes } else { 4271553Srgrimes mib[2] = GPROF_TOS; 4281553Srgrimes i = kvp->gpm.tossize; 4291553Srgrimes if (sysctl(mib, 3, tos, &i, NULL, 0) < 0) 4301553Srgrimes i = 0; 4311553Srgrimes } 43229736Scharnier if (i != kvp->gpm.tossize) 433134505Smarcel errx(11, "read tos: read %lu, got %ld: %s", 434134505Smarcel kvp->gpm.tossize, (long)i, 4351553Srgrimes kflag ? kvm_geterr(kvp->kd) : strerror(errno)); 4361553Srgrimes if (debug) 437134505Smarcel warnx("lowpc 0x%lx, textsize 0x%lx", 438134505Smarcel (unsigned long)kvp->gpm.lowpc, kvp->gpm.textsize); 4391553Srgrimes endfrom = kvp->gpm.fromssize / sizeof(*froms); 4401553Srgrimes for (fromindex = 0; fromindex < endfrom; ++fromindex) { 4411553Srgrimes if (froms[fromindex] == 0) 4421553Srgrimes continue; 4431553Srgrimes frompc = (u_long)kvp->gpm.lowpc + 4441553Srgrimes (fromindex * kvp->gpm.hashfraction * sizeof(*froms)); 4451553Srgrimes for (toindex = froms[fromindex]; toindex != 0; 446134505Smarcel toindex = tos[toindex].link) { 4471553Srgrimes if (debug) 448134505Smarcel warnx("[mcleanup] frompc 0x%lx selfpc 0x%lx " 449134505Smarcel "count %ld", frompc, tos[toindex].selfpc, 450134505Smarcel tos[toindex].count); 4511553Srgrimes rawarc.raw_frompc = frompc; 4521553Srgrimes rawarc.raw_selfpc = (u_long)tos[toindex].selfpc; 4531553Srgrimes rawarc.raw_count = tos[toindex].count; 4541553Srgrimes fwrite((char *)&rawarc, sizeof(rawarc), 1, fp); 4551553Srgrimes } 4561553Srgrimes } 4571553Srgrimes fclose(fp); 4581553Srgrimes} 4591553Srgrimes 4601553Srgrimes/* 4611553Srgrimes * Get the profiling rate. 4621553Srgrimes */ 4631553Srgrimesint 4641553Srgrimesgetprofhz(kvp) 4651553Srgrimes struct kvmvars *kvp; 4661553Srgrimes{ 467100904Sjake size_t size; 468100904Sjake int mib[2], profrate; 4691553Srgrimes struct clockinfo clockrate; 4701553Srgrimes 4711553Srgrimes if (kflag) { 4721553Srgrimes profrate = 1; 4731553Srgrimes if (kvm_read(kvp->kd, nl[N_PROFHZ].n_value, &profrate, 4741553Srgrimes sizeof profrate) != sizeof profrate) 47529736Scharnier warnx("get clockrate: %s", kvm_geterr(kvp->kd)); 4761553Srgrimes return (profrate); 4771553Srgrimes } 4781553Srgrimes mib[0] = CTL_KERN; 4791553Srgrimes mib[1] = KERN_CLOCKRATE; 4801553Srgrimes clockrate.profhz = 1; 4811553Srgrimes size = sizeof clockrate; 4821553Srgrimes if (sysctl(mib, 2, &clockrate, &size, NULL, 0) < 0) 48329736Scharnier warn("get clockrate"); 4841553Srgrimes return (clockrate.profhz); 4851553Srgrimes} 4861553Srgrimes 4871553Srgrimes/* 4881553Srgrimes * Reset the kernel profiling date structures. 4891553Srgrimes */ 4901553Srgrimesvoid 4911553Srgrimesreset(kvp) 4921553Srgrimes struct kvmvars *kvp; 4931553Srgrimes{ 4941553Srgrimes char *zbuf; 4951553Srgrimes u_long biggest; 4961553Srgrimes int mib[3]; 4971553Srgrimes 4981553Srgrimes setprof(kvp, GMON_PROF_OFF); 4991553Srgrimes 5001553Srgrimes biggest = kvp->gpm.kcountsize; 5011553Srgrimes if (kvp->gpm.fromssize > biggest) 5021553Srgrimes biggest = kvp->gpm.fromssize; 5031553Srgrimes if (kvp->gpm.tossize > biggest) 5041553Srgrimes biggest = kvp->gpm.tossize; 50529736Scharnier if ((zbuf = (char *)malloc(biggest)) == NULL) 50629736Scharnier errx(12, "cannot allocate zbuf space"); 5071553Srgrimes bzero(zbuf, biggest); 5081553Srgrimes if (kflag) { 5091553Srgrimes if (kvm_write(kvp->kd, (u_long)kvp->gpm.kcount, zbuf, 51029736Scharnier kvp->gpm.kcountsize) != kvp->gpm.kcountsize) 51129736Scharnier errx(13, "tickbuf zero: %s", kvm_geterr(kvp->kd)); 5121553Srgrimes if (kvm_write(kvp->kd, (u_long)kvp->gpm.froms, zbuf, 51329736Scharnier kvp->gpm.fromssize) != kvp->gpm.fromssize) 51429736Scharnier errx(14, "froms zero: %s", kvm_geterr(kvp->kd)); 5151553Srgrimes if (kvm_write(kvp->kd, (u_long)kvp->gpm.tos, zbuf, 51629736Scharnier kvp->gpm.tossize) != kvp->gpm.tossize) 51729736Scharnier errx(15, "tos zero: %s", kvm_geterr(kvp->kd)); 5181553Srgrimes return; 5191553Srgrimes } 5201553Srgrimes (void)seteuid(0); 5211553Srgrimes mib[0] = CTL_KERN; 5221553Srgrimes mib[1] = KERN_PROF; 5231553Srgrimes mib[2] = GPROF_COUNT; 52429736Scharnier if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.kcountsize) < 0) 52529736Scharnier err(13, "tickbuf zero"); 5261553Srgrimes mib[2] = GPROF_FROMS; 52729736Scharnier if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.fromssize) < 0) 52829736Scharnier err(14, "froms zero"); 5291553Srgrimes mib[2] = GPROF_TOS; 53029736Scharnier if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.tossize) < 0) 53129736Scharnier err(15, "tos zero"); 5321553Srgrimes (void)seteuid(getuid()); 5331553Srgrimes free(zbuf); 5341553Srgrimes} 535