@@ -600,6 +600,29 @@ class ReflectionContext
600600 return false ;
601601 auto StrTab = reinterpret_cast <const char *>(StrTabBuf);
602602 bool Error = false ;
603+
604+ // GNU ld and lld both merge sections regardless of the
605+ // `SHF_GNU_RETAIN` flag. gold, presently, does not. The Swift
606+ // compiler has a couple of switches that control whether or not
607+ // the reflection sections are stripped; when these are enabled,
608+ // it will _not_ set `SHF_GNU_RETAIN` on the reflection metadata
609+ // sections. However, `swiftrt.o` contains declarations of the
610+ // sections _with_ the `SHF_GNU_RETAIN` flag set, which makes
611+ // sense since at runtime we will only expect to be able to access
612+ // reflection metadata that we said we wanted to exist at runtime.
613+ //
614+ // The upshot is that when linking with gold, we can end up with
615+ // two sets of reflection metadata sections. In a normal build
616+ // where the compiler flags are the same for every linked object,
617+ // we'll have *either* all retained *or* all un-retained sections
618+ // (the retained sections will still exist because of `swiftrt.o`,
619+ // but will be empty). The only time we'd expect to have a mix is
620+ // where some code was compiled with a different setting of the
621+ // metadata stripping flags. If that happens, the code below will
622+ // simply add both sets of reflection sections, with the retained
623+ // ones added first.
624+ //
625+ // See also https://sourceware.org/bugzilla/show_bug.cgi?id=31415.
603626 auto findELFSectionByName =
604627 [&](llvm::StringRef Name, bool Retained) -> std::pair<RemoteRef<void >, uint64_t > {
605628 if (Error)
0 commit comments