}
}
+ public class ReadyToRunAssembly
+ {
+ private ReadyToRunReader _reader;
+ internal List<string> _availableTypes;
+ internal List<ReadyToRunMethod> _methods;
+
+ internal ReadyToRunAssembly(ReadyToRunReader reader)
+ {
+ _reader = reader;
+ }
+
+ public IReadOnlyList<string> AvailableTypes
+ {
+ get
+ {
+ _reader.EnsureAvailableTypes();
+ return _availableTypes;
+ }
+ }
+
+ public IReadOnlyList<ReadyToRunMethod> Methods
+ {
+ get
+ {
+ _reader.EnsureMethods();
+ return _methods;
+ }
+ }
+ }
+
public sealed class ReadyToRunReader
{
private const string SystemModuleName = "System.Private.CoreLib";
private int _readyToRunHeaderRVA;
private ReadyToRunHeader _readyToRunHeader;
private List<ReadyToRunCoreHeader> _readyToRunAssemblyHeaders;
+ private List<ReadyToRunAssembly> _readyToRunAssemblies;
// DebugInfo
private Dictionary<int, int> _runtimeFunctionIdToDebugOffset;
private Dictionary<int, EHInfo> _runtimeFunctionToEHInfo;
// Methods
- private Dictionary<ReadyToRunSection, List<ReadyToRunMethod>> _methods;
private List<InstanceMethod> _instanceMethods;
// ImportSections
private List<ReadyToRunImportSection> _importSections;
private Dictionary<int, ReadyToRunSignature> _importSignatures;
- // AvailableType
- private Dictionary<ReadyToRunSection, List<string>> _availableTypes;
-
// CompilerIdentifier
private string _compilerIdentifier;
}
}
- /// <summary>
- /// The runtime functions and method signatures of each method
- /// </summary>
- public Dictionary<ReadyToRunSection, List<ReadyToRunMethod>> Methods
+ public IReadOnlyList<ReadyToRunAssembly> ReadyToRunAssemblies
{
get
{
- EnsureMethods();
- return _methods;
+ EnsureHeader();
+ return _readyToRunAssemblies;
}
}
}
/// <summary>
- /// The available types from READYTORUN_SECTION_AVAILABLE_TYPES
- /// </summary>
- public Dictionary<ReadyToRunSection, List<string>> AvailableTypes
- {
-
- get
- {
- EnsureAvailableTypes();
- return _availableTypes;
- }
-
- }
-
- /// <summary>
/// The compiler identifier string from READYTORUN_SECTION_COMPILER_IDENTIFIER
/// </summary>
public string CompilerIdentifier
}
}
- private void EnsureMethods()
+ internal void EnsureMethods()
{
- if (_methods != null)
+ EnsureHeader();
+ if (_readyToRunAssemblies[0]._methods != null)
{
return;
}
- _methods = new Dictionary<ReadyToRunSection, List<ReadyToRunMethod>>();
_instanceMethods = new List<InstanceMethod>();
if (ReadyToRunHeader.Sections.TryGetValue(ReadyToRunSectionType.RuntimeFunctions, out ReadyToRunSection runtimeFunctionSection))
if (_runtimeFunctionToMethod == null)
{
_runtimeFunctionToMethod = new Dictionary<int, ReadyToRunMethod>();
- foreach (var section in _methods)
+ foreach (var method in Methods)
{
- foreach (var method in section.Value)
- {
- if (!_runtimeFunctionToMethod.ContainsKey(method.EntryPointRuntimeFunctionId))
- _runtimeFunctionToMethod.Add(method.EntryPointRuntimeFunctionId, method);
- }
+ if (!_runtimeFunctionToMethod.ContainsKey(method.EntryPointRuntimeFunctionId))
+ _runtimeFunctionToMethod.Add(method.EntryPointRuntimeFunctionId, method);
}
}
}
int r2rHeaderOffset = GetOffset(_readyToRunHeaderRVA);
_readyToRunHeader = new ReadyToRunHeader(Image, _readyToRunHeaderRVA, r2rHeaderOffset);
+ _readyToRunAssemblies = new List<ReadyToRunAssembly>();
if (_composite)
{
ParseComponentAssemblies();
}
+ else
+ {
+ _readyToRunAssemblies.Add(new ReadyToRunAssembly(this));
+ }
}
private void EnsureDebugInfo()
/// <param name="isEntryPoint">Set to true for each runtime function index representing a method entrypoint</param>
private void ParseMethodDefEntrypointsSection(ReadyToRunSection section, IAssemblyMetadata componentReader, bool[] isEntryPoint)
{
+ int assemblyIndex = GetAssemblyIndex(section);
+ _readyToRunAssemblies[assemblyIndex]._methods = new List<ReadyToRunMethod>();
int methodDefEntryPointsOffset = GetOffset(section.RelativeVirtualAddress);
NativeArray methodEntryPoints = new NativeArray(Image, (uint)methodDefEntryPointsOffset);
uint nMethodEntryPoints = methodEntryPoints.GetCount();
throw new BadImageFormatException("EntryPointRuntimeFunctionId out of bounds");
}
isEntryPoint[method.EntryPointRuntimeFunctionId] = true;
- if (!_methods.TryGetValue(section, out List<ReadyToRunMethod> sectionMethods))
- {
- sectionMethods = new List<ReadyToRunMethod>();
- _methods.Add(section, sectionMethods);
- }
- sectionMethods.Add(method);
+ _readyToRunAssemblies[assemblyIndex]._methods.Add(method);
}
}
}
GetRuntimeFunctionIndexFromOffset(offset, out runtimeFunctionId, out fixupOffset);
ReadyToRunMethod r2rMethod = _runtimeFunctionToMethod[runtimeFunctionId];
var customMethod = provider.GetMethodFromMethodDef(metadataReader.MetadataReader, MetadataTokens.MethodDefinitionHandle((int)rid), default(TType));
-
+
if (!Object.ReferenceEquals(customMethod, null) && !foundMethods.ContainsKey(customMethod))
foundMethods.Add(customMethod, r2rMethod);
}
{
isEntryPoint[method.EntryPointRuntimeFunctionId] = true;
}
- if (!Methods.TryGetValue(instMethodEntryPointSection, out List<ReadyToRunMethod> sectionMethods))
- {
- sectionMethods = new List<ReadyToRunMethod>();
- Methods.Add(instMethodEntryPointSection, sectionMethods);
- }
- sectionMethods.Add(method);
_instanceMethods.Add(new InstanceMethod(curParser.LowHashcode, method));
curParser = allEntriesEnum.GetNext();
}
}
+ public IEnumerable<ReadyToRunMethod> Methods
+ {
+ get
+ {
+ EnsureMethods();
+ return _readyToRunAssemblies.SelectMany(assembly => assembly.Methods).Concat(_instanceMethods.Select(im => im.Method));
+ }
+ }
+
private void CountRuntimeFunctions(bool[] isEntryPoint)
{
- foreach (ReadyToRunMethod method in Methods.Values.SelectMany(sectionMethods => sectionMethods))
+ foreach (ReadyToRunMethod method in Methods)
{
int runtimeFunctionId = method.EntryPointRuntimeFunctionId;
if (runtimeFunctionId == -1)
}
}
+ public int GetAssemblyIndex(ReadyToRunSection section)
+ {
+ EnsureHeader();
+ if (_composite)
+ {
+ for (int assemblyIndex = 0; assemblyIndex < _readyToRunAssemblyHeaders.Count; assemblyIndex++)
+ {
+ ReadyToRunSection toMatch;
+ if (_readyToRunAssemblyHeaders[assemblyIndex].Sections.TryGetValue(section.Type, out toMatch) && section.RelativeVirtualAddress == toMatch.RelativeVirtualAddress)
+ {
+ return assemblyIndex;
+ }
+ }
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
/// <summary>
/// Iterates through a native hashtable to get all RIDs
/// </summary>
- private void EnsureAvailableTypes()
+ internal void EnsureAvailableTypes()
{
- if (_availableTypes != null)
+ EnsureHeader();
+ if (_readyToRunAssemblies[0]._availableTypes != null)
{
return;
}
- _availableTypes = new Dictionary<ReadyToRunSection, List<string>>();
ReadyToRunSection availableTypesSection;
if (ReadyToRunHeader.Sections.TryGetValue(ReadyToRunSectionType.AvailableTypes, out availableTypesSection))
{
- ParseAvailableTypesSection(availableTypesSection, GetGlobalMetadata());
+ ParseAvailableTypesSection(0, availableTypesSection, GetGlobalMetadata());
}
else if (_readyToRunAssemblyHeaders != null)
{
if (_readyToRunAssemblyHeaders[assemblyIndex].Sections.TryGetValue(
ReadyToRunSectionType.AvailableTypes, out availableTypesSection))
{
- ParseAvailableTypesSection(availableTypesSection, OpenReferenceAssembly(assemblyIndex + 1));
+ ParseAvailableTypesSection(assemblyIndex, availableTypesSection, OpenReferenceAssembly(assemblyIndex + 1));
}
}
}
/// as available types are stored separately for each component assembly of the composite R2R executable.
/// </summary>
/// <param name="availableTypesSection"></param>
- private void ParseAvailableTypesSection(ReadyToRunSection availableTypesSection, IAssemblyMetadata metadataReader)
+ private void ParseAvailableTypesSection(int assemblyIndex, ReadyToRunSection availableTypesSection, IAssemblyMetadata metadataReader)
{
+ _readyToRunAssemblies[assemblyIndex]._availableTypes = new List<string>();
int availableTypesOffset = GetOffset(availableTypesSection.RelativeVirtualAddress);
NativeParser parser = new NativeParser(Image, (uint)availableTypesOffset);
NativeHashtable availableTypes = new NativeHashtable(Image, parser, (uint)(availableTypesOffset + availableTypesSection.Size));
{
ExportedTypeHandle exportedTypeHandle = MetadataTokens.ExportedTypeHandle((int)rid);
string exportedTypeName = GetExportedTypeFullName(metadataReader.MetadataReader, exportedTypeHandle);
- if (!AvailableTypes.TryGetValue(availableTypesSection, out List<string> sectionTypes))
- {
- sectionTypes = new List<string>();
- AvailableTypes.Add(availableTypesSection, sectionTypes);
- }
- sectionTypes.Add("exported " + exportedTypeName);
+
+ _readyToRunAssemblies[assemblyIndex]._availableTypes.Add("exported " + exportedTypeName);
}
else
{
TypeDefinitionHandle typeDefHandle = MetadataTokens.TypeDefinitionHandle((int)rid);
string typeDefName = MetadataNameFormatter.FormatHandle(metadataReader.MetadataReader, typeDefHandle);
- if (!AvailableTypes.TryGetValue(availableTypesSection, out List<string> sectionTypes))
- {
- sectionTypes = new List<string>();
- AvailableTypes.Add(availableTypesSection, sectionTypes);
- }
- sectionTypes.Add(typeDefName);
+ _readyToRunAssemblies[assemblyIndex]._availableTypes.Add(typeDefName);
}
curParser = allEntriesEnum.GetNext();
ReadyToRunCoreHeader assemblyHeader = new ReadyToRunCoreHeader(Image, ref headerOffset);
_readyToRunAssemblyHeaders.Add(assemblyHeader);
+ _readyToRunAssemblies.Add(new ReadyToRunAssembly(this));
}
}
}
}
+ private bool TryGetMethods(ReadyToRunReader reader, ReadyToRunSection section, out IReadOnlyList<ReadyToRunMethod> methods)
+ {
+ int assemblyIndex = reader.GetAssemblyIndex(section);
+ if (assemblyIndex == -1)
+ {
+ methods = null;
+ return false;
+ }
+ else
+ {
+ methods = reader.ReadyToRunAssemblies[assemblyIndex].Methods;
+ return true;
+ }
+ }
+
private void DiffMethodsForModule(ReadyToRunSection leftSection, ReadyToRunSection rightSection)
{
- if (!_leftDumper.Reader.Methods.TryGetValue(leftSection, out List<ReadyToRunMethod> leftSectionMethods))
+ if (!TryGetMethods(_leftDumper.Reader, leftSection, out IReadOnlyList<ReadyToRunMethod> leftSectionMethods))
{
leftSectionMethods = new List<ReadyToRunMethod>();
}
- if (!_rightDumper.Reader.Methods.TryGetValue(rightSection, out List<ReadyToRunMethod> rightSectionMethods))
+ if (!TryGetMethods(_rightDumper.Reader, rightSection, out IReadOnlyList<ReadyToRunMethod> rightSectionMethods))
{
rightSectionMethods = new List<ReadyToRunMethod>();
}
{
Dictionary<string, int> methodMap = new Dictionary<string, int>();
- if (reader.Methods.TryGetValue(section, out List<ReadyToRunMethod> sectionMethods))
+ if (TryGetMethods(reader, section, out IReadOnlyList<ReadyToRunMethod> sectionMethods))
{
foreach (ReadyToRunMethod method in sectionMethods)
{
/// <param name="signatureFilter">Set of common signatures of methods to dump</param>
private void DumpCommonMethods(Dumper dumper, ReadyToRunSection section, Dictionary<string, MethodPair> signatureFilter)
{
- if (dumper.Reader.Methods.TryGetValue(section, out List<ReadyToRunMethod> sectionMethods))
+ if (!TryGetMethods(dumper.Reader, section, out IReadOnlyList<ReadyToRunMethod> sectionMethods))
{
IEnumerable<ReadyToRunMethod> filteredMethods = sectionMethods
.Where(method => signatureFilter.ContainsKey(method.SignatureString))