This is an archive of the discontinued LLVM Phabricator instance.

Always add -lc++abi when using vptr sanitizer on Darwin.
Needs ReviewPublic

Authored by samsonov on Jan 13 2015, 4:09 PM.

Details

Reviewers
kubamracek
Summary

-fsanitize=vptr implementation depends on RTTI descriptors for
cxxabiv1::class_type_info and friends.

Diff Detail

Event Timeline

samsonov updated this revision to Diff 18121.Jan 13 2015, 4:09 PM
samsonov retitled this revision from to Always add -lc++abi when using vptr sanitizer on Darwin..
samsonov updated this object.
samsonov edited the test plan for this revision. (Show Details)
samsonov added a reviewer: kubamracek.
samsonov added subscribers: kledzik, glider, Unknown Object (MLST).
kledzik added inline comments.Jan 13 2015, 5:22 PM
lib/Driver/ToolChains.cpp
385

Nothing should be linking directly with libc++abi.dylib. C++ code should link with libc++.dylib or libstdc++.dylib. I think there is some other setting in the clang driver that controls which to link with. But just linking with -lc++ will be right most of the time.

samsonov added inline comments.Jan 13 2015, 5:54 PM
lib/Driver/ToolChains.cpp
385

What if chooses to provide -lstdc++? In that case we still need to get RTTI for __cxxabiv1::__class_type_info from somewhere...
(see http://llvm.org/bugs/show_bug.cgi?id=21424).

385

What if *user* chooses

It will just work. libstdc++.dylib re-exports symbols from libc++abi.dylib:

[/tmp]> dyldinfo -export /usr/lib/libstdc++.dylib | grep class_type_info
[re-export]
ZTVN10cxxabiv117class_type_infoE (from libc++abi)
[re-export] ZTSN10cxxabiv117class_type_infoE (from libc++abi)
[re-export]
ZTVN10cxxabiv117class_type_infoE (from libc++abi)
[re-export] ZTSN10cxxabiv117__class_type_infoE (from libc++abi)
[/tmp]>

It will just work. libstdc++.dylib re-exports symbols from libc++abi.dylib:

[/tmp]> dyldinfo -export /usr/lib/libstdc++.dylib | grep class_type_info
[re-export]
ZTVN10cxxabiv117class_type_infoE (from libc++abi)
[re-export] ZTSN10cxxabiv117class_type_infoE (from libc++abi)
[re-export]
ZTVN10cxxabiv117class_type_infoE (from libc++abi)
[re-export] ZTSN10cxxabiv117__class_type_infoE (from libc++abi)
[/tmp]>

Well, users in that bug tell that they saw errors about unresolved symbols:

Undefined symbols for architecture x86_64:
  "__ZTIN10__cxxabiv117__class_type_infoE", referenced from:
      __ZN7__ubsan16checkDynamicTypeEPvS0_m in

but they went away after adding -lc++abi. Sorry, I don't have the Mac box at hand to verify it...

but they went away after adding -lc++abi.

and they would have gone away if they had added -lc++ or -lstdc++

Clang driver adds -lstdc++ to linker invocation automatically if user
provides -fsanitize=address or -fsanitize=undefined, yet we see linker
errors.

Alexander or Kuba, could you please check if the problem reproduces for you?

kubamracek edited edge metadata.Jan 17 2015, 9:25 PM

I can reproduce on the testcase from https://code.google.com/p/address-sanitizer/issues/detail?id=367:

$ ./bin/clang++ a.cpp
$ ./bin/clang++ a.cpp -fsanitize=undefined
Undefined symbols for architecture x86_64:
  "typeinfo for __cxxabiv1::__class_type_info", referenced from:
      __ubsan::checkDynamicType(void*, void*, unsigned long) in libclang_rt.ubsan_osx.a(ubsan_type_hash.cc.o)
      isDerivedFromAtOffset(__cxxabiv1::__class_type_info const*, __cxxabiv1::__class_type_info const*, long) in libclang_rt.ubsan_osx.a(ubsan_type_hash.cc.o)
      findBaseAtOffset(__cxxabiv1::__class_type_info const*, long) in libclang_rt.ubsan_osx.a(ubsan_type_hash.cc.o)
  "typeinfo for __cxxabiv1::__si_class_type_info", referenced from:
      isDerivedFromAtOffset(__cxxabiv1::__class_type_info const*, __cxxabiv1::__class_type_info const*, long) in libclang_rt.ubsan_osx.a(ubsan_type_hash.cc.o)
      findBaseAtOffset(__cxxabiv1::__class_type_info const*, long) in libclang_rt.ubsan_osx.a(ubsan_type_hash.cc.o)
  "typeinfo for __cxxabiv1::__vmi_class_type_info", referenced from:
      isDerivedFromAtOffset(__cxxabiv1::__class_type_info const*, __cxxabiv1::__class_type_info const*, long) in libclang_rt.ubsan_osx.a(ubsan_type_hash.cc.o)
      findBaseAtOffset(__cxxabiv1::__class_type_info const*, long) in libclang_rt.ubsan_osx.a(ubsan_type_hash.cc.o)
ld: symbol(s) not found for architecture x86_64
clang-3.6: error: linker command failed with exit code 1 (use -v to see invocation)
$ ./bin/clang++ a.cpp -fsanitize=undefined -lc++abi
$

The mangled names of these are:

__ZTIN10__cxxabiv117__class_type_infoE
__ZTIN10__cxxabiv120__si_class_type_infoE
__ZTIN10__cxxabiv121__vmi_class_type_infoE

It looks like libc++ is actually re-exporting a lot of symbols from libc++abi, but it doesn't re-export all of them:

$ dyldinfo -export /usr/lib/libc++.dylib | grep cxxabiv117__class
[re-export] __ZTSN10__cxxabiv117__class_type_infoE (from libc++abi)
[re-export] __ZTVN10__cxxabiv117__class_type_infoE (from libc++abi)
[re-export] __ZTSN10__cxxabiv117__class_type_infoE (from libc++abi)
[re-export] __ZTVN10__cxxabiv117__class_type_infoE (from libc++abi)
$ dyldinfo -export /usr/lib/libc++.dylib | grep __ZTIN10__cxxabiv117__class_type_infoE
$ 

So it looks like a libc++ issue (assuming the missing symbols are meant to be re-exported), and they need to be added to libcxx/lib/libc++abi.exp.