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