/*
* 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. 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1983, 1992, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
do {
if (cpuid == -1)
on_cpu[0] = '\0';
else
snprintf(on_cpu, sizeof(on_cpu), " on cpu%d", cpuid);
mode = getprof(&kvmvars, cpuid);
if (hflag)
disp = GMON_PROF_OFF;
else if (bflag)
disp = GMON_PROF_ON;
else
disp = mode;
if (pflag)
dumpstate(&kvmvars, cpuid);
if (rflag)
reset(&kvmvars, cpuid);
if (accessmode == O_RDWR)
setprof(&kvmvars, disp, cpuid);
(void)fprintf(stdout, "%s: kernel profiling is %s%s.\n",
getprogname(), disp == GMON_PROF_OFF ? "off" : "running",
on_cpu);
} while (cflag_all && ++cpuid < ncpu);
return (0);
}
/*
* Check that profiling is enabled and open any necessary files.
*/
static int
openfiles(char *sys, char *kmemf, struct kvmvars *kvp)
{
int mib[3], state, openmode;
size_t size;
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)
err(EXIT_FAILURE, "profiling not defined in kernel");
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(sys, kmemf, NULL, openmode, errbuf);
if (kvp->kd == NULL) {
if (openmode == O_RDWR) {
openmode = O_RDONLY;
kvp->kd = kvm_openfiles(sys, kmemf, NULL, O_RDONLY,
errbuf);
}
if (kvp->kd == NULL)
errx(EXIT_FAILURE, "kvm_openfiles: %s", errbuf);
kern_readonly(GMON_PROF_ON);
}
if (kvm_nlist(kvp->kd, nl) < 0)
errx(EXIT_FAILURE, "%s: no namelist", sys);
if (!nl[N_GMONPARAM].n_value)
errx(EXIT_FAILURE, "profiling not defined in kernel");
return (openmode);
}
/*
* Suppress options that require a writable kernel.
*/
static void
kern_readonly(int mode)
{
(void)fprintf(stderr, "%s: kernel read-only: ", getprogname());
if (pflag && mode == GMON_PROF_ON)
(void)fprintf(stderr, "data may be inconsistent\n");
if (rflag)
(void)fprintf(stderr, "-r suppressed\n");
if (bflag)
(void)fprintf(stderr, "-b suppressed\n");
if (hflag)
(void)fprintf(stderr, "-h suppressed\n");
rflag = bflag = hflag = 0;
}
/*
* Get the state of kernel profiling.
*/
static int
getprof(struct kvmvars *kvp, int cpuid)
{
int mib[5], miblen, mibparam;
size_t size;
/*
* Enable or disable kernel profiling according to the state variable.
*/
static void
setprof(struct kvmvars *kvp, int state, int cpuid)
{
struct gmonparam *p = (struct gmonparam *)nl[N_GMONPARAM].n_value;
int mib[5], miblen, mibparam, oldstate;
size_t sz;