-
Notifications
You must be signed in to change notification settings - Fork 108
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
Deviare fails to fix up branch instructions in trampoline, causing crashes #87
Comments
@bo3b which version of Deviare are we currently using? The sha1sum doesn't match any of the releases I see for it on github - was it built from source? |
This bug is still present in nektra/Deviare-InProc@3b08bab |
Very nice find. I'm really quite surprised they would miss something so obviously necessary. Our version is years old though, so maybe it has been fixed. To be honest, I cannot recall how I added the original files. Look at dates, it seems like my adding those files predates them open-sourcing the project, and any github releases. I vaguely recall that you could download directly from their website. I do not believe I had source code at that point. Assuming that is true, our code predates their 1.0 github release. |
Bummer. Edit: BTW, I did a quick code inspection, and they do handle a bunch of other variants of relative addressing, like MOV, JMP, CALL instructions. No idea why they didn't just flesh out the instruction set. |
Hi guys, I'll check it and add the patch as soon as possible. EDIT: Never hit a near jump in the code being relocated before. @DarkStarSword which API did you hook for testing? |
Thanks for looking at this :) This one was specifically ID3D11DeviceContext::VSSetSamplers() on Windows 10 (the other variants of XXSetSamplers are similarly affected - DS, HS, GS, PS, CS). Worth noting that differing Windows versions and patch levels change the d3d11 code, so these crashes can be OS / patch level specific - I don't think the above one occurs prior to Windows 10. We've also seen crashes happen when hooking ID3D11DeviceContext::VSSetShaderResources() and related functions when NumViews is passed 0 on Windows 7 with KB2670838 installed (and I think that may now also affect Windows 10, possibly following the creators update). Another variant we identified is ID3D11DeviceContext::RSSetState(), which crashes when hooked on Windows 7 without KB2670838 installed. If you wanted to use 3DMigoto to test this hooking has to be enabled in the d3dx.ini - "hook=all" will attempt to hook all ID3D11Device and ID3D11DeviceContext APIs, and there are flags to disable hooks on these specific calls. The Witcher 3 is a good game to use while testing, since it triggers the VSSetSamplers crash on Windows 10 a few seconds after the game window appears, and allows a debugger to attach to it (we have an undocumented waitfordebugger=1 option that goes under [Logging] to attach to a running game early in 3DMigoto's init), but I expect almost any game would trigger that on Windows 10. |
Commited new code |
I've updated our copy of the library in master and can confirm that the crash I as looking at above is now resolved. I'll do a little wider smokescreen testing on the other hooks as well just to be sure, then we can change hook=recommended to leave the workarounds disabled. I might wait a release or two to actually drop the "except_" options (1.3 might be a good time) - just in case. I think this justifies doing a 1.2.71 release before we archive the 1.2 branch, since 1.2.68 changed the way we prevent games from unbinding StereoParams and IniParams to depend on the XXSetShaderResources calls, so if anyone enables hooking and it's one of those games they would see 3DMigoto appear to be mostly non-functional. We've got other existing workarounds (ShaderRegex + command list to force rebinding on every draw call), but it's better if this "just works", because it is not at all obvious what has gone wrong. As a bonus - this also makes the frame analysis log useful in games where we need hooking :) |
@bo3b I'd be interested to know if you are now able to hook that IDXGIFactory::QueryInterface call you were getting crashes with in Dishonored 2, even if we don't end up using it for anything. I haven't disassembled that call to see if it was the same issue or not, but it's worth a try. |
Super good. Great advance for our stability. As another data point, I also tested Witcher3 on Win10, and could reproduce the crash, then swapped in the new InProc .lib files and no longer see the crash. I also then reverted the lib files and reproduced the crash again. This seems like a good fix. I also stepped through the asm to see the fix in action, and it looks right to me. Of note there, Debug builds will never show the problem, because even for DX11 calls they don't do early exit. Also of note, if you set the bLog=true in DLLMainHook, then you'll see the Deviare logging in the VS console for the instructions being hooked, including the prior code, and the addresses of trampoline functions. Edit: BTW, this was using 1.3 exp_single_layer. I'll take a look at the QueryInterface crash and report back. |
@DarkStarSword QueryInterface crash is unrelated to the Deviare problem. Actual patch code is:
But... the actual problem was...
Copy/Paste bug. < cough > |
Ok, good to know. Thanks @bo3b :) |
Just brought up my win7 machine and uninstalled KB2670838 to look at the RSSetState crash, and can confirm that it was the same problem and is also resolved by this fix :) |
1.2.71 is out with the updated Deviare library, and a commit removing the except_ workarounds is in the 1.3 branch, so closing this. |
I've confirmed beyond a shadow of a doubt that the Deviare library we are using is definitely the source of our crashes when hooking.
Here is the VSSetSamplers function before being hooked:
As you can see, the first three instructions is an early exit case if r8d (NumSamplers) is 0. The hook replaces the first five bytes of the function, which includes the jne instruction:
Let's examine the branch target it patched in:
That all looks fine. Now let's examine the trampoline that we call in order to call through to DirectX:
Oh dear - the jne instruction has been included here to execute out of line, but since that is a relative branch it needed to be fixed up to point back to the correct offset in the original function, which Deviare has not done. Instead it will branch here and try to execute this garbage:
There's our crash.
We need to update Deviare and see if this bug has been fixed.
The text was updated successfully, but these errors were encountered: