Skip to content

Commit c9dcee2

Browse files
committed
[RemoteInspection] Update ReflectionContext to cope with multiple sections.
When linking with `gold`, we can end up with two separate sections for each of the reflection sections; this happens because `swiftrt.o` declares them with `SHF_GNU_RETAIN` set (to stop them from vanishing when section GC is enabled), but if the compiler is set to allow the reflection information to be stripped then *it* will generate them *without* `SHF_GNU_RETAIN`. The other Linux linkers will coalesce the two sections and leave the `SHF_GNU_RETAIN` flag set, but `gold` does not, and adds both of them separately to the output. The upshot is that we want `ReflectionContext` to look for both the retained and non-retained sections and read the data from both of them. rdar://123504095
1 parent b755724 commit c9dcee2

File tree

1 file changed

+77
-27
lines changed

1 file changed

+77
-27
lines changed

include/swift/RemoteInspection/ReflectionContext.h

Lines changed: 77 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ class ReflectionContext
601601
auto StrTab = reinterpret_cast<const char *>(StrTabBuf);
602602
bool Error = false;
603603
auto findELFSectionByName =
604-
[&](llvm::StringRef Name) -> std::pair<RemoteRef<void>, uint64_t> {
604+
[&](llvm::StringRef Name, bool Retained) -> std::pair<RemoteRef<void>, uint64_t> {
605605
if (Error)
606606
return {nullptr, 0};
607607
// Now for all the sections, find their name.
@@ -616,6 +616,8 @@ class ReflectionContext
616616
std::string SecName(Start, StringSize);
617617
if (SecName != Name)
618618
continue;
619+
if (Retained != !!(Hdr->sh_flags & llvm::ELF::SHF_GNU_RETAIN))
620+
continue;
619621
RemoteAddress SecStart =
620622
RemoteAddress(ImageStart.getAddressData() + Hdr->sh_addr);
621623
auto SecSize = Hdr->sh_size;
@@ -649,48 +651,96 @@ class ReflectionContext
649651

650652
SwiftObjectFileFormatELF ObjectFileFormat;
651653
auto FieldMdSec = findELFSectionByName(
652-
ObjectFileFormat.getSectionName(ReflectionSectionKind::fieldmd));
654+
ObjectFileFormat.getSectionName(ReflectionSectionKind::fieldmd), true);
653655
auto AssocTySec = findELFSectionByName(
654-
ObjectFileFormat.getSectionName(ReflectionSectionKind::assocty));
656+
ObjectFileFormat.getSectionName(ReflectionSectionKind::assocty), true);
655657
auto BuiltinTySec = findELFSectionByName(
656-
ObjectFileFormat.getSectionName(ReflectionSectionKind::builtin));
658+
ObjectFileFormat.getSectionName(ReflectionSectionKind::builtin), true);
657659
auto CaptureSec = findELFSectionByName(
658-
ObjectFileFormat.getSectionName(ReflectionSectionKind::capture));
660+
ObjectFileFormat.getSectionName(ReflectionSectionKind::capture), true);
659661
auto TypeRefMdSec = findELFSectionByName(
660-
ObjectFileFormat.getSectionName(ReflectionSectionKind::typeref));
662+
ObjectFileFormat.getSectionName(ReflectionSectionKind::typeref), true);
661663
auto ReflStrMdSec = findELFSectionByName(
662-
ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr));
664+
ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr), true);
663665
auto ConformMdSec = findELFSectionByName(
664-
ObjectFileFormat.getSectionName(ReflectionSectionKind::conform));
666+
ObjectFileFormat.getSectionName(ReflectionSectionKind::conform), true);
665667
auto MPEnumMdSec = findELFSectionByName(
666-
ObjectFileFormat.getSectionName(ReflectionSectionKind::mpenum));
668+
ObjectFileFormat.getSectionName(ReflectionSectionKind::mpenum), true);
667669

668670
if (Error)
669671
return false;
670672

