4 ms·
In general, this doesn't work by accident. In practice, whenever calling a function from a different DLL, normally a thunk is inserted (if it isn't marked dllim
by mstorsjo 5y ago
In general, this doesn't work by accident. In practice, whenever calling a function from a different DLL, normally a thunk is inserted (if it isn't marked dllimport), and when referencing a variable that might reside in a different DLL (and be autoimported), its address is read indirectly via a full 64 bit pointer.
When linking to a function "func" in another DLL, the import library normally provides two symbols, "func" which is a thunk which allows it to be called from anywhere, and "__imp_func" which is the IAT entry (containing a full 64 bit address). If the caller called it via a dllimport marked declaration, it's using "__imp_func", otherwise it uses "func" and ends up jumping via a thunk.
In some cases, when mingw-w64 wants to override importing certain functions (by providing a statically linked version of it instead), the functions are marked "DATA" in the def file (which is used for generating the import libraries). Then the thunk is left out and only the "__imp_func" symbol is left. If you hit a situation where you didn't end up linking the intended replacement function, then it's possible to hit this situation where you autoimport something that only works if it's loaded close enough. (In hindsight, it might have been even better to comment out those functions entirely from the import libraries.)
If you do hit this issue again (or if you remember exactly how to reproduce it), then plese do file a bug somewhere so we can look into it.
But in general, mingw-w64 linked binaries, even including ones using the autoimport facility and runtime pseudo relocations, should work even if they are loaded far apart from each other.
- jchw 5y agoThis is useful information, and I think it explains exactly how we wound up with pseudo relocs instead of thunks, but honestly, the thing that makes this so bothersome is that there's really no documentation that explains this, there's seemingly no warning when it occurs, and there's no error when it fails. From my perspective, I saw WINE crashing with a CALL into seemingly nowhere. Then I realized the CALL on disk pointed directly to the IAT (which obviously makes no sense.) Finally I realized that the library probably shouldn't be linking to VirtualProtect, traced it to the entrypoint, and found an error message that made me aware of the existence of pseudo relocs. There was a 0% chance the person who created this bug was ever going to figure it out, and I'm not even sure I could've figured out the build issue if I had access to the project files. There's plenty of minutiae when it comes to MinGW and MSys and a lot of people are not adequately prepared for what they are getting themselves into. I think (hope) the mess with exception handling is cleared up and everyone just uses SEH on Windows, but I bet there's still issues with licensing and winpthreads, and MSys and PTYs. I'd be more than happy to try to submit PRs to help with this particular problem, though I'm not going to lie, I find the pseudo-reloc thing horrifying and would be afraid of somehow breaking some ridiculous edge case.
- mstorsjo 5y agoRegarding error reporting - yeah, it's super non obvious when that happens. See the sibling post I made; I've added error reporting for that case now (2 months ago, so not in any released version yet).
- ChrisSD 5y agoWhile you're here, do you happen to know if mingw will gain support for native thread local storage? Emulated TLS is still the only option, right?
- mstorsjo 5y agoClang (and lld) do support native TLS, and mingw-w64 does have the things that are needed. I think binutils also might have what's needed too, but AFAIK the thing that's missing is support for it in GCC. Actually, (upstream) Clang defaults to native TLS instead of emulated TLS. In MSYS2, Clang is overridden to use emulated TLS by deafult to interoperate better with GCC built code and libstdc++ though. The toolchain I maintain, https://github.com/mstorsjo/llvm-mingw https://github.com/mstorsjo/llvm-mingw, defaults to native TLS throughout.
- ChrisSD 5y agoThanks! That's super helpful.
- mstorsjo 5y agoOh, I forgot to add; these days, msys2 have got a number of extra package repos. They have one, "CLANG64", which has got Clang/lld as the default compiler (just like in llvm-mingw) and with all packages built that way. And there, it defaults to native TLS too. Depending on your use case, this might be easier to take for a spin than llvm-mingw.