예제 #1
0
파일: ILScanner.cs 프로젝트: kztao/FlingOS
        /// <summary>
        /// Process an unplugged IL chunk.
        /// </summary>
        /// <param name="aChunk">The chunk to process.</param>
        /// <returns>The resulting ASM chunk or null if processing failed.</returns>
        private ASMChunk ProcessUnpluggedILChunk(ILChunk aChunk)
        {
            ASMChunk result = new ASMChunk();

            string methodSignature = Utils.GetMethodSignature(aChunk.Method);
            string MethodID = TheScannerState.GetMethodID(aChunk.Method);
            
            //Add the method to the debug database
            DB_Method dbMethod = null;
            if (TheSettings.DebugBuild)
            {
                dbMethod = new DB_Method();
                dbMethod.Id = MethodID;
                dbMethod.MethodSignature = methodSignature;
                dbMethod.Plugged = false;
                dbMethod.ASMStartPos = -1;
                dbMethod.ASMEndPos = -1;
                result.DBMethod = dbMethod;
                DebugDatabase.AddMethod(dbMethod);
            }

            result.ASM.AppendLine("; IL Scanned Method"); //DEBUG INFO
            result.ASM.AppendLine("; " + methodSignature); //DEBUG INFO
            //Outputs the label that is the start of this method
            result.ASM.AppendLine(MethodID + ":");

            //Construct the stack frame state for the start of this method
            StackFrame currFrame = new StackFrame();
            TheScannerState.CurrentStackFrame = currFrame;
            TheScannerState.CurrentILChunk = aChunk;

            //Insert the method start op
            //See comments on method start op for what it does etc.
            int addASMLineNum = 0;
            {
                //TODO - Add DBILOpInfo for MethodStart op

                result.ASM.AppendLine("; MethodStart"); // DEBUG INFO
                //Get the ASM of the op
                string asm = MethodStartOp.Convert(null, TheScannerState);
                //Split the ASM into lines
                string[] asmLines = asm.Replace("\r", "").Split('\n');
                
                //This code inserts the ASM line by line, outputting labels for
                //  each line of ASM.
                //Start at any existing offset for the current op
                //  - prevents duplication of labels
                int asmLineNum = addASMLineNum;
                //For each line of ASM:
                foreach (string asmLine in asmLines)
                {
                    //If the line isn't already a label:
                    if (!asmLine.Split(';')[0].Trim().EndsWith(":"))
                    {
                        //Output the ASM label
                        result.ASM.AppendLine(string.Format("{0}.IL_{1}_{2}:", MethodID, 0, asmLineNum));
                    }
                    //Append the ASM
                    result.ASM.AppendLine(asmLine);
                    //Increment the ASM line num
                    asmLineNum++;
                }
                //Set the overall ASM line offset for current op to final 
                //  offset
                addASMLineNum = asmLineNum;
            }

            #region GC
            
            //If Garbage Collection code should be added to this method:
            if (aChunk.ApplyGC)
            {
                //Inc ref count of all args passed to the method 
                //      - see ILReader for GC cleanup / dec ref count (use search: "Dec ref count" exc. quotes)
                List<Type> allParams = aChunk.Method.GetParameters()
                    .Select(x => x.ParameterType)
                    .ToList();
                //Non-static methods have first arg as instance reference
                if (!aChunk.Method.IsStatic)
                {
                    allParams.Insert(0, aChunk.Method.DeclaringType);
                }
                //If the number of args for this method > 0
                if (allParams.Count > 0)
                {
                    //Store the new ASM to append afterwards
                    string asm = "";

                    //For each arg:
                    for (int i = 0; i < allParams.Count; i++)
                    {
                        Type aVarType = allParams[i];
                        //If the arg is of a type managed by the GC
                        if (Utils.IsGCManaged(aVarType))
                        {
                            //Load the arg
                            asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Ldarg]
                                            .Convert(new ILOpInfo()
                                {
                                    opCode = System.Reflection.Emit.OpCodes.Ldarg,
                                    ValueBytes = BitConverter.GetBytes(i)
                                }, TheScannerState);
                            //Call increment ref count
                            asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Call]
                                            .Convert(new ILOpInfo()
                                {
                                    opCode = System.Reflection.Emit.OpCodes.Call,
                                    MethodToCall = TheScannerState.IncrementRefCountMethod
                                }, TheScannerState);
                        }
                    }

                    //Append the new ASM - see MethodStart for explanation above
                    string[] asmLines = asm.Replace("\r", "").Split('\n');
                    int asmLineNum = addASMLineNum;
                    foreach (string asmLine in asmLines)
                    {
                        if (!asmLine.Split(';')[0].Trim().EndsWith(":"))
                        {
                            result.ASM.AppendLine(string.Format("{0}.IL_{1}_{2}:", MethodID, 0, asmLineNum));
                        }
                        result.ASM.AppendLine(asmLine);
                        asmLineNum++;
                    }
                    addASMLineNum = asmLineNum;
                }
            }

            #endregion

            //Stores the label of the last IL op that was a debug NOP
            //  - See documentation for use of Debug NOPs / INT3s
            string debugNopLabel = null;
            
            //Stores the start position of the current IL op in the ASM
            int ASMStartPos = 0;
            //Get a list of all the IL ops
            List<ILOpInfo> TheILOpInfos = aChunk.ILOpInfos;
            //For each IL op:
            foreach (ILOpInfo anILOpInfo in TheILOpInfos)
            {
                //We surround all this with a try-catch block 
                //  so that if processing the current IL op causes an exception, we don't abort processing 
                //  of the entire method. We will end up with invalid ASM code in the output, but at least
                //  the developer will receive all the errors with their code not just one per build.
                try
                {
                    #region Debug 

                    //Create the debug
                    DB_ILOpInfo dbILOpInfo = null;
                    if (TheSettings.DebugBuild)
                    {
                        dbILOpInfo = new DB_ILOpInfo();
                        dbILOpInfo.Id = Guid.NewGuid();
                        dbILOpInfo.MethodID = MethodID;
                        dbILOpInfo.OpCode = anILOpInfo.opCode.Value;
                        dbILOpInfo.CustomOpCode = 0;
                        dbILOpInfo.NextPosition = anILOpInfo.NextPosition;
                        dbILOpInfo.Position = anILOpInfo.Position;
                        if (anILOpInfo.ValueBytes != null)
                        {
                            if (anILOpInfo.ValueBytes.Length < 8000)
                            {
                                dbILOpInfo.ValueBytes = new System.Data.Linq.Binary(anILOpInfo.ValueBytes);
                            }
                            else
                            {
                                OutputWarning(new Exception("ValueBytes not set because data too large. Op: " + anILOpInfo.opCode.Name + ", Op offset: " + anILOpInfo.Position.ToString("X2") + "\r\n" + methodSignature));
                                anILOpInfo.ValueBytes = null;
                            }
                        }
                        dbILOpInfo.ASMInsertLabel = true;
                        anILOpInfo.DBILOpInfo = dbILOpInfo;

                        dbILOpInfo.ASMStartPos = anILOpInfo.ASMStartPos = ASMStartPos;
                    }

                    #endregion

                    //Stores all the new ASM for this IL op
                    //  - This ASM gets appended to the result at the end of the try-section
                    //    thus it only gets appended if there are no processing errors.
                    string asm = "";

                    #region Exception Handling

                    //We needs to check if we are in try, catch or finally blocks (a.k.a critical sections):
                    ExceptionHandledBlock exBlock = aChunk.GetExceptionHandledBlock(anILOpInfo.Position);
                    //If we are in a critical section:
                    if (exBlock != null)
                    {
                        //If this IL op is the first op of a try-section:
                        if (exBlock.Offset == anILOpInfo.Position)
                        {
                            //Insert the start of try-block

                            //Consists of adding a new ExceptionHandlerInfos
                            //  built from the info in exBlock so we:
                            //      - Add infos for all finally blocks first
                            //      - Then add infos for all catch blocks
                            //  Since finally code is always run after catch code in C#,
                            //      by adding catch handlers after finally handlers, they 
                            //      appear as the inner-most exception handlers and so get 
                            //      run before finally handlers.

                            //To add a new ExceptionHandlerInfo we must set up args for 
                            //  calling Exceptions.AddExceptionHandlerInfo:
                            // 1. We load a pointer to the handler
                            //      - This is calculated from an offset from the start of the function to the handler
                            // 2. We load a pointer to the filter
                            //      - This is calculated from an offset from the start of the function to the filter
                            //      Note: Filter has not been implemented as an actual filter. 
                            //            At the moment, 0x00000000 indicates a finally handler,
                            //                           0xFFFFFFFF indicates no filter block 
                            //                                      (i.e. an unfiltered catch handler)
                            //                           0xXXXXXXXX has undetermined behaviour!
                            
                            result.ASM.AppendLine("; Try-block start"); // DEBUG INFO
                            //For each finally block:
                            foreach (FinallyBlock finBlock in exBlock.FinallyBlocks)
                            {
                                // 1. Load the pointer to the handler code:
                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Ldftn].Convert(new ILOpInfo()
                                {
                                    //Load function pointer op
                                    opCode = System.Reflection.Emit.OpCodes.Ldftn,
                                    //Load a pointer to the current method
                                    MethodToCall = aChunk.Method,
                                    //At this offset: The first IL op of the finally block
                                    LoadAtILOffset = finBlock.Offset
                                }, TheScannerState);
                                // 2. Load the pointer to the filter code:
                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Ldc_I4].Convert(new ILOpInfo()
                                {
                                    //Load a constant value
                                    opCode = System.Reflection.Emit.OpCodes.Ldc_I4,
                                    //The value is 0x00000000 - since this is a finally handler
                                    ValueBytes = BitConverter.GetBytes(0x00000000)
                                }, TheScannerState);
                                // Call Exceptions.AddExceptionHandlerInfo
                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Call].Convert(new ILOpInfo()
                                {
                                    opCode = System.Reflection.Emit.OpCodes.Call,
                                    MethodToCall = TheScannerState.AddExceptionHandlerInfoMethod
                                }, TheScannerState);
                            }
                            foreach (CatchBlock catchBlock in exBlock.CatchBlocks)
                            {
                                // 1. Load the pointer to the handler code:
                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Ldftn].Convert(new ILOpInfo()
                                {
                                    opCode = System.Reflection.Emit.OpCodes.Ldftn,
                                    MethodToCall = aChunk.Method,
                                    LoadAtILOffset = catchBlock.Offset
                                }, TheScannerState);
                                //TODO - We need to sort out a way of doing filter functions
                                // 2. Load the pointer to the filter code:
                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Ldc_I4].Convert(new ILOpInfo()
                                {
                                    opCode = System.Reflection.Emit.OpCodes.Ldc_I4,
                                    //The value is 0xFFFFFFFF - since this is a catch handler (and filters aren't implemented yet!)
                                    ValueBytes = BitConverter.GetBytes(0xFFFFFFFF)
                                }, TheScannerState);
                                // Call Exceptions.AddExceptionHandlerInfo
                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Call].Convert(new ILOpInfo()
                                {
                                    opCode = System.Reflection.Emit.OpCodes.Call,
                                    MethodToCall = TheScannerState.AddExceptionHandlerInfoMethod
                                }, TheScannerState);
                            }
                        }

                        //We need to check if the current IL op is the first op
                        //  of a catch block. This is because C# catch blocks are
                        //  compiled with a "pop" instruction as the first op if
                        //  the catch block has no filter. Presumably, this is because
                        //  C# would be expecting the current exception to be on the
                        //  stack.

                        //Get any catch blocks we are currently in.
                        List<CatchBlock> potCatchBlocks = (from catchBlocks in exBlock.CatchBlocks
                                                           where (catchBlocks.Offset <= anILOpInfo.Position &&
                                                                  catchBlocks.Offset + catchBlocks.Length >= anILOpInfo.Position)
                                                           select catchBlocks).ToList();
                        //If we are in a catch block:
                        if (potCatchBlocks.Count > 0)
                        {
                            CatchBlock catchBlock = potCatchBlocks.First();
                            //If this is the first op of the catch block:
                            if (catchBlock.Offset == anILOpInfo.Position)
                            {
                                result.ASM.AppendLine("; Catch-block start"); // DEBUG INFO

                                //Ignore the first pop-op of the catch block
                                if ((int)anILOpInfo.opCode.Value == (int)ILOps.ILOp.OpCodes.Pop)
                                {
                                    //Do an immediate append rather than using the "asm" variable as we will be calling
                                    // "continue" - see below.
                                    //For debug, we must insert this op's label in to the ASM.
                                    string label = string.Format("{0}.IL_{1}_{2}", MethodID, anILOpInfo.Position, 0);
                                    result.ASM.AppendLine(label + ":");
                                    result.ASM.AppendLine("; Skipped first pop of catch handler"); // DEBUG INFO
                                    //End processing of this op by skipping to the next!
                                    continue;
                                }
                            }
                        }

                        //We want to be able to output some debug info if we are starting a finally block
                        //  just so that our ASM is more intellgible / debuggable.
                        List<FinallyBlock> potFinallyBlocks = (from finallyBlocks in exBlock.FinallyBlocks
                                                               where (finallyBlocks.Offset <= anILOpInfo.Position &&
                                                                      finallyBlocks.Offset + finallyBlocks.Length >= anILOpInfo.Position)
                                                               select finallyBlocks).ToList();
                        if (potFinallyBlocks.Count > 0)
                        {
                            FinallyBlock finallyBlock = potFinallyBlocks.First();

                            if (finallyBlock.Offset == anILOpInfo.Position)
                            {
                                result.ASM.AppendLine("; Finally-block start"); // DEBUG INFO
                            }
                        }
                    }

                    #endregion

                    #region Debug 

                    if (TheSettings.DebugBuild)
                    {
                        //If this chunk hasn't been marked as no-debug ops:
                        if (!aChunk.NoDebugOps)
                        {
                            // Insert a debug nop just before the op
                            //  - This allows us to step an entire IL op at a time rather than just one
                            //    line of ASM at a time.
                            result.ASM.AppendLine("; Debug Nop"); // DEBUG INFO
                            // Insert the nop
                            asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Nop].Convert(anILOpInfo, TheScannerState);
                            //See above for how this append code works
                            string[] asmLines = asm.Replace("\r", "").Split("\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                            int asmLineNum = addASMLineNum;
                            //Clear the current debug nop label so we can get the first label
                            //  of the new ASM and use it as the debug nop label for this IL op.
                            debugNopLabel = null;
                            foreach (string asmLine in asmLines)
                            {
                                if (!asmLine.Split(';')[0].Trim().EndsWith(":"))
                                {
                                    string label = string.Format("{0}.IL_{1}_{2}", MethodID, anILOpInfo.Position, asmLineNum);
                                    //If we do not currently have a debug nop label for this IL op:
                                    if (debugNopLabel == null)
                                    {
                                        //Set the current debug nop label.
                                        debugNopLabel = label;
                                    }
                                    result.ASM.AppendLine(label + ":");
                                }
                                result.ASM.AppendLine(asmLine);
                                asmLineNum++;
                            }
                            addASMLineNum = asmLineNum;
                            //We just added all the ASM for this op generated so far, so clean the "asm" variable
                            asm = "";
                        }
                        //Set the debug nop label for this IL op as the last inserted debug nop label
                        dbILOpInfo.DebugOpMeta = "DebugNopLabel=" + debugNopLabel + ";";
                    }

                    #endregion

                    //Insert some method end code just before the ret op.
                    if ((int)anILOpInfo.opCode.Value == (int)ILOps.ILOp.OpCodes.Ret)
                    {
                        //Method End op inserts code such as storing the return value
                        //  in the return argument and restoring the stack base pointer
                        result.ASM.AppendLine("; MethodEnd"); // DEBUG INFO
                        asm += "\r\n" + MethodEndOp.Convert(null, TheScannerState);
                    }


                    if ((int)anILOpInfo.opCode.Value == (int)ILOps.ILOp.OpCodes.Leave ||
                        (int)anILOpInfo.opCode.Value == (int)ILOps.ILOp.OpCodes.Leave_S)
                    #region Exception Handling
                    {
                        //Leave is for leaving a critical section
                        //We handle it by a higher-level implementation rather than 
                        //  leaving it to each architecture to implement.

                        //Leave is handled by inserting a call to the Exceptions.HandleLeave method

                        //This value is an offset from the next IL op to the line to continue execution at
                        //  if there isno current exception and no finally handler.
                        int ILOffset = 0;
                        if ((int)anILOpInfo.opCode.Value == (int)ILOps.ILOp.OpCodes.Leave)
                        {
                            ILOffset = BitConverter.ToInt32(anILOpInfo.ValueBytes, 0);
                        }
                        else
                        {
                            ILOffset = (int)anILOpInfo.ValueBytes[0];
                        }

                        //Get the IL number of the next op
                        int startILNum = anILOpInfo.NextPosition;
                        //Add the offset to get the IL op num to jump to
                        int ILNumToGoTo = startILNum + ILOffset;

                        // Load the address of the op to continue execution at if there is no exception and
                        //  no finally handler.
                        asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Ldftn].Convert(new ILOpInfo()
                        {
                            opCode = System.Reflection.Emit.OpCodes.Ldftn,
                            MethodToCall = aChunk.Method,
                            LoadAtILOffset = ILNumToGoTo
                        }, TheScannerState);
                        // Call Exceptions.HandleLeave
                        asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Call].Convert(new ILOpInfo()
                        {
                            opCode = System.Reflection.Emit.OpCodes.Call,
                            MethodToCall = TheScannerState.ExceptionsHandleLeaveMethod
                        }, TheScannerState);
                    }
                    else if ((int)anILOpInfo.opCode.Value == (int)ILOps.ILOp.OpCodes.Endfinally)
                    {
                        //Endfinally is for leaving a (critical) finally section
                        //We handle it by a higher-level implementation rather than 
                        //  leaving it to each architecture to implement.

                        //Endfinally is handled by inserting a call to the Exceptions.HandleEndFinally method

                        asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Call].Convert(new ILOpInfo()
                        {
                            opCode = System.Reflection.Emit.OpCodes.Call,
                            MethodToCall = TheScannerState.ExceptionsHandleEndFinallyMethod
                        }, TheScannerState);
                    }

                    #endregion
                    else if ((int)anILOpInfo.opCode.Value == (int)ILOps.ILOp.OpCodes.Castclass)
                    {
                        //This IL op is ignored for now. We assume the the Microsoft compiler (csc.exe) 
                        //makes the correct casting checks etc
                        //And even if it doesn't, at the kernel level it is useful to be able to play
                        //  tricks with converting objects to/from MS types and custom kernel types 
                        //  e.g. System.String to Kernel.FOS_System.String
                    }
                    else
                    {
                        //Indicates whether the IL op should actually be processed or not.
                        //  - At this stage, there are a few cases when the Il op should not be
                        //    processed but the new ASM should still be appended.
                        bool processOp = true;

                        #region Special-case op handling

                        //If the op is a call:
                        if ((int)anILOpInfo.opCode.Value == (int)ILOps.ILOp.OpCodes.Call)
                        {
                            //If the method to call is actually in mscorlib:
                            if (anILOpInfo.MethodToCall != null && anILOpInfo.MethodToCall.DeclaringType.AssemblyQualifiedName.
                                Contains("mscorlib"))
                            {
                                //We do not want to process ops which attempt to call methods in mscorlib!
                                processOp = false;

                                //We do not allow calls to methods declared in MSCorLib.
                                //Some of these calls can just be ignored (e.g. GetTypeFromHandle is
                                //  called by typeof operator).
                                //Ones which can't be ignored, will result in an error...by virtue of
                                //  the fact that they were ignored when they were required.

                                //But just to make sure we save ourselves a headache later when
                                //  runtime debugging, output a message saying we ignored the call.
                                result.ASM.AppendLine("; Call to method defined in MSCorLib ignored:"); // DEBUG INFO
                                result.ASM.AppendLine("; " + anILOpInfo.MethodToCall.DeclaringType.FullName + "." + anILOpInfo.MethodToCall.Name); // DEBUG INFO

                                //If the method is a call to a constructor in MsCorLib:
                                if (anILOpInfo.MethodToCall is ConstructorInfo)
                                {
                                    //Then we can presume it was a call to a base-class constructor (e.g. the Object constructor)
                                    //  and so we just need to remove any args that were loaded onto the stack.
                                    result.ASM.AppendLine("; Method to call was constructor so removing params"); // DEBUG INFO
                                    //Remove args from stack
                                    //If the constructor was non-static, then the first arg is the instance reference.
                                    if (!anILOpInfo.MethodToCall.IsStatic)
                                    {
                                        asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Pop].Convert(new ILOpInfo()
                                        {
                                            opCode = System.Reflection.Emit.OpCodes.Pop
                                        }, TheScannerState);
                                    }
                                    foreach (ParameterInfo anInfo in anILOpInfo.MethodToCall.GetParameters())
                                    {
                                        asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Pop].Convert(new ILOpInfo()
                                        {
                                            opCode = System.Reflection.Emit.OpCodes.Pop
                                        }, TheScannerState);
                                    }
                                }
                            }
                            //If the method to call wasn't to a method in MsCorLib, we may need to set the method to call:
                            else if(anILOpInfo.SetToGCDecRefCountMethod)
                            {
                                anILOpInfo.MethodToCall = TheScannerState.DecrementRefCountMethod;
                            }
                        }

                        #endregion

                        //If the op should be processed:
                        if(processOp)
                        {
                            #region GC 

                            //GC requires us to decrement ref count of any field/local/arg
                            //  that is about to be overwritten
                            //NewILOps - Unimplemented and new IL Ops need checking and below
                            //           adding if necessary

                            if (aChunk.ApplyGC)
                            {
                                bool IncRefCount = false;

                                switch ((ILOps.ILOp.OpCodes)anILOpInfo.opCode.Value)
                                {
                                    case ILOps.ILOp.OpCodes.Stsfld:
                                        {
                                            int metadataToken = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                                            FieldInfo theField = TheScannerState.CurrentILChunk.Method.Module.ResolveField(metadataToken);
                                            if (Utils.IsGCManaged(theField.FieldType))
                                            {
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Ldsfld].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Ldsfld,
                                                    ValueBytes = anILOpInfo.ValueBytes
                                                }, TheScannerState);
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Call].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Call,
                                                    MethodToCall = TheScannerState.DecrementRefCountMethod
                                                }, TheScannerState);

                                                IncRefCount = true;
                                            }
                                        }
                                        break;
                                    case ILOps.ILOp.OpCodes.Stloc:
                                        {
                                            UInt16 localIndex = (UInt16)Utils.ReadInt16(anILOpInfo.ValueBytes, 0);
                                            if (Utils.IsGCManaged(aChunk.LocalVariables[localIndex].TheType))
                                            {
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Ldloc].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Ldloc,
                                                    ValueBytes = anILOpInfo.ValueBytes
                                                }, TheScannerState);
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Call].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Call,
                                                    MethodToCall = TheScannerState.DecrementRefCountMethod
                                                }, TheScannerState);

                                                IncRefCount = true;
                                            }
                                        }
                                        break;
                                    case ILOps.ILOp.OpCodes.Stloc_0:
                                        {
                                            if (Utils.IsGCManaged(aChunk.LocalVariables[0].TheType))
                                            {
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Ldloc_0].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Ldloc_0
                                                }, TheScannerState);
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Call].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Call,
                                                    MethodToCall = TheScannerState.DecrementRefCountMethod
                                                }, TheScannerState);

                                                IncRefCount = true;
                                            }
                                        }
                                        break;
                                    case ILOps.ILOp.OpCodes.Stloc_1:
                                        {
                                            if (Utils.IsGCManaged(aChunk.LocalVariables[1].TheType))
                                            {
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Ldloc_1].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Ldloc_1
                                                }, TheScannerState);
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Call].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Call,
                                                    MethodToCall = TheScannerState.DecrementRefCountMethod
                                                }, TheScannerState);

                                                IncRefCount = true;
                                            }
                                        }
                                        break;
                                    case ILOps.ILOp.OpCodes.Stloc_2:
                                        {
                                            if (Utils.IsGCManaged(aChunk.LocalVariables[2].TheType))
                                            {
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Ldloc_2].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Ldloc_2
                                                }, TheScannerState);
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Call].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Call,
                                                    MethodToCall = TheScannerState.DecrementRefCountMethod
                                                }, TheScannerState);

                                                IncRefCount = true;
                                            }
                                        }
                                        break;
                                    case ILOps.ILOp.OpCodes.Stloc_3:
                                        {
                                            if (Utils.IsGCManaged(aChunk.LocalVariables[3].TheType))
                                            {
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Ldloc_3].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Ldloc_3
                                                }, TheScannerState);
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Call].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Call,
                                                    MethodToCall = TheScannerState.DecrementRefCountMethod
                                                }, TheScannerState);

                                                IncRefCount = true;
                                            }
                                        }
                                        break;
                                    case ILOps.ILOp.OpCodes.Stloc_S:
                                        {
                                            UInt16 localIndex = (UInt16)anILOpInfo.ValueBytes[0];
                                            if (Utils.IsGCManaged(aChunk.LocalVariables[localIndex].TheType))
                                            {
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Ldloc_S].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Ldloc_S,
                                                    ValueBytes = anILOpInfo.ValueBytes
                                                }, TheScannerState);
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Call].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Call,
                                                    MethodToCall = TheScannerState.DecrementRefCountMethod
                                                }, TheScannerState);

                                                IncRefCount = true;
                                            }
                                        }
                                        break;
                                    case ILOps.ILOp.OpCodes.Stfld:
                                        {
                                            int metadataToken = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                                            FieldInfo theField = aChunk.Method.Module.ResolveField(metadataToken);
                                            if (Utils.IsGCManaged(theField.FieldType))
                                            {
                                                // Items on stack:
                                                //  - Object reference
                                                //  - (New) Value to store
                                                //
                                                // We want to load the current value of the field
                                                //  for which we must duplicate the object ref
                                                // But first, we must remove the (new) value to store
                                                //  off the stack, while also storing it to put back
                                                //  on the stack after so the store can continue
                                                //
                                                // So:
                                                //      1. Switch value to store and object ref on stack
                                                //      3. Duplicate the object ref
                                                //      4. Load the field value
                                                //      5. Call dec ref count
                                                //      6. Switch value to store and object ref back again

                                                //USE A SWITCH STACK ITEMS OP!!

                                                asm += "\r\n" + StackSwitchOp.Convert(new ILOpInfo()
                                                {
                                                }, TheScannerState);
                                                StackItem switchItem1 = TheScannerState.CurrentStackFrame.Stack.Pop();
                                                StackItem switchItem2 = TheScannerState.CurrentStackFrame.Stack.Pop();
                                                TheScannerState.CurrentStackFrame.Stack.Push(switchItem1);
                                                TheScannerState.CurrentStackFrame.Stack.Push(switchItem2);
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Dup].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Dup
                                                }, TheScannerState);
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Ldfld].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Ldfld,
                                                    ValueBytes = anILOpInfo.ValueBytes
                                                }, TheScannerState);
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Call].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Call,
                                                    MethodToCall = TheScannerState.DecrementRefCountMethod
                                                }, TheScannerState);
                                                asm += "\r\n" + StackSwitchOp.Convert(new ILOpInfo()
                                                {
                                                }, TheScannerState);
                                                switchItem1 = TheScannerState.CurrentStackFrame.Stack.Pop();
                                                switchItem2 = TheScannerState.CurrentStackFrame.Stack.Pop();
                                                TheScannerState.CurrentStackFrame.Stack.Push(switchItem1);
                                                TheScannerState.CurrentStackFrame.Stack.Push(switchItem2);

                                                IncRefCount = true;
                                            }
                                        }
                                        break;
                                    case ILOps.ILOp.OpCodes.Stelem:
                                    case ILOps.ILOp.OpCodes.Stelem_Ref:
                                        {
                                            bool doDecrement = false;
                                            bool isRefOp = false;
                                            if ((ILOps.ILOp.OpCodes)anILOpInfo.opCode.Value == ILOps.ILOp.OpCodes.Stelem_Ref)
                                            {
                                                doDecrement = TheScannerState.CurrentStackFrame.Stack.Peek().isGCManaged;
                                                isRefOp = true;
                                            }
                                            else
                                            {
                                                int metadataToken = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                                                Type elementType = aChunk.Method.Module.ResolveType(metadataToken);
                                                doDecrement = Utils.IsGCManaged(elementType);
                                            }

                                            if (doDecrement)
                                            {
                                                // Items on stack:
                                                //  - Array reference
                                                //  - Index
                                                //  - (New) Value to store
                                                //
                                                // We want to load the current value of the element at Index in the array
                                                //  for which we must duplicate the array ref and index
                                                // But first, we must remove the (new) value to store
                                                //  off the stack, while also storing it to put back
                                                //  on the stack after so the store can continue
                                                //
                                                // So:
                                                //      1. Switch (rotate) 1 times the top 3 values so that index is on top
                                                //      2. Duplicate the index
                                                //      3. Switch (rotate) 2 times the top 4 values so that array ref is on top
                                                //      4. Duplicate the array ref
                                                //      5. Switch (rotate) 4 times the top 5 values so that duplicate array ref and index are on top
                                                //      6. Do LdElem op to load existing element value
                                                //      7. Call GC.DecrementRefCount
                                                //      8. Switch (rotate) 1 times the top 3 values so that the stack is in its original state
                                                //      (9. Continue to increment ref count as normal)
                                                //
                                                // The following is a diagram of the stack manipulation occurring here:
                                                //      Key: A=Array ref, I=Index, V=Value to store, E=Loaded element
                                                //      Top-most stack item appears last
                                                //  
                                                //     1) Rotate x 1    2) Duplicate       3)  Rot x 2         4)  Dup
                                                //  A,I,V ---------> V,A,I ---------> V,A,I,I ---------> I,I,V,A ---------> I,I,V,A,A
                                                //
                                                //
                                                //          5) Rot x 4           6) Ldelem        7) Call GC (Dec)
                                                //  I,I,V,A,A ---------> I,V,A,A,I ---------> I,V,A,E ---------> I,V,A
                                                //
                                                //
                                                //      8) Rot x 1       9)  Dup         10) Call GC (Inc)
                                                //  I,V,A ---------> A,I,V ---------> A,I,V,V ---------> A,I,V

                                                #region 1.
                                                asm += "\r\n" + StackSwitchOp.Convert(new ILOpInfo()
                                                {
                                                    ValueBytes = BitConverter.GetBytes(3)
                                                }, TheScannerState);

                                                rotateStackItems(3, 1);
                                                #endregion
                                                #region 2.
                                                    asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Dup].Convert(new ILOpInfo()
                                                    {
                                                        opCode = System.Reflection.Emit.OpCodes.Dup
                                                    }, TheScannerState);
                                                #endregion
                                                #region 3.
                                                asm += "\r\n" + StackSwitchOp.Convert(new ILOpInfo()
                                                {
                                                    ValueBytes = BitConverter.GetBytes(4)
                                                }, TheScannerState);
                                                asm += "\r\n" + StackSwitchOp.Convert(new ILOpInfo()
                                                {
                                                    ValueBytes = BitConverter.GetBytes(4)
                                                }, TheScannerState);

                                                rotateStackItems(4, 2);
                                                #endregion
                                                #region 4.
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Dup].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Dup
                                                }, TheScannerState);
                                                #endregion
                                                #region 5.
                                                asm += "\r\n" + StackSwitchOp.Convert(new ILOpInfo()
                                                {
                                                    ValueBytes = BitConverter.GetBytes(5)
                                                }, TheScannerState);
                                                asm += "\r\n" + StackSwitchOp.Convert(new ILOpInfo()
                                                {
                                                    ValueBytes = BitConverter.GetBytes(5)
                                                }, TheScannerState);
                                                asm += "\r\n" + StackSwitchOp.Convert(new ILOpInfo()
                                                {
                                                    ValueBytes = BitConverter.GetBytes(5)
                                                }, TheScannerState);
                                                asm += "\r\n" + StackSwitchOp.Convert(new ILOpInfo()
                                                {
                                                    ValueBytes = BitConverter.GetBytes(5)
                                                }, TheScannerState);

                                                rotateStackItems(5, 4);
                                                #endregion
                                                #region 6.
                                                asm += "\r\n" + TargetILOps[isRefOp ? ILOps.ILOp.OpCodes.Ldelem_Ref : ILOps.ILOp.OpCodes.Ldelem].Convert(new ILOpInfo()
                                                {
                                                    opCode = isRefOp ? System.Reflection.Emit.OpCodes.Ldelem_Ref : System.Reflection.Emit.OpCodes.Ldelem,
                                                    ValueBytes = anILOpInfo.ValueBytes,
                                                    Position = anILOpInfo.Position
                                                }, TheScannerState);
                                                #endregion
                                                #region 7.
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Call].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Call,
                                                    MethodToCall = TheScannerState.DecrementRefCountMethod
                                                }, TheScannerState);
                                                #endregion
                                                #region 8.
                                                asm += "\r\n" + StackSwitchOp.Convert(new ILOpInfo()
                                                {
                                                    ValueBytes = BitConverter.GetBytes(3)
                                                }, TheScannerState);

                                                rotateStackItems(3, 1);
                                                #endregion

                                                IncRefCount = true;
                                            }
                                        }
                                        break;
                                    case ILOps.ILOp.OpCodes.Starg:
                                        {
                                            Int16 index = Utils.ReadInt16(anILOpInfo.ValueBytes, 0);
                                            index -= (Int16)(!aChunk.Method.IsStatic ? 1 : 0);
                                            if (Utils.IsGCManaged(aChunk.Method.GetParameters()[index].ParameterType))
                                            {
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Ldarg].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Ldarg,
                                                    ValueBytes = anILOpInfo.ValueBytes
                                                }, TheScannerState);
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Call].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Call,
                                                    MethodToCall = TheScannerState.DecrementRefCountMethod
                                                }, TheScannerState);

                                                IncRefCount = true;
                                            }
                                        }
                                        break;
                                    case ILOps.ILOp.OpCodes.Starg_S:
                                        {
                                            Int16 index = (Int16)anILOpInfo.ValueBytes[0];
                                            index -= (Int16)(!aChunk.Method.IsStatic ? 1 : 0);
                                            if (Utils.IsGCManaged(aChunk.Method.GetParameters()[index].ParameterType))
                                            {
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Ldarg_S].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Ldarg_S,
                                                    ValueBytes = anILOpInfo.ValueBytes
                                                }, TheScannerState);
                                                asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Call].Convert(new ILOpInfo()
                                                {
                                                    opCode = System.Reflection.Emit.OpCodes.Call,
                                                    MethodToCall = TheScannerState.DecrementRefCountMethod
                                                }, TheScannerState);

                                                IncRefCount = true;
                                            }
                                        }
                                        break;
                                }

                                if(IncRefCount &&
                                   !TheScannerState.CurrentStackFrame.Stack.Peek().isNewGCObject)
                                {
                                    TheScannerState.CurrentStackFrame.Stack.Peek().isNewGCObject = false;

                                    asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Dup].Convert(new ILOpInfo()
                                    {
                                        opCode = System.Reflection.Emit.OpCodes.Dup
                                    }, TheScannerState);
                                    asm += "\r\n" + TargetILOps[ILOps.ILOp.OpCodes.Call].Convert(new ILOpInfo()
                                    {
                                        opCode = System.Reflection.Emit.OpCodes.Call,
                                        MethodToCall = TheScannerState.IncrementRefCountMethod
                                    }, TheScannerState);
                                }
                            }

                            #endregion

                            result.ASM.AppendLine("; " + anILOpInfo.opCode.Name); //DEBUG INFO

                            ILOps.ILOp TheIlOp = TargetILOps[(ILOps.ILOp.OpCodes)anILOpInfo.opCode.Value];

                            #region Debug

                            if (TheSettings.DebugBuild)
                            {
                                if (anILOpInfo.opCode.Name == "nop" && !aChunk.NoDebugOps)
                                {
                                    anILOpInfo.IsDebugOp = dbILOpInfo.IsDebugOp = true;
                                    dbILOpInfo.DebugOpMeta += "breakpoint;";
                                }
                                else
                                {
                                    dbILOpInfo.IsDebugOp = false;
                                }
                            }

                            #endregion

                            // Convert the IL op to ASM!
                            asm += "\r\n" + TheIlOp.Convert(anILOpInfo, TheScannerState);
                        }
                    }
                    {
                        // Append the new ASm to the result ASM :)
                        // See above (MethodStart op) for thow this code works.
                        string[] asmLines = asm.Replace("\r", "").Split("\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                        int asmLineNum = addASMLineNum;
                        foreach (string asmLine in asmLines)
                        {
                            if (!asmLine.Split(';')[0].Trim().EndsWith(":"))
                            {
                                result.ASM.AppendLine(string.Format("{0}.IL_{1}_{2}:", MethodID, anILOpInfo.Position, asmLineNum));
                            }
                            result.ASM.AppendLine(asmLine);
                            asmLineNum++;
                        }
                        addASMLineNum = asmLineNum;
                    }

                    #region Debug

                    if (TheSettings.DebugBuild)
                    {
                        dbILOpInfo.ASMEndPos = anILOpInfo.ASMEndPos = result.ASM.Length;

                        DebugDatabase.AddILOpInfo(dbILOpInfo);
                    }

                    #endregion
                }
                catch(KeyNotFoundException)
                {
                    result.ASM.AppendLine("; ERROR! Target architecture does not support this IL op."); //DEBUG INFO
                    OutputError(new Exception("Target architecture does not support ILOp! Op type: " + anILOpInfo.opCode.Name + ", Op offset: " + anILOpInfo.Position.ToString("X2") + "\r\n" + methodSignature));
                }
                catch (Exception ex)
                {
                    result.ASM.AppendLine("; ERROR! ILScanner failed to process."); //DEBUG INFO
                    OutputError(new Exception("Could not process an ILOp! Op type: " + anILOpInfo.opCode.Name + ", Op offset: " + anILOpInfo.Position.ToString("X2") + "\r\n" + methodSignature, ex));
                }

                ASMStartPos = result.ASM.Length;
                addASMLineNum = 0;
            }

            #region Debug

            if (TheSettings.DebugBuild)
            {
                //Add debug info for local variables of this method
                int locIndex = 0;
                foreach (LocalVariable localItem in aChunk.LocalVariables)
                {
                    DB_LocalVariable dbLocalVar = new DB_LocalVariable();
                    dbLocalVar.BytesSize = localItem.sizeOnStackInBytes;
                    dbLocalVar.Id = Guid.NewGuid();
                    dbLocalVar.Index = locIndex;
                    //We always call ProcessType just in case we missed a type
                    //  when loading assemblies
                    dbLocalVar.TypeID = ProcessType(localItem.TheType).Id;
                    dbLocalVar.MethodID = dbMethod.Id;
                    DebugDatabase.AddLocalVariable(dbLocalVar);
                    locIndex++;
                }
            }

            #endregion

            return result;
        }
