Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern Make {s, g}et{db, fp, }regs work again for PK_32 proce...



details:   https://anonhg.NetBSD.org/src/rev/f00699b60be9
branches:  trunk
changeset: 357996:f00699b60be9
user:      christos <christos%NetBSD.org@localhost>
date:      Thu Dec 07 15:21:34 2017 +0000

description:
Make {s,g}et{db,fp,}regs work again for PK_32 processes
XXX: pullup-8

diffstat:

 sys/kern/sys_ptrace_common.c |  162 +++++++++++++++++++++++-------------------
 1 files changed, 87 insertions(+), 75 deletions(-)

diffs (217 lines):

diff -r a864ed71f603 -r f00699b60be9 sys/kern/sys_ptrace_common.c
--- a/sys/kern/sys_ptrace_common.c      Thu Dec 07 10:22:04 2017 +0000
+++ b/sys/kern/sys_ptrace_common.c      Thu Dec 07 15:21:34 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sys_ptrace_common.c,v 1.23 2017/08/28 00:46:07 kamil Exp $     */
+/*     $NetBSD: sys_ptrace_common.c,v 1.24 2017/12/07 15:21:34 christos Exp $  */
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -118,12 +118,13 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.23 2017/08/28 00:46:07 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.24 2017/12/07 15:21:34 christos Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ptrace.h"
 #include "opt_ktrace.h"
 #include "opt_pax.h"
+#include "opt_compat_netbsd32.h"
 #endif
 
 #include <sys/param.h>
@@ -1320,40 +1321,69 @@
        return error;
 }
 
+typedef int (*regfunc_t)(struct lwp *, void *);
+
+#if defined(PT_GETDBREGS) || defined(PT_SETDBREGS) || \
+    defined(PT_GETFPREGS) || defined(PT_SETFPREGS) || \
+    defined(PT_GETREGS) || defined(PT_SETREGS)
+static int
+proc_regio(struct lwp *l, struct uio *uio, size_t kl, regfunc_t r, regfunc_t w)
+{
+       char buf[1024];
+       int error;
+       char *kv;
+
+       if (kl > sizeof(buf))
+               return E2BIG;
+
+       if (uio->uio_offset < 0 || uio->uio_offset > (off_t)kl)
+               return EINVAL;
+
+       kv = buf + uio->uio_offset;
+       kl -= uio->uio_offset;
+
+       if (kl > uio->uio_resid)
+               kl = uio->uio_resid;
+
+       error = (*r)(l, buf);
+       if (error == 0)
+               error = uiomove(kv, kl, uio);
+       if (error == 0 && uio->uio_rw == UIO_WRITE) {
+               if (l->l_stat != LSSTOP)
+                       error = EBUSY;
+               else
+                       error = (*w)(l, buf);
+       }
+
+       uio->uio_offset = 0;
+       return error;
+}
+#endif
+
 int
 process_doregs(struct lwp *curl /*tracer*/,
     struct lwp *l /*traced*/,
     struct uio *uio)
 {
 #if defined(PT_GETREGS) || defined(PT_SETREGS)
-       int error;
-       struct reg r;
-       char *kv;
-       int kl;
+       size_t s;
+       regfunc_t r, w;
 
-       if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r))
-               return EINVAL;
-
-       kl = sizeof(r);
-       kv = (char *)&r;
+#ifdef COMPAT_NETBSD32
+       const bool pk32 = (l->l_proc->p_flag & PK_32) != 0;
 
