/* * Return user to state before notify() */ void noted(Ureg* cur, uintptr arg0) { NFrame *nf; Note note; Ureg *nur; qlock(&up->debug); if(arg0 != NRSTR && !up->notified){ qunlock(&up->debug); pprint("suicide: call to noted when not notified\n"); pexit("Suicide", 0); } up->notified = 0; fpunoted(); nf = up->ureg; /* sanity clause */ if(!okaddr(PTR2UINT(nf), sizeof(NFrame), 0)){ qunlock(&up->debug); pprint("suicide: bad ureg %#p in noted\n", nf); pexit("Suicide", 0); } /* * Check the segment selectors are all valid. */ nur = &nf->ureg; if(nur->cs != SSEL(SiUCS, SsRPL3) || nur->ss != SSEL(SiUDS, SsRPL3) || nur->ds != SSEL(SiUDS, SsRPL3) || nur->es != SSEL(SiUDS, SsRPL3) || nur->fs != SSEL(SiUDS, SsRPL3) || nur->gs != SSEL(SiUDS, SsRPL3)){ qunlock(&up->debug); pprint("suicide: bad segment selector in noted\n"); pexit("Suicide", 0); } /* don't let user change system flags */ nur->flags &= (Of|Df|Sf|Zf|Af|Pf|Cf); nur->flags |= cur->flags & ~(Of|Df|Sf|Zf|Af|Pf|Cf); memmove(cur, nur, sizeof(Ureg)); switch((int)arg0){ case NCONT: case NRSTR: if(!okaddr(nur->ip, BY2SE, 0) || !okaddr(nur->sp, BY2SE, 0)){ qunlock(&up->debug); pprint("suicide: trap in noted pc=%#p sp=%#p\n", nur->ip, nur->sp); pexit("Suicide", 0); } up->ureg = nf->old; qunlock(&up->debug); break; case NSAVE: if(!okaddr(nur->ip, BY2SE, 0) || !okaddr(nur->sp, BY2SE, 0)){ qunlock(&up->debug); pprint("suicide: trap in noted pc=%#p sp=%#p\n", nur->ip, nur->sp); pexit("Suicide", 0); } qunlock(&up->debug); splhi(); nf->arg1 = nf->msg; nf->arg0 = &nf->ureg; cur->bp = PTR2UINT(nf->arg0); nf->ip = 0; cur->sp = PTR2UINT(nf); break; default: memmove(¬e, &up->lastnote, sizeof(Note)); qunlock(&up->debug); pprint("suicide: bad arg %#p in noted: %s\n", arg0, note.msg); pexit(note.msg, 0); break; case NDFLT: memmove(¬e, &up->lastnote, sizeof(Note)); qunlock(&up->debug); if(note.flag == NDebug) pprint("suicide: %s\n", note.msg); pexit(note.msg, note.flag != NDebug); break; } }
/* * Return user to state before notify() */ static void noted(Ureg* cur, uintptr arg0) { NFrame *nf; Ureg *nur; qlock(&up->debug); if(arg0 != NRSTR && !up->notified){ qunlock(&up->debug); pprint("call to noted() when not notified\n"); pexit("Suicide", 0); } up->notified = 0; fpunoted(); nf = up->ureg; /* sanity clause */ if(!okaddr(PTR2UINT(nf), sizeof(NFrame), 0)){ qunlock(&up->debug); pprint("bad ureg in noted %#p\n", nf); pexit("Suicide", 0); } /* don't let user change system flags */ nur = &nf->ureg; nur->psr &= PsrMask|PsrDfiq|PsrDirq; nur->psr |= (cur->psr & ~(PsrMask|PsrDfiq|PsrDirq)); memmove(cur, nur, sizeof(Ureg)); switch((int)arg0){ case NCONT: case NRSTR: if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->sp, BY2WD, 0)){ qunlock(&up->debug); pprint("suicide: trap in noted\n"); pexit("Suicide", 0); } up->ureg = nf->old; qunlock(&up->debug); break; case NSAVE: if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->sp, BY2WD, 0)){ qunlock(&up->debug); pprint("suicide: trap in noted\n"); pexit("Suicide", 0); } qunlock(&up->debug); splhi(); nf->arg1 = nf->msg; nf->arg0 = &nf->ureg; nf->ip = 0; cur->sp = PTR2UINT(nf); cur->r0 = PTR2UINT(nf->arg0); break; default: pprint("unknown noted arg %#p\n", arg0); up->lastnote.flag = NDebug; /*FALLTHROUGH*/ case NDFLT: if(up->lastnote.flag == NDebug){ qunlock(&up->debug); pprint("suicide: %s\n", up->lastnote.msg); } else qunlock(&up->debug); pexit(up->lastnote.msg, up->lastnote.flag != NDebug); } }