Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.NET Runtime Contexts #471

Closed
Washi1337 opened this issue Aug 1, 2023 · 0 comments · Fixed by #537
Closed

.NET Runtime Contexts #471

Washi1337 opened this issue Aug 1, 2023 · 0 comments · Fixed by #537
Labels
dotnet Issues related to AsmResolver.DotNet enhancement
Milestone

Comments

@Washi1337
Copy link
Owner

Washi1337 commented Aug 1, 2023

Problem Description

.NET binaries often depend on one or more DLL dependencies. These in turn may have dependencies on their own, all the way back to mscorlib (.NET Framework) or System.Private.Corlib (.NET Core / .NET). AsmResolver currently loads all modules independently of each other. Currently, this poses a couple problems:

  • Walking the dependency graph may result in loading the same dependency multiple times. Consider assembly A that depends on assembly B. When a type resolution is issued for a member reference defined in B from A, loading assembly B may trigger the load of mscorlib a second time given that assembly B also depends on mscorlib but has their own assembly resolver and thus their own assembly cache.

  • Different modules can target different .NET runtimes which may trigger different resolvers to be initialized. Consider a main assembly A targeting .NET Framework 4.6.x that depends on assembly B targeting .NET standard 2.0. By default, loading assembly B will initialize an instance of DotNetCoreAssemblyResolver. However, from the perspective of assembly A, a DotNetFrameworkAssemblyResolver should be initialized instead since the library would be loaded under .NET Framework as opposed to .NET Core. This can result in inconsistencies during type resolution and signature comparing. In particular, these inconsistencies may result in resolution scopes to be resolved multiple times during type signature comparisons (to determine equivalence), which is very slow.

  • AppHost bundles may have their own set of embedded dependencies. Not only may these dependencies be third-party that won't exist in the same source folder, these dependencies may also include a specific version of the BCL libraries themselves (e.g. in the case of single-file-host binaries). AsmResolver ideally should prefer loading assemblies embedded in the bundle (keeping in mind the runtimeconfig.json file as well), over the ones that can be found on the file system.

Proposal

The challenges above would be solved in the following manner:

  • Introduce a concept of runtime contexts. This would be similar to System.Runtime.Loader.AssemblyLoadContext but for binaries loaded statically by AsmResolver where .NET binaries are loaded and wired with a single assembly resolver based on the "root" assembly.

  • Add runtime context property to ModuleReaderParameters. When not null, the module will be loaded into this runtime context.

  • Add a get-only property ModuleDefinition::RuntimeContext exposing the context the module was loaded in. This is useful when manually opening multiple modules in the same load context, or when a user wants to get access to the "root" assembly easily.

  • Add an assembly resolver specifically for apphost/singlefilehost binaries. This is to facilitate the option of processing bundled files without having to extract them to the disk first. BundleManifest should also provide a RuntimeContext property for the loaded bundle, such that all assemblies embedded in the bundle can be easily loaded using the same load context as well.

Alternatives

The alternative for users right now is to manually assign the right reader parameters and assembly resolvers to each module that is being loaded, or to add all loaded assemblies to the assembly cache of each resolver. This, however, is very error-prone and is also highly susceptible to data-races given the nature of AsmResolvers lazy initialization.

Additional Context

This is a stepping stone for AsmResolver.Workspaces (#298).

@Washi1337 Washi1337 added enhancement dotnet Issues related to AsmResolver.DotNet labels Aug 1, 2023
@Washi1337 Washi1337 added this to the 6.0.0 milestone Aug 1, 2023
@Washi1337 Washi1337 changed the title .NET Assembly Load Contexts .NET Runtime Contexts Mar 5, 2024
@Washi1337 Washi1337 linked a pull request Mar 16, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dotnet Issues related to AsmResolver.DotNet enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant