Browse Source

Read variable names from debug symbols (.pdb files), if available. Based on #122.

pull/150/head
Daniel Grunwald 15 years ago
parent
commit
51c2321a92
  1. 22
      ICSharpCode.Decompiler/Ast/NameVariables.cs
  2. 15
      ICSharpCode.Decompiler/DecompilerSettings.cs
  3. 30
      ILSpy.sln
  4. 1
      ILSpy/DecompilerSettingsPanel.xaml
  5. 2
      ILSpy/DecompilerSettingsPanel.xaml.cs
  6. 6
      ILSpy/ILSpy.csproj
  7. 22
      ILSpy/LoadedAssembly.cs
  8. 3
      ILSpy/OptionsDialog.xaml.cs
  9. 2
      Mono.Cecil/symbols/pdb/Mono.Cecil.Pdb/PdbHelper.cs
  10. 4
      TestPlugin/TestPlugin.csproj

22
ICSharpCode.Decompiler/Ast/NameVariables.cs

@ -42,8 +42,23 @@ namespace ICSharpCode.Decompiler.Ast
foreach (var p in parameters) foreach (var p in parameters)
nv.AddExistingName(p.Name); nv.AddExistingName(p.Name);
foreach (var v in variables) { foreach (var v in variables) {
if (v.IsGenerated) if (v.IsGenerated) {
// don't introduce names for variables generated by ILSpy - keep "expr"/"arg"
nv.AddExistingName(v.Name); nv.AddExistingName(v.Name);
} else if (v.OriginalVariable != null && context.Settings.UseDebugSymbols) {
string varName = v.OriginalVariable.Name;
if (string.IsNullOrEmpty(varName) || varName.StartsWith("V_", StringComparison.Ordinal) || varName.StartsWith("CS$", StringComparison.Ordinal))
{
// don't use the name from the debug symbols if it looks like a generated name
v.Name = null;
} else {
// use the name from the debug symbols
// (but ensure we don't use the same name for two variables)
v.Name = nv.GetAlternativeName(varName);
}
} else {
v.Name = null;
}
} }
// Now generate names: // Now generate names:
foreach (ILVariable p in parameters) { foreach (ILVariable p in parameters) {
@ -51,9 +66,8 @@ namespace ICSharpCode.Decompiler.Ast
p.Name = nv.GenerateNameForVariable(p, methodBody); p.Name = nv.GenerateNameForVariable(p, methodBody);
} }
foreach (ILVariable varDef in variables) { foreach (ILVariable varDef in variables) {
if (!varDef.IsGenerated) { if (string.IsNullOrEmpty(varDef.Name))
varDef.Name = nv.GenerateNameForVariable(varDef, methodBody); varDef.Name = nv.GenerateNameForVariable(varDef, methodBody);
}
} }
} }
@ -107,7 +121,7 @@ namespace ICSharpCode.Decompiler.Ast
string nameWithoutDigits = SplitName(oldVariableName, out number); string nameWithoutDigits = SplitName(oldVariableName, out number);
if (!typeNames.ContainsKey(nameWithoutDigits)) { if (!typeNames.ContainsKey(nameWithoutDigits)) {
typeNames.Add(nameWithoutDigits, 0); typeNames.Add(nameWithoutDigits, number - 1);
} }
int count = ++typeNames[nameWithoutDigits]; int count = ++typeNames[nameWithoutDigits];
if (count > 1) { if (count > 1) {

15
ICSharpCode.Decompiler/DecompilerSettings.cs

@ -164,6 +164,21 @@ namespace ICSharpCode.Decompiler
} }
} }
bool useDebugSymbols = true;
/// <summary>
/// Gets/Sets whether to use variable names from debug symbols, if available.
/// </summary>
public bool UseDebugSymbols {
get { return useDebugSymbols; }
set {
if (useDebugSymbols != value) {
useDebugSymbols = value;
OnPropertyChanged("UseDebugSymbols");
}
}
}
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName) protected virtual void OnPropertyChanged(string propertyName)

30
ILSpy.sln

