Пример #1
0
            public Hexes(uint pointer, DisassemblerTrumb.Code code, int jisage, uint addr)
            {
                this.Pointer = pointer;
                if (U.isPointer(code.Data))
                {
                    this.Data = code.Data;
                }
                if (code.Data2 >= 0x100 && code.Data2 < 0x02000000)
                {
                    this.Data2 = U.toPointer(code.Data2);
                }

                this.Jisage       = jisage;
                this.CodeString   = code.ASM;
                this.OPDumpString = U.MakeOPData(addr, code.GetLength());
                this.Comment      = code.Comment;
            }
        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);
            }
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }