Exemplo n.º 1
0
        protected ILExpression CreateLabeledExpression(GMCode code)
        {
            int          absolute = GMCodeUtil.getBranchOffset(CurrentRaw) + CurrentPC;
            ILExpression e        = new ILExpression(code, GetLabel(absolute));

            e.Extra = (int)(CurrentRaw & 0xFFFF);
            e.ILRanges.Add(new ILRange(CurrentPC, CurrentPC));
            return(e);
        }
Exemplo n.º 2
0
        public static Instruction DissasembleFromReader(int address, BinaryReader r)
        {
            Instruction ret = new Instruction(address);
            uint        raw = r.ReadUInt32();

            ret.Code = GMCodeUtil.getFromRaw(raw);
            if (DissasembleRawCode(ret, raw))
            {
                switch (ret.Code)
                {
                case GMCode.Call:
                case GMCode.Pop:
                    ret.Operand = r.ReadInt32();
                    break;

                case GMCode.Push:
                {
                    switch (ret.Types[0])
                    {
                    case GM_Type.Long:
                        ret.Operand = r.ReadInt64();
                        break;

                    case GM_Type.Double:
                        ret.Operand = r.ReadDouble();
                        break;

                    case GM_Type.Float:
                        ret.Operand = r.ReadSingle();
                        break;

                    case GM_Type.Bool:
                        ret.Operand = r.ReadInt32() != 0 ? true : false;             // tested, yess this is silly
                        break;

                    case GM_Type.String:
                    case GM_Type.Var:
                    case GM_Type.Int:
                        ret.Operand = r.ReadInt32();
                        break;

                    case GM_Type.Short:
                        break;             // already read in DissasembleRawCode
                    }
                }
                break;
                }
                Debug.Assert(ret.Operand != null);
            }
            return(ret);
        }
Exemplo n.º 3
0
 public ILValue(object o, GM_Type type)
 {
     if (o is short)
     {
         this.Value = (int)((short)o);
     }
     else if (type == GM_Type.String)
     {
         this.ValueText = GMCodeUtil.EscapeString(o as string);
     }
     else
     {
         this.Value = o;
     }
     Type = type;
 }
Exemplo n.º 4
0
 void WriteOperand(ITextOutput output, bool escapeString = true)
 {
     if (Operand == null)
     {
         output.Write("%NULL_OPERAND%");
     }
     else if (Operand is ILLabel)
     {
         output.Write((Operand as ILLabel).Name);
     }
     else if (escapeString)
     {
         if (Operand is string)
         {
             output.Write(GMCodeUtil.EscapeString((string)Operand));
         }
         else if (Operand is ILValue)
         {
             ILValue val = Operand as ILValue;
             if (escapeString && val.Type == GM_Type.String)
             {
                 output.Write(val.ValueText);
             }
             else
             {
                 output.Write(val.ToString());
             }
         }
         else
         {
             output.Write(Operand.ToString());
         }
     }
     else
     {
         output.Write(Operand.ToString());
     }
 }
Exemplo n.º 5
0
 public ILValue(string i)
 {
     this.Value = i; Type = GM_Type.String; this.ValueText = GMCodeUtil.EscapeString(i as string);
 }
