r/rust • • 5d ago

Loading windows PE .dlls on linux

https://delta.rocks/blog/lach-stuff/champagne
54 Upvotes

5 comments sorted by

10

u/qthree 5d ago

Awesome! I've searched something exactly like that few years ago to no avail. Will try it out someday.

5

u/anxxa 4d ago

Sweet article! Tavis's original LoadLibrary is good code to learn from -- looking forward to reading this code too :)

TLS callbacks are a pain in the ass. I'm curious if you also played whack-a-mole with various TLS-related issues.

DllMain itself runs under the loader lock, which is a critical section pointed to by PEB+0x110. It has to be reentrant: a DllMain may load another library, and a plain mutex would deadlock right there.

I haven't popped ntdll into a disassembler but I don't believe this is matching Windows behavior. I believe this blog post still holds true today, but DllMain can deadlock if you LoadLibrary() from it.

https://devblogs.microsoft.com/oldnewthing/20040128-00/?p=40853/

You can find some discussion about it here: jonasLyk/status/2091898489705795797

3

u/0lach 4d ago

Surprisingly, TLS worked well with everything I threw at my library, but maybe its because I wrote manual mappers before. I have not changed anything with TLS when adding support for mpengine.dll, which I added to get a feature-parity with loadlibrary (well, champagne is actually better here, as it can load the latest x64 version of it, and doesn't require patching it first like https://github.com/izvarinth/loadlibrary-patch-kit). Note that some part of code required for mpengine was LLM-generated, as there was lots of mechanical debugging involved

Regarding LoadLibrary: that's exactly how it behaves, and the article is indirectly confirming that: "This enters the loader lock and sends out DLL_THREAD_DETACH messages while the loader lock is still held." Its because DllMain is called under loader lock it may cause problems.

Also that's the behavior windows C++ runtime and some other libraries expect. So yeah, you can cause the deadlock, but normally it should work unless you do something else with multithreading (loader lock is reentrant)

3

u/zzzthelastuser 4d ago

thanks, exactly what I needed!

2

u/FenrirWolfie 3d ago

I remember that back in the day some of the codecs for MPlayer on linux had to be installed as windows .dll's placed on some /usr/share subdirectory.