Annotation of researchv9/jtools/src/pi/hostcore.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.