public MethodDebugInfo(MethodBody body, ISymbolMethod pdb)
        {
            Body = body;

            // todo. support multiple locals sharing the same local slot
            // (but having different Start::End offsets, of course)
            // so far we just silently ignore them taking into account only the first one
            var locals = pdb.RootScope.Flatten(ss => ss.GetChildren()).SelectMany(ss => ss.GetLocals());

            LocalNames = locals.Select(lv => new { Index = lv.AddressField1, Name = lv.Name })
                         .Distinct().ToDictionary(lv => lv.Index, lv => lv.Name).ToReadOnly();

            var count      = pdb.SequencePointCount;
            var offsets    = new int[count];
            var documents  = new ISymbolDocument[count];
            var lines      = new int[count];
            var columns    = new int[count];
            var endLines   = new int[count];
            var endColumns = new int[count];

            pdb.GetSequencePoints(offsets, documents, lines, columns, endLines, endColumns);

            SequencePoints = 0.UpTo(count - 1).Select(i =>
                                                      new SequencePoint(offsets[i], documents[i], lines[i], columns[i], endLines[i], endColumns[i])
                                                      ).ToReadOnly();
        }
Beispiel #2
0
        void AddSequencePoints(CilBody body, ISymbolMethod method)
        {
            int numSeqs    = method.SequencePointCount;
            var offsets    = new int[numSeqs];
            var documents  = new ISymbolDocument[numSeqs];
            var lines      = new int[numSeqs];
            var columns    = new int[numSeqs];
            var endLines   = new int[numSeqs];
            var endColumns = new int[numSeqs];

            method.GetSequencePoints(offsets, documents, lines, columns, endLines, endColumns);

            int instrIndex = 0;

            for (int i = 0; i < numSeqs; i++)
            {
                var instr = GetInstruction(body.Instructions, offsets[i], ref instrIndex);
                if (instr == null)
                {
                    continue;
                }
                var seqPoint = new SequencePoint()
                {
                    Document    = Add_NoLock(new PdbDocument(documents[i])),
                    StartLine   = lines[i],
                    StartColumn = columns[i],
                    EndLine     = endLines[i],
                    EndColumn   = endColumns[i],
                };
                instr.SequencePoint = seqPoint;
            }
        }
        public SequencePoint[] Generate(ISymbolMethod method)
        {
            var sequencePoints = new List<SequencePoint>();
            var sp_count = method.SequencePointCount;
            var spOffsets = new int[sp_count]; // Array.CreateInstance(int, sp_count)
            var spDocs = new ISymbolDocument[sp_count]; // Array.CreateInstance(ISymbolDocument, sp_count)
            var spStartLines = new int[sp_count]; // Array.CreateInstance(int, sp_count)
            var spEndLines = new int[sp_count]; // Array.CreateInstance(int, sp_count)
            var spStartCol = new int[sp_count]; // Array.CreateInstance(int, sp_count)
            var spEndCol = new int[sp_count]; // Array.CreateInstance(int, sp_count)

            method.GetSequencePoints(spOffsets, spDocs, spStartLines, spStartCol, spEndLines, spEndCol);

            for (int i = 0; i < sp_count; i++) // (var i in range(sp_count))
            {
                if (spStartLines[i] != 0xfeefee) // if spStartLines[i] != 0xfeefee:
                {
                    sequencePoints.Add(new SequencePoint(spOffsets[i],
                                                         spDocs[i],
                                                         spStartLines[i],
                                                         spStartCol[i],
                                                         spEndLines[i],
                                                         spEndCol[i]));
                }
            }
            return sequencePoints.ToArray();
        }
        // Write the sequence points for the given method
        // Sequence points are the map between IL offsets and source lines.
        // A single method could span multiple files (use C#'s #line directive to see for yourself).
        private SequencePoint[] ReadSequencePoints(ISymbolMethod method)
        {
            int count = method.SequencePointCount;

            // Get the sequence points from the symbol store.
            // We could cache these arrays and reuse them.
            int[]             offsets     = new int[count];
            ISymbolDocument[] docs        = new ISymbolDocument[count];
            int[]             startColumn = new int[count];
            int[]             endColumn   = new int[count];
            int[]             startRow    = new int[count];
            int[]             endRow      = new int[count];
            method.GetSequencePoints(offsets, docs, startRow, startColumn, endRow, endColumn);

            // Store them into the list
            var sequencePoints = new List <SequencePoint>(count);

            for (int i = 0; i < count; i++)
            {
                var sp = new SequencePoint(offsets[i], docs[i].URL, startRow[i], endRow[i], startColumn[i], endColumn[i]);
                sequencePoints.Add(sp);
            }

            return(sequencePoints.OrderBy(sp => sp.SourcePath).ThenBy(sp => sp.StartLine).ToArray());
        }
Beispiel #5
0
        static void Main(string[] args)
        {
            Assembly      ass       = Assembly.GetExecutingAssembly();
            ISymbolReader symreader = SymUtil.GetSymbolReaderForFile(ass.Location, null);

            MethodInfo    m   = ass.GetType("PdbTest.TestClass").GetMethod("GetStringRepresentation");
            ISymbolMethod met = symreader.GetMethod(new SymbolToken(m.MetadataToken));

            int count = met.SequencePointCount;

            ISymbolDocument[] docs       = new ISymbolDocument[count];
            int[]             offsets    = new int[count];
            int[]             lines      = new int[count];
            int[]             columns    = new int[count];
            int[]             endlines   = new int[count];
            int[]             endcolumns = new int[count];

            met.GetSequencePoints(offsets, docs, lines, columns, endlines, endcolumns);

            StreamReader reader = new StreamReader(docs[0].URL);

            string[] linesOfCode = reader.ReadToEnd().Split('n');
            reader.Close();

            Console.WriteLine("The content of method PdbTest.TestClass.GetStringRepresentation");
            for (int i = lines[0]; i < endlines[count - 1] - 1; i++)
            {
                Console.WriteLine(linesOfCode[i]);
            }
        }
Beispiel #6
0
        //�Public�Methods�(1)�

        /// <summary>
        /// Gets the method source from PDB.
        /// </summary>
        /// <param name="methodInfo">The method info.</param>
        /// <returns></returns>
        public PDBMethodSourceData GetMethodSourceFromPDB(MethodInfo methodInfo)
        {
            ISymbolMethod met = _symbolReader.GetMethod(new SymbolToken(methodInfo.MetadataToken));

            int count = met.SequencePointCount;

            ISymbolDocument[] docs       = new ISymbolDocument[count];
            int[]             offsets    = new int[count];
            int[]             lines      = new int[count];
            int[]             columns    = new int[count];
            int[]             endlines   = new int[count];
            int[]             endcolumns = new int[count];

            met.GetSequencePoints(offsets, docs, lines, columns, endlines, endcolumns);

            return(new PDBMethodSourceData()
            {
                symbolDocs = docs,
                sourceCodeLines = lines,
                ilOpcodeOffsets = offsets,
                souceCodeColumns = columns,
                sourceCodeEndColumns = endcolumns,
                sourceCodeEndLines = endlines
            });
        }
Beispiel #7
0
            /// <summary>
            /// Returns the name of the file for the given method using the given symbol reader
            /// </summary>
            /// <param name="reader">The reader to use</param>
            /// <param name="methodBase">The method to lookup</param>
            /// <returns>The file containing the method or null.</returns>
            private static string GetFileForMethod(ISymbolReader reader, MethodBase methodBase)
            {
                int token = methodBase.MetadataToken;

                ISymbolMethod methodSymbol = reader == null ? null : reader.GetMethod(new SymbolToken(token));

                if (methodSymbol != null)
                {
                    int count = methodSymbol.SequencePointCount;

                    // Get the sequence points from the symbol store.
                    // We could cache these arrays and reuse them.
                    int[]             offsets     = new int[count];
                    ISymbolDocument[] docs        = new ISymbolDocument[count];
                    int[]             startColumn = new int[count];
                    int[]             endColumn   = new int[count];
                    int[]             startRow    = new int[count];
                    int[]             endRow      = new int[count];
                    methodSymbol.GetSequencePoints(offsets, docs, startRow, startColumn, endRow, endColumn);

                    foreach (ISymbolDocument doc in docs)
                    {
                        string file = doc.URL.ToString();
                        return(file);
                    }
                }
                return(null);
            }
