Index: kern/init_main.c =================================================================== RCS file: /cvsroot/src/sys/kern/init_main.c,v retrieving revision 1.471 diff -p -u -r1.471 init_main.c --- kern/init_main.c 17 Oct 2015 13:52:52 -0000 1.471 +++ kern/init_main.c 25 Oct 2015 22:34:22 -0000 @@ -601,6 +601,8 @@ main(void) procinit_sysctl(); + scdebug_init(); + /* * Create process 1 (init(8)). We do this now, as Unix has * historically had init be process 1, and changing this would Index: kern/kern_xxx.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_xxx.c,v retrieving revision 1.72 diff -p -u -r1.72 kern_xxx.c --- kern/kern_xxx.c 1 Sep 2011 18:25:44 -0000 1.72 +++ kern/kern_xxx.c 25 Oct 2015 22:34:22 -0000 @@ -36,6 +36,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_xxx.c,v #ifdef _KERNEL_OPT #include "opt_syscall_debug.h" +#include "opt_kernhist.h" #endif #include @@ -49,6 +50,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_xxx.c,v #include #include #include +#include /* ARGSUSED */ int @@ -102,42 +104,134 @@ sys_reboot(struct lwp *l, const struct s #ifdef SYSCALL_DEBUG #define SCDEBUG_CALLS 0x0001 /* show calls */ #define SCDEBUG_RETURNS 0x0002 /* show returns */ -#define SCDEBUG_ALL 0x0004 /* even syscalls that are implemented */ +#define SCDEBUG_ALL 0x0004 /* even syscalls that are not implemented */ #define SCDEBUG_SHOWARGS 0x0008 /* show arguments to calls */ +#define SCDEBUG_KERNHIST 0x0010 /* use kernhist instead of printf */ -#if 0 -int scdebug = SCDEBUG_CALLS|SCDEBUG_RETURNS|SCDEBUG_SHOWARGS; +#ifndef SCDEBUG_DEFAULT +#define SCDEBUG_DEFAULT (SCDEBUG_CALLS|SCDEBUG_RETURNS|SCDEBUG_SHOWARGS) +#endif + +int scdebug = SCDEBUG_DEFAULT; + +#ifdef KERNHIST +KERNHIST_DEFINE(scdebughist); +#define SCDEBUG_KERNHIST_FUNC(a) KERNHIST_FUNC(a) +#define SCDEBUG_KERNHIST_CALLED(a) KERNHIST_CALLED(a) +#define SCDEBUG_KERNHIST_LOG(a,b,c,d,e,f) KERNHIST_LOG(a,b,c,d,e,f) +#else +#define SCDEBUG_KERNHIST_FUNC(a) /* nothing */ +#define SCDEBUG_KERNHIST_CALLED(a) /* nothing */ +#define SCDEBUG_KERNHIST_LOG(a,b,c,d,e,f) /* nothing */ +/* The non-kernhist support version can elide all this code easily. */ +#undef SCDEBUG_KERNHIST +#define SCDEBUG_KERNHIST 0 +#endif + +#ifdef __HAVE_MINIMAL_EMUL +#define CODE_NOT_OK(code, em) ((int)(code) < 0) #else -int scdebug = SCDEBUG_CALLS|SCDEBUG_RETURNS|SCDEBUG_SHOWARGS|SCDEBUG_ALL; +#define CODE_NOT_OK(code, em) (((int)(code) < 0) || \ + ((int)(code) >= (em)->e_nsysent)) #endif void scdebug_call(register_t code, const register_t args[]) { + SCDEBUG_KERNHIST_FUNC("scdebug_call"); struct lwp *l = curlwp; struct proc *p = l->l_proc; const struct sysent *sy; const struct emul *em; int i; - if (!(scdebug & SCDEBUG_CALLS)) + if ((scdebug & SCDEBUG_CALLS) == 0) return; + if (scdebug & SCDEBUG_KERNHIST) + SCDEBUG_KERNHIST_CALLED(scdebughist); + em = p->p_emul; sy = &em->e_sysent[code]; - if (!(scdebug & SCDEBUG_ALL || (int)code < 0 -#ifndef __HAVE_MINIMAL_EMUL - || code >= em->e_nsysent -#endif - || sy->sy_call == sys_nosys)) + + if ((scdebug & SCDEBUG_ALL) == 0 && + (CODE_NOT_OK(code, em) || sy->sy_call == sys_nosys)) { + if (scdebug & SCDEBUG_KERNHIST) + SCDEBUG_KERNHIST_LOG(scdebughist, "", 0, 0, 0, 0); + return; + } + + /* + * The kernhist version of scdebug needs to restrict the usage + * compared to the normal version. histories must avoid these + * sorts of usage: + * + * - the format string *must* be literal, as it is used + * at display time in the kernel or userland + * - strings in the format will cause vmstat -u to crash + * so avoid using %s formats + * + * to avoid these, we have a fairly long block to print args + * as the format needs to change for each, and we can't just + * call printf() on each argument until we're done. + */ + if (scdebug & SCDEBUG_KERNHIST) { + if (CODE_NOT_OK(code, em)) { + SCDEBUG_KERNHIST_LOG(scdebughist, + "pid %d:%d: OUT OF RANGE (%ld)", + p->p_pid, l->l_lid, code, 0); + } else { + SCDEBUG_KERNHIST_LOG(scdebughist, + "pid %d:%d: num %d call %p", + p->p_pid, l->l_lid, code, sy->sy_call); + if ((scdebug & SCDEBUG_SHOWARGS) == 0) + return; + + if (sy->sy_narg > 7) { + SCDEBUG_KERNHIST_LOG(scdebughist, + "args[4-7]: (%lx, %lx, %lx, %lx, ...)", + (long)args[4], (long)args[5], + (long)args[6], (long)args[7]); + } else if (sy->sy_narg > 6) { + SCDEBUG_KERNHIST_LOG(scdebughist, + "args[4-6]: (%lx, %lx, %lx)", + (long)args[4], (long)args[5], + (long)args[6], 0); + } else if (sy->sy_narg > 5) { + SCDEBUG_KERNHIST_LOG(scdebughist, + "args[4-5]: (%lx, %lx)", + (long)args[4], (long)args[5], 0, 0); + } else if (sy->sy_narg == 5) { + SCDEBUG_KERNHIST_LOG(scdebughist, + "args[4]: (%lx)", + (long)args[4], 0, 0, 0); + } + + if (sy->sy_narg > 3) { + SCDEBUG_KERNHIST_LOG(scdebughist, + "args[0-3]: (%lx, %lx, %lx, %lx, ...)", + (long)args[0], (long)args[1], + (long)args[2], (long)args[3]); + } else if (sy->sy_narg > 2) { + SCDEBUG_KERNHIST_LOG(scdebughist, + "args[0-2]: (%lx, %lx, %lx)", + (long)args[0], (long)args[1], + (long)args[2], 0); + } else if (sy->sy_narg > 1) { + SCDEBUG_KERNHIST_LOG(scdebughist, + "args[0-1]: (%lx, %lx)", + (long)args[0], (long)args[1], 0, 0); + } else if (sy->sy_narg == 1) { + SCDEBUG_KERNHIST_LOG(scdebughist, + "args[0]: (%lx)", + (long)args[0], 0, 0, 0); + } + } return; + } printf("proc %d (%s): %s num ", p->p_pid, p->p_comm, em->e_name); - if ((int)code < 0 -#ifndef __HAVE_MINIMAL_EMUL - || code >= em->e_nsysent -#endif - ) + if (CODE_NOT_OK(code, em)) printf("OUT OF RANGE (%ld)", (long)code); else { printf("%ld call: %s", (long)code, em->e_syscallnames[code]); @@ -155,29 +249,45 @@ scdebug_call(register_t code, const regi void scdebug_ret(register_t code, int error, const register_t retval[]) { + SCDEBUG_KERNHIST_FUNC("scdebug_ret"); struct lwp *l = curlwp; struct proc *p = l->l_proc; const struct sysent *sy; const struct emul *em; - if (!(scdebug & SCDEBUG_RETURNS)) + if ((scdebug & SCDEBUG_RETURNS) == 0) return; + if (scdebug & SCDEBUG_KERNHIST) + SCDEBUG_KERNHIST_CALLED(scdebughist); + em = p->p_emul; sy = &em->e_sysent[code]; - if (!(scdebug & SCDEBUG_ALL || (int)code < 0 -#ifndef __HAVE_MINIMAL_EMUL - || (int)code >= em->e_nsysent -#endif - || sy->sy_call == sys_nosys)) + if ((scdebug & SCDEBUG_ALL) == 0 && + (CODE_NOT_OK(code, em) || sy->sy_call == sys_nosys)) { + if (scdebug & SCDEBUG_KERNHIST) + SCDEBUG_KERNHIST_LOG(scdebughist, "", 0, 0, 0, 0); + return; + } + + if (scdebug & SCDEBUG_KERNHIST) { + if (CODE_NOT_OK(code, em)) { + SCDEBUG_KERNHIST_LOG(scdebughist, + "pid %d:%d: OUT OF RANGE (%ld)", + p->p_pid, l->l_lid, code, 0); + } else { + SCDEBUG_KERNHIST_LOG(scdebughist, + "pid %d:%d: num %ld", + p->p_pid, l->l_lid, code, 0); + SCDEBUG_KERNHIST_LOG(scdebughist, + "ret: err = %d, rv = 0x%lx,0x%lx", + error, (long)retval[0], (long)retval[1], 0); + } return; + } printf("proc %d (%s): %s num ", p->p_pid, p->p_comm, em->e_name); - if ((int)code < 0 -#ifndef __HAVE_MINIMAL_EMUL - || code >= em->e_nsysent -#endif - ) + if (CODE_NOT_OK(code, em)) printf("OUT OF RANGE (%ld)", (long)code); else printf("%ld ret %s: err = %d, rv = 0x%lx,0x%lx", (long)code, @@ -186,3 +296,16 @@ scdebug_ret(register_t code, int error, printf("\n"); } #endif /* SYSCALL_DEBUG */ + +#ifndef SCDEBUG_KERNHIST_SIZE +#define SCDEBUG_KERNHIST_SIZE 500 +#endif + +void +scdebug_init(void) +{ +#if defined(SYSCALL_DEBUG) && defined(KERNHIST) + /* Setup scdebughist kernel history */ + KERNHIST_INIT(scdebughist, SCDEBUG_KERNHIST_SIZE); +#endif +} Index: sys/systm.h =================================================================== RCS file: /cvsroot/src/sys/sys/systm.h,v retrieving revision 1.268 diff -p -u -r1.268 systm.h --- sys/systm.h 28 Aug 2015 07:18:40 -0000 1.268 +++ sys/systm.h 25 Oct 2015 22:34:22 -0000 @@ -489,6 +489,7 @@ extern int db_fromconsole; /* XXX ddb/dd #endif /* _KERNEL */ /* For SYSCALL_DEBUG */ +void scdebug_init(void); void scdebug_call(register_t, const register_t[]); void scdebug_ret(register_t, int, const register_t[]);