|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.