126 lines · plain
1==============2LTO Visibility3==============4 5*LTO visibility* is a property of an entity that specifies whether it can be6referenced from outside the current LTO unit. A *linkage unit* is a set of7translation units linked together into an executable or DSO, and a linkage8unit's *LTO unit* is the subset of the linkage unit that is linked together9using link-time optimization; in the case where LTO is not being used, the10linkage unit's LTO unit is empty. Each linkage unit has only a single LTO unit.11 12The LTO visibility of a class is used by the compiler to determine which13classes the whole-program devirtualization (``-fwhole-program-vtables``) and14control flow integrity (``-fsanitize=cfi-vcall`` and ``-fsanitize=cfi-mfcall``)15features apply to. These features use whole-program information, so they16require the entire class hierarchy to be visible in order to work correctly.17 18If any translation unit in the program uses either of the whole-program19devirtualization or control flow integrity features, it is effectively an ODR20violation to define a class with hidden LTO visibility in multiple linkage21units. A class with public LTO visibility may be defined in multiple linkage22units, but the tradeoff is that the whole-program devirtualization and23control flow integrity features can only be applied to classes with hidden LTO24visibility. A class's LTO visibility is treated as an ODR-relevant property25of its definition, so it must be consistent between translation units.26 27In translation units built with LTO, LTO visibility is based on the28class's symbol visibility as expressed at the source level (i.e. the29``__attribute__((visibility("...")))`` attribute, or the ``-fvisibility=``30flag) or, on the Windows platform, the dllimport and dllexport attributes. When31targeting non-Windows platforms, classes with a visibility other than hidden32visibility receive public LTO visibility. When targeting Windows, classes33with dllimport or dllexport attributes receive public LTO visibility. All34other classes receive hidden LTO visibility. Classes with internal linkage35(e.g. classes declared in unnamed namespaces) also receive hidden LTO36visibility.37 38During the LTO link, all classes with public LTO visibility but not marked with39``[[clang::lto_visibility_public]]`` (see below) will be refined to hidden LTO40visibility when the ``--lto-whole-program-visibility`` lld linker option is41applied (``-plugin-opt=whole-program-visibility`` for gold). This flag can be42used to defer specifying whether classes have hidden LTO visibility until link43time, to allow bitcode objects to be shared by different LTO links. Due to an44implementation limitation, symbols associated with classes with hidden LTO45visibility may still be exported from the binary when using this flag. It is46unsafe to refer to these symbols, and their visibility may be relaxed to hidden47in a future compiler release.48 49A class defined in a translation unit built without LTO receives public50LTO visibility regardless of its object file visibility, linkage or other51attributes.52 53This mechanism will produce the correct result in most cases, but there are54two cases where it may wrongly infer hidden LTO visibility.55 561. As a corollary of the above rules, if a linkage unit is produced from a57 combination of LTO object files and non-LTO object files, any hidden58 visibility class defined in both a translation unit built with LTO and59 a translation unit built without LTO must be defined with public LTO60 visibility in order to avoid an ODR violation.61 622. Some ABIs provide the ability to define an abstract base class without63 visibility attributes in multiple linkage units and have virtual calls64 to derived classes in other linkage units work correctly. One example of65 this is COM on Windows platforms. If the ABI allows this, any base class66 used in this way must be defined with public LTO visibility.67 68Classes that fall into either of these categories can be marked up with the69``[[clang::lto_visibility_public]]`` attribute. To specifically handle the70COM case, classes with the ``__declspec(uuid())`` attribute receive public71LTO visibility. On Windows platforms, clang-cl's ``/MT`` and ``/MTd``72flags statically link the program against a prebuilt standard library;73these flags imply public LTO visibility for every class declared in the74``std`` and ``stdext`` namespaces.75 76Example77=======78 79The following example shows how LTO visibility works in practice in several80cases involving two linkage units, ``main`` and ``dso.so``.81 82.. code-block:: none83 84 +-----------------------------------------------------------+ +----------------------------------------------------+85 | main (clang++ -fvisibility=hidden): | | dso.so (clang++ -fvisibility=hidden): |86 | | | |87 | +-----------------------------------------------------+ | | struct __attribute__((visibility("default"))) C { |88 | | LTO unit (clang++ -fvisibility=hidden -flto): | | | virtual void f(); |89 | | | | | } |90 | | struct A { ... }; | | | void C::f() {} |91 | | struct [[clang::lto_visibility_public]] B { ... }; | | | struct D { |92 | | struct __attribute__((visibility("default"))) C { | | | virtual void g() = 0; |93 | | virtual void f(); | | | }; |94 | | }; | | | struct E : D { |95 | | struct [[clang::lto_visibility_public]] D { | | | virtual void g() { ... } |96 | | virtual void g() = 0; | | | }; |97 | | }; | | | __attribute__((visibility("default"))) D *mkE() { |98 | | | | | return new E; |99 | +-----------------------------------------------------+ | | } |100 | | | |101 | struct B { ... }; | +----------------------------------------------------+102 | |103 +-----------------------------------------------------------+104 105We will now describe the LTO visibility of each of the classes defined in106these linkage units.107 108Class ``A`` is not defined outside of ``main``'s LTO unit, so it can have109hidden LTO visibility. This is inferred from the object file visibility110specified on the command line.111 112Class ``B`` is defined in ``main``, both inside and outside its LTO unit. The113definition outside the LTO unit has public LTO visibility, so the definition114inside the LTO unit must also have public LTO visibility in order to avoid115an ODR violation.116 117Class ``C`` is defined in both ``main`` and ``dso.so`` and therefore must118have public LTO visibility. This is correctly inferred from the ``visibility``119attribute.120 121Class ``D`` is an abstract base class with a derived class ``E`` defined122in ``dso.so``. This is an example of the COM scenario; the definition of123``D`` in ``main``'s LTO unit must have public LTO visibility in order to be124compatible with the definition of ``D`` in ``dso.so``, which is observable125by calling the function ``mkE``.126