Beispiel #8
0
        public static IEnumerable <SequencePoint> GetSequencePoints(this ISymbolMethod met)
        {
            int sc = met.SequencePointCount;

            int[]             offsets    = new int[sc];
            int[]             lines      = new int[sc];
            int[]             endLines   = new int[sc];
            int[]             columns    = new int[sc];
            int[]             endColumns = new int[sc];
            ISymbolDocument[] docs       = new ISymbolDocument[sc];
            met.GetSequencePoints(offsets, docs, lines, columns, endLines, endColumns);

            for (int n = 0; n < sc; n++)
            {
                if (columns[n] == 0)
                {
                    continue;
                }
                SequencePoint sp = new SequencePoint();
                sp.Document = docs[n];
                sp.Line     = lines[n];
                sp.Offset   = offsets[n];
                yield return(sp);
            }
        }
Beispiel #9
0
        // note: sadly it's not possible to cache all the [count] allocations and reuse them.
        // a NRE is throw if the size of the arrays does not match SequencePointCount :(
        void ReadSequencePoints(ISymbolMethod method, IDictionary instructions)
        {
            int count = method.SequencePointCount;

            int []             offsets     = new int [count];
            ISymbolDocument [] docs        = new ISymbolDocument [count];
            int []             startColumn = new int [count];
            int []             endColumn   = new int [count];
            int []             startRow    = new int [count];
            int []             endRow      = new int [count];
            method.GetSequencePoints(offsets, docs, startRow, startColumn, endRow, endColumn);

            for (int i = 0; i < offsets.Length; i++)
            {
                Cil.Instruction instr = (Cil.Instruction)instructions [offsets [i]];

                Cil.SequencePoint sp = new Cil.SequencePoint(GetDocument(docs [i]));
                sp.StartLine   = startRow [i];
                sp.StartColumn = startColumn [i];
                sp.EndLine     = endRow [i];
                sp.EndColumn   = endColumn [i];

                instr.SequencePoint = sp;
            }
        }
Beispiel #10
0
        // Initializes all private symbol variables
        private void SetupSymbolInformation()
        {
            if (p_symbolsInitialized)
            {
                return;
            }

            p_symbolsInitialized = true;
            CorModule     module    = GetModule();
            ISymbolReader symreader = module.GetSymbolReader();

            p_hasSymbols = symreader != null;
            if (p_hasSymbols)
            {
                ISymbolMethod sm = null;
                sm = symreader.GetMethod(new SymbolToken((Int32)GetToken())); // FIXME add version
                if (sm == null)
                {
                    p_hasSymbols = false;
                    return;
                }
                p_symMethod      = sm;
                p_SPcount        = p_symMethod.SequencePointCount;
                p_SPoffsets      = new Int32[p_SPcount];
                p_SPdocuments    = new ISymbolDocument[p_SPcount];
                p_SPstartLines   = new Int32[p_SPcount];
                p_SPendLines     = new Int32[p_SPcount];
                p_SPstartColumns = new Int32[p_SPcount];
                p_SPendColumns   = new Int32[p_SPcount];

                p_symMethod.GetSequencePoints(p_SPoffsets, p_SPdocuments, p_SPstartLines,
                                              p_SPstartColumns, p_SPendLines, p_SPendColumns);
            }
        }
Beispiel #11
0
 /// <summary>
 /// Gets information about the source if it is available.
 /// </summary>
 private bool GetSourceReference()
 {
     try
     {
         ISymbolReader sr = SymUtil.GetSymbolReaderForFile(_method.Module.Assembly.Location, null);
         ISymbolMethod sm = sr.GetMethod(new SymbolToken(_method.MetadataToken));
         _count        = sm.SequencePointCount;
         _offsets      = new int[_count];
         _documents    = new ISymbolDocument[_count];
         _startColumns = new int[_count];
         _endColumns   = new int[_count];
         _startRows    = new int[_count];
         _endRows      = new int[_count];
         sm.GetSequencePoints(_offsets, _documents, _startRows, _startColumns, _endRows, _endColumns);
         return(true);
     }
     catch
     {
         _count        = 0;
         _offsets      = null;
         _documents    = null;
         _startColumns = null;
         _endColumns   = null;
         _startRows    = null;
         _endRows      = null;
         return(false);
     }
 }
Beispiel #12
0
        //private string[] GetCombinedSource(IEnumerable<SequencePoint> points) {
        //    var lines = new List<string>();
        //    foreach (var point in points) {
        //        var contentLines = documentCache.Get(point.Document, () => File.ReadAllLines(point.Document.URL));
        //        var start = point.Start.Row - 1;
        //        var end = point.End.Row - 1;

        //        if (start >= contentLines.Length || end >= contentLines.Length)
        //            continue;

        //        for (var i = start; i <= end; i++) {
        //            var line = contentLines[i];

        //            if (i == start)
        //                line = line.Substring(point.Start.Column - 1);
        //            else if (i == end)
        //                line = line.Substring(0, point.End.Column - 1);

        //            lines.Add(line);
        //        }
        //    }

        //    return lines.ToArray();
        //}

        private IEnumerable <SequencePoint> GetSequencePoints(ISymbolMethod method)
        {
            var count = method.SequencePointCount;

            var offsets      = new int[count];
            var docs         = new ISymbolDocument[count];
            var startColumns = new int[count];
            var endColumns   = new int[count];
            var startRows    = new int[count];
            var endRows      = new int[count];

            method.GetSequencePoints(offsets, docs, startRows, startColumns, endRows, endColumns);

            for (int i = 0; i < count; i++)
            {
                if (startRows[i] == SequencePointHiddenLine || endRows[i] == SequencePointHiddenLine)
                {
                    continue;
                }

                yield return(new SequencePoint {
                    Document = this.GetOrLoadContent(docs[i]),
                    Start = new SourcePosition(startRows[i], startColumns[i]),
                    End = new SourcePosition(endRows[i], endColumns[i])
                });
            }
        }
Beispiel #13
0
        protected override BreakEventInfo OnInsertBreakEvent(BreakEvent be)
        {
            BreakEventInfo binfo = new BreakEventInfo();

            lock (documents) {
                Breakpoint bp = be as Breakpoint;
                if (bp != null)
                {
                    DocInfo doc;
                    if (!documents.TryGetValue(System.IO.Path.GetFullPath(bp.FileName), out doc))
                    {
                        binfo.SetStatus(BreakEventStatus.NotBound, null);
                        return(binfo);
                    }

                    int line;
                    try {
                        line = doc.Document.FindClosestLine(bp.Line);
                    }
                    catch {
                        // Invalid line
                        binfo.SetStatus(BreakEventStatus.Invalid, null);
                        return(binfo);
                    }
                    ISymbolMethod met = doc.Reader.GetMethodFromDocumentPosition(doc.Document, line, 0);
                    if (met == null)
                    {
                        binfo.SetStatus(BreakEventStatus.Invalid, null);
                        return(binfo);
                    }

                    int offset = -1;
                    foreach (SequencePoint sp in met.GetSequencePoints())
                    {
                        if (sp.Line == line && sp.Document.URL == doc.Document.URL)
                        {
                            offset = sp.Offset;
                            break;
                        }
                    }
                    if (offset == -1)
                    {
                        binfo.SetStatus(BreakEventStatus.Invalid, null);
                        return(binfo);
                    }

                    CorFunction           func  = doc.Module.GetFunctionFromToken(met.Token.GetToken());
                    CorFunctionBreakpoint corBp = func.ILCode.CreateBreakpoint(offset);
                    corBp.Activate(bp.Enabled);
                    breakpoints[corBp] = binfo;

                    binfo.Handle = corBp;
                    binfo.SetStatus(BreakEventStatus.Bound, null);
                    return(binfo);
                }
            }
            return(null);
        }