Exemplo n.º 6
0
        // This pass accepts index or instance values being
        protected override ILExpression CreateExpression(List <ILNode> list)
        {
            ILExpression e       = null;
            OldCode      nOpCode = (OldCode)(CurrentRaw >> 24);

            GM_Type[] types = ReadTypes(CurrentRaw);
            switch (nOpCode) // the bit switch
            {
            case OldCode.Conv: e = CreateExpression(GMCode.Conv, types); break;

            case OldCode.Popz: e = CreateExpression(GMCode.Popz, types); break;

            case OldCode.Mul: e = CreateExpression(GMCode.Mul, types); break;

            case OldCode.Div: e = CreateExpression(GMCode.Div, types); break;

            case OldCode.Rem: e = CreateExpression(GMCode.Rem, types); break;

            case OldCode.Mod: e = CreateExpression(GMCode.Mod, types); break;

            case OldCode.Add: e = CreateExpression(GMCode.Add, types); break;

            case OldCode.Sub: e = CreateExpression(GMCode.Sub, types); break;

            case OldCode.And: e = CreateExpression(GMCode.And, types); break;

            case OldCode.Or: e = CreateExpression(GMCode.Or, types); break;

            case OldCode.Xor: e = CreateExpression(GMCode.Xor, types); break;

            case OldCode.Neg: e = CreateExpression(GMCode.Neg, types); break;

            case OldCode.Not: e = CreateExpression(GMCode.Not, types); break;

            case OldCode.Sal: e = CreateExpression(GMCode.Sal, types); break;

            //    case GMCode.S: e = CreateExpression(GMCode.Sal, types); break;
            //    case GMCode.S: e = CreateExpression(GMCode.Sal, types); break;
            //  case GMCode.shr:     e = CreateExpression(GMCode.Saa, types); break; // hack, handle shift right
            case OldCode.Slt: e = CreateExpression(GMCode.Slt, types); break;

            case OldCode.Sle: e = CreateExpression(GMCode.Sle, types); break;

            case OldCode.Seq: e = CreateExpression(GMCode.Seq, types); break;

            case OldCode.Sne: e = CreateExpression(GMCode.Sne, types); break;

            case OldCode.Sge: e = CreateExpression(GMCode.Sge, types); break;

            case OldCode.Sgt: e = CreateExpression(GMCode.Sgt, types); break;


            case OldCode.Dup:
                e         = CreateExpression(GMCode.Dup, types);
                e.Operand = (int)(CurrentRaw & 0xFFFF);     // dup type
                break;

            case OldCode.Call:
                e         = CreateExpression(GMCode.CallUnresolved, types);
                e.Operand = ILCall.CreateCall(File.Strings[r.ReadInt32()].String, (int)(CurrentRaw & 0xFFFF));

                break;

            case OldCode.Ret: e = CreateExpression(GMCode.Ret, types); break;

            case OldCode.Exit: e = CreateExpression(GMCode.Exit, types); break;

            case OldCode.B: e = CreateLabeledExpression(GMCode.B); break;

            case OldCode.Bt: e = CreateLabeledExpression(GMCode.Bt); break;

            case OldCode.Bf: e = CreateLabeledExpression(GMCode.Bf); break;

            // We have to fix these to a lopp to emulate a while latter
            case OldCode.Pushenv:
            {
                //    Debug.WriteLine("Popenv: Address: {0}, Extra: {1} {1:X8}  Calc: {2}", CurrentPC, CurrentRaw, GMCodeUtil.getBranchOffset(CurrentRaw));
                int sextra = CurrentPC + GMCodeUtil.getBranchOffset(CurrentRaw);
                e = CreateExpression(GMCode.Pushenv, types, GetLabel(sextra + 1)); // we are one instruction after the pop
                pushEnviroment.Add(sextra, GetLabel(CurrentPC));                   // record the pop position
            }
            break;

            case OldCode.Popenv:
            {
                // We convert this to a Branch so the loop detecter will find it
                e = CreateExpression(GMCode.Popenv, types);
                // e = CreateExpression(GMCode.Popenv, types);
                if (CurrentRaw == 0xbcf00000)        // its a break, ugh, old break code ugh
                {
                    foreach (var last in list.Reverse <ILNode>().OfType <ILExpression>())
                    {
                        if (last.Code == GMCode.Pushenv)
                        {
                            e.Operand = last.Operand;
                            return(e);
                        }
                    }
                    Debug.Assert(false);
                }
                else
                {
                    // some reason its the negitive offset?
                    // int offset = GMCodeUtil.getBranchOffset(CurrentRaw) - currentPC;
                    ILLabel endOfEnviroment;
                    if (pushEnviroment.TryGetValue(CurrentPC, out endOfEnviroment)) // this is the code
                    {
                        e.Operand = endOfEnviroment;                                // not a break, set the label BACK to the push as we are simulating a loop
                    }
                    else
                    {
                        throw new Exception("This MUST be a break");
                    }
                }
            }
            break;

            case OldCode.Pop:
                e         = CreateExpression(GMCode.Pop, types);
                e.Operand = BuildUnresolvedVar(r.ReadInt32());

                break;

            case OldCode.Push:
                e = CreatePushExpression(GMCode.Push, types);
                break;

            case OldCode.Break: e = CreateExpression(GMCode.Break, types); break;

            default:
                throw new Exception("Bad opcode");
            }
            return(e);
        }
