|
|
1.1 ! root 1: #include "process.pub" ! 2: #include "frame.pri" ! 3: #include "symtab.pri" ! 4: #include "symbol.h" ! 5: #include "hostcore.h" ! 6: #include <a.out.h> ! 7: #include "asm.pri" ! 8: #include "format.pub" ! 9: #include "bpts.pri" ! 10: #include "master.pri" ! 11: SRCFILE("hostcore.c") ! 12: #define TXTOFF(magic) (magic==ZMAGIC ? 0 : sizeof (struct exec)) ! 13: #include <setjmp.h> ! 14: ! 15: static WaitList waitlist; ! 16: int kill(int,int); ! 17: ! 18: const int STOPPED=0, RUNNING=1, EXITED=2, DIED=3; ! 19: const REGADDR = USRADR - 18 * 4; ! 20: ! 21: Behavs HostCore::behavetype() { return behavs(); } ! 22: char *HostCore::eventname() { return SignalName(event()); } ! 23: char *HostCore::stop() { ::kill(pid, SIGSTOP); return 0; } ! 24: int HostCore::event() { return cursig; } ! 25: long HostCore::regaddr() { return REGADDR; } ! 26: long HostCore::scratchaddr() { return 0x2000; } ! 27: ! 28: extern int errno; ! 29: ! 30: int HostCore::ptrace(int cmd, int a, int d, int a2) ! 31: { ! 32: errno = 0; ! 33: int ret = ::ptrace(cmd, pid, a, d, a2); ! 34: switch (cmd) { ! 35: case PTRACE_CONT: ! 36: case PTRACE_KILL: ! 37: case PTRACE_SINGLESTEP: ! 38: case PTRACE_ATTACH: ! 39: case PTRACE_DETACH: ! 40: break; ! 41: default: ! 42: if (!errno) ! 43: waitlist.wait(this, WAIT_DISCARD); ! 44: break; ! 45: } ! 46: return ret; ! 47: } ! 48: ! 49: char *HostCore::run() ! 50: { ! 51: if (cursig == SIGSTOP || cursig == SIGTRAP) ! 52: cursig = 0; ! 53: ptrace(PTRACE_CONT, 1, cursig); ! 54: state = RUNNING; ! 55: cursig = 0; ! 56: return 0; ! 57: } ! 58: ! 59: #define SUNBPT 0x4e4f /* Trap #15 */ ! 60: char *HostCore::laybpt(Trap *t) ! 61: { ! 62: Cslfd *cp = peek(t->stmt->range.lo, 0); ! 63: if (!cp) ! 64: return "text not readable (probably shared)"; ! 65: t->saved = cp->sht; ! 66: return poke(t->stmt->range.lo, SUNBPT, 2); ! 67: } ! 68: ! 69: Behavs HostCore::behavs() ! 70: { ! 71: if( !online() ) ! 72: return PENDING; ! 73: // Confirm it is still running ! 74: if ( state == EXITED || state == DIED) ! 75: return ERRORED; ! 76: if ( state == RUNNING ) { ! 77: if (waitlist.wait(this, WAIT_POLL|WAIT_PCFIX)) { ! 78: if (state != STOPPED) ! 79: return ERRORED; ! 80: if (!(sigmask&(1<<(cursig-1)))) { ! 81: run(); ! 82: return ACTIVE; ! 83: } ! 84: } else ! 85: return ACTIVE; ! 86: } ! 87: switch( cursig ){ ! 88: case SIGSTOP: ! 89: return HALTED; ! 90: case SIGTRAP: ! 91: return BREAKED; ! 92: default: ! 93: return PENDING; ! 94: } ! 95: } ! 96: ! 97: char *HostCore::problem() ! 98: { ! 99: static char buf[64]; ! 100: ! 101: if( !online() ) { ! 102: if( corefstat() ) ! 103: return "core image has gone away"; ! 104: return Core::problem(); ! 105: } ! 106: if (state == EXITED) ! 107: sprintf( buf, "exited with status %d", cursig); ! 108: else if (state == DIED) ! 109: sprintf( buf, "died from signal %d", cursig); ! 110: return buf; ! 111: } ! 112: ! 113: char *HostCore::readcontrol() ! 114: { ! 115: if( online() ) ! 116: return "online readcontrol"; ! 117: if( corefstat() ) ! 118: return "cannot fstat core image"; ! 119: int got = ::read(corefd, (char *)&bsdcore, sizeof(bsdcore)); ! 120: if (got != sizeof(bsdcore)) ! 121: return "cannot read bsdcore"; ! 122: state = STOPPED; ! 123: cursig = bsdcore.c_signo; ! 124: endtext = N_TXTADDR(bsdcore.c_aouthdr) + bsdcore.c_tsize; ! 125: startdata = N_DATADDR(bsdcore.c_aouthdr); ! 126: enddata = startdata + bsdcore.c_dsize; ! 127: startstack = SYSADR - bsdcore.c_ssize; ! 128: return 0; ! 129: } ! 130: ! 131: void HostCore::close() ! 132: { ! 133: if (online()){ ! 134: if (state == RUNNING) { ! 135: stop(); ! 136: waitstop(WAIT_PCFIX); ! 137: ptrace(PTRACE_DETACH, 1); ! 138: } else if (state == STOPPED) { ! 139: ::kill(pid, SIGSTOP); ! 140: ptrace(PTRACE_DETACH, 1); ! 141: } ! 142: waitlist.remove(this); ! 143: } ! 144: Core::close(); ! 145: } ! 146: ! 147: char *HostCore::open() ! 148: { ! 149: int mode = 2; ! 150: if( procpath() && !strcmp(basename(procpath()), "core") ) { ! 151: while( corefd<0 && mode>=0 ) ! 152: corefd = ::open(procpath(), mode--); ! 153: if( corefd<0 ) ! 154: return SysErr("core image: " ); ! 155: if( corefstat() ) ! 156: return SysErr("core image: " ); ! 157: if( corestat.st_mode & S_IEXEC ) ! 158: return "executable - should be dump (core)"; ! 159: } else if( procpath() ) { ! 160: sscanf(procpath(), "%d", &pid); ! 161: _online = 1; ! 162: waitlist.add(this); ! 163: waitlist.wait(this, 0); ! 164: cursig = SIGSTOP; ! 165: } ! 166: stabfd = ::open(stabpath(),0); ! 167: if( stabfd<0 ) { ! 168: if( online() ) { ! 169: ::kill(pid, SIGSTOP); ! 170: ptrace(PTRACE_DETACH, 1); ! 171: } ! 172: return SysErr( "symbol tables: " ); ! 173: } ! 174: stabfstat(); ! 175: BsdSymTab *bsdsp = new BsdSymTab(this, stabfd, _symtab); ! 176: _symtab = bsdsp; ! 177: _symtab->read(); ! 178: // Can't find endtext from U structure in 4.0 release, this is a kludge ! 179: endtext = bsdsp->endtext(); ! 180: if( online() || !procpath() ) ! 181: return 0; ! 182: return readcontrol(); ! 183: } ! 184: ! 185: char *HostCore::reopen(char *newprocpath, char *newstabpath) ! 186: { ! 187: int compstabfd = -1; ! 188: char *error = 0; ! 189: int retstat; ! 190: ! 191: if( !online() || (newprocpath && !strcmp(basename(newprocpath), "core")) ) ! 192: return "reopen core not implemented"; ! 193: int opid = pid; ! 194: int ostate = state; ! 195: int ocursig = cursig; ! 196: sscanf(newprocpath, "%d", &pid); ! 197: waitlist.wait(this, 0); ! 198: ! 199: compstabfd = ::open(newstabpath, 0); ! 200: struct stat compstabstat; ! 201: if( compstabfd < 0 ) { ! 202: error = "symbol table error"; ! 203: goto out; ! 204: } ! 205: retstat = ::fstat(compstabfd, &compstabstat); ! 206: ::close(compstabfd); ! 207: if (retstat) ! 208: error = "symbol table error"; ! 209: else if( compstabstat.st_mtime != stabstat.st_mtime ) ! 210: error = "symbol tables differ (modified time)"; ! 211: else if( compstabstat.st_size != stabstat.st_size ) ! 212: error = "symbol tables differ (file size)"; ! 213: cursig = ocursig; ! 214: state = ostate; ! 215: if (error) { ! 216: out: ! 217: ::kill(pid, SIGSTOP); ! 218: ptrace(PTRACE_DETACH, 1); ! 219: pid = opid; ! 220: return error; ! 221: } ! 222: // Must disconnect from the old process ! 223: int npid = pid; ! 224: pid = opid; ! 225: switch (state) { ! 226: case RUNNING: ! 227: stop(); ! 228: waitstop(WAIT_PCFIX); ! 229: ptrace(PTRACE_DETACH, 1); ! 230: break; ! 231: case STOPPED: ! 232: ::kill(pid, SIGSTOP); ! 233: ptrace(PTRACE_DETACH, 1); ! 234: break; ! 235: case EXITED: ! 236: case DIED: ! 237: break; ! 238: } ! 239: pid = npid; ! 240: state = STOPPED; ! 241: cursig = SIGSTOP; ! 242: // Can't find endtext from U structure in 4.0 release, this is a kludge ! 243: BsdSymTab *bsdsp = (BsdSymTab *)_symtab; ! 244: endtext = bsdsp->endtext(); ! 245: return 0; ! 246: } ! 247: ! 248: const int REGFD = -2, DATAFD = -3, TEXTFD = -4, USERFD = -5; ! 249: char *HostCore::seekto(int &fd, long &addr, int &whence) ! 250: { ! 251: if( !online() ) { ! 252: if ( (u_long)addr >= USRADR) { ! 253: addr -= USRADR + ctob(UPAGES); ! 254: whence = 2; ! 255: } else if ( (u_long)addr >= REGADDR) { ! 256: addr -= REGADDR; ! 257: fd = REGFD; ! 258: } else if ( (u_long)addr < 0x2000) ! 259: return "offset below text segment"; ! 260: else if ( (u_long)addr <= endtext) { ! 261: addr += N_TXTOFF(bsdcore.c_aouthdr) ! 262: - N_TXTADDR(bsdcore.c_aouthdr); ! 263: fd = stabfd; ! 264: } else if ( (u_long)addr < startdata) ! 265: return "offset beyond text segment"; ! 266: else if ( (u_long)addr <= enddata) ! 267: addr -= startdata - bsdcore.c_len; ! 268: else if ( (u_long)addr < startstack) ! 269: return "offset beyond data segment"; ! 270: else if ( (u_long)addr < SYSADR) { ! 271: addr -= SYSADR + ctob(UPAGES); ! 272: whence = 2; ! 273: } else ! 274: return "offset in system space"; ! 275: } else { ! 276: if ( (u_long)addr >= USRADR) { ! 277: addr -= USRADR; ! 278: fd = USERFD; ! 279: } else if ( (u_long)addr >= REGADDR) { ! 280: addr -= REGADDR; ! 281: fd = REGFD; ! 282: } else if ( (u_long)addr >= SYSADR ) { ! 283: extern char *DEVKMEM; ! 284: if( kmemfd == -1 ) { ! 285: kmemfd = ::open(DEVKMEM, 0); ! 286: if (kmemfd == -1) ! 287: return "can't read kernel"; ! 288: } ! 289: fd = kmemfd; ! 290: } else if ( (u_long)addr <= endtext) ! 291: fd = TEXTFD; ! 292: else ! 293: fd = DATAFD; ! 294: } ! 295: return 0; ! 296: } ! 297: ! 298: void bcopy(char*,char*,int); ! 299: ! 300: char *HostCore::readwrite(long offset, char *buf, int r, int w) ! 301: { ! 302: int fd = corefd, whence = 0; ! 303: int rv; ! 304: char *msg = "core image:"; ! 305: ! 306: char *error = seekto(fd, offset, whence); ! 307: if( error ) ! 308: return sf("core image: %s", error); ! 309: if( fd >= 0 ) { ! 310: if( lseek(fd, offset, whence) == -1 ) ! 311: return sf("lseek(%d,0x%X,%d)", fd, offset, whence); ! 312: if( r ){ ! 313: int got = ::read(fd, buf, r); ! 314: for( int i = got; i < r; ++i ) buf[i] = 0; ! 315: if( got > 0 ) return 0; ! 316: } ! 317: if( w && ::write(fd, buf, w) == w ) return 0; ! 318: return SysErr(msg); ! 319: } ! 320: int wasrunning = 0; ! 321: if (state == RUNNING) { ! 322: stop(); ! 323: if (error = waitstop(WAIT_PCFIX)) ! 324: return error; ! 325: if (cursig != SIGSTOP) { ! 326: int savesig = cursig; ! 327: /* The STOP signal still has to be eaten */ ! 328: run(); ! 329: waitstop(WAIT_PCFIX); ! 330: cursig = savesig; ! 331: } else ! 332: wasrunning = 1; ! 333: } ! 334: if (fd == REGFD) { ! 335: error = regrw(offset, buf, r, w); ! 336: if (wasrunning && !error) ! 337: run(); ! 338: return error; ! 339: } else if (fd == DATAFD) { ! 340: if ( r ) ! 341: rv = ptrace(PTRACE_READDATA, offset, r, (int)buf); ! 342: else ! 343: rv = ptrace(PTRACE_WRITEDATA, offset, w, (int)buf); ! 344: } ! 345: else if (fd == TEXTFD) { ! 346: if ( r ) ! 347: rv = ptrace(PTRACE_READTEXT, offset, r, (int)buf); ! 348: else { ! 349: /* Damn bug in Sun's kernel */ ! 350: if (w < 4){ ! 351: int tmp; ! 352: ptrace(PTRACE_READTEXT, offset, 4, (int)&tmp); ! 353: ::bcopy(buf, (char*)&tmp, w); ! 354: if (rv = ptrace(PTRACE_WRITETEXT, offset, 4, (int)&tmp)) ! 355: return "text not writable (probably shared)"; ! 356: } else ! 357: rv = ptrace(PTRACE_WRITETEXT, offset, w, (int)buf); ! 358: } ! 359: } ! 360: else if (fd == USERFD) { ! 361: int *ip = (int *)buf; ! 362: if ( r ) { ! 363: do { ! 364: *ip++ = ptrace(PTRACE_PEEKUSER, offset); ! 365: offset += 4; ! 366: r -= 4; ! 367: } while (r > 0 && errno == 0); ! 368: } else { ! 369: do { ! 370: ptrace(PTRACE_POKEUSER, offset, *ip++); ! 371: offset += 4; ! 372: w -= 4; ! 373: } while (w > 0 && errno == 0); ! 374: } ! 375: rv = errno; ! 376: } ! 377: if (wasrunning && !rv) ! 378: run(); ! 379: return rv == 0 ? 0 : "bad ptrace call"; ! 380: } ! 381: ! 382: char *HostCore::regrw(long offset, char *buf, int r, int w) ! 383: { ! 384: if ( online() ) { ! 385: regs rg; ! 386: if ( ptrace(PTRACE_GETREGS, (int)&rg) ) ! 387: return "Can't read registers"; ! 388: if ( r ) ! 389: ::bcopy( (char*)&rg + offset, buf, r); ! 390: else { ! 391: ::bcopy( buf, (char*)&rg + offset, w); ! 392: ptrace(PTRACE_SETREGS, (int)&rg); ! 393: } ! 394: } else { ! 395: if ( r ) ! 396: ::bcopy( (char*)&bsdcore.c_regs + offset, buf, r); ! 397: else if ( w ) ! 398: ::bcopy( buf, (char*)&bsdcore.c_regs + offset, w); ! 399: } ! 400: return 0; ! 401: } ! 402: ! 403: int HostCore::instack(long curfp, long prevfp ) ! 404: { ! 405: return ((curfp&0xf8000000)==0x08000000) && ((curfp&0xff000000)!=0x0f000000) ! 406: && (curfp>prevfp); ! 407: } ! 408: ! 409: int HostCore::fpvalid(long fp) ! 410: { ! 411: return (instack(fp, 0x08000000) && fp < 0x0f000000); ! 412: } ! 413: ! 414: char *HostCore::signalmask(long mask) ! 415: { ! 416: sigmask = mask; ! 417: return 0; ! 418: } ! 419: ! 420: char *HostCore::exechang(long ehang) ! 421: { ! 422: if (!ehang) ! 423: return "Must hang on exec"; ! 424: return 0; ! 425: } ! 426: ! 427: #define PSW_T 0x00008000 ! 428: char *HostCore::pswT(long psw_loc, int t) ! 429: { ! 430: long ps; ! 431: ! 432: char *error = read(psw_loc, (char*) &ps, 4 ); ! 433: if( error ) return error; ! 434: if( t ) ! 435: ps |= PSW_T; ! 436: else ! 437: ps &= ~PSW_T; ! 438: return write(psw_loc, (char*)&ps, 4); ! 439: } ! 440: ! 441: static jmp_buf saveenv; ! 442: void longjmp(jmp_buf, int); ! 443: int setjmp(jmp_buf); ! 444: ! 445: static void SigCatch(int) ! 446: { ! 447: longjmp(saveenv, 1); ! 448: } ! 449: ! 450: const int STEPWAIT = 15; ! 451: ! 452: char *HostCore::waitstop(int flags) ! 453: { ! 454: int wret; ! 455: ! 456: SIG_TYP oldsig = ::signal(SIGALRM, (SIG_TYP)&SigCatch); ! 457: int oldalarm = ::alarm(STEPWAIT); ! 458: if( ::setjmp(saveenv) ){ ! 459: ::alarm(oldalarm); ! 460: ::signal(SIGALRM, (SIG_TYP)oldsig); ! 461: ::kill(pid, SIGSTOP); ! 462: return sf("timeout (%d secs)", STEPWAIT); ! 463: } ! 464: wret = waitlist.wait(this, flags); ! 465: ::alarm(oldalarm); ! 466: ::signal(SIGALRM, (SIG_TYP)oldsig); ! 467: if (!wret ) ! 468: return "Unexpected wait error"; ! 469: if (state != STOPPED) ! 470: return "Process exited"; ! 471: return 0; ! 472: } ! 473: ! 474: const short M68K_TRAP0=0x4E40, M68K_RTS = 0x4E75; ! 475: ! 476: char *HostCore::dostep(long lo, long hi, int sstep) ! 477: { ! 478: char *error = 0; ! 479: long fp0, time0, time(long); ! 480: ! 481: time0 = ::time(0L); ! 482: fp0 = fp(); ! 483: for(;;){ ! 484: if( hi && isM68KJSB(peek(pc())->sht) ) { ! 485: error = stepoverM68KJSB(); ! 486: goto next; ! 487: } ! 488: if (sstep) ! 489: ptrace(PTRACE_SINGLESTEP, 1); ! 490: else ! 491: error = run(); ! 492: if( !error ) error = waitstop(sstep ? 0 : WAIT_PCFIX); ! 493: if( !error && event()!=SIGTRAP ) ! 494: error = sf( "single step error. signal=%d", event() ); ! 495: if( !error ) error = clrcurrsig(); ! 496: next: ! 497: if( error ) return error; ! 498: if( !hi || pc()<lo || pc()>=hi || ! 499: (fp()>fp0 && peek(pc())->sht != M68K_RTS) ) ! 500: return 0; ! 501: if( ::time(0L) > time0+STEPWAIT ) ! 502: return sf("single step timeout (%d secs)",STEPWAIT); ! 503: } ! 504: } ! 505: ! 506: char *HostCore::destroy() ! 507: { ! 508: char *error; ! 509: ! 510: if ( state == EXITED || state == DIED) ! 511: return 0; ! 512: clrcurrsig(); ! 513: if (state == RUNNING) { ! 514: stop(); ! 515: if (error = waitstop(WAIT_PCFIX)) ! 516: return error; ! 517: } ! 518: ptrace(PTRACE_KILL); ! 519: waitlist.wait(this, WAIT_DISCARD|WAIT_POLL); ! 520: state = EXITED; ! 521: cursig = SIGKILL; ! 522: return 0; ! 523: } ! 524: ! 525: char *HostCore::clrcurrsig() ! 526: { ! 527: cursig = 0; ! 528: return 0; ! 529: } ! 530: ! 531: char *HostCore::sendsig(long sig) ! 532: { ! 533: if( !online() ) return "send signal: process not live"; ! 534: ::kill(pid, sig); ! 535: return 0; ! 536: } ! 537: ! 538: Context* HostCore::newContext() ! 539: { ! 540: HostContext *cc = new HostContext; ! 541: cc->error = 0; ! 542: cc->core = this; ! 543: cc->pending = 0; ! 544: if( state != STOPPED ) ! 545: cc->error = "context save: process not stopped"; ! 546: else if( peek(pc()-2)->sht == M68K_TRAP0 ) ! 547: cc->error = "context save: process in system call"; ! 548: else if( cc->pending = cursig ) ! 549: cc->error = clrcurrsig(); ! 550: if( !cc->error ) ! 551: for( int i = 0; i < 18; ++i ) ! 552: cc->regs[i] = regpeek(i); ! 553: return cc; ! 554: } ! 555: ! 556: void HostContext::restore() ! 557: { ! 558: if( pending ) ! 559: core->cursig = pending; ! 560: for( int i = 0; i < 18; ++i ) ! 561: if( error = core->regpoke(i, regs[i]) ) ! 562: return; ! 563: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.