[clang] [compiler-rt] Reland [asan][windows] Eliminate the static asan runtime on windows (PR #107899)

Charlie Barto via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 11 21:13:47 PDT 2024


barcharcraz wrote:

> This PR seems to have broken ASAN in mingw configurations. The symptoms seem to be that the ASAN DLL just locks up, hard, when the process is loaded. (Or more precisely, has entered some infinite loop.)
> 
> I tried attaching to such a hung process with windbg, and it's showing this:
> 
> ```
> Break-in sent, waiting 30 seconds...
> WARNING: Break-in timed out, suspending.
>          This is usually caused by another thread holding the loader lock.
> ```
> 
> And a backtrace that looks like this:
> 
> ```
> libclang_rt_asan_dynamic_x86_64!_asan_default_options__dll
> libclang_rt_asan_dynamic_x86_64!_asan_default_options__dll+0xa17
> libclang_rt_asan_dynamic_x86_64!_sanitizer_register_weak_function+0xd2
> stacksmash_asan+0x1dad
> stacksmash_asan+0x16b7
> stacksmash_asan+0x20e3
> ntdll!LdrpCallInitRoutine+0x6f
> ntdll!...
> ```
> 
> (Side note; the PR seems to have added a bunch of new files with CRLF newlines - it'd be nice to clean this up.)
> 
> To repro the issue for yourself, you can do the following:
> 
> 1. Download and unzip https://github.com/mstorsjo/llvm-mingw/releases/download/20240903/llvm-mingw-20240903-ucrt-x86_64.zip, and add the `llvm-mingw-<version>-ucrt-x86_64\bin` directory to your `%PATH%` within a terminal
> 2. Configure a build of compiler-rt with the following parameters: `cmake ..\compiler-rt -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER_TARGET=x86_64-w64-windows-gnu -DCOMPILER_RT_DEFAULT_TARGET_ONLY=TRUE -DCOMPILER_RT_USE_BUILTINS_LIBRARY=TRUE -DSANITIZER_CXX_ABI=libc++ -DCMAKE_INSTALL_PREFIX=c:\code\llvm-mingw-20240903-ucrt-x86_64\lib\clang\19`
> 3. Build and install (on top of the newly unpacked toolchain), `ninja install`
> 4. Copy the newly built asan DLL into the current directory, `copy /y lib\windows\libclang_rt.asan_dynamic-x86_64.dll .`
> 5. Compile a trivial hello world, like https://github.com/mstorsjo/llvm-mingw/blob/master/test/hello.c (really any snippet will do), with asan `clang hello.c -o hello.exe -fsanitize=address`
> 6. Try to run `hello.exe`, which hangs.
> 
> It's possible to reproduce the same by building and running the whole compiler-rt testsuite as well, but that's a bit trickier to set up for this configuration.
> 
> Surprising side note; when I tried the repro procedure above, building compiler-rt with a slightly older Clang release, and 18.x version, the built ASAN seems to not hang. I'm not sure if this is a functional difference, or if it just so happens to link things slightly differently so whatever issue there is seems to just not happen.
> 
> This commit is kinda complex, as it not only removes the static asan configuration (which never was involved in mingw use cases before), but I guess also sets things up so the dynamic asan can be used even when linking the CRT statically?
> 
> This issue has caused my nightly builds to start failing: https://github.com/mstorsjo/llvm-mingw/actions/runs/10803005560

After investigating it is indeed mangled code due to the UB in register_weak_<whatever>. I had to step through from the very beginning of process init, as it doesn't seem like the debuginfo generated by `-gcodeview` points to the right place, but anyway for `__asan_default_options_dll` the codegen for the weak registration function looks as follows

```asm
00007ff6`90501440 4883ec28                 sub     rsp, 28h
00007ff6`90501444 488d0d752c0000           lea     rcx, [hello!.refptr._newmode+0x38 (7ff6905040c0)]
00007ff6`9050144b 488d159e1f0000           lea     rdx, [hello!__asan_default_options__dll (7ff6905033f0)]
00007ff6`90501452 e8e9060000               call    hello!_ZN11__sanitizer13register_weakEPKcy (7ff690501b40)
00007ff6`90501457 89442424                 mov     dword ptr [rsp+24h], eax
00007ff6`9050145b 8b442424                 mov     eax, dword ptr [rsp+24h]
00007ff6`9050145f 4883c428                 add     rsp, 28h
00007ff6`90501463 c3                       ret     
```
Note that there is no comparison, the call to __sanitizer::register_weak is made unconditionally, even though in this case the local function should be the same as the default implementation from the dll. Worse, it seems like it's not even loading the correct pointer for the local function, so it ends up "intercepting" some random memory! 

I've fixed this in https://github.com/llvm/llvm-project/pull/108327

https://github.com/llvm/llvm-project/pull/107899


More information about the cfe-commits mailing list