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