|
|
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.