Browse Source

Added UnwindInfo as an optional printout

pull/2043/head
plupiman 5 years ago
parent
commit
fd0d89b253
  1. 44
      ILSpy.ReadyToRun/ReadyToRunLanguage.cs
  2. 11
      ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml
  3. 15
      ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs
  4. 18
      ILSpy.ReadyToRun/ReadyToRunOptions.cs

44
ILSpy.ReadyToRun/ReadyToRunLanguage.cs

@ -103,9 +103,47 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -103,9 +103,47 @@ namespace ICSharpCode.ILSpy.ReadyToRun
output.WriteLine("; " + comment);
}
private Dictionary<ulong, ILCompiler.Reflection.ReadyToRun.Amd64.UnwindCode> WriteUnwindInfo(ReadyToRunMethod readyToRunMethod, ITextOutput output)
{
IReadOnlyList<RuntimeFunction> runTimeList = readyToRunMethod.RuntimeFunctions;
Dictionary<ulong, ILCompiler.Reflection.ReadyToRun.Amd64.UnwindCode> unwindCodes = new Dictionary<ulong, ILCompiler.Reflection.ReadyToRun.Amd64.UnwindCode>();
foreach (RuntimeFunction i in runTimeList) {
if (i.UnwindInfo is ILCompiler.Reflection.ReadyToRun.Amd64.UnwindInfo amd64UnwindInfo) {
string parsedFlags = "";
if ((amd64UnwindInfo.Flags & (int)ILCompiler.Reflection.ReadyToRun.Amd64.UnwindFlags.UNW_FLAG_EHANDLER) != 0) {
parsedFlags += " EHANDLER";
}
if ((amd64UnwindInfo.Flags & (int)ILCompiler.Reflection.ReadyToRun.Amd64.UnwindFlags.UNW_FLAG_UHANDLER) != 0) {
parsedFlags += " UHANDLER";
}
if ((amd64UnwindInfo.Flags & (int)ILCompiler.Reflection.ReadyToRun.Amd64.UnwindFlags.UNW_FLAG_CHAININFO) != 0) {
parsedFlags += " CHAININFO";
}
if (parsedFlags.Length == 0) {
parsedFlags = " NHANDLER";
}
WriteCommentLine(output, $"UnwindInfo:");
WriteCommentLine(output, $"Version: {amd64UnwindInfo.Version}");
WriteCommentLine(output, $"Flags: 0x{amd64UnwindInfo.Flags:X2}{parsedFlags}");
WriteCommentLine(output, $"FrameRegister: {((amd64UnwindInfo.FrameRegister == 0) ? "none" : amd64UnwindInfo.FrameRegister.ToString())}");
for (int unwindCodeIndex = 0; unwindCodeIndex < amd64UnwindInfo.CountOfUnwindCodes; unwindCodeIndex++) {
unwindCodes.Add(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset, amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex]);
}
}
}
return unwindCodes;
}
private void Disassemble(PEFile currentFile, ITextOutput output, ReadyToRunReader reader, ReadyToRunMethod readyToRunMethod, RuntimeFunction runtimeFunction, int bitness, ulong address, bool showMetadataTokens, bool showMetadataTokensInBase10)
{
WriteCommentLine(output, readyToRunMethod.SignatureString);
Dictionary<ulong, ILCompiler.Reflection.ReadyToRun.Amd64.UnwindCode> unwindInfo = null;
if (ReadyToRunOptions.GetIsChecked(null)) {
unwindInfo = WriteUnwindInfo(readyToRunMethod, output);
WriteCommentLine(output, unwindInfo.ToString());
}
byte[] codeBytes = new byte[runtimeFunction.Size];
for (int i = 0; i < runtimeFunction.Size; i++) {
codeBytes[i] = reader.Image[reader.GetOffset(runtimeFunction.StartAddress) + i];
@ -133,6 +171,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -133,6 +171,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun
formatter.Options.DigitSeparator = "`";
formatter.Options.FirstOperandCharIndex = 10;
var tempOutput = new StringOutput();
ulong baseInstrIP = instructions[0].IP;
foreach (var instr in instructions) {
int byteBaseIndex = (int)(instr.IP - address);
if (runtimeFunction.DebugInfo != null) {
@ -160,6 +199,10 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -160,6 +199,10 @@ namespace ICSharpCode.ILSpy.ReadyToRun
output.Write(" ");
output.Write(tempOutput.ToStringAndReset());
int importCellAddress = (int)instr.IPRelativeMemoryAddress;
if (unwindInfo!= null && unwindInfo.ContainsKey(instr.IP - baseInstrIP)) {
ILCompiler.Reflection.ReadyToRun.Amd64.UnwindCode unwindCode = unwindInfo[instr.IP - baseInstrIP];
output.Write($" ; UnwindCode: OpCode: {unwindCode.UnwindOp} Op: {unwindCode.OpInfoStr}");
}
if (instr.IsCallNearIndirect && reader.ImportCellNames.ContainsKey(importCellAddress)) {
output.Write(" ; ");
ReadyToRunSignature signature = reader.ImportSignatures[(int)instr.IPRelativeMemoryAddress];
@ -190,6 +233,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -190,6 +233,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun
output.WriteLine(reader.ImportCellNames[importCellAddress]);
break;
}
output.WriteLine();
} else {
output.WriteLine();

11
ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml

@ -3,8 +3,15 @@ @@ -3,8 +3,15 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock>Disassembly Format</TextBlock>
<ComboBox ItemsSource="{Binding DisassemblyFormats}" SelectedItem="{Binding DisassemblyFormat}"/>
<StackPanel Orientation="Vertical">
<TextBlock>Disassembly Format</TextBlock>
<TextBlock>Show Unwind Info</TextBlock>
</StackPanel>
<StackPanel Orientation="Vertical">
<ComboBox ItemsSource="{Binding DisassemblyFormats}" SelectedItem="{Binding DisassemblyFormat}"/>
<CheckBox IsChecked="{Binding IsChecked}"></CheckBox>
</StackPanel>
</StackPanel>
</StackPanel>
</UserControl>

15
ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs

@ -35,6 +35,8 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -35,6 +35,8 @@ namespace ICSharpCode.ILSpy.ReadyToRun
{
Options s = new Options();
s.DisassemblyFormat = ReadyToRunOptions.GetDisassemblyFormat(settings);
s.IsChecked = ReadyToRunOptions.GetIsChecked(settings);
this.DataContext = s;
}
@ -46,7 +48,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -46,7 +48,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun
public void Save(XElement root)
{
Options s = (Options)this.DataContext;
ReadyToRunOptions.SetDisassemblyFormat(root, s.DisassemblyFormat);
ReadyToRunOptions.SetDisassemblyOptions(root, s.DisassemblyFormat, s.IsChecked);
}
}
@ -58,6 +60,17 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -58,6 +60,17 @@ namespace ICSharpCode.ILSpy.ReadyToRun
}
}
private bool isChecked;
public bool IsChecked {
get {
return isChecked;
}
set {
isChecked = value;
OnPropertyChanged(nameof(IsChecked));
}
}
private string disassemblyFormat;
public string DisassemblyFormat {

18
ILSpy.ReadyToRun/ReadyToRunOptions.cs

@ -42,10 +42,25 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -42,10 +42,25 @@ namespace ICSharpCode.ILSpy.ReadyToRun
}
}
public static void SetDisassemblyFormat(XElement root, string disassemblyFormat)
public static bool GetIsChecked(ILSpySettings settings)
{
if (settings == null) {
settings = ILSpySettings.Load();
}
XElement e = settings[ns + "ReadyToRunOptions"];
XAttribute a = e.Attribute("IsChecked");
if (a == null) {
return false;
} else {
return (bool)a;
}
}
public static void SetDisassemblyOptions(XElement root, string disassemblyFormat, bool isChecked)
{
XElement section = new XElement(ns + "ReadyToRunOptions");
section.SetAttributeValue("DisassemblyFormat", disassemblyFormat);
section.SetAttributeValue("IsChecked", isChecked);
XElement existingElement = root.Element(ns + "ReadyToRunOptions");
if (existingElement != null) {
@ -54,5 +69,6 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -54,5 +69,6 @@ namespace ICSharpCode.ILSpy.ReadyToRun
root.Add(section);
}
}
}
}

Loading…
Cancel
Save