10

I am working on a product that is composed of multiple C++ executables and libraries that have various dependencies on one another. I am building them all with GCC and -fsanitize-address. From what I understand, if I want to use address sanitizer with a library I have to build it as a shared object (which is the default option for GCC). Because of this, I thought the best option would be to build address sanitizer statically with -static-libasan for the executables and build it dinamically for the libraries. However, when I do that I get a link error when building one of the C++ executables:

==10823==Your application is linked against incompatible ASan runtimes

This makes me think that static and dynamic version of address sanitizer cannot be mixed with GCC, am I right? I was not able to find any information about this on the sanitizers GitHub page.

Perennialista
  • 1,083
  • 2
  • 12
  • 22
  • 1
    That's not specific to ASAN, you never do what you just described with any library. Either you only use the shared version (either for libraries and executable or just the later), or you only use the static version (only for the executable). – Marc Glisse Oct 30 '17 at 18:31

1 Answers1

24

TLDR:

  • If you use GCC/Clang and both main executable and shlibs are sanitized, you don't need to do anything special - just stick with default -fsanitize=address.
  • If you use GCC and only shlibs are sanitized, again keep using -fsanitize=address and additionally export LD_PRELOAD=$(gcc -print-file-name=libasan.so) when running your application.
  • If you use Clang and only shlibs are sanitized, compile/link with -fsanitize-address -shared-libasan and additionally export LD_PRELOAD=$(clang -print-file-name=libclang_rt.asan-x86_64.so) when running the app.

Now some explanations. Originally Asan existed only in Clang which by default used (and still uses) -static-libasan. When it was ported to GCC, GCC developers decided that shared runtime is preferred (e.g. because it allows one to sanitize just one shared library and keep main executable unsanitized e.g. sanitize Python module without recompiling python.exe, see wiki for other examples). Both approaches are binary incompatible so you can't link part of your applications with static runtime and part with dynamic runtime.

Roughly

  • GCCs -fsanitize=address is equivalent to Clangs -fsanitize=address -shared-libasan (and -shared-libasan is second-class citizen in Clang so not as well supported)
  • Clangs -fsanitize=address is equivalent to GCCs -fsanitize=address -static-libasan (and again, -static-libasan is second-class citizen in GCC so has some issues)

As a side note, for other GCC/Clang Asan differences see this helpful wiki.

yugr
  • 19,769
  • 3
  • 51
  • 96
  • Got it, I was trying to statically compile address sanitizer with GCC because of [this issue](https://github.com/google/sanitizers/issues/849#issuecomment-338332581). – Perennialista Oct 30 '17 at 20:41
  • 1
    LD_PRELOAD shouldn't be necessary, -fsanitize=address when creating the library adds libasan.so.* as NEEDED unless you specifically tell it not to. – Marc Glisse Oct 30 '17 at 23:48
  • 2
    @MarcGlisse Yes but it won't intercept standard symbols because it's not the first in library list. Also I vaguely remember that there were other important issues so currently Asan will [abort execution if `LD_PRELOAD` is missing](https://github.com/gcc-mirror/gcc/blob/36093749ff955d9e8cf208b04724c3a1a2ac9b04/libsanitizer/asan/asan_linux.cc#L137). – yugr Oct 31 '17 at 11:29
  • @yugr thanks, that's useful information. I thought being the first dependency of the first dependency would be enough (one indirection more), but apparently not. – Marc Glisse Oct 31 '17 at 13:07
  • 1
    @Perennialista Note that you _can_ use `-static-libasan` in GCC as long as your main executable is sanitized (just append it to `CFLAGS` for both executable and shlibs). But beware of [this issue](https://stackoverflow.com/questions/46682210/undefined-symbol-error-with-static-libasan/46684596). – yugr Oct 31 '17 at 17:15