Hi, The diff below implements utrace(2), a syscall to introduce data into a ktrace stream from a userland program.
The interface is taken from netbsd, freebsd also has a utrace(2) syscall, but lacks the label argument. You could uise this as a debugging aid, to get tarce information intermixed with sysclal info, or set more specific tracepoint and only see the utrace records. Do we want this? If so, this should be reviewed and tested. And a man page for utrace(2) should be written. Output of utrace("It is I", "some data", 10) looks like: 24413 a.out CALL utrace(0x500a09,0x5009ff,0xa) 24413 a.out USER It is I: 10 bytes "some data\0" 24413 a.out RET utrace 0 -Otto Index: lib/libc/sys/Makefile.inc =================================================================== RCS file: /cvs/src/lib/libc/sys/Makefile.inc,v retrieving revision 1.92 diff -u -p -r1.92 Makefile.inc --- lib/libc/sys/Makefile.inc 3 Jul 2010 04:44:51 -0000 1.92 +++ lib/libc/sys/Makefile.inc 12 Jul 2011 14:59:02 -0000 @@ -64,7 +64,7 @@ ASM= accept.o access.o acct.o adjfreq.o setuid.o shmat.o shmctl.o shmdt.o shmget.o shutdown.o sigaction.o \ sigaltstack.o socket.o socketpair.o stat.o statfs.o swapctl.o \ symlink.o sync.o sysarch.o umask.o unlink.o unmount.o \ - utimes.o wait4.o write.o writev.o nnpfspioctl.o __semctl.o \ + utimes.o utrace.o wait4.o write.o writev.o nnpfspioctl.o __semctl.o \ __syscall.o __sysctl.o __getcwd.o sched_yield.o getthrid.o \ thrsleep.o thrwakeup.o threxit.o thrsigdivert.o \ setrtable.o getrtable.o Index: lib/libc/sys/ktrace.2 =================================================================== RCS file: /cvs/src/lib/libc/sys/ktrace.2,v retrieving revision 1.20 diff -u -p -r1.20 ktrace.2 --- lib/libc/sys/ktrace.2 8 Jul 2011 19:30:32 -0000 1.20 +++ lib/libc/sys/ktrace.2 12 Jul 2011 14:59:02 -0000 @@ -94,6 +94,8 @@ generate much output). .It Dv KTRFAC_EMUL Trace emulation changes. .It Dv KTRFAC_CSW Trace context switch points. .It Dv KTRFAC_STRUCT Trace various structs +.It Dv KTRFAC_USER Trace user data coming from +.Xr utrace 2 .It Dv KTRFAC_INHERIT Inherit tracing to future children. .El .Pp @@ -174,7 +176,8 @@ No process can be found corresponding to .El .Sh SEE ALSO .Xr kdump 1 , -.Xr ktrace 1 +.Xr ktrace 1, +.Xr utrace 2 .Sh HISTORY A .Fn ktrace Index: sys/kern/init_sysent.c =================================================================== RCS file: /cvs/src/sys/kern/init_sysent.c,v retrieving revision 1.129 diff -u -p -r1.129 init_sysent.c --- sys/kern/init_sysent.c 9 Jul 2011 05:46:58 -0000 1.129 +++ sys/kern/init_sysent.c 12 Jul 2011 14:59:03 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: init_sysent.c,v 1.129 2011/07/09 05:46:58 matthew Exp $ */ +/* $OpenBSD$ */ /* * System call switch table. @@ -785,5 +785,12 @@ struct sysent sysent[] = { sys_unlinkat }, /* 325 = unlinkat */ { 4, s(struct sys_utimensat_args), 0, sys_utimensat }, /* 326 = utimensat */ +#ifdef KTRACE + { 3, s(struct sys_utrace_args), 0, + sys_utrace }, /* 327 = utrace */ +#else + { 0, 0, 0, + sys_nosys }, /* 327 = unimplemented utrace */ +#endif }; Index: sys/kern/kern_ktrace.c =================================================================== RCS file: /cvs/src/sys/kern/kern_ktrace.c,v retrieving revision 1.54 diff -u -p -r1.54 kern_ktrace.c --- sys/kern/kern_ktrace.c 11 Jul 2011 15:40:47 -0000 1.54 +++ sys/kern/kern_ktrace.c 12 Jul 2011 14:59:03 -0000 @@ -58,6 +58,7 @@ int ktrsetchildren(struct proc *, struct struct vnode *); int ktrwrite(struct proc *, struct ktr_header *); int ktrcanset(struct proc *, struct proc *); +int ktruser(struct proc *, const char *, void *, size_t, int); /* * Change the trace vnode in a correct way (to avoid races). @@ -297,6 +298,41 @@ ktrstruct(struct proc *p, const char *na p->p_traceflag &= ~KTRFAC_ACTIVE; } +int +ktruser(struct proc *p, const char *id, void *addr, size_t len, int ustr) +{ + struct ktr_header kth; + struct ktr_user *ktp; + int error; + + if (!KTRPOINT(p, KTR_USER)) + return (0); + if (len > KTR_USER_MAXLEN) + return ENOSPC; + + p->p_traceflag |= KTRFAC_ACTIVE; + ktrinitheader(&kth, p, KTR_USER); + ktp = malloc(sizeof(*ktp) + len, M_TEMP, M_WAITOK); + bzero(ktp->ktr_id, KTR_USER_MAXIDLEN); + if (ustr) { + error = copyinstr(id, ktp->ktr_id, KTR_USER_MAXIDLEN, NULL); + if (error) + goto out; + } else + strlcpy(ktp->ktr_id, id, KTR_USER_MAXIDLEN); + error = copyin(addr, (void *)(ktp + 1), len); + if (error) + goto out; + kth.ktr_buf = (void *)ktp; + kth.ktr_len = sizeof(*ktp) + len; + ktrwrite(p, &kth); +out: + free(ktp, M_TEMP); + p->p_traceflag &= ~KTRFAC_ACTIVE; + return (error); +} + + /* Interface and common routines */ /* @@ -408,6 +444,22 @@ done: (void) vn_close(vp, FWRITE, curp->p_ucred, curp); curp->p_traceflag &= ~KTRFAC_ACTIVE; return (error); +} + +/* + * utrace system call + */ +/* ARGSUSED */ +int +sys_utrace(struct proc *curp, void *v, register_t *retval) +{ + struct sys_utrace_args /* { + syscallarg(const char *) label; + syscallarg(void) addr; + syscallarg(size_t) len; + } */ *uap = v; + return (ktruser(curp, SCARG(uap, label), SCARG(uap, addr), + SCARG(uap, len), 1)); } int Index: sys/kern/syscalls.c =================================================================== RCS file: /cvs/src/sys/kern/syscalls.c,v retrieving revision 1.130 diff -u -p -r1.130 syscalls.c --- sys/kern/syscalls.c 9 Jul 2011 05:46:58 -0000 1.130 +++ sys/kern/syscalls.c 12 Jul 2011 14:59:03 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: syscalls.c,v 1.130 2011/07/09 05:46:58 matthew Exp $ */ +/* $OpenBSD$ */ /* * System call names. @@ -409,4 +409,9 @@ char *syscallnames[] = { "symlinkat", /* 324 = symlinkat */ "unlinkat", /* 325 = unlinkat */ "utimensat", /* 326 = utimensat */ +#ifdef KTRACE + "utrace", /* 327 = utrace */ +#else + "#327 (unimplemented utrace)", /* 327 = unimplemented utrace */ +#endif }; Index: sys/kern/syscalls.master =================================================================== RCS file: /cvs/src/sys/kern/syscalls.master,v retrieving revision 1.117 diff -u -p -r1.117 syscalls.master --- sys/kern/syscalls.master 9 Jul 2011 05:46:26 -0000 1.117 +++ sys/kern/syscalls.master 12 Jul 2011 14:59:03 -0000 @@ -572,3 +572,9 @@ int flag); } 326 STD { int sys_utimensat(int fd, const char *path, \ const struct timespec *times, int flag); } +#ifdef KTRACE +327 STD { int sys_utrace(const char *label, void *addr, \ + size_t len); } +#else +327 UNIMPL utrace +#endif Index: sys/sys/ktrace.h =================================================================== RCS file: /cvs/src/sys/sys/ktrace.h,v retrieving revision 1.11 diff -u -p -r1.11 ktrace.h --- sys/sys/ktrace.h 8 Jul 2011 19:28:38 -0000 1.11 +++ sys/sys/ktrace.h 12 Jul 2011 14:59:03 -0000 @@ -146,6 +146,19 @@ struct sockaddr; struct stat; /* + * KTR_USER - user record + */ +#define KTR_USER 9 +#define KTR_USER_MAXIDLEN 20 +#define KTR_USER_MAXLEN 2048 /* maximum length of passed data */ +struct ktr_user { + char ktr_id[KTR_USER_MAXIDLEN]; /* string id of caller */ + /* + * Followed by ktr_len - sizeof(struct ktr_user) of user data. + */ +}; + +/* * kernel trace points (in p_traceflag) */ #define KTRFAC_MASK 0x00ffffff @@ -157,6 +170,7 @@ struct stat; #define KTRFAC_CSW (1<<KTR_CSW) #define KTRFAC_EMUL (1<<KTR_EMUL) #define KTRFAC_STRUCT (1<<KTR_STRUCT) +#define KTRFAC_USER (1<<KTR_USER) /* * trace flags (also in p_traceflags) @@ -171,6 +185,7 @@ struct stat; __BEGIN_DECLS int ktrace(const char *, int, int, pid_t); +int utrace(const char *, void *, size_t); __END_DECLS #else @@ -182,6 +197,7 @@ void ktrnamei(struct proc *, char *); void ktrpsig(struct proc *, int, sig_t, int, int, siginfo_t *); void ktrsyscall(struct proc *, register_t, size_t, register_t []); void ktrsysret(struct proc *, register_t, int, register_t); +void ktr_kuser(const char *, void *, size_t); void ktrsettracevnode(struct proc *, struct vnode *); Index: sys/sys/syscall.h =================================================================== RCS file: /cvs/src/sys/sys/syscall.h,v retrieving revision 1.129 diff -u -p -r1.129 syscall.h --- sys/sys/syscall.h 9 Jul 2011 05:46:58 -0000 1.129 +++ sys/sys/syscall.h 12 Jul 2011 14:59:03 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: syscall.h,v 1.129 2011/07/09 05:46:58 matthew Exp $ */ +/* $OpenBSD$ */ /* * System call numbers. @@ -670,4 +670,7 @@ /* syscall: "utimensat" ret: "int" args: "int" "const char *" "const struct timespec *" "int" */ #define SYS_utimensat 326 -#define SYS_MAXSYSCALL 327 +/* syscall: "utrace" ret: "int" args: "const char *" "void *" "size_t" */ +#define SYS_utrace 327 + +#define SYS_MAXSYSCALL 328 Index: sys/sys/syscallargs.h =================================================================== RCS file: /cvs/src/sys/sys/syscallargs.h,v retrieving revision 1.131 diff -u -p -r1.131 syscallargs.h --- sys/sys/syscallargs.h 9 Jul 2011 05:46:58 -0000 1.131 +++ sys/sys/syscallargs.h 12 Jul 2011 14:59:03 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: syscallargs.h,v 1.131 2011/07/09 05:46:58 matthew Exp $ */ +/* $OpenBSD$ */ /* * System call argument lists. @@ -1040,6 +1040,12 @@ struct sys_utimensat_args { syscallarg(int) flag; }; +struct sys_utrace_args { + syscallarg(const char *) label; + syscallarg(void *) addr; + syscallarg(size_t) len; +}; + /* * System call prototypes. */ @@ -1293,3 +1299,7 @@ int sys_renameat(struct proc *, void *, int sys_symlinkat(struct proc *, void *, register_t *); int sys_unlinkat(struct proc *, void *, register_t *); int sys_utimensat(struct proc *, void *, register_t *); +#ifdef KTRACE +int sys_utrace(struct proc *, void *, register_t *); +#else +#endif Index: usr.bin/kdump/kdump.1 =================================================================== RCS file: /cvs/src/usr.bin/kdump/kdump.1,v retrieving revision 1.20 diff -u -p -r1.20 kdump.1 --- usr.bin/kdump/kdump.1 9 Jul 2011 15:43:38 -0000 1.20 +++ usr.bin/kdump/kdump.1 12 Jul 2011 14:59:03 -0000 @@ -101,7 +101,7 @@ When decoding STRU records, display stru GIDs, dates etc. symbolically instead of numerically. .It Fl T Display absolute timestamps for each entry (seconds since the Epoch). -.It Fl t Op ceinstw +.It Fl t Op ceinstuw Selects which tracepoints to display. See the .Fl t Index: usr.bin/kdump/kdump.c =================================================================== RCS file: /cvs/src/usr.bin/kdump/kdump.c,v retrieving revision 1.58 diff -u -p -r1.58 kdump.c --- usr.bin/kdump/kdump.c 10 Jul 2011 06:13:55 -0000 1.58 +++ usr.bin/kdump/kdump.c 12 Jul 2011 14:59:03 -0000 @@ -130,6 +130,7 @@ static void ktrpsig(struct ktr_psig *); static void ktrsyscall(struct ktr_syscall *); static void ktrsysret(struct ktr_sysret *); static void ktrstruct(char *, size_t); +static void ktruser(struct ktr_user *, size_t); static void setemul(const char *); static void usage(void); @@ -244,6 +245,9 @@ main(int argc, char *argv[]) case KTR_STRUCT: ktrstruct(m, ktrlen); break; + case KTR_USER: + ktruser(m, ktrlen); + break; } if (tail) (void)fflush(stdout); @@ -295,6 +299,9 @@ dumpheader(struct ktr_header *kth) case KTR_STRUCT: type = "STRU"; break; + case KTR_USER: + type = "USER"; + break; default: (void)snprintf(unknown, sizeof unknown, "UNKNOWN(%d)", kth->ktr_type); @@ -754,12 +761,10 @@ ktremul(char *cp, size_t len) } static void -ktrgenio(struct ktr_genio *ktr, size_t len) +showbuf(unsigned char *dp, size_t datalen) { - unsigned char *dp = (unsigned char *)ktr + sizeof(struct ktr_genio); int i, j; - size_t datalen = len - sizeof(struct ktr_genio); - static int screenwidth = 0; + static int screenwidth; int col = 0, width, bpl; unsigned char visbuf[5], *cp, c; @@ -772,14 +777,6 @@ ktrgenio(struct ktr_genio *ktr, size_t l else screenwidth = 80; } - printf("fd %d %s %zu bytes\n", ktr->ktr_fd, - ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen); - if (maxdata == 0) - return; - if (datalen > maxdata) - datalen = maxdata; - if (iohex && !datalen) - return; if (iohex == 1) { putchar('\t'); col = 8; @@ -862,6 +859,23 @@ ktrgenio(struct ktr_genio *ktr, size_t l } static void +ktrgenio(struct ktr_genio *ktr, size_t len) +{ + unsigned char *dp = (unsigned char *)ktr + sizeof(struct ktr_genio); + size_t datalen = len - sizeof(struct ktr_genio); + + printf("fd %d %s %zu bytes\n", ktr->ktr_fd, + ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen); + if (maxdata == 0) + return; + if (datalen > maxdata) + datalen = maxdata; + if (iohex && !datalen) + return; + showbuf(dp, datalen); +} + +static void ktrpsig(struct ktr_psig *psig) { (void)printf("SIG%s ", sys_signame[psig->signo]); @@ -891,8 +905,6 @@ ktrcsw(struct ktr_csw *cs) cs->user ? "user" : "kernel"); } - - void ktrsockaddr(struct sockaddr *sa) { @@ -1080,6 +1092,15 @@ ktrstruct(char *buf, size_t buflen) return; invalid: printf("invalid record\n"); +} + +static void +ktruser(struct ktr_user *usr, size_t len) +{ + len -= sizeof(struct ktr_user); + printf("%.*s:", KTR_USER_MAXIDLEN, usr->ktr_id); + printf(" %zu bytes\n", len); + showbuf((unsigned char *)(usr + 1), len); } static void Index: usr.bin/ktrace/ktrace.1 =================================================================== RCS file: /cvs/src/usr.bin/ktrace/ktrace.1,v retrieving revision 1.22 diff -u -p -r1.22 ktrace.1 --- usr.bin/ktrace/ktrace.1 8 Jul 2011 20:37:18 -0000 1.22 +++ usr.bin/ktrace/ktrace.1 12 Jul 2011 14:59:03 -0000 @@ -109,8 +109,9 @@ The default flags are .Cm i , .Cm n , .Cm s , +.Cm t , and -.Cm t . +.Cm u . The following table equates the letters with the tracepoints: .Pp .Bl -tag -width flag -offset indent -compact @@ -126,6 +127,9 @@ trace namei translations trace signal processing .It Cm t trace various structures +.It Cm u +trace user data coming from +.Xr utrace 2 .It Cm w trace context switch points .It Cm + @@ -177,7 +181,8 @@ Disable tracing of all processes owned b .Dl $ ktrace -C .Sh SEE ALSO .Xr kdump 1 , -.Xr ktrace 2 +.Xr ktrace 2 , +.Xr utrace 2 .Sh HISTORY The .Nm ktrace Index: usr.bin/ktrace/ktrace.h =================================================================== RCS file: /cvs/src/usr.bin/ktrace/ktrace.h,v retrieving revision 1.4 diff -u -p -r1.4 ktrace.h --- usr.bin/ktrace/ktrace.h 8 Jul 2011 19:29:44 -0000 1.4 +++ usr.bin/ktrace/ktrace.h 12 Jul 2011 14:59:03 -0000 @@ -31,7 +31,8 @@ */ #define DEF_POINTS (KTRFAC_SYSCALL | KTRFAC_SYSRET | KTRFAC_NAMEI | \ - KTRFAC_GENIO | KTRFAC_PSIG | KTRFAC_EMUL | KTRFAC_STRUCT) + KTRFAC_GENIO | KTRFAC_PSIG | KTRFAC_EMUL | KTRFAC_STRUCT | \ + KTRFAC_USER) #define ALL_POINTS (DEF_POINTS | KTRFAC_CSW) Index: usr.bin/ktrace/subr.c =================================================================== RCS file: /cvs/src/usr.bin/ktrace/subr.c,v retrieving revision 1.7 diff -u -p -r1.7 subr.c --- usr.bin/ktrace/subr.c 8 Jul 2011 19:29:44 -0000 1.7 +++ usr.bin/ktrace/subr.c 12 Jul 2011 14:59:03 -0000 @@ -71,6 +71,9 @@ getpoints(s) case 't': facs |= KTRFAC_STRUCT; break; + case 'u': + facs |= KTRFAC_USER; + break; case '+': facs |= DEF_POINTS; break;