@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Decompiler.Test
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestPlugin", "TestPlugin\TestPlugin.csproj", "{F32EBCC8-0E53-4421-867E-05B3D6E10C70}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestPlugin", "TestPlugin\TestPlugin.csproj", "{F32EBCC8-0E53-4421-867E-05B3D6E10C70}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Pdb", "Mono.Cecil\symbols\pdb\Mono.Cecil.Pdb.csproj", "{63E6915C-7EA4-4D76-AB28-0D7191EEA626}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -50,11 +52,11 @@ Global
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.ActiveCfg = net_4_0_Debug|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.ActiveCfg = net_4_0_Debug|Any CPU
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.Build.0 = net_2_0_Debug|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.Build.0 = net_4_0_Debug|Any CPU
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.Build.0 = net_4_0_Release|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.Build.0 = net_4_0_Release|Any CPU
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.ActiveCfg = net_4_0_Release|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.ActiveCfg = net_4_0_Release|Any CPU
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.Build.0 = net_2_0_Debug|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.Build.0 = net_4_0_Debug|Any CPU
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|Any CPU.Build.0 = Debug|Any CPU {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|x86.ActiveCfg = Debug|Any CPU {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|x86.ActiveCfg = Debug|Any CPU
@ -87,14 +89,22 @@ Global
{FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|Any CPU.Build.0 = Release|x86 {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|Any CPU.Build.0 = Release|x86
{FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|x86.ActiveCfg = Release|x86 {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|x86.ActiveCfg = Release|x86
{FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|x86.Build.0 = Release|x86 {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|x86.Build.0 = Release|x86
{F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Debug|Any CPU.Build.0 = Debug|x86 {F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Debug|Any CPU.ActiveCfg = Debug|x86 {F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Debug|x86.Build.0 = Debug|x86 {F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Debug|x86.Build.0 = Debug|Any CPU
{F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Debug|x86.ActiveCfg = Debug|x86 {F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Debug|x86.ActiveCfg = Debug|Any CPU
{F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Release|Any CPU.Build.0 = Release|x86 {F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Release|Any CPU.Build.0 = Release|Any CPU
{F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Release|Any CPU.ActiveCfg = Release|x86 {F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Release|x86.Build.0 = Release|x86 {F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Release|x86.Build.0 = Release|Any CPU
{F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Release|x86.ActiveCfg = Release|x86 {F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Release|x86.ActiveCfg = Release|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|x86.Build.0 = net_4_0_Debug|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|x86.ActiveCfg = net_4_0_Debug|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|Any CPU.Build.0 = net_4_0_Debug|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|x86.Build.0 = net_4_0_Debug|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|x86.ActiveCfg = net_4_0_Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

1
ILSpy/DecompilerSettingsPanel.xaml

@ -6,5 +6,6 @@
<CheckBox IsChecked="{Binding AnonymousMethods}">Decompile anonymous methods/lambdas</CheckBox> <CheckBox IsChecked="{Binding AnonymousMethods}">Decompile anonymous methods/lambdas</CheckBox>
<CheckBox IsChecked="{Binding YieldReturn}">Decompile enumerators (yield return)</CheckBox> <CheckBox IsChecked="{Binding YieldReturn}">Decompile enumerators (yield return)</CheckBox>
<CheckBox IsChecked="{Binding QueryExpressions}" IsEnabled="{Binding AnonymousMethods}">Decompile query expressions</CheckBox> <CheckBox IsChecked="{Binding QueryExpressions}" IsEnabled="{Binding AnonymousMethods}">Decompile query expressions</CheckBox>
<CheckBox IsChecked="{Binding UseDebugSymbols}">Use variable names from debug symbols, if available</CheckBox>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

2
ILSpy/DecompilerSettingsPanel.xaml.cs

@ -46,6 +46,7 @@ namespace ICSharpCode.ILSpy
s.AnonymousMethods = (bool?)e.Attribute("anonymousMethods") ?? s.AnonymousMethods; s.AnonymousMethods = (bool?)e.Attribute("anonymousMethods") ?? s.AnonymousMethods;
s.YieldReturn = (bool?)e.Attribute("yieldReturn") ?? s.YieldReturn; s.YieldReturn = (bool?)e.Attribute("yieldReturn") ?? s.YieldReturn;
s.QueryExpressions = (bool?)e.Attribute("queryExpressions") ?? s.QueryExpressions; s.QueryExpressions = (bool?)e.Attribute("queryExpressions") ?? s.QueryExpressions;
s.UseDebugSymbols = (bool?)e.Attribute("useDebugSymbols") ?? s.UseDebugSymbols;
return s; return s;
} }
@ -56,6 +57,7 @@ namespace ICSharpCode.ILSpy
section.SetAttributeValue("anonymousMethods", s.AnonymousMethods); section.SetAttributeValue("anonymousMethods", s.AnonymousMethods);
section.SetAttributeValue("yieldReturn", s.YieldReturn); section.SetAttributeValue("yieldReturn", s.YieldReturn);
section.SetAttributeValue("queryExpressions", s.QueryExpressions); section.SetAttributeValue("queryExpressions", s.QueryExpressions);
section.SetAttributeValue("useDebugSymbols", s.UseDebugSymbols);
XElement existingElement = root.Element("DecompilerSettings"); XElement existingElement = root.Element("DecompilerSettings");
if (existingElement != null) if (existingElement != null)

6
ILSpy/ILSpy.csproj

@ -262,6 +262,10 @@
<Project>{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}</Project> <Project>{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}</Project>
<Name>ICSharpCode.AvalonEdit</Name> <Name>ICSharpCode.AvalonEdit</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\Mono.Cecil\symbols\pdb\Mono.Cecil.Pdb.csproj">
<Project>{63E6915C-7EA4-4D76-AB28-0D7191EEA626}</Project>
<Name>Mono.Cecil.Pdb</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> <ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Name>ICSharpCode.NRefactory</Name> <Name>ICSharpCode.NRefactory</Name>
@ -273,4 +277,4 @@
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project> </Project>

22
ILSpy/LoadedAssembly.cs

@ -69,7 +69,27 @@ namespace ICSharpCode.ILSpy
// runs on background thread // runs on background thread
ReaderParameters p = new ReaderParameters(); ReaderParameters p = new ReaderParameters();
p.AssemblyResolver = new MyAssemblyResolver(this); p.AssemblyResolver = new MyAssemblyResolver(this);
return AssemblyDefinition.ReadAssembly(fileName, p); try {
if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols) {
SetSymbolSettings(p);
}
return AssemblyDefinition.ReadAssembly(fileName, p);
} finally {
if (p.SymbolStream != null)
p.SymbolStream.Dispose();
}
}
private void SetSymbolSettings(ReaderParameters p)
{
// search for pdb in same directory as dll
string pdbName = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + ".pdb");
if (File.Exists(pdbName)) {
p.ReadSymbols = true;
p.SymbolStream = File.OpenRead(pdbName);
}
// TODO: use symbol cache, get symbols from microsoft
} }
[ThreadStatic] [ThreadStatic]

3
ILSpy/OptionsDialog.xaml.cs

@ -87,8 +87,7 @@ namespace ICSharpCode.ILSpy
OptionsDialog dlg = new OptionsDialog(); OptionsDialog dlg = new OptionsDialog();
dlg.Owner = MainWindow.Instance; dlg.Owner = MainWindow.Instance;
if (dlg.ShowDialog() == true) { if (dlg.ShowDialog() == true) {
MainWindow.Instance.RefreshTreeViewFilter(); new RefreshCommand().Execute(parameter);
MainWindow.Instance.RefreshDecompiledView();
} }
} }
} }

2
Mono.Cecil/symbols/pdb/Mono.Cecil.Pdb/PdbHelper.cs

@ -65,7 +65,7 @@ namespace Mono.Cecil.Pdb {
public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream) public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream)
{ {
throw new NotImplementedException (); return new PdbReader (symbolStream);
} }
} }

4
TestPlugin/TestPlugin.csproj

@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<ProjectGuid>{F32EBCC8-0E53-4421-867E-05B3D6E10C70}</ProjectGuid> <ProjectGuid>{F32EBCC8-0E53-4421-867E-05B3D6E10C70}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RootNamespace>TestPlugin</RootNamespace> <RootNamespace>TestPlugin</RootNamespace>
<AssemblyName>Test.Plugin</AssemblyName> <AssemblyName>Test.Plugin</AssemblyName>
@ -15,7 +15,7 @@
<TreatWarningsAsErrors>false</TreatWarningsAsErrors> <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<StartArguments>/separate</StartArguments> <StartArguments>/separate</StartArguments>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x86' "> <PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<RegisterForComInterop>False</RegisterForComInterop> <RegisterForComInterop>False</RegisterForComInterop>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies> <GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>

Loading…
Cancel
Save