Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clang 8 with MinGW-w64: How do I use address- & UB sanitizers?

Clang 8 release notes have this promising line:

  • Allow using Address Sanitizer and Undefined Behaviour Sanitizer on MinGW.

However, I unable to figure out how to use those properly.

I'm using Clang 8.0.0 with MSYS2 MinGW GCC. Exact details are at the bottom of the question.

I'm trying to compile following minimal piece of code:

1.cpp

#include <iostream>

int main()
{
    // Testing ubsan
    int x = 0x7fffffff;
    x++;
    std::cout << x << std::endl;

    // Testing asan
    int *y = new int;
    delete y;
    std::cout << *y << std::endl;
}

Here are results for -fsanitize=address:

# /z/Lander/LLVM/bin/clang++ -target x86_64-w64-windows-gnu -fsanitize=address 1.cpp
Z:\Lander\msys2\mingw64\bin\ld.exe: cannot find Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\libclang_rt.asan_dynamic-x86_64.dll.a: No such file or directory
Z:\Lander\msys2\mingw64\bin\ld.exe: cannot find Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\libclang_rt.asan_dynamic_runtime_thunk-x86_64.a: No such file or directory
Z:\Lander\msys2\mingw64\bin\ld.exe: cannot find Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\libclang_rt.asan_dynamic_runtime_thunk-x86_64.a: No such file or directory
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

And here is -fsanitize=undefined:

# /z/Lander/LLVM/bin/clang++ -target x86_64-w64-windows-gnu -fsanitize=undefined 1.cpp
Warning: corrupt .drectve at end of def file
Z:\Lander\msys2\tmp\1-13f09e.o:1.cpp:(.text+0x9f): undefined reference to `__ubsan_handle_add_overflow'
Z:\Lander\msys2\tmp\1-13f09e.o:1.cpp:(.text+0xef): undefined reference to `__ubsan_handle_type_mismatch_v1'
Z:\Lander\msys2\tmp\1-13f09e.o:1.cpp:(.text+0x148): undefined reference to `__ubsan_handle_type_mismatch_v1'
Z:\Lander\msys2\tmp\1-13f09e.o:1.cpp:(.text+0x196): undefined reference to `__ubsan_handle_type_mismatch_v1'
Z:\Lander\msys2\tmp\1-13f09e.o:1.cpp:(.text+0x1df): undefined reference to `__ubsan_handle_type_mismatch_v1'
Z:\Lander\msys2\tmp\1-13f09e.o:1.cpp:(.text+0x22c): undefined reference to `__ubsan_handle_type_mismatch_v1'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

Here are the contents of Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\ where it looks for libraries:

clang_rt.asan-preinit-x86_64.lib
clang_rt.asan-x86_64.lib
clang_rt.asan_cxx-x86_64.lib
clang_rt.asan_dll_thunk-x86_64.lib
clang_rt.asan_dynamic-x86_64.dll
clang_rt.asan_dynamic-x86_64.lib
clang_rt.asan_dynamic_runtime_thunk-x86_64.lib
clang_rt.builtins-x86_64.lib
clang_rt.fuzzer-x86_64.lib
clang_rt.fuzzer_no_main-x86_64.lib
clang_rt.profile-x86_64.lib
clang_rt.stats-x86_64.lib
clang_rt.stats_client-x86_64.lib
clang_rt.ubsan_standalone-x86_64.lib
clang_rt.ubsan_standalone_cxx-x86_64.lib

This doesn't look right, since the MinGW GCC normally works with .a libraries, not .lib.

I tried to manually link various libraries from that directory.

For asan, I managed to get rid of compiler errors, but the asan itself doesn't seem to emit any diagnostics:

# /z/Lander/LLVM/bin/clang++ -target x86_64-w64-windows-gnu -fsanitize=address 1.cpp -c
# /z/Lander/LLVM/bin/clang++ -target x86_64-w64-windows-gnu 1.o /z/Lander/LLVM/lib/clang/8.0.0/lib/windows/clang_rt.asan_dynamic-x86_64.lib
# ./a.exe
-2147483648
5089296         <- expected a diagnostic here

For ubsan, I tried to link against clang_rt.ubsan_standalone-x86_64.lib, but got more undefined references and several Warning: corrupt .drectve at end of def file.

I did some research on Warning: corrupt .drectve at end of def file, and this question suggests that it means I'm linking incompatible MSVC libraries.

What's going on here? How am I supposed to use asan & ubsan?


All commands above were run from MSYS2 terminal, running on Windows 7 x64.

I'm targeting x86_64 and using latest GCC available in MSYS2:

# g++ --version
g++.exe (Rev2, Built by MSYS2 project) 8.3.0

Clang from MSYS2 doesn't seem to have asan & ubsan libraries bundled, so I'm using the official build from llvm.org:

# /z/Lander/LLVM/bin/clang++ --version
clang version 8.0.0 (tags/RELEASE_800/final)
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: Z:\Lander\LLVM\bin

I'm using -target x86_64-w64-windows-gnu because otherwise Clang tries to use a MSVC installation, which I don't have. This specific triplet is what MSYS2 clang reports in reponse to --version.

like image 338
HolyBlackCat Avatar asked Apr 02 '19 17:04

HolyBlackCat


2 Answers

ASAN indeed works on Windows.

To avoid errors such as:

C:/msys64/mingw64/bin/ld: cannot find C:/msys64/mingw64/lib/clang/13.0.0/lib/windows/libclang_rt.asan_dynamic-x86_64.dll.a: No such file or directory
C:/msys64/mingw64/bin/ld: cannot find C:/msys64/mingw64/lib/clang/13.0.0/lib/windows/libclang_rt.asan_dynamic_runtime_thunk-x86_64.a: No such file or directory

use /clang64/bin/clang instead of /mingw64/bin/clang. Install it with:

pacman -S mingw-w64-clang-x86_64-clang

See https://www.msys2.org/docs/environments/

like image 161
0xF Avatar answered Sep 21 '22 08:09

0xF


I've found a way to make UBsan work, but not Asan.

Turns out, UBsan can function even without libubsan. You need to use following flags:

-fsanitize=undefined -fsanitize-undefined-trap-on-error

This way, errors are reported via crashing with 'Illegal instruction' rather by emitting pretty diagnostics, but it's better than nothing.

This flag is supported by both GCC and Clang.

GCC manual:

-fsanitize-undefined-trap-on-error

The -fsanitize-undefined-trap-on-error option instructs the compiler to report undefined behavior using __builtin_trap rather than a libubsan library routine. The advantage of this is that the libubsan library is not needed and is not linked in, so this is usable even in freestanding environments.

like image 37
HolyBlackCat Avatar answered Sep 23 '22 08:09

HolyBlackCat