Beispiel #14
0
        public static void GetLocalVariables(Assembly asm, MethodInfo m)
        {
            // Assembly asm = Assembly.GetExecutingAssembly();
            ISymbolReader symreader = SymUtil.GetSymbolReaderForFile(asm.Location, null);

            if (symreader == null)
            {
                Console.WriteLine(" ERROR: no symreader was created. Aborting GetLocalVariables...");
                return;
            }
            ISymbolMethod symMethod = symreader.GetMethod(new SymbolToken(m.MetadataToken));

            int sequencePointCount = symMethod.SequencePointCount;

            ISymbolDocument[] docs       = new ISymbolDocument[sequencePointCount];
            int[]             offsets    = new int[sequencePointCount];
            int[]             lines      = new int[sequencePointCount];
            int[]             columns    = new int[sequencePointCount];
            int[]             endlines   = new int[sequencePointCount];
            int[]             endcolumns = new int[sequencePointCount];

            symMethod.GetSequencePoints(offsets, docs, lines, columns, endlines, endcolumns);

            Console.WriteLine();
            Console.WriteLine("The source code for method: " + m.Name + "; found in " + docs[0].URL);
            Console.WriteLine(new String('*', 60));

            // although there's an array of docs, they seem to all have the same value (?) so we'll only use the first one
            StreamReader reader = new StreamReader(docs[0].URL); // URL is typically a fully path-qualified filename

            string[] linesOfCode = reader.ReadToEnd().Split('\r');

            string PrintableLineNumber = "0000";

            Console.WriteLine(linesOfCode[lines[0] - 2].Replace('\n', ' ')); // the preceding line (assumes declaration is only one line long, and found on immediately precediting line!


            // foreach (int LineNumber in lines) // print the source code (comments omitted)
            for (int LineNumber = lines[0]; LineNumber < lines[sequencePointCount - 1] + 1; LineNumber++) // print the source code (including comments)
            {
                PrintableLineNumber = new String(' ', 4 - LineNumber.ToString().Length)                   // padding
                                      + LineNumber.ToString();
                Console.WriteLine(PrintableLineNumber + ": " + linesOfCode[LineNumber - 1].Replace('\n', ' '));
            }
            // Console.WriteLine(linesOfCode[lines[sequencePointCount -1] + 1].Replace('\n', ' ')); // the trailing line
            //Console.WriteLine(linesOfCode);
            reader.Close();

            Console.WriteLine(new String('*', 60));
            Console.WriteLine();
            linesOfCode = null;
        }
Beispiel #15
0
        protected override object OnInsertBreakEvent(BreakEvent be, bool activate)
        {
            lock (documents) {
                Breakpoint bp = be as Breakpoint;
                if (bp != null)
                {
                    DocInfo doc;
                    if (!documents.TryGetValue(System.IO.Path.GetFullPath(bp.FileName), out doc))
                    {
                        return(null);
                    }

                    int line;
                    try {
                        line = doc.Document.FindClosestLine(bp.Line);
                    }
                    catch {
                        // Invalid line
                        return(null);
                    }
                    ISymbolMethod met = doc.Reader.GetMethodFromDocumentPosition(doc.Document, line, 0);
                    if (met == null)
                    {
                        return(null);
                    }

                    int offset = -1;
                    foreach (SequencePoint sp in met.GetSequencePoints())
                    {
                        if (sp.Line == line && sp.Document.URL == doc.Document.URL)
                        {
                            offset = sp.Offset;
                            break;
                        }
                    }
                    if (offset == -1)
                    {
                        return(null);
                    }

                    CorFunction           func  = doc.Module.GetFunctionFromToken(met.Token.GetToken());
                    CorFunctionBreakpoint corBp = func.ILCode.CreateBreakpoint(offset);
                    corBp.Activate(activate);
                    return(corBp);
                }
            }
            return(null);
        }
Beispiel #16
0
        ISymbolDocument[] GetDocumentList(ISymbolMethod method)
		{
			int count = method.SequencePointCount;

			// Get the sequence points from the symbol store. 
			// We could cache these arrays and reuse them.
			int[] offsets = new int[count];
			ISymbolDocument[] docs = new ISymbolDocument[count];
			int[] startColumn = new int[count];
			int[] endColumn = new int[count];
			int[] startRow = new int[count];
			int[] endRow = new int[count];

			method.GetSequencePoints(offsets, docs, startRow, startColumn, endRow, endColumn);
			return docs;
		}
Beispiel #17
0
        // Write the sequence points for the given method
        // Sequence points are the map between IL offsets and source lines.
        // A single method could span multiple files (use C#'s #line directive to see for yourself).
        private void WriteSequencePoints(ISymbolMethod method)
        {
            m_writer.WriteStartElement("sequencepoints");

            int count = method.SequencePointCount;

            m_writer.WriteAttributeString("total", Util.CultureInvariantToString(count));

            // Get the sequence points from the symbol store.
            // We could cache these arrays and reuse them.
            var offsets     = new int[count];
            var docs        = new ISymbolDocument[count];
            var startColumn = new int[count];
            var endColumn   = new int[count];
            var startRow    = new int[count];
            var endRow      = new int[count];

            method.GetSequencePoints(offsets, docs, startRow, startColumn, endRow, endColumn);

            // Write out sequence points
            for (int i = 0; i < count; i++)
            {
                m_writer.WriteStartElement("entry");
                m_writer.WriteAttributeString("il_offset", Util.AsIlOffset(offsets[i]));

                // If it's a special 0xFeeFee sequence point (eg, "hidden"),
                // place an attribute on it to make it very easy for tools to recognize.
                // See http://blogs.msdn.com/jmstall/archive/2005/06/19/FeeFee_SequencePoints.aspx
                if (startRow[i] == 0xFeeFee)
                {
                    m_writer.WriteAttributeString("hidden", XmlConvert.ToString(true));
                }
                //else
                {
                    m_writer.WriteAttributeString("start_row", Util.CultureInvariantToString(startRow[i]));
                    m_writer.WriteAttributeString("start_column", Util.CultureInvariantToString(startColumn[i]));
                    m_writer.WriteAttributeString("end_row", Util.CultureInvariantToString(endRow[i]));
                    m_writer.WriteAttributeString("end_column", Util.CultureInvariantToString(endColumn[i]));
                    m_writer.WriteAttributeString("file_ref", Util.CultureInvariantToString(m_fileMapping[docs[i].URL]));
                }
                m_writer.WriteEndElement();
            }

            m_writer.WriteEndElement(); // sequencepoints
        }
Beispiel #18
0
        // Write the sequence points for the given method
        // Sequence points are the map between IL offsets and source lines.
        // A single method could span multiple files (use C#'s #line directive to see for yourself).
        private void WriteSequencePoints(ISymbolMethod method)
        {
            int count = method.SequencePointCount;

            // Get the sequence points from the symbol store.
            // We could cache these arrays and reuse them.
            int[]             offsets     = new int[count];
            ISymbolDocument[] docs        = new ISymbolDocument[count];
            int[]             startColumn = new int[count];
            int[]             endColumn   = new int[count];
            int[]             startRow    = new int[count];
            int[]             endRow      = new int[count];
            method.GetSequencePoints(offsets, docs, startRow, startColumn, endRow, endColumn);

            xmlWriter.WriteStartElement("sequencePoints");
            for (int i = 0; i < count; i++)
            {
                xmlWriter.WriteStartElement("entry");
                // IL offsets are usually written in hexadecimal...
                xmlWriter.WriteAttributeString("ilOffset", "0x" + offsets[i].ToString("x4"));
                // ... but .NET XPath 1.0 cannot compare strings so we need a decimal number as well :-(
                xmlWriter.WriteAttributeString("ilOffsetDec", offsets[i].ToString());
                xmlWriter.WriteAttributeString("fileRef", fileMapping[docs[i].URL].ToString());

                // If it's a special 0xfeefee sequence point (e.g., "hidden"),
                // place an attribute on it to make it very easy for tools to recognize.
                // See http://blogs.msdn.com/b/jmstall/archive/2005/06/19/feefee-sequencepoints.aspx
                if (startRow[i] == 0xfeefee)
                {
                    xmlWriter.WriteAttributeString("hidden", "true");
                }
                else
                {
                    xmlWriter.WriteAttributeString("startLine", startRow[i].ToString());
                    xmlWriter.WriteAttributeString("startColumn", startColumn[i].ToString());
                    xmlWriter.WriteAttributeString("endLine", endRow[i].ToString());
                    xmlWriter.WriteAttributeString("endColumn", endColumn[i].ToString());
                }
                xmlWriter.WriteEndElement();           // </entry>
            }
            xmlWriter.WriteEndElement();               // </sequencePoints>
        }