Exemplo n.º 7
0
        protected override ILExpression CreateExpression(List <ILNode> list)
        {
            ILExpression e       = null;
            NewOpcode    nOpCode = (NewOpcode)(CurrentRaw >> 24);

            GM_Type[] types = ReadTypes(CurrentRaw);
            switch (nOpCode) // the bit switch
            {
            case NewOpcode.conv: e = CreateExpression(GMCode.Conv, types); break;

            case NewOpcode.popz: e = CreateExpression(GMCode.Popz, types); break;

            case NewOpcode.mul: e = CreateExpression(GMCode.Mul, types); break;

            case NewOpcode.div: e = CreateExpression(GMCode.Div, types); break;

            case NewOpcode.rem: e = CreateExpression(GMCode.Rem, types); break;

            case NewOpcode.mod: e = CreateExpression(GMCode.Mod, types); break;

            case NewOpcode.@add: e = CreateExpression(GMCode.Add, types); break;

            case NewOpcode.sub: e = CreateExpression(GMCode.Sub, types); break;

            case NewOpcode.and: e = CreateExpression(GMCode.And, types); break;

            case NewOpcode.or: e = CreateExpression(GMCode.Or, types); break;

            case NewOpcode.xor: e = CreateExpression(GMCode.Xor, types); break;

            case NewOpcode.neg: e = CreateExpression(GMCode.Neg, types); break;

            case NewOpcode.not: e = CreateExpression(GMCode.Not, types); break;

            case NewOpcode.shl: e = CreateExpression(GMCode.Sal, types); break;

            //  case NewOpcode.shr:     e = CreateExpression(GMCode.Saa, types); break; // hack, handle shift right
            case NewOpcode.@set:
                switch ((CurrentRaw >> 8) & 0xFF)
                {
                case 1: e = CreateExpression(GMCode.Slt, types); break;

                case 2: e = CreateExpression(GMCode.Sle, types); break;

                case 3: e = CreateExpression(GMCode.Seq, types); break;

                case 4: e = CreateExpression(GMCode.Sne, types); break;

                case 5: e = CreateExpression(GMCode.Sge, types); break;

                case 6: e = CreateExpression(GMCode.Sgt, types); break;

                default:
                    throw new Exception("Bad condition");
                }
                break;

            case NewOpcode.dup:
                e         = CreateExpression(GMCode.Dup, types);
                e.Operand = (int)(CurrentRaw & 0xFFFF);     // dup type
                break;

            case NewOpcode.call:
                e         = CreateExpression(GMCode.CallUnresolved, types);
                e.Operand = ILCall.CreateCall(File.Strings[r.ReadInt32()].String, (int)(CurrentRaw & 0xFFFF));
                // since we can have var args on alot of functions, extra is used
                break;

            case NewOpcode.ret: e = CreateExpression(GMCode.Ret, types); break;

            case NewOpcode.exit: e = CreateExpression(GMCode.Exit, types); break;

            case NewOpcode.b: e = CreateLabeledExpression(GMCode.B); break;

            case NewOpcode.bt: e = CreateLabeledExpression(GMCode.Bt); break;

            case NewOpcode.bf: e = CreateLabeledExpression(GMCode.Bf); break;

            // We have to fix these to a lopp to emulate a while latter
            case NewOpcode.pushenv:
            {
                //  Debug.WriteLine("Popenv: Address: {0}, Extra: {1} {1:X8}  Calc: {2}",i.Address, raw, GMCodeUtil.getBranchOffset(raw));
                int sextra = CurrentPC + GMCodeUtil.getBranchOffset(CurrentRaw);
                e = CreateExpression(GMCode.Pushenv, types, GetLabel(sextra + 1)); // we are one instruction after the pop
                pushEnviroment.Add(sextra, GetLabel(CurrentPC));                   // record the pop position
            }
            break;

            case NewOpcode.popenv:
            {
                // We convert this to a Branch so the loop detecter will find it
                e = CreateExpression(GMCode.B, types);
                // e = CreateExpression(GMCode.Popenv, types);
                if (CurrentRaw == 0xBBF00000)        // its a break, ugh
                {
                    foreach (var last in list.Reverse <ILNode>().OfType <ILExpression>())
                    {
                        if (last.Code == GMCode.Pushenv)
                        {
                            e.Operand = last.Operand;
                            return(e);
                        }
                    }
                    Debug.Assert(false);
                }
                else
                {
                    // some reason its the negitive offset?
                    // int offset = GMCodeUtil.getBranchOffset(CurrentRaw) - currentPC;
                    ILLabel endOfEnviroment;
                    if (pushEnviroment.TryGetValue(CurrentPC, out endOfEnviroment)) // this is the code
                    {
                        e.Operand = endOfEnviroment;                                // not a break, set the label BACK to the push as we are simulating a loop
                    }
                    else
                    {
                        throw new Exception("This MUST be a break");
                    }
                }
            }
            break;

            case NewOpcode.pop:
                e         = CreateExpression(GMCode.Pop, types);
                e.Operand = BuildUnresolvedVar(r.ReadInt32());
                break;

            case NewOpcode.pushi:
                Debug.Assert(types[0] == GM_Type.Short);
                e = CreatePushExpression(GMCode.Push, types);
                break;    // push int? ah like a pushe

            case NewOpcode.push:
                e = CreatePushExpression(GMCode.Push, types);
                break;            // generic push is fine right?

            case NewOpcode.pushl: // local
                e = CreatePushExpression(GMCode.Push, types);

                break;            // local? -7

            case NewOpcode.pushg: // Global
                e = CreatePushExpression(GMCode.Push, types);
                break;            // global? -5 // id is the last bit?

            case NewOpcode.pushb: // builtin .. seeing a patern hummmm
                                  // Built in vars?  always -1?
                e = CreatePushExpression(GMCode.Push, types);
                break;

            //      case NewOpcode.call2: e = CreateExpression(GMCode.Sal, types, operand); break;
            case NewOpcode.@break: e = CreateExpression(GMCode.Break, types); break;

            default:
                throw new Exception("Bad opcode");
            }
            return(e);
        }