예제 #2
0
파일: ILScanner.cs 프로젝트: kztao/FlingOS
        /// <summary>
        /// Process a plugged IL chunk.
        /// </summary>
        /// <param name="aChunk">The chunk to process.</param>
        /// <returns>The resulting ASM chunk or null if processing failed.</returns>
        /// <exception cref="System.IO.FileNotFoundException">
        /// Thrown if the plug file for the ILChunk could not be found.
        /// </exception>
        private ASMChunk ProcessPluggedILChunk(ILChunk aChunk)
        {
            string methodSignature = Utils.GetMethodSignature(aChunk.Method);

            ASMChunk result = new ASMChunk();

            DB_Method dbMethod = null;
            if (TheSettings.DebugBuild)
            {
                //Add the method to the debug database
                //  (method is marked as plugged)
                dbMethod = new DB_Method();
                dbMethod.Id = TheScannerState.GetMethodID(aChunk.Method);
                dbMethod.MethodSignature = methodSignature;
                dbMethod.Plugged = true;
                dbMethod.ASMStartPos = -1;
                dbMethod.ASMEndPos = -1;
                result.DBMethod = dbMethod;
                DebugDatabase.AddMethod(dbMethod);
            }

            //We do not want to output this initial comment stuff in front of 
            //  the Multiboot signature!
            //The Multiboot signature has to be the first stuff in the final
            //  ASM file
            if (aChunk.PlugASMFilePath == null || 
                !aChunk.PlugASMFilePath.Contains("Multiboot"))
            {
                if (TheSettings.DebugBuild)
                {
                    result.ASM.AppendLine("; Plugged Method"); //DEBUG INFO
                    result.ASM.AppendLine("; Method Signature : " + methodSignature); //DEBUG INFO
                    result.ASM.AppendLine("; Method ID : " + dbMethod.Id); //DEBUG INFO
                }

                if (aChunk.PlugASMFilePath == null)
                {
                    result.ASM.AppendLine("; No plug file loaded as ASM path was null");
                    return result;
                }
                else
                {
                    result.ASM.AppendLine("; " + aChunk.PlugASMFilePath);
                }
            }
            result.ASM.Append(PlugLoader.LoadPlugASM(aChunk.PlugASMFilePath, TheSettings));
            if (result.ASM == null)
            {
                throw new System.IO.FileNotFoundException("Failed to load ASM plug file! Path: " + aChunk.PlugASMFilePath);
            }
            return result;
        }
