Annotation of Net2/kern/sys_process.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by the University of
                     16:  *     California, Berkeley and its contributors.
                     17:  * 4. Neither the name of the University nor the names of its contributors
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  *
                     33:  *     from: @(#)sys_process.c 7.22 (Berkeley) 5/11/91
                     34:  */
                     35: 
                     36: #define IPCREG
                     37: #include "param.h"
                     38: #include "proc.h"
                     39: #include "vnode.h"
                     40: #include "buf.h"
                     41: #include "ptrace.h"
                     42: 
                     43: #include "machine/reg.h"
                     44: #include "machine/psl.h"
                     45: #include "vm/vm.h"
                     46: #include "vm/vm_page.h"
                     47: 
                     48: #include "user.h"
                     49: 
                     50: /*
1.1.1.3 ! root       51:  * NOTES.
        !            52:  *
        !            53:  * The following ptrace calls have been defined in addition to
        !            54:  * the standard ones found in original <sys/ptrace.h>:
        !            55:  *
        !            56:  * PT_ATTACH           -       attach to running process
        !            57:  * PT_DETACH           -       detach from running process
        !            58:  * PT_SYSCALL          -       trace system calls
        !            59:  * PT_GETREG           -       get register file
        !            60:  * PT_SETREG           -       set register file
        !            61:  * PT_BREAD_[IDU]      -       block read from process (not yet implemented)
        !            62:  * PT_BWRITE_[IDU]     -       block write     "               "
        !            63:  * PT_INHERIT          -       make forked processes inherit trace flags
        !            64:  *
        !            65:  */
        !            66: 
        !            67: /* Define to prevent extraneous clutter in source */
        !            68: #ifndef SSTRC
        !            69: #define        SSTRC   0
        !            70: #endif
        !            71: #ifndef SFTRC
        !            72: #define        SFTRC   0
        !            73: #endif
        !            74: 
        !            75: /*
        !            76:  * `ipcreg' defined in <machine/reg.h>
        !            77:  * Should we define a structure with all regs?
        !            78:  */
        !            79: int sipcreg[NIPCREG] =
        !            80:   { 0,0,sEDI,sESI,sEBP,sEBX,sEDX,sECX,sEAX,sEIP,sCS,sEFLAGS,sESP,sSS };
        !            81: 
        !            82: struct {
        !            83:        int     flag;
        !            84: #define IPC_BUSY       1
        !            85: #define IPC_WANT       2
        !            86: #define IPC_DONE       4
        !            87:        int     req;                    /* copy of ptrace request */
        !            88:        int     *addr;                  /* copy of ptrace address */
        !            89:        int     data;                   /* copy of ptrace data */
        !            90:        int     error;                  /* errno from `procxmt' */
        !            91:        int     regs[NIPCREG];          /* PT_[GS]ETREG */
        !            92:        caddr_t buf;                    /* PT_BREAD/WRITE */
        !            93:        int     buflen;                 /*      "       */
        !            94: } ipc;
        !            95: 
        !            96: /*
1.1       root       97:  * Process debugging system call.
                     98:  */
                     99: ptrace(curp, uap, retval)
                    100:        struct proc *curp;
                    101:        register struct args {
                    102:                int     req;
                    103:                int     pid;
                    104:                int     *addr;
                    105:                int     data;
                    106:        } *uap;
                    107:        int *retval;
                    108: {
1.1.1.3 ! root      109:        struct proc *p;
        !           110:        int s, error = 0;
1.1       root      111: 
1.1.1.3 ! root      112:        *retval = 0;
        !           113:        if (uap->req == PT_TRACE_ME) {
        !           114:                curp->p_flag |= STRC;
        !           115:                /*p->p_tptr = p->p_pptr; * What shall we do here ? */
        !           116:                return 0;
        !           117:        }
        !           118:        if ((p = pfind(uap->pid)) == NULL) {
        !           119:                return ESRCH;
        !           120:        }
        !           121: 
        !           122: #ifdef notyet
        !           123:        if (uap->req != PT_ATTACH && (
        !           124:                        (p->p_flag & STRC) == 0 ||
        !           125:                        (p->p_tptr && curp != p->p_tptr) ||
        !           126:                        (!p->p_tptr && curp != p->p_pptr)))
        !           127: 
        !           128:                return ESRCH;
        !           129: #endif
        !           130: 
        !           131: 
        !           132: #ifdef PT_ATTACH
        !           133:        switch (uap->req) {
        !           134:        case PT_ATTACH:
        !           135:                if (curp->p_ucred->cr_uid != 0 && (
        !           136:                        curp->p_ucred->cr_uid != p->p_ucred->cr_uid ||
        !           137:                        curp->p_ucred->cr_uid != p->p_cred->p_svuid))
        !           138:                        return EACCES;
        !           139: 
        !           140:                p->p_tptr = curp;
        !           141:                p->p_flag |= STRC;
        !           142:                psignal(p, SIGTRAP);
        !           143:                return 0;
        !           144: 
        !           145:        case PT_DETACH:
        !           146:                if ((unsigned)uap->data >= NSIG)
        !           147:                        return EINVAL;
        !           148:                p->p_flag &= ~(STRC|SSTRC|SFTRC);
        !           149:                p->p_tptr = NULL;
        !           150:                psignal(p->p_pptr, SIGCHLD);
        !           151:                wakeup((caddr_t)p->p_pptr);
        !           152:                s = splhigh();
        !           153:                if (p->p_stat == SSTOP) {
        !           154:                        p->p_xstat = uap->data;
        !           155:                        setrun(p);
        !           156:                } else if (uap->data) {
        !           157:                        psignal(p, uap->data);
        !           158:                }
        !           159:                splx(s);
        !           160:                return 0;
        !           161: 
        !           162: #ifdef PT_INHERIT
        !           163:        case PT_INHERIT:
        !           164:                if ((p->p_flag & STRC) == 0)
        !           165:                        return ESRCH;
        !           166:                p->p_flag |= SFTRC;
        !           167:                return 0;
        !           168: #endif
        !           169: 
        !           170:        default:
        !           171:                break;
        !           172:        }
        !           173: #endif
        !           174: 
        !           175:        /* Other ptrace calls require target process to be in stopped state */
        !           176:        if ((p->p_flag & STRC) == 0 || p->p_stat != SSTOP) {
        !           177:                return ESRCH;
        !           178:        }
        !           179: 
        !           180:        /* Acquire the ipc structure */
        !           181:        while (ipc.flag & IPC_BUSY) {
        !           182:                ipc.flag |= IPC_WANT;
        !           183:                error = tsleep((caddr_t)&ipc, PWAIT|PCATCH, "ipc", 0);
        !           184:                if (error)
        !           185:                        goto out;
        !           186:        }
        !           187: 
        !           188:        /* Got it, fill it */
        !           189:        ipc.flag = IPC_BUSY;
        !           190:        ipc.error = 0;
        !           191:        ipc.req = uap->req;
        !           192:        ipc.addr = uap->addr;
        !           193:        ipc.data = uap->data;
        !           194: 
        !           195: #ifdef PT_GETREGS
        !           196:        switch (uap->req) {
        !           197:        case PT_SETREGS:
        !           198:                error = copyin((char *)ipc.addr, (char *)ipc.regs, sizeof(ipc.regs));
        !           199:                if (error)
        !           200:                        goto out;
        !           201:                break;
        !           202: 
        !           203: #ifdef notyet  /* requires change in number of args to ptrace syscall */
        !           204:        case PT_BWRITE_I:
        !           205:        case PT_BWRITE_D:
        !           206:                ipc.buflen = uap->data;
        !           207:                ipc.buf = kmem_alloc_wait(kernelmap, uap->data);
        !           208:                error = copyin((char *)ipc.addr, (char *)ipc.buf, ipc.buflen);
        !           209:                if (error) {
        !           210:                        kmem_free_wakeup(kernelmap, ipc.buf, ipc.buflen);
        !           211:                        goto out;
        !           212:                }
        !           213: #endif
        !           214:        default:
        !           215:                break;
        !           216:        }
        !           217: #endif
        !           218: 
        !           219:        setrun(p);
        !           220:        while ((ipc.flag & IPC_DONE) == 0) {
        !           221:                error = tsleep((caddr_t)&ipc, PWAIT|PCATCH, "ipc", 0);
        !           222:                if (error)
        !           223:                        goto out;
        !           224:        }
        !           225: 
        !           226:        *retval = ipc.data;
        !           227:        if (error = ipc.error)
        !           228:                goto out;
        !           229: 
        !           230: #ifdef PT_GETREGS
        !           231:        switch (uap->req) {
        !           232:        case PT_GETREGS:
        !           233:                error = copyout((char *)ipc.regs, (char *)ipc.addr, sizeof(ipc.regs));
        !           234:                break;
        !           235: 
        !           236:        case PT_BREAD_I:
        !           237:        case PT_BREAD_D:
        !           238:                /* Not yet */
        !           239:        default:
        !           240:                break;
        !           241:        }
        !           242: #endif
        !           243: 
        !           244: out:
        !           245:        /* Release ipc structure */
        !           246:        ipc.flag &= ~IPC_BUSY;
        !           247:        if (ipc.flag & IPC_WANT) {
        !           248:                ipc.flag &= ~IPC_WANT;
        !           249:                wakeup((caddr_t)&ipc);
        !           250:        }
        !           251:        return error;
1.1       root      252: }
                    253: 
                    254: procxmt(p)
                    255:        register struct proc *p;
                    256: {
1.1.1.3 ! root      257:        int i, *xreg, rv = 0;
1.1       root      258: 
1.1.1.3 ! root      259:        /* Are we still being traced? */
        !           260:        if ((p->p_flag & STRC) == 0)
        !           261:                return 1;
        !           262: 
        !           263:        p->p_addr->u_kproc.kp_proc = *p;
        !           264:        fill_eproc(p, &p->p_addr->u_kproc.kp_eproc);
        !           265: 
        !           266:        switch (ipc.req) {
        !           267:        case PT_READ_I:
        !           268:        case PT_READ_D:
        !           269:                ipc.error = copyin((char *)ipc.addr, (char *)&ipc.data, sizeof(ipc.data));
        !           270:                break;
        !           271: 
        !           272:        case PT_READ_U:
        !           273:                if ((u_int)ipc.addr > UPAGES * NBPG - sizeof(int)) {
        !           274:                        ipc.error = EFAULT;
        !           275:                        break;
        !           276:                }
        !           277:                ipc.data = *(int *)((u_int)p->p_addr + (u_int)ipc.addr);
        !           278:                break;
        !           279: 
        !           280:        case PT_WRITE_I:
        !           281:        case PT_WRITE_D:
        !           282:                ipc.error = copyout((char *)&ipc.data, (char *)ipc.addr, sizeof(ipc.data));
        !           283:                break;
        !           284: 
        !           285:        case PT_WRITE_U:
        !           286:                if ((u_int)ipc.addr > UPAGES * NBPG - sizeof(int)) {
        !           287:                        ipc.error = EFAULT;
        !           288:                        break;
        !           289:                }
        !           290:                *(int *)((u_int)p->p_addr + (u_int)ipc.addr) = ipc.data;
        !           291:                break;
        !           292: 
        !           293:        case PT_CONTINUE:
        !           294:                if (ipc.addr != (int *)1) {
        !           295: #ifdef i386
        !           296:                        p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr;
        !           297: #endif
        !           298:                }
        !           299:                p->p_flag &= ~SSTRC;    /* Only set by PT_SYSCALL */
        !           300:                if ((unsigned)ipc.data >= NSIG) {
        !           301:                        ipc.error = EINVAL;
        !           302:                } else {
        !           303:                        p->p_xstat = ipc.data;
        !           304:                        rv = 1;
        !           305:                }
        !           306:                break;
        !           307: 
        !           308:        case PT_KILL:
        !           309:                p->p_flag &= ~SSTRC;    /* Only set by PT_SYSCALL */
        !           310:                rv = 2;
        !           311:                break;
        !           312: 
        !           313:        case PT_STEP:
        !           314: #ifdef i386
        !           315:                if (ipc.addr != (int *)1) {
        !           316:                        p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr;
        !           317:                }
        !           318:                p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEFLAGS:sEFLAGS] |= PSL_T;
        !           319: #endif
        !           320:                p->p_flag &= ~SSTRC;    /* Only set by PT_SYSCALL */
        !           321:                p->p_xstat = 0;
        !           322:                rv = 1;
        !           323:                break;
        !           324: 
        !           325: #ifdef PT_SYSCALL
        !           326:        case PT_SYSCALL:
        !           327:                if (ipc.addr != (int *)1) {
        !           328: #ifdef i386
        !           329:                        p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr;
        !           330: #endif
        !           331:                }
        !           332:                p->p_flag |= SSTRC;
        !           333:                p->p_xstat = 0;
        !           334:                rv = 1;
        !           335:                break;
        !           336: #endif
        !           337: #ifdef PT_GETREGS
        !           338:        case PT_GETREGS:
        !           339: #ifdef i386
        !           340:                xreg = (curpcb->pcb_flags&FM_TRAP)?ipcreg:sipcreg;
        !           341: #endif
        !           342: 
        !           343:                for (i = 0; i < NIPCREG; i++)
        !           344:                        ipc.regs[i] = p->p_regs[xreg[i]];
        !           345:                break;
        !           346: 
        !           347:        case PT_SETREGS:
        !           348: #ifdef i386
        !           349:                xreg = (curpcb->pcb_flags&FM_TRAP)?ipcreg:sipcreg;
        !           350: #endif
        !           351: 
        !           352:                for (i = 0; i < NIPCREG; i++)
        !           353:                        p->p_regs[xreg[i]] = ipc.regs[i];
        !           354:                break;
        !           355: #endif
        !           356: 
        !           357: #ifdef PT_DUMP
        !           358:        case PT_DUMP:
        !           359:                /* Should be able to specify core file name */
        !           360:                ipc.error = coredump(p);
        !           361:                break;
        !           362: #endif
        !           363: 
        !           364:        default:
        !           365:                ipc.error = EINVAL;
        !           366:        }
        !           367:        ipc.flag |= IPC_DONE;
        !           368:        wakeup((caddr_t)&ipc);
        !           369: 
        !           370:        if (rv == 2)
        !           371:                exit(p, 0);     /*???*/
        !           372: 
        !           373:        return rv;
1.1       root      374: }
                    375: 
                    376: /*
                    377:  * Enable process profiling system call.
                    378:  */
                    379: /* ARGSUSED */
                    380: profil(p, uap, retval)
                    381:        struct proc *p;
                    382:        register struct args {
1.1.1.3 ! root      383:                short   *bufbase;       /* base of data buffer */
        !           384:                unsigned bufsize;       /* size of data buffer */
        !           385:                unsigned pcoffset;      /* pc offset (for subtraction) */
        !           386:                unsigned pcscale;       /* scaling factor for offset pc */
1.1       root      387:        } *uap;
                    388:        int *retval;
                    389: {
1.1.1.3 ! root      390:        /* from looking at man pages, and include files, looks like
        !           391:         * this just sets up the fields of p->p_stats->p_prof...
        !           392:         * and those fields come straight from the args.
        !           393:         * only thing *we* have to do is check the args for validity...
        !           394:         *
        !           395:         * cgd
        !           396:         */
1.1       root      397: 
1.1.1.3 ! root      398:        /* check to make sure that the buffer is OK.  addupc (in locore)
        !           399:         * checks for faults, but would one be generated, say, writing to
        !           400:         * kernel space?  probably not -- it just uses "movl"...
        !           401:         *
        !           402:         * so we've gotta check to make sure that the info set up for
        !           403:         * addupc is set right... it's gotta be writable by the user...
1.1       root      404:         */
1.1.1.3 ! root      405: 
        !           406:        if (useracc(uap->bufbase,uap->bufsize*sizeof(short),B_WRITE) == 0)
        !           407:                return EFAULT;
        !           408: 
        !           409:        p->p_stats->p_prof.pr_base = uap->bufbase;
        !           410:        p->p_stats->p_prof.pr_size = uap->bufsize;
        !           411:        p->p_stats->p_prof.pr_off = uap->pcoffset;
        !           412:        p->p_stats->p_prof.pr_scale = uap->pcscale;
        !           413: 
        !           414:        return 0;
1.1       root      415: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.