Esempio n. 1
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);
        }