#include #include "debug.h" #include "stringutils.h" #include "args.h" #include "kernelmisc.h" #include "arm_cp.h" // tstbxj // r[i] = 0xe0000000+0x1110*i // -> prefetch abort @ pc=0xe000eee0 bva=0x27ffc9e4 pexi=0xe000dda4{SP-0x2c} r5 -= 0x140 // -> data abort @ pc=0x8c10a368, bva=0xe0005810{r5+0x2c0} // // tstbxj -5 // r[i] = 0xe0000000+0x1110*i, r[5]={handler, ..., handler} // -> prefetch abort @ pc=0xe000eee0 bva=0x2dffc9e4 pexi=0xe000dda4 r5 = 0x1a90730-0x300 // // tstbxj -5 // -> prefetch abort @ pc=0xe000eee0 bva=0xe0007770{r7} pexi=0xe000dda4 r5 = 0x1a90730-0x300 // -> data abort @ pc=0x8c10a368, bva=0xe0007770 // // tstbxj -5, r5={0xd0000000+i*0x1000} // -> prefetchabort @ pc=0xd0024000, ra=0x1a902cc, bva=0xd0024000 // #define structofs(s,x) ((int)(&(((s*)0)->x))) struct regbank { uint32_t cpsr; uint32_t r[16]; }; class bxjcode { private: typedef void (*voidfn)(); DwordVector _code; voidfn _fn; regbank *_regs; public: bxjcode() { genbxj(_code, &_regs, &_fn); debug("%08lx: bxjcall: %s\n", &_code[0], hexdump((BYTE*)(&_code[0]), _code.size(), 4).c_str()); } regbank call(const regbank& regs) { memcpy(_regs, ®s, sizeof(regbank)); _fn(); regbank out; memcpy(&out, _regs+1, sizeof(regbank)); return out; } private: void genbxj(DwordVector& code, regbank** regs, voidfn *bxjfn) { typedef std::map fixupmap_t; fixupmap_t fixups; code.push_back(0xe92d7ff0); // STMFD SP!, {R4..R14} fixups[code.size()]= structofs(regbank, cpsr); code.push_back(0xe59f0000); // LDR R0, [PC,#...] // cond 0001 0R10 field_mask : SBO SBZ 0000 Rm - msr code.push_back(0xe128f000); // MSR R0, CPSR fixups[code.size()]= structofs(regbank, r[0]); code.push_back(0xe28f0000); // ADD R0, PC, #... // don't touch LR and SP code.push_back(0xe8901fff); // LDMIA R0, {R0..R12} code.push_back(0xe1a0e00f); // MOV LR, PC code.push_back(0xe12fff2c); // BXJ R12 // cond 01IP U0W0 Rn : Rd addr_mode fixups[code.size()]= sizeof(regbank)+structofs(regbank, r[0]); code.push_back(0xe58f0000); // STR R0, [PC,#...] // cond 0001 0R00 SBO : Rd SBZ - mrs code.push_back(0xe10f0000); // MRS R0, CPSR fixups[code.size()]= sizeof(regbank)+structofs(regbank, cpsr); code.push_back(0xe58f0000); // STR R0, [PC,#...] fixups[code.size()]= sizeof(regbank)+structofs(regbank, r[1]); code.push_back(0xe28f0000); // ADD R0, PC, #... code.push_back(0xe8807ffe); // STMIA R0, {R1..R14} code.push_back(0xe8bd7ff0); // LDMFD SP!, {R4..R14} code.push_back(0xe12fff1e); // BX LR int ofstoregs=code.size(); code.resize(code.size()+2*(sizeof(regbank)/sizeof(uint32_t))); // twice r0..r14 + twice cpsr + once spsr for (fixupmap_t::iterator i= fixups.begin() ; i!=fixups.end() ; i++) { code[(*i).first] += sizeof(uint32_t)*(ofstoregs-(*i).first-2)+(*i).second; } CacheRangeFlush(0, 0, CACHE_SYNC_ALL); *regs= reinterpret_cast(&code[ofstoregs]); *bxjfn= reinterpret_cast(&code[0]); } }; void unhandled(int r0, int r1, int r2, int r3) { *(DWORD*)0xeeee0000; } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { DebugSetLogfile("tstbxj.log"); StringList args; if (!SplitString(ToString(lpCmdLine), args, false)) { error("Error in commandline"); return false; } bool bPointR5= false; bool bPointR14=false; for (StringList::iterator i= args.begin() ; i!=args.end() ; ++i) { std::string& arg= *i; if (arg[0]=='-') switch(arg[1]) { case '5': bPointR5=true; break; case 'e': case 'E': bPointR14=true; break; } } KernelMode _km; bxjcode bxj; armcoprocessor cp; debug("jzid= %08lx [AIISSiii]\n", cp.read(14,7,0,0,0)); debug("jzoscontrol=%08lx [0000000C] cv + cd bits\n", cp.read(14,7,1,0,0)); debug("jzconfig= %08lx [0000000J] JE bit\n", cp.read(14,7,2,0,0)); cp.write(14,7,2,0,0, 1); regbank r; memset(&r, 0, sizeof(r)); for (int i=0 ; i<16 ; i++) r.r[i]= 0x1110*i+0xe0000000; const uint8_t undefbc[]={0xcb,0xfe,0xff}; const uint8_t load42bc[]={0x10,0x00,0x00,0x00,0x2a,0x3b,0x1a,0xff,0xfe}; if (bPointR14) r.r[14]= reinterpret_cast(undefbc); // todo: generate different code for each handler DwordVector r5(1024); for (unsigned i=0 ; i<1024 ; i++) { r5[i]= 0xd0000000+i*0x1000; // reinterpret_cast(&unhandled); } if (bPointR5) r.r[5]= reinterpret_cast(&r5[0]); debug("unh=%08lx, r5=%08lx r14=%08lx\n", &unhandled, r.r[5], r.r[14]); DWORD heapblock= ((DWORD)&r5[0])&~0xfff; // debug(".... heap block (ph=%08lx)\n%s\n", GetProcessHeap(), // hexdump(heapblock, (BYTE*)heapblock, 0x1000).c_str()); regbank rout= bxj.call(r); debug("cpsr=%08lx\n", r.cpsr); debug("0-3 =%08lx %08lx %08lx %08lx\n", rout.r[0], rout.r[1], rout.r[2], rout.r[3]); debug("4-7 =%08lx %08lx %08lx %08lx\n", rout.r[4], rout.r[5], rout.r[6], rout.r[7]); debug("8-b =%08lx %08lx %08lx %08lx\n", rout.r[8], rout.r[9], rout.r[10], rout.r[11]); debug("c-f =%08lx %08lx %08lx %08lx\n", rout.r[12], rout.r[13], rout.r[14], rout.r[15]); debug("done\n\n"); }