code *nteh_monitor_prolog(Symbol *shandle) { /* * PUSH handle * PUSH offset _d_monitor_handler * PUSH FS:__except_list * MOV FS:__except_list,ESP * CALL _d_monitor_prolog */ CodeBuilder cdb1; CodeBuilder cdb; assert(config.exe == EX_WIN32); // BUG: figure out how to implement for other EX's if (shandle->Sclass == SCfastpar) { assert(shandle->Spreg != DX); assert(shandle->Spreg2 == NOREG); cdb.gen1(0x50 + shandle->Spreg); // PUSH shandle } else { // PUSH shandle useregs(mCX); cdb.genc1(0x8B,modregrm(2,CX,4),FLconst,4 * (1 + needframe) + shandle->Soffset + localsize); cdb.last()->Isib = modregrm(0,4,SP); cdb.gen1(0x50 + CX); // PUSH ECX } Symbol *smh = getRtlsym(RTLSYM_MONITOR_HANDLER); cdb.gencs(0x68,0,FLextern,smh); // PUSH offset _d_monitor_handler makeitextern(smh); code cs; useregs(mDX); cs.Iop = 0x8B; cs.Irm = modregrm(0,DX,BPRM); cs.Iflags = CFfs; cs.Irex = 0; cs.IFL1 = FLextern; cs.IEVsym1 = getRtlsym(RTLSYM_EXCEPT_LIST); cs.IEVoffset1 = 0; cdb1.gen(&cs); // MOV EDX,FS:__except_list cdb.gen1(0x50 + DX); // PUSH EDX Symbol *s = getRtlsym(RTLSYM_MONITOR_PROLOG); regm_t desregs = ~s->Sregsaved & ALLREGS; cdb.append(getregs(desregs)); cdb.gencs(0xE8,0,FLfunc,s); // CALL _d_monitor_prolog cs.Iop = 0x89; NEWREG(cs.Irm,SP); cdb.gen(&cs); // MOV FS:__except_list,ESP cdb1.append(cdb); return cdb1.finish(); }
code *nteh_epilog() { if (config.exe != EX_WIN32) return NULL; /* Generate: mov ECX,__context[EBP].prev mov FS:__except_list,ECX */ code cs; CodeBuilder cdb; unsigned reg; #if MARS reg = CX; #else reg = (tybasic(funcsym_p->Stype->Tnext->Tty) == TYvoid) ? AX : CX; #endif useregs(mask[reg]); cs.Iop = 0x8B; cs.Irm = modregrm(2,reg,BPRM); cs.Iflags = 0; cs.Irex = 0; cs.IFL1 = FLconst; // EBP offset of __context.prev cs.IEV1.Vint = nteh_EBPoffset_prev(); cdb.gen(&cs); cs.Iop = 0x89; cs.Irm = modregrm(0,reg,BPRM); cs.Iflags |= CFfs; cs.IFL1 = FLextern; cs.IEVsym1 = getRtlsym(RTLSYM_EXCEPT_LIST); cs.IEVoffset1 = 0; cdb.gen(&cs); return cdb.finish(); }
code *nteh_epilog() { if (!(config.flags2 & CFG2seh)) return NULL; /* Generate: mov ECX,__context[EBP].prev mov FS:__except_list,ECX */ code cs; code *c; unsigned reg; #if MARS reg = CX; #else reg = (tybasic(funcsym_p->Stype->Tnext->Tty) == TYvoid) ? AX : CX; #endif useregs(mask[reg]); cs.Iop = 0x8B; cs.Irm = modregrm(2,reg,BPRM); cs.Iflags = 0; cs.Irex = 0; cs.IFL1 = FLconst; // EBP offset of __context.prev cs.IEV1.Vint = nteh_EBPoffset_prev(); c = gen(CNIL,&cs); cs.Iop = 0x89; cs.Irm = modregrm(0,reg,BPRM); cs.Iflags |= CFfs; cs.IFL1 = FLextern; cs.IEVsym1 = rtlsym[RTLSYM_EXCEPT_LIST]; cs.IEVoffset1 = 0; return gen(c,&cs); }
code *nteh_monitor_prolog(Symbol *shandle) { /* * PUSH handle * PUSH offset _d_monitor_handler * PUSH FS:__except_list * MOV FS:__except_list,ESP * CALL _d_monitor_prolog */ code *c1 = NULL; code *c; code cs; Symbol *s; regm_t desregs; assert(config.flags2 & CFG2seh); // BUG: figure out how to implement for other EX's if (shandle->Sclass == SCfastpar) { assert(shandle->Spreg != DX); c = gen1(NULL,0x50 + shandle->Spreg); // PUSH shandle } else { // PUSH shandle #if 0 c = genc1(NULL,0xFF,modregrm(2,6,4),FLconst,4 * (1 + needframe) + shandle->Soffset + localsize); c->Isib = modregrm(0,4,SP); #else useregs(mCX); c = genc1(NULL,0x8B,modregrm(2,CX,4),FLconst,4 * (1 + needframe) + shandle->Soffset + localsize); c->Isib = modregrm(0,4,SP); gen1(c,0x50 + CX); // PUSH ECX #endif } s = rtlsym[RTLSYM_MONITOR_HANDLER]; c = gencs(c,0x68,0,FLextern,s); // PUSH offset _d_monitor_handler makeitextern(s); #if 0 cs.Iop = 0xFF; cs.Irm = modregrm(0,6,BPRM); cs.Iflags = CFfs; cs.Irex = 0; cs.IFL1 = FLextern; cs.IEVsym1 = rtlsym[RTLSYM_EXCEPT_LIST]; cs.IEVoffset1 = 0; gen(c,&cs); // PUSH FS:__except_list #else useregs(mDX); cs.Iop = 0x8B; cs.Irm = modregrm(0,DX,BPRM); cs.Iflags = CFfs; cs.Irex = 0; cs.IFL1 = FLextern; cs.IEVsym1 = rtlsym[RTLSYM_EXCEPT_LIST]; cs.IEVoffset1 = 0; c1 = gen(c1,&cs); // MOV EDX,FS:__except_list gen1(c,0x50 + DX); // PUSH EDX #endif s = rtlsym[RTLSYM_MONITOR_PROLOG]; desregs = ~s->Sregsaved & ALLREGS; c = cat(c,getregs(desregs)); c = gencs(c,0xE8,0,FLfunc,s); // CALL _d_monitor_prolog cs.Iop = 0x89; NEWREG(cs.Irm,SP); gen(c,&cs); // MOV FS:__except_list,ESP return cat(c1,c); }
code *nteh_prolog() { code cs; code *c1; code *c; if (usednteh & NTEHpassthru) { /* An sindex value of -2 is a magic value that tells the * stack unwinder to skip this frame. */ assert(config.exe & (EX_LINUX | EX_LINUX64 | EX_OSX | EX_OSX64 | EX_FREEBSD | EX_FREEBSD64 | EX_SOLARIS | EX_SOLARIS64)); cs.Iop = 0x68; cs.Iflags = 0; cs.Irex = 0; cs.IFL2 = FLconst; cs.IEV2.Vint = -2; return gen(CNIL,&cs); // PUSH -2 } /* Generate instance of struct __nt_context on stack frame: [ ] // previous ebp already there push -1 // sindex mov EDX,FS:__except_list push offset FLAT:scope_table // stable (not for MARS or C++) push offset FLAT:__except_handler3 // handler push EDX // prev mov FS:__except_list,ESP sub ESP,8 // info, esp for __except support */ // useregs(mAX); // What is this for? cs.Iop = 0x68; cs.Iflags = 0; cs.Irex = 0; cs.IFL2 = FLconst; cs.IEV2.Vint = -1; c1 = gen(CNIL,&cs); // PUSH -1 if (usednteh & NTEHcpp || MARS) { // PUSH &framehandler cs.IFL2 = FLframehandler; #if MARS nteh_scopetable(); #endif } else { // Do stable cs.Iflags |= CFoff; cs.IFL2 = FLextern; cs.IEVsym2 = nteh_scopetable(); cs.IEVoffset2 = 0; c1 = gen(c1,&cs); // PUSH &scope_table cs.IFL2 = FLextern; cs.IEVsym2 = rtlsym[RTLSYM_EXCEPT_HANDLER3]; makeitextern(rtlsym[RTLSYM_EXCEPT_HANDLER3]); } c = gen(NULL,&cs); // PUSH &__except_handler3 if (config.exe == EX_NT) { makeitextern(rtlsym[RTLSYM_EXCEPT_LIST]); #if 0 cs.Iop = 0xFF; cs.Irm = modregrm(0,6,BPRM); cs.Iflags = CFfs; cs.Irex = 0; cs.IFL1 = FLextern; cs.IEVsym1 = rtlsym[RTLSYM_EXCEPT_LIST]; cs.IEVoffset1 = 0; gen(c,&cs); // PUSH FS:__except_list #else useregs(mDX); cs.Iop = 0x8B; cs.Irm = modregrm(0,DX,BPRM); cs.Iflags = CFfs; cs.Irex = 0; cs.IFL1 = FLextern; cs.IEVsym1 = rtlsym[RTLSYM_EXCEPT_LIST]; cs.IEVoffset1 = 0; gen(c1,&cs); // MOV EDX,FS:__except_list gen1(c,0x50 + DX); // PUSH EDX #endif cs.Iop = 0x89; NEWREG(cs.Irm,SP); gen(c,&cs); // MOV FS:__except_list,ESP } c = genc2(c,0x81,modregrm(3,5,SP),8); // SUB ESP,8 return cat(c1,c); }
code *nteh_prolog() { code cs; if (usednteh & NTEHpassthru) { /* An sindex value of -2 is a magic value that tells the * stack unwinder to skip this frame. */ assert(config.exe & (EX_LINUX | EX_LINUX64 | EX_OSX | EX_OSX64 | EX_FREEBSD | EX_FREEBSD64 | EX_SOLARIS | EX_SOLARIS64 | EX_OPENBSD | EX_OPENBSD64)); cs.Iop = 0x68; cs.Iflags = 0; cs.Irex = 0; cs.IFL2 = FLconst; cs.IEV2.Vint = -2; return gen(CNIL,&cs); // PUSH -2 } /* Generate instance of struct __nt_context on stack frame: [ ] // previous ebp already there push -1 // sindex mov EDX,FS:__except_list push offset FLAT:scope_table // stable (not for MARS or C++) push offset FLAT:__except_handler3 // handler push EDX // prev mov FS:__except_list,ESP sub ESP,8 // info, esp for __except support */ // useregs(mAX); // What is this for? CodeBuilder cdb1; cs.Iop = 0x68; cs.Iflags = 0; cs.Irex = 0; cs.IFL2 = FLconst; cs.IEV2.Vint = -1; cdb1.gen(&cs); // PUSH -1 if (MARS || (usednteh & NTEHcpp)) { // PUSH &framehandler cs.IFL2 = FLframehandler; #if MARS nteh_scopetable(); #endif } else { // Do stable cs.Iflags |= CFoff; cs.IFL2 = FLextern; cs.IEVsym2 = nteh_scopetable(); cs.IEVoffset2 = 0; cdb1.gen(&cs); // PUSH &scope_table cs.IFL2 = FLextern; cs.IEVsym2 = getRtlsym(RTLSYM_EXCEPT_HANDLER3); makeitextern(getRtlsym(RTLSYM_EXCEPT_HANDLER3)); } CodeBuilder cdb2; cdb2.gen(&cs); // PUSH &__except_handler3 if (config.exe == EX_WIN32) { makeitextern(getRtlsym(RTLSYM_EXCEPT_LIST)); #if 0 cs.Iop = 0xFF; cs.Irm = modregrm(0,6,BPRM); cs.Iflags = CFfs; cs.Irex = 0; cs.IFL1 = FLextern; cs.IEVsym1 = getRtlsym(RTLSYM_EXCEPT_LIST); cs.IEVoffset1 = 0; cdb2.gen(&cs); // PUSH FS:__except_list #else useregs(mDX); cs.Iop = 0x8B; cs.Irm = modregrm(0,DX,BPRM); cs.Iflags = CFfs; cs.Irex = 0; cs.IFL1 = FLextern; cs.IEVsym1 = getRtlsym(RTLSYM_EXCEPT_LIST); cs.IEVoffset1 = 0; cdb1.gen(&cs); // MOV EDX,FS:__except_list cdb2.gen1(0x50 + DX); // PUSH EDX #endif cs.Iop = 0x89; NEWREG(cs.Irm,SP); cdb2.gen(&cs); // MOV FS:__except_list,ESP } CodeBuilder cdb3(cod3_stackadj(NULL, 8)); cdb1.append(cdb2, cdb3); return cdb1.finish(); }