Beispiel #19
0
        // Write the sequence points for the given method
        // Sequence points are the map between IL offsets and source lines.
        // A single method could span multiple files (use C#'s #line directive to see for yourself).
        private List <SequencePoint> ReadSequencePoints(ISymbolMethod method)
        {
            int count = method.SequencePointCount;

            // Get the sequence points from the symbol store.
            // We could cache these arrays and reuse them.
            int[]             offsets     = new int[count];
            ISymbolDocument[] docs        = new ISymbolDocument[count];
            int[]             startColumn = new int[count];
            int[]             endColumn   = new int[count];
            int[]             startRow    = new int[count];
            int[]             endRow      = new int[count];
            method.GetSequencePoints(offsets, docs, startRow, startColumn, endRow, endColumn);

            // Store them into the list
            List <SequencePoint> sequencePoints = new List <SequencePoint>(count);

            for (int i = 0; i < count; i++)
            {
                SequencePoint sp = new SequencePoint();
                sp.ilOffset = offsets[i];

                // If it's a special 0xFeeFee sequence point (eg, "hidden"),
                // place an attribute on it to make it very easy for tools to recognize.
                // See http://blogs.msdn.com/jmstall/archive/2005/06/19/FeeFee_SequencePoints.aspx
                if (startRow[i] == 0xFeeFee)
                {
                    sp.hidden = true;
                }

                sp.sourceId    = this.fileMapping[docs[i].URL];
                sp.startRow    = startRow[i];
                sp.startColumn = startColumn[i];
                sp.endRow      = endRow[i];
                sp.endColumn   = endColumn[i];

                sequencePoints.Add(sp);
            }

            return(sequencePoints);
        }
        //////////////////////////////////////////////////////////////////////////////////
        //
        //  Initialization & locals
        //
        //////////////////////////////////////////////////////////////////////////////////

        private void EnsureIsUpToDate()
        {
            Debug.Assert(m_module != null);
            Debug.Assert(m_module.EditsCounter >= CorFunction.Version - 1);
            // version cannot be greater then # of edits; versions are 1 based

            if (m_isInitialized)
            {
                return; // no need to do any refresh
            }
            // perform refresh
            m_isInitialized = true;
            m_haveSymbols   = m_module.SymReader != null;
            if (m_haveSymbols)
            {
                ISymbolMethod sm = null;
                sm = m_module.SymReader.GetMethod(new SymbolToken(m_function.Token), CorFunction.Version);
                if (sm == null)
                {
                    m_haveSymbols = false;
                    return;
                }

                m_symMethod      = sm;
                m_SPcount        = m_symMethod.SequencePointCount;
                m_SPoffsets      = new int[m_SPcount];
                m_SPdocuments    = new ISymbolDocument[m_SPcount];
                m_SPstartLines   = new int[m_SPcount];
                m_SPendLines     = new int[m_SPcount];
                m_SPstartColumns = new int[m_SPcount];
                m_SPendColumns   = new int[m_SPcount];

                m_symMethod.GetSequencePoints(m_SPoffsets, m_SPdocuments, m_SPstartLines, m_SPstartColumns, m_SPendLines,
                                              m_SPendColumns);
            }
        }
        public MethodDebugInfo(MethodBody body, ISymbolMethod pdb)
        {
            Body = body;

            // todo. support multiple locals sharing the same local slot 
            // (but having different Start::End offsets, of course)
            // so far we just silently ignore them taking into account only the first one
            var locals = pdb.RootScope.Flatten(ss => ss.GetChildren()).SelectMany(ss => ss.GetLocals());
            LocalNames = locals.Select(lv => new {Index = lv.AddressField1, Name = lv.Name})
                .Distinct().ToDictionary(lv => lv.Index, lv => lv.Name).ToReadOnly();

            var count = pdb.SequencePointCount;
            var offsets = new int[count];
            var documents = new ISymbolDocument[count];
            var lines = new int[count];
            var columns = new int[count];
            var endLines = new int[count];
            var endColumns = new int[count];
            pdb.GetSequencePoints(offsets, documents, lines, columns, endLines, endColumns);

            SequencePoints = 0.UpTo(count - 1).Select(i => 
                new SequencePoint(offsets[i], documents[i], lines[i], columns[i], endLines[i], endColumns[i])
            ).ToReadOnly();
        }
Beispiel #22
0
 private void Populate(ISymbolMethod method)
 {
     method.GetSequencePoints(Offsets, Documents, Lines, Columns, EndLines, EndColumns);
     for (int i = 0; i < Count; i++) {
         this.indexByOffsets.Add(Offsets[i], i);
     }
 }
Beispiel #23
0
        internal static GotoInfo[] LookupLocationsFromPdb(GotoInfo info, IVsSmartOpenScope vsSmartOpenScope)
        {
            Debug.Assert(info != null && info.MemberInfo != null, "LookupLocationsFromPdb lacks required parameter");
            var sources = new Dictionary <string, Location>();

            if (string.IsNullOrEmpty(info.FilePath) || !File.Exists(info.FilePath))
            {
                return(new GotoInfo[0]);
            }

            object         unkMetaDataImport;
            IntPtr         ptrMetaDataImport = IntPtr.Zero;
            ISymbolBinder1 binder;
            ISymbolReader  reader;

            ISymbolDocument[] documents;
            int[]             lines;
            int[]             columns;
            int[]             endLines;
            int[]             endColumns;
            int[]             offsets;
            var  methods = new List <MethodBase>();
            Type ty      = null;

            try
            {
                int hr = vsSmartOpenScope.OpenScope(info.FilePath, 0, ref IID_MetaDataImport, out unkMetaDataImport);

                if (hr == VSConstants.S_OK)
                {
                    ptrMetaDataImport = Marshal.GetIUnknownForObject(unkMetaDataImport);
                    binder            = new SymBinder();
                    reader            = binder.GetReader(ptrMetaDataImport, info.FilePath, null);
                    documents         = new ISymbolDocument[1];
                    lines             = new int[1];
                    columns           = new int[1];
                    endLines          = new int[1];
                    endColumns        = new int[1];
                    offsets           = new int[1];
                }
                else
                {
                    Debug.WriteLineIf(TS.TraceWarning,
                                      string.Format("Failed to obtain MetaDataImport from VS, hr 0x{0:X8}", hr), TS.DisplayName);

                    return(new GotoInfo[0]);
                }

                switch (info.MemberInfo.MemberType)
                {
                case MemberTypes.Constructor:
                case MemberTypes.Method:
                    MethodBase mb = (MethodBase)info.MemberInfo;

                    // Abstract methods does not contain any code.
                    //
                    if (mb.IsAbstract)
                    {
                        methods.AddRange(mb.DeclaringType.GetMethods(DeclaredMembers));
                    }
                    else
                    {
                        methods.Add(mb);
                    }
                    break;

                case MemberTypes.Property:
                    PropertyInfo pi = (PropertyInfo)info.MemberInfo;
                    methods.AddRange(pi.GetAccessors(true));
                    break;

                case MemberTypes.Field:
                    methods.AddRange(info.MemberInfo.DeclaringType.GetMethods(DeclaredMembers));
                    break;

                case MemberTypes.Event:
                    EventInfo ei = (EventInfo)info.MemberInfo;
                    methods.Add(ei.GetAddMethod(true));
                    methods.Add(ei.GetRemoveMethod(true));
                    methods.Add(ei.GetRaiseMethod(true));
                    methods.AddRange(ei.GetOtherMethods(true));
                    break;

                case MemberTypes.TypeInfo:
                case MemberTypes.NestedType:
                    ty = (Type)info.MemberInfo;
                    methods.AddRange(ty.GetMethods(DeclaredMembers));
                    methods.AddRange(ty.GetConstructors(DeclaredMembers));
                    break;

                default:
                    Trace.Fail("Unexpected MemberType " + info.MemberInfo.MemberType);
                    break;
                }


                foreach (MethodBase mb in methods)
                {
                    if (mb == null || Attribute.GetCustomAttribute(mb, typeof(CompilerGeneratedAttribute)) != null)
                    {
                        continue;
                    }

                    try
                    {
                        SymbolToken   token  = new SymbolToken(mb.MetadataToken);
                        ISymbolMethod method = reader.GetMethod(token);

                        if (method.SequencePointCount > 0)
                        {
                            method.GetSequencePoints(offsets, documents, lines, columns, endLines, endColumns);

                            var path = documents[0].URL;
                            // We are interested in unique files only.
                            if (File.Exists(path) && (ty == null || mb.DeclaringType.Equals(ty)))
                            {
                                Location value;
                                if (sources.TryGetValue(path, out value))
                                {
                                    if ((value.Column == 0 || value.Line == 0) && lines[0] != 0 && columns[0] != 0)
                                    {
                                        sources[path] = new Location(path, lines[0], columns[0], endLines[0], endColumns[0]);
                                    }
                                }
                                else
                                {
                                    sources.Add(path, new Location(path, lines[0], columns[0], endLines[0], endColumns[0]));
                                }
                            }
                        }
                    }
                    catch (COMException ex)
                    {
                        // Abstract method or not a method at all.
                        // Sequence points are available only for methods.
                        //
                        Trace.WriteLineIf(TS.TraceError,
                                          string.Format("({0}) {1}, code 0x{2:X8}", mb.Name, ex.Message, ex.ErrorCode), TS.DisplayName);
                    }
                }
            }
            catch (COMException ex)
            {
                // The file was not found or source locations were stripped from the pdb.
                //
                Trace.WriteLineIf(TS.TraceError,
                                  string.Format("{0}, code 0x{1:8X}", ex.Message, ex.ErrorCode), TS.DisplayName);
            }
            finally
            {
                if (ptrMetaDataImport != IntPtr.Zero)
                {
                    Marshal.Release(ptrMetaDataImport);
                }
            }

            return(sources.Select(x => new GotoInfo(x.Key, x.Value)).ToArray());
        }
Beispiel #24
0
		void AddSequencePoints(CilBody body, ISymbolMethod method) {
			int numSeqs = method.SequencePointCount;
			var offsets = new int[numSeqs];
			var documents = new ISymbolDocument[numSeqs];
			var lines = new int[numSeqs];
			var columns = new int[numSeqs];
			var endLines = new int[numSeqs];
			var endColumns = new int[numSeqs];
			method.GetSequencePoints(offsets, documents, lines, columns, endLines, endColumns);

			int instrIndex = 0;
			for (int i = 0; i < numSeqs; i++) {
				var instr = GetInstruction(body.Instructions, offsets[i], ref instrIndex);
				if (instr == null)
					continue;
				var seqPoint = new SequencePoint() {
					Document = Add_NoLock(new PdbDocument(documents[i])),
					StartLine = lines[i],
					StartColumn = columns[i],
					EndLine = endLines[i],
					EndColumn = endColumns[i],
				};
				instr.SequencePoint = seqPoint;
			}
		}
Beispiel #25
0
        public static SequencePoint GetSequencePoint(CorDebuggerSession session, CorFrame frame)
        {
            ISymbolReader reader = session.GetReaderForModule(frame.Function.Module);

            if (reader == null)
            {
                return(null);
            }

            ISymbolMethod met = reader.GetMethod(new SymbolToken(frame.Function.Token));

            if (met == null)
            {
                return(null);
            }

            int SequenceCount = met.SequencePointCount;

            if (SequenceCount <= 0)
            {
                return(null);
            }

            CorDebugMappingResult mappingResult;
            uint ip;

            frame.GetIP(out ip, out mappingResult);
            if (mappingResult == CorDebugMappingResult.MAPPING_NO_INFO || mappingResult == CorDebugMappingResult.MAPPING_UNMAPPED_ADDRESS)
            {
                return(null);
            }

            int[]             offsets    = new int[SequenceCount];
            int[]             lines      = new int[SequenceCount];
            int[]             endLines   = new int[SequenceCount];
            int[]             columns    = new int[SequenceCount];
            int[]             endColumns = new int[SequenceCount];
            ISymbolDocument[] docs       = new ISymbolDocument[SequenceCount];
            met.GetSequencePoints(offsets, docs, lines, columns, endLines, endColumns);

            if ((SequenceCount > 0) && (offsets [0] <= ip))
            {
                int i;
                for (i = 0; i < SequenceCount; ++i)
                {
                    if (offsets [i] >= ip)
                    {
                        break;
                    }
                }

                if ((i == SequenceCount) || (offsets [i] != ip))
                {
                    --i;
                }

                if (lines [i] == SpecialSequencePoint)
                {
                    int j = i;
                    // let's try to find a sequence point that is not special somewhere earlier in the code
                    // stream.
                    while (j > 0)
                    {
                        --j;
                        if (lines [j] != SpecialSequencePoint)
                        {
                            return(new SequencePoint()
                            {
                                IsSpecial = true,
                                Offset = offsets [j],
                                StartLine = lines [j],
                                EndLine = endLines [j],
                                StartColumn = columns [j],
                                EndColumn = endColumns [j],
                                Document = docs [j]
                            });
                        }
                    }
                    // we didn't find any non-special seqeunce point before current one, let's try to search
                    // after.
                    j = i;
                    while (++j < SequenceCount)
                    {
                        if (lines [j] != SpecialSequencePoint)
                        {
                            return(new SequencePoint()
                            {
                                IsSpecial = true,
                                Offset = offsets [j],
                                StartLine = lines [j],
                                EndLine = endLines [j],
                                StartColumn = columns [j],
                                EndColumn = endColumns [j],
                                Document = docs [j]
                            });
                        }
                    }

                    // Even if sp is null at this point, it's a valid scenario to have only special sequence
                    // point in a function.  For example, we can have a compiler-generated default ctor which
                    // doesn't have any source.
                    return(null);
                }
                else
                {
                    return(new SequencePoint()
                    {
                        IsSpecial = false,
                        Offset = offsets [i],
                        StartLine = lines [i],
                        EndLine = endLines [i],
                        StartColumn = columns [i],
                        EndColumn = endColumns [i],
                        Document = docs [i]
                    });
                }
            }
            return(null);
        }
