2222using System . Collections . Generic ;
2323using System . ComponentModel . Composition ;
2424using System . Diagnostics ;
25+ using System . IO ;
2526using System . Linq ;
2627using System . Reflection . Metadata ;
2728using System . Reflection . PortableExecutable ;
@@ -121,10 +122,13 @@ public override ProjectId DecompileAssembly(LoadedAssembly assembly, ITextOutput
121122 else
122123 {
123124 ReadyToRunReader reader = cacheEntry . readyToRunReader ;
124- WriteCommentLine ( output , reader . Machine . ToString ( ) ) ;
125- WriteCommentLine ( output , reader . OperatingSystem . ToString ( ) ) ;
126- WriteCommentLine ( output , reader . CompilerIdentifier ) ;
127- WriteCommentLine ( output , "TODO - display more header information" ) ;
125+ WriteCommentLine ( output , $ "Machine : { reader . Machine } ") ;
126+ WriteCommentLine ( output , $ "OperatingSystem : { reader . OperatingSystem } ") ;
127+ WriteCommentLine ( output , $ "CompilerIdentifier : { reader . CompilerIdentifier } ") ;
128+ if ( reader . OwnerCompositeExecutable != null )
129+ {
130+ WriteCommentLine ( output , $ "OwnerCompositeExecutable : { reader . OwnerCompositeExecutable } ") ;
131+ }
128132 }
129133
130134 return base . DecompileAssembly ( assembly , output , options ) ;
@@ -153,9 +157,22 @@ public override void DecompileMethod(IMethod method, ITextOutput output, Decompi
153157 }
154158 if ( cacheEntry . methodMap == null )
155159 {
156- cacheEntry . methodMap = reader . Methods . ToList ( )
157- . GroupBy ( m => m . MethodHandle )
158- . ToDictionary ( g => g . Key , g => g . ToArray ( ) ) ;
160+ IEnumerable < ReadyToRunMethod > readyToRunMethods = null ;
161+ if ( cacheEntry . compositeReadyToRunReader == null )
162+ {
163+ readyToRunMethods = reader . Methods ;
164+ }
165+ else
166+ {
167+ readyToRunMethods = cacheEntry . compositeReadyToRunReader . Methods
168+ . Where ( m => {
169+ MetadataReader mr = m . ComponentReader . MetadataReader ;
170+ return string . Equals ( mr . GetString ( mr . GetAssemblyDefinition ( ) . Name ) , method . ParentModule . Name , StringComparison . OrdinalIgnoreCase ) ;
171+ } ) ;
172+ }
173+ cacheEntry . methodMap = readyToRunMethods . ToList ( )
174+ . GroupBy ( m => m . MethodHandle )
175+ . ToDictionary ( g => g . Key , g => g . ToArray ( ) ) ;
159176 }
160177 var displaySettings = MainWindow . Instance . CurrentDisplaySettings ;
161178 bool showMetadataTokens = displaySettings . ShowMetadataTokens ;
@@ -174,7 +191,20 @@ public override void DecompileMethod(IMethod method, ITextOutput output, Decompi
174191#endif
175192 foreach ( RuntimeFunction runtimeFunction in readyToRunMethod . RuntimeFunctions )
176193 {
177- new ReadyToRunDisassembler ( output , reader , runtimeFunction ) . Disassemble ( method . ParentModule . PEFile , bitness , ( ulong ) runtimeFunction . StartAddress , showMetadataTokens , showMetadataTokensInBase10 ) ;
194+ PEFile file = null ;
195+ ReadyToRunReader disassemblingReader = null ;
196+ if ( cacheEntry . compositeReadyToRunReader == null )
197+ {
198+ disassemblingReader = reader ;
199+ file = method . ParentModule . PEFile ;
200+ }
201+ else
202+ {
203+ disassemblingReader = cacheEntry . compositeReadyToRunReader ;
204+ file = ( ( IlSpyAssemblyMetadata ) readyToRunMethod . ComponentReader ) . Module ;
205+ }
206+
207+ new ReadyToRunDisassembler ( output , disassemblingReader , runtimeFunction ) . Disassemble ( file , bitness , ( ulong ) runtimeFunction . StartAddress , showMetadataTokens , showMetadataTokensInBase10 ) ;
178208 }
179209 }
180210 }
@@ -206,6 +236,11 @@ private ReadyToRunReaderCacheEntry GetReader(LoadedAssembly assembly, PEFile mod
206236 result . failureReason = $ "Architecture { result . readyToRunReader . Machine } is not currently supported.";
207237 result . readyToRunReader = null ;
208238 }
239+ else if ( result . readyToRunReader . OwnerCompositeExecutable != null )
240+ {
241+ string compositePath = Path . Combine ( Path . GetDirectoryName ( module . FileName ) , result . readyToRunReader . OwnerCompositeExecutable ) ;
242+ result . compositeReadyToRunReader = new ReadyToRunReader ( new ReadyToRunAssemblyResolver ( assembly ) , compositePath ) ;
243+ }
209244 }
210245 catch ( BadImageFormatException e )
211246 {
@@ -219,31 +254,52 @@ private ReadyToRunReaderCacheEntry GetReader(LoadedAssembly assembly, PEFile mod
219254
220255 private class ReadyToRunAssemblyResolver : ILCompiler . Reflection . ReadyToRun . IAssemblyResolver
221256 {
257+ private LoadedAssembly loadedAssembly ;
222258 private Decompiler . Metadata . IAssemblyResolver assemblyResolver ;
223259
224260 public ReadyToRunAssemblyResolver ( LoadedAssembly loadedAssembly )
225261 {
262+ this . loadedAssembly = loadedAssembly ;
226263 assemblyResolver = loadedAssembly . GetAssemblyResolver ( ) ;
227264 }
228265
229266 public IAssemblyMetadata FindAssembly ( MetadataReader metadataReader , AssemblyReferenceHandle assemblyReferenceHandle , string parentFile )
230267 {
231- PEFile module = assemblyResolver . Resolve ( new Decompiler . Metadata . AssemblyReference ( metadataReader , assemblyReferenceHandle ) ) ;
232- PEReader reader = module ? . Reader ;
233- return reader == null ? null : new StandaloneAssemblyMetadata ( reader ) ;
268+ return GetAssemblyMetadata ( assemblyResolver . Resolve ( new Decompiler . Metadata . AssemblyReference ( metadataReader , assemblyReferenceHandle ) ) ) ;
234269 }
235270
236271 public IAssemblyMetadata FindAssembly ( string simpleName , string parentFile )
237272 {
238- // This is called only for the composite R2R scenario,
239- // So it will never be called before the feature is released.
240- throw new NotSupportedException ( "Composite R2R format is not currently supported" ) ;
273+ return GetAssemblyMetadata ( assemblyResolver . ResolveModule ( loadedAssembly . GetPEFileOrNull ( ) , simpleName + ".dll" ) ) ;
274+ }
275+
276+ private IAssemblyMetadata GetAssemblyMetadata ( PEFile module )
277+ {
278+ if ( module . Reader == null )
279+ {
280+ return null ;
281+ }
282+ else
283+ {
284+ return new IlSpyAssemblyMetadata ( module ) ;
285+ }
286+ }
287+ }
288+
289+ private class IlSpyAssemblyMetadata : StandaloneAssemblyMetadata
290+ {
291+ public PEFile Module { get ; private set ; }
292+
293+ public IlSpyAssemblyMetadata ( PEFile module ) : base ( module . Reader )
294+ {
295+ Module = module ;
241296 }
242297 }
243298
244299 private class ReadyToRunReaderCacheEntry
245300 {
246301 public ReadyToRunReader readyToRunReader ;
302+ public ReadyToRunReader compositeReadyToRunReader ;
247303 public string failureReason ;
248304 public Dictionary < EntityHandle , ReadyToRunMethod [ ] > methodMap ;
249305 }
0 commit comments