Browse Source

Create IL <-> editor code mappings

pull/191/merge
Eusebiu Marcu 15 years ago
parent
commit
556fb79e8c
  1. 1
      Debugger/ILSpy.Debugger/ILSpy.Debugger.csproj
  2. 2
      Debugger/ILSpy.Debugger/Services/Debugger/DebuggerService.cs
  3. 66
      ICSharpCode.Decompiler/Disassembler/CodeMappings.cs
  4. 34
      ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
  5. 15
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  6. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  7. 2
      ICSharpCode.Decompiler/ITextOutput.cs
  8. 4
      ICSharpCode.Decompiler/PlainTextOutput.cs
  9. 28
      ILSpy.sln
  10. 8
      ILSpy/TextView/AvalonEditTextOutput.cs

1
Debugger/ILSpy.Debugger/ILSpy.Debugger.csproj

@ -78,7 +78,6 @@
<Compile Include="Models\TreeModel\Utils.cs" /> <Compile Include="Models\TreeModel\Utils.cs" />
<Compile Include="Services\Debugger\DebuggerHelper.cs" /> <Compile Include="Services\Debugger\DebuggerHelper.cs" />
<Compile Include="Services\Debugger\DebuggerService.cs" /> <Compile Include="Services\Debugger\DebuggerService.cs" />
<Compile Include="Services\Debugger\DefaultDebugger.cs" />
<Compile Include="Services\Debugger\IDebugger.cs" /> <Compile Include="Services\Debugger\IDebugger.cs" />
<Compile Include="Services\Debugger\ListHelper.cs" /> <Compile Include="Services\Debugger\ListHelper.cs" />
<Compile Include="Services\Debugger\RemotingConfigurationHelpper.cs" /> <Compile Include="Services\Debugger\RemotingConfigurationHelpper.cs" />

2
Debugger/ILSpy.Debugger/Services/Debugger/DebuggerService.cs

@ -22,7 +22,7 @@ namespace ILSpy.Debugger.Services
static IDebugger GetCompatibleDebugger() static IDebugger GetCompatibleDebugger()
{ {
return new DefaultDebugger(); return new WindowsDebugger();
} }
/// <summary> /// <summary>

66
ICSharpCode.Decompiler/Disassembler/CodeMappings.cs

@ -0,0 +1,66 @@
// 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 int 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;
}
}
}

34
ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs

