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_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(); }