A line of bytecode, disassembled from the source bytes.
Beispiel #1
0
        /// <summary>
        /// Convenience method for creating an opcode from a position in a byte array.
        /// Returns an opcode object with references resolved and advances the position
        /// to the next place in the byte array.
        /// </summary>
        /// <param name="reader">Where to read the next opcode from</param>
        /// <param name="abc">The code within which we're reading</param>
        /// <returns>A new Opcode object, or null if there was no more data to be read</returns>
        public static Opcode BuildOpcode(ABCDataTypeReader reader, AbcCode abc)
        {
            Opcode op = new Opcode(abc);

            int code;
            code = reader.ReadUI8();
            if (code == -1)
            {
                return null;
            }
            op.Instruction = (uint)code;

            if (OpcodeTable[code] == null)
            {
                throw new SWFModellerException(
                        SWFModellerError.Internal,
                        "Bad opcode 0x" + code.ToString("X") + " at @" + (reader.Offset - 1));
            }
            OpcodeDef info = (OpcodeDef)OpcodeTable[code];

            List<object> args = new List<object>();

            if (info.Mnemonic == Mnemonics.LookupSwitch)
            {
                /* Special case: Has a variable arg */
                args.Add(reader.ReadSI24()); /* default offset */
                uint caseCount = reader.ReadU30();
                args.Add(caseCount);

                for (int i = 0; i < caseCount + 1; i++)
                {
                    args.Add(reader.ReadSI24());
                }
            }
            else
            {
                if (info.Args != null)
                {
                    foreach (ArgType type in info.Args)
                    {
                        switch (type)
                        {
                            case ArgType.MultinameU30:
                                args.Add(abc.GetMultiname((int)reader.ReadU30()));
                                break;

                            case ArgType.OffsetS24:
                                args.Add(reader.ReadSI24());
                                break;

                            case ArgType.StringU30:
                                args.Add(abc.StringConsts[reader.ReadU30()]);
                                break;

                            case ArgType.RegisterU30:
                            case ArgType.ObjectRegisterU30:
                            case ArgType.PropertyRegisterU30:
                                args.Add(reader.ReadU30());
                                break;

                            case ArgType.ByteU8:
                                args.Add((byte)reader.ReadUI8());
                                break;

                            case ArgType.ShortU30:
                            case ArgType.IntU30:
                            case ArgType.UintU30:
                            case ArgType.DoubleU30:
                                args.Add(reader.ReadU30());
                                break;

                            case ArgType.ShortS30:
                                args.Add((int)reader.ReadU30());
                                break;

                            case ArgType.ByteS8:
                                args.Add(reader.ReadSI8());
                                break;

                            case ArgType.NamespaceU30:
                                args.Add(abc.GetNamespace((int)reader.ReadU30()));
                                break;

                            case ArgType.MethodU30:
                                args.Add(abc.GetMethod((int)reader.ReadU30()));
                                break;

                            case ArgType.CountU30:
                                args.Add(reader.ReadU30());
                                break;

                            case ArgType.ClassU30:
                                args.Add(abc.GetClass((int)reader.ReadU30()));
                                break;

                            case ArgType.ExceptionU30:
                                args.Add(reader.ReadU30());
                                break;

                            case ArgType.StackU8:
                                args.Add((byte)reader.ReadUI8());
                                break;

                            case ArgType.SlotU30:
                                args.Add(reader.ReadU30());
                                break;

                            case ArgType.DebugU8:
                                args.Add((byte)reader.ReadUI8());
                                break;

                            case ArgType.DebugTypeU30:
                                args.Add(reader.ReadU30());
                                break;

                            case ArgType.StringU8:
                                args.Add(abc.StringConsts[reader.ReadUI8()]);
                                break;

                            case ArgType.LineNumberU30:
                                args.Add(reader.ReadU30());
                                break;

                            default:
                                /* ISSUE 73 */
                                throw new SWFModellerException(
                                        SWFModellerError.UnimplementedFeature,
                                        "Oops. Not done " + type.ToString());
                        }
                    }
                }
            }

            op.Args = args.ToArray();

            return op;
        }
Beispiel #2
0
 /// <summary>
 /// Convenience method for debug file opcodes, which can be inserted sneakily at the
 /// last moment when serialising the bytecode, and so need to be created in this lightweight
 /// way.
 /// </summary>
 public static Opcode CreateDebugFile(string fileName)
 {
     Opcode op = new Opcode(null);
     op.Instruction = (uint)Mnemonics.DebugFile;
     op.Args = new object[] { fileName };
     return op;
 }
Beispiel #3
0
 /// <summary>
 /// Convenience method for debug line opcodes, which can be inserted sneakily at the
 /// last moment when serialising the bytecode, and so need to be created in this lightweight
 /// way.
 /// </summary>
 public static Opcode CreateDebugLine(uint line)
 {
     Opcode op = new Opcode(null);
     op.Instruction = (uint)Mnemonics.DebugLine;
     op.Args = new object[] { line };
     return op;
 }
Beispiel #4
0
        /// <summary>
        /// Technically, from an OO perspective, this isn't the most logical place
        /// for this method. It's a factory method for opcodes used when building up
        /// new methods, bytecode by bytecode. It's here because this is the place
        /// that makes calling it require the least typing, which is good when you're
        /// creating lists of loads of these things.
        /// </summary>
        /// <param name="mnemonic">The opcode mnemonic</param>
        /// <param name="args">The argument list. If the types of the args don't
        /// match the type requirements of the opcode, an exception will be
        /// thrown.</param>
        /// <returns>An opcode</returns>
        internal Opcode Op(Opcode.Mnemonics mnemonic, params object[] args)
        {
            Opcode op = new Opcode(this) { Mnemonic = mnemonic, Args = args.Length == 0 ? null : args };

            if (mnemonic != Opcode.Mnemonics.LookupSwitch)
            {
                if (!Opcode.VerifyArgTypes(mnemonic, args))
                {
                    throw new SWFModellerException(
                            SWFModellerError.Internal,
                            "Invalid arg values or types in opcode " + mnemonic.ToString());
                }
            }

            /* ISSUE 7: There must be some way to verify lookupswitch to some degree.
             * Update: There is. The case count must be correct and the offsets must be references
             * to preceeding Label opcodes. */

            return op;
        }