Quantcast
Viewing all articles
Browse latest Browse all 49

libc++/libc++abi on Linux

LibreOffice bug report “Build failure with clang++/libc++ on Linux x86_64” and reports about a similar failure when trying to build on NetBSD made me look at building LibreOffice on Linux with Clang against libc++/libc++abi (instead of the usual libstdc++) myself.

The libc++ web site warns: “Unfortunately you can’t simply run clang with ‘-stdlib=libc++’ at this point [when you have built Clang to be able to use libc++ in combination with libc++abi], as clang is set up to link for libc++ linked to libsupc++.” But that appears to no longer be true (at least on current LLVM trunk). All it takes is to include the libcxx and libcxxabi repositories in the projects sub-directory of the LLVM/Clang source tree and build it. The resulting libc++.so includes the necessary -lc++abi, so building LibreOffice with CXX=clang++ -stdlib=libc++ just works. (You need to make sure that the libc++.so.1 gets found at runtime, of course, e.g., by setting LD_LIBRARY_PATH.)

One remaining problem is that libc++abi and libstdc++ (resp. its ABI-related libsupc++ part) differ in how they determine type equivalence. On the one hand, libc++abi sticks to the original C++ ABI semantics: “It is intended that two type_info pointers point to equivalent type descriptions if and only if the pointers are equal.” (That is, type equivalence is determined by comparing _ZTI* type_info pointers for equality.) On the other hand, libstdc++ relaxed this quite a while ago to comparing type_infos’ name fields (_ZTS*) for string equality (via strcmp).

While both approaches have pros and cons, they do lead to different behaviour. One example is when a dynamic library is dlopen’ed RTLD_LOCAL. If code in that library (or any library that gets loaded dependent of it) throws an exception of type T, and code beyond that RTLD_LOCAL “wall” shall catch it, then that will work with the libstdc++ approach but fail with the libc++abi approach (even if all the relevant _ZTI*, _ZTS* symbols are weakly exported).

That is the reason why e.g. the UNO runtime makes sure to dlopen all relevant libraries as RTLD_GLOBAL, but LibreOfficeKit/LibreOfficeKitInit.h somewhat ignorantly tries to get away with dlopen’ing the sofficeapp library as RTLD_LOCAL. Now LibreOffice’s cppunittester executable (used to run CppUnit tests during the LibreOffice build) links against the sal library. So by the time CppunitTest_libreofficekit_tiledrendering dlopen’s the sofficeapp library as RTLD_LOCAL, the sal library has already been loaded into the process (implicitly as RTLD_GLOBAL), so any UNO components that happen to get instantiated in that process (via the dlopen in sal’s osl_loadModule) will be outside that “sofficeapp RTLD_LOCAL walled garden,” so that when code in ucb/source/ucp/file/bc.cxx throws a css::ucb::CommandFailedException, code in ucbhelper/source/client/content.cxx (inside the walled garden) won’t catch it (but would instead proceed to std::unexpected, std::terminate, std::abort).

That problematic dlopen with RTLD_LOCAL had already been addressed for UBSan builds (where runtime type identification code in at least Clang’s UBSan implementation always operates under the original C++ ABI semantics, regardless of compiler ABI library used), “Ensure RTTI symbol visibility for Linux Clang -fsanitize=function,vptr.” The only problem this time is to find a suitable #if condition to distinguish usage of libc++abi from usage of other compiler ABI libraries, “[cfe-dev] Feature-test macro whether compiling against libc++abi?”


Image may be NSFW.
Clik here to view.
Image may be NSFW.
Clik here to view.

Viewing all articles
Browse latest Browse all 49

Trending Articles