ruptura icon indicating copy to clipboard operation
ruptura copied to clipboard

Support injecting NativeAOT-compiled DLLs (.NET 8)

Open alexrp opened this issue 2 years ago • 2 comments

In theory, Ruptura + NativeAOT is a match made in heaven. We could just inject a NativeAOT-compiled DLL and directly invoke an entry point method in it, skipping ruptura-<arch>.dll and all the ceremony around .NET hosting entirely.

For this to work, the source generator would need to export a function that we can invoke to pass in these parameters:

https://github.com/vezel-dev/ruptura/blob/adc65b4532d70c0f61e6c4a0aafd29e1466408a5/src/module/main.h#L3-L12

That function would then do all the initialization that the native module currently does (e.g. calling InjectedProgramContext.Initialize()), and then call the user's IInjectedProgram.RunAsync() implementation.

NativeAOT does come with a number of disadvantages that are inherent to that model of compilation: Very limited reflection, no dynamic code generation, forced IL trimming, and more. This means that any NativeAOT support would exist alongside our current hosting model so that users can choose the approach that makes the most sense for them.

alexrp avatar Jul 06 '22 12:07 alexrp

NativeAOT support in .NET 8 should be good enough that we can do this.

alexrp avatar Aug 03 '23 06:08 alexrp

When we do this, we should just document the exported entry point that Vezel.Ruptura.Injection will support. That way, it can effectively be used to inject arbitrary native DLLs that conform to that signature. Something like:

typedef struct
{
    size_t size;
    const wchar_t *nonnull *nonnull argument_vector;
    uint32_t argument_count;
    uint32_t injector_process_id;
    uint32_t main_thread_id;
} ruptura_native_parameters;

__declspec(dllexport) uint32_t ruptura_native_main(ruptura_native_parameters *nonnull parameters);

alexrp avatar Apr 30 '24 01:04 alexrp