summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordg <dg@FreeBSD.org>1993-11-16 09:54:57 +0000
committerdg <dg@FreeBSD.org>1993-11-16 09:54:57 +0000
commit156d1cd94abe1d84c9c789f2ecdab3d9319bffcb (patch)
tree3ee443a3e14741f6dd44b063356acc99a9b68dad /sys
parent9ff4f18864dd67b440e023a4a65daa2bffbc495c (diff)
downloadFreeBSD-src-156d1cd94abe1d84c9c789f2ecdab3d9319bffcb.zip
FreeBSD-src-156d1cd94abe1d84c9c789f2ecdab3d9319bffcb.tar.gz
new process tracing code from Sean Eric Fagen (sef@kithrup.com).
...also, fixed up the syscall args to make GCC happy.
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/machdep.c169
-rw-r--r--sys/amd64/include/reg.h40
-rw-r--r--sys/i386/i386/machdep.c169
-rw-r--r--sys/i386/include/reg.h40
4 files changed, 394 insertions, 24 deletions
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 61948b0..ae1271f 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.15 1993/11/07 21:47:00 wollman Exp $
+ * $Id: machdep.c,v 1.16 1993/11/13 02:25:02 davidg Exp $
*/
#include "npx.h"
@@ -1239,6 +1239,173 @@ _remque(element)
element->ph_rlink = (struct proc *)0;
}
+/*
+ * The registers are in the frame; the frame is in the user area of
+ * the process in question; when the process is active, the registers
+ * are in "the kernel stack"; when it's not, they're still there, but
+ * things get flipped around. So, since p->p_regs is the whole address
+ * of the register set, take its offset from the kernel stack, and
+ * index into the user block. Don't you just *love* virtual memory?
+ * (I'm starting to think seymour is right...)
+ */
+
+int
+ptrace_set_pc (struct proc *p, unsigned int addr) {
+ struct pcb *pcb;
+ void *regs = (char*)p->p_addr +
+ ((char*) p->p_regs - (char*) kstack);
+
+ pcb = &p->p_addr->u_pcb;
+ if (pcb->pcb_flags & FM_TRAP)
+ ((struct trapframe *)regs)->tf_eip = addr;
+ else
+ ((struct syscframe *)regs)->sf_eip = addr;
+ return 0;
+}
+
+int
+ptrace_single_step (struct proc *p) {
+ struct pcb *pcb;
+ void *regs = (char*)p->p_addr +
+ ((char*) p->p_regs - (char*) kstack);
+
+ pcb = &p->p_addr->u_pcb;
+ if (pcb->pcb_flags & FM_TRAP)
+ ((struct trapframe *)regs)->tf_eflags |= PSL_T;
+ else
+ ((struct syscframe *)regs)->sf_eflags |= PSL_T;
+ return 0;
+}
+
+/*
+ * Copy the registers to user-space. This is tedious because
+ * we essentially duplicate code for trapframe and syscframe. *sigh*
+ */
+
+int
+ptrace_getregs (struct proc *p, unsigned int *addr) {
+ int error;
+ struct regs regs = {0};
+
+ if (error = fill_regs (p, &regs))
+ return error;
+
+ return copyout (&regs, addr, sizeof (regs));
+}
+
+int
+ptrace_setregs (struct proc *p, unsigned int *addr) {
+ int error;
+ struct regs regs = {0};
+
+ if (error = copyin (addr, &regs, sizeof(regs)))
+ return error;
+
+ return set_regs (p, &regs);
+}
+
+int
+fill_regs(struct proc *p, struct regs *regs) {
+ int error;
+ struct trapframe *tp;
+ struct syscframe *sp;
+ struct pcb *pcb;
+ void *ptr = (char*)p->p_addr +
+ ((char*) p->p_regs - (char*) kstack);
+
+ pcb = &p->p_addr->u_pcb;
+ if (pcb->pcb_flags & FM_TRAP) {
+ tp = ptr;
+ regs->r_es = tp->tf_es;
+ regs->r_ds = tp->tf_ds;
+ regs->r_edi = tp->tf_edi;
+ regs->r_esi = tp->tf_esi;
+ regs->r_ebp = tp->tf_ebp;
+ regs->r_ebx = tp->tf_ebx;
+ regs->r_edx = tp->tf_edx;
+ regs->r_ecx = tp->tf_ecx;
+ regs->r_eax = tp->tf_eax;
+ regs->r_eip = tp->tf_eip;
+ regs->r_cs = tp->tf_cs;
+ regs->r_eflags = tp->tf_eflags;
+ regs->r_esp = tp->tf_esp;
+ regs->r_ss = tp->tf_ss;
+ } else {
+ sp = ptr;
+ /*
+ * No sf_es or sf_ds... dunno why.
+ */
+ /*
+ * regs.r_es = sp->sf_es;
+ * regs.r_ds = sp->sf_ds;
+ */
+ regs->r_edi = sp->sf_edi;
+ regs->r_esi = sp->sf_esi;
+ regs->r_ebp = sp->sf_ebp;
+ regs->r_ebx = sp->sf_ebx;
+ regs->r_edx = sp->sf_edx;
+ regs->r_ecx = sp->sf_ecx;
+ regs->r_eax = sp->sf_eax;
+ regs->r_eip = sp->sf_eip;
+ regs->r_cs = sp->sf_cs;
+ regs->r_eflags = sp->sf_eflags;
+ regs->r_esp = sp->sf_esp;
+ regs->r_ss = sp->sf_ss;
+ }
+ return 0;
+}
+
+int
+set_regs (struct proc *p, struct regs *regs) {
+ int error;
+ struct trapframe *tp;
+ struct syscframe *sp;
+ struct pcb *pcb;
+ void *ptr = (char*)p->p_addr +
+ ((char*) p->p_regs - (char*) kstack);
+
+ pcb = &p->p_addr->u_pcb;
+ if (pcb->pcb_flags & FM_TRAP) {
+ tp = ptr;
+ tp->tf_es = regs->r_es;
+ tp->tf_ds = regs->r_ds;
+ tp->tf_edi = regs->r_edi;
+ tp->tf_esi = regs->r_esi;
+ tp->tf_ebp = regs->r_ebp;
+ tp->tf_ebx = regs->r_ebx;
+ tp->tf_edx = regs->r_edx;
+ tp->tf_ecx = regs->r_ecx;
+ tp->tf_eax = regs->r_eax;
+ tp->tf_eip = regs->r_eip;
+ tp->tf_cs = regs->r_cs;
+ tp->tf_eflags = regs->r_eflags;
+ tp->tf_esp = regs->r_esp;
+ tp->tf_ss = regs->r_ss;
+ } else {
+ sp = ptr;
+ /*
+ * No sf_es or sf_ds members, dunno why...
+ */
+ /*
+ * sp->sf_es = regs.r_es;
+ * sp->sf_ds = regs.r_ds;
+ */
+ sp->sf_edi = regs->r_edi;
+ sp->sf_esi = regs->r_esi;
+ sp->sf_ebp = regs->r_ebp;
+ sp->sf_ebx = regs->r_ebx;
+ sp->sf_edx = regs->r_edx;
+ sp->sf_ecx = regs->r_ecx;
+ sp->sf_eax = regs->r_eax;
+ sp->sf_eip = regs->r_eip;
+ sp->sf_cs = regs->r_cs;
+ sp->sf_eflags = regs->r_eflags;
+ sp->sf_esp = regs->r_esp;
+ sp->sf_ss = regs->r_ss;
+ }
+ return 0;
+}
+
#ifdef SLOW_OLD_COPYSTRS
vmunaccess() {}
diff --git a/sys/amd64/include/reg.h b/sys/amd64/include/reg.h
index 46f6b80..55f1556 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.2 1993/10/16 14:39:29 rgrimes Exp $
+ * $Id: reg.h,v 1.3 1993/11/07 17:43:07 wollman Exp $
*/
#ifndef _MACHINE_REG_H_
@@ -82,17 +82,35 @@
#define sESP (11)
#define sSS (12)
-#define PC sEIP
-#define SP sESP
-#define PS sEFLAGS
-#define R0 sEDX
-#define R1 sECX
+#define PC sEIP
+#define SP sESP
+#define PS sEFLAGS
+#define R0 sEDX
+#define R1 sECX
+
/*
* Registers accessible to ptrace(2) syscall for debugger
+ * The machine-dependent code for PT_{SET,GET}REGS needs to
+ * use whichver order, defined above, is correct, so that it
+ * is all invisible to the user.
*/
-#ifdef IPCREG
-#define NIPCREG 14
-int ipcreg[NIPCREG] =
- { tES,tDS,tEDI,tESI,tEBP,tEBX,tEDX,tECX,tEAX,tEIP,tCS,tEFLAGS,tESP,tSS };
-#endif
+struct regs {
+ unsigned int r_es;
+ unsigned int r_ds;
+ unsigned int r_edi;
+ unsigned int r_esi;
+ unsigned int r_ebp;
+ unsigned int r_ebx;
+ unsigned int r_edx;
+ unsigned int r_ecx;
+ unsigned int r_eax;
+ unsigned int r_eip;
+ unsigned int r_cs;
+ unsigned int r_eflags;
+ unsigned int r_esp;
+ unsigned int r_ss;
+ unsigned int r_fs;
+ unsigned int r_gs;
+};
+
#endif /* _MACHINE_REG_H_ */
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index 61948b0..ae1271f 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.15 1993/11/07 21:47:00 wollman Exp $
+ * $Id: machdep.c,v 1.16 1993/11/13 02:25:02 davidg Exp $
*/
#include "npx.h"
@@ -1239,6 +1239,173 @@ _remque(element)
element->ph_rlink = (struct proc *)0;
}
+/*
+ * The registers are in the frame; the frame is in the user area of
+ * the process in question; when the process is active, the registers
+ * are in "the kernel stack"; when it's not, they're still there, but
+ * things get flipped around. So, since p->p_regs is the whole address
+ * of the register set, take its offset from the kernel stack, and
+ * index into the user block. Don't you just *love* virtual memory?
+ * (I'm starting to think seymour is right...)
+ */
+
+int
+ptrace_set_pc (struct proc *p, unsigned int addr) {
+ struct pcb *pcb;
+ void *regs = (char*)p->p_addr +
+ ((char*) p->p_regs - (char*) kstack);
+
+ pcb = &p->p_addr->u_pcb;
+ if (pcb->pcb_flags & FM_TRAP)
+ ((struct trapframe *)regs)->tf_eip = addr;
+ else
+ ((struct syscframe *)regs)->sf_eip = addr;
+ return 0;
+}
+
+int
+ptrace_single_step (struct proc *p) {
+ struct pcb *pcb;
+ void *regs = (char*)p->p_addr +
+ ((char*) p->p_regs - (char*) kstack);
+
+ pcb = &p->p_addr->u_pcb;
+ if (pcb->pcb_flags & FM_TRAP)
+ ((struct trapframe *)regs)->tf_eflags |= PSL_T;
+ else
+ ((struct syscframe *)regs)->sf_eflags |= PSL_T;
+ return 0;
+}
+
+/*
+ * Copy the registers to user-space. This is tedious because
+ * we essentially duplicate code for trapframe and syscframe. *sigh*
+ */
+
+int
+ptrace_getregs (struct proc *p, unsigned int *addr) {
+ int error;
+ struct regs regs = {0};
+
+ if (error = fill_regs (p, &regs))
+ return error;
+
+ return copyout (&regs, addr, sizeof (regs));
+}
+
+int
+ptrace_setregs (struct proc *p, unsigned int *addr) {
+ int error;
+ struct regs regs = {0};
+
+ if (error = copyin (addr, &regs, sizeof(regs)))
+ return error;
+
+ return set_regs (p, &regs);
+}
+
+int
+fill_regs(struct proc *p, struct regs *regs) {
+ int error;
+ struct trapframe *tp;
+ struct syscframe *sp;
+ struct pcb *pcb;
+ void *ptr = (char*)p->p_addr +
+ ((char*) p->p_regs - (char*) kstack);
+
+ pcb = &p->p_addr->u_pcb;
+ if (pcb->pcb_flags & FM_TRAP) {
+ tp = ptr;
+ regs->r_es = tp->tf_es;
+ regs->r_ds = tp->tf_ds;
+ regs->r_edi = tp->tf_edi;
+ regs->r_esi = tp->tf_esi;
+ regs->r_ebp = tp->tf_ebp;
+ regs->r_ebx = tp->tf_ebx;
+ regs->r_edx = tp->tf_edx;
+ regs->r_ecx = tp->tf_ecx;
+ regs->r_eax = tp->tf_eax;
+ regs->r_eip = tp->tf_eip;
+ regs->r_cs = tp->tf_cs;
+ regs->r_eflags = tp->tf_eflags;
+ regs->r_esp = tp->tf_esp;
+ regs->r_ss = tp->tf_ss;
+ } else {
+ sp = ptr;
+ /*
+ * No sf_es or sf_ds... dunno why.
+ */
+ /*
+ * regs.r_es = sp->sf_es;
+ * regs.r_ds = sp->sf_ds;
+ */
+ regs->r_edi = sp->sf_edi;
+ regs->r_esi = sp->sf_esi;
+ regs->r_ebp = sp->sf_ebp;
+ regs->r_ebx = sp->sf_ebx;
+ regs->r_edx = sp->sf_edx;
+ regs->r_ecx = sp->sf_ecx;
+ regs->r_eax = sp->sf_eax;
+ regs->r_eip = sp->sf_eip;
+ regs->r_cs = sp->sf_cs;
+ regs->r_eflags = sp->sf_eflags;
+ regs->r_esp = sp->sf_esp;
+ regs->r_ss = sp->sf_ss;
+ }
+ return 0;
+}
+
+int
+set_regs (struct proc *p, struct regs *regs) {
+ int error;
+ struct trapframe *tp;
+ struct syscframe *sp;
+ struct pcb *pcb;
+ void *ptr = (char*)p->p_addr +
+ ((char*) p->p_regs - (char*) kstack);
+
+ pcb = &p->p_addr->u_pcb;
+ if (pcb->pcb_flags & FM_TRAP) {
+ tp = ptr;
+ tp->tf_es = regs->r_es;
+ tp->tf_ds = regs->r_ds;
+ tp->tf_edi = regs->r_edi;
+ tp->tf_esi = regs->r_esi;
+ tp->tf_ebp = regs->r_ebp;
+ tp->tf_ebx = regs->r_ebx;
+ tp->tf_edx = regs->r_edx;
+ tp->tf_ecx = regs->r_ecx;
+ tp->tf_eax = regs->r_eax;
+ tp->tf_eip = regs->r_eip;
+ tp->tf_cs = regs->r_cs;
+ tp->tf_eflags = regs->r_eflags;
+ tp->tf_esp = regs->r_esp;
+ tp->tf_ss = regs->r_ss;
+ } else {
+ sp = ptr;
+ /*
+ * No sf_es or sf_ds members, dunno why...
+ */
+ /*
+ * sp->sf_es = regs.r_es;
+ * sp->sf_ds = regs.r_ds;
+ */
+ sp->sf_edi = regs->r_edi;
+ sp->sf_esi = regs->r_esi;
+ sp->sf_ebp = regs->r_ebp;
+ sp->sf_ebx = regs->r_ebx;
+ sp->sf_edx = regs->r_edx;
+ sp->sf_ecx = regs->r_ecx;
+ sp->sf_eax = regs->r_eax;
+ sp->sf_eip = regs->r_eip;
+ sp->sf_cs = regs->r_cs;
+ sp->sf_eflags = regs->r_eflags;
+ sp->sf_esp = regs->r_esp;
+ sp->sf_ss = regs->r_ss;
+ }
+ return 0;
+}
+
#ifdef SLOW_OLD_COPYSTRS
vmunaccess() {}
diff --git a/sys/i386/include/reg.h b/sys/i386/include/reg.h
index 46f6b80..55f1556 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.2 1993/10/16 14:39:29 rgrimes Exp $
+ * $Id: reg.h,v 1.3 1993/11/07 17:43:07 wollman Exp $
*/
#ifndef _MACHINE_REG_H_
@@ -82,17 +82,35 @@
#define sESP (11)
#define sSS (12)
-#define PC sEIP
-#define SP sESP
-#define PS sEFLAGS
-#define R0 sEDX
-#define R1 sECX
+#define PC sEIP
+#define SP sESP
+#define PS sEFLAGS
+#define R0 sEDX
+#define R1 sECX
+
/*
* Registers accessible to ptrace(2) syscall for debugger
+ * The machine-dependent code for PT_{SET,GET}REGS needs to
+ * use whichver order, defined above, is correct, so that it
+ * is all invisible to the user.
*/
-#ifdef IPCREG
-#define NIPCREG 14
-int ipcreg[NIPCREG] =
- { tES,tDS,tEDI,tESI,tEBP,tEBX,tEDX,tECX,tEAX,tEIP,tCS,tEFLAGS,tESP,tSS };
-#endif
+struct regs {
+ unsigned int r_es;
+ unsigned int r_ds;
+ unsigned int r_edi;
+ unsigned int r_esi;
+ unsigned int r_ebp;
+ unsigned int r_ebx;
+ unsigned int r_edx;
+ unsigned int r_ecx;
+ unsigned int r_eax;
+ unsigned int r_eip;
+ unsigned int r_cs;
+ unsigned int r_eflags;
+ unsigned int r_esp;
+ unsigned int r_ss;
+ unsigned int r_fs;
+ unsigned int r_gs;
+};
+
#endif /* _MACHINE_REG_H_ */
OpenPOWER on IntegriCloud