A question about how to get trace record generated by KERNEL_DEBUG(...).
A question about how to get trace record generated by KERNEL_DEBUG(...).
- Subject: A question about how to get trace record generated by KERNEL_DEBUG(...).
- From: Sid Moore <email@hidden>
- Date: Tue, 06 Sep 2011 15:54:35 +0800
Hello, everyone.
I am a beginner of darwin kernel dev. I have a question and ask for
help. I found there are many kernel debug information generated by
KERNEL_DEBUG(...). For example, I want to trace the detailed info
about how NFS running, so those information are important to me. trace
record is identified by its debugid, which is a structured 32bit
object. in NFS, class is 0x03(DBG_FSYSTEM), subclass is
0x01(DBG_FSRW), code is defined in respective kernel functions. for
example, nfs_vnop_write() defines its code is 515 (0x0203). so, trace
record of nfs_vnop_write() is identified by the debugid 0x03010203.
I wrote a demo program, for fetching those trace record from kernel
via sysctl(3), but It doesn't work, no trace record with debugid
matched 0x0301XXXX. :-(
the program is listed below. please correct me if you found issues.
Thanks a lot. BTW, uname -a shows me "Darwin bogon 10.7.0 Darwin
Kernel Version 10.7.0".
/* gcc xx.c -o xx -I/Users/myself/mysourcecode/xnu-1504.15.3/bsd/sys/ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/uio.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <syslog.h>
#include <errno.h>
#include <getopt.h>
#include <libgen.h>
#include <signal.h>
#define PRIVATE
#define KERNEL_PRIVATE
#include "kdebug.h"
#undef KERNEL_PRIVATE
#undef PRIVATE
int trace_enabled = 0;
int set_remove_flag = 1;
int exiting = 0;
int pid = -1;
int miblen = CTL_MAXNAME;
int *mib = NULL;
char *progname = NULL; /* program name */
size_t oldlen = 0;
static void ukdbg_exit_handler(int);
static void ukdbg_exit(int, const char *);
static void ukdbg_setenable(int);
static void ukdbg_clear();
static void ukdbg_reinit();
static void ukdbg_setbuf(int);
static void ukdbg_getbuf(kbufinfo_t *);
static void ukdbg_setpidcheck(pid_t, int);
static void ukdbg_read(char *, size_t *);
static void ukdbg_setreg_valcheck(int val1, int val2, int val3, int val4);
static void ukdbg_entropy();
const unsigned int KDBG_FUNC_MASK = 0xfffffffc;
const unsigned int KDBG_CLASS_MASK = 0xff000000;
const unsigned int KDBG_CLASS_SHIFT = 24;
/* FSDBG code in NFS. Must be in order!! */
int CODE[] = {
260, 263, 264, 266, 267, 269,
273, 274, 275,
320, 321, 322, 323, 324, 325,
512, 513, 514, 515, 516, 518,
521, 524, 525, 526, 527, 528, 529,
530, 531, 532, 535, 536, 537, 538, 539,
540, 544, 545, 547, 548,
551, 554, 556, 557,
};
/* is a code interested? */
#define is_interest_code(c) \
({\
int i, j, n, ret=0;\
i = 0; j = sizeof(CODE)/sizeof(CODE[0])-1;\
while (i <= j) {\
n = i + (j-i+1)/2;\
if (CODE[n] > (c)) {\
j = n-1;\
} else if (CODE[n] < (c)) {\
i = n+1;\
} else {\
ret = 1;\
break;\
}\
}\
ret;\
})
int main(int argc, char *argv[])
{
char *progname = basename(argv[0]);
int err = 0;
int code = 0;
FILE *fp = stdout;
unsigned int elem = 65536;
size_t buflen = 0;
char *buf = NULL;
kd_buf *kd = NULL;
kbufinfo_t bufinfo = { 0, 0, 0, 0 };
int i, count;
long long sample_interval = 1000; /* us */
if (argc > 1)
pid = atoi(argv[1]);
mib = (int *)malloc(sizeof(int)*miblen);
if (NULL == mib) {
err = ENOMEM;
goto out;
}
memset(mib, 0, sizeof(int)*miblen);
signal(SIGHUP, ukdbg_exit_handler);
signal(SIGINT, ukdbg_exit_handler);
signal(SIGQUIT, ukdbg_exit_handler);
signal(SIGTERM, ukdbg_exit_handler);
buflen = elem * sizeof(kd_buf);
buf = (char *)malloc(buflen);
if (NULL == buf) {
err = ENOMEM;
goto out;
}
ukdbg_clear();
ukdbg_setbuf(elem);
ukdbg_reinit();
if (pid > 0)
ukdbg_setpidcheck(pid, 1);
for (i=0; i < sizeof(CODE)/sizeof(CODE[0]); i++) {
int c = FSDBG_CODE(DBG_FSRW, CODE[i]);
//ukdbg_setreg_valcheck(c, 0 , 0, 0);
}
ukdbg_setenable(1);
while (1) {
ukdbg_getbuf(&bufinfo); // Query information
oldlen = bufinfo.nkdbufs * sizeof(kd_buf); // How much to read?
ukdbg_read(buf, &oldlen); // Read that much
count = oldlen;
kd = (kd_buf *)buf;
for (i = 0; i < count; i++) {
char *qual = "";
unsigned long long cpu=0, now=0;
long thread;
int debugid, type, class;
thread = kd[i].arg5;
debugid = kd[i].debugid;
type = debugid & KDBG_FUNC_MASK;
class = (debugid & KDBG_CLASS_MASK) >> KDBG_CLASS_SHIFT;
//now = kd[i].timestamp & KDBG_TIMESTAMP_MASK;
//cpu = (kd[i].timestamp & KDBG_CPU_MASK) >> KDBG_CPU_SHIFT;
if (debugid <= 0)
continue;
//printf("x\n", debugid);
if (class != DBG_FSYSTEM)
continue;
if (debugid & DBG_FUNC_START)
qual = "DBG_FUNC_START";
else if (debugid & DBG_FUNC_END)
qual = "DBG_FUNC_END";
code = (debugid & 0xffff) >> 2;
//if (!is_interest_code(code)) {
// fprintf(stdout, ":-(\n");
// continue;
//}
fprintf(fp, "6Lx; lx; lx; lx; lx;"\
" lx; x.\n", kd[i].timestamp, \
(kd[i].arg1), (kd[i].arg2), (kd[i].arg3),\
(kd[i].arg4), (kd[i].arg5), kd[i].debugid);
}
usleep(sample_interval);
}
out:
if (buf)
free(buf);
if (mib)
free(mib);
fprintf(((0==err)? stdout:stderr), "'%s': exit(%d).\n",
progname, err);
exit(err);
}
void ukdbg_exit_handler(int s)
{
exiting = 1;
if (trace_enabled)
ukdbg_setenable(0);
if (pid > 0)
ukdbg_setpidcheck(pid, 0);
if (set_remove_flag)
ukdbg_clear();
fprintf(stderr, "cleaning up...\n");
exit(s);
}
void ukdbg_exit(int err, const char *msg)
{
fprintf(stderr, "%d: ", err);
if (msg)
perror(msg);
else
fprintf(stderr, "\n");
ukdbg_exit_handler(0);
}
void ukdbg_setenable(int enable)
{
memset(mib, 0, sizeof(int)*miblen);
mib[0] = CTL_KERN;
mib[1] = KERN_KDEBUG;
mib[2] = KERN_KDENABLE;
mib[3] = enable;
if ((sysctl(mib, 4, NULL, &oldlen, NULL, 0) < 0) && !exiting)
ukdbg_exit(errno, "ukdbg_setenable::sysctl");
trace_enabled = enable;
}
void ukdbg_clear(void)
{
memset(mib, 0, sizeof(int)*miblen);
mib[0] = CTL_KERN;
mib[1] = KERN_KDEBUG;
mib[2] = KERN_KDREMOVE;
if ((sysctl(mib, 3, NULL, &oldlen, NULL, 0) < 0) && !exiting) {
set_remove_flag = 0;
ukdbg_exit(errno, "ukdbg_clear::sysctl");
}
}
void ukdbg_reinit(void)
{
memset(mib, 0, sizeof(int)*miblen);
mib[0] = CTL_KERN;
mib[1] = KERN_KDEBUG;
mib[2] = KERN_KDSETUP;
if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) < 0) {
ukdbg_exit(errno, "ukdbg_reinit::sysctl");
}
}
void ukdbg_setbuf(int nbufs)
{
memset(mib, 0, sizeof(int)*miblen);
mib[0] = CTL_KERN;
mib[1] = KERN_KDEBUG;
mib[2] = KERN_KDSETBUF;
mib[3] = nbufs;
if (sysctl(mib, 4, NULL, &oldlen, NULL, 0) < 0) {
ukdbg_exit(errno, "ukdbg_setbuf::sysctl");
}
memset(mib, 0, sizeof(int)*miblen);
mib[0] = CTL_KERN;
mib[1] = KERN_KDEBUG;
mib[2] = KERN_KDSETUP;
mib[3] = 0;
mib[4] = 0;
mib[5] = 0;
if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) < 0) {
ukdbg_exit(errno, "ukdbg_setbuf2::sysctl");
}
}
void ukdbg_setpidcheck(pid_t pid, int check)
{
kd_regtype kr;
kr.type = KDBG_TYPENONE;
kr.value1 = pid;
kr.value2 = check;
oldlen = sizeof(kd_regtype);
memset(mib, 0, sizeof(int)*miblen);
mib[0] = CTL_KERN;
mib[1] = KERN_KDEBUG;
mib[2] = KERN_KDPIDTR;
if ((sysctl(mib, 3, &kr, &oldlen, NULL, 0) < 0) && !exiting) {
ukdbg_exit(errno, "ukdbg_setpidcheck::sysctl");
}
}
void ukdbg_setreg_valcheck(int val1, int val2, int val3, int val4)
{
kd_regtype kr;
kr.type = KDBG_VALCHECK;
kr.value1 = val1;
kr.value2 = val2;
kr.value3 = val3;
kr.value4 = val4;
oldlen = sizeof(kd_regtype);
memset(mib, 0, sizeof(int)*miblen);
mib[0] = CTL_KERN;
mib[1] = KERN_KDEBUG;
mib[2] = KERN_KDSETREG;
if (sysctl(mib, 3, &kr, &oldlen, NULL, 0) < 0) {
ukdbg_exit(errno, "ukdbg_setreg_valcheck::sysctl");
}
}
void ukdbg_getbuf(kbufinfo_t *bufinfop)
{
oldlen = sizeof(bufinfop);
memset(mib, 0, sizeof(int)*miblen);
mib[0] = CTL_KERN;
mib[1] = KERN_KDEBUG;
mib[2] = KERN_KDGETBUF;
if (sysctl(mib, 3, bufinfop, &oldlen, 0, 0) < 0) {
ukdbg_exit(errno, "ukdbg_getbuf::sysctl");
}
}
void ukdbg_read(char *buf, size_t *len)
{
memset(mib, 0, sizeof(int)*miblen);
mib[0] = CTL_KERN;
mib[1] = KERN_KDEBUG;
mib[2] = KERN_KDREADTR;
if (sysctl(mib, 3, buf, len, NULL, 0) < 0) {
ukdbg_exit(errno, "ukdbg_read::sysctl");
}
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-kernel mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden