/symbols/mdb/Mono.Cecil.Mdb/MdbReader.cs
http://github.com/jbevain/cecil · C# · 207 lines · 151 code · 47 blank · 9 comment · 23 complexity · e86acffd88489648590ff299528970ce MD5 · raw file
- //
- // Author:
- // Jb Evain (jbevain@gmail.com)
- //
- // Copyright (c) 2008 - 2015 Jb Evain
- // Copyright (c) 2008 - 2011 Novell, Inc.
- //
- // Licensed under the MIT/X11 license.
- //
- using System;
- using System.Collections.Generic;
- using System.IO;
- using Mono.Cecil.Cil;
- using Mono.Collections.Generic;
- using Mono.CompilerServices.SymbolWriter;
- namespace Mono.Cecil.Mdb {
- public sealed class MdbReaderProvider : ISymbolReaderProvider {
- public ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName)
- {
- Mixin.CheckModule (module);
- Mixin.CheckFileName (fileName);
- return new MdbReader (module, MonoSymbolFile.ReadSymbolFile (Mixin.GetMdbFileName (fileName)));
- }
- public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream)
- {
- Mixin.CheckModule (module);
- Mixin.CheckStream (symbolStream);
- return new MdbReader (module, MonoSymbolFile.ReadSymbolFile (symbolStream));
- }
- }
- public sealed class MdbReader : ISymbolReader {
- readonly ModuleDefinition module;
- readonly MonoSymbolFile symbol_file;
- readonly Dictionary<string, Document> documents;
- public MdbReader (ModuleDefinition module, MonoSymbolFile symFile)
- {
- this.module = module;
- this.symbol_file = symFile;
- this.documents = new Dictionary<string, Document> ();
- }
- public ISymbolWriterProvider GetWriterProvider ()
- {
- return new MdbWriterProvider ();
- }
- public bool ProcessDebugHeader (ImageDebugHeader header)
- {
- return symbol_file.Guid == module.Mvid;
- }
- public MethodDebugInformation Read (MethodDefinition method)
- {
- var method_token = method.MetadataToken;
- var entry = symbol_file.GetMethodByToken (method_token.ToInt32 ());
- if (entry == null)
- return null;
- var info = new MethodDebugInformation (method);
- info.code_size = ReadCodeSize (method);
- var scopes = ReadScopes (entry, info);
- ReadLineNumbers (entry, info);
- ReadLocalVariables (entry, scopes);
- return info;
- }
- static int ReadCodeSize (MethodDefinition method)
- {
- return method.Module.Read (method, (m, reader) => reader.ReadCodeSize (m));
- }
- static void ReadLocalVariables (MethodEntry entry, ScopeDebugInformation [] scopes)
- {
- var locals = entry.GetLocals ();
- foreach (var local in locals) {
- var variable = new VariableDebugInformation (local.Index, local.Name);
- var index = local.BlockIndex;
- if (index < 0 || index >= scopes.Length)
- continue;
- var scope = scopes [index];
- if (scope == null)
- continue;
- scope.Variables.Add (variable);
- }
- }
- void ReadLineNumbers (MethodEntry entry, MethodDebugInformation info)
- {
- var table = entry.GetLineNumberTable ();
- info.sequence_points = new Collection<SequencePoint> (table.LineNumbers.Length);
- for (var i = 0; i < table.LineNumbers.Length; i++) {
- var line = table.LineNumbers [i];
- if (i > 0 && table.LineNumbers [i - 1].Offset == line.Offset)
- continue;
- info.sequence_points.Add (LineToSequencePoint (line));
- }
- }
- Document GetDocument (SourceFileEntry file)
- {
- var file_name = file.FileName;
- Document document;
- if (documents.TryGetValue (file_name, out document))
- return document;
- document = new Document (file_name) {
- Hash = file.Checksum,
- };
- documents.Add (file_name, document);
- return document;
- }
- static ScopeDebugInformation [] ReadScopes (MethodEntry entry, MethodDebugInformation info)
- {
- var blocks = entry.GetCodeBlocks ();
- var scopes = new ScopeDebugInformation [blocks.Length + 1];
- info.scope = scopes [0] = new ScopeDebugInformation {
- Start = new InstructionOffset (0),
- End = new InstructionOffset (info.code_size),
- };
- foreach (var block in blocks) {
- if (block.BlockType != CodeBlockEntry.Type.Lexical && block.BlockType != CodeBlockEntry.Type.CompilerGenerated)
- continue;
- var scope = new ScopeDebugInformation ();
- scope.Start = new InstructionOffset (block.StartOffset);
- scope.End = new InstructionOffset (block.EndOffset);
- scopes [block.Index + 1] = scope;
- if (!AddScope (info.scope.Scopes, scope))
- info.scope.Scopes.Add (scope);
- }
- return scopes;
- }
- static bool AddScope (Collection<ScopeDebugInformation> scopes, ScopeDebugInformation scope)
- {
- foreach (var sub_scope in scopes) {
- if (sub_scope.HasScopes && AddScope (sub_scope.Scopes, scope))
- return true;
- if (scope.Start.Offset >= sub_scope.Start.Offset && scope.End.Offset <= sub_scope.End.Offset) {
- sub_scope.Scopes.Add (scope);
- return true;
- }
- }
- return false;
- }
- SequencePoint LineToSequencePoint (LineNumberEntry line)
- {
- var source = symbol_file.GetSourceFile (line.File);
- return new SequencePoint (line.Offset, GetDocument (source)) {
- StartLine = line.Row,
- EndLine = line.EndRow,
- StartColumn = line.Column,
- EndColumn = line.EndColumn,
- };
- }
- public void Dispose ()
- {
- symbol_file.Dispose ();
- }
- }
- static class MethodEntryExtensions {
- public static bool HasColumnInfo (this MethodEntry entry)
- {
- return (entry.MethodFlags & MethodEntry.Flags.ColumnsInfoIncluded) != 0;
- }
- public static bool HasEndInfo (this MethodEntry entry)
- {
- return (entry.MethodFlags & MethodEntry.Flags.EndInfoIncluded) != 0;
- }
- }
- }