예제 #1
0
        /// <summary>
        /// Turns bytecode into an AbcCode object.
        /// </summary>
        /// <param name="bytecode">The bytecode, as chopped out of a SWF.</param>
        /// <param name="readLog">Ignored in release builds. This logs
        /// on every constant value read for unit test inspection.</param>
        /// <returns>A string rendition of the bytecode.</returns>
        public AbcCode Read(byte[] bytecode, StringBuilder readLog)
        {
            #if DEBUG
            this.ReadLog = readLog;
            if (this.ReadLog != null)
            {
                this.ReadLog.AppendLine("\nNew ABC file\n-----------\n");
            }
            #endif

            this.code = new AbcCode();
            this.abcdtr = new ABCDataTypeReader(new MemoryStream(bytecode));

            this.LateResolutions = new Dictionary<object, int>();

            int minor = this.abcdtr.ReadUI16();
            int major = this.abcdtr.ReadUI16();
            if (minor != AbcFileValues.MinorVersion || major != AbcFileValues.MajorVersion)
            {
                throw new SWFModellerException(
                        SWFModellerError.ABCParsing,
                        "Unsupported version, or not an ABC file.");
            }

            this.ReadConstantPool();
            this.ReadMethods();
            this.ReadMetadata();
            this.ReadClasses();
            this.ReadScriptDefs();
            this.ReadMethodBodies();

            this.ResolveReferences();

            return this.code;
        }
예제 #2
0
        /// <summary>
        /// Creates the MovieClip class. Or something that looks like it from the outside.
        /// </summary>
        /// <param name="abc">Where to put the namespace</param>
        /// <returns>The MovieClip class.</returns>
        public static AdobeClass CreateFlashDisplayMovieClip(AbcCode abc)
        {
            Namespace nsFlashDisplay = abc.CreateNamespace(Namespace.NamespaceKind.Package, "flash.display");
            Multiname mnMovieClip = abc.CreateMultiname(Multiname.MultinameKind.QName, "MovieClip", nsFlashDisplay, null);

            return new AdobeClass()
            {
                Name = mnMovieClip
            };
        }
예제 #3
0
        public static void SetProperty(AbcCode code)
        {
            // stack: name, value
            var vh    = code.Generator.RuntimeImpl.ValueHolder;
            var value = vh.GetStaticSlot("value");

            code.Getlex(vh);         //after: name, value, vh
            code.Swap();             //after: name, vh, value
            code.SetSlot(value);

            code.PushGlobalPackage(); //after: name, ns
            code.Swap();              //ns, name

            code.Getlex(vh);
            code.GetSlot(value);

            code.SetRuntimeProperty();
        }
예제 #4
0
        public void UndelayCalls(AbcCode code, IList <AbcInstance> list, int arr)
        {
            int n = list.Count;

            for (int i = 0; i < n; ++i)
            {
                var instance = list[i];

                code.GetLocal(arr);
                code.PushInt(i);
                code.GetNativeArrayItem();
                var br = code.IfFalse();

                SetCalledFlag(code, instance, false);

                br.BranchTarget = code.Label();
            }
        }
예제 #5
0
        private static void SetAccessor(AbcCode code, IMethod accessor, FieldId fieldId, int varProp)
        {
            if (accessor == null)
            {
                return;
            }
            var abcMethod = accessor.AbcMethod();

            if (abcMethod == null)
            {
                return;
            }
            int index = abcMethod.MethodInfoIndex;

            code.GetLocal(varProp);
            code.PushInt(index);
            code.SetField(fieldId);
        }
예제 #6
0
        private void RegisterEffectTriggers(AbcFile app, AbcCode code)
        {
            if (_effects.Count == 0)
            {
                return;
            }

            var effectManager = _compiler.ImportType(app, "mx.effects.EffectManager");
            var mn            = app.DefineName(QName.MxInternal("registerEffectTrigger"));

            foreach (var pair in _effects)
            {
                code.Getlex(effectManager);
                code.PushString(pair.Key);
                code.PushString(pair.Value);
                code.CallVoid(mn, 2);
            }
        }
