|
|
|
@ -22,6 +22,7 @@ using System;
@@ -22,6 +22,7 @@ using System;
|
|
|
|
|
using System.Collections.Generic; |
|
|
|
|
using System.ComponentModel.Composition; |
|
|
|
|
using System.Diagnostics; |
|
|
|
|
using System.IO; |
|
|
|
|
using System.Linq; |
|
|
|
|
using System.Reflection.Metadata; |
|
|
|
|
using System.Reflection.PortableExecutable; |
|
|
|
@ -121,10 +122,13 @@ namespace ICSharpCode.ILSpy.ReadyToRun
@@ -121,10 +122,13 @@ namespace ICSharpCode.ILSpy.ReadyToRun
|
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
ReadyToRunReader reader = cacheEntry.readyToRunReader; |
|
|
|
|
WriteCommentLine(output, reader.Machine.ToString()); |
|
|
|
|
WriteCommentLine(output, reader.OperatingSystem.ToString()); |
|
|
|
|
WriteCommentLine(output, reader.CompilerIdentifier); |
|
|
|
|
WriteCommentLine(output, "TODO - display more header information"); |
|
|
|
|
WriteCommentLine(output, $"Machine : {reader.Machine}"); |
|
|
|
|
WriteCommentLine(output, $"OperatingSystem : {reader.OperatingSystem}"); |
|
|
|
|
WriteCommentLine(output, $"CompilerIdentifier : {reader.CompilerIdentifier}"); |
|
|
|
|
if (reader.OwnerCompositeExecutable != null) |
|
|
|
|
{ |
|
|
|
|
WriteCommentLine(output, $"OwnerCompositeExecutable : {reader.OwnerCompositeExecutable}"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return base.DecompileAssembly(assembly, output, options); |
|
|
|
@ -153,9 +157,22 @@ namespace ICSharpCode.ILSpy.ReadyToRun
@@ -153,9 +157,22 @@ namespace ICSharpCode.ILSpy.ReadyToRun
|
|
|
|
|
} |
|
|
|
|
if (cacheEntry.methodMap == null) |
|
|
|
|
{ |
|
|
|
|
cacheEntry.methodMap = reader.Methods.ToList() |
|
|
|
|
.GroupBy(m => m.MethodHandle) |
|
|
|
|
.ToDictionary(g => g.Key, g => g.ToArray()); |
|
|
|
|
IEnumerable<ReadyToRunMethod> readyToRunMethods = null; |
|
|
|
|
if (cacheEntry.compositeReadyToRunReader == null) |
|
|
|
|
{ |
|
|
|
|
readyToRunMethods = reader.Methods; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
readyToRunMethods = cacheEntry.compositeReadyToRunReader.Methods |
|
|
|
|
.Where(m => { |
|
|
|
|
MetadataReader mr = m.ComponentReader.MetadataReader; |
|
|
|
|
return string.Equals(mr.GetString(mr.GetAssemblyDefinition().Name), method.ParentModule.Name, StringComparison.OrdinalIgnoreCase); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
cacheEntry.methodMap = readyToRunMethods.ToList() |
|
|
|
|
.GroupBy(m => m.MethodHandle) |
|
|
|
|
.ToDictionary(g => g.Key, g => g.ToArray()); |
|
|
|
|
} |
|
|
|
|
var displaySettings = MainWindow.Instance.CurrentDisplaySettings; |
|
|
|
|
bool showMetadataTokens = displaySettings.ShowMetadataTokens; |
|
|
|
@ -174,7 +191,20 @@ namespace ICSharpCode.ILSpy.ReadyToRun
@@ -174,7 +191,20 @@ namespace ICSharpCode.ILSpy.ReadyToRun
|
|
|
|
|
#endif
|
|
|
|
|
foreach (RuntimeFunction runtimeFunction in readyToRunMethod.RuntimeFunctions) |
|
|
|
|
{ |
|
|
|
|
new ReadyToRunDisassembler(output, reader, runtimeFunction).Disassemble(method.ParentModule.PEFile, bitness, (ulong)runtimeFunction.StartAddress, showMetadataTokens, showMetadataTokensInBase10); |
|
|
|
|
PEFile file = null; |
|
|
|
|
ReadyToRunReader disassemblingReader = null; |
|
|
|
|
if (cacheEntry.compositeReadyToRunReader == null) |
|
|
|
|
{ |
|
|
|
|
disassemblingReader = reader; |
|
|
|
|
file = method.ParentModule.PEFile; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
disassemblingReader = cacheEntry.compositeReadyToRunReader; |
|
|
|
|
file = ((IlSpyAssemblyMetadata)readyToRunMethod.ComponentReader).Module; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
new ReadyToRunDisassembler(output, disassemblingReader, runtimeFunction).Disassemble(file, bitness, (ulong)runtimeFunction.StartAddress, showMetadataTokens, showMetadataTokensInBase10); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -206,6 +236,11 @@ namespace ICSharpCode.ILSpy.ReadyToRun
@@ -206,6 +236,11 @@ namespace ICSharpCode.ILSpy.ReadyToRun
|
|
|
|
|
result.failureReason = $"Architecture {result.readyToRunReader.Machine} is not currently supported."; |
|
|
|
|
result.readyToRunReader = null; |
|
|
|
|
} |
|
|
|
|
else if (result.readyToRunReader.OwnerCompositeExecutable != null) |
|
|
|
|
{ |
|
|
|
|
string compositePath = Path.Combine(Path.GetDirectoryName(module.FileName), result.readyToRunReader.OwnerCompositeExecutable); |
|
|
|
|
result.compositeReadyToRunReader = new ReadyToRunReader(new ReadyToRunAssemblyResolver(assembly), compositePath); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
catch (BadImageFormatException e) |
|
|
|
|
{ |
|
|
|
@ -219,31 +254,52 @@ namespace ICSharpCode.ILSpy.ReadyToRun
@@ -219,31 +254,52 @@ namespace ICSharpCode.ILSpy.ReadyToRun
|
|
|
|
|
|
|
|
|
|
private class ReadyToRunAssemblyResolver : ILCompiler.Reflection.ReadyToRun.IAssemblyResolver |
|
|
|
|
{ |
|
|
|
|
private LoadedAssembly loadedAssembly; |
|
|
|
|
private Decompiler.Metadata.IAssemblyResolver assemblyResolver; |
|
|
|
|
|
|
|
|
|
public ReadyToRunAssemblyResolver(LoadedAssembly loadedAssembly) |
|
|
|
|
{ |
|
|
|
|
this.loadedAssembly = loadedAssembly; |
|
|
|
|
assemblyResolver = loadedAssembly.GetAssemblyResolver(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public IAssemblyMetadata FindAssembly(MetadataReader metadataReader, AssemblyReferenceHandle assemblyReferenceHandle, string parentFile) |
|
|
|
|
{ |
|
|
|
|
PEFile module = assemblyResolver.Resolve(new Decompiler.Metadata.AssemblyReference(metadataReader, assemblyReferenceHandle)); |
|
|
|
|
PEReader reader = module?.Reader; |
|
|
|
|
return reader == null ? null : new StandaloneAssemblyMetadata(reader); |
|
|
|
|
return GetAssemblyMetadata(assemblyResolver.Resolve(new Decompiler.Metadata.AssemblyReference(metadataReader, assemblyReferenceHandle))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public IAssemblyMetadata FindAssembly(string simpleName, string parentFile) |
|
|
|
|
{ |
|
|
|
|
// This is called only for the composite R2R scenario,
|
|
|
|
|
// So it will never be called before the feature is released.
|
|
|
|
|
throw new NotSupportedException("Composite R2R format is not currently supported"); |
|
|
|
|
return GetAssemblyMetadata(assemblyResolver.ResolveModule(loadedAssembly.GetPEFileOrNull(), simpleName + ".dll")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private IAssemblyMetadata GetAssemblyMetadata(PEFile module) |
|
|
|
|
{ |
|
|
|
|
if (module.Reader == null) |
|
|
|
|
{ |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
return new IlSpyAssemblyMetadata(module); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private class IlSpyAssemblyMetadata : StandaloneAssemblyMetadata |
|
|
|
|
{ |
|
|
|
|
public PEFile Module { get; private set; } |
|
|
|
|
|
|
|
|
|
public IlSpyAssemblyMetadata(PEFile module) : base(module.Reader) |
|
|
|
|
{ |
|
|
|
|
Module = module; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private class ReadyToRunReaderCacheEntry |
|
|
|
|
{ |
|
|
|
|
public ReadyToRunReader readyToRunReader; |
|
|
|
|
public ReadyToRunReader compositeReadyToRunReader; |
|
|
|
|
public string failureReason; |
|
|
|
|
public Dictionary<EntityHandle, ReadyToRunMethod[]> methodMap; |
|
|
|
|
} |
|
|
|
|