带有MinGW-w64的Clang 8:如何使用地址和UB消毒器?

时间:2019-04-02 17:18:49

标签: c++ clang mingw-w64 address-sanitizer ubsan

Clang 8 release notes的这一行很有希望:

  
      
  • 允许在MinGW上使用Address Sanitizer和Undefined Behavior Sanitizer。
  •   

但是,我无法弄清楚如何正确使用它们。

我将Clang 8.0.0与MSYS2 MinGW GCC结合使用。确切的细节在问题的底部。

我正在尝试按照以下最少的代码进行编译:

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;
}

以下是-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)

这是-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)

以下是Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\在其中查找库的内容:

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

这看起来不太正确,因为MinGW GCC通常与.a库一起使用,而不是.lib库。

我试图手动链接该目录中的各种库。

对于asan,我设法摆脱了编译器错误,但是asan本身似乎并未发出任何诊断信息:

# /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

对于ubsan,我尝试链接到clang_rt.ubsan_standalone-x86_64.lib,但获得了更多未定义的引用和多个Warning: corrupt .drectve at end of def file

我对Warning: corrupt .drectve at end of def file做过一些研究,this question暗示我正在链接不兼容的MSVC库。

这是怎么回事?我应该如何使用asan和ubsan?


以上所有命令都是从Windows 7 x64上的MSYS2终端运行的。

我的目标是x86_64,并使用MSYS2中提供的最新GCC:

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

MSYS2中的Clang似乎没有捆绑asan和ubsan库,因此我使用的是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

我正在使用-target x86_64-w64-windows-gnu,因为否则Clang会尝试使用我没有的MSVC安装。这个特定的三元组是MSYS2叮当声报告给--version的内容。

1 个答案:

答案 0 :(得分:0)

我找到了使UBsan正常工作的方法,但没有找到Asan。

结果证明,即使没有libubsan,UBsan也可以运行。您需要使用以下标志:

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

这样,通过“非法指令”崩溃报告错误,而不是发出漂亮的诊断信息,但总比没有好。

GCC和Clang均支持此标志。

  

GCC manual:

     

-fsanitize-undefined-trap-on-error

     

-fsanitize-undefined-trap-on-error选项指示编译器使用__builtin_trap而非libubsan库例程报告未定义的行为。这样做的好处是不需要libubsan库,也不会链接libubsan库,因此即使在独立环境中也可以使用。