예제 #3
0
파일: ILScanner.cs 프로젝트: kztao/FlingOS
        /// <summary>
        /// Process any IL chunk (plugged or unplugged).
        /// </summary>
        /// <param name="aChunk">The IL chunk to process.</param>
        /// <returns>The resulting ASM chunk or null if processing failed.</returns>
        public ASMChunk ProcessILChunk(ILChunk aChunk)
        {
            ASMChunk result = null;
            //Process the chunk from IL to ASM
            if (aChunk.Plugged)
            {
                result = ProcessPluggedILChunk(aChunk);
            }
            else
            {
                result = ProcessUnpluggedILChunk(aChunk);
            }

            //Result could be null if processing failed
            if (result != null)
            {
                result.SequencePriority = aChunk.SequencePriority;

                //Add arguments info to debug database

                int argIndex = 0;
                if (TheSettings.DebugBuild)
                {
                    if (!aChunk.Method.IsStatic)
                    {
                        DB_Argument dbArgVar = new DB_Argument();
                        dbArgVar.BytesSize = Utils.GetNumBytesForType(aChunk.Method.DeclaringType);
                        dbArgVar.Id = Guid.NewGuid();
                        dbArgVar.Index = argIndex;
                        dbArgVar.TypeID = ProcessType(aChunk.Method.DeclaringType).Id;
                        dbArgVar.MethodID = TheScannerState.GetMethodID(aChunk.Method);
                        DebugDatabase.AddArgument(dbArgVar);
                        argIndex++;
                    }
                    ParameterInfo[] args = aChunk.Method.GetParameters();
                    foreach (ParameterInfo argItem in args)
                    {
                        DB_Argument dbArgVar = new DB_Argument();
                        dbArgVar.BytesSize = Utils.GetNumBytesForType(argItem.ParameterType);
                        dbArgVar.Id = Guid.NewGuid();
                        dbArgVar.Index = argIndex;
                        dbArgVar.TypeID = ProcessType(argItem.ParameterType).Id;
                        dbArgVar.MethodID = TheScannerState.GetMethodID(aChunk.Method);
                        DebugDatabase.AddArgument(dbArgVar);
                        argIndex++;
                    }
                }
                else
                {
                    //Must still process types info for release builds
                    if (!aChunk.Method.IsStatic)
                    {
                        ProcessType(aChunk.Method.DeclaringType);
                    }
                    ParameterInfo[] args = aChunk.Method.GetParameters();
                    foreach (ParameterInfo argItem in args)
                    {
                        ProcessType(argItem.ParameterType);
                    }
                }

                //Must add the return arg

                if (TheSettings.DebugBuild)
                {
                    ParameterInfo argItem = (aChunk.Method.IsConstructor || aChunk.Method is ConstructorInfo ? null : ((MethodInfo)aChunk.Method).ReturnParameter);
                    if (argItem == null)
                    {
                        //If arg item is null, then return type is void
                        //We still add info about the return value
                        //  so the debugger can make sense of what is happening
                        //  without unnecessary assumptions
                        DB_Argument dbArgVar = new DB_Argument();
                        dbArgVar.BytesSize = Utils.GetNumBytesForType(typeof(void));
                        dbArgVar.Id = Guid.NewGuid();
                        dbArgVar.Index = argIndex;
                        dbArgVar.TypeID = TheScannerState.GetTypeID(typeof(void));
                        dbArgVar.MethodID = TheScannerState.GetMethodID(aChunk.Method);
                        dbArgVar.IsReturnArg = true;
                        DebugDatabase.AddArgument(dbArgVar);
                    }
                    else
                    {
                        DB_Argument dbArgVar = new DB_Argument();
                        dbArgVar.BytesSize = Utils.GetNumBytesForType(argItem.ParameterType);
                        dbArgVar.Id = Guid.NewGuid();
                        dbArgVar.Index = argIndex;
                        dbArgVar.TypeID = ProcessType(argItem.ParameterType).Id;
                        dbArgVar.MethodID = TheScannerState.GetMethodID(aChunk.Method);
                        dbArgVar.IsReturnArg = true;
                        DebugDatabase.AddArgument(dbArgVar);
                    }
                }
                else
                {
                    ParameterInfo argItem = (aChunk.Method.IsConstructor || aChunk.Method is ConstructorInfo ? null : ((MethodInfo)aChunk.Method).ReturnParameter);
                    if (argItem != null)
                    {
                        ProcessType(argItem.ParameterType);
                    }
                }
            }

            return result;
        }