예제 #7
0
        public void OnLoadAbc(bool lazyInit, SWFContext ctx, string abcName, int doAbcCount, byte[] bytecode)
        {
            string abcDir = this.TestDir + @"\abc\";

            Directory.CreateDirectory(abcDir);

            string name = ctx.Name + "." + abcName + doAbcCount + abcName + ".abc";

            using (FileStream fs = new FileStream(abcDir + name, FileMode.Create))
            {
                fs.Write(bytecode, 0, bytecode.Length);
            }

            StringBuilder readLog = new StringBuilder();
            AbcCode       code    = null;

            try
            {
                code = new AbcReader().Read(bytecode, readLog);
            }
            catch (Exception e)
            {
                readLog.Append(e.Message);
                throw;
            }
            finally
            {
                using (FileStream fs = new FileStream(abcDir + name + ".readlog.txt", FileMode.Create))
                {
                    byte[] readLogBytes = new ASCIIEncoding().GetBytes(readLog.ToString());
                    fs.Write(readLogBytes, 0, readLogBytes.Length);
                }
            }

            StringBuilder abcd = new StringBuilder();

            code.ToStringModelView(0, abcd);
            byte[] dasmBytes = new ASCIIEncoding().GetBytes(abcd.ToString());

            using (FileStream fs = new FileStream(abcDir + name + ".txt", FileMode.Create))
            {
                fs.Write(dasmBytes, 0, dasmBytes.Length);
            }
        }
예제 #8
0
        private void InitFields(AbcCode code, AbcInstance instance, IType type)
        {
            if (!MustInitFields)
            {
                return;
            }
            if (type.IsInterface)
            {
                return;
            }
            var init = DefineMyFieldsInitializer(instance, type);

            if (init != null)
            {
                code.GetLocal(varType);
                code.GetStaticFunction(init);
                code.SetProperty(Const.Type.MyFieldsInit);
            }
        }
예제 #9
0
        private void InitTypeFuncs(AbcCode code, IType type, AbcInstance instance)
        {
            var f = _generator.Boxing.Box(type);

            if (f != null)
            {
                code.GetLocal(varType);
                code.GetStaticFunction(f);
                code.SetProperty(Const.Type.BoxFunction);
            }

            f = _generator.Boxing.Unbox(type, false);
            if (f != null)
            {
                code.GetLocal(varType);
                code.GetStaticFunction(f);
                code.SetProperty(Const.Type.UnboxFunction);
            }

            f = CopyImpl.StaticCopy(instance);
            if (f != null)
            {
                code.GetLocal(varType);
                code.GetStaticFunction(f);
                code.SetProperty(Const.Type.CopyFunction);
            }

            var ctor = type.FindParameterlessConstructor();

            if (ctor != null)
            {
                f = _generator.MethodBuilder.Build(ctor) as AbcMethod;
                if (f != null && !f.IsInitializer)
                {
                    f = _generator.TypeBuilder.DefineCtorStaticCall(ctor);
                    Debug.Assert(f != null);
                    code.GetLocal(varType);
                    code.GetStaticFunction(f);
                    code.SetProperty(Const.Type.CreateFunction);
                }
            }
        }
예제 #10
0
        public IEnumerable <IInstruction> Return(bool isvoid)
        {
            var code = new AbcCode(_abc);

            if (isvoid)
            {
                if (!IsCtorAsStaticCall)
                {
                    code.ReturnVoid();
                }
            }
            else
            {
                if (!DonotCopyReturnValue)
                {
                    code.CopyValue(_method.Type);
                }
                code.ReturnValue();
            }
            return(code);
        }
예제 #11
0
        public static void GetItem2(IMethod method, AbcCode code)
        {
            var p0 = method.Parameters[0].Type;

            if (p0.Name == "Namespace")
            {
                code.GetRuntimeProperty();
                code.CoerceXMLList();
            }
            else                               //namespace as Avm.String
            {
                code.Swap();                   //stack [name, nsname]
                var ns = code[AvmTypeCode.Namespace];
                code.FindPropertyStrict(ns);   //stack [name, nsname, global]
                code.Swap();                   //stack [name, global, nsname]
                code.ConstructProperty(ns, 1); //stack [name, ns]
                code.Coerce(ns);               //stack [name, ns]
                code.Swap();                   //stack [ns, name]
                code.GetRuntimeProperty();
                code.CoerceXMLList();
            }
        }
예제 #12
0
        public IEnumerable <IInstruction> EndCatch(ISehHandlerBlock handlerBlock, bool isLast, bool generateExit, out IInstruction jump)
        {
            var ci = handlerBlock.GetCatchInfo();

            jump = null;
            var code = new AbcCode(_abc);

            if (PopCatchScope)
            {
                code.PopScope(); //pops catch scope
            }
            //we now no need in exception variable
            KillExceptionVariable(code, ci);

            //NOTE: no need to generate exit jump for last catch block
            if (generateExit && !isLast)
            {
                jump = code.Goto();
            }

            return(code);
        }