673+
std::optional<uint32_t> result = false;
674+
671675
// We succeed if at least one of the sections is present in the
672676
// ELF executable.
673-
if (FieldMdSec.first == nullptr &&
674-
AssocTySec.first == nullptr &&
675-
BuiltinTySec.first == nullptr &&
676-
CaptureSec.first == nullptr &&
677-
TypeRefMdSec.first == nullptr &&
678-
ReflStrMdSec.first == nullptr &&
679-
ConformMdSec.first == nullptr &&
680-
MPEnumMdSec.first == nullptr)
677+
if (FieldMdSec.first != nullptr ||
678+
AssocTySec.first != nullptr ||
679+
BuiltinTySec.first != nullptr ||
680+
CaptureSec.first != nullptr ||
681+
TypeRefMdSec.first != nullptr ||
682+
ReflStrMdSec.first != nullptr ||
683+
ConformMdSec.first != nullptr ||
684+
MPEnumMdSec.first != nullptr) {
685+
ReflectionInfo info = {{FieldMdSec.first, FieldMdSec.second},
686+
{AssocTySec.first, AssocTySec.second},
687+
{BuiltinTySec.first, BuiltinTySec.second},
688+
{CaptureSec.first, CaptureSec.second},
689+
{TypeRefMdSec.first, TypeRefMdSec.second},
690+
{ReflStrMdSec.first, ReflStrMdSec.second},
691+
{ConformMdSec.first, ConformMdSec.second},
692+
{MPEnumMdSec.first, MPEnumMdSec.second},
693+
PotentialModuleNames};
694+
result = this->addReflectionInfo(info);
695+
}
696+
697+
// Also check for the non-retained versions of the sections; we'll
698+
// only return a single reflection info ID if both are found (and it'll
699+
// be the one for the retained sections if we have them), but we'll
700+
// still add all the reflection information.
701+
FieldMdSec = findELFSectionByName(
702+
ObjectFileFormat.getSectionName(ReflectionSectionKind::fieldmd), false);
703+
AssocTySec = findELFSectionByName(
704+
ObjectFileFormat.getSectionName(ReflectionSectionKind::assocty), false);
705+
BuiltinTySec = findELFSectionByName(
706+
ObjectFileFormat.getSectionName(ReflectionSectionKind::builtin), false);
707+
CaptureSec = findELFSectionByName(
708+
ObjectFileFormat.getSectionName(ReflectionSectionKind::capture), false);
709+
TypeRefMdSec = findELFSectionByName(
710+
ObjectFileFormat.getSectionName(ReflectionSectionKind::typeref), false);
711+
ReflStrMdSec = findELFSectionByName(
712+
ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr), false);
713+
ConformMdSec = findELFSectionByName(
714+
ObjectFileFormat.getSectionName(ReflectionSectionKind::conform), false);
715+
MPEnumMdSec = findELFSectionByName(
716+
ObjectFileFormat.getSectionName(ReflectionSectionKind::mpenum), false);
717+
718+
if (Error)
681719
return false;
682720

683-
ReflectionInfo info = {{FieldMdSec.first, FieldMdSec.second},
684-
{AssocTySec.first, AssocTySec.second},
685-
{BuiltinTySec.first, BuiltinTySec.second},
686-
{CaptureSec.first, CaptureSec.second},
687-
{TypeRefMdSec.first, TypeRefMdSec.second},
688-
{ReflStrMdSec.first, ReflStrMdSec.second},
689-
{ConformMdSec.first, ConformMdSec.second},
690-
{MPEnumMdSec.first, MPEnumMdSec.second},
691-
PotentialModuleNames};
721+
if (FieldMdSec.first != nullptr ||
722+
AssocTySec.first != nullptr ||
723+
BuiltinTySec.first != nullptr ||
724+
CaptureSec.first != nullptr ||
725+
TypeRefMdSec.first != nullptr ||
726+
ReflStrMdSec.first != nullptr ||
727+
ConformMdSec.first != nullptr ||
728+
MPEnumMdSec.first != nullptr) {
729+
ReflectionInfo info = {{FieldMdSec.first, FieldMdSec.second},
730+
{AssocTySec.first, AssocTySec.second},
731+
{BuiltinTySec.first, BuiltinTySec.second},
732+
{CaptureSec.first, CaptureSec.second},
733+
{TypeRefMdSec.first, TypeRefMdSec.second},
734+
{ReflStrMdSec.first, ReflStrMdSec.second},
735+
{ConformMdSec.first, ConformMdSec.second},
736+
{MPEnumMdSec.first, MPEnumMdSec.second},
737+
PotentialModuleNames};
738+
auto rid = this->addReflectionInfo(info);
739+
if (!result)
740+
result = rid;
741+
}
692742

693-
return this->addReflectionInfo(info);
743+
return result;
694744
}
695745

696746
/// Parses metadata information from an ELF image. Because the Section

0 commit comments

Comments
 (0)