Windows NT 5.x 系で動かすとどうしてもクラッシュしてしまうプログラムについて
無理やり、Java 9 を Windows 2000で動かす実験をしてるのですが次のコードで引っかかってるので解説するよ。
| SUB_L081B7500: push ebp mov ebp,esp mov edx,[L086A3308] mov eax,fs:[0000002Ch] push ebx push esi mov esi,ecx mov eax,[eax+edx*4] <- eax = 0! Fault |
何が行われてるかというと、TLS(Thread Local Storege) にアクセスしようとしてる。
Vista 以降では 0以外がかえってくるのだが…。
disassembly – Thread local storage access on Windows XP – Reverse Engineering Stack Exchange
| Obviously the compiler seems to implement thread-safety by first poking into the TLS slot of the current thread. fs:2Ch is supposed to lead to the TLS array per documentation. However on Windows XP, fs:2Ch doesn’t seem to be set. This returned 0 for me and so did the next instruction (_tls_index was also 0.) That led to the 3rd instruction blowing up as it was accessing invalid memory.
“On Windows Vista and later, dynamically-loaded DLLs also support Thread Local Storage. This is in direct contradiction to the existing Portable Executable format documentation, which states that “Statically declared TLS data objects … can be used only in statically loaded image files. This fact makes it unreliable to use static Thread Local Storage data in a DLL unless you know that the DLL, or anything statically linked with it, will never be loaded dynamically with the LoadLibrary API function |
XPはLoadLibrary で初期化されないらしい
スレッド ローカル ストレージ (TLS: Thread Local Storage)
| Windows Vista より前の Windows オペレーティング システムでは、__declspec( thread ) にいくつか制限があります。 DLL で任意のデータまたはオブジェクトを __declspec( thread ) として宣言した場合、動的に読み込まれたときに保護違反が発生する可能性があります。 DLL が LoadLibrary によって読み込まれると、コードが __declspec( thread ) データを参照するたびにシステム エラーが発生します。 スレッドのグローバル変数領域は実行時に割り当てられるため、この領域のサイズは、アプリケーションの要件および静的にリンクされているすべての DLL の要件に基づいて計算されます。 LoadLibrary を使用すると、__declspec( thread ) を使用して宣言されたスレッド ローカル変数用にこの領域を拡張することはできません。 DLL が LoadLibrary で読み込まれる可能性がある場合は、DLL で TLS API (TlsAlloc など) を使用して TLS を割り当ててください。 |
・ω・まじかよ!
VC++ 2015で作ったDLLをWindows XPで動かすと最悪死ぬ – イグトランスの頭の中
試しに次のコード書いてみる
| DLL_THREAD_ATTACH: _asm{ call DWORD PTR [TlsAlloc] mov eax,fs:[00000018h] add eax,0xe10 mov fs:[0x2c],eax } |
ちなみに、これやると、Windows Vista 以降だとクラッシュする
| c:\java\jre-9>bin\java -version Error occurred during initialization of VM java.lang.UnsatisfiedLinkError: N:\dev\jre-9\bin\nio.dll: 指定されたプロシージャが見つかりません。 at java.lang.ClassLoader$NativeLibrary.load(java.base/Native Method) |
ちょっとエラーが変わった。 nio.dllで CreateSymbolicLinkW を使っててロードできないらしい
(つづく)


Comments