The system call NtSetInformationProcess.ProcessTlsInformation modifies the static TLS pointers in other threads. If DR is swapping static TLS TEB fields, the kernel could modify a thread while it is in DR state, failing to properly update the app state. To solve this, we suspend all other threads and swap them to app state before executing the system call.
Avoids static TLS field swapping if no private libraries are using any slots. Previously, TEB.ThreadLocalStoragePointer was swapped if any client was present at all, regardless of whether any static TLS slots were in use by private libraries. Given that late-loaded static TLS is not supported, we know at gencode creation time whether we have any static TLS slots to make swapping worthwhile. Adds an assert that this holds to help catch this if we later add late-loaded static TLS support.
Adds static TLS to the client.tls test, which exercises the new code, but does not necessarily reproduce a fatal crash from the bug. The suspend solution (without the swap-avoid solution in place yet) was manually tested with drcov on the minimized code calling GetOpenFileName at https://github.com/DynamoRIO/dynamorio/issues/4136#issuecomment-613135121 where a crash happened on initialization prior to drawing the window on every run before the solution was applied.
Fixes #4136 (closed)