예제 #4
0
파일: ILReader.cs 프로젝트: kztao/FlingOS
        /// <summary>
        /// Process an unplugged method.
        /// </summary>
        /// <param name="aMethod">The method to process.</param>
        /// <param name="staticConstructorDependencyRoot">Null if method scanning is not a static constructor. Otherwise, the root node that represents the static constructor being scanned.</param>
        /// <returns>A new ILChunk with ILOpInfos and common attribites loaded. Null if any errors occur.</returns>
        /// <exception cref="System.Exception">
        /// Thrown when an unrecognised operand type is read. Can occur if MSBuild has been 
        /// updated/extended from when the kernel compiler was last updated.
        /// </exception>
        public ILChunk ProcessUnpluggedMethod(MethodBase aMethod, StaticConstructorDependency staticConstructorDependencyRoot = null)
        {
            ILChunk result = new ILChunk()
            {
                Plugged = false,
                Method = aMethod
            };

            //Pre-process common method attributes so we get information such as
            //whether to apply GC or not etc.
            ProcessCommonMethodAttributes(aMethod, result);

            //Get the method body which can then be used to get locals info and
            //IL bytes that are the IL code.
            MethodBody theMethodBody = aMethod.GetMethodBody();

            //Method body for something like [DelegateType].Invoke()
            //  is null
            if (theMethodBody == null)
            {
                //Just return empty method
                return result;
            }

            //For each local variable in this method
            foreach (LocalVariableInfo aLocal in theMethodBody.LocalVariables)
            {
                //Add it to our list of locals with some common information pre-worked out
                LocalVariable localItem = new LocalVariable()
                {
                    sizeOnStackInBytes = Utils.GetNumBytesForType(aLocal.LocalType),
                    isFloat = Utils.IsFloat(aLocal.LocalType),
                    TheType = aLocal.LocalType,
                    isGCManaged = Utils.IsGCManaged(aLocal.LocalType)
                };
                result.LocalVariables.Add(localItem);
            }


            //Used later to store location and length of the cleanup try-finally block
            int CleanUpBlock_TryOffset = 0;
            int CleanUpBlock_TryLength = 0;
            int CleanUpBlock_FinallyOffset = 0;
            int CleanUpBlock_FinallyLength = 0;
            //The "cleanup" block is the finally handler created by the IL reader that
            //calls GC.DecrementRefCount of locals and arguments as-required so that 
            //memory managed by the GC through objects gets freed correctly.
            //The try-section of the cleanup block surrounds all of the main code of the method
            //excluding the final "ret" instruction. In this way, even if an exception occurs, 
            //locals and args still get "cleaned up".
            
            //The IL bytes are the IL code.
            byte[] ILBytes = theMethodBody.GetILAsByteArray();
            //Note: IL offsets are usually calculated as the number of bytes offset from the
            //      start of the method.
            //Note: IL line numbers are IL offsets.

            //The current position in the IL bytes. 
            //This will change throughout the loop below so it always points past
            //all the bytes processed so far.
            int ILBytesPos = 0;
            //The previous position in the IL bytes.
            //This will only change in the loop below after a new IL op is created. In this way,
            //it actually points to the IL bytes position just before the new op is created.
            //That is to say, it points to the IL bytes pos of the start of the new op.
            int PrevILBytesPos = 0;

            //The previous IL op info that was created.
            //This is the latest one that was created as opposed the the one before that.
            //I.e. this is the last ILOpInfo added to the final list of IL op infos.
            ILOpInfo prevInfo = null;

            //Loop through all the IL bytes for this method...
            while (ILBytesPos < ILBytes.Length)
            {
                //The current System.Reflection.Emit.OpCode being processed
                OpCode currOpCode;
                //The unique number that identifies the op code. 
                //This number is also deliberately equivalent to Kernel.Compiler.ILOps.IlOp.OpCodes!
                ushort currOpCodeID = 0;
                //MSIL is saved such that OpIds that only require 1 byte, only use 1 byte!
                //ILBytes encoded as big-endian(?) so high bytes of the op code value (ID) come first
                //So if high byte is set to 0xFE then we need to load the next byte as low byte
                if (ILBytes[ILBytesPos] == 0xFE)
                {
                    currOpCodeID = (ushort)(0xFE00 + (short)ILBytes[ILBytesPos + 1]);
                    ILBytesPos += 2;
                }
                else
                {
                    currOpCodeID = (ushort)ILBytes[ILBytesPos];
                    ILBytesPos++;
                }
                //Load the op code from our pre-constructed list of all op codes
                currOpCode = AllOpCodes[currOpCodeID];

                int operandSize = 0;
                //Operand type tells us the operand size
                //We must:
                // a) Skip over the operand bytes so that we read the next IL op correctly
                // b) Store the operand bytes in the ILOpInfo for later use
                switch(currOpCode.OperandType)
                {
                    case OperandType.InlineBrTarget:
                        operandSize = 4;
                        break;
                    case OperandType.InlineField:
                        operandSize = 4;
                        break;
                    case OperandType.InlineI:
                        operandSize = 4;
                        break;
                    case OperandType.InlineI8:
                        operandSize = 8;
                        break;
                    case OperandType.InlineMethod:
                        operandSize = 4;
                        break;
                    case OperandType.InlineNone:
                        //No operands = no op size
                        break;
                    case OperandType.InlineR:
                        operandSize = 8;
                        break;
                    case OperandType.InlineSig:
                        operandSize = 4;
                        break;
                    case OperandType.InlineString:
                        operandSize = 4;
                        break;
                    case OperandType.InlineSwitch:
                        {
                            int count = Utils.ReadInt32(ILBytes, ILBytesPos);
                            ILBytesPos += 4;
                            operandSize = count * 4;
                        }
                        break;
                    case OperandType.InlineTok:
                        operandSize = 4;
                        break;
                    case OperandType.InlineType:
                        operandSize = 4;
                        break;
                    case OperandType.InlineVar:
                        operandSize = 2;
                        break;
                    case OperandType.ShortInlineBrTarget:
                        operandSize = 1;
                        break;
                    case OperandType.ShortInlineI:
                        operandSize = 1;
                        break;
                    case OperandType.ShortInlineR:
                        operandSize = 4;
                        break;
                    case OperandType.ShortInlineVar:
                        operandSize = 1;
                        break;
                    default:
                        throw new Exception("Unrecognised operand type!");
                }
                
                //Update the previous op with next position now that we
                //  know what that is...
                if (prevInfo != null)
                {
                    prevInfo.NextPosition = PrevILBytesPos;
                }

                //The IL reader pre-loads any methods that should be called by, for example, a call op
                //This was added so that the MethodToCall could be set by the IL reader to inject call ops
                //    - It was going to be a lot harder to try and get the "metadata token bytes" for the 
                //      method to call than to simply "pre-load" the method to call.
                MethodBase methodToCall = null;
                //Value bytes generally contain a constant value to be loaded or the bytes of a metadata token.
                //Metadata tokens can be used to retrieve information such as string literals or method infos
                //from the calling assembly.
                byte[] valueBytes = new byte[operandSize];
                //Don't bother copying 0 bytes...
                if (operandSize > 0)
                {
                    //Copy the bytes...
                    Array.Copy(ILBytes, ILBytesPos, valueBytes, 0, operandSize);

                    //If the op is one where the valueBytes are a metadata token pointing to a method:
                    if ((ILOps.ILOp.OpCodes)currOpCode.Value == ILOps.ILOp.OpCodes.Call ||
                        (ILOps.ILOp.OpCodes)currOpCode.Value == ILOps.ILOp.OpCodes.Calli ||
                        (ILOps.ILOp.OpCodes)currOpCode.Value == ILOps.ILOp.OpCodes.Callvirt ||
                        (ILOps.ILOp.OpCodes)currOpCode.Value == ILOps.ILOp.OpCodes.Ldftn ||
                        (ILOps.ILOp.OpCodes)currOpCode.Value == ILOps.ILOp.OpCodes.Newobj)
                    {
                        //Pre-load the method for reasons described above. 

                        //The metadata token that identifies the method to call in the DLL
                        //It is used to retrieve more information about the method from the DLL
                        int MethodMetadataToken = Utils.ReadInt32(valueBytes, 0);
                        //The method to call retrieved using the metasdata token
                        methodToCall = aMethod.Module.ResolveMethod(MethodMetadataToken);
                    }
                }

                //If the op being processed is a Return op and this method has GC applied:
                if ((ILOps.ILOp.OpCodes)currOpCode.Value == ILOps.ILOp.OpCodes.Ret &&
                    result.ApplyGC)
                {       
                    //We must insert the cleanup block code.

                    //Insert try-finally block around the entire method but just before Ret
                    //The finally block can then do clean-up of local variables and args
                    //1. Insert IL ops for doing locals / args cleanup
                    //2. Add the try/finally block (or just finally block if try block already exists)

                    //We must also consider the fact that just before a "ret" op, the return value is loaded.
                    //Since this cleanup block will wrap that load op, we must add code to store the return value 
                    //at the end of the try block and then re-load the return value after the finally block (but
                    //before the ret op.)

                    //Get a list of all the params to the current method
                    List<Type> allParams = result.Method.GetParameters()
                        .Select(x => x.ParameterType)
                        .ToList();
                    //If it isn't a static method:
                    if (!result.Method.IsStatic)
                    {
                        //The first param is the current instance reference.
                        allParams.Insert(0, result.Method.DeclaringType);
                    }
                    //Only insert the cleanup block if there are some params or locals to clean up.
                    //This is the first of two checks of this condition.
                    if (result.LocalVariables.Count > 0 ||
                        allParams.Count > 0)
                    {
                        //As per above we need to check for return value
                        LocalVariable returnValVariable = null;
                        //Return type of constructor is void, so only check proper methods
                        if(result.Method is MethodInfo)
                        {
                            Type returnType = ((MethodInfo)result.Method).ReturnType;
                            //Void return type = no return value
                            if(returnType != typeof(void))
                            {
                                //Add a new local variable for storing the return value
                                returnValVariable = new LocalVariable()
                                {
                                    isFloat = Utils.IsFloat(returnType),
                                    sizeOnStackInBytes = Utils.GetNumBytesForType(returnType),
                                    TheType = returnType,
                                    isGCManaged = Utils.IsGCManaged(returnType)
                                };
                                result.LocalVariables.Add(returnValVariable);
                                //This will become the penultimate IL op of the try-block
                                //It will immediately follow the op just before ret which 
                                //  will have loaded the return value or, at the very least,
                                //  the top-most item on the stack is the return value
                                //This op stores that return value in our new local variable
                                //  for reload after the finally block has completed.
                                result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                                {
                                    opCode = OpCodes.Stloc,
                                    Position = PrevILBytesPos++,
                                    NextPosition = PrevILBytesPos,
                                    ValueBytes = BitConverter.GetBytes(result.LocalVariables.IndexOf(returnValVariable))
                                });
                            }
                        }
                        //This becomes the last op of the try-block (and is required to be
                        //  the last op of a try block)
                        result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                        {
                            opCode = OpCodes.Leave_S,
                            Position = PrevILBytesPos++,
                            NextPosition = PrevILBytesPos,
                            ValueBytes = new byte[4]
                        });

                        //Try block length is now the length in IL bytes from start
                        //  (i.e. offset) to start of the current IL op. See above for
                        //  why we use PrevIlBytesPos.
                        CleanUpBlock_TryLength = PrevILBytesPos - CleanUpBlock_TryOffset;
                        //Finally offset is offset to first op of finally block i.e. 
                        //  current IL op position.
                        CleanUpBlock_FinallyOffset = PrevILBytesPos;
                        //Finally length is currently 0 - gets increased later.
                        CleanUpBlock_FinallyLength = 0;

                        //Add cleanup code for each local
                        for (int i = 0; i < result.LocalVariables.Count; i++)
                        {
                            //Clean-up local variables
                            //If the local variable is GC handled:
                            //1. Load the the local
                            //2. Call GC Dec Ref count

                            LocalVariable aVar = result.LocalVariables[i];
                            //Only add cleanup code if the local is actually GC managed.
                            if (Utils.IsGCManaged(aVar.TheType))
                            {
                                if (prevInfo != null)
                                {
                                    prevInfo.NextPosition = PrevILBytesPos;
                                }
                                //Load the local
                                result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                                {
                                    opCode = OpCodes.Ldloc,
                                    Position = PrevILBytesPos++,
                                    NextPosition = -1,
                                    ValueBytes = BitConverter.GetBytes(i)
                                });
                                prevInfo.NextPosition = PrevILBytesPos;
                                //Decrement the ref count of the local
                                result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                                {
                                    opCode = OpCodes.Call,
                                    Position = PrevILBytesPos++,
                                    NextPosition = -1,
                                    SetToGCDecRefCountMethod = true
                                });

                                CleanUpBlock_FinallyLength += 2;
                            }
                        }
                        //Add cleanup code for each arg
                        //Dec ref count of all args passed to the method 
                        for (int i = 0; i < allParams.Count; i++)
                        {
                            Type aVarType = allParams[i];
                            //Only add cleanup code if the arg is actually GC managed.
                            if (Utils.IsGCManaged(aVarType))
                            {
                                if (prevInfo != null)
                                {
                                    prevInfo.NextPosition = PrevILBytesPos;
                                }
                                result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                                {
                                    opCode = OpCodes.Ldarg,
                                    Position = PrevILBytesPos++,
                                    NextPosition = -1,
                                    ValueBytes = BitConverter.GetBytes(i)
                                });
                                prevInfo.NextPosition = PrevILBytesPos;
                                result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                                {
                                    opCode = OpCodes.Call,
                                    Position = PrevILBytesPos++,
                                    NextPosition = -1,
                                    SetToGCDecRefCountMethod = true
                                });

                                CleanUpBlock_FinallyLength += 2;
                            }
                        }

                        //Locals and args not necessarily of GC managed type
                        //  so we could potentially have cleaned up nothing
                        //This is the second of the two checks to make sure we 
                        //  only add cleanup code if there is something to cleanup
                        if (CleanUpBlock_FinallyLength > 0)
                        {
                            //If there is cleanup code, add the end of the finally block and
                            // reload the return value if necessary.

                            prevInfo.NextPosition = PrevILBytesPos;
                            result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                            {
                                opCode = OpCodes.Endfinally,
                                Position = PrevILBytesPos++,
                                NextPosition = -1
                            });
                            CleanUpBlock_FinallyLength += 1;

                            if (returnValVariable != null)
                            {
                                result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                                {
                                    opCode = OpCodes.Ldloc,
                                    Position = PrevILBytesPos++,
                                    NextPosition = PrevILBytesPos,
                                    ValueBytes = BitConverter.GetBytes(result.LocalVariables.IndexOf(returnValVariable))
                                });
                            }
                        }
                        else
                        {
                            //If there was nothing to cleanup, we need to remove 
                            //  the ops and locals etc. that got added earlier.
                            result.ILOpInfos.RemoveAt(result.ILOpInfos.Count - 1);
                            PrevILBytesPos--;

                            if(returnValVariable != null)
                            {
                                result.LocalVariables.Remove(returnValVariable);
                                result.ILOpInfos.RemoveAt(result.ILOpInfos.Count - 1);
                                PrevILBytesPos--;
                            }
                        }
                    }
                }

                if (staticConstructorDependencyRoot != null)
                {
                    //Create our static constructor dependency tree
                    
                    //Each of these ops could try to access a static method or field
                    switch((ILOps.ILOp.OpCodes)currOpCode.Value)
                    {
                        case ILOps.ILOp.OpCodes.Call:
                            //Check if the method to call is static and not a constructor itself
                            //If so, we must add the declaring type's static constructors to the tree
                            {
                                int metadataToken = Utils.ReadInt32(valueBytes, 0);
                                MethodBase methodBaseInf = aMethod.Module.ResolveMethod(metadataToken);
                                if(!(methodBaseInf.IsConstructor || methodBaseInf is ConstructorInfo))
                                {
                                    MethodInfo methodInf = (MethodInfo)methodBaseInf;
                                    ConstructorInfo[] staticConstructors = methodInf.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.Public)
                                                               .Concat(methodInf.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic))
                                                               .ToArray();
                                    if (staticConstructors.Length > 0)
                                    {
                                        ConstructorInfo TheConstructor = staticConstructors[0];
                                        if (staticConstructorDependencyRoot[TheConstructor] == null)
                                        {
                                            staticConstructorDependencyRoot.Children.Add(new StaticConstructorDependency()
                                            {
                                                TheConstructor = TheConstructor
                                            });
                                        }
                                    }
                                }
                            }
                            break;
                        case ILOps.ILOp.OpCodes.Ldsfld:
                        case ILOps.ILOp.OpCodes.Ldsflda:
                        case ILOps.ILOp.OpCodes.Stsfld:
                            {
                                int metadataToken = Utils.ReadInt32(valueBytes, 0);
                                FieldInfo fieldInf = aMethod.Module.ResolveField(metadataToken);
                                ConstructorInfo[] staticConstructors = fieldInf.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.Public)
                                                               .Concat(fieldInf.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic))
                                                               .ToArray();
                                if(staticConstructors.Length > 0)
                                {
                                    ConstructorInfo TheConstructor = staticConstructors[0];
                                    if (staticConstructorDependencyRoot[TheConstructor] == null)
                                    {
                                        staticConstructorDependencyRoot.Children.Add(new StaticConstructorDependency()
                                        {
                                            TheConstructor = TheConstructor
                                        });
                                    }
                                }
                            }
                            break;
                    }
                }

                //Add the IL op
                result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                {
                    opCode = currOpCode,
                    Position = PrevILBytesPos,
                    // Next position set to -1 indicates no next op
                    NextPosition = -1,
                    ValueBytes = valueBytes,
                    MethodToCall = methodToCall
                });

                ILBytesPos += operandSize;
                PrevILBytesPos = ILBytesPos;
            }
            prevInfo.NextPosition = PrevILBytesPos;
            
            //Add the exception handlers (excluding Cleanup try-finally block - see below)
            foreach (ExceptionHandlingClause aClause in theMethodBody.ExceptionHandlingClauses)
            {
                ExceptionHandledBlock exBlock = result.GetExactExceptionHandledBlock(aClause.TryOffset);
                if (exBlock == null)
                {
                    exBlock = new ExceptionHandledBlock();
                    exBlock.Offset = aClause.TryOffset;
                    exBlock.Length = aClause.TryLength;
                    result.ExceptionHandledBlocks.Add(exBlock);
                }

                switch (aClause.Flags)
                {
                    case ExceptionHandlingClauseOptions.Fault:
                    case ExceptionHandlingClauseOptions.Clause:
                        {
                            CatchBlock catchBlock = new CatchBlock()
                            {
                                Offset = aClause.HandlerOffset,
                                Length = aClause.HandlerLength,
                                //Though not used, we may as well set it anyway
                                FilterType = aClause.CatchType
                            };
                            exBlock.CatchBlocks.Add(catchBlock);
                        }
                        break;
                    case ExceptionHandlingClauseOptions.Finally:
                        {
                            FinallyBlock finallyBlock = new FinallyBlock()
                            {
                                Offset = aClause.HandlerOffset,
                                Length = aClause.HandlerLength
                            };
                            exBlock.FinallyBlocks.Add(finallyBlock);
                        }
                        break;
                    default:
                        OutputError(new NotSupportedException("Exception handling clause not supported! Type: " + aClause.Flags.ToString()));
                        break;
                }
            }

            //Add the cleanup try-finally block
            //Only add the block if try-section has non-zero length and
            //  if the finally block has more than just the endfinally op
            if (CleanUpBlock_TryLength != 0 &&
                CleanUpBlock_FinallyLength > 1)
            {
                ExceptionHandledBlock cleanUpTryBlock = new ExceptionHandledBlock()
                {
                    Offset = CleanUpBlock_TryOffset,
                    Length = CleanUpBlock_TryLength
                };
                FinallyBlock cleanupFinallyBlock = new FinallyBlock()
                {
                    Offset = CleanUpBlock_FinallyOffset,
                    Length = CleanUpBlock_FinallyLength,
                };
                cleanUpTryBlock.FinallyBlocks.Add(cleanupFinallyBlock);
                result.ExceptionHandledBlocks.Add(cleanUpTryBlock);
            }
                            
            return result;
        }
