/// <summary> /// Process the field and add to datamember /// </summary> /// <param name="aField">The field to process</param> private void ProcessField(FieldInfo aField) { var xName = aField.FullName(); int xTheSize = 4; Type xFieldTypeDef = aField.FieldType; if (!xFieldTypeDef.IsClass || xFieldTypeDef.IsValueType) { xTheSize = aField.FieldType.SizeOf(); } // We use marshal and read c# assembly memory to get the value of static field byte[] xData = new byte[xTheSize]; try { object xValue = aField.GetValue(null); if (xValue != null) { try { xData = new byte[xTheSize]; if (xValue.GetType().IsValueType) { for (int x = 0; x < xTheSize; x++) { xData[x] = Marshal.ReadByte(xValue, x); } } } catch { // Do nothing, if error...we won't care it } } } catch { // Do nothing, if error...we won't care it } // Add it to data member Core.InsertData(new AsmData(xName, xData)); // Add it build definations BuildDefinations.Add(aField); }
public static void main() { const uint MultibootMagic = 0x1BADB002; const uint MultibootFlags = 0x10007; const uint InitalStackSize = 0x50000; /* Multiboot Config */ AssemblyHelper.AssemblerCode.Add(new Literal("MultibootSignature dd {0}", MultibootMagic)); AssemblyHelper.AssemblerCode.Add(new Literal("MultibootFlags dd {0}", 65543)); AssemblyHelper.AssemblerCode.Add(new Literal("MultibootChecksum dd {0}", -(MultibootMagic + MultibootFlags))); AssemblyHelper.AssemblerCode.Add(new Literal("MultibootHeaderAddr dd {0}", 0)); AssemblyHelper.AssemblerCode.Add(new Literal("MultibootLoadAddr dd {0}", 0)); AssemblyHelper.AssemblerCode.Add(new Literal("MultibootLoadEndAddr dd {0}", 0)); AssemblyHelper.AssemblerCode.Add(new Literal("MultibootBSSEndAddr dd {0}", 0)); AssemblyHelper.AssemblerCode.Add(new Literal("MultibootEntryAddr dd {0}", 0)); AssemblyHelper.InsertData(new AsmData("InitialStack", InitalStackSize)); AssemblyHelper.AssemblerCode.Add(new Label("_Kernel_Main")); /* Here is Entrypoint Method */ AssemblyHelper.AssemblerCode.Add(new Cli()); //Clear interrupts first !! //Setup Stack pointer, We do rest things later (i.e. Another method) because they are managed :) AssemblyHelper.AssemblerCode.Add(new Mov { DestinationReg = Registers.ESP, SourceRef = "InitialStack" }); AssemblyHelper.AssemblerCode.Add(new Add { DestinationReg = Registers.ESP, SourceRef = InitalStackSize.ToString() }); AssemblyHelper.AssemblerCode.Add(new Push { DestinationReg = Registers.EAX }); AssemblyHelper.AssemblerCode.Add(new Push { DestinationReg = Registers.EBX }); //Push Multiboot Header Info Address AssemblyHelper.AssemblerCode.Add(new Call("Kernel_Start")); }
/// <summary> /// Scan the normal method and find inline calls of virtual or real method to add it into queue /// After that Process method and add its assembly to main Array /// </summary> /// <param name="aMethod">The normal mathod =)</param> private void ScanMethod(MethodBase aMethod) { // Just a basic patch to fix Null reference exception var xBody = aMethod.GetMethodBody(); var xAssemblyName = aMethod.DeclaringType.Assembly.GetName().Name; if (RestrictedAssembliesName.Contains(xAssemblyName) && Plugs.ContainsValue(aMethod.FullName())) { return; } if (ILHelper.IsDelegate(aMethod.DeclaringType)) { ProcessDelegate(aMethod); return; } if (xBody == null) // Don't try to build null method { return; } // Tell logger that we are processing a method with given name and declaring type // Well declaring type is necessary because when we have a plugged method than // Its full name is the plugged value so we will not get where the plug is implemented // So declaring type help us to determine that ILCompiler.Logger.Write("@Processor", aMethod.FullName(), "Scanning Method()"); ILCompiler.Logger.Write("Type: " + aMethod.DeclaringType.FullName); ILCompiler.Logger.Write("Assembly: " + xAssemblyName); /* Scan Method for inline virtual or real methods call */ var xParams = aMethod.GetParameters(); var xParamTypes = new Type[xParams.Length]; for (int i = 0; i < xParams.Length; i++) { xParamTypes[i] = xParams[i].ParameterType; QueuedMember.Enqueue(xParamTypes[i]); } bool DynamicMethod = (aMethod.DeclaringType == null); if (!DynamicMethod) { QueuedMember.Enqueue(aMethod.DeclaringType); } if (aMethod is MethodInfo) { QueuedMember.Enqueue(((MethodInfo)aMethod).ReturnType); } if (!DynamicMethod && aMethod.IsVirtual) { #warning Need to implement currently } /* Process method and get out its IL's array */ // @Newlabels: New labels is the branches where we have to assign method // a label for branch/call IL's operations to perform. // we make its array while making the IL's array so its make our task easier List <int> NewLabels = new List <int>(); var OpCodes = aMethod.Process(NewLabels); // Here seems to be going something wrong ILCompiler.Logger.Write("MSIL Codes Loaded... Count::" + OpCodes.Count); string xMethodLabel = aMethod.FullName(); /* Method begin */ Core.AssemblerCode.Add(new Label(xMethodLabel)); TryToMakeGlobalSymbol(aMethod); Core.AssemblerCode.Add(new Comment(Worker.OPTIMIZATION_START_FLAG)); if (aMethod.IsStatic && aMethod is ConstructorInfo) { string aData = "cctor_" + xMethodLabel; Core.InsertData(new AsmData(aData, new byte[] { 0x00 })); Core.AssemblerCode.Add(new Cmp() { DestinationRef = aData, DestinationIndirect = true, SourceRef = "0x0", Size = 8 }); Core.AssemblerCode.Add(new Jmp() { Condition = ConditionalJumpEnum.JE, DestinationRef = Label.PrimaryLabel + ".Load" }); /* Footer of method */ Core.AssemblerCode.Add(new Mov { DestinationReg = Registers.ECX, SourceRef = "0x0" }); Core.AssemblerCode.Add(new Ret()); Core.AssemblerCode.Add(new Label(".Load")); Core.AssemblerCode.Add(new Mov() { DestinationRef = aData, DestinationIndirect = true, SourceRef = "0x1", Size = 8 }); } /* Calli instructions */ Core.AssemblerCode.Add(new Push() { DestinationReg = Registers.EBP }); Core.AssemblerCode.Add(new Mov() { DestinationReg = Registers.EBP, SourceReg = Registers.ESP }); /* Calculate Method Variables Size */ int Size = (from item in xBody.LocalVariables select item.LocalType.SizeOf().Align()).Sum(); if (Size > 0) { // Make a space for local variables Core.AssemblerCode.Add(new Sub { DestinationReg = Registers.ESP, SourceRef = "0x" + Size.Align().ToString("X") }); } ILCompiler.Logger.Write("Listening OpCodes"); /* Exceute IL Codes */ foreach (var Op in OpCodes) { // Check if we need exception to push? var xNeedsExceptionPush = (Op.Ehc != null) && (((Op.Ehc.HandlerOffset > 0 && Op.Ehc.HandlerOffset == Op.Position) || ((Op.Ehc.Flags & ExceptionHandlingClauseOptions.Filter) > 0 && Op.Ehc.FilterOffset > 0 && Op.Ehc.FilterOffset == Op.Position)) && (Op.Ehc.Flags == ExceptionHandlingClauseOptions.Clause)); ILCompiler.Logger.Write(Op.ToString() + "; Stack Count => " + Core.vStack.Count); // Check if current position inside the list of label list, if yes than break label and make a new one if (NewLabels.Contains(Op.Position)) { var xLbl = new Label(ILHelper.GetLabel(aMethod, Op.Position)); if (!Core.AssemblerCode.Contains(xLbl)) { Core.AssemblerCode.Add(xLbl); } } // If catch IL here than push current error so, that catch IL pop and do what it want if (xNeedsExceptionPush) { Core.AssemblerCode.Add(new Push { DestinationRef = "0x0" }); Core.AssemblerCode.Add(new Call(Helper.lblGetException, true)); Core.vStack.Push(4, typeof(Exception)); } // Well this is just to comment whole output Assembly if (!DoOptimization) { Core.AssemblerCode.Add(new Comment(Op.ToString() + "; " + Core.vStack.Count)); } // Check if this IL is in out implementation if (MSIL.ContainsKey(Op.Code)) { // If yes than execute it MSIL[Op.Code].Execute(Op, aMethod); } else { // If it is not implementation than throw error while compilation throw new Exception(Op.ToString() + "; " + xMethodLabel); } #region Queue Inline calls if (Op is OpMethod) { QueuedMember.Enqueue(((OpMethod)Op).Value); } else if (Op is OpType) { QueuedMember.Enqueue(((OpType)Op).Value); } else if (Op is OpField) { QueuedMember.Enqueue(((OpField)Op).Value.DeclaringType); if (((OpField)Op).Value.IsStatic) { QueuedMember.Enqueue(((OpField)Op).Value); } } else if (Op is OpToken) { var x = ((OpToken)Op); if (x.ValueIsType) { QueuedMember.Enqueue(x.ValueType); } if (x.ValueIsField) { QueuedMember.Enqueue(x.ValueField.DeclaringType); if (x.ValueField.IsStatic) { QueuedMember.Enqueue(x.ValueField); } } } #endregion } // End the method and return method, without exception Core.AssemblerCode.Add(new Label(xMethodLabel + ".End")); // We assume that if the ecx is 0x0 then the method is done without any exception // it can be assumed by test instruction followed by conditional jump while calling a function Core.AssemblerCode.Add(new Mov { DestinationReg = Registers.ECX, SourceRef = "0x0" }); Core.AssemblerCode.Add(new Label(xMethodLabel + ".Error")); // Now below code save the return value to EBP varaible // And calculate size int ArgSize = ILHelper.GetArgumentsSize(aMethod); int ReturnSize = ILHelper.GetReturnTypeSize(aMethod); if (ReturnSize > 0) { // For return type Method var xOffset = ILHelper.GetResultCodeOffset(ReturnSize, ArgSize); for (int i = 0; i < ReturnSize / 4; i++) { Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EAX }); Core.AssemblerCode.Add(new Mov { DestinationReg = Registers.EBP, DestinationIndirect = true, DestinationDisplacement = (int)(xOffset + ((i + 0) * 4)), SourceReg = Registers.EAX }); } } Core.AssemblerCode.Add(new Comment(Worker.OPTIMIAZTION_END_FLAG)); byte RetSize = (byte)Math.Max(0, ILHelper.GetArgumentsSize(aMethod) - ILHelper.GetReturnTypeSize(aMethod)); // Leave this method mean regain original EBP and ESP offset Core.AssemblerCode.Add(new Leave()); // Return to parent method with given stack offset Core.AssemblerCode.Add(new Ret { Address = RetSize }); // Add this method to build definations so we will not build it again BuildDefinations.Add(aMethod); // And log it ILCompiler.Logger.Write("Method Build Done()"); }