If executable is linked with -static-libasan, it won't export libasan public API (__asan_reportXYZ, etc.), causing dlopens of sanitized shlibs to fail. Same applies to other sanitizers (-static-libubsan, etc.).
I think we can only recommend not to do that, or suggest users to consider -Wl,-E. The linker automatically makes symbols mentioned in dependent libraries exported from binaries, but e.g. implying -Wl,-E from -static-libasan is IMNSHO undesirable, it doesn't make just the selected few symbols dynamic, but all, and that really should be users decision whether it is desirable or not.
(In reply to Jakub Jelinek from comment #1) > I think we can only recommend not to do that For legacy codebase (e.g. when sanitizing full distributions) you often don't have a choice. > implying -Wl,-E from -static-libasan is IMNSHO undesirable, > it doesn't make just the selected few symbols dynamic, but all, Right, -Wl,-E would be an overkill. AFAIK Clang automatically appends --dynamic-list=something.syms when it compiles sanitized executable. Perhaps we could do this as well?
But why do you want to use -static-libasan ? Just link it dynamically... --dynamic-list is hard to maintain, aren't there hundreds of symbols that are exported from libasan?
(In reply to Jakub Jelinek from comment #3) > But why do you want to use -static-libasan ? Just link it dynamically... For one thing it can speed up code by avoiding PLT calls. > --dynamic-list is hard to maintain, aren't there hundreds of symbols that > are exported from libasan? Indeed there are, upstream has a special script to autogenerate file with symbols.
Few workarounds for this are listed in https://stackoverflow.com/questions/46682210/undefined-symbol-error-with-static-libasan/46684596#46684596
I've the same problem when try to link at runtime shared library compiled with static asan. Here is minimal example: echo ' #include <stdlib.h> #include <stdio.h> void f(){ int* x = new int; printf("kek\n"); }' > lib.cpp echo ' #include <dlfcn.h> #include <stdio.h> int main() { printf("lol\n"); void* handler = dlopen("./libkek.so", RTLD_NOW); if (!handler) return 1; void (* func)() = reinterpret_cast<void(*)()>(dlsym(handler, "_Z1fv")); printf("kek\n"); func(); printf("cheburek\n"); }' > main.cpp g++ -fsanitize=address -static-libasan -static-libstdc++ -static-libgcc -fPIC -shared lib.cpp -o libkek.so g++ -fsanitize=address -static-libasan -static-libstdc++ -static-libgcc -ldl main.cpp LD_DEBUG=libs ./a.out; echo $? Part of the output: ... 347802: initialize program: ./a.out 347802: 347802: 347802: transferring control: ./a.out 347802: lol 347802: ./libkek.so: error: symbol lookup error: undefined symbol: __asan_unregister_globals (fatal) 347802: 347802: calling fini: ./a.out [0] 347802: 347802: 347802: calling fini: /lib/x86_64-linux-gnu/libm.so.6 [0] 347802: With clang everything is ok.... GCC version 12.1 System: Ubuntu 21.10
> But why do you want to use -static-libasan ? Just link it dynamically... Another reason is shared linking clobbers executable's RUNPATH: https://github.com/google/sanitizers/issues/1219
https://www.youtube.com/watch?v=Ua3TiOSwVTI