// vim: ft=cpp sw=4 ts=4 et /* (C) 2003-2008 Willem Jan Hengeveld * * Web: http://www.xs4all.nl/~itsme/projects/ida/ */ #include // these are all very experimental functions, which are quite unfinished. // it is an attempt to simulate arm instructions. static DataStart() { return FindData(0,1); } static DataEnd() { return FindCode(0,1); } static CodeStart() { return FindCode(0,1); } static CodeEnd() { return FindCode(0,0); } static FixDatasegment() { auto ea,v,x; ea=DataStart(); while(ea0 && v<10)) { if (x==0) { x= ea; } } else { if (x && (ea-x)/4>1) { MakeDword(x); MakeArray(x, (ea-x)/4); } x=0; } ea= ea+4; } ea=DataStart(); while(ea=DataStart() && v=CodeStart() && v>25)&7)==0 || ((n>>25)&7)==1) && (n&0x00100000)!=0) { x= 0; Message("set status: %08lx %s\n", ea, GetMnem(ea)); } if (GetMnem(ea)=="CMP") { opnd= ""; if (GetOpnd(ea,0)=="R7") opnd=GetOpnd(ea,1); if (GetOpnd(ea,1)=="R7") opnd=GetOpnd(ea,0); x= GetHashLong(1, opnd); Message("cmp: %08lx %s == %s(%08lx)\n", ea, GetOpnd(ea,0), GetOpnd(ea,1), x); } if (GetMnem(ea)=="B" && x && (Dword(ea)>>28)==1) // BNE { addr= ea+4; MakeName(addr, form("handle_ioctl_%08lx_%08lx", x, addr)); Message(" set %08lx to %08lx\n", addr, x); x= 0; } if (GetMnem(ea)=="B" && x && (Dword(ea)>>28)==0) // BEQ { opnd= GetOpnd(ea,0); addr= LocByName(opnd); MakeName(addr, form("handle_ioctl_%08lx_%08lx", x, addr)); Message(" set %08lx (%08lx) to %08lx\n", addr, opnd, x); x= 0; } // if (x) Message("%08lx : %08lx %s\n", ea, x, GetMnem(ea)); ea= ea+4; } } static DoesUpdateStatus(n) { return ( (((n>>25)&7)==0 || ((n>>25)&7)==1) && (n&0x00100000)!=0); } static FixStacks() { auto ea; ea= NextFunction(0); while ( ea!=BADADDR) { FixFuncStack(ea, FindFuncEnd(ea)); ea= NextFunction(ea); } } // this function is not finished, the idea is to automatically create function stack frames static FixFuncStack(start, end) { auto parammap; // what parameters are saved to be referenced auto savedmap; // what parameters are saved to be referenced auto ea; auto ea_save; auto ea_locals; auto savedsize; auto localsize; auto frameid; ea= start; /* * function start is one of these cases: * * case 1: ( with references to parameters ) * MOV R12, SP * STMFD SP!, {Ra-Rb} // a,b in range 0-3 * STMFD SP!, {Rx-Ry,R12,LR} // x,y in range 4-11 * ... * LDMFD SP!, {Rx-Ry,SP,PC} * * case 2: normal save regs. * STMFD SP!, {Rx-Ry,LR} // x,y in range 4-11 * ... * LDMFD SP!, {Rx-Ry,PC} */ if (GetMnem(ea)=="MOV" && GetOpnd(ea,0)=="R12" && GetOpnd(ea,1)=="SP") { ea= ea+4; // references to params 0-3 if (GetMnem(ea)=="STM" && GetOpnd(ea,0)=="SP!") { parammap= Dword(ea)&0xffff; ea= ea+4; } else { Message("unknown function entry1: %08lx %s %s\n", ea, GetMnem(ea), GetOpnd(ea,0)); return; } } if (GetMnem(ea)=="STM" && GetOpnd(ea,0)=="SP!") { savedmap= Dword(ea)&0xbfff; // ignore LR ea_save= ea; ea= ea+4; } else { Message("unknown function entry2: %08lx %s %s\n", ea, GetMnem(ea), GetOpnd(ea,0)); return; } savedsize= 4*CountBits(savedmap); /* * local variable reservation is one of these cases: * * case 1: large reservation * MOV R12, =CONSTANT * SUB SP, SP, R12 * ... * MOV R12, #0x... * ORR R12, R12, #0x... * ADD SP, SP, R12 * * case 2: small reservation * SUB SP, SP, #0x... * ... * ADD SP, SP, #0x... */ if (GetMnem(ea)=="LDR" && GetOpnd(ea, 0)=="R12" && substr(GetOpnd(ea,1),0,1)=="=") { localsize=Dword(GetOperandValue(ea,1)); ea= ea+4; } if (GetMnem(ea)=="SUB" && GetOpnd(ea, 0)=="SP" && GetOpnd(ea,1)=="SP") { ea_locals= ea; if (substr(GetOpnd(ea,2),0,1)=="#") localsize= GetOperandValue(ea,2); ea= ea+4; } else { localsize= 0; ea_locals= 0; //Message("unknown function entry3: %08lx %s %s\n", ea, GetMnem(ea), GetOpnd(ea,0)); //return; } /* * function exit is one of these cases: * * case 1: normal exit * LDMFD SP!, {...,PC} * * case 2: jump to subroutine * LDMFD SP!, {...,LR} * B sub * */ // GetFrameArgsSize()!=0 || GetFrameSize()!=4 || GetFrameRegsSize()!=0 || GetFrameLvarSize()!=0 if (GetSpd(ea)!=0 || GetFrameArgsSize(ea)!=0 || GetFrameSize(ea)!=4 || GetFrameRegsSize(ea)!=0 || GetFrameLvarSize(ea)!=0) { if (-GetSpd(ea)!=savedsize+localsize) { Message("spd=%08lx calced: %08lx\n", GetSpd(ea), savedsize+localsize); } if (GetFrameRegsSize(ea)!=savedsize) { Message("saved=%08lx calced: %08lx\n", GetFrameRegsSize(ea), savedsize); } if (GetFrameLvarSize(ea)!=localsize) { Message("local=%08lx calced: %08lx\n", GetFrameLvarSize(ea), localsize); } } Message(" regs=%04x locals=%04x\n", savedsize, localsize); SetSpDiff(ea_save, -savedsize); if (ea_locals) { SetSpDiff(ea_locals, -localsize); } frameid= MakeFrame(ea, localsize, savedsize, 0); while (ea>b1)&( (1<<(b0-b1+1))-1 ); } static GetBit(dw, b) { return (dw>>b)&1; } // this function is also not ready. // the intention is to assist in calculating register values. static DecodeInsn(op) { if (GetBits(op, 31,28)==15 && GetBit(op, 27)==0) { // this is the exception '[1a]' // undefined instruction [4,7] ( unpredictable =armv5 && armv4t) // Rm= GetBits(op, 3,0) } else // bit19-8 != all ones { // ?? } } else if (GetBits(op, 22,21)==3) { if (GetBits(op, 19,16)==15 && GetBits(op, 11,8)==15) { // Count leading zeros [2] (undef in armv4, unpred= C==1 * 0x3 CC LO uint< C==0 * 0x4 MI <0 N==1 * 0x5 PL >=0 N==0 * 0x6 VS overflow V==1 * 0x7 VC no ov V==0 * 0x8 HI uint> C==1 && Z==0 * 0x9 LS uint<= C==0 || Z==1 * 0xa GE int>= N==V * 0xb LT int< N!=V * 0xc GT int> N==V && Z==0 * 0xd LE int<= N!=V || Z==1 * 0xe AL always * 0xf NV never or invalid * */ static CountBits(n) { auto count; auto i; while(n) { if (n<0) count++; n = n<<1; } return count; }