예제 #5
0
파일: ILReader.cs 프로젝트: kztao/FlingOS
        /// <summary>
        /// Process a plugged method.
        /// </summary>
        /// <param name="aMethod">The method to process.</param>
        /// <returns>A new ILChunk marked as plugged with common attribites loaded. Null if any errors occur.</returns>
        public ILChunk ProcessPluggedMethod(MethodBase aMethod)
        {
            ILChunk result = null;
            PluggedMethodAttribute plugAttr = (PluggedMethodAttribute)aMethod.GetCustomAttribute(typeof(PluggedMethodAttribute));
            //Resolve the ASMPlugPath to be relative to the assembly file that the method came from
            string ASMPlugPath = plugAttr.ASMFilePath;
            //Null path will result in no load attempt
            //Allows multiple methods to be plugged by the same ASM file
            if (ASMPlugPath == null)
            {
                result = new ILChunk()
                {
                    Plugged = true,
                    PlugASMFilePath = null,
                    Method = aMethod
                };
                ProcessCommonMethodAttributes(aMethod, result);
                return result;
            }

            string assemblyPath = aMethod.DeclaringType.Assembly.Location;
            assemblyPath = Path.GetDirectoryName(assemblyPath);
            ASMPlugPath = Path.Combine(assemblyPath, ASMPlugPath);
            if (ASMPlugPath.EndsWith("\\"))
            {
                ASMPlugPath = ASMPlugPath.Substring(0, ASMPlugPath.Length - 1);
            }
            result = new ILChunk()
                {
                    Plugged = true,
                    PlugASMFilePath = ASMPlugPath,
                    Method = aMethod
                };
            ProcessCommonMethodAttributes(aMethod, result);
            return result;
        }
