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;

Reply via email to