使用 Memory Sanitizer 检测 libc++

Using Memory Sanitizer instrumented libc++

我已经按照 here 的描述构建了一个检测过的 libc++。我已经按照上面网站的建议设置了标志:

MSAN_CFLAGS="-fsanitize=memory -stdlib=libc++ -L/path_to/llvm-build-msan/lib -lc++abi -I/path_to/llvm-build-msan/include -I/path_to/llvm-build-msan/include/c++/v1"

并尝试构建这个:

#include <string.h>
#include <stdio.h>

int main(){
    char str[] = "This is a sample string";
    char * pch;
    printf ("Looking for the 's' character in \"%s\"...\n",str);
    pch=strchr(str,'s');
}

与:clang++ ${MSAN_CFLAGS} m.cpp。我得到了:

In file included from m.cpp:1:
/path_to/llvm-build-msan/include/c++/v1/string.h:74:64: error: use of undeclared identifier 'strchr'
char* __libcpp_strchr(const char* __s, int __c) {return (char*)strchr(__s, __c);}
                                                               ^
/path_to/llvm-build-msan/include/c++/v1/string.h:81:75: error: use of undeclared identifier 'strpbrk'
char* __libcpp_strpbrk(const char* __s1, const char* __s2) {return (char*)strpbrk(__s1, __s2);}
                                                                          ^
/path_to/llvm-build-msan/include/c++/v1/string.h:88:65: error: use of undeclared identifier 'strrchr'; did you mean 'strchr'?
char* __libcpp_strrchr(const char* __s, int __c) {return (char*)strrchr(__s, __c);}
                                                                ^
/path_to/llvm-build-msan/include/c++/v1/string.h:76:13: note: 'strchr' declared here
const char* strchr(const char* __s, int __c) {return __libcpp_strchr(__s, __c);}
            ^
/path_to/llvm-build-msan/include/c++/v1/string.h:95:49: error: unknown type name 'size_t'
void* __libcpp_memchr(const void* __s, int __c, size_t __n) {return (void*)memchr(__s, __c, __n);}
                                                ^
/path_to/llvm-build-msan/include/c++/v1/string.h:97:46: error: unknown type name 'size_t'
const void* memchr(const void* __s, int __c, size_t __n) {return __libcpp_memchr(__s, __c, __n);}
                                             ^
/path_to/llvm-build-msan/include/c++/v1/string.h:99:46: error: unknown type name 'size_t'
      void* memchr(      void* __s, int __c, size_t __n) {return __libcpp_memchr(__s, __c, __n);}
                                             ^
/path_to/llvm-build-msan/include/c++/v1/string.h:102:74: error: use of undeclared identifier 'strstr'; did you mean 'strchr'?
char* __libcpp_strstr(const char* __s1, const char* __s2) {return (char*)strstr(__s1, __s2);}
                                                                         ^
/path_to/llvm-build-msan/include/c++/v1/string.h:78:13: note: 'strchr' declared here
      char* strchr(      char* __s, int __c) {return __libcpp_strchr(__s, __c);}
            ^
/path_to/llvm-build-msan/include/c++/v1/string.h:102:74: error: no matching function for call to 'strchr'
char* __libcpp_strstr(const char* __s1, const char* __s2) {return (char*)strstr(__s1, __s2);}
                                                                         ^
/path_to/llvm-build-msan/include/c++/v1/string.h:78:13: note: candidate disabled: <no message provided>
      char* strchr(      char* __s, int __c) {return __libcpp_strchr(__s, __c);}
            ^
/path_to/llvm-build-msan/include/c++/v1/string.h:102:81: error: cannot initialize a parameter of type 'char *' with an lvalue of type 'const char *'
char* __libcpp_strstr(const char* __s1, const char* __s2) {return (char*)strstr(__s1, __s2);}
                                                                                ^~~~
/path_to/llvm-build-msan/include/c++/v1/string.h:78:32: note: passing argument to parameter '__s' here
      char* strchr(      char* __s, int __c) {return __libcpp_strchr(__s, __c);}
                               ^
m.cpp:7:5: error: use of undeclared identifier 'printf'
    printf ("Looking for the 's' character in \"%s\"...\n",str);
    ^
10 errors generated.

我还尝试使用与构建 libc++ 相同的方法来构建已清理的内存 clang++,但我得到了:

[  9%] Building Checkers.inc...
==20994==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x53bf93 in _M_lower_bound /usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/stl_tree.h:1887:7
    #1 0x53bf93 in std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<llvm::Record, std::default_delete<llvm::Record> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<llvm::Record, std::default_delete<llvm::Record> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<llvm::Record, std::default_delete<llvm::Record> > > > >::find(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const /usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/stl_tree.h:2536
    #2 0x6f0f32 in find /usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/stl_map.h:1174:21
    #3 0x6f0f32 in getClass /path_to/llvm/include/llvm/TableGen/Record.h:1536
    #4 0x6f0f32 in llvm::TGParser::ParseClass() /path_to/llvm/lib/TableGen/TGParser.cpp:2130
    #5 0x6f0924 in llvm::TGParser::ParseObject(llvm::MultiClass*) /path_to/llvm/lib/TableGen/TGParser.cpp:2669:29
    #6 0x6fc77a in ParseObjectList /path_to/llvm/lib/TableGen/TGParser.cpp:2678:9
    #7 0x6fc77a in llvm::TGParser::ParseFile() /path_to/llvm/lib/TableGen/TGParser.cpp:2686
    #8 0x688049 in llvm::TableGenMain(char*, bool (*)(llvm::raw_ostream&, llvm::RecordKeeper&)) /path_to/llvm/lib/TableGen/Main.cpp:96:14
    #9 0x61b5d5 in main /path_to/llvm/tools/clang/utils/TableGen/TableGen.cpp:287:10
    #10 0x7f03af5691c0 in __libc_start_main /build/glibc-CxtIbX/glibc-2.26/csu/../csu/libc-start.c:308
    #11 0x424d99 in _start (/path_to/llvm-build/bin/clang-tblgen+0x424d99)

SUMMARY: MemorySanitizer: use-of-uninitialized-value /usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/stl_tree.h:1887:7 in _M_lower_bound
Exiting
tools/clang/include/clang/StaticAnalyzer/Checkers/CMakeFiles/ClangSACheckers.dir/build.make:94: recipe for target 'tools/clang/include/clang/StaticAnalyzer/Checkers/Checkers.inc.tmp' failed
make[3]: *** [tools/clang/include/clang/StaticAnalyzer/Checkers/Checkers.inc.tmp] Error 77
CMakeFiles/Makefile2:18275: recipe for target 'tools/clang/include/clang/StaticAnalyzer/Checkers/CMakeFiles/ClangSACheckers.dir/all' failed
make[2]: *** [tools/clang/include/clang/StaticAnalyzer/Checkers/CMakeFiles/ClangSACheckers.dir/all] Error 2
make[2]: *** Waiting for unfinished jobs....

有什么关于如何编译以上代码的建议吗?

当然,clang++ m.cpp 可以,但在这种情况下,可执行文件链接到 libstdc++

找到解决方案here

  1. 使用未检测的 clang-fsanitize=memory

  2. 进行编译
  3. link 与上面的 MSAN_CFLAGS (可以省略包含路径),添加 -Wl,-rpath -Wl,/path_to/llvm-build-msan/lib/