예제 #13
0
        private byte[] GenerateMetadata(AbcCode code)
        {
            MemoryStream      buf    = new MemoryStream();
            ABCDataTypeWriter writer = new ABCDataTypeWriter(buf);

            writer.WriteU30Packed((uint)code.MetadataCount);

            foreach (string key in code.MetadataKeys)
            {
                writer.WriteU30Packed((uint)this.stringMarshal.GetIDFor(key));
                Dictionary <string, string> itemInfo = code.GetMetadata(key);
                writer.WriteU30Packed((uint)itemInfo.Count);
                foreach (string itemKey in itemInfo.Keys)
                {
                    writer.WriteU30Packed((uint)this.stringMarshal.GetIDFor(itemKey));
                    writer.WriteU30Packed((uint)this.stringMarshal.GetIDFor(itemInfo[itemKey]));
                }
            }

            writer.Close(); /* Closes the buffer */
            return(buf.ToArray());
        }
예제 #14
0
        public IEnumerable <IInstruction> BeginCatch(ISehHandlerBlock handlerBlock)
        {
            var tryBlock = handlerBlock.Owner;

            var exceptionType = handlerBlock.ExceptionType;

            if (exceptionType != null)
            {
                EnsureType(exceptionType);
            }

            var seh = new AbcExceptionHandler();

            _body.Exceptions.Add(seh);
            _resolver.Add(tryBlock, new ExceptionFrom(seh), new ExceptionTo(seh));

            bool catchAnyException = MustCatchAnyException(handlerBlock);

            seh.Type = catchAnyException ? _abc.BuiltinTypes.Object : handlerBlock.ExceptionType.GetMultiname();

            int var = handlerBlock.ExceptionVariable;

            if (var >= 0)
            {
                var = GetVarIndex(var);
            }

            var code = new AbcCode(_abc);

            BeginCatch(handlerBlock, code, seh, ref var, !_popException, catchAnyException);

            if (catchAnyException)
            {
                RouteException(code, handlerBlock, var);
                _sehsToResolve.Add(tryBlock);
            }

            return(code);
        }
예제 #15
0
        public IEnumerable <IInstruction> StoreField(IField field)
        {
            var code = new AbcCode(_abc);

            if (field.HasEmbedAttribute())
            {
                _generator.CheckEmbedAsset(field);
                code.Pop();
            }
            else
            {
                var prop = GetFieldName(field);
                CallStaticCtor(code, field);
                if (field.IsStatic)
                {
                    LoadStaticInstance(code, field.DeclaringType);
                    code.Swap();
                }
                code.SetProperty(prop);
            }
            return(code);
        }
예제 #16
0
 private void NewAttribute(AbcCode code, ICustomAttribute attr, int varAttr)
 {
     code.NewObject(attr.Constructor,
                    () =>
     {
         foreach (var arg in attr.FixedArguments())
         {
             code.PushValue(code, arg.Value);
         }
     });
     code.SetLocal(varAttr);
     //TODO: Set fields and properties
     foreach (var arg in attr.NamedArguments())
     {
         code.GetLocal(varAttr);
         code.PushValue(code, arg.Value);
         if (arg.Kind == ArgumentKind.Field)
         {
             var field = arg.Member as IField;
             if (field == null)
             {
                 throw new InvalidOperationException();
             }
             code.SetField(field);
         }
         else
         {
             var prop = arg.Member as IProperty;
             if (prop == null)
             {
                 throw new InvalidOperationException();
             }
             var s = _generator.MethodBuilder.BuildAbcMethod(prop.Setter);
             code.Call(s);
         }
     }
     code.GetLocal(varAttr);
 }
예제 #17
0
        private void CallStaticCtor(AbcCode code, ITypeMember member)
        {
            if (!_method.IsStatic)
            {
                return;
            }
            if (!_method.IsConstructor)
            {
                return;
            }
            if (!NeedCallStaticCtor(member))
            {
                return;
            }

            var declType = member.DeclaringType;

            if (ReferenceEquals(declType, _declType))
            {
                return;
            }
            _generator.StaticCtors.Call(code, declType);
        }
예제 #18
0
        private void LoadGlobalReceiver(AbcCode code, IMethod method)
        {
            var type = method.DeclaringType;

            if (type.Data is GlobalFunctionsContainer)
            {
                var mn = GetMethodName(method);
                code.FindPropertyStrict(mn);
                return;
            }

            if (type.IsInternalType())
            {
                string name = method.Name;
                var    mn   = _abc.DefineName(QName.Global(name));
                code.FindPropertyStrict(mn);
                return;
            }

            if (type.Is(SystemTypeCode.String))
            {
                code.Getlex(AvmTypeCode.String);
                return;
            }

            if (type.Is(AvmTypeCode.Class))
            {
                if (method.Name == "Find")
                {
                    var m = _generator.RuntimeImpl.FindClass();
                    code.Getlex(m);
                    return;
                }
            }

            throw new InvalidOperationException();
        }
