Address/memory/thread sanitizer WIP
Opening this draft PR to discuss and get feedback.
TODO
- [ ] Windows
- [ ] macOS
- [x] Project option
- [x] sanitizer.c3 (common_interface_defs.h)
- [x] tsan.c3 (tsan_interface.h)
There is an issue on macOS where I get an undefined symbol __asan_version_mismatch_check_v8, presumably because it's linking the wrong asan library. Not sure what to do about it.
Edit: Apparently it's linking against /Library/Developer/CommandLineTools/usr/lib/clang/15.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib.
So I've ran some experiments and with Windows there are different linking options based on CRT type (see https://devblogs.microsoft.com/cppblog/asan-for-windows-x64-and-debug-build-support/)
- Dynamic CRT
- Need to link
clang_rt.asan_dynamic-x86_64.libandclang_rt.asan_dynamic_runtime_thunk-x86_64.lib - Need to copy
clang_rt.asan_dynamic-x86_64.dllnext to built exe, because I don't know how else it would be found- This raises the question if the dll should be deleted from the output dir if not needed anymore
- Static CRT
- Link
clang_rt.asan-x86_64.lib, BUT need to link non-debug CRT to avoid symbol conflicts- So would we need to change
--wincrtoptions tostatic|static-debug|dynamic|dynamic-debugand not make it depend on whether debug info is enabled?
- So would we need to change
- OR, linking dynamically as in
1.also seems to work even though it's not mentioned in blog post
static / static-debug should be possible to deduce from whether debug is used or not.
Found more up to date info here, although some of their changes to LLVM/Asan are not officially released yet.
https://learn.microsoft.com/en-us/cpp/sanitizers/asan-runtime?view=msvc-170
Before Preview 3 they also use asan libraries linked against debug CRT, such as clang_rt.asan_dbg-{arch}.lib, which must come from a custom build on an unreleased branch as well.
I can't be bothered with the LLVM compiler-rt dumpster fire on Windows at the moment, so I think we should just start with Linux here and gradually add support for Windows and Darwin in the future.
A possibility is to just upload compiler-rt.lib from elsewhere.
I know the standalone build of compiler-rt works, so we should go back to that.
Note that unless single-module is enabled, you'll get a bunch of duplicate symbol errors on Windows with address sanitizer enabled. That's why I added a check for it. Might want to take a look at why that happens @lerno.
Did you check the linker arguments?
What linker arguments? It's not about external symbols, it's about the ones inserted by the asan pass on functions in generic modules.
Oh, ok.
The macOS linker issue with -fsanitize=address is fixed by passing the correct -resource-dir to the system linker.
For example for me it would be -resource-dir=/opt/homebrew/opt/llvm/lib/clang/17.
I don't know what the the situation with the builtin linker is since you can't even use it, but I'm noting that lld doesn't support -fsanitize=address so you'd have to link libclang_rt.asan_osx_dynamic.dylib manually.
Linking the library manually isn't that much of a problem though?
I don't know how -fsanitize=... selects the libraries to link, but no. The problem is more how to get the library path.
It seems to depend. For example, if I look into: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/15.0.0/lib/darwin on my machine I have a bunch of asan dylibs.
I rebased dev and made the changes needed to call asan correctly. HOWEVER, if you look there are additional settings you can give to the sanitizers. They should be set as well.
It seems to depend. For example, if I look into: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/15.0.0/lib/darwin on my machine I have a bunch of asan dylibs.
Yeah those are not ABI compatible anymore though.
You mean compatible with the LLVM 18 Asan output? I've cut away LLVM < 17 support now. I think it should be possible to the get the asan libraries from the LLVM builds as long as they also got Clang. I'd place things in a /compiler_support/ library and try to look for it in the same places the compiler looks for the standard library.
Windows almost looks good now with the new asan pass, however you still need to add this to not exit with an odr-violation error on startup:
fn ZString __asan_default_options() @export("__asan_default_options") @if(env::ADDRESS_SANITIZER) {
return "detect_odr_violation=0";
}
Alternatively you need to to have this environment variable set for the process: ASAN_OPTIONS=detect_odr_violation=0.
I don't know how this could automatically be compiled into the program. You'd still want to give a user the option to define __asan_default_options with their own set of options.
I've added a warning for the odr-violation issue on Windows since I can't think of a better solution.
Other than that it's pretty close to being done on my end. You might want to review the changes to wincrt @lerno. It decouples the type of wincrt from the debug info setting.
This is ready for review @lerno, I'd like for this to be merged soon.
Thank you, I'm excited to have this finally in the compiler. I'm planning to take time this evening.
PS I'll handle the merge conflicts as well.
Can you please squash this into a single commit for me to look at? I can do the final merge onto master, but before that I want something that's just a single commit to merge rather than more than 10 commits.
I squashed it and preserved the commit history in another branch.
Can you have a look at sanitizer2 and check that I didn't introduce any new problems in my rebase?
Thank you for your hard work!