aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJonathan Lemon <jlemon@FreeBSD.org>1999-07-09 04:16:00 +0000
committerJonathan Lemon <jlemon@FreeBSD.org>1999-07-09 04:16:00 +0000
commitab001a72bef18732f5c48efedcc6d2285aa8fc81 (patch)
tree041d2aa2a0fba42e80b16789e7d05986d8bcfab3 /sys
parentbd17e46e5537768cc2677acf080f3980c9041b8c (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/cpu_switch.S40
-rw-r--r--sys/amd64/amd64/genassym.c9
-rw-r--r--sys/amd64/amd64/machdep.c83
-rw-r--r--sys/amd64/amd64/swtch.s40
-rw-r--r--sys/amd64/include/md_var.h4
-rw-r--r--sys/amd64/include/pcb.h11
-rw-r--r--sys/amd64/include/ptrace.h4
-rw-r--r--sys/amd64/include/reg.h15
-rw-r--r--sys/conf/files1
-rw-r--r--sys/fs/procfs/procfs.h8
-rw-r--r--sys/fs/procfs/procfs_subr.c7
-rw-r--r--sys/fs/procfs/procfs_vnops.c8
-rw-r--r--sys/i386/i386/genassym.c9
-rw-r--r--sys/i386/i386/machdep.c83
-rw-r--r--sys/i386/i386/procfs_machdep.c25
-rw-r--r--sys/i386/i386/swtch.s40
-rw-r--r--sys/i386/include/md_var.h4
-rw-r--r--sys/i386/include/pcb.h11
-rw-r--r--sys/i386/include/ptrace.h4
-rw-r--r--sys/i386/include/reg.h15
-rw-r--r--sys/kern/sys_process.c34
-rw-r--r--sys/miscfs/procfs/procfs.h8
-rw-r--r--sys/miscfs/procfs/procfs_subr.c7
-rw-r--r--sys/miscfs/procfs/procfs_vnops.c8
-rw-r--r--sys/powerpc/include/ptrace.h4
25 files changed, 458 insertions, 24 deletions
diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S
index 428b0ae2d5736..82c9737261e26 100644
--- a/sys/amd64/amd64/cpu_switch.S
+++ b/sys/amd64/amd64/cpu_switch.S
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: swtch.s,v 1.82 1999/06/01 18:19:45 jlemon Exp $
+ * $Id: swtch.s,v 1.83 1999/07/03 06:33:24 alc Exp $
*/
#include "npx.h"
@@ -480,6 +480,26 @@ ENTRY(cpu_switch)
movl %edi,PCB_EDI(%edx)
movl %gs,PCB_GS(%edx)
+ /* test if debug regisers should be saved */
+ movb PCB_FLAGS(%edx),%al
+ andb $PCB_DBREGS,%al
+ jz 1f /* no, skip over */
+ movl %dr7,%eax /* yes, do the save */
+ movl %eax,PCB_DR7(%edx)
+ andl $0x0000ff00, %eax /* disable all watchpoints */
+ movl %eax,%dr7
+ movl %dr6,%eax
+ movl %eax,PCB_DR6(%edx)
+ movl %dr3,%eax
+ movl %eax,PCB_DR3(%edx)
+ movl %dr2,%eax
+ movl %eax,PCB_DR2(%edx)
+ movl %dr1,%eax
+ movl %eax,PCB_DR1(%edx)
+ movl %dr0,%eax
+ movl %eax,PCB_DR0(%edx)
+1:
+
#ifdef SMP
movl _mp_lock, %eax
/* XXX FIXME: we should be saving the local APIC TPR */
@@ -718,6 +738,24 @@ swtch_com:
cpu_switch_load_gs:
movl PCB_GS(%edx),%gs
+ /* test if debug regisers should be restored */
+ movb PCB_FLAGS(%edx),%al
+ andb $PCB_DBREGS,%al
+ jz 1f /* no, skip over */
+ movl PCB_DR6(%edx),%eax /* yes, do the restore */
+ movl %eax,%dr6
+ movl PCB_DR3(%edx),%eax
+ movl %eax,%dr3
+ movl PCB_DR2(%edx),%eax
+ movl %eax,%dr2
+ movl PCB_DR1(%edx),%eax
+ movl %eax,%dr1
+ movl PCB_DR0(%edx),%eax
+ movl %eax,%dr0
+ movl PCB_DR7(%edx),%eax
+ movl %eax,%dr7
+1:
+
sti
ret
diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c
index 3e92787bf8520..dc5a18d61bf7a 100644
--- a/sys/amd64/amd64/genassym.c
+++ b/sys/amd64/amd64/genassym.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)genassym.c 5.11 (Berkeley) 5/10/91
- * $Id: genassym.c,v 1.71 1999/06/28 09:21:41 peter Exp $
+ * $Id: genassym.c,v 1.72 1999/07/06 07:13:32 cracauer Exp $
*/
#include "opt_user_ldt.h"
@@ -128,6 +128,13 @@ main()
printf("#define\tTSS_ESP0 %#x\n", OS(i386tss, tss_esp0));
printf("#define\tPCB_USERLDT %#x\n", OS(pcb, pcb_ldt));
printf("#define\tPCB_GS %#x\n", OS(pcb, pcb_gs));
+ printf("#define\tPCB_DR0 %#x\n", OS(pcb, pcb_dr0));
+ printf("#define\tPCB_DR1 %#x\n", OS(pcb, pcb_dr1));
+ printf("#define\tPCB_DR2 %#x\n", OS(pcb, pcb_dr2));
+ printf("#define\tPCB_DR3 %#x\n", OS(pcb, pcb_dr3));
+ printf("#define\tPCB_DR6 %#x\n", OS(pcb, pcb_dr6));
+ printf("#define\tPCB_DR7 %#x\n", OS(pcb, pcb_dr7));
+ printf("#define\tPCB_DBREGS %#x\n", PCB_DBREGS );
printf("#define\tPCB_EXT %#x\n", OS(pcb, pcb_ext));
#ifdef SMP
printf("#define\tPCB_MPNEST %#x\n", OS(pcb, pcb_mpnest));
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index ec11c9827bd16..423de1258cf72 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
- * $Id: machdep.c,v 1.353 1999/07/06 07:13:33 cracauer Exp $
+ * $Id: machdep.c,v 1.354 1999/07/08 06:05:48 mckusick Exp $
*/
#include "apm.h"
@@ -1927,6 +1927,87 @@ set_fpregs(p, fpregs)
return (0);
}
+int
+fill_dbregs(p, dbregs)
+ struct proc *p;
+ struct dbreg *dbregs;
+{
+ struct pcb *pcb;
+
+ pcb = &p->p_addr->u_pcb;
+ dbregs->dr0 = pcb->pcb_dr0;
+ dbregs->dr1 = pcb->pcb_dr1;
+ dbregs->dr2 = pcb->pcb_dr2;
+ dbregs->dr3 = pcb->pcb_dr3;
+ dbregs->dr4 = 0;
+ dbregs->dr5 = 0;
+ dbregs->dr6 = pcb->pcb_dr6;
+ dbregs->dr7 = pcb->pcb_dr7;
+ return (0);
+}
+
+int
+set_dbregs(p, dbregs)
+ struct proc *p;
+ struct dbreg *dbregs;
+{
+ struct pcb *pcb;
+
+ pcb = &p->p_addr->u_pcb;
+
+ /*
+ * Don't let a process set a breakpoint that is not within the
+ * process's address space. If a process could do this, it
+ * could halt the system by setting a breakpoint in the kernel
+ * (if ddb was enabled). Thus, we need to check to make sure
+ * that no breakpoints are being enabled for addresses outside
+ * process's address space, unless, perhaps, we were called by
+ * uid 0.
+ *
+ * XXX - what about when the watched area of the user's
+ * address space is written into from within the kernel
+ * ... wouldn't that still cause a breakpoint to be generated
+ * from within kernel mode?
+ */
+
+ if (p->p_cred->pc_ucred->cr_uid != 0) {
+ if (dbregs->dr7 & 0x3) {
+ /* dr0 is enabled */
+ if (dbregs->dr0 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+
+ if (dbregs->dr7 & (0x3<<2)) {
+ /* dr1 is enabled */
+ if (dbregs->dr1 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+
+ if (dbregs->dr7 & (0x3<<4)) {
+ /* dr2 is enabled */
+ if (dbregs->dr2 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+
+ if (dbregs->dr7 & (0x3<<6)) {
+ /* dr3 is enabled */
+ if (dbregs->dr3 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+ }
+
+ pcb->pcb_dr0 = dbregs->dr0;
+ pcb->pcb_dr1 = dbregs->dr1;
+ pcb->pcb_dr2 = dbregs->dr2;
+ pcb->pcb_dr3 = dbregs->dr3;
+ pcb->pcb_dr6 = dbregs->dr6;
+ pcb->pcb_dr7 = dbregs->dr7;
+
+ pcb->pcb_flags |= PCB_DBREGS;
+
+ return (0);
+}
+
#ifndef DDB
void
Debugger(const char *msg)
diff --git a/sys/amd64/amd64/swtch.s b/sys/amd64/amd64/swtch.s
index 428b0ae2d5736..82c9737261e26 100644
--- a/sys/amd64/amd64/swtch.s
+++ b/sys/amd64/amd64/swtch.s
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: swtch.s,v 1.82 1999/06/01 18:19:45 jlemon Exp $
+ * $Id: swtch.s,v 1.83 1999/07/03 06:33:24 alc Exp $
*/
#include "npx.h"
@@ -480,6 +480,26 @@ ENTRY(cpu_switch)
movl %edi,PCB_EDI(%edx)
movl %gs,PCB_GS(%edx)
+ /* test if debug regisers should be saved */
+ movb PCB_FLAGS(%edx),%al
+ andb $PCB_DBREGS,%al
+ jz 1f /* no, skip over */
+ movl %dr7,%eax /* yes, do the save */
+ movl %eax,PCB_DR7(%edx)
+ andl $0x0000ff00, %eax /* disable all watchpoints */
+ movl %eax,%dr7
+ movl %dr6,%eax
+ movl %eax,PCB_DR6(%edx)
+ movl %dr3,%eax
+ movl %eax,PCB_DR3(%edx)
+ movl %dr2,%eax
+ movl %eax,PCB_DR2(%edx)
+ movl %dr1,%eax
+ movl %eax,PCB_DR1(%edx)
+ movl %dr0,%eax
+ movl %eax,PCB_DR0(%edx)
+1:
+
#ifdef SMP
movl _mp_lock, %eax
/* XXX FIXME: we should be saving the local APIC TPR */
@@ -718,6 +738,24 @@ swtch_com:
cpu_switch_load_gs:
movl PCB_GS(%edx),%gs
+ /* test if debug regisers should be restored */
+ movb PCB_FLAGS(%edx),%al
+ andb $PCB_DBREGS,%al
+ jz 1f /* no, skip over */
+ movl PCB_DR6(%edx),%eax /* yes, do the restore */
+ movl %eax,%dr6
+ movl PCB_DR3(%edx),%eax
+ movl %eax,%dr3
+ movl PCB_DR2(%edx),%eax
+ movl %eax,%dr2
+ movl PCB_DR1(%edx),%eax
+ movl %eax,%dr1
+ movl PCB_DR0(%edx),%eax
+ movl %eax,%dr0
+ movl PCB_DR7(%edx),%eax
+ movl %eax,%dr7
+1:
+
sti
ret
diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h
index 35b65455e244c..491eb46b024ab 100644
--- a/sys/amd64/include/md_var.h
+++ b/sys/amd64/include/md_var.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: md_var.h,v 1.28 1999/01/08 16:29:58 bde Exp $
+ * $Id: md_var.h,v 1.29 1999/04/28 01:04:02 luoqi Exp $
*/
#ifndef _MACHINE_MD_VAR_H_
@@ -64,6 +64,7 @@ typedef void alias_for_inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss));
struct proc;
struct reg;
struct fpreg;
+struct dbreg;
void bcopyb __P((const void *from, void *to, size_t len));
void busdma_swi __P((void));
@@ -80,6 +81,7 @@ void doreti_popl_fs __P((void)) __asm(__STRING(doreti_popl_fs));
void doreti_popl_fs_fault __P((void)) __asm(__STRING(doreti_popl_fs_fault));
int fill_fpregs __P((struct proc *, struct fpreg *));
int fill_regs __P((struct proc *p, struct reg *regs));
+int fill_dbregs __P((struct proc *p, struct dbreg *dbregs));
void fillw __P((int /*u_short*/ pat, void *base, size_t cnt));
void i486_bzero __P((void *buf, size_t len));
void i586_bcopy __P((const void *from, void *to, size_t len));
diff --git a/sys/amd64/include/pcb.h b/sys/amd64/include/pcb.h
index 2dbc707d0fcc0..5cee924dd9ff2 100644
--- a/sys/amd64/include/pcb.h
+++ b/sys/amd64/include/pcb.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)pcb.h 5.10 (Berkeley) 5/12/91
- * $Id: pcb.h,v 1.27 1999/04/28 01:04:05 luoqi Exp $
+ * $Id: pcb.h,v 1.28 1999/06/01 18:20:06 jlemon Exp $
*/
#ifndef _I386_PCB_H_
@@ -54,11 +54,20 @@ struct pcb {
int pcb_esp;
int pcb_ebx;
int pcb_eip;
+
+ int pcb_dr0;
+ int pcb_dr1;
+ int pcb_dr2;
+ int pcb_dr3;
+ int pcb_dr6;
+ int pcb_dr7;
+
caddr_t pcb_ldt; /* per process (user) LDT */
int pcb_ldt_len; /* number of LDT entries */
struct save87 pcb_savefpu; /* floating point state for 287/387 */
u_char pcb_flags;
#define FP_SOFTFP 0x01 /* process using software fltng pnt emulator */
+#define PCB_DBREGS 0x02 /* process using debug registers */
caddr_t pcb_onfault; /* copyin/out fault recovery */
#ifdef SMP
u_long pcb_mpnest;
diff --git a/sys/amd64/include/ptrace.h b/sys/amd64/include/ptrace.h
index ec3d5aab5ca57..2c43a2eef8d4e 100644
--- a/sys/amd64/include/ptrace.h
+++ b/sys/amd64/include/ptrace.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ptrace.h 8.1 (Berkeley) 6/11/93
- * $Id: ptrace.h,v 1.5 1997/02/22 09:35:03 peter Exp $
+ * $Id: ptrace.h,v 1.6 1998/05/19 00:00:12 tegge Exp $
*/
#ifndef _MACHINE_PTRACE_H_
@@ -44,6 +44,8 @@
#define PT_SETREGS (PT_FIRSTMACH + 2)
#define PT_GETFPREGS (PT_FIRSTMACH + 3)
#define PT_SETFPREGS (PT_FIRSTMACH + 4)
+#define PT_GETDBREGS (PT_FIRSTMACH + 5)
+#define PT_SETDBREGS (PT_FIRSTMACH + 6)
#ifdef KERNEL
int ptrace_read_u_check __P((struct proc *p, vm_offset_t off, size_t len));
diff --git a/sys/amd64/include/reg.h b/sys/amd64/include/reg.h
index 247011646fa52..994bdfda03606 100644
--- a/sys/amd64/include/reg.h
+++ b/sys/amd64/include/reg.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)reg.h 5.5 (Berkeley) 1/18/91
- * $Id: reg.h,v 1.17 1999/04/03 22:19:59 jdp Exp $
+ * $Id: reg.h,v 1.18 1999/04/28 01:04:06 luoqi Exp $
*/
#ifndef _MACHINE_REG_H_
@@ -118,6 +118,18 @@ struct fpreg {
unsigned char fpr_pad[64];
};
+struct dbreg {
+ unsigned int dr0; /* debug address register 0 */
+ unsigned int dr1; /* debug address register 1 */
+ unsigned int dr2; /* debug address register 2 */
+ unsigned int dr3; /* debug address register 3 */
+ unsigned int dr4; /* reserved */
+ unsigned int dr5; /* reserved */
+ unsigned int dr6; /* debug status register */
+ unsigned int dr7; /* debug control register */
+};
+
+
#ifdef KERNEL
/*
* XXX these interfaces are MI, so they should be declared in a MI place.
@@ -125,6 +137,7 @@ struct fpreg {
int set_fpregs __P((struct proc *, struct fpreg *));
int set_regs __P((struct proc *p, struct reg *regs));
void setregs __P((struct proc *, u_long, u_long, u_long));
+int set_dbregs __P((struct proc *p, struct dbreg *dbregs));
#endif
#endif /* !_MACHINE_REG_H_ */
diff --git a/sys/conf/files b/sys/conf/files
index 5d9bb05119962..241d71b2d24bf 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -362,6 +362,7 @@ miscfs/nullfs/null_vnops.c optional nullfs
miscfs/portal/portal_vfsops.c optional portal
miscfs/portal/portal_vnops.c optional portal
miscfs/procfs/procfs_ctl.c optional procfs
+miscfs/procfs/procfs_dbregs.c standard
miscfs/procfs/procfs_fpregs.c standard
miscfs/procfs/procfs_map.c optional procfs
miscfs/procfs/procfs_mem.c standard
diff --git a/sys/fs/procfs/procfs.h b/sys/fs/procfs/procfs.h
index b38ed872dc8ba..f813070e699e5 100644
--- a/sys/fs/procfs/procfs.h
+++ b/sys/fs/procfs/procfs.h
@@ -37,7 +37,7 @@
* @(#)procfs.h 8.9 (Berkeley) 5/14/95
*
* From:
- * $Id: procfs.h,v 1.25 1999/05/04 08:00:10 phk Exp $
+ * $Id: procfs.h,v 1.26 1999/06/13 20:53:13 phk Exp $
*/
/*
@@ -51,6 +51,7 @@ typedef enum {
Pmem, /* the process's memory image */
Pregs, /* the process's register set */
Pfpregs, /* the process's FP register set */
+ Pdbregs, /* the process's debug register set */
Pctl, /* process control */
Pstatus, /* process status */
Pnote, /* process notifier */
@@ -124,6 +125,7 @@ vfs_namemap_t *vfs_findname __P((vfs_namemap_t *, char *, int));
/* <machine/reg.h> */
struct reg;
struct fpreg;
+struct dbreg;
#define PFIND(pid) ((pid) ? pfind(pid) : &proc0)
@@ -137,9 +139,12 @@ int procfs_read_regs __P((struct proc *, struct reg *));
int procfs_write_regs __P((struct proc *, struct reg *));
int procfs_read_fpregs __P((struct proc *, struct fpreg *));
int procfs_write_fpregs __P((struct proc *, struct fpreg *));
+int procfs_read_dbregs __P((struct proc *, struct dbreg *));
+int procfs_write_dbregs __P((struct proc *, struct dbreg *));
int procfs_donote __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_doregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_dofpregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_dodbregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_domem __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_doctl __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_dostatus __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
@@ -155,6 +160,7 @@ int procfs_kmemaccess __P((struct proc *));
int procfs_validfile __P((struct proc *));
int procfs_validfpregs __P((struct proc *));
int procfs_validregs __P((struct proc *));
+int procfs_validdbregs __P((struct proc *));
int procfs_validmap __P((struct proc *));
int procfs_validtype __P((struct proc *));
diff --git a/sys/fs/procfs/procfs_subr.c b/sys/fs/procfs/procfs_subr.c
index 7b5e18c440d58..cf313e8638564 100644
--- a/sys/fs/procfs/procfs_subr.c
+++ b/sys/fs/procfs/procfs_subr.c
@@ -36,7 +36,7 @@
*
* @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95
*
- * $Id: procfs_subr.c,v 1.23 1999/01/27 22:42:07 dillon Exp $
+ * $Id: procfs_subr.c,v 1.24 1999/04/30 13:04:21 phk Exp $
*/
#include <sys/param.h>
@@ -167,6 +167,7 @@ loop:
case Pregs:
case Pfpregs:
+ case Pdbregs:
pfs->pfs_mode = (VREAD|VWRITE);
vp->v_type = VREG;
break;
@@ -264,6 +265,10 @@ procfs_rw(ap)
rtval = procfs_dofpregs(curp, p, pfs, uio);
break;
+ case Pdbregs:
+ rtval = procfs_dodbregs(curp, p, pfs, uio);
+ break;
+
case Pctl:
rtval = procfs_doctl(curp, p, pfs, uio);
break;
diff --git a/sys/fs/procfs/procfs_vnops.c b/sys/fs/procfs/procfs_vnops.c
index d421bac0e3b83..fc47353f62cec 100644
--- a/sys/fs/procfs/procfs_vnops.c
+++ b/sys/fs/procfs/procfs_vnops.c
@@ -36,7 +36,7 @@
*
* @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
*
- * $Id: procfs_vnops.c,v 1.68 1999/05/04 08:01:55 phk Exp $
+ * $Id: procfs_vnops.c,v 1.69 1999/06/13 20:53:16 phk Exp $
*/
/*
@@ -95,6 +95,7 @@ static struct proc_target {
{ DT_REG, N("mem"), Pmem, NULL },
{ DT_REG, N("regs"), Pregs, procfs_validregs },
{ DT_REG, N("fpregs"), Pfpregs, procfs_validfpregs },
+ { DT_REG, N("dbregs"), Pdbregs, procfs_validdbregs },
{ DT_REG, N("ctl"), Pctl, NULL },
{ DT_REG, N("status"), Pstatus, NULL },
{ DT_REG, N("note"), Pnote, NULL },
@@ -491,6 +492,7 @@ procfs_getattr(ap)
case Pctl:
case Pregs:
case Pfpregs:
+ case Pdbregs:
if (procp->p_flag & P_SUGID)
vap->va_mode &= ~((VREAD|VWRITE)|
((VREAD|VWRITE)>>3)|
@@ -571,6 +573,10 @@ procfs_getattr(ap)
vap->va_bytes = vap->va_size = sizeof(struct fpreg);
break;
+ case Pdbregs:
+ vap->va_bytes = vap->va_size = sizeof(struct dbreg);
+ break;
+
case Ptype:
case Pmap:
case Pctl:
diff --git a/sys/i386/i386/genassym.c b/sys/i386/i386/genassym.c
index 3e92787bf8520..dc5a18d61bf7a 100644
--- a/sys/i386/i386/genassym.c
+++ b/sys/i386/i386/genassym.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)genassym.c 5.11 (Berkeley) 5/10/91
- * $Id: genassym.c,v 1.71 1999/06/28 09:21:41 peter Exp $
+ * $Id: genassym.c,v 1.72 1999/07/06 07:13:32 cracauer Exp $
*/
#include "opt_user_ldt.h"
@@ -128,6 +128,13 @@ main()
printf("#define\tTSS_ESP0 %#x\n", OS(i386tss, tss_esp0));
printf("#define\tPCB_USERLDT %#x\n", OS(pcb, pcb_ldt));
printf("#define\tPCB_GS %#x\n", OS(pcb, pcb_gs));
+ printf("#define\tPCB_DR0 %#x\n", OS(pcb, pcb_dr0));
+ printf("#define\tPCB_DR1 %#x\n", OS(pcb, pcb_dr1));
+ printf("#define\tPCB_DR2 %#x\n", OS(pcb, pcb_dr2));
+ printf("#define\tPCB_DR3 %#x\n", OS(pcb, pcb_dr3));
+ printf("#define\tPCB_DR6 %#x\n", OS(pcb, pcb_dr6));
+ printf("#define\tPCB_DR7 %#x\n", OS(pcb, pcb_dr7));
+ printf("#define\tPCB_DBREGS %#x\n", PCB_DBREGS );
printf("#define\tPCB_EXT %#x\n", OS(pcb, pcb_ext));
#ifdef SMP
printf("#define\tPCB_MPNEST %#x\n", OS(pcb, pcb_mpnest));
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index ec11c9827bd16..423de1258cf72 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
- * $Id: machdep.c,v 1.353 1999/07/06 07:13:33 cracauer Exp $
+ * $Id: machdep.c,v 1.354 1999/07/08 06:05:48 mckusick Exp $
*/
#include "apm.h"
@@ -1927,6 +1927,87 @@ set_fpregs(p, fpregs)
return (0);
}
+int
+fill_dbregs(p, dbregs)
+ struct proc *p;
+ struct dbreg *dbregs;
+{
+ struct pcb *pcb;
+
+ pcb = &p->p_addr->u_pcb;
+ dbregs->dr0 = pcb->pcb_dr0;
+ dbregs->dr1 = pcb->pcb_dr1;
+ dbregs->dr2 = pcb->pcb_dr2;
+ dbregs->dr3 = pcb->pcb_dr3;
+ dbregs->dr4 = 0;
+ dbregs->dr5 = 0;
+ dbregs->dr6 = pcb->pcb_dr6;
+ dbregs->dr7 = pcb->pcb_dr7;
+ return (0);
+}
+
+int
+set_dbregs(p, dbregs)
+ struct proc *p;
+ struct dbreg *dbregs;
+{
+ struct pcb *pcb;
+
+ pcb = &p->p_addr->u_pcb;
+
+ /*
+ * Don't let a process set a breakpoint that is not within the
+ * process's address space. If a process could do this, it
+ * could halt the system by setting a breakpoint in the kernel
+ * (if ddb was enabled). Thus, we need to check to make sure
+ * that no breakpoints are being enabled for addresses outside
+ * process's address space, unless, perhaps, we were called by
+ * uid 0.
+ *
+ * XXX - what about when the watched area of the user's
+ * address space is written into from within the kernel
+ * ... wouldn't that still cause a breakpoint to be generated
+ * from within kernel mode?
+ */
+
+ if (p->p_cred->pc_ucred->cr_uid != 0) {
+ if (dbregs->dr7 & 0x3) {
+ /* dr0 is enabled */
+ if (dbregs->dr0 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+
+ if (dbregs->dr7 & (0x3<<2)) {
+ /* dr1 is enabled */
+ if (dbregs->dr1 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+
+ if (dbregs->dr7 & (0x3<<4)) {
+ /* dr2 is enabled */
+ if (dbregs->dr2 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+
+ if (dbregs->dr7 & (0x3<<6)) {
+ /* dr3 is enabled */
+ if (dbregs->dr3 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+ }
+
+ pcb->pcb_dr0 = dbregs->dr0;
+ pcb->pcb_dr1 = dbregs->dr1;
+ pcb->pcb_dr2 = dbregs->dr2;
+ pcb->pcb_dr3 = dbregs->dr3;
+ pcb->pcb_dr6 = dbregs->dr6;
+ pcb->pcb_dr7 = dbregs->dr7;
+
+ pcb->pcb_flags |= PCB_DBREGS;
+
+ return (0);
+}
+
#ifndef DDB
void
Debugger(const char *msg)
diff --git a/sys/i386/i386/procfs_machdep.c b/sys/i386/i386/procfs_machdep.c
index 03a8d9dd02619..b0f8e3cda6e23 100644
--- a/sys/i386/i386/procfs_machdep.c
+++ b/sys/i386/i386/procfs_machdep.c
@@ -37,7 +37,7 @@
* @(#)procfs_machdep.c 8.3 (Berkeley) 1/27/94
*
* From:
- * $Id: procfs_machdep.c,v 1.10 1997/07/20 08:37:22 bde Exp $
+ * $Id: procfs_machdep.c,v 1.11 1998/09/14 22:43:33 jdp Exp $
*/
/*
@@ -59,6 +59,9 @@
* procfs_read_fpregs, procfs_write_fpregs
* deal with the floating point register set, otherwise as above.
*
+ * procfs_read_dbregs, procfs_write_dbregs
+ * deal with the processor debug register set, otherwise as above.
+ *
* procfs_sstep(proc)
* Arrange for the process to trap after executing a single instruction.
*
@@ -100,6 +103,26 @@ procfs_write_regs(p, regs)
return (set_regs(p, regs));
}
+int
+procfs_read_dbregs(p, dbregs)
+ struct proc *p;
+ struct dbreg *dbregs;
+{
+ if ((p->p_flag & P_INMEM) == 0)
+ return (EIO);
+ return (fill_dbregs(p, dbregs));
+}
+
+int
+procfs_write_dbregs(p, dbregs)
+ struct proc *p;
+ struct dbreg *dbregs;
+{
+ if ((p->p_flag & P_INMEM) == 0)
+ return (EIO);
+ return (set_dbregs(p, dbregs));
+}
+
/*
* Ptrace doesn't support fpregs at all, and there are no security holes
* or translations for fpregs, so we can just copy them.
diff --git a/sys/i386/i386/swtch.s b/sys/i386/i386/swtch.s
index 428b0ae2d5736..82c9737261e26 100644
--- a/sys/i386/i386/swtch.s
+++ b/sys/i386/i386/swtch.s
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: swtch.s,v 1.82 1999/06/01 18:19:45 jlemon Exp $
+ * $Id: swtch.s,v 1.83 1999/07/03 06:33:24 alc Exp $
*/
#include "npx.h"
@@ -480,6 +480,26 @@ ENTRY(cpu_switch)
movl %edi,PCB_EDI(%edx)
movl %gs,PCB_GS(%edx)
+ /* test if debug regisers should be saved */
+ movb PCB_FLAGS(%edx),%al
+ andb $PCB_DBREGS,%al
+ jz 1f /* no, skip over */
+ movl %dr7,%eax /* yes, do the save */
+ movl %eax,PCB_DR7(%edx)
+ andl $0x0000ff00, %eax /* disable all watchpoints */
+ movl %eax,%dr7
+ movl %dr6,%eax
+ movl %eax,PCB_DR6(%edx)
+ movl %dr3,%eax
+ movl %eax,PCB_DR3(%edx)
+ movl %dr2,%eax
+ movl %eax,PCB_DR2(%edx)
+ movl %dr1,%eax
+ movl %eax,PCB_DR1(%edx)
+ movl %dr0,%eax
+ movl %eax,PCB_DR0(%edx)
+1:
+
#ifdef SMP
movl _mp_lock, %eax
/* XXX FIXME: we should be saving the local APIC TPR */
@@ -718,6 +738,24 @@ swtch_com:
cpu_switch_load_gs:
movl PCB_GS(%edx),%gs
+ /* test if debug regisers should be restored */
+ movb PCB_FLAGS(%edx),%al
+ andb $PCB_DBREGS,%al
+ jz 1f /* no, skip over */
+ movl PCB_DR6(%edx),%eax /* yes, do the restore */
+ movl %eax,%dr6
+ movl PCB_DR3(%edx),%eax
+ movl %eax,%dr3
+ movl PCB_DR2(%edx),%eax
+ movl %eax,%dr2
+ movl PCB_DR1(%edx),%eax
+ movl %eax,%dr1
+ movl PCB_DR0(%edx),%eax
+ movl %eax,%dr0
+ movl PCB_DR7(%edx),%eax
+ movl %eax,%dr7
+1:
+
sti
ret
diff --git a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h
index 35b65455e244c..491eb46b024ab 100644
--- a/sys/i386/include/md_var.h
+++ b/sys/i386/include/md_var.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: md_var.h,v 1.28 1999/01/08 16:29:58 bde Exp $
+ * $Id: md_var.h,v 1.29 1999/04/28 01:04:02 luoqi Exp $
*/
#ifndef _MACHINE_MD_VAR_H_
@@ -64,6 +64,7 @@ typedef void alias_for_inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss));
struct proc;
struct reg;
struct fpreg;
+struct dbreg;
void bcopyb __P((const void *from, void *to, size_t len));
void busdma_swi __P((void));
@@ -80,6 +81,7 @@ void doreti_popl_fs __P((void)) __asm(__STRING(doreti_popl_fs));
void doreti_popl_fs_fault __P((void)) __asm(__STRING(doreti_popl_fs_fault));
int fill_fpregs __P((struct proc *, struct fpreg *));
int fill_regs __P((struct proc *p, struct reg *regs));
+int fill_dbregs __P((struct proc *p, struct dbreg *dbregs));
void fillw __P((int /*u_short*/ pat, void *base, size_t cnt));
void i486_bzero __P((void *buf, size_t len));
void i586_bcopy __P((const void *from, void *to, size_t len));
diff --git a/sys/i386/include/pcb.h b/sys/i386/include/pcb.h
index 2dbc707d0fcc0..5cee924dd9ff2 100644
--- a/sys/i386/include/pcb.h
+++ b/sys/i386/include/pcb.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)pcb.h 5.10 (Berkeley) 5/12/91
- * $Id: pcb.h,v 1.27 1999/04/28 01:04:05 luoqi Exp $
+ * $Id: pcb.h,v 1.28 1999/06/01 18:20:06 jlemon Exp $
*/
#ifndef _I386_PCB_H_
@@ -54,11 +54,20 @@ struct pcb {
int pcb_esp;
int pcb_ebx;
int pcb_eip;
+
+ int pcb_dr0;
+ int pcb_dr1;
+ int pcb_dr2;
+ int pcb_dr3;
+ int pcb_dr6;
+ int pcb_dr7;
+
caddr_t pcb_ldt; /* per process (user) LDT */
int pcb_ldt_len; /* number of LDT entries */
struct save87 pcb_savefpu; /* floating point state for 287/387 */
u_char pcb_flags;
#define FP_SOFTFP 0x01 /* process using software fltng pnt emulator */
+#define PCB_DBREGS 0x02 /* process using debug registers */
caddr_t pcb_onfault; /* copyin/out fault recovery */
#ifdef SMP
u_long pcb_mpnest;
diff --git a/sys/i386/include/ptrace.h b/sys/i386/include/ptrace.h
index ec3d5aab5ca57..2c43a2eef8d4e 100644
--- a/sys/i386/include/ptrace.h
+++ b/sys/i386/include/ptrace.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ptrace.h 8.1 (Berkeley) 6/11/93
- * $Id: ptrace.h,v 1.5 1997/02/22 09:35:03 peter Exp $
+ * $Id: ptrace.h,v 1.6 1998/05/19 00:00:12 tegge Exp $
*/
#ifndef _MACHINE_PTRACE_H_
@@ -44,6 +44,8 @@
#define PT_SETREGS (PT_FIRSTMACH + 2)
#define PT_GETFPREGS (PT_FIRSTMACH + 3)
#define PT_SETFPREGS (PT_FIRSTMACH + 4)
+#define PT_GETDBREGS (PT_FIRSTMACH + 5)
+#define PT_SETDBREGS (PT_FIRSTMACH + 6)
#ifdef KERNEL
int ptrace_read_u_check __P((struct proc *p, vm_offset_t off, size_t len));
diff --git a/sys/i386/include/reg.h b/sys/i386/include/reg.h
index 247011646fa52..994bdfda03606 100644
--- a/sys/i386/include/reg.h
+++ b/sys/i386/include/reg.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)reg.h 5.5 (Berkeley) 1/18/91
- * $Id: reg.h,v 1.17 1999/04/03 22:19:59 jdp Exp $
+ * $Id: reg.h,v 1.18 1999/04/28 01:04:06 luoqi Exp $
*/
#ifndef _MACHINE_REG_H_
@@ -118,6 +118,18 @@ struct fpreg {
unsigned char fpr_pad[64];
};
+struct dbreg {
+ unsigned int dr0; /* debug address register 0 */
+ unsigned int dr1; /* debug address register 1 */
+ unsigned int dr2; /* debug address register 2 */
+ unsigned int dr3; /* debug address register 3 */
+ unsigned int dr4; /* reserved */
+ unsigned int dr5; /* reserved */
+ unsigned int dr6; /* debug status register */
+ unsigned int dr7; /* debug control register */
+};
+
+
#ifdef KERNEL
/*
* XXX these interfaces are MI, so they should be declared in a MI place.
@@ -125,6 +137,7 @@ struct fpreg {
int set_fpregs __P((struct proc *, struct fpreg *));
int set_regs __P((struct proc *p, struct reg *regs));
void setregs __P((struct proc *, u_long, u_long, u_long));
+int set_dbregs __P((struct proc *p, struct dbreg *dbregs));
#endif
#endif /* !_MACHINE_REG_H_ */
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index 41482954a7680..814db9845c5e3 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: sys_process.c,v 1.45 1999/04/28 11:37:04 phk Exp $
+ * $Id: sys_process.c,v 1.46 1999/07/01 22:52:40 peter Exp $
*/
#include <sys/param.h>
@@ -275,6 +275,12 @@ ptrace(curp, uap)
#ifdef PT_SETFPREGS
case PT_SETFPREGS:
#endif
+#ifdef PT_GETDBREGS
+ case PT_GETDBREGS:
+#endif
+#ifdef PT_SETDBREGS
+ case PT_SETDBREGS:
+#endif
/* not being traced... */
if ((p->p_flag & P_TRACED) == 0)
return EPERM;
@@ -502,6 +508,32 @@ ptrace(curp, uap)
}
#endif /* defined(PT_SETFPREGS) || defined(PT_GETFPREGS) */
+#ifdef PT_SETDBREGS
+ case PT_SETDBREGS:
+ write = 1;
+ /* fallthrough */
+#endif /* PT_SETDBREGS */
+#ifdef PT_GETDBREGS
+ case PT_GETDBREGS:
+ /* write = 0 above */
+#endif /* PT_SETDBREGS */
+#if defined(PT_SETDBREGS) || defined(PT_GETDBREGS)
+ if (!procfs_validdbregs(p)) /* no P_SYSTEM procs please */
+ return EINVAL;
+ else {
+ iov.iov_base = uap->addr;
+ iov.iov_len = sizeof(struct dbreg);
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = 0;
+ uio.uio_resid = sizeof(struct dbreg);
+ uio.uio_segflg = UIO_USERSPACE;
+ uio.uio_rw = write ? UIO_WRITE : UIO_READ;
+ uio.uio_procp = curp;
+ return (procfs_dodbregs(curp, p, NULL, &uio));
+ }
+#endif /* defined(PT_SETDBREGS) || defined(PT_GETDBREGS) */
+
default:
break;
}
diff --git a/sys/miscfs/procfs/procfs.h b/sys/miscfs/procfs/procfs.h
index b38ed872dc8ba..f813070e699e5 100644
--- a/sys/miscfs/procfs/procfs.h
+++ b/sys/miscfs/procfs/procfs.h
@@ -37,7 +37,7 @@
* @(#)procfs.h 8.9 (Berkeley) 5/14/95
*
* From:
- * $Id: procfs.h,v 1.25 1999/05/04 08:00:10 phk Exp $
+ * $Id: procfs.h,v 1.26 1999/06/13 20:53:13 phk Exp $
*/
/*
@@ -51,6 +51,7 @@ typedef enum {
Pmem, /* the process's memory image */
Pregs, /* the process's register set */
Pfpregs, /* the process's FP register set */
+ Pdbregs, /* the process's debug register set */
Pctl, /* process control */
Pstatus, /* process status */
Pnote, /* process notifier */
@@ -124,6 +125,7 @@ vfs_namemap_t *vfs_findname __P((vfs_namemap_t *, char *, int));
/* <machine/reg.h> */
struct reg;
struct fpreg;
+struct dbreg;
#define PFIND(pid) ((pid) ? pfind(pid) : &proc0)
@@ -137,9 +139,12 @@ int procfs_read_regs __P((struct proc *, struct reg *));
int procfs_write_regs __P((struct proc *, struct reg *));
int procfs_read_fpregs __P((struct proc *, struct fpreg *));
int procfs_write_fpregs __P((struct proc *, struct fpreg *));
+int procfs_read_dbregs __P((struct proc *, struct dbreg *));
+int procfs_write_dbregs __P((struct proc *, struct dbreg *));
int procfs_donote __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_doregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_dofpregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_dodbregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_domem __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_doctl __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_dostatus __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
@@ -155,6 +160,7 @@ int procfs_kmemaccess __P((struct proc *));
int procfs_validfile __P((struct proc *));
int procfs_validfpregs __P((struct proc *));
int procfs_validregs __P((struct proc *));
+int procfs_validdbregs __P((struct proc *));
int procfs_validmap __P((struct proc *));
int procfs_validtype __P((struct proc *));
diff --git a/sys/miscfs/procfs/procfs_subr.c b/sys/miscfs/procfs/procfs_subr.c
index 7b5e18c440d58..cf313e8638564 100644
--- a/sys/miscfs/procfs/procfs_subr.c
+++ b/sys/miscfs/procfs/procfs_subr.c
@@ -36,7 +36,7 @@
*
* @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95
*
- * $Id: procfs_subr.c,v 1.23 1999/01/27 22:42:07 dillon Exp $
+ * $Id: procfs_subr.c,v 1.24 1999/04/30 13:04:21 phk Exp $
*/
#include <sys/param.h>
@@ -167,6 +167,7 @@ loop:
case Pregs:
case Pfpregs:
+ case Pdbregs:
pfs->pfs_mode = (VREAD|VWRITE);
vp->v_type = VREG;
break;
@@ -264,6 +265,10 @@ procfs_rw(ap)
rtval = procfs_dofpregs(curp, p, pfs, uio);
break;
+ case Pdbregs:
+ rtval = procfs_dodbregs(curp, p, pfs, uio);
+ break;
+
case Pctl:
rtval = procfs_doctl(curp, p, pfs, uio);
break;
diff --git a/sys/miscfs/procfs/procfs_vnops.c b/sys/miscfs/procfs/procfs_vnops.c
index d421bac0e3b83..fc47353f62cec 100644
--- a/sys/miscfs/procfs/procfs_vnops.c
+++ b/sys/miscfs/procfs/procfs_vnops.c
@@ -36,7 +36,7 @@
*
* @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
*
- * $Id: procfs_vnops.c,v 1.68 1999/05/04 08:01:55 phk Exp $
+ * $Id: procfs_vnops.c,v 1.69 1999/06/13 20:53:16 phk Exp $
*/
/*
@@ -95,6 +95,7 @@ static struct proc_target {
{ DT_REG, N("mem"), Pmem, NULL },
{ DT_REG, N("regs"), Pregs, procfs_validregs },
{ DT_REG, N("fpregs"), Pfpregs, procfs_validfpregs },
+ { DT_REG, N("dbregs"), Pdbregs, procfs_validdbregs },
{ DT_REG, N("ctl"), Pctl, NULL },
{ DT_REG, N("status"), Pstatus, NULL },
{ DT_REG, N("note"), Pnote, NULL },
@@ -491,6 +492,7 @@ procfs_getattr(ap)
case Pctl:
case Pregs:
case Pfpregs:
+ case Pdbregs:
if (procp->p_flag & P_SUGID)
vap->va_mode &= ~((VREAD|VWRITE)|
((VREAD|VWRITE)>>3)|
@@ -571,6 +573,10 @@ procfs_getattr(ap)
vap->va_bytes = vap->va_size = sizeof(struct fpreg);
break;
+ case Pdbregs:
+ vap->va_bytes = vap->va_size = sizeof(struct dbreg);
+ break;
+
case Ptype:
case Pmap:
case Pctl:
diff --git a/sys/powerpc/include/ptrace.h b/sys/powerpc/include/ptrace.h
index ec3d5aab5ca57..2c43a2eef8d4e 100644
--- a/sys/powerpc/include/ptrace.h
+++ b/sys/powerpc/include/ptrace.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ptrace.h 8.1 (Berkeley) 6/11/93
- * $Id: ptrace.h,v 1.5 1997/02/22 09:35:03 peter Exp $
+ * $Id: ptrace.h,v 1.6 1998/05/19 00:00:12 tegge Exp $
*/
#ifndef _MACHINE_PTRACE_H_
@@ -44,6 +44,8 @@
#define PT_SETREGS (PT_FIRSTMACH + 2)
#define PT_GETFPREGS (PT_FIRSTMACH + 3)
#define PT_SETFPREGS (PT_FIRSTMACH + 4)
+#define PT_GETDBREGS (PT_FIRSTMACH + 5)
+#define PT_SETDBREGS (PT_FIRSTMACH + 6)
#ifdef KERNEL
int ptrace_read_u_check __P((struct proc *p, vm_offset_t off, size_t len));