136adb5cbScgd /* 2*7bb1d933Spk * Copyright (c) 1983, 1992, 1993 3*7bb1d933Spk * The Regents of the University of California. All rights reserved. 436adb5cbScgd * 536adb5cbScgd * Redistribution and use in source and binary forms, with or without 636adb5cbScgd * modification, are permitted provided that the following conditions 736adb5cbScgd * are met: 836adb5cbScgd * 1. Redistributions of source code must retain the above copyright 936adb5cbScgd * notice, this list of conditions and the following disclaimer. 1036adb5cbScgd * 2. Redistributions in binary form must reproduce the above copyright 1136adb5cbScgd * notice, this list of conditions and the following disclaimer in the 1236adb5cbScgd * documentation and/or other materials provided with the distribution. 1336adb5cbScgd * 3. All advertising materials mentioning features or use of this software 1436adb5cbScgd * must display the following acknowledgement: 1536adb5cbScgd * This product includes software developed by the University of 1636adb5cbScgd * California, Berkeley and its contributors. 1736adb5cbScgd * 4. Neither the name of the University nor the names of its contributors 1836adb5cbScgd * may be used to endorse or promote products derived from this software 1936adb5cbScgd * without specific prior written permission. 2036adb5cbScgd * 2136adb5cbScgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2236adb5cbScgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2336adb5cbScgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2436adb5cbScgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2536adb5cbScgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2636adb5cbScgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2736adb5cbScgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2836adb5cbScgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2936adb5cbScgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3036adb5cbScgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3136adb5cbScgd * SUCH DAMAGE. 3236adb5cbScgd */ 3336adb5cbScgd 3436adb5cbScgd #ifndef lint 35*7bb1d933Spk static char copyright[] = 36*7bb1d933Spk "@(#) Copyright (c) 1983, 1992, 1993\n\ 37*7bb1d933Spk The Regents of the University of California. All rights reserved.\n"; 3836adb5cbScgd #endif /* not lint */ 3936adb5cbScgd 4036adb5cbScgd #ifndef lint 41*7bb1d933Spk /* static char sccsid[] = "@(#)kgmon.c 8.1 (Berkeley) 6/6/93"; */ 42*7bb1d933Spk static char rcsid[] = "$Id"; 4336adb5cbScgd #endif /* not lint */ 4436adb5cbScgd 4536adb5cbScgd #include <sys/param.h> 4636adb5cbScgd #include <sys/file.h> 47*7bb1d933Spk #include <sys/sysctl.h> 48*7bb1d933Spk #include <sys/gmon.h> 49*7bb1d933Spk #include <errno.h> 50*7bb1d933Spk #include <kvm.h> 51*7bb1d933Spk #include <limits.h> 5236adb5cbScgd #include <stdio.h> 53*7bb1d933Spk #include <stdlib.h> 54*7bb1d933Spk #include <string.h> 5536adb5cbScgd #include <nlist.h> 5636adb5cbScgd #include <ctype.h> 5736adb5cbScgd #include <paths.h> 5836adb5cbScgd 5936adb5cbScgd struct nlist nl[] = { 60*7bb1d933Spk #define N_GMONPARAM 0 61*7bb1d933Spk { "__gmonparam" }, 62*7bb1d933Spk #define N_PROFHZ 1 63*7bb1d933Spk { "_profhz" }, 6436adb5cbScgd 0, 6536adb5cbScgd }; 6636adb5cbScgd 67*7bb1d933Spk struct kvmvars { 68*7bb1d933Spk kvm_t *kd; 69*7bb1d933Spk struct gmonparam gpm; 70*7bb1d933Spk }; 7136adb5cbScgd 7236adb5cbScgd int bflag, hflag, kflag, rflag, pflag; 7336adb5cbScgd int debug = 0; 74*7bb1d933Spk void setprof __P((struct kvmvars *kvp, int state)); 75*7bb1d933Spk void dumpstate __P((struct kvmvars *kvp)); 76*7bb1d933Spk void reset __P((struct kvmvars *kvp)); 7736adb5cbScgd 78*7bb1d933Spk int 79*7bb1d933Spk main(int argc, char **argv) 8036adb5cbScgd { 8136adb5cbScgd extern char *optarg; 8236adb5cbScgd extern int optind; 83*7bb1d933Spk int ch, mode, disp, accessmode; 84*7bb1d933Spk struct kvmvars kvmvars; 85*7bb1d933Spk char *system, *kmemf; 8636adb5cbScgd 87*7bb1d933Spk seteuid(getuid()); 88*7bb1d933Spk kmemf = NULL; 89*7bb1d933Spk system = NULL; 90*7bb1d933Spk while ((ch = getopt(argc, argv, "M:N:bhpr")) != EOF) { 9136adb5cbScgd switch((char)ch) { 92*7bb1d933Spk 9336adb5cbScgd case 'M': 9436adb5cbScgd kmemf = optarg; 9536adb5cbScgd kflag = 1; 9636adb5cbScgd break; 97*7bb1d933Spk 9836adb5cbScgd case 'N': 9936adb5cbScgd system = optarg; 10036adb5cbScgd break; 101*7bb1d933Spk 10236adb5cbScgd case 'b': 10336adb5cbScgd bflag = 1; 10436adb5cbScgd break; 105*7bb1d933Spk 10636adb5cbScgd case 'h': 10736adb5cbScgd hflag = 1; 10836adb5cbScgd break; 109*7bb1d933Spk 11036adb5cbScgd case 'p': 11136adb5cbScgd pflag = 1; 11236adb5cbScgd break; 113*7bb1d933Spk 11436adb5cbScgd case 'r': 11536adb5cbScgd rflag = 1; 11636adb5cbScgd break; 117*7bb1d933Spk 11836adb5cbScgd default: 11936adb5cbScgd (void)fprintf(stderr, 12036adb5cbScgd "usage: kgmon [-bhrp] [-M core] [-N system]\n"); 12136adb5cbScgd exit(1); 12236adb5cbScgd } 123*7bb1d933Spk } 12436adb5cbScgd argc -= optind; 12536adb5cbScgd argv += optind; 12636adb5cbScgd 12736adb5cbScgd #define BACKWARD_COMPATIBILITY 12836adb5cbScgd #ifdef BACKWARD_COMPATIBILITY 12936adb5cbScgd if (*argv) { 13036adb5cbScgd system = *argv; 13136adb5cbScgd if (*++argv) { 13236adb5cbScgd kmemf = *argv; 13336adb5cbScgd ++kflag; 13436adb5cbScgd } 13536adb5cbScgd } 13636adb5cbScgd #endif 137*7bb1d933Spk if (system == NULL) 138*7bb1d933Spk system = _PATH_UNIX; 139*7bb1d933Spk accessmode = openfiles(system, kmemf, &kvmvars); 140*7bb1d933Spk mode = getprof(&kvmvars); 141*7bb1d933Spk if (hflag) 142*7bb1d933Spk disp = GMON_PROF_OFF; 143*7bb1d933Spk else if (bflag) 144*7bb1d933Spk disp = GMON_PROF_ON; 145*7bb1d933Spk else 146*7bb1d933Spk disp = mode; 147*7bb1d933Spk if (pflag) 148*7bb1d933Spk dumpstate(&kvmvars); 149*7bb1d933Spk if (rflag) 150*7bb1d933Spk reset(&kvmvars); 151*7bb1d933Spk if (accessmode == O_RDWR) 152*7bb1d933Spk setprof(&kvmvars, disp); 153*7bb1d933Spk (void)fprintf(stdout, "kgmon: kernel profiling is %s.\n", 154*7bb1d933Spk disp == GMON_PROF_OFF ? "off" : "running"); 155*7bb1d933Spk return (0); 156*7bb1d933Spk } 15736adb5cbScgd 158*7bb1d933Spk /* 159*7bb1d933Spk * Check that profiling is enabled and open any ncessary files. 160*7bb1d933Spk */ 161*7bb1d933Spk openfiles(system, kmemf, kvp) 162*7bb1d933Spk char *system; 163*7bb1d933Spk char *kmemf; 164*7bb1d933Spk struct kvmvars *kvp; 165*7bb1d933Spk { 166*7bb1d933Spk int mib[3], state, size, openmode; 167*7bb1d933Spk char errbuf[_POSIX2_LINE_MAX]; 168*7bb1d933Spk 169*7bb1d933Spk if (!kflag) { 170*7bb1d933Spk mib[0] = CTL_KERN; 171*7bb1d933Spk mib[1] = KERN_PROF; 172*7bb1d933Spk mib[2] = GPROF_STATE; 173*7bb1d933Spk size = sizeof state; 174*7bb1d933Spk if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) { 175*7bb1d933Spk (void)fprintf(stderr, 176*7bb1d933Spk "kgmon: profiling not defined in kernel.\n"); 177*7bb1d933Spk exit(20); 178*7bb1d933Spk } 179*7bb1d933Spk if (!(bflag || hflag || rflag || 180*7bb1d933Spk (pflag && state == GMON_PROF_ON))) 181*7bb1d933Spk return (O_RDONLY); 182*7bb1d933Spk (void)seteuid(0); 183*7bb1d933Spk if (sysctl(mib, 3, NULL, NULL, &state, size) >= 0) 184*7bb1d933Spk return (O_RDWR); 185*7bb1d933Spk (void)seteuid(getuid()); 186*7bb1d933Spk kern_readonly(state); 187*7bb1d933Spk return (O_RDONLY); 188*7bb1d933Spk } 189*7bb1d933Spk openmode = (bflag || hflag || pflag || rflag) ? O_RDWR : O_RDONLY; 190*7bb1d933Spk kvp->kd = kvm_openfiles(system, kmemf, NULL, openmode, errbuf); 191*7bb1d933Spk if (kvp->kd == NULL) { 192*7bb1d933Spk if (openmode == O_RDWR) { 193*7bb1d933Spk openmode = O_RDONLY; 194*7bb1d933Spk kvp->kd = kvm_openfiles(system, kmemf, NULL, O_RDONLY, 195*7bb1d933Spk errbuf); 196*7bb1d933Spk } 197*7bb1d933Spk if (kvp->kd == NULL) { 198*7bb1d933Spk (void)fprintf(stderr, "kgmon: kvm_openfiles: %s\n", 199*7bb1d933Spk errbuf); 20036adb5cbScgd exit(2); 20136adb5cbScgd } 202*7bb1d933Spk kern_readonly(GMON_PROF_ON); 20336adb5cbScgd } 204*7bb1d933Spk if (kvm_nlist(kvp->kd, nl) < 0) { 205*7bb1d933Spk (void)fprintf(stderr, "kgmon: %s: no namelist\n", system); 20636adb5cbScgd exit(3); 20736adb5cbScgd } 208*7bb1d933Spk if (!nl[N_GMONPARAM].n_value) { 209*7bb1d933Spk (void)fprintf(stderr, 210*7bb1d933Spk "kgmon: profiling not defined in kernel.\n"); 211*7bb1d933Spk exit(20); 212*7bb1d933Spk } 213*7bb1d933Spk return (openmode); 214*7bb1d933Spk } 215*7bb1d933Spk 216*7bb1d933Spk /* 217*7bb1d933Spk * Suppress options that require a writable kernel. 218*7bb1d933Spk */ 219*7bb1d933Spk kern_readonly(mode) 220*7bb1d933Spk int mode; 221*7bb1d933Spk { 222*7bb1d933Spk 223*7bb1d933Spk (void)fprintf(stderr, "kgmon: kernel read-only: "); 224*7bb1d933Spk if (pflag && mode == GMON_PROF_ON) 225*7bb1d933Spk (void)fprintf(stderr, "data may be inconsistent\n"); 22636adb5cbScgd if (rflag) 22736adb5cbScgd (void)fprintf(stderr, "-r supressed\n"); 22836adb5cbScgd if (bflag) 22936adb5cbScgd (void)fprintf(stderr, "-b supressed\n"); 23036adb5cbScgd if (hflag) 23136adb5cbScgd (void)fprintf(stderr, "-h supressed\n"); 23236adb5cbScgd rflag = bflag = hflag = 0; 23336adb5cbScgd } 234e9d867efSmycroft 235*7bb1d933Spk /* 236*7bb1d933Spk * Get the state of kernel profiling. 237*7bb1d933Spk */ 238*7bb1d933Spk getprof(kvp) 239*7bb1d933Spk struct kvmvars *kvp; 240c78c6a22Smrg { 241*7bb1d933Spk int mib[3], size; 242*7bb1d933Spk 243*7bb1d933Spk if (kflag) { 244*7bb1d933Spk size = kvm_read(kvp->kd, nl[N_GMONPARAM].n_value, &kvp->gpm, 245*7bb1d933Spk sizeof kvp->gpm); 246*7bb1d933Spk } else { 247*7bb1d933Spk mib[0] = CTL_KERN; 248*7bb1d933Spk mib[1] = KERN_PROF; 249*7bb1d933Spk mib[2] = GPROF_GMONPARAM; 250*7bb1d933Spk size = sizeof kvp->gpm; 251*7bb1d933Spk if (sysctl(mib, 3, &kvp->gpm, &size, NULL, 0) < 0) 252*7bb1d933Spk size = 0; 253*7bb1d933Spk } 254*7bb1d933Spk if (size != sizeof kvp->gpm) { 255*7bb1d933Spk (void)fprintf(stderr, "kgmon: cannot get gmonparam: %s\n", 256*7bb1d933Spk kflag ? kvm_geterr(kvp->kd) : strerror(errno)); 257*7bb1d933Spk exit (4); 258*7bb1d933Spk } 259*7bb1d933Spk return (kvp->gpm.state); 260*7bb1d933Spk } 261*7bb1d933Spk 262*7bb1d933Spk /* 263*7bb1d933Spk * Enable or disable kernel profiling according to the state variable. 264*7bb1d933Spk */ 265*7bb1d933Spk void 266*7bb1d933Spk setprof(kvp, state) 267*7bb1d933Spk struct kvmvars *kvp; 268*7bb1d933Spk int state; 269*7bb1d933Spk { 270*7bb1d933Spk struct gmonparam *p = (struct gmonparam *)nl[N_GMONPARAM].n_value; 271*7bb1d933Spk int mib[3], sz, oldstate; 272*7bb1d933Spk 273*7bb1d933Spk sz = sizeof(state); 274*7bb1d933Spk if (!kflag) { 275*7bb1d933Spk mib[0] = CTL_KERN; 276*7bb1d933Spk mib[1] = KERN_PROF; 277*7bb1d933Spk mib[2] = GPROF_STATE; 278*7bb1d933Spk if (sysctl(mib, 3, &oldstate, &sz, NULL, 0) < 0) 279*7bb1d933Spk goto bad; 280*7bb1d933Spk if (oldstate == state) 281*7bb1d933Spk return; 282*7bb1d933Spk (void)seteuid(0); 283*7bb1d933Spk if (sysctl(mib, 3, NULL, NULL, &state, sz) >= 0) { 284*7bb1d933Spk (void)seteuid(getuid()); 285*7bb1d933Spk return; 286*7bb1d933Spk } 287*7bb1d933Spk (void)seteuid(getuid()); 288*7bb1d933Spk } else if (kvm_write(kvp->kd, (u_long)&p->state, (void *)&state, sz) 289*7bb1d933Spk == sz) 290*7bb1d933Spk return; 291*7bb1d933Spk bad: 292*7bb1d933Spk (void)fprintf(stderr, "kgmon: warning: cannot turn profiling %s\n", 293*7bb1d933Spk state == GMON_PROF_OFF ? "off" : "on"); 294*7bb1d933Spk } 295*7bb1d933Spk 296*7bb1d933Spk /* 297*7bb1d933Spk * Build the gmon.out file. 298*7bb1d933Spk */ 299*7bb1d933Spk void 300*7bb1d933Spk dumpstate(kvp) 301*7bb1d933Spk struct kvmvars *kvp; 302*7bb1d933Spk { 303*7bb1d933Spk register FILE *fp; 30436adb5cbScgd struct rawarc rawarc; 30536adb5cbScgd struct tostruct *tos; 306*7bb1d933Spk u_long frompc, addr; 307*7bb1d933Spk u_short *froms, *tickbuf; 308*7bb1d933Spk int mib[3], i; 309*7bb1d933Spk struct gmonhdr h; 310*7bb1d933Spk int fromindex, endfrom, toindex; 31136adb5cbScgd 312*7bb1d933Spk setprof(kvp, GMON_PROF_OFF); 313*7bb1d933Spk fp = fopen("gmon.out", "w"); 314*7bb1d933Spk if (fp == 0) { 31536adb5cbScgd perror("gmon.out"); 31636adb5cbScgd return; 31736adb5cbScgd } 318*7bb1d933Spk 319*7bb1d933Spk /* 320*7bb1d933Spk * Build the gmon header and write it to a file. 321*7bb1d933Spk */ 322*7bb1d933Spk bzero(&h, sizeof(h)); 323*7bb1d933Spk h.lpc = kvp->gpm.lowpc; 324*7bb1d933Spk h.hpc = kvp->gpm.highpc; 325*7bb1d933Spk h.ncnt = kvp->gpm.kcountsize + sizeof(h); 326*7bb1d933Spk h.version = GMONVERSION; 327*7bb1d933Spk h.profrate = getprofhz(kvp); 328*7bb1d933Spk fwrite((char *)&h, sizeof(h), 1, fp); 329*7bb1d933Spk 330*7bb1d933Spk /* 331*7bb1d933Spk * Write out the tick buffer. 332*7bb1d933Spk */ 333*7bb1d933Spk mib[0] = CTL_KERN; 334*7bb1d933Spk mib[1] = KERN_PROF; 335*7bb1d933Spk if ((tickbuf = (u_short *)malloc(kvp->gpm.kcountsize)) == NULL) { 336*7bb1d933Spk fprintf(stderr, "kgmon: cannot allocate kcount space\n"); 33736adb5cbScgd exit (5); 33836adb5cbScgd } 339*7bb1d933Spk if (kflag) { 340*7bb1d933Spk i = kvm_read(kvp->kd, (u_long)kvp->gpm.kcount, (void *)tickbuf, 341*7bb1d933Spk kvp->gpm.kcountsize); 342*7bb1d933Spk } else { 343*7bb1d933Spk mib[2] = GPROF_COUNT; 344*7bb1d933Spk i = kvp->gpm.kcountsize; 345*7bb1d933Spk if (sysctl(mib, 3, tickbuf, &i, NULL, 0) < 0) 346*7bb1d933Spk i = 0; 347*7bb1d933Spk } 348*7bb1d933Spk if (i != kvp->gpm.kcountsize) { 349*7bb1d933Spk (void)fprintf(stderr, "kgmon: read ticks: read %u, got %d: %s", 350*7bb1d933Spk kvp->gpm.kcountsize, i, 351*7bb1d933Spk kflag ? kvm_geterr(kvp->kd) : strerror(errno)); 35236adb5cbScgd exit(6); 35336adb5cbScgd } 354*7bb1d933Spk if ((fwrite(tickbuf, kvp->gpm.kcountsize, 1, fp)) != 1) { 355*7bb1d933Spk perror("kgmon: writing tocks to gmon.out"); 356*7bb1d933Spk exit(7); 357*7bb1d933Spk } 358*7bb1d933Spk free(tickbuf); 359*7bb1d933Spk 360*7bb1d933Spk /* 361*7bb1d933Spk * Write out the arc info. 362*7bb1d933Spk */ 363*7bb1d933Spk if ((froms = (u_short *)malloc(kvp->gpm.fromssize)) == NULL) { 364*7bb1d933Spk fprintf(stderr, "kgmon: cannot allocate froms space\n"); 365*7bb1d933Spk exit (8); 366*7bb1d933Spk } 367*7bb1d933Spk if (kflag) { 368*7bb1d933Spk i = kvm_read(kvp->kd, (u_long)kvp->gpm.froms, (void *)froms, 369*7bb1d933Spk kvp->gpm.fromssize); 370*7bb1d933Spk } else { 371*7bb1d933Spk mib[2] = GPROF_FROMS; 372*7bb1d933Spk i = kvp->gpm.fromssize; 373*7bb1d933Spk if (sysctl(mib, 3, froms, &i, NULL, 0) < 0) 374*7bb1d933Spk i = 0; 375*7bb1d933Spk } 376*7bb1d933Spk if (i != kvp->gpm.fromssize) { 377*7bb1d933Spk (void)fprintf(stderr, "kgmon: read froms: read %u, got %d: %s", 378*7bb1d933Spk kvp->gpm.fromssize, i, 379*7bb1d933Spk kflag ? kvm_geterr(kvp->kd) : strerror(errno)); 380*7bb1d933Spk exit(9); 381*7bb1d933Spk } 382*7bb1d933Spk if ((tos = (struct tostruct *)malloc(kvp->gpm.tossize)) == NULL) { 383*7bb1d933Spk fprintf(stderr, "kgmon: cannot allocate tos space\n"); 384*7bb1d933Spk exit(10); 385*7bb1d933Spk } 386*7bb1d933Spk if (kflag) { 387*7bb1d933Spk i = kvm_read(kvp->kd, (u_long)kvp->gpm.tos, (void *)tos, 388*7bb1d933Spk kvp->gpm.tossize); 389*7bb1d933Spk } else { 390*7bb1d933Spk mib[2] = GPROF_TOS; 391*7bb1d933Spk i = kvp->gpm.tossize; 392*7bb1d933Spk if (sysctl(mib, 3, tos, &i, NULL, 0) < 0) 393*7bb1d933Spk i = 0; 394*7bb1d933Spk } 395*7bb1d933Spk if (i != kvp->gpm.tossize) { 396*7bb1d933Spk (void)fprintf(stderr, "kgmon: read tos: read %u, got %d: %s", 397*7bb1d933Spk kvp->gpm.tossize, i, 398*7bb1d933Spk kflag ? kvm_geterr(kvp->kd) : strerror(errno)); 399*7bb1d933Spk exit(11); 400*7bb1d933Spk } 40136adb5cbScgd if (debug) 402*7bb1d933Spk (void)fprintf(stderr, "kgmon: lowpc 0x%x, textsize 0x%x\n", 403*7bb1d933Spk kvp->gpm.lowpc, kvp->gpm.textsize); 404*7bb1d933Spk endfrom = kvp->gpm.fromssize / sizeof(*froms); 405*7bb1d933Spk for (fromindex = 0; fromindex < endfrom; ++fromindex) { 40636adb5cbScgd if (froms[fromindex] == 0) 40736adb5cbScgd continue; 408*7bb1d933Spk frompc = (u_long)kvp->gpm.lowpc + 409*7bb1d933Spk (fromindex * kvp->gpm.hashfraction * sizeof(*froms)); 41036adb5cbScgd for (toindex = froms[fromindex]; toindex != 0; 41136adb5cbScgd toindex = tos[toindex].link) { 41236adb5cbScgd if (debug) 41336adb5cbScgd (void)fprintf(stderr, 414*7bb1d933Spk "%s: [mcleanup] frompc 0x%x selfpc 0x%x count %d\n", 415*7bb1d933Spk "kgmon", frompc, tos[toindex].selfpc, 416*7bb1d933Spk tos[toindex].count); 41736adb5cbScgd rawarc.raw_frompc = frompc; 41836adb5cbScgd rawarc.raw_selfpc = (u_long)tos[toindex].selfpc; 41936adb5cbScgd rawarc.raw_count = tos[toindex].count; 420*7bb1d933Spk fwrite((char *)&rawarc, sizeof(rawarc), 1, fp); 42136adb5cbScgd } 42236adb5cbScgd } 423*7bb1d933Spk fclose(fp); 42436adb5cbScgd } 42536adb5cbScgd 426*7bb1d933Spk /* 427*7bb1d933Spk * Get the profiling rate. 428*7bb1d933Spk */ 429*7bb1d933Spk int 430*7bb1d933Spk getprofhz(kvp) 431*7bb1d933Spk struct kvmvars *kvp; 43236adb5cbScgd { 433*7bb1d933Spk int mib[2], size, profrate; 434*7bb1d933Spk struct clockinfo clockrate; 43536adb5cbScgd 436*7bb1d933Spk if (kflag) { 437*7bb1d933Spk profrate = 1; 438*7bb1d933Spk if (kvm_read(kvp->kd, nl[N_PROFHZ].n_value, &profrate, 439*7bb1d933Spk sizeof profrate) != sizeof profrate) 440*7bb1d933Spk (void)fprintf(stderr, "kgmon: get clockrate: %s\n", 441*7bb1d933Spk kvm_geterr(kvp->kd)); 442*7bb1d933Spk return (profrate); 44336adb5cbScgd } 444*7bb1d933Spk mib[0] = CTL_KERN; 445*7bb1d933Spk mib[1] = KERN_CLOCKRATE; 446*7bb1d933Spk clockrate.profhz = 1; 447*7bb1d933Spk size = sizeof clockrate; 448*7bb1d933Spk if (sysctl(mib, 2, &clockrate, &size, NULL, 0) < 0) 449*7bb1d933Spk (void)fprintf(stderr, "kgmon: get clockrate: %s\n", 450*7bb1d933Spk strerror(errno)); 451*7bb1d933Spk return (clockrate.profhz); 45236adb5cbScgd } 45336adb5cbScgd 454*7bb1d933Spk /* 455*7bb1d933Spk * Reset the kernel profiling date structures. 456*7bb1d933Spk */ 457*7bb1d933Spk void 458*7bb1d933Spk reset(kvp) 459*7bb1d933Spk struct kvmvars *kvp; 46036adb5cbScgd { 461*7bb1d933Spk char *zbuf; 462*7bb1d933Spk u_long biggest; 463*7bb1d933Spk int mib[3]; 46436adb5cbScgd 465*7bb1d933Spk setprof(kvp, GMON_PROF_OFF); 46636adb5cbScgd 467*7bb1d933Spk biggest = kvp->gpm.kcountsize; 468*7bb1d933Spk if (kvp->gpm.fromssize > biggest) 469*7bb1d933Spk biggest = kvp->gpm.fromssize; 470*7bb1d933Spk if (kvp->gpm.tossize > biggest) 471*7bb1d933Spk biggest = kvp->gpm.tossize; 472*7bb1d933Spk if ((zbuf = (char *)malloc(biggest)) == NULL) { 473*7bb1d933Spk fprintf(stderr, "kgmon: cannot allocate zbuf space\n"); 47436adb5cbScgd exit(12); 47536adb5cbScgd } 476*7bb1d933Spk bzero(zbuf, biggest); 477*7bb1d933Spk if (kflag) { 478*7bb1d933Spk if (kvm_write(kvp->kd, (u_long)kvp->gpm.kcount, zbuf, 479*7bb1d933Spk kvp->gpm.kcountsize) != kvp->gpm.kcountsize) { 480*7bb1d933Spk (void)fprintf(stderr, "kgmon: tickbuf zero: %s\n", 481*7bb1d933Spk kvm_geterr(kvp->kd)); 48236adb5cbScgd exit(13); 48336adb5cbScgd } 484*7bb1d933Spk if (kvm_write(kvp->kd, (u_long)kvp->gpm.froms, zbuf, 485*7bb1d933Spk kvp->gpm.fromssize) != kvp->gpm.fromssize) { 486*7bb1d933Spk (void)fprintf(stderr, "kgmon: froms zero: %s\n", 487*7bb1d933Spk kvm_geterr(kvp->kd)); 488*7bb1d933Spk exit(14); 48936adb5cbScgd } 490*7bb1d933Spk if (kvm_write(kvp->kd, (u_long)kvp->gpm.tos, zbuf, 491*7bb1d933Spk kvp->gpm.tossize) != kvp->gpm.tossize) { 492*7bb1d933Spk (void)fprintf(stderr, "kgmon: tos zero: %s\n", 493*7bb1d933Spk kvm_geterr(kvp->kd)); 494*7bb1d933Spk exit(15); 49536adb5cbScgd } 496*7bb1d933Spk return; 497*7bb1d933Spk } 498*7bb1d933Spk (void)seteuid(0); 499*7bb1d933Spk mib[0] = CTL_KERN; 500*7bb1d933Spk mib[1] = KERN_PROF; 501*7bb1d933Spk mib[2] = GPROF_COUNT; 502*7bb1d933Spk if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.kcountsize) < 0) { 503*7bb1d933Spk (void)fprintf(stderr, "kgmon: tickbuf zero: %s\n", 504*7bb1d933Spk strerror(errno)); 505*7bb1d933Spk exit(13); 506*7bb1d933Spk } 507*7bb1d933Spk mib[2] = GPROF_FROMS; 508*7bb1d933Spk if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.fromssize) < 0) { 509*7bb1d933Spk (void)fprintf(stderr, "kgmon: froms zero: %s\n", 510*7bb1d933Spk strerror(errno)); 511*7bb1d933Spk exit(14); 512*7bb1d933Spk } 513*7bb1d933Spk mib[2] = GPROF_TOS; 514*7bb1d933Spk if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.tossize) < 0) { 515*7bb1d933Spk (void)fprintf(stderr, "kgmon: tos zero: %s\n", 516*7bb1d933Spk strerror(errno)); 517*7bb1d933Spk exit(15); 518*7bb1d933Spk } 519*7bb1d933Spk (void)seteuid(getuid()); 520*7bb1d933Spk free(zbuf); 52136adb5cbScgd } 522