code *nteh_unwind(regm_t retregs,unsigned index) { code cs; regm_t desregs; int reg; int local_unwind; // Shouldn't this always be CX? #if SCPP reg = AX; #else reg = CX; #endif #if MARS local_unwind = RTLSYM_D_LOCAL_UNWIND2; #else local_unwind = RTLSYM_LOCAL_UNWIND2; #endif desregs = (~getRtlsym(local_unwind)->Sregsaved & (ALLREGS)) | mask[reg]; code *cs1; code *cs2; gensaverestore(retregs & desregs,&cs1,&cs2); CodeBuilder cdb(getregs(desregs)); cs.Iop = 0x8D; 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); // LEA ECX,contextsym cdb.genc2(0x68,0,index); // PUSH index cdb.gen1(0x50 + reg); // PUSH ECX #if MARS //cdb.gencs(0xB8+AX,0,FLextern,nteh_scopetable()); // MOV EAX,&scope_table cdb.gencs(0x68,0,FLextern,nteh_scopetable()); // PUSH &scope_table cdb.gencs(0xE8,0,FLfunc,getRtlsym(local_unwind)); // CALL __d_local_unwind2() cdb.append(cod3_stackadj(NULL, -12)); #else cdb.gencs(0xE8,0,FLfunc,getRtlsym(local_unwind)); // CALL __local_unwind2() cdb.append(cod3_stackadj(NULL, -8)); #endif CodeBuilder cdb1(cs1); CodeBuilder cdb2(cs2); cdb1.append(cdb, cdb2); return cdb1.finish(); }
code *nteh_unwind(regm_t retregs,unsigned index) { code *c; code cs; code *cs1; code *cs2; regm_t desregs; int reg; int local_unwind; // Shouldn't this always be CX? #if SCPP reg = AX; #else reg = CX; #endif #if MARS local_unwind = RTLSYM_D_LOCAL_UNWIND2; #else local_unwind = RTLSYM_LOCAL_UNWIND2; #endif desregs = (~rtlsym[local_unwind]->Sregsaved & (ALLREGS)) | mask[reg]; gensaverestore(retregs & desregs,&cs1,&cs2); c = getregs(desregs); cs.Iop = 0x8D; 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(c,&cs); // LEA ECX,contextsym genc2(c,0x68,0,index); // PUSH index gen1(c,0x50 + reg); // PUSH ECX #if MARS //gencs(c,0xB8+AX,0,FLextern,nteh_scopetable()); // MOV EAX,&scope_table gencs(c,0x68,0,FLextern,nteh_scopetable()); // PUSH &scope_table gencs(c,0xE8,0,FLfunc,rtlsym[local_unwind]); // CALL __d_local_unwind2() genc2(c,0x81,modregrm(3,0,SP),12); // ADD ESP,12 #else gencs(c,0xE8,0,FLfunc,rtlsym[local_unwind]); // CALL __local_unwind2() genc2(c,0x81,modregrm(3,0,SP),8); // ADD ESP,8 #endif c = cat4(cs1,c,cs2,NULL); return c; }
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); }