Beispiel #26
0
        // Write the sequence points for the given method
        // Sequence points are the map between IL offsets and source lines.
        // A single method could span multiple files (use C#'s #line directive to see for yourself).
        private List<SequencePoint> ReadSequencePoints(ISymbolMethod method)
        {
            int count = method.SequencePointCount;

            // Get the sequence points from the symbol store.
            // We could cache these arrays and reuse them.
            int[] offsets = new int[count];
            ISymbolDocument[] docs = new ISymbolDocument[count];
            int[] startColumn = new int[count];
            int[] endColumn = new int[count];
            int[] startRow = new int[count];
            int[] endRow = new int[count];
            method.GetSequencePoints(offsets, docs, startRow, startColumn, endRow, endColumn);

            // Store them into the list
            List<SequencePoint> sequencePoints = new List<SequencePoint>(count);
            for (int i = 0; i < count; i++)
            {
                SequencePoint sp = new SequencePoint();
                sp.ilOffset = offsets[i];

                // If it's a special 0xFeeFee sequence point (eg, "hidden"),
                // place an attribute on it to make it very easy for tools to recognize.
                // See http://blogs.msdn.com/jmstall/archive/2005/06/19/FeeFee_SequencePoints.aspx
                if (startRow[i] == 0xFeeFee)
                {
                    sp.hidden = true;
                }

                sp.sourceId = this.m_fileMapping[docs[i].URL];
                sp.startRow = startRow[i];
                sp.startColumn = startColumn[i];
                sp.endRow = endRow[i];
                sp.endColumn = endColumn[i];

                sequencePoints.Add(sp);
            }

            return sequencePoints;
        }
        private void InitSymbolInformation()
        {
            if (p_symbolsInitialized)
                return;

            p_symbolsInitialized = true;

            ISymbolReader symreader = Module.GetSymReader();
            p_hasSymbols = symreader != null;
            if (p_hasSymbols)
            {
                ISymbolMethod sm = null;
                sm = symreader.GetMethod(new SymbolToken((Int32)Token));
                if (sm == null)
                {
                    p_hasSymbols = false;
                    return;
                }
                p_symMethod = sm;
                p_SPcount = p_symMethod.SequencePointCount;
                p_SPoffsets = new Int32[p_SPcount];
                p_SPdocuments = new ISymbolDocument[p_SPcount];
                p_SPstartLines = new Int32[p_SPcount];
                p_SPendLines = new Int32[p_SPcount];
                p_SPstartColumns = new Int32[p_SPcount];
                p_SPendColumns = new Int32[p_SPcount];

                p_symMethod.GetSequencePoints(p_SPoffsets, p_SPdocuments, p_SPstartLines,
                                                p_SPstartColumns, p_SPendLines, p_SPendColumns);
            }
        }
Beispiel #28
0
        void Step(bool into)
        {
            if (stepper != null)
            {
                stepper.IsActive();
                CorFrame      frame  = activeThread.ActiveFrame;
                ISymbolReader reader = GetReaderForModule(frame.Function.Module.Name);
                if (reader == null)
                {
                    RawContinue(into);
                    return;
                }
                ISymbolMethod met = reader.GetMethod(new SymbolToken(frame.Function.Token));
                if (met == null)
                {
                    RawContinue(into);
                    return;
                }

                uint offset;
                CorDebugMappingResult mappingResult;
                frame.GetIP(out offset, out mappingResult);

                // Find the current line
                SequencePoint currentSeq = null;
                foreach (SequencePoint sp in met.GetSequencePoints())
                {
                    if (sp.Offset > offset)
                    {
                        break;
                    }
                    currentSeq = sp;
                }

                if (currentSeq == null)
                {
                    RawContinue(into);
                    return;
                }

                // Exclude all ranges belonging to the current line
                List <COR_DEBUG_STEP_RANGE> ranges = new List <COR_DEBUG_STEP_RANGE> ();
                SequencePoint lastSeq = null;
                foreach (SequencePoint sp in met.GetSequencePoints())
                {
                    if (lastSeq != null && lastSeq.Line == currentSeq.Line)
                    {
                        COR_DEBUG_STEP_RANGE r = new COR_DEBUG_STEP_RANGE();
                        r.startOffset = (uint)lastSeq.Offset;
                        r.endOffset   = (uint)sp.Offset;
                        ranges.Add(r);
                    }
                    lastSeq = sp;
                }

                stepper.StepRange(into, ranges.ToArray());

                ClearEvalStatus();
                process.SetAllThreadsDebugState(CorDebugThreadState.THREAD_RUN, null);
                process.Continue(false);
            }
        }
Beispiel #29
0
        // Write the sequence points for the given method
        // Sequence points are the map between IL offsets and source lines.
        // A single method could span multiple files (use C#'s #line directive to see for yourself).        
        private void WriteSequencePoints(ISymbolMethod method)
        {
            writer.WriteStartElement("sequencepoints");

            int count = method.SequencePointCount;
            writer.WriteAttributeString("total", CultureInvariantToString(count));

            // Get the sequence points from the symbol store. 
            // We could cache these arrays and reuse them.
            int[] offsets = new int[count];
            ISymbolDocument[] docs = new ISymbolDocument[count];
            int[] startColumn = new int[count];
            int[] endColumn = new int[count];
            int[] startRow = new int[count];
            int[] endRow = new int[count];
            method.GetSequencePoints(offsets, docs, startRow, startColumn, endRow, endColumn);

            // Write out sequence points
            for (int i = 0; i < count; i++)
            {
                writer.WriteStartElement("entry");
                writer.WriteAttributeString("il_offset", AsILOffset(offsets[i]));

                // If it's a special 0xFeeFee sequence point (eg, "hidden"), 
                // place an attribute on it to make it very easy for tools to recognize.
                // See http://blogs.msdn.com/jmstall/archive/2005/06/19/FeeFee_SequencePoints.aspx
                if (startRow[i] == 0xFeeFee)
                {
                    writer.WriteAttributeString("hidden", XmlConvert.ToString(true));
                }

                writer.WriteAttributeString("start_row", CultureInvariantToString(startRow[i]));
                writer.WriteAttributeString("start_column", CultureInvariantToString(startColumn[i]));
                writer.WriteAttributeString("end_row", CultureInvariantToString(endRow[i]));
                writer.WriteAttributeString("end_column", CultureInvariantToString(endColumn[i]));
                //EDMAURER allow there to be PDBs generated for sources that don't have a name (document).
                int fileRefVal = -1;
                this.m_fileMapping.TryGetValue(docs[i].URL, out fileRefVal);
                writer.WriteAttributeString("file_ref", CultureInvariantToString(fileRefVal));

                writer.WriteEndElement();
            }

            writer.WriteEndElement(); // sequencepoints
        }
        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);
        }
Beispiel #31
0
        // Write the sequence points for the given method
        // Sequence points are the map between IL offsets and source lines.
        // A single method could span multiple files (use C#'s #line directive to see for yourself).        
        private void WriteSequencePoints(ISymbolMethod method)
        {
            m_writer.WriteStartElement("sequencepoints");

            int count = method.SequencePointCount;
            m_writer.WriteAttributeString("total", Util.CultureInvariantToString(count));

            // Get the sequence points from the symbol store. 
            // We could cache these arrays and reuse them.
            var offsets = new int[count];
            var docs = new ISymbolDocument[count];
            var startColumn = new int[count];
            var endColumn = new int[count];
            var startRow = new int[count];
            var endRow = new int[count];
            method.GetSequencePoints(offsets, docs, startRow, startColumn, endRow, endColumn);

            // Write out sequence points
            for (int i = 0; i < count; i++)
            {
                m_writer.WriteStartElement("entry");
                m_writer.WriteAttributeString("il_offset", Util.AsIlOffset(offsets[i]));

                // If it's a special 0xFeeFee sequence point (eg, "hidden"), 
                // place an attribute on it to make it very easy for tools to recognize.
                // See http://blogs.msdn.com/jmstall/archive/2005/06/19/FeeFee_SequencePoints.aspx
                if (startRow[i] == 0xFeeFee)
                {
                    m_writer.WriteAttributeString("hidden", XmlConvert.ToString(true));
                }
                //else
                {
                    m_writer.WriteAttributeString("start_row", Util.CultureInvariantToString(startRow[i]));
                    m_writer.WriteAttributeString("start_column", Util.CultureInvariantToString(startColumn[i]));
                    m_writer.WriteAttributeString("end_row", Util.CultureInvariantToString(endRow[i]));
                    m_writer.WriteAttributeString("end_column", Util.CultureInvariantToString(endColumn[i]));
                    m_writer.WriteAttributeString("file_ref", Util.CultureInvariantToString(m_fileMapping[docs[i].URL]));
                }
                m_writer.WriteEndElement();
            }

            m_writer.WriteEndElement(); // sequencepoints
        }
