|
|
@ -19,6 +19,17 @@ namespace ICSharpCode.Decompiler |
|
|
|
CSharp |
|
|
|
CSharp |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// Interface for decompliler classes : AstBuilder & ReflectionDisassembler.
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
public interface ICodeMappings |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// Gets the code mappings.
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
Tuple<string, List<MemberMapping>> CodeMappings { get; } |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// Maps the source code to IL.
|
|
|
|
/// Maps the source code to IL.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
@ -122,30 +133,7 @@ namespace ICSharpCode.Decompiler |
|
|
|
/// Code mappings helper class.
|
|
|
|
/// Code mappings helper class.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public static class CodeMappings |
|
|
|
public static class CodeMappings |
|
|
|
{ |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// Gets the storage of code mappings for a language.
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
/// <param name="language">A language.</param>
|
|
|
|
|
|
|
|
/// <returns>The storage of code mappings.</returns>
|
|
|
|
|
|
|
|
public static ConcurrentDictionary<string, List<MemberMapping>> GetStorage(DecompiledLanguages language) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
ConcurrentDictionary<string, List<MemberMapping>> 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>
|
|
|
|
/// <summary>
|
|
|
|
/// Create code mapping for a method.
|
|
|
|
/// Create code mapping for a method.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
@ -153,18 +141,18 @@ namespace ICSharpCode.Decompiler |
|
|
|
/// <param name="sourceCodeMappings">Source code mapping storage.</param>
|
|
|
|
/// <param name="sourceCodeMappings">Source code mapping storage.</param>
|
|
|
|
internal static MemberMapping CreateCodeMapping( |
|
|
|
internal static MemberMapping CreateCodeMapping( |
|
|
|
this MethodDefinition member, |
|
|
|
this MethodDefinition member, |
|
|
|
ConcurrentDictionary<string, List<MemberMapping>> codeMappings) |
|
|
|
Tuple<string, List<MemberMapping>> codeMappings) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (member == null || !member.HasBody) |
|
|
|
if (member == null || !member.HasBody) |
|
|
|
return null; |
|
|
|
return null; |
|
|
|
|
|
|
|
|
|
|
|
if (codeMappings == null) |
|
|
|
if (codeMappings == null) |
|
|
|
throw new ArgumentNullException("CodeMappings storage must be valid!"); |
|
|
|
return null; |
|
|
|
|
|
|
|
|
|
|
|
// create IL/CSharp code mappings - used in debugger
|
|
|
|
// create IL/CSharp code mappings - used in debugger
|
|
|
|
MemberMapping currentMemberMapping = null; |
|
|
|
MemberMapping currentMemberMapping = null; |
|
|
|
if (codeMappings.ContainsKey(member.DeclaringType.FullName)) { |
|
|
|
if (codeMappings.Item1 == member.DeclaringType.FullName) { |
|
|
|
var mapping = codeMappings[member.DeclaringType.FullName]; |
|
|
|
var mapping = codeMappings.Item2; |
|
|
|
if (mapping.Find(map => (int)map.MetadataToken == member.MetadataToken.ToInt32()) == null) { |
|
|
|
if (mapping.Find(map => (int)map.MetadataToken == member.MetadataToken.ToInt32()) == null) { |
|
|
|
currentMemberMapping = new MemberMapping() { |
|
|
|
currentMemberMapping = new MemberMapping() { |
|
|
|
MetadataToken = (uint)member.MetadataToken.ToInt32(), |
|
|
|
MetadataToken = (uint)member.MetadataToken.ToInt32(), |
|
|
@ -188,15 +176,15 @@ namespace ICSharpCode.Decompiler |
|
|
|
/// <param name="metadataToken">Metadata token.</param>
|
|
|
|
/// <param name="metadataToken">Metadata token.</param>
|
|
|
|
/// <returns></returns>
|
|
|
|
/// <returns></returns>
|
|
|
|
public static SourceCodeMapping GetInstructionByTypeAndLine( |
|
|
|
public static SourceCodeMapping GetInstructionByTypeAndLine( |
|
|
|
this ConcurrentDictionary<string, List<MemberMapping>> codeMappings, |
|
|
|
this Tuple<string, List<MemberMapping>> codeMappings, |
|
|
|
string typeName, |
|
|
|
string memberReferenceName, |
|
|
|
int lineNumber, |
|
|
|
int lineNumber, |
|
|
|
out uint metadataToken) |
|
|
|
out uint metadataToken) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (codeMappings == null) |
|
|
|
if (codeMappings == null) |
|
|
|
throw new ArgumentNullException("CodeMappings storage must be valid!"); |
|
|
|
throw new ArgumentNullException("CodeMappings storage must be valid!"); |
|
|
|
|
|
|
|
|
|
|
|
if (!codeMappings.ContainsKey(typeName)) { |
|
|
|
if (codeMappings.Item1 != memberReferenceName) { |
|
|
|
metadataToken = 0; |
|
|
|
metadataToken = 0; |
|
|
|
return null; |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
@ -206,7 +194,7 @@ namespace ICSharpCode.Decompiler |
|
|
|
return null; |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var methodMappings = codeMappings[typeName]; |
|
|
|
var methodMappings = codeMappings.Item2; |
|
|
|
foreach (var maping in methodMappings) { |
|
|
|
foreach (var maping in methodMappings) { |
|
|
|
var map = maping.MemberCodeMappings.Find(m => m.SourceCodeLine == lineNumber); |
|
|
|
var map = maping.MemberCodeMappings.Find(m => m.SourceCodeLine == lineNumber); |
|
|
|
if (map != null) { |
|
|
|
if (map != null) { |
|
|
@ -229,22 +217,22 @@ namespace ICSharpCode.Decompiler |
|
|
|
/// <param name="isMatch">True, if perfect match.</param>
|
|
|
|
/// <param name="isMatch">True, if perfect match.</param>
|
|
|
|
/// <returns>A code mapping.</returns>
|
|
|
|
/// <returns>A code mapping.</returns>
|
|
|
|
public static SourceCodeMapping GetInstructionByTypeTokenAndOffset( |
|
|
|
public static SourceCodeMapping GetInstructionByTypeTokenAndOffset( |
|
|
|
this ConcurrentDictionary<string, List<MemberMapping>> codeMappings, |
|
|
|
this Tuple<string, List<MemberMapping>> codeMappings, |
|
|
|
string typeName, |
|
|
|
string memberReferenceName, |
|
|
|
uint token, |
|
|
|
uint token, |
|
|
|
int ilOffset, out bool isMatch) |
|
|
|
int ilOffset, out bool isMatch) |
|
|
|
{ |
|
|
|
{ |
|
|
|
isMatch = false; |
|
|
|
isMatch = false; |
|
|
|
typeName = typeName.Replace("+", "/"); |
|
|
|
memberReferenceName = memberReferenceName.Replace("+", "/"); |
|
|
|
|
|
|
|
|
|
|
|
if (codeMappings == null) |
|
|
|
if (codeMappings == null) |
|
|
|
throw new ArgumentNullException("CodeMappings storage must be valid!"); |
|
|
|
throw new ArgumentNullException("CodeMappings storage must be valid!"); |
|
|
|
|
|
|
|
|
|
|
|
if (!codeMappings.ContainsKey(typeName)) { |
|
|
|
if (codeMappings.Item1 != memberReferenceName) { |
|
|
|
return null; |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var methodMappings = codeMappings[typeName]; |
|
|
|
var methodMappings = codeMappings.Item2; |
|
|
|
var maping = methodMappings.Find(m => m.MetadataToken == token); |
|
|
|
var maping = methodMappings.Find(m => m.MetadataToken == token); |
|
|
|
|
|
|
|
|
|
|
|
if (maping == null) { |
|
|
|
if (maping == null) { |
|
|
@ -279,8 +267,8 @@ namespace ICSharpCode.Decompiler |
|
|
|
/// <param name="line">Line number.</param>
|
|
|
|
/// <param name="line">Line number.</param>
|
|
|
|
/// <remarks>It is possible to exist to different types from different assemblies with the same metadata token.</remarks>
|
|
|
|
/// <remarks>It is possible to exist to different types from different assemblies with the same metadata token.</remarks>
|
|
|
|
public static bool GetSourceCodeFromMetadataTokenAndOffset( |
|
|
|
public static bool GetSourceCodeFromMetadataTokenAndOffset( |
|
|
|
this ConcurrentDictionary<string, List<MemberMapping>> codeMappings, |
|
|
|
this Tuple<string, List<MemberMapping>> codeMappings, |
|
|
|
string typeName, |
|
|
|
string memberReferenceName, |
|
|
|
uint token, |
|
|
|
uint token, |
|
|
|
int ilOffset, |
|
|
|
int ilOffset, |
|
|
|
out MemberReference type, |
|
|
|
out MemberReference type, |
|
|
@ -292,11 +280,11 @@ namespace ICSharpCode.Decompiler |
|
|
|
if (codeMappings == null) |
|
|
|
if (codeMappings == null) |
|
|
|
throw new ArgumentNullException("CodeMappings storage must be valid!"); |
|
|
|
throw new ArgumentNullException("CodeMappings storage must be valid!"); |
|
|
|
|
|
|
|
|
|
|
|
typeName = typeName.Replace("+", "/"); |
|
|
|
memberReferenceName = memberReferenceName.Replace("+", "/"); |
|
|
|
if (!codeMappings.ContainsKey(typeName)) |
|
|
|
if (codeMappings.Item1 != memberReferenceName) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
var mapping = codeMappings[typeName].Find(m => m.MetadataToken == token); |
|
|
|
var mapping = codeMappings.Item2.Find(m => m.MetadataToken == token); |
|
|
|
if (mapping == null) |
|
|
|
if (mapping == null) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|