1 /*- 2 * Copyright (c) 1980, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)ptrace.c 8.1 (Berkeley) 06/06/93"; 10 #endif /* not lint */ 11 12 /* 13 * routines for tracing the execution of a process 14 * 15 * The system call "ptrace" does all the work, these 16 * routines just try to interface easily to it. 17 */ 18 19 #include "defs.h" 20 #include <signal.h> 21 #include <sys/param.h> 22 #include <machine/reg.h> 23 #include "process.h" 24 #include "object.h" 25 #include "process.rep" 26 27 # include "pxinfo.h" 28 29 #ifdef mc68000 30 # define U_PAGE 0x2400 31 # define U_AR0 (14*sizeof(int)) 32 LOCAL int ar0val = -1; 33 #endif 34 35 /* 36 * This magic macro enables us to look at the process' registers 37 * in its user structure. Very gross. 38 */ 39 40 #if defined(vax) || defined(tahoe) 41 # define regloc(reg) (ctob(UPAGES) + ( sizeof(int) * (reg) )) 42 #else 43 # define regloc(reg) (ar0val + ( sizeof(int) * (reg) )) 44 #endif 45 46 #define WMASK (~(sizeof(WORD) - 1)) 47 #define cachehash(addr) ((unsigned) ((addr >> 2) % CSIZE)) 48 49 #define ischild(pid) ((pid) == 0) 50 #define traceme() ptrace(0, 0, 0, 0) 51 #define setrep(n) (1 << ((n)-1)) 52 #define istraced(p) (p->sigset&setrep(p->signo)) 53 54 /* 55 * ptrace options (specified in first argument) 56 */ 57 58 #define UREAD 3 /* read from process's user structure */ 59 #define UWRITE 6 /* write to process's user structure */ 60 #define IREAD 1 /* read from process's instruction space */ 61 #define IWRITE 4 /* write to process's instruction space */ 62 #define DREAD 2 /* read from process's data space */ 63 #define DWRITE 5 /* write to process's data space */ 64 #define CONT 7 /* continue stopped process */ 65 #define SSTEP 9 /* continue for approximately one instruction */ 66 #define PKILL 8 /* terminate the process */ 67 68 /* 69 * Start up a new process by forking and exec-ing the 70 * given argument list, returning when the process is loaded 71 * and ready to execute. The PROCESS information (pointed to 72 * by the first argument) is appropriately filled. 73 * 74 * If the given PROCESS structure is associated with an already running 75 * process, we terminate it. 76 */ 77 78 /* VARARGS2 */ 79 pstart(p, cmd, argv, infile, outfile) 80 PROCESS *p; 81 char *cmd; 82 char **argv; 83 char *infile; 84 char *outfile; 85 { 86 int status; 87 FILE *in, *out; 88 89 if (p->pid != 0) { /* child already running? */ 90 ptrace(PKILL, p->pid, 0, 0); /* ... kill it! */ 91 } 92 #ifdef tahoe 93 INTFP = (ADDRESS)0; 94 #endif tahoe 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 LOCAL void *onintr, *onquit; 201 202 LOCAL sigs_off() 203 { 204 onintr = signal(SIGINT, SIG_IGN); 205 onquit = signal(SIGQUIT, SIG_IGN); 206 } 207 208 /* 209 * turn back on attention to signals 210 */ 211 212 LOCAL sigs_on() 213 { 214 (void) signal(SIGINT, onintr); 215 (void) signal(SIGQUIT, onquit); 216 } 217 218 /* 219 * get PROCESS information from process's user area 220 */ 221 222 #if vax 223 LOCAL int rloc[] ={ 224 R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, 225 }; 226 #endif 227 #if tahoe 228 LOCAL int rloc[] ={ 229 R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, 230 }; 231 #endif 232 #if mc68000 233 LOCAL int rloc[] ={ 234 R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5, 235 }; 236 #endif 237 238 LOCAL getinfo(p, status) 239 register PROCESS *p; 240 register int status; 241 { 242 register int i; 243 244 p->signo = (status&0177); 245 p->exitval = ((status >> 8)&0377); 246 if (p->signo == STOPPED) { 247 p->status = p->signo; 248 p->signo = p->exitval; 249 p->exitval = 0; 250 } else { 251 p->status = FINISHED; 252 return; 253 } 254 #if !defined(vax) && !defined(tahoe) 255 if (ar0val < 0){ 256 ar0val = ptrace(UREAD, p->pid, U_AR0, 0); 257 ar0val -= U_PAGE; 258 } 259 #endif 260 for (i = 0; i < NREG; i++) { 261 p->reg[i] = ptrace(UREAD, p->pid, regloc(rloc[i]), 0); 262 p->oreg[i] = p->reg[i]; 263 } 264 #if defined(vax) || defined(tahoe) 265 p->fp = p->ofp = ptrace(UREAD, p->pid, regloc(FP), 0); 266 p->sp = p->osp = ptrace(UREAD, p->pid, regloc(SP), 0); 267 p->pc = p->opc = ptrace(UREAD, p->pid, regloc(PC), 0); 268 #endif 269 #ifdef vax 270 p->ap = p->oap = ptrace(UREAD, p->pid, regloc(AP), 0); 271 #endif 272 #ifdef mc68000 273 p->fp = p->ofp = ptrace(UREAD, p->pid, regloc(AR6), 0); 274 p->ap = p->oap = p->fp; 275 p->sp = p->osp = ptrace(UREAD, p->pid, regloc(SP), 0); 276 p->pc = p->opc = ptrace(UREAD, p->pid, regloc(PC), 0); 277 #endif 278 } 279 280 /* 281 * set process's user area information from given PROCESS structure 282 */ 283 284 LOCAL setinfo(p) 285 register PROCESS *p; 286 { 287 register int i; 288 register int r; 289 290 if (istraced(p)) { 291 p->signo = 0; 292 } 293 for (i = 0; i < NREG; i++) { 294 if ((r = p->reg[i]) != p->oreg[i]) { 295 ptrace(UWRITE, p->pid, regloc(rloc[i]), r); 296 } 297 } 298 #if vax || tahoe 299 if ((r = p->fp) != p->ofp) { 300 ptrace(UWRITE, p->pid, regloc(FP), r); 301 } 302 #endif 303 #if vax 304 if ((r = p->ap) != p->oap) { 305 ptrace(UWRITE, p->pid, regloc(AP), r); 306 } 307 #endif 308 #if mc68000 309 if ((r = p->fp) != p->ofp) { 310 ptrace(UWRITE, p->pid, regloc(AR6), r); 311 } 312 #endif 313 if ((r = p->sp) != p->osp) { 314 ptrace(UWRITE, p->pid, regloc(SP), r); 315 } 316 if ((r = p->pc) != p->opc) { 317 ptrace(UWRITE, p->pid, regloc(PC), r); 318 } 319 } 320 321 /* 322 * Structure for reading and writing by words, but dealing with bytes. 323 */ 324 325 typedef union { 326 WORD pword; 327 BYTE pbyte[sizeof(WORD)]; 328 } PWORD; 329 330 /* 331 * Read (write) from (to) the process' address space. 332 * We must deal with ptrace's inability to look anywhere other 333 * than at a word boundary. 334 */ 335 336 LOCAL WORD fetch(); 337 LOCAL store(); 338 339 pio(p, op, seg, buff, addr, nbytes) 340 PROCESS *p; 341 PIO_OP op; 342 PIO_SEG seg; 343 char *buff; 344 ADDRESS addr; 345 int nbytes; 346 { 347 register int i, k; 348 register ADDRESS newaddr; 349 register char *cp; 350 char *bufend; 351 PWORD w; 352 ADDRESS wordaddr; 353 int byteoff; 354 355 if (p->status != STOPPED) { 356 error("program is not active"); 357 } 358 cp = buff; 359 newaddr = addr; 360 wordaddr = (newaddr&WMASK); 361 if (wordaddr != newaddr) { 362 w.pword = fetch(p, seg, wordaddr); 363 for (i = newaddr - wordaddr; i<sizeof(WORD) && nbytes>0; i++) { 364 if (op == PREAD) { 365 *cp++ = w.pbyte[i]; 366 } else { 367 w.pbyte[i] = *cp++; 368 } 369 nbytes--; 370 } 371 if (op == PWRITE) { 372 store(p, seg, wordaddr, w.pword); 373 } 374 newaddr = wordaddr + sizeof(WORD); 375 } 376 byteoff = (nbytes&(~WMASK)); 377 nbytes -= byteoff; 378 bufend = cp + nbytes; 379 while (cp < bufend) { 380 if (op == PREAD) { 381 w.pword = fetch(p, seg, newaddr); 382 for (k = 0; k < sizeof(WORD); k++) { 383 *cp++ = w.pbyte[k]; 384 } 385 } else { 386 for (k = 0; k < sizeof(WORD); k++) { 387 w.pbyte[k] = *cp++; 388 } 389 store(p, seg, newaddr, w.pword); 390 } 391 newaddr += sizeof(WORD); 392 } 393 if (byteoff > 0) { 394 w.pword = fetch(p, seg, newaddr); 395 for (i = 0; i < byteoff; i++) { 396 if (op == PREAD) { 397 *cp++ = w.pbyte[i]; 398 } else { 399 w.pbyte[i] = *cp++; 400 } 401 } 402 if (op == PWRITE) { 403 store(p, seg, newaddr, w.pword); 404 } 405 } 406 } 407 408 /* 409 * Get a word from a process at the given address. 410 * The address is assumed to be on a word boundary. 411 * 412 * We use a simple cache scheme to avoid redundant references to 413 * the instruction space (which is assumed to be pure). In the 414 * case of px, the "instruction" space lies between ENDOFF and 415 * ENDOFF + objsize. 416 * 417 * It is necessary to use a write-through scheme so that 418 * breakpoints right next to each other don't interfere. 419 */ 420 421 LOCAL WORD fetch(p, seg, addr) 422 PROCESS *p; 423 PIO_SEG seg; 424 register int addr; 425 { 426 register CACHEWORD *wp; 427 register WORD w; 428 429 switch (seg) { 430 case TEXTSEG: 431 panic("tried to fetch from px i-space"); 432 /* NOTREACHED */ 433 434 case DATASEG: 435 if (addr >= ENDOFF && addr < ENDOFF + objsize) { 436 wp = &p->word[cachehash(addr)]; 437 if (addr == 0 || wp->addr != addr) { 438 w = ptrace(DREAD, p->pid, addr, 0); 439 wp->addr = addr; 440 wp->val = w; 441 } else { 442 w = wp->val; 443 } 444 } else { 445 w = ptrace(DREAD, p->pid, addr, 0); 446 } 447 break; 448 449 default: 450 panic("fetch: bad seg %d", seg); 451 /* NOTREACHED */ 452 } 453 return(w); 454 } 455 456 /* 457 * Put a word into the process' address space at the given address. 458 * The address is assumed to be on a word boundary. 459 */ 460 461 LOCAL store(p, seg, addr, data) 462 PROCESS *p; 463 PIO_SEG seg; 464 int addr; 465 WORD data; 466 { 467 register CACHEWORD *wp; 468 469 switch (seg) { 470 case TEXTSEG: 471 wp = &p->word[cachehash(addr)]; 472 wp->addr = addr; 473 wp->val = data; 474 ptrace(IWRITE, p->pid, addr, data); 475 break; 476 477 case DATASEG: 478 if (addr >= ENDOFF && addr < ENDOFF + objsize) { 479 wp = &p->word[cachehash(addr)]; 480 wp->addr = addr; 481 wp->val = data; 482 } 483 ptrace(DWRITE, p->pid, addr, data); 484 break; 485 486 default: 487 panic("store: bad seg %d", seg); 488 /*NOTREACHED*/ 489 } 490 } 491 492 /* 493 * Initialize the instruction cache for a process. 494 * This is particularly necessary after the program has been remade. 495 */ 496 497 initcache(process) 498 PROCESS *process; 499 { 500 register int i; 501 502 for (i = 0; i < CSIZE; i++) { 503 process->word[i].addr = 0; 504 } 505 } 506 507 /* 508 * Swap file numbers so as to redirect standard input and output. 509 */ 510 511 LOCAL fswap(oldfd, newfd) 512 int oldfd; 513 int newfd; 514 { 515 if (oldfd != newfd) { 516 close(oldfd); 517 dup(newfd); 518 close(newfd); 519 } 520 } 521 522 #ifdef tahoe 523 BOOLEAN didret; 524 525 void 526 chkret(p, status) 527 PROCESS *p; 528 int status; 529 { 530 if (((status == (SIGILL << 8) | STOPPED) || 531 (status == (SIGTRAP << 8) | STOPPED))) { 532 didret = FALSE; 533 } else { 534 didret = TRUE; 535 } 536 } 537 538 void 539 doret(p) 540 PROCESS *p; 541 { 542 register count = 0; 543 544 if (!didret) { 545 do { 546 if (++count > 5) { 547 panic("px would not return to interpreter"); 548 } 549 p->pc = RETLOC; 550 pstep(p); 551 } while(INTFP && p->fp != INTFP); 552 didret = TRUE; 553 } 554 } 555 #endif 556