Open llvmbot opened 4 years ago
I have just encountered this issue when linking a C++ library to a C program, both having ubsan enabled, linker error:
[24/25] Linking C executable examples/Debug/ReferenceApp
FAILED: examples/Debug/ReferenceApp
: && /usr/bin/clang -g -fsanitize=address,leak,undefined -Wall -Wextra -Wshadow -Wcast-align -Wunused -Wpedantic -Wconversion -Wsign-conversion -Wnull-dereference -Wdouble-promotion -Wformat=2 -Wimplicit-fallthrough -Werror examples/CMakeFiles/ReferenceApp.dir/Debug/main.c.o -o examples/Debug/ReferenceApp -Wl,-rpath,/tmp/9512b82f-d185-50ea-ee23-d010bc14782f/build/clang/example/Debug example/Debug/libexampled.so.0.1.0 --coverage && :
/usr/bin/ld: example/Debug/libexampled.so.0.1.0: undefined reference to `__ubsan_vptr_type_cache'
/usr/bin/ld: example/Debug/libexampled.so.0.1.0: undefined reference to `__ubsan_handle_dynamic_type_cache_miss'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Extended Description
I create a file d.cpp:
struct D { bool d; };
struct E : virtual D { int e; };
extern "C" { void f(); }
void f() { D g = E(); };
and compile it with clang 10.0 $ clang++ -fsanitize=undefined -shared -fpic -o libd.so d.cpp
Then I create a file h.c: void f(); int main() { f(); return 0; } and compile it with: $ clang -fsanitize=undefined -L. -ld h.c /usr/local/bin/ld: ./libd.so: undefined reference to
__ubsan_vptr_type_cache' /usr/local/bin/ld: ./libd.so: undefined reference to
__ubsan_handle_dynamic_type_cache_miss' clang-10: error: linker command failed with exit code 1 (use -v to see invocation)If I use instead $ clang -fsanitize=undefined -L. -ld h.c -lubsan then it magically works. But libubsan is from gcc, sometimes does not contain the symbols that clang emits and UBSAN is not supposed to work this way.
If I take instead j.cpp: extern "C" { void f(); }
int main() { f(); return 0; }
then $ clang++ -fsanitize=undefined -L. -ld j.cpp does work. If I put in h.c the f() declarition withing extern "C" {}, then $ clang++ -fsanitize=undefined -L. -ld h.c clang-10: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
works somehow.
If I use: $ clang -fsanitize=undefined -c -o h.o h.c $ clang++ -fsanitize=undefined h.o -L. -ld -o h then it also works, but build tools do not know that they cannot short-circuit to $ clang -fsanitize=undefined -o h -L. -ld h.c
https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#usage says for Clang 11 (I use 10): “Use clang++ to compile and link your program with -fsanitize=undefined flag. … You can use clang instead of clang++ if you’re compiling/linking C code.”
Now, I am compiling C code, but linking it with C++ code. There are real-world use cases: ICU and WebKIT are in C++, but can be used from C code. So to verify the whole linking C code using clang, with C++ libraries must also work.
See also https://sourceware.org/bugzilla/show_bug.cgi?id=25940 .
⇒ Enhance
clang -fsanitize=undefined -ld
to link with the d-library, even when that library is in C++ and was compiled withclang++ -fsanitize=undefined
.