-       kv += uio->uio_offset;
-       kl -= uio->uio_offset;
-       if ((size_t)kl > uio->uio_resid)
-               kl = uio->uio_resid;
-
-       error = process_read_regs(l, &r);
-       if (error == 0)
-               error = uiomove(kv, kl, uio);
-       if (error == 0 && uio->uio_rw == UIO_WRITE) {
-               if (l->l_stat != LSSTOP)
-                       error = EBUSY;
-               else
-                       error = process_write_regs(l, &r);
+       if (__predict_false(pk32)) {
+               s = sizeof(struct reg32);
+               r = (regfunc_t)process_read_regs32;
+               w = (regfunc_t)process_write_regs32;
+       } else
+#endif
+       {
+               s = sizeof(struct reg);
+               r = (regfunc_t)process_read_regs;
+               w = (regfunc_t)process_write_regs;
        }
-
-       uio->uio_offset = 0;
-       return error;
+       return proc_regio(l, uio, s, r, w);
 #else
        return EINVAL;
 #endif
@@ -1376,33 +1406,24 @@
     struct uio *uio)
 {
 #if defined(PT_GETFPREGS) || defined(PT_SETFPREGS)
-       int error;
-       struct fpreg r;
-       char *kv;
-       size_t kl;
+       size_t s;
+       regfunc_t r, w;
 
-       if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r))
-               return EINVAL;
-
-       kl = sizeof(r);
-       kv = (char *)&r;
+#ifdef COMPAT_NETBSD32
+       const bool pk32 = (l->l_proc->p_flag & PK_32) != 0;
 
-       kv += uio->uio_offset;
-       kl -= uio->uio_offset;
-       if (kl > uio->uio_resid)
-               kl = uio->uio_resid;
-
-       error = process_read_fpregs(l, &r, &kl);
-       if (error == 0)
-               error = uiomove(kv, kl, uio);
-       if (error == 0 && uio->uio_rw == UIO_WRITE) {
-               if (l->l_stat != LSSTOP)
-                       error = EBUSY;
-               else
-                       error = process_write_fpregs(l, &r, kl);
+       if (__predict_false(pk32)) {
+               s = sizeof(struct fpreg32);
+               r = (regfunc_t)process_read_fpregs32;
+               w = (regfunc_t)process_write_fpregs32;
+       } else
+#endif
+       {
+               s = sizeof(struct fpreg);
+               r = (regfunc_t)process_read_fpregs;
+               w = (regfunc_t)process_write_fpregs;
        }
-       uio->uio_offset = 0;
-       return error;
+       return proc_regio(l, uio, s, r, w);
 #else
        return EINVAL;
 #endif
@@ -1425,33 +1446,24 @@
     struct uio *uio)
 {
 #if defined(PT_GETDBREGS) || defined(PT_SETDBREGS)
-       int error;
-       struct dbreg r;
-       char *kv;
-       size_t kl;
+       size_t s;
+       regfunc_t r, w;
 
-       if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r))
-               return EINVAL;
-
-       kl = sizeof(r);
-       kv = (char *)&r;
+#ifdef COMPAT_NETBSD32
+       const bool pk32 = (l->l_proc->p_flag & PK_32) != 0;
 
-       kv += uio->uio_offset;
-       kl -= uio->uio_offset;
-       if (kl > uio->uio_resid)
-               kl = uio->uio_resid;
-
-       error = process_read_dbregs(l, &r, &kl);
-       if (error == 0)
-               error = uiomove(kv, kl, uio);
-       if (error == 0 && uio->uio_rw == UIO_WRITE) {
-               if (l->l_stat != LSSTOP)
-                       error = EBUSY;
-               else
-                       error = process_write_dbregs(l, &r, kl);
+       if (__predict_false(pk32)) {
+               s = sizeof(struct dbreg32);
+               r = (regfunc_t)process_read_dbregs32;
+               w = (regfunc_t)process_write_dbregs32;
+       } else
+#endif
+       {
+               s = sizeof(struct dbreg);
+               r = (regfunc_t)process_read_dbregs;
+               w = (regfunc_t)process_write_dbregs;
        }
-       uio->uio_offset = 0;
-       return error;
+       return proc_regio(l, uio, s, r, w);
 #else
        return EINVAL;
 #endif



Home | Main Index | Thread Index | Old Index