Closed valters-tomsons closed 3 months ago
Note: This library will be deprecated in a couple of months; I've written ~80% of a Rust successor already.
And will provide a backcompat layer that implementes IReloadedHooks
It's just on a small hiatus while I write the Reloaded3 docs; so that may take around half a year.
That said, I'm still happy to help nonetheless.
Here's some quick questions:
Reloaded.Hooks.Trim.Dummy
, it's meant to be used to catch trimmer errors.A few years ago I went through a lot of pain to get this annotated for trimming (there's almost 100 trim annotations), in an era where Source Generators still weren't really a thing. Although Reloaded.Memory
7.x is quite dated, that's also trimming annotated.
I've used this library trimmed before (with JIT though), so it's kind of a bummer to see it fail in a specific use case :sweat_smile:
It's also a bit weird that it would trim away Reloaded.Memory.Sources.IMemory
. There shouldn't be any reflection involved there, or up to the path of new Hook<T>()
. I do find that quite odd.
Hey, thanks for the reply! Great to see you working on more stuff!
There are some warnings on the Hook
constructor:
warning IL2026: Using member 'System.Delegate.CreateDelegate(Type, Object, String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. The target method might be removed.
warning IL2026: Using member 'System.Delegate.CreateDelegate(Type, Object, String, Boolean)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. The target method might be removed.
warning IL2026: Using member 'System.Delegate.CreateDelegate(Type, Object, String, Boolean, Boolean)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. The target method might be removed.
warning IL2111: Method 'System.Delegate.CreateDelegate(Type, Type, String)' with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method.
warning IL2111: Method 'System.Delegate.CreateDelegate(Type, Type, String, Boolean)' with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method.
warning IL2111: Method 'System.Delegate.CreateDelegate(Type, Type, String, Boolean, Boolean)' with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method.
Here's the runtime exception too:
Unhandled exception. System.TypeLoadException: Could not load type 'Reloaded.Memory.Sources.IMemory' from assembly 'Reloaded.Memory, Version=9.4.1.0, Culture=neutral, PublicKeyToken=null'.
at Internal.Runtime.CompilerHelpers.ThrowHelpers.ThrowTypeLoadException(ExceptionStringID, String, String) + 0x10
at Reloaded.Hooks.Tools.Utilities.CreateJump(UIntPtr, Boolean, Int32) + 0x12
at Reloaded.Hooks.X86.ReverseWrapper`1.Create(ReverseWrapper`1, UIntPtr) + 0xc9
at Reloaded.Hooks.X86.ReverseWrapper`1..ctor(TFunction) + 0x45
at Reloaded.Hooks.Hook`1.CreateReverseWrapper(TFunction) + 0x50
at frosthook.Patches.BC2.Win32ServerR11.Initialize() + 0x17a
at frosthook.FrostHook.OnAttach() + 0x20
at frosthook.EntryPoint.DllMain(IntPtr, FwdReason, IntPtr) + 0x2fd
I assume this would also be an issue on .NET 8 AOT too
As for reproduction
hook
branch of this repo: https://github.com/valters-tomsons/frosthookdotnet publish src/ -c Release -r win-x86 -o ./frosthook-win-x86
frosthook-win-x86
to a folder of a 32-bit app that imports dinput8.dll
Few notes:
DllMain
and loader lock memes applyWhoops, turns out the runtime error is caused by having a reference to newer version of Reloaded.Memory
than Reloaded.Hooks
relies on. Removing memory package lets the hooks work!
Trimming warnings remain, but the hook seems to actually work! :+1:
I'll reboot into Windows check the trimmer warning when I finish up eating, but yeah, it should work.
Curious why the warning shows up, I don't even call that API pretty sure. Unless it's some compiler sugar.
I checked.
Nothing wrong with the library, you're getting trimmer warnings because you haven't propagated the trimmer attributes from the library onto your code.
Normally you shouldn't have to do that. I think I know the reason why it's complaining though. Usually when you build a normal program, the trimmer checks for used code from the entry point.
But because it's a library technically speaking, the NAOT tooling maybe doesn't yet recognize DLL exports as roots. Assuming you don't have any dead code, doing this should be sufficient:
<ItemGroup>
<TrimmerRootAssembly Include="frosthook" />
</ItemGroup>
To mark the whole library as a root. (I rebooted back to Linux so can't doublecheck this).
But that should probably resolve your issue.
Some extra notes:
Most likely any 32-bit game will work
If you're planning on building a mod loader, or component with a plugin system, NAOT might not be the best choice here.
Every single NAOT Mod will get their own GC heap; they unfortunately don't know how to share. These days with regions, I think that's ~4MB, and all the GC code, and some metadata.
This means you risk virtual address space starvation.
loader lock memes apply
Careful with using hooks from here, yeah.
Hooks depend on the FASM
DLL, you might hit the loader lock if called directly from DllMain.
Edit:
CreateFileA
Consider hooking NtCreateFile, it's the lowest level user mode function. Otherwise you risk missing some file open events. Feel free to copy definitions for that from reloaded.universal.redirector
or FileEmulationFramework
.
Silly me, that makes sense, for some reason I expected the compiler to automatically recognize DLL exports. :+1:
Thanks for the extra notes, I'm not planning to build anything extendable, so that should not be a problem.
Thanks again!
Edit: warnings were gone for a moment, but they're back, so that wasn't it. Keeping this closed, since hooking itself seems to work just fine.
Description
I'm trying to use
Reloaded.Hooks
in a project with Ahead-Of-Time (AOT) compilation, but it appears that hook generation needs runtime reflection. Additionally, the trimmer seems to strip away important types likeReloaded.Memory.Sources.IMemory
. This issue complicates the use ofReloaded.Hooks
in AOT scenarios.Would it be possible to provide reflection-less & trimming-friendly hooks?
Use Case
I am running the hooker outside the regular Reloaded-II runtime/injector, and instead, compiling as a native
dinput8.dll
proxy that's placed in the target folder. See hereExpected Behavior:
An AOT compiled project depending on
Reloaded.Hooks
should build without warnings and install hooks without runtime exceptions.Actual Behavior
The application builds with warnings, and at runtime, it fails to load
Reloaded.Memory.Sources.IMemory
onnew Hook<T>()
due to the trimming process removing necessary components.