public void Analyse() { var toAnalyse = new List <ILGroup>(StructuredCode); while (toAnalyse.Count != 0) { var analysing = toAnalyse.First(g => g.StartStack != null); toAnalyse.Remove(analysing); var stack = new Stack <Type>(analysing.StartStack.Reverse()); uint stackOffset = 0; foreach (var item in stack) { stackOffset += ILOp.Align(ILOp.SizeOfType(item), 4); } foreach (var opcode in analysing.OpCodes) { if (opcode.CurrentExceptionRegion != null && opcode.CurrentExceptionRegion.TryOffset == opcode.Position) { analysing.PossibleContinuations.First(c => c.StartPosition == opcode.CurrentExceptionRegion.HandlerOffset).StartStack = new Stack <Type>(analysing.StartStack.Reverse()); } opcode.DoStackAnalysis(stack, ref stackOffset); } foreach (var c in analysing.PossibleContinuations) { c.StartStack = new Stack <Type>(stack.Reverse()); } } }
public override void AssembleNew(Cosmos.Assembler.Assembler aAssembler, object aMethodInfo) { // method signature: $this, object @object, IntPtr method var xAssembler = aAssembler; var xMethodInfo = (_MethodInfo)aMethodInfo; XS.Comment("Save target ($this) to field"); XS.Comment("-- ldarg 0"); Ldarg.DoExecute(xAssembler, xMethodInfo, 0); XS.Comment("-- ldarg 1"); Ldarg.DoExecute(xAssembler, xMethodInfo, 1); XS.Comment("-- stfld _target"); Stfld.DoExecute(xAssembler, xMethodInfo, "System.Object System.Delegate._target", xMethodInfo.MethodBase.DeclaringType, true, false); XS.Comment("Save method pointer to field"); XS.Comment("-- ldarg 0"); Ldarg.DoExecute(xAssembler, xMethodInfo, 0); XS.Comment("-- ldarg 2"); Ldarg.DoExecute(xAssembler, xMethodInfo, 2); XS.Comment("-- stfld _methodPtr"); Stfld.DoExecute(xAssembler, xMethodInfo, "System.IntPtr System.Delegate._methodPtr", xMethodInfo.MethodBase.DeclaringType, true, false); XS.Comment("Saving ArgSize to field"); uint xSize = 0; foreach (var xArg in xMethodInfo.MethodBase.DeclaringType.GetMethod("Invoke").GetParameters()) { xSize += ILOp.Align(ILOp.SizeOfType(xArg.ParameterType), 4); } XS.Comment("-- ldarg 0"); Ldarg.DoExecute(xAssembler, xMethodInfo, 0); XS.Comment("-- push argsize"); XS.Push(xSize); XS.Comment("-- stfld ArgSize"); Stfld.DoExecute(xAssembler, xMethodInfo, "$$ArgSize$$", xMethodInfo.MethodBase.DeclaringType, true, false); }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { // todo: implement exception support. var xSize = SizeOfType(aOpCode.StackPopTypes[0]); new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = ILOp.Align((uint)xSize, 4) }; }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { var xStackContent = aOpCode.StackPopTypes[0]; var xStackContentSize = SizeOfType(xStackContent); var xStackContent2 = aOpCode.StackPopTypes[1]; var xStackContent2Size = SizeOfType(xStackContent2); var xSize = Math.Max(xStackContentSize, xStackContent2Size); if (ILOp.Align(xStackContentSize, 4u) != ILOp.Align(xStackContent2Size, 4u)) { throw new NotSupportedException("Cosmos.IL2CPU.x86->IL->And.cs->Error: Operands have different size!"); } if (xSize > 8) { throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->And.cs->Error: StackSize > 8 not supported"); } if (xSize > 4) { // [ESP] is low part // [ESP + 4] is high part // [ESP + 8] is low part // [ESP + 12] is high part new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; new CPUx86.Pop { DestinationReg = CPUx86.Registers.EDX }; // [ESP] is low part // [ESP + 4] is high part new CPUx86.And { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX }; new CPUx86.And { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceReg = CPUx86.Registers.EDX }; } else { new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; new CPUx86.And { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX }; } }
public override void AssembleNew(Cosmos.Assembler.Assembler aAssembler, object aMethodInfo) { // method signature: $this, object @object, IntPtr method var xMethodInfo = (MethodInfo)aMethodInfo; var xAssembler = (NewAssembler)aAssembler; new Comment("Save target ($this) to field"); new Comment("-- ldarg 0"); Ldarg.DoExecute(xAssembler, xMethodInfo, 0); //Ldarg.DoExecute(xAssembler, xMethodInfo, 0); new Comment("-- ldarg 1"); Ldarg.DoExecute(xAssembler, xMethodInfo, 1); new Comment("-- stfld _target"); Stfld.DoExecute(xAssembler, xMethodInfo, "System.Object System.Delegate._target", xMethodInfo.MethodBase.DeclaringType, true, false); new Comment("Save method pointer to field"); //Ldarg.DoExecute(xAssembler, xMethodInfo, 0); new Comment("-- ldarg 0"); Ldarg.DoExecute(xAssembler, xMethodInfo, 0); new Comment("-- ldarg 2"); Ldarg.DoExecute(xAssembler, xMethodInfo, 2); new Comment("-- stfld _methodPtr"); Stfld.DoExecute(xAssembler, xMethodInfo, "System.IntPtr System.Delegate._methodPtr", xMethodInfo.MethodBase.DeclaringType, true, false); new Comment("Saving ArgSize to field"); uint xSize = 0; foreach (var xArg in xMethodInfo.MethodBase.DeclaringType.GetMethod("Invoke").GetParameters()) { xSize += ILOp.Align(ILOp.SizeOfType(xArg.ParameterType), 4); } new Comment("-- ldarg 0"); Ldarg.DoExecute(xAssembler, xMethodInfo, 0); if (xMethodInfo.MethodBase.DeclaringType.FullName.Contains("InterruptDelegate")) { Console.Write(""); } new Comment("-- push argsize"); new CPUx86.Push { DestinationValue = xSize }; new Comment("-- stfld ArgSize"); Stfld.DoExecute(xAssembler, xMethodInfo, "$$ArgSize$$", xMethodInfo.MethodBase.DeclaringType, true, false); //public static void Ctor(Delegate aThis, object aObject, IntPtr aMethod, //[FieldAccess(Name = "System.Object System.Delegate._target")] ref object aFldTarget, //[FieldAccess(Name = "System.IntPtr System.Delegate._methodPtr")] ref IntPtr aFldMethod) { }
public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xStackContent = aOpCode.StackPopTypes[0]; var xStackContentSecond = aOpCode.StackPopTypes[1]; var xStackContentSize = SizeOfType(xStackContent); var xStackContentSecondSize = SizeOfType(xStackContentSecond); var xSize = Math.Max(xStackContentSize, xStackContentSecondSize); if (ILOp.Align(xStackContentSize, 4u) != ILOp.Align(xStackContentSecondSize, 4u)) { throw new NotSupportedException("Operands have different size!"); } if (xSize > 8) { throw new NotImplementedException("StackSize>8 not supported"); } if (xSize > 4) { // [ESP] is low part // [ESP + 4] is high part // [ESP + 8] is low part // [ESP + 12] is high part XS.Pop(XSRegisters.EAX); XS.Pop(XSRegisters.EDX); // [ESP] is low part // [ESP + 4] is high part XS.Or(XSRegisters.ESP, XSRegisters.EAX, destinationIsIndirect: true); XS.Or(XSRegisters.ESP, XSRegisters.EDX, destinationDisplacement: 4); } else { XS.Pop(XSRegisters.EAX); XS.Or(XSRegisters.ESP, XSRegisters.EAX, destinationIsIndirect: true); } }
public static void DoExecute(Cosmos.Assembler.Assembler Assembler, Type aDeclaringType, string xFieldId, bool aDerefExternalField, bool debugEnabled) { var xOffset = GetFieldOffset(aDeclaringType, xFieldId); var xFields = GetFieldsInfo(aDeclaringType); var xFieldInfo = (from item in xFields where item.Id == xFieldId select item).Single(); new Comment("Field = '" + xFieldId + "'"); DoNullReferenceCheck(Assembler, debugEnabled, 0); new CPUx86.Pop { DestinationReg = CPUx86.Registers.ECX }; #if DOTNETCOMPATIBLE // pushed size is always 4 or 8 var xSize = ILOp.Align(xFieldInfo.Size, 4); #else var xSize = xFieldInfo.Size; #endif new CPUx86.Add { DestinationReg = CPUx86.Registers.ECX, SourceValue = (uint)(xOffset) }; if (xFieldInfo.IsExternalValue && aDerefExternalField) { new CPUx86.Mov { DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.ECX, SourceIsIndirect = true }; } for (int i = 1; i <= (xSize / 4); i++) { new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ECX, SourceIsIndirect = true, SourceDisplacement = (int)(xSize - (i * 4)) }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; } switch (xSize % 4) { case 1: { new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceValue = 0 }; new CPUx86.Mov { DestinationReg = CPUx86.Registers.AL, SourceReg = CPUx86.Registers.ECX, SourceIsIndirect = true }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; break; } case 2: { new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceValue = 0 }; new CPUx86.Mov { DestinationReg = CPUx86.Registers.AX, SourceReg = CPUx86.Registers.ECX, SourceIsIndirect = true }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; break; } case 3: //For Release { new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceValue = 0 }; new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ECX, SourceIsIndirect = true }; new CPUx86.ShiftRight { DestinationReg = CPUx86.Registers.EAX, SourceValue = 8 }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; break; } case 0: { break; } default: throw new Exception(string.Format("Remainder size {0:D} {1:D} not supported!", xFieldInfo.FieldType.ToString(), xSize)); } }
public static void DoExecute(Cosmos.Assembler.Assembler Assembler, Type aDeclaringType, string xFieldId, bool aDerefExternalField, bool debugEnabled, Type aTypeOnStack) { var xOffset = GetFieldOffset(aDeclaringType, xFieldId); var xFields = GetFieldsInfo(aDeclaringType, false); var xFieldInfo = (from item in xFields where item.Id == xFieldId select item).Single(); new Comment("Field: " + xFieldInfo.Id); new Comment("Type: " + xFieldInfo.FieldType.ToString()); new Comment("Size: " + xFieldInfo.Size); new Comment("Offset: " + xOffset + " (includes object header)"); if (aDeclaringType.IsValueType && aTypeOnStack == aDeclaringType) { // the full struct is on the stack, instead of only a pointer to it if (xFieldInfo.Size > 4) { throw new Exception("For now, loading fields with sizes > 4 bytes from structs on the stack is not possible!"); } new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceValue = 0 }; switch (xFieldInfo.Size) { case 1: new CPUx86.Mov { DestinationReg = CPUx86.Registers.AL, SourceReg = CPUx86.Registers.ESP, SourceDisplacement = xOffset, SourceIsIndirect = true }; break; case 2: new CPUx86.Mov { DestinationReg = CPUx86.Registers.AX, SourceReg = CPUx86.Registers.ESP, SourceDisplacement = xOffset, SourceIsIndirect = true }; break; case 3: //For Release new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceDisplacement = xOffset, SourceIsIndirect = true }; new CPUx86.ShiftRight { DestinationReg = CPUx86.Registers.EAX, SourceValue = 8 }; break; case 4: new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceDisplacement = xOffset, SourceIsIndirect = true }; break; default: throw new Exception(string.Format("Field size {0} not supported!", xFieldInfo.Size)); } // now remove the struct from the stack new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = Align(GetStorageSize(aDeclaringType), 4) }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; return; } DoNullReferenceCheck(Assembler, debugEnabled, 0); new CPUx86.Pop { DestinationReg = CPUx86.Registers.ECX }; #if DOTNETCOMPATIBLE // pushed size is always 4 or 8 var xSize = ILOp.Align(xFieldInfo.Size, 4); #else var xSize = xFieldInfo.Size; #endif new CPUx86.Add { DestinationReg = CPUx86.Registers.ECX, SourceValue = (uint)(xOffset) }; if (xFieldInfo.IsExternalValue && aDerefExternalField) { new CPUx86.Mov { DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.ECX, SourceIsIndirect = true }; } for (int i = 1; i <= (xSize / 4); i++) { new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ECX, SourceIsIndirect = true, SourceDisplacement = (int)(xSize - (i * 4)) }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; } new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceValue = 0 }; switch (xSize % 4) { case 1: new CPUx86.Mov { DestinationReg = CPUx86.Registers.AL, SourceReg = CPUx86.Registers.ECX, SourceIsIndirect = true }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; break; case 2: new CPUx86.Mov { DestinationReg = CPUx86.Registers.AX, SourceReg = CPUx86.Registers.ECX, SourceIsIndirect = true }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; break; case 3: //For Release new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ECX, SourceIsIndirect = true }; new CPUx86.ShiftRight { DestinationReg = CPUx86.Registers.EAX, SourceValue = 8 }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; break; case 0: { break; } default: throw new Exception(string.Format("Remainder size {0:D} {1:D} not supported!", xFieldInfo.FieldType.ToString(), xSize)); } }