mirror of https://github.com/icsharpcode/ILSpy.git
13 changed files with 318 additions and 201 deletions
@ -0,0 +1,25 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using ICSharpCode.Decompiler; |
||||||
|
|
||||||
|
namespace Decompiler |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Stores the C# code mappings.
|
||||||
|
/// </summary>
|
||||||
|
public static class CSharpCodeMapping |
||||||
|
{ |
||||||
|
static Dictionary<string, List<MethodMapping>> codeMappings = new Dictionary<string, List<MethodMapping>>(); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stores the source codes mappings: CSharp <-> editor lines
|
||||||
|
/// </summary>
|
||||||
|
public static Dictionary<string, List<MethodMapping>> SourceCodeMappings { |
||||||
|
get { return codeMappings; } |
||||||
|
set { codeMappings = value; } |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,157 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using Decompiler; |
||||||
|
using ICSharpCode.Decompiler.Disassembler; |
||||||
|
using Mono.Cecil; |
||||||
|
|
||||||
|
namespace ICSharpCode.Decompiler |
||||||
|
{ |
||||||
|
public enum DecompiledLanguages |
||||||
|
{ |
||||||
|
IL, |
||||||
|
CSharp |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maps the source code to IL.
|
||||||
|
/// </summary>
|
||||||
|
public class SourceCodeMapping |
||||||
|
{ |
||||||
|
public int SourceCodeLine { get; set; } |
||||||
|
|
||||||
|
public ILRange ILInstructionOffset { get; set; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stores the method information and its source code mappings.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class MethodMapping |
||||||
|
{ |
||||||
|
public string TypeName { get; set; } |
||||||
|
|
||||||
|
public uint MetadataToken { get; set; } |
||||||
|
|
||||||
|
public List<SourceCodeMapping> MethodCodeMappings { get; set; } |
||||||
|
} |
||||||
|
|
||||||
|
public static class CodeMappings |
||||||
|
{ |
||||||
|
public static Dictionary<string, List<MethodMapping>> GetStorage(DecompiledLanguages language) |
||||||
|
{ |
||||||
|
Dictionary<string, List<MethodMapping>> storage = null; |
||||||
|
|
||||||
|
switch (language) { |
||||||
|
case DecompiledLanguages.IL: |
||||||
|
storage = ILCodeMapping.SourceCodeMappings; |
||||||
|
break; |
||||||
|
case DecompiledLanguages.CSharp: |
||||||
|
storage = CSharpCodeMapping.SourceCodeMappings; |
||||||
|
break; |
||||||
|
default: |
||||||
|
throw new System.Exception("Invalid value for DecompiledLanguages"); |
||||||
|
} |
||||||
|
|
||||||
|
return storage; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create code mapping for a method.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="method">Method to create the mapping for.</param>
|
||||||
|
/// <param name="sourceCodeMappings">Source code mapping storage.</param>
|
||||||
|
public static MethodMapping CreateCodeMapping( |
||||||
|
this MethodDefinition method, |
||||||
|
Dictionary<string, List<MethodMapping>> sourceCodeMappings) |
||||||
|
{ |
||||||
|
// create IL code mappings - used in debugger
|
||||||
|
MethodMapping currentMethodMapping = null; |
||||||
|
if (sourceCodeMappings.ContainsKey(method.DeclaringType.FullName)) { |
||||||
|
var mapping = sourceCodeMappings[method.DeclaringType.FullName]; |
||||||
|
if (mapping.Find(map => (int)map.MetadataToken == method.MetadataToken.ToInt32()) == null) { |
||||||
|
currentMethodMapping = new MethodMapping() { |
||||||
|
MetadataToken = (uint)method.MetadataToken.ToInt32(), |
||||||
|
TypeName = method.DeclaringType.FullName, |
||||||
|
MethodCodeMappings = new List<SourceCodeMapping>() |
||||||
|
}; |
||||||
|
mapping.Add(currentMethodMapping); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return currentMethodMapping; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets source code mapping and metadata token based on type name and line number.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="codeMappings">Code mappings storage.</param>
|
||||||
|
/// <param name="typeName">Type name.</param>
|
||||||
|
/// <param name="lineNumber">Line number.</param>
|
||||||
|
/// <param name="metadataToken">Metadata token.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static SourceCodeMapping GetInstructionByTypeAndLine( |
||||||
|
this Dictionary<string, List<MethodMapping>> codeMappings, |
||||||
|
string typeName, |
||||||
|
int lineNumber, |
||||||
|
out uint metadataToken) |
||||||
|
{ |
||||||
|
if (!codeMappings.ContainsKey(typeName)) { |
||||||
|
metadataToken = 0; |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
if (lineNumber <= 0) { |
||||||
|
metadataToken = 0; |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
var methodMappings = codeMappings[typeName]; |
||||||
|
foreach (var maping in methodMappings) { |
||||||
|
var map = maping.MethodCodeMappings.Find(m => m.SourceCodeLine == lineNumber); |
||||||
|
if (map != null) { |
||||||
|
metadataToken = maping.MetadataToken; |
||||||
|
return map; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
metadataToken = 0; |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the source code and type name from metadata token and offset.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="codeMappings">Code mappings storage.</param>
|
||||||
|
/// <param name="token">Metadata token.</param>
|
||||||
|
/// <param name="ilOffset">IL offset.</param>
|
||||||
|
/// <param name="typeName">Type name.</param>
|
||||||
|
/// <param name="line">Line number.</param>
|
||||||
|
public static void GetSourceCodeFromMetadataTokenAndOffset( |
||||||
|
this Dictionary<string, List<MethodMapping>> codeMappings, |
||||||
|
uint token, |
||||||
|
int ilOffset, |
||||||
|
out string typeName, |
||||||
|
out int line) |
||||||
|
{ |
||||||
|
typeName = null; |
||||||
|
line = 0; |
||||||
|
|
||||||
|
foreach (var typename in codeMappings.Keys) { |
||||||
|
var mapping = codeMappings[typename].Find(m => m.MetadataToken == token); |
||||||
|
if (mapping == null) |
||||||
|
continue; |
||||||
|
|
||||||
|
var codeMapping = mapping.MethodCodeMappings.Find( |
||||||
|
cm => cm.ILInstructionOffset.From <= ilOffset && ilOffset <= cm.ILInstructionOffset.To); |
||||||
|
if (codeMapping == null) |
||||||
|
continue; |
||||||
|
|
||||||
|
typeName = typename; |
||||||
|
line = codeMapping.SourceCodeLine; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -1,124 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
|
||||||
using System; |
|
||||||
using System.Collections.Generic; |
|
||||||
using Mono.Cecil.Cil; |
|
||||||
|
|
||||||
namespace ICSharpCode.Decompiler.Disassembler |
|
||||||
{ |
|
||||||
public class ILCodeMapping |
|
||||||
{ |
|
||||||
public int SourceCodeLine { get; set; } |
|
||||||
|
|
||||||
public Instruction ILInstruction { get; set; } |
|
||||||
} |
|
||||||
|
|
||||||
public class MethodMapping |
|
||||||
{ |
|
||||||
public string TypeName { get; set; } |
|
||||||
|
|
||||||
public uint MetadataToken { get; set; } |
|
||||||
|
|
||||||
public List<ILCodeMapping> MethodCodeMappings { get; set; } |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finds the IL instruction given a source code line number.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sourceCodeLine">Source code line number.</param>
|
|
||||||
/// <returns>IL Instruction or null, if the instruction was not found.</returns>
|
|
||||||
public Instruction FindByLine(int sourceCodeLine) |
|
||||||
{ |
|
||||||
if (sourceCodeLine <= 0) |
|
||||||
throw new ArgumentException("The source line must be greater thatn 0."); |
|
||||||
|
|
||||||
if (MethodCodeMappings == null || MethodCodeMappings.Count == 0) |
|
||||||
return null; |
|
||||||
|
|
||||||
foreach (var codeMapping in MethodCodeMappings) { |
|
||||||
if (codeMapping.SourceCodeLine == sourceCodeLine) |
|
||||||
return codeMapping.ILInstruction; |
|
||||||
} |
|
||||||
|
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finds the source code line given an IL instruction offset.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instruction">IL Instruction offset.</param>
|
|
||||||
/// <returns>Source code line, if it is found, -1 otherwise.</returns>
|
|
||||||
public int FindByInstruction(int instructionOffset) |
|
||||||
{ |
|
||||||
if (instructionOffset <= 0) |
|
||||||
throw new ArgumentNullException("The instruction offset cannot be lower than 0."); |
|
||||||
|
|
||||||
if (MethodCodeMappings == null || MethodCodeMappings.Count == 0) |
|
||||||
return -1; |
|
||||||
|
|
||||||
foreach (var codeMapping in MethodCodeMappings) { |
|
||||||
if (codeMapping.ILInstruction.Offset == instructionOffset) |
|
||||||
return codeMapping.SourceCodeLine; |
|
||||||
} |
|
||||||
|
|
||||||
return -1; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static class ILCodeMappings |
|
||||||
{ |
|
||||||
static Dictionary<string, List<MethodMapping>> ilCodeMappings = new Dictionary<string, List<MethodMapping>>(); |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Stores the source codes mappings: IL <-> editor lines
|
|
||||||
/// </summary>
|
|
||||||
public static Dictionary<string, List<MethodMapping>> ILSourceCodeMappings { |
|
||||||
get { return ilCodeMappings; } |
|
||||||
set { ilCodeMappings = value; } |
|
||||||
} |
|
||||||
|
|
||||||
public static ILCodeMapping GetInstructionByTypeAndLine(string typeName, int lineNumber, out uint metadataToken) |
|
||||||
{ |
|
||||||
if (!ilCodeMappings.ContainsKey(typeName)) { |
|
||||||
metadataToken = 0; |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
if (lineNumber <= 0) { |
|
||||||
metadataToken = 0; |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
var methodMappings = ilCodeMappings[typeName]; |
|
||||||
foreach (var maping in methodMappings) { |
|
||||||
var ilMap = maping.MethodCodeMappings.Find(m => m.SourceCodeLine == lineNumber); |
|
||||||
if (ilMap != null) { |
|
||||||
metadataToken = maping.MetadataToken; |
|
||||||
return ilMap; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
metadataToken = 0; |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
public static void GetSourceCodeFromMetadataTokenAndOffset(uint token, int ilOffset, out string typeName, out int line) |
|
||||||
{ |
|
||||||
typeName = null; |
|
||||||
line = 0; |
|
||||||
|
|
||||||
foreach (var typename in ilCodeMappings.Keys) { |
|
||||||
var mapping = ilCodeMappings[typename].Find(m => m.MetadataToken == token); |
|
||||||
if (mapping == null) |
|
||||||
continue; |
|
||||||
|
|
||||||
var ilCodeMapping = mapping.MethodCodeMappings.Find(cm => cm.ILInstruction.Offset == ilOffset); |
|
||||||
if (ilCodeMapping == null) |
|
||||||
continue; |
|
||||||
|
|
||||||
typeName = typename; |
|
||||||
line = ilCodeMapping.SourceCodeLine; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,24 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
|
||||||
|
namespace ICSharpCode.Decompiler.Disassembler |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Stores the IL code mappings.
|
||||||
|
/// </summary>
|
||||||
|
public static class ILCodeMapping |
||||||
|
{ |
||||||
|
static Dictionary<string, List<MethodMapping>> codeMappings = new Dictionary<string, List<MethodMapping>>(); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stores the source codes mappings: IL <-> editor lines
|
||||||
|
/// </summary>
|
||||||
|
public static Dictionary<string, List<MethodMapping>> SourceCodeMappings { |
||||||
|
get { return codeMappings; } |
||||||
|
set { codeMappings = value; } |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue