* Copyright (c) 1983, 1992 The Regents of the University of California.
* %sccs.include.redist.c%
"@(#) Copyright (c) 1983, 1992 The Regents of the University of California.\n\
static char sccsid
[] = "@(#)kgmon.c 5.14 (Berkeley) %G%";
* We should call this _gmonparam for consistency, but that would cause a
* problem if we want to profile this program itself.
struct gmonparam gmonparam
;
int bflag
, hflag
, kflag
, rflag
, pflag
;
#define KREAD(kd, addr, s)\
kvm_read(kd, addr, (void *)(s), sizeof*(s)) != (sizeof*(s))
* Build the gmon header and write it to a file.
dumphdr(FILE *fp
, struct gmonparam
*p
, int ksize
)
/* zero out the unused fields */
h
.ncnt
= ksize
+ sizeof(h
);
fwrite((char *)&h
, sizeof(h
), 1, fp
);
* Dump a range of kernel memory to a file.
dumpbuf(FILE *fp
, u_long addr
, int cc
)
n
= MIN(cc
, sizeof(buf
));
if ((ret
= kvm_read(kd
, addr
, buf
, n
)) != n
) {
"kgmon: read kmem: read %d, got %d: %s\n",
if ((ret
= fwrite(buf
, n
, 1, fp
)) != 1) {
perror("kgmon: gmon.out");
* Enable or disable kernel profiling according to the state variable.
struct gmonparam
*p
= (struct gmonparam
*)nl
[N_GMONPARAM
].n_value
;
if (kvm_write(kd
, (u_long
)&p
->state
, (void *)&state
, sizeof(state
)) !=
"kgmon: warning: can't turn profiling %s\n",
state
== GMON_PROF_OFF
? "off" : "on");
* Build the gmon.out file.
dumpstate(struct gmonparam
*p
)
int fromindex
, endfrom
, toindex
;
u_int fromssize
, tossize
, ksize
;
fp
= fopen("gmon.out", "w");
ksize
= p
->textsize
/ HISTFRACTION
;
dumpbuf(fp
, (u_long
)kcount
, ksize
);
fromssize
= p
->textsize
/ HASHFRACTION
;
froms
= (u_short
*)malloc(fromssize
);
i
= kvm_read(kd
, (u_long
)p
->froms
, (void *)froms
, fromssize
);
(void)fprintf(stderr
, "kgmon: read kmem: read %u, got %d: %s",
fromssize
, i
, strerror(errno
));
tossize
= (p
->textsize
* ARCDENSITY
/ 100) * sizeof(struct tostruct
);
tos
= (struct tostruct
*)malloc(tossize
);
i
= kvm_read(kd
, (u_long
)p
->tos
, (void *)tos
, tossize
);
(void)fprintf(stderr
, "kgmon: read kmem: read %u, got %d: %s",
tossize
, i
, kvm_geterr(kd
));
(void)fprintf(stderr
, "lowpc 0x%x, textsize 0x%x\n",
endfrom
= fromssize
/ sizeof(*froms
);
for (fromindex
= 0; fromindex
< endfrom
; ++fromindex
) {
if (froms
[fromindex
] == 0)
frompc
= (u_long
)p
->lowpc
+
(fromindex
* HASHFRACTION
* sizeof(*froms
));
for (toindex
= froms
[fromindex
]; toindex
!= 0;
toindex
= tos
[toindex
].link
) {
"[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
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
);
* Zero out a region of kernel memory.
kzero(u_long addr
, int cc
)
static char zbuf
[MAXBSIZE
];
register int n
= MIN(cc
, sizeof(zbuf
));
if (kvm_write(kd
, addr
, zbuf
, n
) != n
)
* Reset the kernel profiling date structures.
reset(struct gmonparam
*p
)
int fromssize
, tossize
, ksize
;
ksize
= p
->textsize
/ HISTFRACTION
;
if (kzero((u_long
)kcount
, ksize
)) {
(void)fprintf(stderr
, "kgmon: sbuf write: %s\n",
fromssize
= p
->textsize
/ HASHFRACTION
;
if (kzero((u_long
)p
->froms
, fromssize
)) {
(void)fprintf(stderr
, "kgmon: kfroms write: %s\n",
tossize
= (p
->textsize
* ARCDENSITY
/ 100) * sizeof(struct tostruct
);
if (kzero((u_long
)p
->tos
, tossize
)) {
(void)fprintf(stderr
, "kgmon: ktos write: %s\n",
main(int argc
, char **argv
)
int ch
, mode
, disp
, openmode
;
char errbuf
[_POSIX2_LINE_MAX
];
while ((ch
= getopt(argc
, argv
, "M:N:bhpr")) != EOF
) {
"usage: kgmon [-bhrp] [-M core] [-N system]\n");
#define BACKWARD_COMPATIBILITY
#ifdef BACKWARD_COMPATIBILITY
openmode
= (bflag
|| hflag
|| pflag
|| rflag
) ? O_RDWR
: O_RDONLY
;
kd
= kvm_openfiles(system
, kmemf
, NULL
, openmode
, errbuf
);
if (openmode
== O_RDWR
) {
kd
= kvm_openfiles(system
, kmemf
, NULL
, O_RDONLY
,
(void)fprintf(stderr
, "kgmon: kvm_openfiles: %s\n",
(void)fprintf(stderr
, "kgmon: kernel opened read-only\n");
(void)fprintf(stderr
, "-r supressed\n");
(void)fprintf(stderr
, "-b supressed\n");
(void)fprintf(stderr
, "-h supressed\n");
rflag
= bflag
= hflag
= 0;
if (kvm_nlist(kd
, nl
) < 0) {
(void)fprintf(stderr
, "kgmon: %s: no namelist\n", system
);
if (!nl
[N_GMONPARAM
].n_value
) {
"kgmon: profiling not defined in kernel.\n");
if (KREAD(kd
, nl
[N_GMONPARAM
].n_value
, &gmonparam
))
"kgmon: read kmem: %s\n", kvm_geterr(kd
));
if (KREAD(kd
, nl
[N_KCOUNT
].n_value
, &kcount
))
(void)fprintf(stderr
, "kgmon: read kmem: %s\n",
if (KREAD(kd
, nl
[N_PROFHZ
].n_value
, &profhz
))
(void)fprintf(stderr
, "kgmon: read kmem: %s\n",
if (openmode
== O_RDONLY
&& mode
== GMON_PROF_ON
)
(void)fprintf(stderr
, "data may be inconsistent\n");
(void)fprintf(stdout
, "kernel profiling is %s.\n",
disp
== GMON_PROF_OFF
? "off" : "running");