static partial void GetEcmaRuntimeAssembly(AssemblyBindResult bindResult, ref RuntimeAssembly runtimeAssembly) { if (bindResult.EcmaMetadataReader != null) { runtimeAssembly = EcmaFormatRuntimeAssembly.GetRuntimeAssembly(bindResult.EcmaMetadataReader); } }
static partial void GetNativeFormatRuntimeAssembly(AssemblyBindResult bindResult, ref RuntimeAssembly runtimeAssembly) { if (bindResult.Reader != null) { runtimeAssembly = NativeFormatRuntimeAssembly.GetRuntimeAssembly(bindResult.Reader, bindResult.ScopeDefinitionHandle, bindResult.OverflowScopes); } }
partial void BindEcmaFilePath(string assemblyPath, ref AssemblyBindResult bindResult, ref Exception?exception, ref bool?result) { // Get a PEReader over a MemoryMappedView of the PE file PEReader pe = OpenPEFile(assemblyPath, out var memoryMappedView); BindEcma(pe, memoryMappedView, out bindResult, out exception, out result); }
partial void BindEcmaByteArray(byte[] rawAssembly, byte[]?rawSymbolStore, ref AssemblyBindResult bindResult, ref Exception?exception, ref bool?result) { // Load byte[] into immutable array for use by PEReader/MetadataReader ImmutableArray <byte> assemblyData = ImmutableArray.Create(rawAssembly); PEReader pe = new PEReader(assemblyData); BindEcma(pe, null, out bindResult, out exception, out result); }
public sealed override bool Bind(AssemblyName refName, out AssemblyBindResult result, out Exception exception) { bool foundMatch = false; result = default(AssemblyBindResult); exception = null; // At least one real-world app calls Type.GetType() for "char" using the assembly name "mscorlib". To accomodate this, // we will adopt the desktop CLR rule that anything named "mscorlib" automatically binds to the core assembly. bool useMscorlibNameCompareFunc = false; AssemblyName compareRefName = refName; if (refName.Name == "mscorlib") { useMscorlibNameCompareFunc = true; compareRefName = new AssemblyName(AssemblyBinder.DefaultAssemblyNameForGetType); } foreach (KeyValuePair <AssemblyNameKey, ScopeDefinitionGroup> group in ScopeGroups) { bool nameMatches; if (useMscorlibNameCompareFunc) { nameMatches = MscorlibAssemblyNameMatches(compareRefName, group.Key.AssemblyName); } else { nameMatches = AssemblyNameMatches(refName, group.Key.AssemblyName); } if (nameMatches) { if (foundMatch) { exception = new AmbiguousMatchException(); return(false); } foundMatch = true; ScopeDefinitionGroup scopeDefinitionGroup = group.Value; result.Reader = scopeDefinitionGroup.CanonicalScope.Reader; result.ScopeDefinitionHandle = scopeDefinitionGroup.CanonicalScope.Handle; result.OverflowScopes = scopeDefinitionGroup.OverflowScopes; } } if (!foundMatch) { exception = new IOException(SR.Format(SR.FileNotFound_AssemblyNotFound, refName.FullName)); return(false); } return(true); }
partial void InsertEcmaLoadedAssemblies(List <AssemblyBindResult> loadedAssemblies) { lock (s_ecmaLoadedAssemblies) { for (int i = 0; i < s_ecmaLoadedAssemblies.Count; i++) { PEInfo info = s_ecmaLoadedAssemblies[i]; AssemblyBindResult result = default(AssemblyBindResult); result.EcmaMetadataReader = info.Reader; loadedAssemblies.Add(result); } } }
private static RuntimeAssembly GetRuntimeAssembly(AssemblyBindResult bindResult) { RuntimeAssembly result = null; GetNativeFormatRuntimeAssembly(bindResult, ref result); if (result != null) { return(result); } GetEcmaRuntimeAssembly(bindResult, ref result); if (result != null) { return(result); } throw new PlatformNotSupportedException(); }
public sealed override bool Bind(byte[] rawAssembly, byte[] rawSymbolStore, out AssemblyBindResult bindResult, out Exception exception) { bool?result = null; exception = null; bindResult = default(AssemblyBindResult); BindEcmaByteArray(rawAssembly, rawSymbolStore, ref bindResult, ref exception, ref result); // If the Ecma assembly binder isn't linked in, simply throw PlatformNotSupportedException if (!result.HasValue) { throw new PlatformNotSupportedException(); } else { return(result.Value); } }
public sealed override bool Bind(string assemblyPath, out AssemblyBindResult bindResult, out Exception exception) { bool?result = null; exception = null; bindResult = default(AssemblyBindResult); BindEcmaFilePath(assemblyPath, ref bindResult, ref exception, ref result); // If the Ecma assembly binder isn't linked in, simply throw PlatformNotSupportedException if (!result.HasValue) { throw new PlatformNotSupportedException(); } else { return(result.Value); } }
public sealed override IList <AssemblyBindResult> GetLoadedAssemblies() { List <AssemblyBindResult> loadedAssemblies = new List <AssemblyBindResult>(ScopeGroups.Length); foreach (KeyValuePair <RuntimeAssemblyName, ScopeDefinitionGroup> group in ScopeGroups) { ScopeDefinitionGroup scopeDefinitionGroup = group.Value; AssemblyBindResult result = default(AssemblyBindResult); result.Reader = scopeDefinitionGroup.CanonicalScope.Reader; result.ScopeDefinitionHandle = scopeDefinitionGroup.CanonicalScope.Handle; result.OverflowScopes = scopeDefinitionGroup.OverflowScopes; loadedAssemblies.Add(result); } InsertEcmaLoadedAssemblies(loadedAssemblies); return(loadedAssemblies); }
partial void BindEcmaByteArray(byte[] rawAssembly, byte[] rawSymbolStore, ref AssemblyBindResult bindResult, ref Exception exception, ref bool?result) { // 1. Load byte[] into immutable array for use by PEReader/MetadataReader ImmutableArray <byte> assemblyData = ImmutableArray.Create(rawAssembly); PEReader pe = new PEReader(assemblyData); MetadataReader reader = pe.GetMetadataReader(); // 2. Create AssemblyName from MetadataReader RuntimeAssemblyName runtimeAssemblyName = reader.GetAssemblyDefinition().ToRuntimeAssemblyName(reader); AssemblyName asmName = new AssemblyName(); runtimeAssemblyName.CopyToAssemblyName(asmName); lock (s_ecmaLoadedAssemblies) { // 3. Attempt to bind to already loaded assembly if (Bind(asmName, out bindResult, out exception)) { result = true; return; } exception = null; // 4. If that fails, then add newly created metareader to global cache of byte array loaded modules PEInfo peinfo = new PEInfo(asmName, reader, pe); s_ecmaLoadedAssemblies.Add(peinfo); ModuleList moduleList = ModuleList.Instance; ModuleInfo newModuleInfo = new EcmaModuleInfo(moduleList.SystemModule.Handle, pe, reader); moduleList.RegisterModule(newModuleInfo); // 5. Then try to load by name again. This load should always succeed if (Bind(asmName, out bindResult, out exception)) { result = true; return; } result = false; Debug.Assert(exception != null); // We must have an error on load. At this time this could happen due to ambiguous name matching } }
partial void BindEcmaAssemblyName(RuntimeAssemblyName refName, ref AssemblyBindResult result, ref Exception exception, ref bool foundMatch) { lock (s_ecmaLoadedAssemblies) { for (int i = 0; i < s_ecmaLoadedAssemblies.Count; i++) { PEInfo info = s_ecmaLoadedAssemblies[i]; if (AssemblyNameMatches(refName, info.Name)) { if (foundMatch) { exception = new AmbiguousMatchException(); return; } foundMatch = true; result.EcmaMetadataReader = info.Reader; } } } }
partial void BindEcmaBytes(ReadOnlySpan <byte> rawAssembly, ReadOnlySpan <byte> rawSymbolStore, ref AssemblyBindResult bindResult, ref Exception exception, ref bool?result);
public sealed override bool Bind(RuntimeAssemblyName refName, bool cacheMissedLookups, out AssemblyBindResult result, out Exception exception) { bool foundMatch = false; result = default(AssemblyBindResult); exception = null; Exception preferredException = null; foreach (KeyValuePair <RuntimeAssemblyName, ScopeDefinitionGroup> group in ScopeGroups) { if (AssemblyNameMatches(refName, group.Key, ref preferredException)) { if (foundMatch) { exception = new AmbiguousMatchException(); return(false); } foundMatch = true; ScopeDefinitionGroup scopeDefinitionGroup = group.Value; result.Reader = scopeDefinitionGroup.CanonicalScope.Reader; result.ScopeDefinitionHandle = scopeDefinitionGroup.CanonicalScope.Handle; result.OverflowScopes = scopeDefinitionGroup.OverflowScopes; } } BindEcmaAssemblyName(refName, cacheMissedLookups, ref result, ref exception, ref preferredException, ref foundMatch); if (exception != null) { return(false); } if (!foundMatch) { exception = preferredException ?? new FileNotFoundException(SR.Format(SR.FileNotFound_AssemblyNotFound, refName.FullName)); return(false); } return(true); }
partial void BindEcmaAssemblyName(RuntimeAssemblyName refName, bool cacheMissedLookups, ref AssemblyBindResult result, ref Exception exception, ref Exception preferredException, ref bool resultBoolean);
partial void BindEcmaByteArray(byte[] rawAssembly, byte[] rawSymbolStore, ref AssemblyBindResult bindResult, ref Exception exception, ref bool?result);
partial void BindEcmaFilePath(string assemblyPath, ref AssemblyBindResult bindResult, ref Exception exception, ref bool?result);
partial void BindEcmaAssemblyName(RuntimeAssemblyName refName, ref AssemblyBindResult result, ref Exception exception, ref bool resultBoolean);
partial void BindEcmaAssemblyName(RuntimeAssemblyName refName, bool cacheMissedLookups, ref AssemblyBindResult result, ref Exception exception, ref Exception preferredException, ref bool foundMatch) { lock (s_ecmaLoadedAssemblies) { for (int i = 0; i < s_ecmaLoadedAssemblies.Count; i++) { PEInfo info = s_ecmaLoadedAssemblies[i]; if (AssemblyNameMatches(refName, info.Name, ref preferredException)) { if (foundMatch) { exception = new AmbiguousMatchException(); return; } result.EcmaMetadataReader = info.Reader; foundMatch = result.EcmaMetadataReader != null; // For failed matches, we will never be able to succeed, so return now if (!foundMatch) { return; } } } if (!foundMatch) { try { // Not found in already loaded list, attempt to source assembly from disk foreach (string filePath in FilePathsForAssembly(refName)) { FileStream ownedFileStream = null; PEReader ownedPEReader = null; try { if (!RuntimeAugments.FileExists(filePath)) { continue; } try { ownedFileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); } catch (System.IO.IOException) { // Failure to open a file is not fundamentally an assembly load error, but it does indicate this file cannot be used continue; } ownedPEReader = new PEReader(ownedFileStream); // FileStream ownership transferred to ownedPEReader ownedFileStream = null; if (!ownedPEReader.HasMetadata) { continue; } MetadataReader reader = ownedPEReader.GetMetadataReader(); // Create AssemblyName from MetadataReader RuntimeAssemblyName runtimeAssemblyName = reader.GetAssemblyDefinition().ToRuntimeAssemblyName(reader).CanonicalizePublicKeyToken(); // If assembly name doesn't match, it isn't the one we're looking for. Continue to look for more assemblies if (!AssemblyNameMatches(refName, runtimeAssemblyName, ref preferredException)) { continue; } // This is the one we are looking for, add it to the list of loaded assemblies PEInfo peinfo = new PEInfo(runtimeAssemblyName, reader, ownedPEReader); s_ecmaLoadedAssemblies.Add(peinfo); // At this point the PE reader is no longer owned by this code, but is owned by the s_ecmaLoadedAssemblies list PEReader pe = ownedPEReader; ownedPEReader = null; ModuleList moduleList = ModuleList.Instance; ModuleInfo newModuleInfo = new EcmaModuleInfo(moduleList.SystemModule.Handle, pe, reader); moduleList.RegisterModule(newModuleInfo); foundMatch = true; result.EcmaMetadataReader = peinfo.Reader; break; } finally { if (ownedFileStream != null) { ownedFileStream.Dispose(); } if (ownedPEReader != null) { ownedPEReader.Dispose(); } } } } catch (System.IO.IOException) { } catch (System.ArgumentException) { } catch (System.BadImageFormatException badImageFormat) { exception = badImageFormat; } // Cache missed lookups if (cacheMissedLookups && !foundMatch) { PEInfo peinfo = new PEInfo(refName, null, null); s_ecmaLoadedAssemblies.Add(peinfo); } } } }
static partial void GetEcmaRuntimeAssembly(AssemblyBindResult bindResult, ref RuntimeAssembly runtimeAssembly);
// Use C# partial method feature to avoid complex #if logic, whichever code files are included will drive behavior static partial void GetNativeFormatRuntimeAssembly(AssemblyBindResult bindResult, ref RuntimeAssembly runtimeAssembly);
private void BindEcma(PEReader pe, MemoryMappedViewAccessor?memoryMappedView, out AssemblyBindResult bindResult, out Exception?exception, out bool?result) { MetadataReader reader = pe.GetMetadataReader(); // 1. Create AssemblyName from MetadataReader RuntimeAssemblyName runtimeAssemblyName = reader.GetAssemblyDefinition().ToRuntimeAssemblyName(reader); lock (s_ecmaLoadedAssemblies) { // 2. Attempt to bind to already loaded assembly if (Bind(runtimeAssemblyName, cacheMissedLookups: false, out bindResult, out exception)) { result = true; return; } exception = null; // 3. If that fails, then add newly created metareader to global cache of loaded modules PEInfo peinfo = new PEInfo(runtimeAssemblyName, reader, pe, memoryMappedView); s_ecmaLoadedAssemblies.Add(peinfo); ModuleList moduleList = ModuleList.Instance; ModuleInfo newModuleInfo = new EcmaModuleInfo(moduleList.SystemModule.Handle, pe, reader); moduleList.RegisterModule(newModuleInfo); // 4. Then try to load by name again. This load should always succeed if (Bind(runtimeAssemblyName, cacheMissedLookups: true, out bindResult, out exception)) { result = true; return; } result = false; Debug.Assert(exception != null); // We must have an error on load. At this time this could happen due to ambiguous name matching } }