Only in sys/arch/i386/compile: a Only in sys/arch/i386/conf: a diff -ur sys.orig/arch/i386/i386/process_machdep.c sys/arch/i386/i386/process_machdep.c --- sys.orig/arch/i386/i386/process_machdep.c 2004-01-28 10:48:55.000000000 +0000 +++ sys/arch/i386/i386/process_machdep.c 2005-04-09 23:02:51.000000000 +0000 @@ -212,6 +212,113 @@ } int +process_doregsv(l, addr, len, version, write) + struct lwp *l; /* traced */ + void *addr; + int len, version, write; +{ + struct regv1 regv1; + struct trapframe *tf = process_frame(l); + struct pcb *pcb = &l->l_addr->u_pcb; + int error; + + switch (version) { + case 1: + if (len != sizeof(regv1)) + return EINVAL; + if (write) { + error = copyin(addr, ®v1, sizeof(regv1)); + if (error) + return (error); +#ifdef VM86 + if (regv1.r_eflags & PSL_VM) { + void syscall_vm86(struct trapframe *); + + tf->tf_vm86_gs = regv1.r_gs; + tf->tf_vm86_fs = regv1.r_fs; + tf->tf_vm86_es = regv1.r_es; + tf->tf_vm86_ds = regv1.r_ds; + set_vflags(l, regv1.r_eflags); + l->l_proc->p_md.md_syscall = syscall_vm86; + } else +#endif + { + /* + * Check for security violations. + */ + if (((regv1.r_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 || + !USERMODE(regv1.r_cs, regv1.r_eflags)) + return (EINVAL); + + tf->tf_gs = regv1.r_gs; + tf->tf_fs = regv1.r_fs; + tf->tf_es = regv1.r_es; + tf->tf_ds = regv1.r_ds; +#ifdef VM86 + if (tf->tf_eflags & PSL_VM) + (*l->l_proc->p_emul->e_syscall_intern)(l->l_proc); +#endif + tf->tf_eflags = regv1.r_eflags; + } + tf->tf_edi = regv1.r_edi; + tf->tf_esi = regv1.r_esi; + tf->tf_ebp = regv1.r_ebp; + tf->tf_ebx = regv1.r_ebx; + tf->tf_edx = regv1.r_edx; + tf->tf_ecx = regv1.r_ecx; + tf->tf_eax = regv1.r_eax; + tf->tf_eip = regv1.r_eip; + tf->tf_cs = regv1.r_cs; + tf->tf_esp = regv1.r_esp; + tf->tf_ss = regv1.r_ss; + + /* r_cr2, r_err, and r_trapno are read-only. */ + + return (0); + } else { +#ifdef VM86 + if (tf->tf_eflags & PSL_VM) { + regv1.r_gs = tf->tf_vm86_gs; + regv1.r_fs = tf->tf_vm86_fs; + regv1.r_es = tf->tf_vm86_es; + regv1.r_ds = tf->tf_vm86_ds; + regv1.r_eflags = get_vflags(l); + } else +#endif + { + regv1.r_gs = tf->tf_gs & 0xffff; + regv1.r_fs = tf->tf_fs & 0xffff; + regv1.r_es = tf->tf_es & 0xffff; + regv1.r_ds = tf->tf_ds & 0xffff; + regv1.r_eflags = tf->tf_eflags; + } + regv1.r_edi = tf->tf_edi; + regv1.r_esi = tf->tf_esi; + regv1.r_ebp = tf->tf_ebp; + regv1.r_ebx = tf->tf_ebx; + regv1.r_edx = tf->tf_edx; + regv1.r_ecx = tf->tf_ecx; + regv1.r_eax = tf->tf_eax; + regv1.r_eip = tf->tf_eip; + regv1.r_cs = tf->tf_cs & 0xffff; + regv1.r_esp = tf->tf_esp; + regv1.r_ss = tf->tf_ss & 0xffff; + + regv1.r_cr2 = pcb->pcb_cr2; + regv1.r_err = tf->tf_err; + regv1.r_trapno = tf->tf_trapno & 0xff; + + error = copyout(®v1, addr, sizeof(regv1)); + if (error) + return (error); + return (0); + } + default: + return EINVAL; + } +} + +int process_read_regs(struct lwp *l, struct reg *regs) { struct trapframe *tf = process_frame(l); diff -ur sys.orig/arch/i386/i386/syscall.c sys/arch/i386/i386/syscall.c --- sys.orig/arch/i386/i386/syscall.c 2003-10-31 03:28:13.000000000 +0000 +++ sys/arch/i386/i386/syscall.c 2005-06-06 19:34:02.000000000 +0000 @@ -57,6 +57,7 @@ #include #endif #include +#include #include @@ -72,6 +73,9 @@ void syscall_vm86(struct trapframe *); #endif +/* Macro to test flags. *//* from sys_process.c */ +#define ISSET(t, f) ((t) & (f)) + void syscall_intern(p) struct proc *p; @@ -112,6 +116,14 @@ l = curlwp; p = l->l_proc; + if (ISSET(p->p_flag, P_SYSTRACED)) { + process_systrace(p, l); + } + if (ISSET(p->p_flag, P_SYSEMU)) { + process_systrace(p, l); + goto sysemu; + } + code = frame->tf_eax; callp = p->p_emul->e_sysent; params = (caddr_t)frame->tf_esp + sizeof(int); @@ -187,6 +199,10 @@ #ifdef SYSCALL_DEBUG scdebug_ret(l, code, error, rval); #endif /* SYSCALL_DEBUG */ + if (ISSET(p->p_flag, P_SYSTRACED)) { + process_systrace(p, l); + } +sysemu: userret(l); } @@ -206,6 +222,14 @@ l = curlwp; p = l->l_proc; + if (ISSET(p->p_flag, P_SYSTRACED)) { + process_systrace(p, l); + } + if (ISSET(p->p_flag, P_SYSEMU)) { + process_systrace(p, l); + goto sysemu; + } + code = frame->tf_eax; callp = p->p_emul->e_sysent; params = (caddr_t)frame->tf_esp + sizeof(int); @@ -280,6 +304,10 @@ trace_exit(l, code, args, rval, error); + if (ISSET(p->p_flag, P_SYSTRACED)) { + process_systrace(p, l); + } +sysemu: userret(l); } diff -ur sys.orig/arch/i386/include/ptrace.h sys/arch/i386/include/ptrace.h --- sys.orig/arch/i386/include/ptrace.h 2003-06-29 22:28:27.000000000 +0000 +++ sys/arch/i386/include/ptrace.h 2005-04-09 22:08:40.000000000 +0000 @@ -87,6 +87,10 @@ #define PT_GETXMMREGS (PT_FIRSTMACH + 5) #define PT_SETXMMREGS (PT_FIRSTMACH + 6) +/* PT_{GET,SET}REGS with version and length. */ +#define PT_GETREGSV (PT_FIRSTMACH + 7) +#define PT_SETREGSV (PT_FIRSTMACH + 8) + #ifdef _KERNEL /* diff -ur sys.orig/arch/i386/include/reg.h sys/arch/i386/include/reg.h --- sys.orig/arch/i386/include/reg.h 2003-08-07 16:27:59.000000000 +0000 +++ sys/arch/i386/include/reg.h 2005-04-09 22:08:40.000000000 +0000 @@ -91,6 +91,30 @@ int r_gs; }; +struct regv1 { + int r_len; + int r_version; + int r_eax; + int r_ecx; + int r_edx; + int r_ebx; + int r_esp; + int r_ebp; + int r_esi; + int r_edi; + int r_eip; + int r_eflags; + int r_cs; + int r_ss; + int r_ds; + int r_es; + int r_fs; + int r_gs; + int r_cr2; + int r_err; + int r_trapno; +}; + struct fpreg { /* * XXX diff -ur sys.orig/arch/i386/isa/npx.c sys/arch/i386/isa/npx.c --- sys.orig/arch/i386/isa/npx.c 2004-07-07 17:10:16.000000000 +0000 +++ sys/arch/i386/isa/npx.c 2005-06-06 09:46:17.000000000 +0000 @@ -99,6 +99,8 @@ #include #include #include +#include +#include #include #include @@ -456,6 +458,7 @@ } trapsignal(l, &ksi); + userret(l); } else { /* * This is a nested interrupt. This should only happen when diff -ur sys.orig/kern/kern_sig.c sys/kern/kern_sig.c --- sys.orig/kern/kern_sig.c 2004-10-01 03:46:37.000000000 +0000 +++ sys/kern/kern_sig.c 2005-06-06 09:57:26.000000000 +0000 @@ -70,6 +70,7 @@ #include #include #include +#include #include #include @@ -2500,3 +2501,24 @@ const struct filterops sig_filtops = { 0, filt_sigattach, filt_sigdetach, filt_signal }; + +void +process_systrace(p, l) + struct proc *p; + struct lwp *l; +{ + int s = 0; + int dolock = (l->l_flag & L_SINTR) == 0; + + p->p_xstat = SIGTRAP; + child_psignal(p, dolock); + + if (dolock) + SCHED_LOCK(s); + proc_stop(p, 1); + mi_switch(l, NULL); + + SCHED_ASSERT_UNLOCKED(); + if (dolock) + splx(s); +} diff -ur sys.orig/kern/sys_process.c sys/kern/sys_process.c --- sys.orig/kern/sys_process.c 2004-03-13 18:43:18.000000000 +0000 +++ sys/kern/sys_process.c 2005-06-06 19:35:38.000000000 +0000 @@ -135,6 +135,12 @@ struct iovec iov; struct ptrace_io_desc piod; struct ptrace_lwpinfo pl; +#if defined(PT_SETREGSV) || defined(PT_GETREGSV) + struct { + int r_len; + int r_version; + } regv_header; +#endif int s, error, write, tmp, size; /* "A foolish consistency..." XXX */ @@ -209,6 +215,8 @@ case PT_WRITE_I: case PT_WRITE_D: case PT_CONTINUE: + case PT_SYSCALL: + case PT_SYSEMU: case PT_IO: case PT_KILL: case PT_DETACH: @@ -228,6 +236,12 @@ #ifdef PT_SETFPREGS case PT_SETFPREGS: #endif +#ifdef PT_GETREGSV + case PT_GETREGSV: +#endif +#ifdef PT_SETREGSV + case PT_SETREGSV: +#endif #ifdef __HAVE_PTRACE_MACHDEP PTRACE_MACHDEP_REQUEST_CASES @@ -362,6 +376,8 @@ */ #endif case PT_CONTINUE: + case PT_SYSCALL: + case PT_SYSEMU: case PT_DETACH: /* * From the 4.4BSD PRM: @@ -408,6 +424,16 @@ t->p_opptr = NULL; CLR(t->p_flag, P_TRACED|P_WAITED); } + if (SCARG(uap, req) == PT_SYSCALL) { + SET(t->p_flag, P_SYSTRACED); + } else { + CLR(t->p_flag, P_SYSTRACED); + } + if (SCARG(uap, req) == PT_SYSEMU) { + SET(t->p_flag, P_SYSEMU); + } else { + CLR(t->p_flag, P_SYSEMU); + } sendsig: /* Finally, deliver the requested signal (or none). */ @@ -553,6 +579,37 @@ } #endif +#ifdef PT_SETREGSV + case PT_SETREGSV: + write = 1; +#endif +#ifdef PT_GETREGSV + case PT_GETREGSV: + /* write = 0 done above. */ +#endif +#if defined(PT_SETREGSV) || defined(PT_GETREGSV) + if (!process_validregs(t)) + return (EINVAL); + if ((error = process_checkioperm(p, t)) != 0) + return (error); + error = copyin(SCARG(uap, addr), ®v_header, + sizeof(regv_header)); + if (error) + return (error); + else { + PHOLD(lt); + if (write && t->p_stat != SSTOP) + error = EBUSY; + else + error = process_doregsv (lt, SCARG(uap, addr), + regv_header.r_len, + regv_header.r_version, + write); + PRELE(lt); + return (error); + } +#endif + #ifdef __HAVE_PTRACE_MACHDEP PTRACE_MACHDEP_REQUEST_CASES return (ptrace_machdep_dorequest(p, lt, Only in sys: machine diff -ur sys.orig/sys/proc.h sys/sys/proc.h --- sys.orig/sys/proc.h 2004-08-15 13:54:20.000000000 +0000 +++ sys/sys/proc.h 2005-06-06 19:36:01.000000000 +0000 @@ -298,6 +298,8 @@ #define P_STOPFORK 0x00800000 /* Child will be stopped on fork(2) */ #define P_STOPEXEC 0x01000000 /* Will be stopped on exec(2) */ #define P_STOPEXIT 0x02000000 /* Will be stopped at process exit */ +#define P_SYSTRACED 0x04000000 +#define P_SYSEMU 0x08000000 /* * Macro to compute the exit signal to be delivered. diff -ur sys.orig/sys/ptrace.h sys/sys/ptrace.h --- sys.orig/sys/ptrace.h 2003-08-07 16:34:11.000000000 +0000 +++ sys/sys/ptrace.h 2005-06-06 19:36:25.000000000 +0000 @@ -46,6 +46,8 @@ #define PT_IO 11 /* do I/O to/from the stopped process */ #define PT_DUMPCORE 12 /* make the child generate a core dump */ #define PT_LWPINFO 13 /* get info about the LWP */ +#define PT_SYSCALL 14 /* Continue and stop at the next (return from) syscall. */ +#define PT_SYSEMU 15 #define PT_FIRSTMACH 32 /* for machine-specific requests */ #include /* machine-specific requests, if any */ @@ -94,6 +96,7 @@ int process_domem __P((struct proc *, struct proc *, struct uio *)); int process_checkioperm __P((struct proc *, struct proc *)); +void process_systrace __P((struct proc *, struct lwp *)); void proc_reparent __P((struct proc *, struct proc *)); #ifdef PT_GETFPREGS @@ -110,6 +113,10 @@ #ifdef PT_SETREGS int process_write_regs __P((struct lwp *, struct reg *)); #endif +#if defined(PT_SETREGSV) || defined(PT_GETREGSV) +int process_doregsv __P((struct lwp *p, void *addr, int len, int version, + int write)); +#endif #ifdef __HAVE_PROCFS_MACHDEP int ptrace_machdep_dorequest(struct proc *, struct lwp *, int,