mesonbuild / meson

The Meson Build System
http://mesonbuild.com
Apache License 2.0
5.49k stars 1.59k forks source link

Clang + asan + gnome.generate_gir() causes link errors due to missing libclang_rt.asan #13211

Open refi64 opened 3 months ago

refi64 commented 3 months ago

Describe the bug When running g-ir-scanner on a library built with b_sanitize=address, link errors occur, because Clang's implementation also seems to require libclang_rt.asan:

To Reproduce

project('xyz', 'c')

gnome = import('gnome')

xyz = shared_library(
  'xyz',
  'xyz.c',
)

gnome.generate_gir(
  xyz,
  sources : 'xyz.c',
  namespace : 'Xyz',
  nsversion : '0',
)

(xyz.c is entirely empty.)

This results in:

$ ninja -C _build
ninja: Entering directory `_build'
[1/2] Generating Xyz-0.gir with a custom command (wrapped by meson to set env)
FAILED: Xyz-0.gir
env PKG_CONFIG_PATH=/home/ryan/collabora/playground/meson-asan/_build/meson-uninstalled PKG_CONFIG=/usr/bin/pkg-config CC=clang /usr/bin/g-ir-scanner --quiet --no-libtool --namespace=Xyz --nsversion=0 --warn-all --output Xyz-0.gir -I/home
/ryan/collabora/playground/meson-asan/ -I/home/ryan/collabora/playground/meson-asan/_build/ --filelist=/home/ryan/collabora/playground/meson-asan/_build/libxyz.so.p/Xyz_0_gir_filelist --cflags-begin -I/usr/include/gobject-introspection-1.
0 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/sysprof-6 --cflags-end --add-include-path=/usr/share/gir-1.0 -lasan -L/home/ryan/collabora/playground/meson-asan/_build/ --library xyz --extra-library=girepository-1.0
 --extra-library=gobject-2.0 --extra-library=glib-2.0 --sources-top-dirs /home/ryan/collabora/playground/meson-asan/ --sources-top-dirs /home/ryan/collabora/playground/meson-asan/_build/
/usr/bin/ld: ./libxyz.so: undefined reference to `__sanitizer_internal_memmove'
/usr/bin/ld: ./libxyz.so: undefined reference to `__sanitizer_internal_memcpy'
/usr/bin/ld: ./libxyz.so: undefined reference to `__sanitizer_internal_memset'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
linking of temporary binary failed: Command '['clang', '-o', '/home/ryan/collabora/playground/meson-asan/_build/tmp-introspectc9vug4v3/Xyz-0', '/home/ryan/collabora/playground/meson-asan/_build/tmp-introspectc9vug4v3/Xyz-0.o', '-L.', '-Wl,-rpath,.', '-Wl,--no-as-needed', '-L/home/ryan/collabora/playground/meson-asan/_build/', '-Wl,-rpath,/home/ryan/collabora/playground/meson-asan/_build/', '-lasan', '-lxyz', '-lgirepository-1.0', '-lgobject-2.0', '-lglib-2.0', '-lgio-2.0', '-Wl,--export-dynamic', '-lgmodule-2.0', '-pthread', '-lgobject-2.0', '-lglib-2.0']' returned non-zero exit status 1.
ninja: build stopped: subcommand failed.

The issue can be demo'd with just the clang CLI directly:

$ clang -shared -fsanitize=address -o libxyz.so -xc - <<<''
# fails:
$ clang -o xyz -xc - -L. -lasan -lxyz <<<'int main() { return 0; }'
/usr/bin/ld: ./libxyz.so: undefined reference to `__sanitizer_internal_memmove'
/usr/bin/ld: ./libxyz.so: undefined reference to `__sanitizer_internal_memcpy'
/usr/bin/ld: ./libxyz.so: undefined reference to `__sanitizer_internal_memset'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

But the invocation you'd expect to work also does not:

$ clang -o xyz -xc - -L. -lasan -lclang_rt.asan -lxyz <<<'int main() { return 0; }'
$ ./xyz
./xyz: error while loading shared libraries: libclang_rt.asan.so: cannot open shared object file: No such file or directory

The only way I actually got it to work was this incantation based on the output of clang -fsanitize=address -v ...:

$ clang -o xyz -xc - -L. -Wl,--whole-archive -Wl,-Bstatic -lclang_rt.asan -Wl,-Bdynamic -Wl,--no-whole-archive -lxyz -lm <<<'int main() { return 0; }'

which removes -lasan completely (otherwise I get Your application is linked against incompatible ASan runtimes on startup) and adds on -lm (fixes some undefined references to signgam). I don't even know if these libraries are correct, though, because there are quite a few options:

$ l -1 /usr/lib/clang/17/lib/aarch64-redhat-linux-gnu/libclang_rt.asan*
/usr/lib/clang/17/lib/aarch64-redhat-linux-gnu/libclang_rt.asan.a
/usr/lib/clang/17/lib/aarch64-redhat-linux-gnu/libclang_rt.asan.a.syms
/usr/lib/clang/17/lib/aarch64-redhat-linux-gnu/libclang_rt.asan_cxx.a
/usr/lib/clang/17/lib/aarch64-redhat-linux-gnu/libclang_rt.asan_cxx.a.syms
/usr/lib/clang/17/lib/aarch64-redhat-linux-gnu/libclang_rt.asan-preinit.a
/usr/lib/clang/17/lib/aarch64-redhat-linux-gnu/libclang_rt.asan.so*
/usr/lib/clang/17/lib/aarch64-redhat-linux-gnu/libclang_rt.asan_static.a

Expected behavior This should successfully run g-ir-scanner.

system parameters

eli-schwartz commented 3 months ago

I think what you're overall trying to say is that clang is garbage and we should emit a fatal configure time error if you try to enable sanitizers with it? :D

eli-schwartz commented 3 months ago

/cc @thesamesam who might know something about the clang internals here. I have often wondered the same problem and certainly don't have understanding of the answer.

thesamesam commented 3 months ago

I'm on diff. HW than usual which makes life a bit harder but I'll at least take a look at what's happening, even if I don't end up fixing it.