I have ld.bfd 2.34.50.20200506, ld.gold 2.34.50.20200506, gcc/g++ 9.3.1 20200506, ld.lld 10.0.0, clang(++) 10.0.0, z.cpp: #include <stdio.h> #include <stdbool.h> #include <string> struct x { std::string x; }; struct z: virtual x { z() { bool b = 99; printf("a %i\n", b); } }; extern "C" { void y(); } void y() { const x x1 = z(); } and a.c: void y(); int main() { y(); } With --- CLANG --- > clang++ -shared -fsanitize=address,undefined z.cpp -fpic -o libz.so > nm -D libz.so|grep san < U __asan_init < U __asan_option_detect_stack_use_after_return < U __asan_register_globals < U __asan_report_load8 < U __asan_report_store8 < U __asan_stack_malloc_2 < U __asan_unregister_globals < U __asan_version_mismatch_check_v8 < U __ubsan_handle_dynamic_type_cache_miss < U __ubsan_handle_load_invalid_value < U __ubsan_handle_type_mismatch_v1 < U __ubsan_vptr_type_cache > clang -fsanitize=address,undefined -o b b.c -L. -lz -fuse-ld=bfd < /usr/local/bin/ld.bfd: ./libz.so: undefined reference to `__ubsan_vptr_type_cache' < /usr/local/bin/ld.bfd: ./libz.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) But if I remove the class conversions from z.cpp, then libz.so does not contains __ubsan_vptr_type_cache as Undefined symbol, while it contains __ubsan_handle_load_invalid_value, and then the linking clang+ld.bfd does work > clang -fsanitize=address,undefined -o b b.c -L. -lz -fuse-ld=bfd -lubsan < (No error, no warning) > LD_LIBRARY_PATH=. ./b < a 1 > clang -fsanitize=address,undefined -o b b.c -L. -lz -fuse-ld=gold < /usr/local/bin/ld.gold: warning: Cannot export local symbol '__asan_extra_spill_area' > LD_LIBRARY_PATH=. ./b < ./b: symbol lookup error: ./libz.so: undefined symbol: __ubsan_vptr_type_cache > clang -fsanitize=address,undefined -o b b.c -L. -lz -fuse-ld=gold -lubsan < /usr/local/bin/ld.gold: warning: Cannot export local symbol '__asan_extra_spill_area' > LD_LIBRARY_PATH=. ./b < a 1 > clang -fsanitize=address,undefined -o b b.c -L. -lz -fuse-ld=lld < (No error, no warning) > LD_LIBRARY_PATH=. ./b < ./b: symbol lookup error: ./libz.so: undefined symbol: __ubsan_vptr_type_cache > clang -fsanitize=address,undefined -o b b.c -L. -lz -fuse-ld=lld -lubsan < (No error, no warning) > LD_LIBRARY_PATH=. ./b < a 1 --- GCC --- > g++ -shared -fsanitize=address,undefined z.cpp -fpic -o libz.so > nm -D libz.so|grep san < U __asan_handle_no_return < U __asan_init < U __asan_option_detect_stack_use_after_return < U __asan_register_globals < U __asan_report_load8 < U __asan_report_store8 < U __asan_stack_malloc_2 < U __asan_unregister_globals < U __asan_version_mismatch_check_v8 < U __ubsan_handle_dynamic_type_cache_miss < U __ubsan_handle_pointer_overflow < U __ubsan_handle_type_mismatch_v1 < U __ubsan_vptr_type_cache > gcc -fsanitize=address,undefined -o b b.c -L. -lz -fuse-ld=bfd < (No error, no warning) > LD_LIBRARY_PATH=. ./b < a 1 > gcc -fsanitize=address,undefined -o b b.c -L. -lz -fuse-ld=gold < (No error, no warning) > LD_LIBRARY_PATH=. ./b < a 1 > gcc -fsanitize=address,undefined -o b b.c -L. -lz -fuse-ld=lld < (No error, no warning) > LD_LIBRARY_PATH=. ./b < a 1 • Why does clang+ld.bfd produce an error when using ubsan with class conversions? • Why do I have to add in clang+ld.bfd -lubsan to get rid of the warning? • Why does clang+ld.bfd does not produce an error when ubsan does no class conversions? • Why does clang+ld.gold produce a warning? Note that I have LLVMGold.so in /usr/local/lib, but not in /usr/local/lib/bfd-plugins. It is therefore not used by the linker (and this LLVMGold.so is for LLVM 8, as I forgot te complice LLVM 10 with the linker plugin).
Looks like you are mixing incompatible versions of libubsan.
Indeed, libubsan is from gcc. Does clang have its own libubsan and do make install of gcc and make install of clang both write libubsan under /usr/local/lib64?
libubsan comes from gcc: after compiling and installig clang/llvm, no libubsan is installed. So it is not possible to link with the wrong libubsan, when using clang, as no such linking is supposed to be done. I have installed the LLVMgold.so plugin for clang 10 under ${libdir}/bfd-plugins and I created one more file, e.cpp: #include <stdio.h> #include <stdbool.h> #include <string> struct x { std::string x; }; struct z : virtual x { z() { bool b = 99; printf("a %i\n", b); } }; extern "C" { void y(); } void y() { const z x1 = z(); } It differs from z.cpp only in: e.cpp: const z x1 = z(); z.cpp: const x x1 = z(); The implication of this difference is, that after compiling e.cpp and z.cpp into a DSO with clang++ -fsanitize=address,undefined -shared -fpic -o libz.so z.cpp clang++ -fsanitize=address,undefined -shared -fpic -o libe.so e.cpp and then comparing the output of "nm -CDP libz.so" with "nm -CDP libe.so", only in libz.so: __asan_report_load8 U __asan_stack_malloc_2 U __ubsan_handle_dynamic_type_cache_miss U __ubsan_vptr_type_cache U Only in libe.so __asan_stack_malloc_1 U and other differences, not related to sanitizers. Then I call: #!/usr/local/bin/bash for i in e z; do for linker in bfd lld gold; do for sanitizer in address undefined "address,undefined"; do echo "input $i clang linker $linker sanitizer $sanitizer" rm lib$i.so b -f clang++ -fsanitize=$sanitizer -fuse-ld=$linker -shared -fpic -o lib$i.so $i.cpp \ && clang -fsanitize=$sanitizer -fuse-ld=$linker -L. -l$i b.c -o b && LD_LIBRARY_PATH=. ./b echo "input $i gcc linker $linker sanitizer $sanitizer" rm lib$i.so b -f g++ -fsanitize=$sanitizer -fuse-ld=$linker -shared -fpic -o lib$i.so $i.cpp \ && gcc -fsanitize=$sanitizer -fuse-ld=$linker -L. -l$i b.c -o b && LD_LIBRARY_PATH=. ./b done done done The gcc and llvm linker plugins under libdir/bfd-plugins play no role for the output, which is: input e clang linker bfd sanitizer address a 1 input e gcc linker bfd sanitizer address a 1 input e clang linker bfd sanitizer undefined a 1 input e gcc linker bfd sanitizer undefined a 1 input e clang linker bfd sanitizer address,undefined a 1 input e gcc linker bfd sanitizer address,undefined a 1 input e clang linker lld sanitizer address a 1 input e gcc linker lld sanitizer address a 1 input e clang linker lld sanitizer undefined a 1 input e gcc linker lld sanitizer undefined a 1 input e clang linker lld sanitizer address,undefined a 1 input e gcc linker lld sanitizer address,undefined a 1 input e clang linker gold sanitizer address /usr/local/bin/ld.gold: warning: Cannot export local symbol '__asan_extra_spill_area' a 1 input e gcc linker gold sanitizer address a 1 input e clang linker gold sanitizer undefined a 1 input e gcc linker gold sanitizer undefined a 1 input e clang linker gold sanitizer address,undefined /usr/local/bin/ld.gold: warning: Cannot export local symbol '__asan_extra_spill_area' a 1 input e gcc linker gold sanitizer address,undefined a 1 input z clang linker bfd sanitizer address a 1 input z gcc linker bfd sanitizer address a 1 input z clang linker bfd sanitizer undefined /usr/local/bin/ld.bfd: ./libz.so: undefined reference to `__ubsan_vptr_type_cache' /usr/local/bin/ld.bfd: ./libz.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) input z gcc linker bfd sanitizer undefined a 1 input z clang linker bfd sanitizer address,undefined /usr/local/bin/ld.bfd: ./libz.so: undefined reference to `__ubsan_vptr_type_cache' /usr/local/bin/ld.bfd: ./libz.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) input z gcc linker bfd sanitizer address,undefined a 1 input z clang linker lld sanitizer address a 1 input z gcc linker lld sanitizer address a 1 input z clang linker lld sanitizer undefined ./b: symbol lookup error: ./libz.so: undefined symbol: __ubsan_vptr_type_cache input z gcc linker lld sanitizer undefined a 1 input z clang linker lld sanitizer address,undefined ./b: symbol lookup error: ./libz.so: undefined symbol: __ubsan_vptr_type_cache input z gcc linker lld sanitizer address,undefined a 1 input z clang linker gold sanitizer address /usr/local/bin/ld.gold: warning: Cannot export local symbol '__asan_extra_spill_area' a 1 input z gcc linker gold sanitizer address a 1 input z clang linker gold sanitizer undefined ./b: symbol lookup error: ./libz.so: undefined symbol: __ubsan_vptr_type_cache input z gcc linker gold sanitizer undefined a 1 input z clang linker gold sanitizer address,undefined /usr/local/bin/ld.gold: warning: Cannot export local symbol '__asan_extra_spill_area' ./b: symbol lookup error: ./libz.so: undefined symbol: __ubsan_vptr_type_cache input z gcc linker gold sanitizer address,undefined a 1 Thus, without the type conversions 'const x x1 = z();' the only problem is the GOLD report “/usr/local/bin/ld.gold: warning: Cannot export local symbol '__asan_extra_spill_area'". What does this mean? GCC is always clear. With the type conversion “const x x1 = z();" and clang and undefined (with or without address): With gold is reported “./b: symbol lookup error: ./libz.so: undefined symbol: __ubsan_vptr_type_cache” at execution time. With lld is reported “./b: symbol lookup error: ./libz.so: undefined symbol: __ubsan_vptr_type_cache” at execution time. With bfd is reported “ /usr/local/bin/ld.bfd: ./libz.so: undefined reference to `__ubsan_vptr_type_cache' /usr/local/bin/ld.bfd: ./libz.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)” at link time. To be honest, I think this is a problem with clang, as with the same parameters gcc works, and gold and lld misbehave in supressing errors, but I am not 100% sure, as I do not understand ELF. So where is the problem exactly?
I created one more file, b.cpp: extern "C" { void y(); } int main() { y(); } It differs from b.c only in the file extension and y() is under “extern "C"”. Doing the iterations with z.cpp and e.cpp, but replacing the executable source from b.c to b.cpp makes all ubsan warning disappear, except: input z clang linker gold sanitizer address /usr/local/bin/ld.gold: warning: Cannot export local symbol '__asan_extra_spill_area' To sum up, when a DSO is written in C++ and does class conversions, then the DSO has at the end undefined symbols “__ubsan_vptr_type_cache” and “`__ubsan_handle_dynamic_type_cache_miss”. These symbols are resolved by clang++, when the DSO is linked towards a C++ code, but not resolved by clang (withouth ++) when the DSO is linked towards C code. Moreover, ld.bfd report problem a problem at link time, while with gold and lld the report is at runtime. With the address sanitizer and clang, gold reports one additional warning, which cause I cannot figure out. So why does the linker resolve “__ubsan_vptr_type_cache” and “`__ubsan_handle_dynamic_type_cache_miss” when it is called from clang++, but not when called from clang? It is valid to link a DSO with extern "C" exported functions with a .c code.
I asked at https://sourceware.org/bugzilla/show_bug.cgi?id=25975 why gold prints “/usr/local/bin/ld.gold: warning: Cannot export local symbol '__asan_extra_spill_ area'” when used by clangs’ address sanitizer.
Closing, as I think this is a problem of clang: https://bugs.llvm.org/show_bug.cgi?id=45948 In particular, while $ clang -fsanitize=undefined -L. -lz a.c does not work, calling $ clang -fsanitize=undefined -c -o a.o a.c $ clang++ -fsanitize=undefined -L. -lz a.o works!