1: /* 2: * Copyright (c) 1980 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: static char sccsid[] = "@(#)ptrace.c 5.1 (Berkeley) 6/6/85"; 9: #endif not lint 10: 11: /* 12: * routines for tracing the execution of a process 13: * 14: * The system call "ptrace" does all the work, these 15: * routines just try to interface easily to it. 16: */ 17: 18: #include "defs.h" 19: #include <signal.h> 20: #include <sys/param.h> 21: #include <machine/reg.h> 22: #include "process.h" 23: #include "object.h" 24: #include "process.rep" 25: 26: # if (isvaxpx) 27: # include "pxinfo.h" 28: # endif 29: 30: #ifndef vax 31: # define U_PAGE 0x2400 32: # define U_AR0 (14*sizeof(int)) 33: LOCAL int ar0val = -1; 34: #endif 35: 36: /* 37: * This magic macro enables us to look at the process' registers 38: * in its user structure. Very gross. 39: */ 40: 41: #ifdef vax 42: # define regloc(reg) (ctob(UPAGES) + ( sizeof(int) * (reg) )) 43: #else 44: # define regloc(reg) (ar0val + ( sizeof(int) * (reg) )) 45: #endif 46: 47: #define WMASK (~(sizeof(WORD) - 1)) 48: #define cachehash(addr) ((unsigned) ((addr >> 2) % CSIZE)) 49: 50: #define FIRSTSIG SIGINT 51: #define LASTSIG SIGQUIT 52: #define ischild(pid) ((pid) == 0) 53: #define traceme() ptrace(0, 0, 0, 0) 54: #define setrep(n) (1 << ((n)-1)) 55: #define istraced(p) (p->sigset&setrep(p->signo)) 56: 57: /* 58: * ptrace options (specified in first argument) 59: */ 60: 61: #define UREAD 3 /* read from process's user structure */ 62: #define UWRITE 6 /* write to process's user structure */ 63: #define IREAD 1 /* read from process's instruction space */ 64: #define IWRITE 4 /* write to process's instruction space */ 65: #define DREAD 2 /* read from process's data space */ 66: #define DWRITE 5 /* write to process's data space */ 67: #define CONT 7 /* continue stopped process */ 68: #define SSTEP 9 /* continue for approximately one instruction */ 69: #define PKILL 8 /* terminate the process */ 70: 71: /* 72: * Start up a new process by forking and exec-ing the 73: * given argument list, returning when the process is loaded 74: * and ready to execute. The PROCESS information (pointed to 75: * by the first argument) is appropriately filled. 76: * 77: * If the given PROCESS structure is associated with an already running 78: * process, we terminate it. 79: */ 80: 81: /* VARARGS2 */ 82: pstart(p, cmd, argv, infile, outfile) 83: PROCESS *p; 84: char *cmd; 85: char **argv; 86: char *infile; 87: char *outfile; 88: { 89: int status; 90: FILE *in, *out; 91: 92: if (p->pid != 0) { /* child already running? */ 93: ptrace(PKILL, p->pid, 0, 0); /* ... kill it! */ 94: } 95: psigtrace(p, SIGTRAP, TRUE); 96: if ((p->pid = fork()) == -1) { 97: panic("can't fork"); 98: } 99: if (ischild(p->pid)) { 100: traceme(); 101: if (infile != NIL) { 102: if ((in = fopen(infile, "r")) == NIL) { 103: printf("can't read %s\n", infile); 104: exit(1); 105: } 106: fswap(0, fileno(in)); 107: } 108: if (outfile != NIL) { 109: if ((out = fopen(outfile, "w")) == NIL) { 110: printf("can't write %s\n", outfile); 111: exit(1); 112: } 113: fswap(1, fileno(out)); 114: } 115: execvp(cmd, argv); 116: panic("can't exec %s", argv[0]); 117: } 118: pwait(p->pid, &status); 119: getinfo(p, status); 120: } 121: 122: /* 123: * Continue a stopped process. The argument points to a PROCESS structure. 124: * Before the process is restarted it's user area is modified according to 125: * the values in the structure. When this routine finishes, 126: * the structure has the new values from the process's user area. 127: * 128: * Pcont terminates when the process stops with a signal pending that 129: * is being traced (via psigtrace), or when the process terminates. 130: */ 131: 132: pcont(p) 133: PROCESS *p; 134: { 135: int status; 136: 137: if (p->pid == 0) { 138: error("program not active"); 139: } 140: do { 141: setinfo(p); 142: sigs_off(); 143: if (ptrace(CONT, p->pid, p->pc, p->signo) < 0) { 144: panic("can't continue process"); 145: } 146: pwait(p->pid, &status); 147: sigs_on(); 148: getinfo(p, status); 149: } while (p->status == STOPPED && !istraced(p)); 150: } 151: 152: /* 153: * single step as best ptrace can 154: */ 155: 156: pstep(p) 157: PROCESS *p; 158: { 159: int status; 160: 161: setinfo(p); 162: sigs_off(); 163: ptrace(SSTEP, p->pid, p->pc, p->signo); 164: pwait(p->pid, &status); 165: sigs_on(); 166: getinfo(p, status); 167: } 168: 169: /* 170: * Return from execution when the given signal is pending. 171: */ 172: 173: psigtrace(p, sig, sw) 174: PROCESS *p; 175: int sig; 176: int sw; 177: { 178: if (sw) { 179: p->sigset |= setrep(sig); 180: } else { 181: p->sigset &= ~setrep(sig); 182: } 183: } 184: 185: /* 186: * Don't catch any signals. 187: * Particularly useful when letting a process finish uninhibited (i.e. px). 188: */ 189: 190: unsetsigtraces(p) 191: PROCESS *p; 192: { 193: p->sigset = 0; 194: } 195: 196: /* 197: * turn off attention to signals not being caught 198: */ 199: 200: typedef int INTFUNC(); 201: 202: LOCAL INTFUNC *sigfunc[NSIG]; 203: 204: LOCAL sigs_off() 205: { 206: register int i; 207: 208: for (i = FIRSTSIG; i < LASTSIG; i++) { 209: if (i != SIGKILL) { 210: sigfunc[i] = signal(i, SIG_IGN); 211: } 212: } 213: } 214: 215: /* 216: * turn back on attention to signals 217: */ 218: 219: LOCAL sigs_on() 220: { 221: register int i; 222: 223: for (i = FIRSTSIG; i < LASTSIG; i++) { 224: if (i != SIGKILL) { 225: signal(i, sigfunc[i]); 226: } 227: } 228: } 229: 230: /* 231: * get PROCESS information from process's user area 232: */ 233: 234: #if vax 235: LOCAL int rloc[] ={ 236: R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, 237: }; 238: #else 239: LOCAL int rloc[] ={ 240: R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5, 241: }; 242: #endif 243: 244: LOCAL getinfo(p, status) 245: register PROCESS *p; 246: register int status; 247: { 248: register int i; 249: 250: p->signo = (status&0177); 251: p->exitval = ((status >> 8)&0377); 252: if (p->signo == STOPPED) { 253: p->status = p->signo; 254: p->signo = p->exitval; 255: p->exitval = 0; 256: } else { 257: p->status = FINISHED; 258: return; 259: } 260: #ifndef vax 261: if (ar0val < 0){ 262: ar0val = ptrace(UREAD, p->pid, U_AR0, 0); 263: ar0val -= U_PAGE; 264: } 265: #endif 266: for (i = 0; i < NREG; i++) { 267: p->reg[i] = ptrace(UREAD, p->pid, regloc(rloc[i]), 0); 268: p->oreg[i] = p->reg[i]; 269: } 270: #ifdef vax 271: p->fp = p->ofp = ptrace(UREAD, p->pid, regloc(FP), 0); 272: p->ap = p->oap = ptrace(UREAD, p->pid, regloc(AP), 0); 273: p->sp = p->osp = ptrace(UREAD, p->pid, regloc(SP), 0); 274: p->pc = p->opc = ptrace(UREAD, p->pid, regloc(PC), 0); 275: #else 276: p->fp = p->ofp = ptrace(UREAD, p->pid, regloc(AR6), 0); 277: p->ap = p->oap = p->fp; 278: p->sp = p->osp = ptrace(UREAD, p->pid, regloc(SP), 0); 279: p->pc = p->opc = ptrace(UREAD, p->pid, regloc(PC), 0); 280: #endif 281: } 282: 283: /* 284: * set process's user area information from given PROCESS structure 285: */ 286: 287: LOCAL setinfo(p) 288: register PROCESS *p; 289: { 290: register int i; 291: register int r; 292: 293: if (istraced(p)) { 294: p->signo = 0; 295: } 296: for (i = 0; i < NREG; i++) { 297: if ((r = p->reg[i]) != p->oreg[i]) { 298: ptrace(UWRITE, p->pid, regloc(rloc[i]), r); 299: } 300: } 301: #if vax 302: if ((r = p->fp) != p->ofp) { 303: ptrace(UWRITE, p->pid, regloc(FP), r); 304: } 305: if ((r = p->sp) != p->osp) { 306: ptrace(UWRITE, p->pid, regloc(SP), r); 307: } 308: if ((r = p->ap) != p->oap) { 309: ptrace(UWRITE, p->pid, regloc(AP), r); 310: } 311: #else 312: if ((r = p->fp) != p->ofp) { 313: ptrace(UWRITE, p->pid, regloc(AR6), r); 314: } 315: if ((r = p->sp) != p->osp) { 316: ptrace(UWRITE, p->pid, regloc(SP), r); 317: } 318: #endif 319: if ((r = p->pc) != p->opc) { 320: ptrace(UWRITE, p->pid, regloc(PC), r); 321: } 322: } 323: 324: /* 325: * Structure for reading and writing by words, but dealing with bytes. 326: */ 327: 328: typedef union { 329: WORD pword; 330: BYTE pbyte[sizeof(WORD)]; 331: } PWORD; 332: 333: /* 334: * Read (write) from (to) the process' address space. 335: * We must deal with ptrace's inability to look anywhere other 336: * than at a word boundary. 337: */ 338: 339: LOCAL WORD fetch(); 340: LOCAL store(); 341: 342: pio(p, op, seg, buff, addr, nbytes) 343: PROCESS *p; 344: PIO_OP op; 345: PIO_SEG seg; 346: char *buff; 347: ADDRESS addr; 348: int nbytes; 349: { 350: register int i; 351: register ADDRESS newaddr; 352: register char *cp; 353: char *bufend; 354: PWORD w; 355: ADDRESS wordaddr; 356: int byteoff; 357: 358: if (p->status != STOPPED) { 359: error("program is not active"); 360: } 361: cp = buff; 362: newaddr = addr; 363: wordaddr = (newaddr&WMASK); 364: if (wordaddr != newaddr) { 365: w.pword = fetch(p, seg, wordaddr); 366: for (i = newaddr - wordaddr; i<sizeof(WORD) && nbytes>0; i++) { 367: if (op == PREAD) { 368: *cp++ = w.pbyte[i]; 369: } else { 370: w.pbyte[i] = *cp++; 371: } 372: nbytes--; 373: } 374: if (op == PWRITE) { 375: store(p, seg, wordaddr, w.pword); 376: } 377: newaddr = wordaddr + sizeof(WORD); 378: } 379: byteoff = (nbytes&(~WMASK)); 380: nbytes -= byteoff; 381: bufend = cp + nbytes; 382: while (cp < bufend) { 383: if (op == PREAD) { 384: *((WORD *) cp) = fetch(p, seg, newaddr); 385: } else { 386: store(p, seg, newaddr, *((WORD *) cp)); 387: } 388: cp += sizeof(WORD); 389: newaddr += sizeof(WORD); 390: } 391: if (byteoff > 0) { 392: w.pword = fetch(p, seg, newaddr); 393: for (i = 0; i < byteoff; i++) { 394: if (op == PREAD) { 395: *cp++ = w.pbyte[i]; 396: } else { 397: w.pbyte[i] = *cp++; 398: } 399: } 400: if (op == PWRITE) { 401: store(p, seg, newaddr, w.pword); 402: } 403: } 404: } 405: 406: /* 407: * Get a word from a process at the given address. 408: * The address is assumed to be on a word boundary. 409: * 410: * We use a simple cache scheme to avoid redundant references to 411: * the instruction space (which is assumed to be pure). In the 412: * case of px, the "instruction" space lies between ENDOFF and 413: * ENDOFF + objsize. 414: * 415: * It is necessary to use a write-through scheme so that 416: * breakpoints right next to each other don't interfere. 417: */ 418: 419: LOCAL WORD fetch(p, seg, addr) 420: PROCESS *p; 421: PIO_SEG seg; 422: register int addr; 423: { 424: register CACHEWORD *wp; 425: register WORD w; 426: 427: switch (seg) { 428: case TEXTSEG: 429: # if (isvaxpx) 430: panic("tried to fetch from px i-space"); 431: /* NOTREACHED */ 432: # else 433: wp = &p->word[cachehash(addr)]; 434: if (addr == 0 || wp->addr != addr) { 435: w = ptrace(IREAD, p->pid, addr, 0); 436: wp->addr = addr; 437: wp->val = w; 438: } else { 439: w = wp->val; 440: } 441: break; 442: # endif 443: 444: case DATASEG: 445: # if (isvaxpx) 446: if (addr >= ENDOFF && addr < ENDOFF + objsize) { 447: wp = &p->word[cachehash(addr)]; 448: if (addr == 0 || wp->addr != addr) { 449: w = ptrace(DREAD, p->pid, addr, 0); 450: wp->addr = addr; 451: wp->val = w; 452: } else { 453: w = wp->val; 454: } 455: } else { 456: w = ptrace(DREAD, p->pid, addr, 0); 457: } 458: # else 459: w = ptrace(DREAD, p->pid, addr, 0); 460: # endif 461: break; 462: 463: default: 464: panic("fetch: bad seg %d", seg); 465: /* NOTREACHED */ 466: } 467: return(w); 468: } 469: 470: /* 471: * Put a word into the process' address space at the given address. 472: * The address is assumed to be on a word boundary. 473: */ 474: 475: LOCAL store(p, seg, addr, data) 476: PROCESS *p; 477: PIO_SEG seg; 478: int addr; 479: WORD data; 480: { 481: register CACHEWORD *wp; 482: 483: switch (seg) { 484: case TEXTSEG: 485: wp = &p->word[cachehash(addr)]; 486: wp->addr = addr; 487: wp->val = data; 488: ptrace(IWRITE, p->pid, addr, data); 489: break; 490: 491: case DATASEG: 492: # if (isvaxpx) 493: if (addr >= ENDOFF && addr < ENDOFF + objsize) { 494: wp = &p->word[cachehash(addr)]; 495: wp->addr = addr; 496: wp->val = data; 497: } 498: # endif 499: ptrace(DWRITE, p->pid, addr, data); 500: break; 501: 502: default: 503: panic("store: bad seg %d", seg); 504: /*NOTREACHED*/ 505: } 506: } 507: 508: /* 509: * Initialize the instruction cache for a process. 510: * This is particularly necessary after the program has been remade. 511: */ 512: 513: initcache(process) 514: PROCESS *process; 515: { 516: register int i; 517: 518: for (i = 0; i < CSIZE; i++) { 519: process->word[i].addr = 0; 520: } 521: } 522: 523: /* 524: * Swap file numbers so as to redirect standard input and output. 525: */ 526: 527: LOCAL fswap(oldfd, newfd) 528: int oldfd; 529: int newfd; 530: { 531: if (oldfd != newfd) { 532: close(oldfd); 533: dup(newfd); 534: close(newfd); 535: } 536: }