Beispiel #32
0
        //////////////////////////////////////////////////////////////////////////////////
        //
        //  Initialization & locals
        //
        //////////////////////////////////////////////////////////////////////////////////
        private void EnsureIsUpToDate()
        {
            Debug.Assert(m_module != null);
            Debug.Assert(m_module.EditsCounter >= CorFunction.Version - 1); // version cannot be greater then # of edits; versions are 1 based

            if (m_isInitialized)
                return; // no need to do any refresh

            // perform refresh
            m_isInitialized = true;
            m_haveSymbols = m_module.SymReader != null;
            if (m_haveSymbols)
            {
                ISymbolMethod sm = null;
                sm = m_module.SymReader.GetMethod(new SymbolToken((int)m_function.Token), CorFunction.Version);
                if (sm == null)
                {
                    m_haveSymbols = false;
                    return;
                }

                m_symMethod = sm;
                m_SPcount = m_symMethod.SequencePointCount;
                m_SPoffsets = new int[m_SPcount];
                m_SPdocuments = new ISymbolDocument[m_SPcount];
                m_SPstartLines = new int[m_SPcount];
                m_SPendLines = new int[m_SPcount];
                m_SPstartColumns = new int[m_SPcount];
                m_SPendColumns = new int[m_SPcount];

                m_symMethod.GetSequencePoints(m_SPoffsets, m_SPdocuments, m_SPstartLines, m_SPstartColumns, m_SPendLines, m_SPendColumns);
            }
        }
Beispiel #33
0
        /// <summary>
        /// Read the pdb file for this module and frame
        /// Retrieve infomation about the function
        /// </summary>
        /// <remarks>
        /// When an unmanaged app like reflector loads CLR, "Function.Module.Name"
        /// doesn't return a valid value and so this function returns null.
        /// </remarks>
        /// <returns>SourcePosition of the function</returns>
        private SourcePosition GetMetaDataInfo(CorMetadataImport importer)
        {
            SourcePosition functionPos = null;             //position in this function where we are

            try
            {
                moduleFullName  = thisFrame.Function.Module.Name;
                moduleShortName = System.IO.Path.GetFileName(moduleFullName);
            }
            catch (ArgumentException)
            {
                moduleFullName  = "";
                moduleShortName = "";
                return(null);
            }


            //TODO: Implement a better method to determine the symbol path than just assuming it's in the same
            //      directory
            string sympath = ".";

            //dealing with readinf the source in the module
            ISymbolReader  metaReader   = null;
            ISymbolBinder1 symbolBinder = new SymbolBinder();

            try
            {
                if (moduleFullName.Length > 0)
                {
                    metaReader = (symbolBinder as SymbolBinder).
                                 GetReaderForFile(importer.RawCOMObject, moduleFullName, sympath);
                }
            }
            catch (COMException)
            {
                //Debug.WriteLine(ed.ToString(CultureInfo.CurrentCulture.NumberFormat));
                //will get here for any function which we cant read the .pdb file for
                //its not a big deal we just wont have source and line info
            }

            if (metaReader != null)
            {
                ISymbolMethod symMethod = null;
                try
                {
                    symMethod = metaReader.GetMethod(new SymbolToken((int)thisFrame.Function.Token), thisFrame.Function.Version);
                    int sequenceCount = symMethod.SequencePointCount;
                    symDocs      = new ISymbolDocument[sequenceCount];
                    offsets      = new int[sequenceCount];
                    startLines   = new int[sequenceCount];
                    startColumns = new int[sequenceCount];
                    endLines     = new int[sequenceCount];
                    endColumns   = new int[sequenceCount];

                    //Get the sequence points and store them in the apporpriate arrays. Seqeunce points
                    //represent the different points in the files which correlate to il instruction and lines
                    symMethod.GetSequencePoints(offsets, symDocs, startLines, startColumns, endLines, endColumns);

                    functionPos = GetSourcePositionFromFrame();
                }
                catch (COMException)
                {
                    functionPos = null;
                }
                finally
                {
                    symDocs   = null;
                    symMethod = null;
                }
            }


            CorType ctype = GetClassType();

            if (ctype != null)
            {
                StringBuilder sb = new StringBuilder();
                GetFunctionClassPath(sb, ctype);
                functionFullName = sb.ToString();
            }
            else
            {
                functionFullName = "";
            }

            MethodInfo methIn = importer.GetMethodInfo(thisFrame.Function.Token);

            functionFullName += "." + methIn.Name;
            functionShortName = methIn.Name;
            return(functionPos);
        }
Beispiel #34
0
        //private string[] GetCombinedSource(IEnumerable<SequencePoint> points) {
        //    var lines = new List<string>();
        //    foreach (var point in points) {
        //        var contentLines = documentCache.Get(point.Document, () => File.ReadAllLines(point.Document.URL));
        //        var start = point.Start.Row - 1;
        //        var end = point.End.Row - 1;
        //        if (start >= contentLines.Length || end >= contentLines.Length)
        //            continue;
        //        for (var i = start; i <= end; i++) {
        //            var line = contentLines[i];
        //            if (i == start)
        //                line = line.Substring(point.Start.Column - 1);
        //            else if (i == end)
        //                line = line.Substring(0, point.End.Column - 1);
        //            lines.Add(line);
        //        }
        //    }
        //    return lines.ToArray();
        //}
        private IEnumerable<SequencePoint> GetSequencePoints(ISymbolMethod method)
        {
            var count = method.SequencePointCount;

            var offsets = new int[count];
            var docs = new ISymbolDocument[count];
            var startColumns = new int[count];
            var endColumns = new int[count];
            var startRows = new int[count];
            var endRows = new int[count];

            method.GetSequencePoints(offsets, docs, startRows, startColumns, endRows, endColumns);

            for (int i = 0; i < count; i++) {
                if (startRows[i] == SequencePointHiddenLine || endRows[i] == SequencePointHiddenLine)
                    continue;

                yield return new SequencePoint {
                    Document = this.GetOrLoadContent(docs[i]),
                    Start = new SourcePosition(startRows[i], startColumns[i]),
                    End = new SourcePosition(endRows[i], endColumns[i])
                };
            }
        }
Beispiel #35
0
        void ReadSequencePoints(ISymbolMethod method, Hashtable instructions)
        {
            int count = method.SequencePointCount;
            int [] offsets = new int [count];
            ISymbolDocument [] docs = new ISymbolDocument [count];
            int [] startColumn = new int [count];
            int [] endColumn = new int [count];
            int [] startRow = new int [count];
            int [] endRow = new int [count];
            method.GetSequencePoints (offsets, docs, startRow, startColumn, endRow, endColumn);

            for (int i = 0; i < offsets.Length; i++) {
                Cil.Instruction instr = (Cil.Instruction) instructions [offsets [i]];

                Cil.SequencePoint sp = new Cil.SequencePoint (GetDocument (docs [i]));
                sp.StartLine = startRow [i];
                sp.StartColumn = startColumn [i];
                sp.EndLine = endRow [i];
                sp.EndColumn = endColumn [i];

                instr.SequencePoint = sp;
            }
        }