예제 #6
0
파일: ILReader.cs 프로젝트: kztao/FlingOS
        /// <summary>
        /// Processes attributes that are common to both plugged and unplugged methods.
        /// </summary>
        /// <param name="aMethod">The method to process attributes of.</param>
        /// <param name="aChunk">The ILChunk to load attributes' info into.</param>
        private void ProcessCommonMethodAttributes(MethodBase aMethod, ILChunk aChunk)
        {
            SequencePriorityAttribute seqPriorityAttr = (SequencePriorityAttribute)aMethod.GetCustomAttribute(typeof(SequencePriorityAttribute));
            if (seqPriorityAttr != null)
            {
                aChunk.SequencePriority = seqPriorityAttr.Priority;
            }
            else
            {
                aChunk.SequencePriority = 0;
            }
            NoGCAttribute noGCAttr = (NoGCAttribute)aMethod.GetCustomAttribute(typeof(NoGCAttribute));
            if (noGCAttr != null)
            {
                aChunk.ApplyGC = false;
            }

            NoDebugAttribute noDebugAttr = (NoDebugAttribute)aMethod.GetCustomAttribute(typeof(NoDebugAttribute));
            if (noDebugAttr != null)
            {
                aChunk.NoDebugOps = true;
            }

            KernelMainMethodAttribute kernelMainMethodAttr = (KernelMainMethodAttribute)aMethod.GetCustomAttribute(typeof(KernelMainMethodAttribute));
            if (kernelMainMethodAttr != null)
            {
                aChunk.IsMainMethod = true;
            }
            CallStaticConstructorsMethodAttribute callStaticConstructorsMethodAttr = (CallStaticConstructorsMethodAttribute)aMethod.GetCustomAttribute(typeof(CallStaticConstructorsMethodAttribute));
            if (callStaticConstructorsMethodAttr != null)
            {
                aChunk.IsCallStaticConstructorsMethod = true;
            }
            AddExceptionHandlerInfoMethodAttribute addExceptionHandlerInfoMethodAttr = (AddExceptionHandlerInfoMethodAttribute)aMethod.GetCustomAttribute(typeof(AddExceptionHandlerInfoMethodAttribute));
            if (addExceptionHandlerInfoMethodAttr != null)
            {
                aChunk.IsAddExceptionHandlerInfoMethod = true;
            }
            ExceptionsHandleLeaveMethodAttribute exceptionsHandleLeaveMethodAttr = (ExceptionsHandleLeaveMethodAttribute)aMethod.GetCustomAttribute(typeof(ExceptionsHandleLeaveMethodAttribute));
            if (exceptionsHandleLeaveMethodAttr != null)
            {
                aChunk.IsExceptionsHandleLeaveMethod = true;
            }
            ExceptionsHandleEndFinallyMethodAttribute exceptionsHandleEndFinallyMethodAttr = (ExceptionsHandleEndFinallyMethodAttribute)aMethod.GetCustomAttribute(typeof(ExceptionsHandleEndFinallyMethodAttribute));
            if (exceptionsHandleEndFinallyMethodAttr != null)
            {
                aChunk.IsExceptionsHandleEndFinallyMethod = true;
            }
            ThrowExceptionMethodAttribute throwExceptionMethodAttr = (ThrowExceptionMethodAttribute)aMethod.GetCustomAttribute(typeof(ThrowExceptionMethodAttribute));
            if (throwExceptionMethodAttr != null)
            {
                aChunk.IsExceptionsThrowMethod = true;
            }
            ThrowNullReferenceExceptionMethodAttribute throwNullReferenceExceptionMethodAttr = (ThrowNullReferenceExceptionMethodAttribute)aMethod.GetCustomAttribute(typeof(ThrowNullReferenceExceptionMethodAttribute));
            if (throwNullReferenceExceptionMethodAttr != null)
            {
                aChunk.IsExceptionsThrowNullReferenceMethod = true;
            }
            ThrowArrayTypeMismatchExceptionMethodAttribute throwArrayTypeMismatchExceptionMethodAttr = (ThrowArrayTypeMismatchExceptionMethodAttribute)aMethod.GetCustomAttribute(typeof(ThrowArrayTypeMismatchExceptionMethodAttribute));
            if (throwArrayTypeMismatchExceptionMethodAttr != null)
            {
                aChunk.IsExceptionsThrowArrayTypeMismatchMethod = true;
            }
            ThrowIndexOutOfRangeExceptionMethodAttribute throwIndexOutOfRangeExceptionMethodAttr = (ThrowIndexOutOfRangeExceptionMethodAttribute)aMethod.GetCustomAttribute(typeof(ThrowIndexOutOfRangeExceptionMethodAttribute));
            if (throwIndexOutOfRangeExceptionMethodAttr != null)
            {
                aChunk.IsExceptionsThrowIndexOutOfRangeMethod = true;
            }
            HandleExceptionMethodAttribute handleExceptionMethodAttr = (HandleExceptionMethodAttribute)aMethod.GetCustomAttribute(typeof(HandleExceptionMethodAttribute));
            if (handleExceptionMethodAttr != null)
            {
                aChunk.IsExceptionsHandleExceptionMethod = true;
            }
            NewObjMethodAttribute newObjMethodAttr = (NewObjMethodAttribute)aMethod.GetCustomAttribute(typeof(NewObjMethodAttribute));
            if (newObjMethodAttr != null)
            {
                aChunk.IsNewObjMethod = true;
            }
            NewArrMethodAttribute newArrMethodAttr = (NewArrMethodAttribute)aMethod.GetCustomAttribute(typeof(NewArrMethodAttribute));
            if (newArrMethodAttr != null)
            {
                aChunk.IsNewArrMethod = true;
            }
            IncrementRefCountMethodAttribute incrementRefCountMethodAttr = (IncrementRefCountMethodAttribute)aMethod.GetCustomAttribute(typeof(IncrementRefCountMethodAttribute));
            if (incrementRefCountMethodAttr != null)
            {
                aChunk.IsIncrementRefCountMethod = true;
            }
            DecrementRefCountMethodAttribute decrementRefCountMethodAttr = (DecrementRefCountMethodAttribute)aMethod.GetCustomAttribute(typeof(DecrementRefCountMethodAttribute));
            if (decrementRefCountMethodAttr != null)
            {
                aChunk.IsDecrementRefCountMethod = true;
            }
            HaltMethodAttribute haltMethodAttr = (HaltMethodAttribute)aMethod.GetCustomAttribute(typeof(HaltMethodAttribute));
            if (haltMethodAttr != null)
            {
                aChunk.IsHaltMethod = true;
            }
            ArrayConstructorMethodAttribute arrayConstructorMethodAttr = (ArrayConstructorMethodAttribute)aMethod.GetCustomAttribute(typeof(ArrayConstructorMethodAttribute));
            if (arrayConstructorMethodAttr != null)
            {
                aChunk.IsArrayConstructorMethod = true;
            }
        }