#include "idc.idc" static make_sda_relative_opcode(ea,mnem,opnd0,realaddr,sda_base,opreg1) { auto output; auto name0,name1; auto brace; // if second operand starts with a brace, it was probably already // converted/handled before, so we do not touch it brace=strstr(GetOpnd(ea,1),"("); if((brace!=-1)&&(brace<2)) { return; } //name0=GetTrueName(realaddr); //name1=GetTrueName(sda_base); name0=NameEx(ea,realaddr); name1=NameEx(ea,sda_base); //output=mnem+" "+opnd0+", "; output="("; if(name0!="") { output=output+name0; } else { output=output+"0x"+ltoa(realaddr,16); } output=output+"-"; if(name1!="") { output=output+name1; } else { output=output+"0x"+ltoa(sda_base,16); } output=output+")(%"; if(opreg1==2) { output=output+"rtoc"; } else { output=output+"r"+ltoa(opreg1,10); } output=output+")"; // modify instruction //SetManualInsn(ea,output); OpAlt(ea,1,output); // add data xref add_dref(ea,realaddr,dr_T|XREF_USER); // Message("%08x: %s\n",ea,output); } static make_sda_imm_opcode(ea,mnem,opreg0,opreg1,realaddr,sda_base) { auto output; auto name0,name1; auto brace; // if third operand starts with a brace, it was probably already // converted/handled before, so we do not touch it brace=strstr(GetOpnd(ea,2),"("); if((brace!=-1)&&(brace<2)) { return; } //name0=GetTrueName(realaddr); //name1=GetTrueName(sda_base); name0=NameEx(ea,realaddr); name1=NameEx(ea,sda_base); //output=mnem+" %r"+ltoa(opreg0,10)+", %r"+ltoa(opreg1,10)+", "; output="("; if(name0!="") { output=output+name0; } else { output=output+"0x"+ltoa(realaddr,16); } output=output+"-"; if(name1!="") { output=output+name1; } else { output=output+"0x"+ltoa(sda_base,16); } output=output+")"; // modify instruction //SetManualInsn(ea,output); OpAlt(ea,2,output); // add data xref add_dref(ea,realaddr,dr_T|XREF_USER); // Message("%08x: %s\n",ea,output); } static dofunction(startea,sda_base,sda2_base) { auto ea,nextea, screenea,funcend,mnem; auto opnd0,opnd1,opnd2; auto output,spdif,i; auto optype; auto opval0,opval1,opval2; auto realaddr; auto opreg0,opreg1,opreg2; auto name0,name1; screenea = startea; funcend=FindFuncEnd(screenea); // Message("Function %08lx-%08lx %s\n", startea,funcend, Name(startea)); for (ea=screenea;ea<=funcend;ea=NextHead(ea, funcend)) { //Message(GetCurrentLine()); //Message(GetMnem(ea)); mnem = GetMnem(ea); opnd0 = GetOpnd(ea,0); opnd1 = GetOpnd(ea,1); opnd2 = GetOpnd(ea,2); optype= GetOpType(ea,1); if (ea==BADADDR) break; if( (strstr( mnem,"lbz" ) != -1)| (strstr( mnem,"lha" ) != -1)| (strstr( mnem,"lhz" ) != -1)| (strstr( mnem,"lwz" ) != -1)| (strstr( mnem,"lfd" ) != -1)| (strstr( mnem,"lfs" ) != -1)| (strstr( mnem,"lmw" ) != -1)| (strstr( mnem,"stb" ) != -1)| (strstr( mnem,"sth" ) != -1)| (strstr( mnem,"stmw" ) != -1)| (strstr( mnem,"stw" ) != -1) ) { opval1= GetOperandValue(ea,1); opreg0= (Dword(ea)>>21)&0x1f; opreg1= (Dword(ea)>>16)&0x1f; if((opreg0!=13)&&(opreg1==13)) // sda_base { realaddr=sda_base+opval1; make_sda_relative_opcode(ea,mnem,opnd0,realaddr,sda_base,opreg1); } if((opreg0!=2)&&(opreg1==2)) // sda2_base { realaddr=sda2_base+opval1; make_sda_relative_opcode(ea,mnem,opnd0,realaddr,sda2_base,opreg1); // Message("%08x: %d %d %d %s\n",ea,opreg1,GetOpType(ea,1),GetOperandValue(ea,1),GetDisasm(ea)); } } if( (strstr( mnem,"subi" ) != -1) ) { opval2= GetOperandValue(ea,2); opreg0= (Dword(ea)>>21)&0x1f; opreg1= (Dword(ea)>>16)&0x1f; if((opreg0!=13)&&(opreg1==13)) // sda_base { realaddr=sda_base-opval2; // Message("%08x: %s %d %d %08x\n",ea,mnem,opreg0,opreg1,opval2); make_sda_imm_opcode(ea,mnem,opreg0,opreg1,realaddr,sda_base); } if((opreg0!=2)&&(opreg1==2)) // sda2_base { realaddr=sda2_base-opval2; // Message("%08x: %s %d %d %08x\n",ea,mnem,opreg0,opreg1,opval2); make_sda_imm_opcode(ea,mnem,opreg0,opreg1,realaddr,sda2_base); } } } } static main(void) { auto ea,startea,endea; auto _f_sbss2; auto __ArenaHi; auto __ArenaLo; auto _db_stack_addr; auto _stack_addr; auto _stack_end; auto _SDA_BASE_; auto _SDA2_BASE_; // get values from absolute symbols segment _SDA_BASE_=Dword(LocByName("_SDA_BASE_")); _SDA2_BASE_=Dword(LocByName("_SDA2_BASE_")); _stack_addr=Dword(LocByName("_stack_addr")); _stack_end=Dword(LocByName("_stack_end")); _db_stack_addr=Dword(LocByName("_db_stack_addr")); __ArenaLo=Dword(LocByName("__ArenaLo")); __ArenaHi=Dword(LocByName("__ArenaHi")); _f_sbss2=Dword(LocByName("_f_sbss2")); // create new segments for the absolute symbols so IDA sees (and uses) them SegCreate(_SDA_BASE_,_SDA_BASE_,0,1,saAbs,scCommon); SegCreate(_SDA2_BASE_,_SDA2_BASE_,0,1,saAbs,scCommon); SegCreate(_stack_addr,_stack_addr,0,1,saAbs,scCommon); SegCreate(_stack_end,_stack_end,0,1,saAbs,scCommon); SegCreate(_db_stack_addr,_db_stack_addr,0,1,saAbs,scCommon); SegCreate(__ArenaLo,__ArenaLo,0,1,saAbs,scCommon); SegCreate(__ArenaHi,__ArenaHi,0,1,saAbs,scCommon); SegCreate(_f_sbss2,_f_sbss2,0,1,saAbs,scCommon); MakeNameEx(_SDA_BASE_,"_SDA_BASE_",SN_PUBLIC); MakeNameEx(_SDA2_BASE_,"_SDA2_BASE_",SN_PUBLIC); MakeNameEx(_stack_addr,"_stack_addr",SN_PUBLIC); MakeNameEx(_stack_end,"_stack_end",SN_PUBLIC); MakeNameEx(_db_stack_addr,"_db_stack_addr",SN_PUBLIC); MakeNameEx(__ArenaLo,"__ArenaLo",SN_PUBLIC); MakeNameEx(__ArenaHi,"__ArenaHi",SN_PUBLIC); MakeNameEx(_f_sbss2,"_f_sbss2",SN_PUBLIC); Message("SDA_BASE (r13): %08lx\n", LocByName("_SDA_BASE_")); Message("SDA_BASE (rtoc): %08lx\n", LocByName("_SDA2_BASE_")); // wait until end of previous autoanalysis Message("waiting for autoanalyzation to finish.\n"); Wait(); // run the fixup procedure for all functions startea= NextFunction(0); endea=0x81700000; Message("starting fixup in area 0x%08x ... 0x%08x\n",startea,endea); ea=startea; while (ea!=BADADDR) { dofunction(ea,_SDA_BASE_,_SDA2_BASE_); ea= NextFunction(ea); } Message("fixup done, rerunning autoanalyzation.\n"); AnalyzeArea(startea,endea); Message("all done.\n"); }