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