public static bool IsASMCode(uint asm) { if (U.IsValueOdd(asm)) { asm = asm - 1; } uint a = U.toOffset(asm); DisassemblerTrumb.VM vm = new DisassemblerTrumb.VM(); DisassemblerTrumb dis = new DisassemblerTrumb(); DisassemblerTrumb.Code code = dis.Disassembler(Program.ROM.Data, a, 0, vm); if (code.Type == DisassemblerTrumb.CodeType.Unknown) { return(false); } return(true); }
List <OtherROMLDRFuncSt> MakeOtherROMLDRFuncList(uint search_address) { List <OtherROMLDRFuncSt> list = new List <OtherROMLDRFuncSt>(); for (int i = 0; i < this.LDRMAPs.Count; i++) { DisassemblerTrumb.LDRPointer ldr = this.LDRMAPs[i]; if (ldr.ldr_data != search_address) { continue; } if (ldr.ldr_address <= SEARCH_PUSH_MAX) { continue; } DisassemblerTrumb Disassembler = new DisassemblerTrumb(); DisassemblerTrumb.VM vm = new DisassemblerTrumb.VM(); uint limit = ldr.ldr_address - SEARCH_PUSH_MAX; for (uint n = ldr.ldr_address - 2; n >= limit; n -= 2) { DisassemblerTrumb.Code code = Disassembler.Disassembler(Program.ROM.Data, n, (uint)Program.ROM.Data.Length, vm); if (code.Type == DisassemblerTrumb.CodeType.PUSH) { OtherROMLDRFuncSt pp = new OtherROMLDRFuncSt(); pp.FuncAddr = U.toPointer(n); pp.BackSize = ldr.ldr_address - n; list.Add(pp); } else if (code.Type == DisassemblerTrumb.CodeType.BXJMP) { break; } } } return(list); }
public static void MakeAllDisASMButton(Form self, string store_filename, bool notifyUpdateMessage) { uint addr = 0x100; using (InputFormRef.AutoPleaseWait wait = new InputFormRef.AutoPleaseWait(self)) using (StreamWriter writer = new StreamWriter(store_filename)) { writer.WriteLine("//FEBuilderGBA " + R._("逆アセンブラ")); if (notifyUpdateMessage) { writer.WriteLine("//" + DateTime.Now.ToString("yyyyMMdd") + " " + R._("ソースコードを更新する場合は、このファイル消すか、0バイトの空ファイルにしてください。")); } wait.DoEvents("GrepAllStructPointers"); AsmMapFile asmMapFile = new AsmMapFile(Program.ROM); DisassemblerTrumb Disassembler = new DisassemblerTrumb(asmMapFile); List <DisassemblerTrumb.LDRPointer> ldrmap = Program.AsmMapFileAsmCache.GetLDRMapCache(); List <Address> structlist = U.MakeAllStructPointersList(false); //既存の構造体 U.AppendAllASMStructPointersList(structlist , ldrmap , isPatchInstallOnly: false , isPatchPointerOnly: false , isPatchStructOnly: false , isUseOtherGraphics: true , isUseOAMSP: true ); AsmMapFile.InvalidateUNUNSED(structlist); UnpackBINByCode(structlist); MakeFreeData(structlist); asmMapFile.AppendMAP(structlist); //コメントデータ Program.CommentCache.MakeAddressList(structlist); asmMapFile.AppendMAP(structlist); {//設計をミスった。 綺麗なリストを作りたいので、もう一回読みこみなおそう... AsmMapFile asmMapFile2 = new AsmMapFile(Program.ROM); asmMapFile2.MakeAllDataLength(structlist); AsmMapFile.InvalidateUNUNSED(structlist); } uint limit = (uint)Program.ROM.Data.Length; int jisage = 0; //字下げする数 string jisageSpaceData = ""; //字下げに利用するマージンデータ List <uint> jmplabel = new List <uint>(); //ジャンプラベル 字下げに使う Dictionary <uint, uint> ldrtable = new Dictionary <uint, uint>(); //LDR参照データがある位置を記録します. コードの末尾などにあります. 数が多くなるのでマップする. AsmMapFile.MakeSwitchDataList(ldrtable, 0x100, 0); wait.DoEvents(R._("データを準備中...")); //探索を早くするために、データをアドレスへマッピングする. メモリを大量に使うが早い. Dictionary <uint, Address> lookupStructMap = MakeAllStructMapping(structlist); structlist = null; uint nextDoEvents = 0; bool prevPointer = false; //ひとつ前がポインタだった Address matchAddress; DisassemblerTrumb.VM vm = new DisassemblerTrumb.VM(); while (addr < limit) { if (addr > nextDoEvents) {//毎回更新するのは無駄なのである程度の間隔で更新して以降 wait.DoEvents(String.Format("{0}/{1}", addr, limit)); nextDoEvents = addr + 0xfff; } if (lookupStructMap.TryGetValue(addr, out matchAddress)) { if (matchAddress.Pointer <= addr && addr < matchAddress.Pointer + 4) {//ポインタ? writer.WriteLine(U.toPointer(addr).ToString("X08") + " " + U.MakeOPData(addr, 4) + " //POINTER " + matchAddress.Info); addr += 4; } else {//データ uint newaddr = U.Padding2(matchAddress.Addr + matchAddress.Length); uint length = (newaddr - addr); Debug.Assert(length < 10000000); writer.WriteLine("{0} - {1} //{2} ({3}bytes)", U.toPointer(addr).ToString("X08"), U.toPointer(newaddr).ToString("X08"), matchAddress.Info, length); addr = U.Padding4(newaddr); } prevPointer = true; continue; } //LDR参照とスイッチ参照 if (ldrtable.ContainsKey(addr)) {//LDR参照のポインタデータが入っている uint ldr = ldrtable[addr]; if (ldr == U.NOT_FOUND) {//switch case writer.WriteLine(U.toPointer(addr).ToString("X08") + " " + U.MakeOPData(addr, 4) + " //SWITCH CASE"); } else { writer.WriteLine(U.toPointer(addr).ToString("X08") + " " + U.MakeOPData(addr, 4) + " //LDRDATA"); } addr += 4; prevPointer = true; continue; } if (prevPointer) {//ひとつ前がポインタの場合、野生のポインタをチェック uint data = Program.ROM.u32(addr); if (U.isPointer(data)) { if (lookupStructMap.TryGetValue(U.toOffset(data), out matchAddress)) { writer.WriteLine(U.toPointer(addr).ToString("X08") + " " + U.MakeOPData(addr, 4) + " //Wild POINTER " + U.ToHexString8(data) + " " + matchAddress.Info); addr += 4; continue; } } } //ひとつ前はポインタではない. prevPointer = false; //Disassembler DisassemblerTrumb.Code code = Disassembler.Disassembler(Program.ROM.Data, addr, limit, vm); if (code.Type == DisassemblerTrumb.CodeType.BXJMP) {//関数の出口なので字下げをすべて取り消す. jisage = 0; jmplabel.Clear(); jisageSpaceData = ""; } else { for (int i = 0; i < jmplabel.Count;) { if (addr >= jmplabel[i]) { jmplabel.RemoveAt(i); jisage--; jisageSpaceData = U.MakeJisageSpace(jisage); i = 0; continue; } i++; } } writer.WriteLine(jisageSpaceData + U.toPointer(addr).ToString("X08") + " " + U.MakeOPData(addr, code.GetLength()) + " " + code.ASM.ToLower() + code.Comment); if (code.Type == DisassemblerTrumb.CodeType.CONDJMP //条件式なので字下げ開始 ) { uint jumplabel = U.toOffset(code.Data); if (addr < jumplabel) {//とび先が自分より後ろであること. 前方はすでに過ぎてしまったので字下げできない. jisage++; jmplabel.Add(jumplabel); jisageSpaceData = U.MakeJisageSpace(jisage); } } else if (code.Type == DisassemblerTrumb.CodeType.BXJMP) {//関数の終わりなので空行を入れる. writer.WriteLine(""); } if (code.Type == DisassemblerTrumb.CodeType.LDR) {//LDR参照位置を記録していく. ldrtable[code.Data2] = addr; } addr += code.GetLength(); } } if (self != null) { //エクスプローラで選択しよう U.SelectFileByExplorer(store_filename); } }
private void ReloadListButton_Click(object sender, EventArgs e) { uint addr = (uint)ReadStartAddress.Value; if (U.isPointer(addr)) { addr = U.toOffset(addr); U.ForceUpdate(ReadStartAddress, addr); } if (DisassemblerTrumb.ProgramAddrToPlain(addr) != addr) { addr = DisassemblerTrumb.ProgramAddrToPlain(addr); U.ForceUpdate(ReadStartAddress, addr); } if (!U.isSafetyOffset(addr)) { return; } uint addr_1 = addr; //変更通知. if (Navigation != null) { NavigationEventArgs arg = new NavigationEventArgs(); arg.Address = addr; Navigation(this, arg); } DisassemblerTrumb Disassembler = new DisassemblerTrumb(Program.AsmMapFileAsmCache.GetAsmMapFile()); uint length = (uint)Program.ROM.Data.Length; if (ReadCount.Value == 0 || this.IsLengthAutoChecked) { List <uint> ldrbuffer = new List <uint>(); U.ForceUpdate(ReadCount, DisassemblerTrumb.CalcLength(Program.ROM.Data , addr, length, ldrbuffer)); //自動的に長さを求めました this.IsLengthAutoChecked = true; } uint bytecount = (uint)ReadCount.Value; this.AddressList.Items.Clear(); this.AddressList.BeginUpdate(); uint limit = Math.Min(addr + bytecount, length); int jisage = 0; //字下げする数 string jisageSpaceData = ""; //字下げに利用するマージンデータ List <uint> jmplabel = new List <uint>(); //ジャンプラベル 字下げに使う Dictionary <uint, uint> ldrtable = new Dictionary <uint, uint>(); //LDR参照データがある位置を記録します. コードの末尾などにあります. 数が多くなるのでマップする. AsmMapFile.MakeSwitchDataList(ldrtable, addr, limit); DisassemblerTrumb.VM vm = new DisassemblerTrumb.VM(); while (addr < limit) { if (ldrtable.ContainsKey(addr)) {//LDR参照のポインタデータが入っている uint ldr = ldrtable[addr]; if (ldr == U.NOT_FOUND) {//switch case this.AddressList.Items.Add(U.toPointer(addr).ToString("X08") + " " + U.MakeOPData(addr, 4) + " //SWITCH CASE"); } else { this.AddressList.Items.Add(U.toPointer(addr).ToString("X08") + " " + U.MakeOPData(addr, 4) + " //LDRDATA"); } addr += 4; continue; } //Disassembler DisassemblerTrumb.Code code = Disassembler.Disassembler(Program.ROM.Data, addr, length, vm); if (code.Type == DisassemblerTrumb.CodeType.BXJMP) {//関数の出口なので字下げをすべて取り消す. jisage = 0; jmplabel.Clear(); jisageSpaceData = ""; } else { for (int i = 0; i < jmplabel.Count;) { if (addr >= jmplabel[i]) { jmplabel.RemoveAt(i); jisage--; jisageSpaceData = U.MakeJisageSpace(jisage); i = 0; continue; } i++; } } this.AddressList.Items.Add(jisageSpaceData + U.toPointer(addr).ToString("X08") + " " + U.MakeOPData(addr, code.GetLength()) + " " + code.ASM + code.Comment); if (code.Type == DisassemblerTrumb.CodeType.CONDJMP //条件式なので字下げ開始 ) { uint jumplabel = U.toOffset(code.Data); if (addr < jumplabel) {//とび先が自分より後ろであること. 前方はすでに過ぎてしまったので字下げできない. jisage++; jmplabel.Add(jumplabel); jisageSpaceData = U.MakeJisageSpace(jisage); } } if (code.Type == DisassemblerTrumb.CodeType.LDR) {//LDR参照位置を記録していく. ldrtable[code.Data2] = addr; } addr += code.GetLength(); } this.AddressList.EndUpdate(); U.SelectedIndexSafety(this.AddressList, 0, true); }
public static bool[] makeSkipDataByCode(byte[] need) { DisassemblerTrumb Disassembler = new DisassemblerTrumb(); DisassemblerTrumb.VM vm = new DisassemblerTrumb.VM(); uint length = (uint)need.Length; bool isFunctionEnd = false; uint ldrCount = 0; bool[] isSkip = new bool[U.Padding4(length)]; for (uint i = 0; i < length - 3;) { if (isFunctionEnd) { //関数は抜けてしまったので、ldr用のポインタだけを見る. if (ldrCount <= 0) { //LDR値の地帯を抜けたので次はまた関数に復帰するはず. isFunctionEnd = false; continue; } ldrCount--; if (U.isPointer(U.u32(need, i))) { isSkip[i + 0] = true; isSkip[i + 1] = true; isSkip[i + 2] = true; isSkip[i + 3] = true; } i += 4; continue; } DisassemblerTrumb.Code code = Disassembler.Disassembler(need, i, length, vm); if (code.Type == DisassemblerTrumb.CodeType.CALL) {//関数呼び出しはアドレスの違いがかなり出てくるので. isSkip[i + 0] = true; isSkip[i + 1] = true; isSkip[i + 2] = true; isSkip[i + 3] = true; } if (code.Type == DisassemblerTrumb.CodeType.LDR) { //LDRで超長距離飛んでしまう場合は例外. uint a = U.u16(need, i); uint imm = DisassemblerTrumb.LDR_IMM(a); if (imm >= 0x64) {//あまりに長い距離飛ぶ場合、シリーズ間でずれることがあるらしい 0x64は適当な値です. isSkip[i + 0] = true; isSkip[i + 1] = true; isSkip[i + 2] = true; //長距離LDRをした次の命令も変わることがあるらしいので、ねんのため isSkip[i + 3] = true; } else { isSkip[i + 0] = true; //次の関数の開始位置を推測. BXJMPで抜けた後 LDRデータが終わったら、次の関数があるはず. ldrCount++; } } i += code.GetLength(); if (code.Type == DisassemblerTrumb.CodeType.BXJMP) {//関数終端 以降あるのは ldr用のアドレス地帯だろう isFunctionEnd = true; //関数を抜けたときに 4バイトパディングを維持しないといけない. i = U.Padding4(i); } } return(isSkip); }