From: William F. Jolitz Date: Tue, 14 Jul 1992 03:15:34 +0000 (-0800) Subject: 386BSD 0.1 development X-Git-Tag: 386BSD-0.1~21 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/49a24fe22707a0819ffb5a4027756e22d5a85bc4 386BSD 0.1 development Work on file usr/src/sys.386bsd/kern/sys_process.c Co-Authored-By: Lynne Greer Jolitz Synthesized-from: 386BSD-0.1 --- diff --git a/usr/src/sys.386bsd/kern/sys_process.c b/usr/src/sys.386bsd/kern/sys_process.c new file mode 100644 index 0000000000..d965256c7c --- /dev/null +++ b/usr/src/sys.386bsd/kern/sys_process.c @@ -0,0 +1,415 @@ +/* + * Copyright (c) 1982, 1986, 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)sys_process.c 7.22 (Berkeley) 5/11/91 + */ + +#define IPCREG +#include "param.h" +#include "proc.h" +#include "vnode.h" +#include "buf.h" +#include "ptrace.h" + +#include "machine/reg.h" +#include "machine/psl.h" +#include "vm/vm.h" +#include "vm/vm_page.h" + +#include "user.h" + +/* + * NOTES. + * + * The following ptrace calls have been defined in addition to + * the standard ones found in original : + * + * PT_ATTACH - attach to running process + * PT_DETACH - detach from running process + * PT_SYSCALL - trace system calls + * PT_GETREG - get register file + * PT_SETREG - set register file + * PT_BREAD_[IDU] - block read from process (not yet implemented) + * PT_BWRITE_[IDU] - block write " " + * PT_INHERIT - make forked processes inherit trace flags + * + */ + +/* Define to prevent extraneous clutter in source */ +#ifndef SSTRC +#define SSTRC 0 +#endif +#ifndef SFTRC +#define SFTRC 0 +#endif + +/* + * `ipcreg' defined in + * Should we define a structure with all regs? + */ +int sipcreg[NIPCREG] = + { 0,0,sEDI,sESI,sEBP,sEBX,sEDX,sECX,sEAX,sEIP,sCS,sEFLAGS,sESP,sSS }; + +struct { + int flag; +#define IPC_BUSY 1 +#define IPC_WANT 2 +#define IPC_DONE 4 + int req; /* copy of ptrace request */ + int *addr; /* copy of ptrace address */ + int data; /* copy of ptrace data */ + int error; /* errno from `procxmt' */ + int regs[NIPCREG]; /* PT_[GS]ETREG */ + caddr_t buf; /* PT_BREAD/WRITE */ + int buflen; /* " */ +} ipc; + +/* + * Process debugging system call. + */ +ptrace(curp, uap, retval) + struct proc *curp; + register struct args { + int req; + int pid; + int *addr; + int data; + } *uap; + int *retval; +{ + struct proc *p; + int s, error = 0; + + *retval = 0; + if (uap->req == PT_TRACE_ME) { + curp->p_flag |= STRC; + /*p->p_tptr = p->p_pptr; * What shall we do here ? */ + return 0; + } + if ((p = pfind(uap->pid)) == NULL) { + return ESRCH; + } + +#ifdef notyet + if (uap->req != PT_ATTACH && ( + (p->p_flag & STRC) == 0 || + (p->p_tptr && curp != p->p_tptr) || + (!p->p_tptr && curp != p->p_pptr))) + + return ESRCH; +#endif + + +#ifdef PT_ATTACH + switch (uap->req) { + case PT_ATTACH: + if (curp->p_ucred->cr_uid != 0 && ( + curp->p_ucred->cr_uid != p->p_ucred->cr_uid || + curp->p_ucred->cr_uid != p->p_cred->p_svuid)) + return EACCES; + + p->p_tptr = curp; + p->p_flag |= STRC; + psignal(p, SIGTRAP); + return 0; + + case PT_DETACH: + if ((unsigned)uap->data >= NSIG) + return EINVAL; + p->p_flag &= ~(STRC|SSTRC|SFTRC); + p->p_tptr = NULL; + psignal(p->p_pptr, SIGCHLD); + wakeup((caddr_t)p->p_pptr); + s = splhigh(); + if (p->p_stat == SSTOP) { + p->p_xstat = uap->data; + setrun(p); + } else if (uap->data) { + psignal(p, uap->data); + } + splx(s); + return 0; + +#ifdef PT_INHERIT + case PT_INHERIT: + if ((p->p_flag & STRC) == 0) + return ESRCH; + p->p_flag |= SFTRC; + return 0; +#endif + + default: + break; + } +#endif + + /* Other ptrace calls require target process to be in stopped state */ + if ((p->p_flag & STRC) == 0 || p->p_stat != SSTOP) { + return ESRCH; + } + + /* Acquire the ipc structure */ + while (ipc.flag & IPC_BUSY) { + ipc.flag |= IPC_WANT; + error = tsleep((caddr_t)&ipc, PWAIT|PCATCH, "ipc", 0); + if (error) + goto out; + } + + /* Got it, fill it */ + ipc.flag = IPC_BUSY; + ipc.error = 0; + ipc.req = uap->req; + ipc.addr = uap->addr; + ipc.data = uap->data; + +#ifdef PT_GETREGS + switch (uap->req) { + case PT_SETREGS: + error = copyin((char *)ipc.addr, (char *)ipc.regs, sizeof(ipc.regs)); + if (error) + goto out; + break; + +#ifdef notyet /* requires change in number of args to ptrace syscall */ + case PT_BWRITE_I: + case PT_BWRITE_D: + ipc.buflen = uap->data; + ipc.buf = kmem_alloc_wait(kernelmap, uap->data); + error = copyin((char *)ipc.addr, (char *)ipc.buf, ipc.buflen); + if (error) { + kmem_free_wakeup(kernelmap, ipc.buf, ipc.buflen); + goto out; + } +#endif + default: + break; + } +#endif + + setrun(p); + while ((ipc.flag & IPC_DONE) == 0) { + error = tsleep((caddr_t)&ipc, PWAIT|PCATCH, "ipc", 0); + if (error) + goto out; + } + + *retval = ipc.data; + if (error = ipc.error) + goto out; + +#ifdef PT_GETREGS + switch (uap->req) { + case PT_GETREGS: + error = copyout((char *)ipc.regs, (char *)ipc.addr, sizeof(ipc.regs)); + break; + + case PT_BREAD_I: + case PT_BREAD_D: + /* Not yet */ + default: + break; + } +#endif + +out: + /* Release ipc structure */ + ipc.flag &= ~IPC_BUSY; + if (ipc.flag & IPC_WANT) { + ipc.flag &= ~IPC_WANT; + wakeup((caddr_t)&ipc); + } + return error; +} + +procxmt(p) + register struct proc *p; +{ + int i, *xreg, rv = 0; + + /* Are we still being traced? */ + if ((p->p_flag & STRC) == 0) + return 1; + + p->p_addr->u_kproc.kp_proc = *p; + fill_eproc(p, &p->p_addr->u_kproc.kp_eproc); + + switch (ipc.req) { + case PT_READ_I: + case PT_READ_D: + ipc.error = copyin((char *)ipc.addr, (char *)&ipc.data, sizeof(ipc.data)); + break; + + case PT_READ_U: + if ((u_int)ipc.addr > UPAGES * NBPG - sizeof(int)) { + ipc.error = EFAULT; + break; + } + ipc.data = *(int *)((u_int)p->p_addr + (u_int)ipc.addr); + break; + + case PT_WRITE_I: + case PT_WRITE_D: + ipc.error = copyout((char *)&ipc.data, (char *)ipc.addr, sizeof(ipc.data)); + break; + + case PT_WRITE_U: + if ((u_int)ipc.addr > UPAGES * NBPG - sizeof(int)) { + ipc.error = EFAULT; + break; + } + *(int *)((u_int)p->p_addr + (u_int)ipc.addr) = ipc.data; + break; + + case PT_CONTINUE: + if (ipc.addr != (int *)1) { +#ifdef i386 + p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr; +#endif + } + p->p_flag &= ~SSTRC; /* Only set by PT_SYSCALL */ + if ((unsigned)ipc.data >= NSIG) { + ipc.error = EINVAL; + } else { + p->p_xstat = ipc.data; + rv = 1; + } + break; + + case PT_KILL: + p->p_flag &= ~SSTRC; /* Only set by PT_SYSCALL */ + rv = 2; + break; + + case PT_STEP: +#ifdef i386 + if (ipc.addr != (int *)1) { + p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr; + } + p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEFLAGS:sEFLAGS] |= PSL_T; +#endif + p->p_flag &= ~SSTRC; /* Only set by PT_SYSCALL */ + p->p_xstat = 0; + rv = 1; + break; + +#ifdef PT_SYSCALL + case PT_SYSCALL: + if (ipc.addr != (int *)1) { +#ifdef i386 + p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr; +#endif + } + p->p_flag |= SSTRC; + p->p_xstat = 0; + rv = 1; + break; +#endif +#ifdef PT_GETREGS + case PT_GETREGS: +#ifdef i386 + xreg = (curpcb->pcb_flags&FM_TRAP)?ipcreg:sipcreg; +#endif + + for (i = 0; i < NIPCREG; i++) + ipc.regs[i] = p->p_regs[xreg[i]]; + break; + + case PT_SETREGS: +#ifdef i386 + xreg = (curpcb->pcb_flags&FM_TRAP)?ipcreg:sipcreg; +#endif + + for (i = 0; i < NIPCREG; i++) + p->p_regs[xreg[i]] = ipc.regs[i]; + break; +#endif + +#ifdef PT_DUMP + case PT_DUMP: + /* Should be able to specify core file name */ + ipc.error = coredump(p); + break; +#endif + + default: + ipc.error = EINVAL; + } + ipc.flag |= IPC_DONE; + wakeup((caddr_t)&ipc); + + if (rv == 2) + exit(p, 0); /*???*/ + + return rv; +} + +/* + * Enable process profiling system call. + */ +/* ARGSUSED */ +profil(p, uap, retval) + struct proc *p; + register struct args { + short *bufbase; /* base of data buffer */ + unsigned bufsize; /* size of data buffer */ + unsigned pcoffset; /* pc offset (for subtraction) */ + unsigned pcscale; /* scaling factor for offset pc */ + } *uap; + int *retval; +{ + /* from looking at man pages, and include files, looks like + * this just sets up the fields of p->p_stats->p_prof... + * and those fields come straight from the args. + * only thing *we* have to do is check the args for validity... + * + * cgd + */ + + /* check to make sure that the buffer is OK. addupc (in locore) + * checks for faults, but would one be generated, say, writing to + * kernel space? probably not -- it just uses "movl"... + * + * so we've gotta check to make sure that the info set up for + * addupc is set right... it's gotta be writable by the user... + */ + + if (useracc(uap->bufbase,uap->bufsize*sizeof(short),B_WRITE) == 0) + return EFAULT; + + p->p_stats->p_prof.pr_base = uap->bufbase; + p->p_stats->p_prof.pr_size = uap->bufsize; + p->p_stats->p_prof.pr_off = uap->pcoffset; + p->p_stats->p_prof.pr_scale = uap->pcscale; + + return 0; +}