@ -47,6 +47,20 @@ namespace ICSharpCode.Decompiler.Disassembler
public void Disassemble(MethodBody body) public void Disassemble(MethodBody body)
{ {
// create mappings
MethodMapping currentMethodMapping = null;
if (ReflectionDisassembler.ILSourceCodeMappings.ContainsKey(body.Method.DeclaringType.FullName)) {
var mapping = ReflectionDisassembler.ILSourceCodeMappings[body.Method.DeclaringType.FullName];
if (mapping.Find(map => map.MetadataToken == body.Method.MetadataToken.ToInt32()) == null) {
currentMethodMapping = new MethodMapping() {
MetadataToken = body.Method.MetadataToken.ToInt32(),
TypeName = body.Method.DeclaringType.FullName,
MethodCodeMappings = new List<ILCodeMapping>()
};
mapping.Add(currentMethodMapping);
}
}
MethodDefinition method = body.Method; MethodDefinition method = body.Method;
output.WriteLine("// Method begins at RVA 0x{0:x4}", method.RVA); output.WriteLine("// Method begins at RVA 0x{0:x4}", method.RVA);
output.WriteLine("// Code size {0} (0x{0:x})", body.CodeSize); output.WriteLine("// Code size {0} (0x{0:x})", body.CodeSize);
@ -74,9 +88,15 @@ namespace ICSharpCode.Decompiler.Disassembler
if (detectControlStructure && body.Instructions.Count > 0) { if (detectControlStructure && body.Instructions.Count > 0) {
Instruction inst = body.Instructions[0]; Instruction inst = body.Instructions[0];
WriteStructureBody(new ILStructure(body), ref inst); WriteStructureBody(new ILStructure(body), ref inst, currentMethodMapping);
} else { } else {
foreach (var inst in method.Body.Instructions) { foreach (var inst in method.Body.Instructions) {
// add IL code mappings
currentMethodMapping.MethodCodeMappings.Add(new ILCodeMapping() {
SourceCodeLine = output.CurrentLine,
ILInstruction = inst
});
inst.WriteTo(output); inst.WriteTo(output);
output.WriteLine(); output.WriteLine();
} }
@ -133,15 +153,23 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Indent(); output.Indent();
} }
void WriteStructureBody(ILStructure s, ref Instruction inst) void WriteStructureBody(ILStructure s, ref Instruction inst, MethodMapping currentMethodMapping)
{ {
int childIndex = 0; int childIndex = 0;
while (inst != null && inst.Offset < s.EndOffset) { while (inst != null && inst.Offset < s.EndOffset) {
// add IL code mappings
if (currentMethodMapping != null) {
currentMethodMapping.MethodCodeMappings.Add(new ILCodeMapping() {
SourceCodeLine = output.CurrentLine,
ILInstruction = inst
});
}
int offset = inst.Offset; int offset = inst.Offset;
if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) { if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) {
ILStructure child = s.Children[childIndex++]; ILStructure child = s.Children[childIndex++];
WriteStructureHeader(child); WriteStructureHeader(child);
WriteStructureBody(child, ref inst); WriteStructureBody(child, ref inst, currentMethodMapping);
WriteStructureFooter(child); WriteStructureFooter(child);
} else { } else {
inst.WriteTo(output); inst.WriteTo(output);

15
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -36,6 +36,16 @@ namespace ICSharpCode.Decompiler.Disassembler
bool isInType; // whether we are currently disassembling a whole type (-> defaultCollapsed for foldings) bool isInType; // whether we are currently disassembling a whole type (-> defaultCollapsed for foldings)
MethodBodyDisassembler methodBodyDisassembler; MethodBodyDisassembler methodBodyDisassembler;
static Dictionary<string, List<MethodMapping>> ilCodeMappings = new Dictionary<string, List<MethodMapping>>();
/// <summary>
/// Stores the source codes mappings: IL &lt;-&gt; editor lines
/// </summary>
public static Dictionary<string, List<MethodMapping>> ILSourceCodeMappings {
get { return ilCodeMappings; }
set { ilCodeMappings = value; }
}
public ReflectionDisassembler(ITextOutput output, bool detectControlStructure, CancellationToken cancellationToken) public ReflectionDisassembler(ITextOutput output, bool detectControlStructure, CancellationToken cancellationToken)
{ {
if (output == null) if (output == null)
@ -101,6 +111,11 @@ namespace ICSharpCode.Decompiler.Disassembler
void DisassembleMethodInternal(MethodDefinition method) void DisassembleMethodInternal(MethodDefinition method)
{ {
// create mappings for types that were not disassebled
if (!ilCodeMappings.ContainsKey(method.DeclaringType.FullName)) {
ilCodeMappings.Add(method.DeclaringType.FullName, new List<MethodMapping>());
}
// .method public hidebysig specialname // .method public hidebysig specialname
// instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed // instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed
// //

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -60,6 +60,7 @@
<Compile Include="Ast\Transforms\RestoreLoop.cs" /> <Compile Include="Ast\Transforms\RestoreLoop.cs" />
<Compile Include="Ast\Transforms\SimplifyTypeReferences.cs" /> <Compile Include="Ast\Transforms\SimplifyTypeReferences.cs" />
<Compile Include="CecilExtensions.cs" /> <Compile Include="CecilExtensions.cs" />
<Compile Include="Disassembler\CodeMappings.cs" />
<Compile Include="Disassembler\DisassemblerHelpers.cs" /> <Compile Include="Disassembler\DisassemblerHelpers.cs" />
<Compile Include="Disassembler\ILStructure.cs" /> <Compile Include="Disassembler\ILStructure.cs" />
<Compile Include="Disassembler\MethodBodyDisassembler.cs" /> <Compile Include="Disassembler\MethodBodyDisassembler.cs" />

2
ICSharpCode.Decompiler/ITextOutput.cs

@ -22,6 +22,8 @@ namespace ICSharpCode.Decompiler
{ {
public interface ITextOutput public interface ITextOutput
{ {
int CurrentLine { get; set; }
void Indent(); void Indent();
void Unindent(); void Unindent();
void Write(char ch); void Write(char ch);

4
ICSharpCode.Decompiler/PlainTextOutput.cs

@ -32,6 +32,7 @@ namespace ICSharpCode.Decompiler
if (writer == null) if (writer == null)
throw new ArgumentNullException("writer"); throw new ArgumentNullException("writer");
this.writer = writer; this.writer = writer;
CurrentLine = 1;
} }
public PlainTextOutput() public PlainTextOutput()
@ -39,6 +40,8 @@ namespace ICSharpCode.Decompiler
this.writer = new StringWriter(); this.writer = new StringWriter();
} }
public int CurrentLine { get; set; }
public override string ToString() public override string ToString()
{ {
return writer.ToString(); return writer.ToString();
@ -80,6 +83,7 @@ namespace ICSharpCode.Decompiler
{ {
writer.WriteLine(); writer.WriteLine();
needsIndent = true; needsIndent = true;
++CurrentLine;
} }
public void WriteDefinition(string text, object definition) public void WriteDefinition(string text, object definition)

28
ILSpy.sln

@ -6,25 +6,25 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Debugger", "Debugger", "{BF
ProjectSection(SolutionItems) = postProject ProjectSection(SolutionItems) = postProject
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Debugger.Core", "Debugger\Debugger.Core\Debugger.Core.csproj", "{1D18D788-F7EE-4585-A23B-34DC8EC63CB8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy.Debugger", "Debugger\ILSpy.Debugger\ILSpy.Debugger.csproj", "{6D3D0F0D-348D-456A-A6ED-E9BD5EFABB6A}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy.Debugger", "Debugger\ILSpy.Debugger\ILSpy.Debugger.csproj", "{6D3D0F0D-348D-456A-A6ED-E9BD5EFABB6A}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Debugger.Core", "Debugger\Debugger.Core\Debugger.Core.csproj", "{1D18D788-F7EE-4585-A23B-34DC8EC63CB8}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{4E076A9B-159A-45C4-9E34-AE1D20D83E42}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{4E076A9B-159A-45C4-9E34-AE1D20D83E42}"
ProjectSection(SolutionItems) = postProject ProjectSection(SolutionItems) = postProject
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil", "Mono.Cecil\Mono.Cecil.csproj", "{D68133BD-1E63-496E-9EDE-4FBDBF77B486}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactory", "Decompiler\lib\NRefactory\Project\NRefactory.csproj", "{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.AvalonEdit", "AvalonEdit\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj", "{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop.Dom", "Libraries\ICSharpCode.SharpDevelop.Dom\Project\ICSharpCode.SharpDevelop.Dom.csproj", "{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory", "NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj", "{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.TreeView", "SharpTreeView\ICSharpCode.TreeView.csproj", "{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.TreeView", "SharpTreeView\ICSharpCode.TreeView.csproj", "{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory", "NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj", "{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop.Dom", "Libraries\ICSharpCode.SharpDevelop.Dom\Project\ICSharpCode.SharpDevelop.Dom.csproj", "{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactory", "Decompiler\lib\NRefactory\Project\NRefactory.csproj", "{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.AvalonEdit", "AvalonEdit\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj", "{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil", "Mono.Cecil\Mono.Cecil.csproj", "{D68133BD-1E63-496E-9EDE-4FBDBF77B486}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy", "ILSpy\ILSpy.csproj", "{1E85EFF9-E370-4683-83E4-8A3D063FF791}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy", "ILSpy\ILSpy.csproj", "{1E85EFF9-E370-4683-83E4-8A3D063FF791}"
EndProject EndProject
@ -117,13 +117,13 @@ Global
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
{6D3D0F0D-348D-456A-A6ED-E9BD5EFABB6A} = {BF79A230-0918-47DF-8A36-776779A331DE}
{1D18D788-F7EE-4585-A23B-34DC8EC63CB8} = {BF79A230-0918-47DF-8A36-776779A331DE} {1D18D788-F7EE-4585-A23B-34DC8EC63CB8} = {BF79A230-0918-47DF-8A36-776779A331DE}
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195} = {4E076A9B-159A-45C4-9E34-AE1D20D83E42} {6D3D0F0D-348D-456A-A6ED-E9BD5EFABB6A} = {BF79A230-0918-47DF-8A36-776779A331DE}
{3B2A5653-EC97-4001-BB9B-D90F1AF2C371} = {4E076A9B-159A-45C4-9E34-AE1D20D83E42}
{DDE2A481-8271-4EAC-A330-8FA6A38D13D1} = {4E076A9B-159A-45C4-9E34-AE1D20D83E42}
{924EE450-603D-49C1-A8E5-4AFAA31CE6F3} = {4E076A9B-159A-45C4-9E34-AE1D20D83E42}
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1} = {4E076A9B-159A-45C4-9E34-AE1D20D83E42}
{D68133BD-1E63-496E-9EDE-4FBDBF77B486} = {4E076A9B-159A-45C4-9E34-AE1D20D83E42} {D68133BD-1E63-496E-9EDE-4FBDBF77B486} = {4E076A9B-159A-45C4-9E34-AE1D20D83E42}
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1} = {4E076A9B-159A-45C4-9E34-AE1D20D83E42}
{924EE450-603D-49C1-A8E5-4AFAA31CE6F3} = {4E076A9B-159A-45C4-9E34-AE1D20D83E42}
{DDE2A481-8271-4EAC-A330-8FA6A38D13D1} = {4E076A9B-159A-45C4-9E34-AE1D20D83E42}
{3B2A5653-EC97-4001-BB9B-D90F1AF2C371} = {4E076A9B-159A-45C4-9E34-AE1D20D83E42}
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195} = {4E076A9B-159A-45C4-9E34-AE1D20D83E42}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

8
ILSpy/TextView/AvalonEditTextOutput.cs

@ -86,6 +86,11 @@ namespace ICSharpCode.ILSpy.TextView
/// <summary>Embedded UIElements, see <see cref="UIElementGenerator"/>.</summary> /// <summary>Embedded UIElements, see <see cref="UIElementGenerator"/>.</summary>
public readonly List<KeyValuePair<int, Lazy<UIElement>>> UIElements = new List<KeyValuePair<int, Lazy<UIElement>>>(); public readonly List<KeyValuePair<int, Lazy<UIElement>>> UIElements = new List<KeyValuePair<int, Lazy<UIElement>>>();
public AvalonEditTextOutput()
{
CurrentLine = 1;
}
/// <summary> /// <summary>
/// Gets the list of references (hyperlinks). /// Gets the list of references (hyperlinks).
/// </summary> /// </summary>
@ -104,6 +109,8 @@ namespace ICSharpCode.ILSpy.TextView
get { return b.Length; } get { return b.Length; }
} }
public int CurrentLine { get; set; }
#region Text Document #region Text Document
TextDocument textDocument; TextDocument textDocument;
@ -173,6 +180,7 @@ namespace ICSharpCode.ILSpy.TextView
{ {
Debug.Assert(textDocument == null); Debug.Assert(textDocument == null);
b.AppendLine(); b.AppendLine();
++CurrentLine;
needsIndent = true; needsIndent = true;
if (this.TextLength > LengthLimit) { if (this.TextLength > LengthLimit) {
throw new OutputLengthExceededException(); throw new OutputLengthExceededException();

Loading…
Cancel
Save