[PATCH] D147832: [libcxx] Introduce clang::lto_visibility_public attribute

Leonard Chan via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 12 11:43:58 PDT 2023


leonardchan added a comment.

In D147832#4644272 <https://reviews.llvm.org/D147832#4644272>, @ldionne wrote:

> In D147832#4256529 <https://reviews.llvm.org/D147832#4256529>, @leonardchan wrote:
>
>>> You say you build with -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -fvisibility=hidden which AFAICT defeats the purpose of a shared library, since it wouldn't export a single symbol.
>>
>> My bad, I should've clarified on this. For fuchsia, we build everything with hidden visibility by default and individual binaries need to explicitly mark their symbols with default visibility if they want to be exported. This also means that when a fuchsia binary uses libc++, we need to make sure it doesn't accidentally export any libc++ symbols. Fuchsia binaries can consume libc++ as either a shared lib or a hermetic static lib, but we don't know at compile time how libc++ will eventually be consumed. If used as a shared lib, then symbols will be defined libc++.so. If linked in as a hermetic static lib, then we need to ensure those symbols have hidden visibility. To cover both cases and prevent us from having to compile twice, we just compile everything with `-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -fvisibility=hidden`.
>
> I still don't understand your setup. So you compile the program using LTO and passing `-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -fvisibility=hidden`, right? That way the program itself doesn't export any libc++ symbols and everything in the program has hidden visibility AND hidden LTO visibility. But then you compile `libc++.so` with `-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -fvisibility=hidden`, which causes everything in `libc++.so` to have hidden visibility. But since you compile `libc++.so` with LTO disabled, everything in `libc++.so` has default LTO visibility.

The program is compiled with LTO and `-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -fvisibility=hidden` but out libc++.so isn't compiled with `-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS`, `-fvisibility=hidden`, or LTO so all the symbols in our libc++.so have default visibility and default LTO visibility while an equivalent symbol in the program will have hidden elf and LTO visibility.

> So for example, let's say you have a `std::map<int, int>` instantiated in your program and let's say there's also one instantiated inside `libc++.so`. On the program side, `std::map<int, int>` has hidden visibility because you passed `-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -fvisibility=hidden`, and it has hidden LTO visibility for the same reason. On the `libc++.so` side, it has hidden visibility because you passed `-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -fvisibility=hidden` when building the `.so`, but it has default LTO visibility because you did not compile `libc++.so` with LTO enabled. That's an ODR violation. Is that correct?

A slight difference in the example is that the symbol has default ELF visibility in the libc++.so side, but yes I believe this is an ODR violation since the map has differing LTO visibilities across different linkage units which is what this patch attempts to fix. We need to make sure the symbols on the program side are hidden ELF visibility and the symbols in libc++ are default ELF visibility, but to ensure LTO visibility is respected, we need a way to plumb `[[clang::lto_visibility_public]]` to all relevant libc++ classes.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D147832/new/

https://reviews.llvm.org/D147832



More information about the llvm-commits mailing list