예제 #19
0
        private bool LinkEvent(IMethod method, AbcInstance instance)
        {
            var e = method.Association as IEvent;

            if (e == null)
            {
                return(false);
            }

            var attr = e.FindAttribute(Attrs.Event);

            if (attr == null)
            {
                return(false);
            }

            string eventName = attr.Arguments[0].Value as string;

            if (string.IsNullOrEmpty(eventName))
            {
                throw new InvalidOperationException();
            }

            if (e.Adder == method || e.Remover == method)
            {
                //stack transition: dispatcher, delegate -> ...
                var code = new AbcCode(instance.Abc);
                code.Swap();
                code.PushString(eventName);
                code.CallVoid(GetDelegateMethodName(e.Adder == method), 2);
                method.Data = new InlineCall(method, null, null, code);
                return(true);
            }

            throw new NotImplementedException();
        }
예제 #20
0
        /// <summary>
        /// Runs a delegate function on every class in the SWF.
        /// </summary>
        /// <param name="cp">The delegate to call for each class.</param>
        private void ClassProc(ClassProcessor cp)
        {
            bool mainClassProcessed = false;

            foreach (DoABC script in this.scripts)
            {
                AbcCode code = script.Code;

                foreach (AS3ClassDef c in code.Classes)
                {
                    if (c == this.Class)
                    {
                        mainClassProcessed = true;
                    }

                    cp(c);
                }
            }

            if (!mainClassProcessed)
            {
                cp((AS3ClassDef)this.Class);
            }
        }
예제 #21
0
        private IEnumerable <IInstruction> EndFinally(ISehHandlerBlock block, bool fault)
        {
            var handlerInfo = block.GetHandlerInfo();
            var ci          = handlerInfo.CatchInfo;
            var fi          = handlerInfo.FinallyInfo;

            if (fi.IsFault != fault)
            {
                throw new InvalidOperationException("Finally block type mistmatch!");
            }

            var code = new AbcCode(_abc);

            if (fault)
            {
                code.GetLocal(ci.ExceptionVar);
                KillExceptionVariable(code, ci);
                code.Throw();
            }
            else
            {
                // check if we should rethrow exception
                code.GetLocal(fi.RethrowFlagVariable);
                // trying to fix IVDiffGramTest
                // KillTempVar(code, fi.RethrowFlagVariable);
                var br = code.IfFalse();

                code.GetLocal(ci.ExceptionVar);
                KillExceptionVariable(code, ci);
                var end = code.Throw();

                br.GotoNext(end);
            }

            return(code);
        }
예제 #22
0
        private byte[] GenerateScriptInfo(AbcCode code)
        {
            MemoryStream      buf    = new MemoryStream();
            ABCDataTypeWriter writer = new ABCDataTypeWriter(buf);

            writer.WriteU30Packed((uint)code.ScriptCount);

            foreach (Script s in code.Scripts)
            {
                writer.WriteU30Packed((uint)this.methodMarshal.GetIDFor(s.Method));

                writer.WriteU30Packed((uint)s.TraitCount);
                using (IEnumerator <Trait> i = s.Traits)
                {
                    while (i.MoveNext())
                    {
                        this.WriteTraitInfo(writer, i.Current);
                    }
                }
            }

            writer.Close(); /* Closes the buffer */
            return(buf.ToArray());
        }
예제 #23
0
 private void Test_Output(AbcCode code, string format, params object[] args)
 {
     Test_Output(code, () => code.PushString(string.Format(format, args)));
 }
예제 #24
0
 private void Test_Output(AbcCode code, Action value)
 {
     code.SetField(1, TestType, "Output", value);
 }
예제 #25
0
 private void Test_StackTrace(AbcCode code, Action value)
 {
     code.SetField(1, TestType, "StackTrace", value);
 }
예제 #26
0
 private void Test_Success(AbcCode code, bool value)
 {
     Test_SetBool(code, "Success", value);
 }
예제 #27
0
 private void Test_Executed(AbcCode code, bool value)
 {
     Test_SetBool(code, "Executed", value);
 }
예제 #28
0
 public static void Equals(AbcCode code)
 {
     code.Add(InstructionCode.Equals);
     code.FixBool();
 }
예제 #29
0
 private void Test_SetBool(AbcCode code, string prop, bool value)
 {
     code.SetPropertyBool(1, TestType, prop, value);
 }
예제 #30
0
 public static void ReturnValue(AbcCode code)
 {
     code.ReturnValue();
 }
예제 #31
0
 public static void op_Inequality(AbcCode code)
 {
     code.Add(InstructionCode.Equals);
     code.Add(InstructionCode.Not);
     code.FixBool();
 }
예제 #32
0
 public static void op_Implicit(AbcCode code)
 {
     // do nothing since System.String is implemented via native avm string
 }
예제 #33
0
 public Opcode(AbcCode abc)
 {
     this.abc = abc;
 }
예제 #34
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;
        }