/// <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; }
/// <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 }; }
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(); }
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(); } }
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); }
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); } }
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); } }
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); } }
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); } } }
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); }
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(); } }
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); }
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()); }
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); }
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); }
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); }
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); }
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(); }
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(); }
/// <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); } }
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); }
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()); }
private void Test_Output(AbcCode code, string format, params object[] args) { Test_Output(code, () => code.PushString(string.Format(format, args))); }
private void Test_Output(AbcCode code, Action value) { code.SetField(1, TestType, "Output", value); }
private void Test_StackTrace(AbcCode code, Action value) { code.SetField(1, TestType, "StackTrace", value); }
private void Test_Success(AbcCode code, bool value) { Test_SetBool(code, "Success", value); }
private void Test_Executed(AbcCode code, bool value) { Test_SetBool(code, "Executed", value); }
public static void Equals(AbcCode code) { code.Add(InstructionCode.Equals); code.FixBool(); }
private void Test_SetBool(AbcCode code, string prop, bool value) { code.SetPropertyBool(1, TestType, prop, value); }
public static void ReturnValue(AbcCode code) { code.ReturnValue(); }
public static void op_Inequality(AbcCode code) { code.Add(InstructionCode.Equals); code.Add(InstructionCode.Not); code.FixBool(); }
public static void op_Implicit(AbcCode code) { // do nothing since System.String is implemented via native avm string }
public Opcode(AbcCode abc) { this.abc = abc; }
/// <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; }