New version of wow64ext library is available for download:
http://rewolf.pl/stuff/rewolf.wow64ext.v1.0.0.8.zip
or if someone prefer github:
https://github.com/rwfpl/rewolf-wow64ext
Changelog
- Fixed elusive bug that appears only on AMD cpus
- Removed VS CRT dependencies – dll size shrank to 9kB (previously 41kB)
- Added sanity checks, so x64 switch won’t run on x86 OS
More details
AMD case is really interesting as it seems that the crash is randomly happening after X64_End() macro inside X64Call() function:
mov dword ptr [esp+4],23h add dword ptr [esp],0Dh retf mov esp,dword ptr [ebp-4] |
I don’t have access to the AMD cpu, but with the help of @KacperSzurek I was able to reproduce the issue and investigate few crashdumps. Crash is always triggered by mov esp, dword ptr[ebp – 4]. WinDbg states that it’s access violation, but it’s clearly visible that memory at [ebp – 4] is accessible. I’ve also tried moving [ebp – 4] to registers other than esp and the crash persisted. There must be some race condition after RETF that renders unusable some memory pages. I was trying few different approaches to fix it, for example placing NOP or PAUSE opcodes between RETF and MOV, but it didn’t helped. Finally I’ve found a combination that solves the problem (or mask it :) but I tend to believe that it’s the solution):
mov dword ptr [esp+4],23h add dword ptr [esp],0Dh retf mov ax, ds mov ss, ax mov esp,dword ptr [ebp-4] |
According to Intel manuals MOV SS opcode has special handling:
Loading the SS register with a MOV instruction inhibits all interrupts until after the execution of the next instruction. This operation allows a stack pointer to be loaded into the ESP register with the next instruction (MOV ESP, stack-pointer value) before an interrupt occurs1. Be aware that the LSS instruction offers a more efficient method of loading the SS and ESP registers.
I’ve no idea why it works, probably it repairs some inconsistent CPU state, but I’ve too less information and knowledge to properly explain it. If anyone cares to research it more deeply, feel free, I’ll be more than happy to read about it.
Crashes were 100% reproducible on AMD FT3 Kabini A4-5000 Quad-Core APU. I would like to thank Mark, who reported this issue and pinpointed the crashes to AMD cpus.
good work! :-)
Is there anything like Wow64-32Ext which enables x64 code to call any x86 function(WOW64)?
Not really, since the wow64ext library is supposed to enable x86 apps with some x64 interfaces that are otherwise not accessible. I assume that you’re asking because you want to load some legacy x86 library to the x64 process. In theory it’s doable, however I’ve no idea if anyone wrote ready-to-use library to do it.
@ReWolf
That’s also what I wanted to ask. I’d use this kind of a library, in case you’re looking for a fun project :)
And thanks for wow64ext!
@ReWolf Does this lib can call any function from a custom .dll?
I have test with LdrLoadDll to load my .dll and call a simple function: test64
If the function only have 1 line code: OutputDebugStringA(“hello world!”);
It’s ok
But if the function have 1 line code: MessageBox to show a simple tips window.
It will be crash.
How to call in the Delphi?