private static void WriteIlAndNative(ILDasmIterator ilDasm, Il2NativeIterator il2nativeIterator, int ilEndOffset)
 {
     while (ilDasm.IlOffset < ilEndOffset)
     {
         ilDasm.WriteIl();
         il2nativeIterator.WriteNative(ilDasm.IlOffset);
         ilDasm.Next();
     }
 }
        // parent - main containing window that this source window lives inside of.
        // function - function for which we're building virtual source around.
        // Get the IL from the given frame.
        // Called on UI thread.
        internal VirtualSourceViewerForm(MainForm parent, MDbgFunction function)
        {
            m_function = function;
            Debug.Assert(function != null);

            // Now actually right in text. do this first so that we can get the current font.
            BeginInit(parent);

            // Get fonts
            FontCache cache;
            {
                Font fontCurrent = this.richText.Font;
                Font emphasis = new Font(
                                   fontCurrent.FontFamily,
                                   fontCurrent.Size,
                                   FontStyle.Bold
                                );

                cache = new FontCache(emphasis);
            }

            // Underlying writer to the window.
            RawWriter rawWriter = new RawWriter(cache);

            // Il2Native mapping can be used to find out what IL offsets we can actually stop on.
            Il2NativeIterator il2nativeIterator = null;

            // Actual IL disassembly in string form.
            ILDasmIterator ilDasm = null;

            // Iterator through sequence points and source files.
            SequencePointIterator seqIterator = null;

            string fullName = "?";
            int token = 0;

            ulong nativeStartAddress = 0;
            CorDebugJITCompilerFlags codeFlags = CorDebugJITCompilerFlags.CORDEBUG_JIT_DEFAULT;

            // Make cross-thread call to worker thread to collect raw information.
            // This needs to access MDbg and so can't be done on our UI thread.
            parent.ExecuteOnWorkerThreadIfStoppedAndBlock(delegate(MDbgProcess proc)
            {
                Debug.Assert(proc != null);
                Debug.Assert(!proc.IsRunning);
                Debug.Assert(function.Module.Process == proc);

                // Get some properties about this function to display.
                token = function.CorFunction.Token;
                nativeStartAddress = function.CorFunction.NativeCode.Address;
                codeFlags = function.CorFunction.NativeCode.CompilerFlags;

                CorCode ilCode = function.CorFunction.ILCode;
                Debug.Assert(true == ilCode.IsIL);
                byte[] code = ilCode.GetCode();
                fullName = function.FullName;

                // This does the real disassembly work.
                string[] lines = null; // strings of IL.
                ILDisassembler.Disassemble(code, function.Module.Importer, out lines, out m_il2RowMapping);

                ilDasm = new ILDasmIterator(rawWriter, m_il2RowMapping, lines);

                IL2NativeMap[] il2nativeMapping = function.CorFunction.NativeCode.GetILToNativeMapping();
                il2nativeIterator = new Il2NativeIterator(rawWriter, il2nativeMapping, code);

                // Get sequence points
                ISymbolMethod symMethod = function.SymMethod;

                // Sequence point information
                int[] seqIlOffsets = null;
                string[] seqPaths = null;
                int[] seqStartLines = null, seqEndLines = null, seqStartColumns = null, seqEndColumns = null;
                int seqCount = 0;

                if (symMethod != null)
                {
                    seqCount = symMethod.SequencePointCount;
                    seqIlOffsets = new int[seqCount];
                    ISymbolDocument[] seqDocuments = new ISymbolDocument[seqCount];
                    seqPaths = new string[seqCount];
                    seqStartLines = new int[seqCount];
                    seqEndLines = new int[seqCount];
                    seqStartColumns = new int[seqCount];
                    seqEndColumns = new int[seqCount];

                    symMethod.GetSequencePoints(seqIlOffsets, seqDocuments, seqStartLines, seqStartColumns, seqEndLines, seqEndColumns);

                    for (int i = 0; i < seqCount; i++)
                    {
                        seqPaths[i] = seqDocuments[i].URL;
                    }
                }
                seqIterator = new SequencePointIterator(rawWriter, parent, seqIlOffsets, seqPaths, seqStartLines, seqStartColumns, seqEndLines, seqEndColumns);
            }
            ); // end worker call

            // We assume sequence points are sorted by IL offset. We assert that in the iterators below.
            // Now we need to go through and stitch the IL + Source together.
            // This also works even if we have no source (since that's just the degenerate case of 0 sequence points)

            // Print out header information
            Debug.Assert(token != 0);
            rawWriter.WriteLine(String.Format(CultureInfo.InvariantCulture,
                "> Function name:{0} (token={1:x})", fullName, token));
            rawWriter.WriteLine(String.Format(CultureInfo.InvariantCulture,
                "> Native Code Address =0x{0:x}, flags={1}", nativeStartAddress, codeFlags));

            // Walk through the IL in order and write out interleaved IL and Sequence Points.
            while (!seqIterator.IsDone)
            {
                // Add IL snippets that occur before this sequence point.
                WriteIlAndNative(ilDasm, il2nativeIterator, seqIterator.IlOffset);

                seqIterator.WriteSource();
                seqIterator.Next();
            }
            // Write the IL that's after the last sequence point
            WriteIlAndNative(ilDasm, il2nativeIterator, ilDasm.IlLength);

            // Set the text.
            InitLines(null, rawWriter.Lines, rawWriter.FormatList);

            EndInit(fullName);
        }
 // Helper to write the IL and corresponding native code up to the end offset
 static void WriteIlAndNative(ILDasmIterator ilDasm, Il2NativeIterator il2nativeIterator, int ilEndOffset)
 {
     while (ilDasm.IlOffset < ilEndOffset)
     {
         ilDasm.WriteIl();
         il2nativeIterator.WriteNative(ilDasm.IlOffset);
         ilDasm.Next();
     }
 }
        internal VirtualSourceViewerForm(MainForm parent, MDbgFunction function)
        {
            m_function = function;
            Debug.Assert(function != null);

            // Now actually right in text. do this first so that we can get the current font.
            BeginInit(parent);

            // Get fonts
            FontCache cache;
            {
                Font fontCurrent = richText.Font;
                var  emphasis    = new Font(
                    fontCurrent.FontFamily,
                    fontCurrent.Size,
                    FontStyle.Bold
                    );

                cache = new FontCache(emphasis);
            }

            // Underlying writer to the window.
            var rawWriter = new RawWriter(cache);

            // Il2Native mapping can be used to find out what IL offsets we can actually stop on.
            Il2NativeIterator il2nativeIterator = null;

            // Actual IL disassembly in string form.
            ILDasmIterator ilDasm = null;

            // Iterator through sequence points and source files.
            SequencePointIterator seqIterator = null;

            string fullName = "?";
            int    token    = 0;

            ulong nativeStartAddress           = 0;
            CorDebugJITCompilerFlags codeFlags = CorDebugJITCompilerFlags.CORDEBUG_JIT_DEFAULT;

            // Make cross-thread call to worker thread to collect raw information.
            // This needs to access MDbg and so can't be done on our UI thread.
            parent.ExecuteOnWorkerThreadIfStoppedAndBlock(delegate(MDbgProcess proc)
            {
                Debug.Assert(proc != null);
                Debug.Assert(!proc.IsRunning);
                Debug.Assert(function.Module.Process == proc);

                // Get some properties about this function to display.
                token = function.CorFunction.Token;
                nativeStartAddress =
                    function.CorFunction.NativeCode.Address;
                codeFlags =
                    function.CorFunction.NativeCode.CompilerFlags;


                CorCode ilCode = function.CorFunction.ILCode;
                Debug.Assert(ilCode.IsIL);
                byte[] code = ilCode.GetCode();
                fullName    = function.FullName;

                // This does the real disassembly work.
                string[] lines = null;                                                   // strings of IL.
                ILDisassembler.Disassemble(code,
                                           function.Module.Importer,
                                           out lines,
                                           out m_il2RowMapping);

                ilDasm = new ILDasmIterator(rawWriter, m_il2RowMapping,
                                            lines);

                IL2NativeMap[] il2nativeMapping =
                    function.CorFunction.NativeCode.
                    GetILToNativeMapping();
                il2nativeIterator = new Il2NativeIterator(rawWriter,
                                                          il2nativeMapping,
                                                          code);

                // Get sequence points
                ISymbolMethod symMethod = function.SymMethod;

                // Sequence point information
                int[] seqIlOffsets  = null;
                string[] seqPaths   = null;
                int[] seqStartLines = null,
                seqEndLines         = null,
                seqStartColumns     = null,
                seqEndColumns       = null;
                int seqCount        = 0;

                if (symMethod != null)
                {
                    seqCount         = symMethod.SequencePointCount;
                    seqIlOffsets     = new int[seqCount];
                    var seqDocuments = new ISymbolDocument[seqCount];
                    seqPaths         = new string[seqCount];
                    seqStartLines    = new int[seqCount];
                    seqEndLines      = new int[seqCount];
                    seqStartColumns  = new int[seqCount];
                    seqEndColumns    = new int[seqCount];

                    symMethod.GetSequencePoints(seqIlOffsets,
                                                seqDocuments,
                                                seqStartLines,
                                                seqStartColumns,
                                                seqEndLines,
                                                seqEndColumns);

                    for (int i = 0; i < seqCount; i++)
                    {
                        seqPaths[i] = seqDocuments[i].URL;
                    }
                }
                seqIterator = new SequencePointIterator(rawWriter,
                                                        parent,
                                                        seqIlOffsets,
                                                        seqPaths,
                                                        seqStartLines,
                                                        seqStartColumns,
                                                        seqEndLines,
                                                        seqEndColumns);
            }
                                                          ); // end worker call

            // We assume sequence points are sorted by IL offset. We assert that in the iterators below.
            // Now we need to go through and stitch the IL + Source together.
            // This also works even if we have no source (since that's just the degenerate case of 0 sequence points)

            // Print out header information
            Debug.Assert(token != 0);
            rawWriter.WriteLine(String.Format(CultureInfo.InvariantCulture,
                                              "> Function name:{0} (token={1:x})", fullName, token));
            rawWriter.WriteLine(String.Format(CultureInfo.InvariantCulture,
                                              "> Native Code Address =0x{0:x}, flags={1}", nativeStartAddress, codeFlags));

            // Walk through the IL in order and write out interleaved IL and Sequence Points.
            while (!seqIterator.IsDone)
            {
                // Add IL snippets that occur before this sequence point.
                WriteIlAndNative(ilDasm, il2nativeIterator, seqIterator.IlOffset);

                seqIterator.WriteSource();
                seqIterator.Next();
            }
            // Write the IL that's after the last sequence point
            WriteIlAndNative(ilDasm, il2nativeIterator, ilDasm.IlLength);


            // Set the text.
            InitLines(null, rawWriter.Lines, rawWriter.FormatList);

            EndInit(fullName);
        }