Exemplo n.º 8
0
        // I had multipul passes on this so trying to combine it all to do one pass
        public static SortedList <int, Instruction> Dissasemble(BinaryReader r, long length, List <string> StringList, List <string> InstanceList = null)
        {
            if (r == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (r.BaseStream.CanRead != true)
            {
                throw new IOException("Cannot read stream");
            }
            int  pc     = 0;
            long lastpc = r.BaseStream.Length / 4;
            SortedList <int, Instruction>  list                  = new SortedList <int, Instruction>();
            Dictionary <int, Label>        labels                = new Dictionary <int, Label>();
            Dictionary <int, Label>        pushEnviroment        = new Dictionary <int, Label>();
            List <Instruction>             branches              = new List <Instruction>();
            Func <Instruction, int, Label> GiveInstructionALabel = (Instruction inst, int laddress) =>
            {
                Label label;
                if (!labels.TryGetValue(laddress, out label))
                {
                    labels.Add(laddress, label = new Label(laddress));
                }
                inst.Operand = label;
                branches.Add(inst);  // add it to the branches to handle latter
                return(label);
            };

            Instruction   prev = null;
            StringBuilder sb   = new StringBuilder(50);

            while (r.BaseStream.Position < length)
            {
                Instruction i = DissasembleFromReader(pc, r);
                pc += i.Size;
                switch (i.Code)
                {
                case GMCode.Pushenv:
                {
                    Label endOfEnviroment = GiveInstructionALabel(i, i.Extra + 1);       // skip the pop
                    i.Operand = endOfEnviroment;
                    pushEnviroment.Add(i.Address, endOfEnviroment);
                    branches.Add(i);
                }
                break;

                case GMCode.Popenv:
                {
                    Label endOfEnviroment;
                    if (pushEnviroment.TryGetValue(i.Extra - 1, out endOfEnviroment))
                    {
                        i.Operand = GiveInstructionALabel(i, i.Extra - 1);          // not a break, set the label BACK to the push as we are simulating a loop
                    }
                    else
                    {
                        foreach (Instruction ii in list.Values.Reverse())
                        {
                            if (ii.Code == GMCode.Pushenv)
                            {
                                i.Operand = GiveInstructionALabel(i, ii.Address);         // we want to make these continues
                                break;
                            }
                        }
                    }
                    branches.Add(i);
                    Debug.Assert(i.Operand != null);
                }
                break;

                case GMCode.Bf:
                case GMCode.Bt:
                case GMCode.B:
                    GiveInstructionALabel(i, i.Extra);
                    break;

                case GMCode.Push:
                    if (i.Types[0] == GM_Type.Var)
                    {
                        // i.Operand = StringList[(int)i.Operand]; Don't want to touch as it might
                        sb.Clear();
                        sb.Append(GMCodeUtil.lookupInstance(i.Extra, InstanceList));
                        sb.Append('.');
                        sb.Append(StringList[(int)i.Operand & 0xFFFFF]);
                        i.OperandText = sb.ToString();
                    }
                    else if (i.Types[0] == GM_Type.String)
                    {
                        i.Operand     = StringList[(int)i.Operand];
                        i.OperandText = GMCodeUtil.EscapeString(i.Operand as string);
                    }
                    break;

                case GMCode.Pop:     // technicaly pop is always a var, but eh
                                     //i.Operand = StringList[(int)i.Operand]; Don't do it this wa as we might need to find out of its an array
                    sb.Clear();
                    sb.Append(GMCodeUtil.lookupInstance(i.Extra, InstanceList));
                    sb.Append('.');
                    sb.Append(StringList[(int)i.Operand & 0xFFFFF]);
                    i.OperandText = sb.ToString();
                    break;

                case GMCode.Call:
                    i.OperandText = StringList[(int)i.Operand];
                    i.Operand     = i.OperandText;
                    break;
                }
                i.Previous = prev;
                if (prev == null)
                {
                    prev = i;
                }
                else
                {
                    prev.Next = i;
                }
                list.Add(i.Address, i);
            }
            if (list.Count == 0)
            {
                return(list);                 // return list, its empty
            }
            Instruction last = list.Last().Value;

            if (last.Code != GMCode.Exit || last.Code != GMCode.Ret)
            {
                int address = last.Address + last.Size;
                list.Add(address, new Instruction(address, GMCode.Exit));
            } // must be done for graph and in case we have a branch that goes right outside.  Its implied in any event
            foreach (var i in branches)
            {
                Label l = i.Operand as Label;
                if (l.Origin == null) // Link the label
                {
                    l.Origin = list[l.Address];
                    list[l.Address].Label = l;
                }
            }
            return(list);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Diassembles a raw opcode.
        /// </summary>
        /// <param name="i"></param>
        /// <param name="raw"></param>
        /// <returns>Returns truee if operand is needed</returns>
        public static bool DissasembleRawCode(Instruction i, uint raw)
        {
            i.Code        = GMCodeUtil.getFromRaw(raw);
            i.Types       = null;
            i.Operand     = null;
            i.OperandText = null;                  // we clear eveything just in case
            i._extra      = (short)(0xFFFF & raw); // default for almost eveything
            switch (i.Code)
            {
            case GMCode.Call:
                i.Types = new GM_Type[] { (GM_Type)((raw >> 16) & 15) };
                return(true);

            case GMCode.Exit:
            case GMCode.Ret:
            case GMCode.Not:
            case GMCode.Neg:
            case GMCode.Popz:
                i.Types = new GM_Type[] { (GM_Type)((raw >> 16) & 15) };
                break;

            case GMCode.Pop:
                i.Types = new GM_Type[] { (GM_Type)((raw >> 16) & 15), (GM_Type)((raw >> 20) & 15) };
                return(true);

            case GMCode.Push:
                i.Types = new GM_Type[] { (GM_Type)((raw >> 16) & 15) };
                // this should be in the operand, but just in case make sure extra is right
                if (i.Types[0] == GM_Type.Short)
                {
                    i.Operand = i._extra; // convert it to int
                    break;                // set the operand ourselfs don't need it
                }
                else
                {
                    return(true);     // need to read an operand
                }

            case GMCode.Add:
            case GMCode.Sub:
            case GMCode.Mul:
            case GMCode.Div:
            case GMCode.Mod:
            case GMCode.Or:
            case GMCode.And:
            case GMCode.Dup:
            case GMCode.Sal:
            case GMCode.Seq:
            case GMCode.Sge:
            case GMCode.Sgt:
            case GMCode.Sle:
            case GMCode.Sne:
            case GMCode.Conv:
            case GMCode.Rem:
            case GMCode.Slt:
            case GMCode.Xor:
                i.Types = new GM_Type[] { (GM_Type)((raw >> 16) & 15), (GM_Type)((raw >> 20) & 15) };
                break;

            case GMCode.Break:
                //  i._extra = (int)(0x00FFFFFFF & raw); // never seen the need for more than this
                break;

            case GMCode.B:
            case GMCode.Bf:
            case GMCode.Bt:
                i._extra = i.Address + GMCodeUtil.getBranchOffset(raw);
                break;

            case GMCode.Popenv:
                //  Debug.WriteLine("Popenv: Address: {0}, Extra: {1} {1:X8}  Calc: {2}",i.Address, raw, GMCodeUtil.getBranchOffset(raw));
                if (0xBCF00000 == raw)     // its a popbreak
                {
                    i._extra = 0;
                }
                else
                {
                    i._extra = i.Address + GMCodeUtil.getBranchOffset(raw);
                }
                break;

            case GMCode.Pushenv:
                //    Debug.WriteLine("Pushenv: Address: {0}, Extra: {1} {1:X8}  Calc: {2}",i.Address, raw, GMCodeUtil.getBranchOffset(raw));
                i._extra = i.Address + GMCodeUtil.getBranchOffset(raw);
                break;

            case GMCode.BadOp:
                throw new Exception("Bad opcode?");

            default:
                throw new Exception("Unkonwn opcode");
            }
            return(false);
        }