Beispiel #36
0
        internal static StackFrame CreateFrame(CorDebuggerSession session, CorFrame frame)
        {
            uint   address = 0;
            string file    = "";
            int    line    = 0;
            string method  = "";
            string lang    = "";
            string module  = "";

            if (frame.FrameType == CorFrameType.ILFrame)
            {
                if (frame.Function != null)
                {
                    module = frame.Function.Module.Name;
                    CorMetadataImport importer = new CorMetadataImport(frame.Function.Module);
                    MethodInfo        mi       = importer.GetMethodInfo(frame.Function.Token);
                    method = mi.DeclaringType.FullName + "." + mi.Name;
                    ISymbolReader reader = session.GetReaderForModule(frame.Function.Module.Name);
                    if (reader != null)
                    {
                        ISymbolMethod met = reader.GetMethod(new SymbolToken(frame.Function.Token));
                        if (met != null)
                        {
                            uint offset;
                            CorDebugMappingResult mappingResult;
                            frame.GetIP(out offset, out mappingResult);
                            SequencePoint prevSp = null;
                            foreach (SequencePoint sp in met.GetSequencePoints())
                            {
                                if (sp.Offset > offset)
                                {
                                    break;
                                }
                                prevSp = sp;
                            }
                            if (prevSp != null)
                            {
                                line = prevSp.Line;
                                file = prevSp.Document.URL;
                            }
                        }
                    }
                }
                lang = "Managed";
            }
            else if (frame.FrameType == CorFrameType.NativeFrame)
            {
                frame.GetNativeIP(out address);
                method = "<Unknown>";
                lang   = "Native";
            }
            else if (frame.FrameType == CorFrameType.InternalFrame)
            {
                switch (frame.InternalFrameType)
                {
                case CorDebugInternalFrameType.STUBFRAME_M2U: method = "[Managed to Native Transition]"; break;

                case CorDebugInternalFrameType.STUBFRAME_U2M: method = "[Native to Managed Transition]"; break;

                case CorDebugInternalFrameType.STUBFRAME_LIGHTWEIGHT_FUNCTION: method = "[Lightweight Method Call]"; break;

                case CorDebugInternalFrameType.STUBFRAME_APPDOMAIN_TRANSITION: method = "[Application Domain Transition]"; break;

                case CorDebugInternalFrameType.STUBFRAME_FUNC_EVAL: method = "[Function Evaluation]"; break;
                }
            }
            if (method == null)
            {
                method = "<Unknown>";
            }
            return(new StackFrame((long)address, module, method, file, line, lang));
        }
        ISymbolDocument[] GetDocumentList(ISymbolMethod method)
        {
            int count = method.SequencePointCount;

            // Get the sequence points from the symbol store.
            // We could cache these arrays and reuse them.
            int[] offsets = new int[count];
            ISymbolDocument[] docs = new ISymbolDocument[count];
            int[] startColumn = new int[count];
            int[] endColumn = new int[count];
            int[] startRow = new int[count];
            int[] endRow = new int[count];

            method.GetSequencePoints(offsets, docs, startRow, startColumn, endRow, endColumn);
            return docs;
        }
Beispiel #38
0
        // Write the sequence points for the given method
        // Sequence points are the map between IL offsets and source lines.
        // A single method could span multiple files (use C#'s #line directive to see for yourself).
        private void WriteSequencePoints(ISymbolMethod method)
        {
            int count = method.SequencePointCount;
            // Get the sequence points from the symbol store.
            // We could cache these arrays and reuse them.
            int[] offsets = new int[count];
            ISymbolDocument[] docs = new ISymbolDocument[count];
            int[] startColumn = new int[count];
            int[] endColumn = new int[count];
            int[] startRow = new int[count];
            int[] endRow = new int[count];
            method.GetSequencePoints(offsets, docs, startRow, startColumn, endRow, endColumn);

            xmlWriter.WriteStartElement("sequencePoints");
            for (int i = 0; i < count; i++)
            {
                xmlWriter.WriteStartElement("entry");
                // IL offsets are usually written in hexadecimal...
                xmlWriter.WriteAttributeString("ilOffset", "0x" + offsets[i].ToString("x4"));
                // ... but .NET XPath 1.0 cannot compare strings so we need a decimal number as well :-(
                xmlWriter.WriteAttributeString("ilOffsetDec", offsets[i].ToString());
                xmlWriter.WriteAttributeString("fileRef", fileMapping[docs[i].URL].ToString());

                // If it's a special 0xfeefee sequence point (e.g., "hidden"),
                // place an attribute on it to make it very easy for tools to recognize.
                // See http://blogs.msdn.com/b/jmstall/archive/2005/06/19/feefee-sequencepoints.aspx
                if (startRow[i] == 0xfeefee)
                {
                    xmlWriter.WriteAttributeString("hidden", "true");
                }
                else
                {
                    xmlWriter.WriteAttributeString("startLine", startRow[i].ToString());
                    xmlWriter.WriteAttributeString("startColumn", startColumn[i].ToString());
                    xmlWriter.WriteAttributeString("endLine", endRow[i].ToString());
                    xmlWriter.WriteAttributeString("endColumn", endColumn[i].ToString());
                }
                xmlWriter.WriteEndElement();   // </entry>
            }
            xmlWriter.WriteEndElement();   // </sequencePoints>
        }
Beispiel #39
0
        internal static StackFrame CreateFrame(CorDebuggerSession session, CorFrame frame)
        {
            // TODO: Fix remaining.
            uint address = 0;
            //string typeFQN;
            //string typeFullName;
            string addressSpace = "";
            string file         = "";
            int    line         = 0;
            int    column       = 0;
            string method       = "";
            string lang         = "";
            string module       = "";
            string type         = "";
            bool   hasDebugInfo = false;
            bool   hidden       = false;
            bool   external     = true;

            if (frame.FrameType == CorFrameType.ILFrame)
            {
                if (frame.Function != null)
                {
                    module = frame.Function.Module.Name;
                    CorMetadataImport importer = new CorMetadataImport(frame.Function.Module);
                    MethodInfo        mi       = importer.GetMethodInfo(frame.Function.Token);
                    method       = mi.DeclaringType.FullName + "." + mi.Name;
                    type         = mi.DeclaringType.FullName;
                    addressSpace = mi.Name;
                    ISymbolReader reader = session.GetReaderForModule(frame.Function.Module.Name);
                    if (reader != null)
                    {
                        ISymbolMethod met = reader.GetMethod(new SymbolToken(frame.Function.Token));
                        if (met != null)
                        {
                            CorDebugMappingResult mappingResult;
                            frame.GetIP(out address, out mappingResult);
                            SequencePoint prevSp = null;
                            foreach (SequencePoint sp in met.GetSequencePoints())
                            {
                                if (sp.Offset > address)
                                {
                                    break;
                                }
                                prevSp = sp;
                            }
                            if (prevSp != null)
                            {
                                line    = prevSp.Line;
                                column  = prevSp.Offset;
                                file    = prevSp.Document.URL;
                                address = (uint)prevSp.Offset;
                            }
                        }
                    }
                    // FIXME: Still steps into.
                    //hidden = mi.GetCustomAttributes (true).Any (v => v is System.Diagnostics.DebuggerHiddenAttribute);
                }
                lang         = "Managed";
                hasDebugInfo = true;
            }
            else if (frame.FrameType == CorFrameType.NativeFrame)
            {
                frame.GetNativeIP(out address);
                method = "<Unknown>";
                lang   = "Native";
            }
            else if (frame.FrameType == CorFrameType.InternalFrame)
            {
                switch (frame.InternalFrameType)
                {
                case CorDebugInternalFrameType.STUBFRAME_M2U: method = "[Managed to Native Transition]"; break;

                case CorDebugInternalFrameType.STUBFRAME_U2M: method = "[Native to Managed Transition]"; break;

                case CorDebugInternalFrameType.STUBFRAME_LIGHTWEIGHT_FUNCTION: method = "[Lightweight Method Call]"; break;

                case CorDebugInternalFrameType.STUBFRAME_APPDOMAIN_TRANSITION: method = "[Application Domain Transition]"; break;

                case CorDebugInternalFrameType.STUBFRAME_FUNC_EVAL: method = "[Function Evaluation]"; break;
                }
            }

            if (method == null)
            {
                method = "<Unknown>";
            }

            var loc = new SourceLocation(method, file, line, column);

            return(new StackFrame((long)address, addressSpace, loc, lang, external, hasDebugInfo, hidden, null, null));
        }