REQUIRES: host-byteorder-little-endian
-CHECK: Contents of section __DWARF,__swift5_typeref:
-CHECK-NEXT: 10000e000 53690000 01ffffff ff002473 346d6169 Si........$s4mai
-CHECK-NEXT: 10000e010 6e31304d 7950726f 746f636f 6c500000 n10MyProtocolP..
-CHECK-NEXT: 10000e020 01ffffff ff007800 42300000 53690000 ......x.B0..Si..
-CHECK-NEXT: 10000e030 01ffffff ff002473 346d6169 6e31304d ......$s4main10M
-CHECK-NEXT: 10000e040 7950726f 746f636f 6c500000 01ffffff yProtocolP......
-
-CHECK: Contents of section __DWARF,__swift5_reflstr:
-CHECK-NEXT: 10000e09b 496e6e65 7200696e 6e657200 496e6e65 Inner.inner.Inne
-CHECK-NEXT: 10000e0ab 72006900 6d73006d 6500696e 6e657200 r.i.ms.me.inner.
-CHECK-NEXT: 10000e0bb 43004900 74006d67 73006d67 65004743 C.I.t.mgs.mge.GC
-CHECK-NEXT: 10000e0cb 00
CHECK: Contents of section __DWARF,__swift5_assocty:
-CHECK-NEXT: 10000e0cc 00000000 fcffffff 01000000 08000000 ................
-CHECK-NEXT: 10000e0dc f0ffffff ecffffff 00000000 fcffffff ................
-CHECK-NEXT: 10000e0ec 01000000 08000000 f0ffffff ecffffff ................
+CHECK-NEXT: 10000e000 00000000 fcffffff 01000000 08000000 ................
+CHECK-NEXT: 10000e010 f0ffffff ecffffff 00000000 fcffffff ................
+CHECK-NEXT: 10000e020 01000000 08000000 f0ffffff ecffffff ................
CHECK: Contents of section __DWARF,__swift5_fieldmd:
-CHECK-NEXT: 10000e0fc 00000000 00000000 00000c00 01000000 ................
-CHECK-NEXT: 10000e10c 02000000 ecffffff e8ffffff 00000000 ................
-CHECK-NEXT: 10000e11c 00000000 00000c00 00000000 00000000 ................
-CHECK-NEXT: 10000e12c 00000000 04000c00 00000000 00000000 ................
-
-CHECK: Contents of section __DWARF,__swift5_capture:
-CHECK-NEXT: 10000e22c 01000000 01000000 02000000 f4ffffff ................
-CHECK-NEXT: 10000e23c f0ffffff ecffffff ........
-
-CHECK: Contents of section __DWARF,__swift5_builtin:
-CHECK-NEXT: 10000e244 00000000 09000000 08000100 10000000 ................
-CHECK-NEXT: 10000e254 fe000000 ....
+CHECK-NEXT: 10000e030 00000000 00000000 00000c00 01000000 ................
+CHECK-NEXT: 10000e040 02000000 ecffffff e8ffffff 00000000 ................
+CHECK-NEXT: 10000e050 00000000 00000c00 00000000 00000000 ................
+CHECK-NEXT: 10000e060 00000000 04000c00 00000000 00000000 ................
+CHECK-NEXT: 10000e070 00000000 01000c00 03000000 00000000 ................
+CHECK-NEXT: 10000e080 ecffffff e8ffffff 00000000 e0ffffff ................
+CHECK-NEXT: 10000e090 dcffffff 00000000 d4ffffff d0ffffff ................
+CHECK-NEXT: 10000e0a0 00000000 00000000 00000c00 01000000 ................
+CHECK-NEXT: 10000e0b0 02000000 ecffffff e8ffffff 00000000 ................
+CHECK-NEXT: 10000e0c0 00000000 00000c00 00000000 00000000 ................
+CHECK-NEXT: 10000e0d0 00000000 03000c00 02000000 00000000 ................
+CHECK-NEXT: 10000e0e0 ecffffff e8ffffff 00000000 e0ffffff ................
+CHECK-NEXT: 10000e0f0 dcffffff 00000000 00000000 01000c00 ................
+CHECK-NEXT: 10000e100 04000000 00000000 ecffffff e8ffffff ................
+CHECK-NEXT: 10000e110 00000000 e0ffffff dcffffff 00000000 ................
+CHECK-NEXT: 10000e120 d4ffffff d0ffffff 00000000 c8ffffff ................
+CHECK-NEXT: 10000e130 c4ffffff 00000000 00000000 00000c00 ................
+CHECK-NEXT: 10000e140 00000000 00000000 00000000 02000c00 ................
+CHECK-NEXT: 10000e150 01000000 00000000 ecffffff e8ffffff ................
-CHECK: Contents of section __DWARF,__swift5_proto:
-CHECK-NEXT: 10000e258 41424344 45464748 4950 ABCDEFGHIP
-
-CHECK: Contents of section __DWARF,__swift5_protos:
-CHECK-NEXT: 10000e264 51525354 55565758 5960 QRSTUVWXY`
-
-CHECK: Contents of section __DWARF,__swift5_acfuncs:
-CHECK-NEXT: 10000e270 61626364 65666768 6970 abcdefghip
-
-CHECK: Contents of section __DWARF,__swift5_mpenum:
-CHECK-NEXT: 10000e27c 71727374 75767778 7980 qrstuvwxy.
+CHECK: Contents of section __DWARF,__swift5_reflstr:
+CHECK-NEXT: 10000e160 496e6e65 7200696e 6e657200 496e6e65 Inner.inner.Inne
+CHECK-NEXT: 10000e170 72006900 6d73006d 6500696e 6e657200 r.i.ms.me.inner.
+CHECK-NEXT: 10000e180 43004900 74006d67 73006d67 65004743 C.I.t.mgs.mge.GC
return ErrorOrObj.getError();
}
-static bool binaryHasSwiftReflectionSections(const DebugMap &Map,
- const LinkOptions &Options,
- BinaryHolder &BinHolder) {
- // If the input binary has swift5 reflection sections, there is no need to
- // copy them to the .dSYM. Only copy them for binaries where the linker
- // omitted the reflection metadata.
+static bool binaryHasStrippableSwiftReflectionSections(
+ const DebugMap &Map, const LinkOptions &Options, BinaryHolder &BinHolder) {
+ // If the input binary has strippable swift5 reflection sections, there is no
+ // need to copy them to the .dSYM. Only copy them for binaries where the
+ // linker omitted the reflection metadata.
if (!Map.getBinaryPath().empty() &&
Options.FileType == OutputFileType::Object) {
continue;
}
NameOrErr->consume_back("__TEXT");
- if (Object->mapReflectionSectionNameToEnumValue(*NameOrErr) !=
- llvm::binaryformat::Swift5ReflectionSectionKind::unknown) {
+ auto ReflectionSectionKind =
+ Object->mapReflectionSectionNameToEnumValue(*NameOrErr);
+ if (Object->isReflectionSectionStrippable(ReflectionSectionKind)) {
return true;
}
}
return false;
}
-static void
-copySwiftReflectionMetadata(const llvm::dsymutil::DebugMapObject *Obj,
- DwarfStreamer *Streamer) {
+/// Calculate the start of the strippable swift reflection sections in Dwarf.
+/// Note that there's an assumption that the reflection sections will appear
+/// in alphabetic order.
+static std::vector<uint64_t>
+calculateStartOfStrippableReflectionSections(const DebugMap &Map) {
+ using llvm::binaryformat::Swift5ReflectionSectionKind;
+ uint64_t AssocTySize = 0;
+ uint64_t FieldMdSize = 0;
+ for (const auto &Obj : Map.objects()) {
+ auto OF =
+ llvm::object::ObjectFile::createObjectFile(Obj->getObjectFilename());
+ if (!OF) {
+ llvm::consumeError(OF.takeError());
+ continue;
+ }
+ if (auto *MO = dyn_cast<llvm::object::MachOObjectFile>(OF->getBinary())) {
+ for (auto &Section : MO->sections()) {
+ llvm::Expected<llvm::StringRef> NameOrErr =
+ MO->getSectionName(Section.getRawDataRefImpl());
+ if (!NameOrErr) {
+ llvm::consumeError(NameOrErr.takeError());
+ continue;
+ }
+ NameOrErr->consume_back("__TEXT");
+ auto ReflSectionKind =
+ MO->mapReflectionSectionNameToEnumValue(*NameOrErr);
+ switch (ReflSectionKind) {
+ case Swift5ReflectionSectionKind::assocty:
+ AssocTySize += Section.getSize();
+ break;
+ case Swift5ReflectionSectionKind::fieldmd:
+ FieldMdSize += Section.getSize();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ // Initialize the vector with enough space to fit every reflection section
+ // kind.
+ std::vector<uint64_t> SectionToOffset(Swift5ReflectionSectionKind::last, 0);
+ SectionToOffset[Swift5ReflectionSectionKind::assocty] = 0;
+ SectionToOffset[Swift5ReflectionSectionKind::fieldmd] =
+ llvm::alignTo(AssocTySize, 4);
+ SectionToOffset[Swift5ReflectionSectionKind::reflstr] = llvm::alignTo(
+ SectionToOffset[Swift5ReflectionSectionKind::fieldmd] + FieldMdSize, 4);
+
+ return SectionToOffset;
+}
+
+void DwarfLinkerForBinary::collectRelocationsToApplyToSwiftReflectionSections(
+ const object::SectionRef &Section, StringRef &Contents,
+ const llvm::object::MachOObjectFile *MO,
+ const std::vector<uint64_t> &SectionToOffsetInDwarf,
+ const llvm::dsymutil::DebugMapObject *Obj,
+ std::vector<MachOUtils::DwarfRelocationApplicationInfo> &RelocationsToApply)
+ const {
+ for (auto It = Section.relocation_begin(); It != Section.relocation_end();
+ ++It) {
+ object::DataRefImpl RelocDataRef = It->getRawDataRefImpl();
+ MachO::any_relocation_info MachOReloc = MO->getRelocation(RelocDataRef);
+
+ if (!object::MachOObjectFile::isMachOPairedReloc(
+ MO->getAnyRelocationType(MachOReloc), MO->getArch())) {
+ reportWarning(
+ "Unimplemented relocation type in strippable reflection section ",
+ Obj->getObjectFilename());
+ continue;
+ }
+
+ auto CalculateAddressOfSymbolInDwarfSegment =
+ [&]() -> llvm::Optional<int64_t> {
+ auto Symbol = It->getSymbol();
+ auto SymbolAbsoluteAddress = Symbol->getAddress();
+ if (!SymbolAbsoluteAddress)
+ return {};
+ auto Section = Symbol->getSection();
+ if (!Section) {
+ llvm::consumeError(Section.takeError());
+ return {};
+ }
+
+ if ((*Section)->getObject()->section_end() == *Section)
+ return {};
+
+ auto SectionStart = (*Section)->getAddress();
+ auto SymbolAddressInSection = *SymbolAbsoluteAddress - SectionStart;
+ auto SectionName = (*Section)->getName();
+ if (!SectionName)
+ return {};
+ auto ReflSectionKind =
+ MO->mapReflectionSectionNameToEnumValue(*SectionName);
+
+ int64_t SectionStartInLinkedBinary =
+ SectionToOffsetInDwarf[ReflSectionKind];
+
+ auto Addr = SectionStartInLinkedBinary + SymbolAddressInSection;
+ return Addr;
+ };
+
+ // The first symbol should always be in the section we're currently
+ // iterating over.
+ auto FirstSymbolAddress = CalculateAddressOfSymbolInDwarfSegment();
+ ++It;
+
+ bool ShouldSubtractDwarfVM = false;
+ // For the second symbol there are two possibilities.
+ llvm::Optional<int64_t> SecondSymbolAddress;
+ auto Sym = It->getSymbol();
+ if (Sym != MO->symbol_end()) {
+ Expected<StringRef> SymbolName = Sym->getName();
+ if (SymbolName) {
+ if (const auto *Mapping = Obj->lookupSymbol(*SymbolName)) {
+ // First possibility: the symbol exists in the binary, and exists in a
+ // non-strippable section (for example, typeref, or __TEXT,__const),
+ // in which case we look up its address in the binary, which dsymutil
+ // will copy verbatim.
+ SecondSymbolAddress = Mapping->getValue().BinaryAddress;
+ // Since the symbols live in different segments, we have to substract
+ // the start of the Dwarf's vmaddr so the value calculated points to
+ // the correct place.
+ ShouldSubtractDwarfVM = true;
+ }
+ }
+ }
+
+ if (!SecondSymbolAddress) {
+ // Second possibility, this symbol is not present in the main binary, and
+ // must be in one of the strippable sections (for example, reflstr).
+ // Calculate its address in the same way as we did the first one.
+ SecondSymbolAddress = CalculateAddressOfSymbolInDwarfSegment();
+ }
+
+ if (!FirstSymbolAddress || !SecondSymbolAddress)
+ continue;
+
+ auto SectionName = Section.getName();
+ if (!SectionName)
+ continue;
+
+ int32_t Addend;
+ memcpy(&Addend, Contents.data() + It->getOffset(), sizeof(int32_t));
+ int32_t Value = (*SecondSymbolAddress + Addend) - *FirstSymbolAddress;
+ auto ReflSectionKind =
+ MO->mapReflectionSectionNameToEnumValue(*SectionName);
+ uint64_t AddressFromDwarfVM =
+ SectionToOffsetInDwarf[ReflSectionKind] + It->getOffset();
+ RelocationsToApply.emplace_back(AddressFromDwarfVM, Value,
+ ShouldSubtractDwarfVM);
+ }
+}
+
+void DwarfLinkerForBinary::copySwiftReflectionMetadata(
+ const llvm::dsymutil::DebugMapObject *Obj, DwarfStreamer *Streamer,
+ const std::vector<uint64_t> &SectionToOffsetInDwarf,
+ std::vector<MachOUtils::DwarfRelocationApplicationInfo>
+ &RelocationsToApply) {
+ using binaryformat::Swift5ReflectionSectionKind;
auto OF =
llvm::object::ObjectFile::createObjectFile(Obj->getObjectFilename());
if (!OF) {
llvm::consumeError(OF.takeError());
return;
- } else if (auto *MO =
- dyn_cast<llvm::object::MachOObjectFile>(OF->getBinary())) {
- for (auto &Section : OF->getBinary()->sections()) {
+ }
+ if (auto *MO = dyn_cast<llvm::object::MachOObjectFile>(OF->getBinary())) {
+ // Collect the swift reflection sections before emitting them. This is
+ // done so we control the order they're emitted.
+ std::unordered_map<Swift5ReflectionSectionKind, object::SectionRef>
+ SwiftSections;
+ for (auto &Section : MO->sections()) {
llvm::Expected<llvm::StringRef> NameOrErr =
MO->getSectionName(Section.getRawDataRefImpl());
if (!NameOrErr) {
llvm::consumeError(NameOrErr.takeError());
continue;
}
+ NameOrErr->consume_back("__TEXT");
+ auto ReflSectionKind =
+ MO->mapReflectionSectionNameToEnumValue(*NameOrErr);
+ if (MO->isReflectionSectionStrippable(ReflSectionKind))
+ SwiftSections[ReflSectionKind] = Section;
+ }
+ // Make sure we copy the sections in alphabetic order.
+ auto SectionKindsToEmit = {Swift5ReflectionSectionKind::assocty,
+ Swift5ReflectionSectionKind::fieldmd,
+ Swift5ReflectionSectionKind::reflstr};
+ for (auto SectionKind : SectionKindsToEmit) {
+ if (!SwiftSections.count(SectionKind))
+ continue;
+ auto &Section = SwiftSections[SectionKind];
llvm::Expected<llvm::StringRef> SectionContents = Section.getContents();
- if (SectionContents) {
- NameOrErr->consume_back("__TEXT");
- Streamer->emitSwiftReflectionSection(
- MO->mapReflectionSectionNameToEnumValue(*NameOrErr),
- *SectionContents, Section.getAlignment(), Section.getSize());
- }
+ if (!SectionContents)
+ continue;
+ const auto *MO =
+ llvm::cast<llvm::object::MachOObjectFile>(Section.getObject());
+ collectRelocationsToApplyToSwiftReflectionSections(
+ Section, *SectionContents, MO, SectionToOffsetInDwarf, Obj,
+ RelocationsToApply);
+ Streamer->emitSwiftReflectionSection(SectionKind, *SectionContents,
+ Section.getAlignment(),
+ Section.getSize());
}
}
}
// reflection sections.
if (!Options.NoOutput) {
ReflectionSectionsPresentInBinary =
- binaryHasSwiftReflectionSections(Map, Options, BinHolder);
+ binaryHasStrippableSwiftReflectionSections(Map, Options, BinHolder);
}
- for (const auto &Obj : Map.objects()) {
- // If there is no output specified or the reflection sections are present in
- // the Input binary, there is no need to copy the Swift Reflection Metadata
- if (!Options.NoOutput && !ReflectionSectionsPresentInBinary)
- copySwiftReflectionMetadata(Obj.get(), Streamer.get());
+ std::vector<MachOUtils::DwarfRelocationApplicationInfo> RelocationsToApply;
+ if (!Options.NoOutput && !ReflectionSectionsPresentInBinary) {
+ auto SectionToOffsetInDwarf =
+ calculateStartOfStrippableReflectionSections(Map);
+ for (const auto &Obj : Map.objects())
+ copySwiftReflectionMetadata(Obj.get(), Streamer.get(),
+ SectionToOffsetInDwarf, RelocationsToApply);
+ }
+ for (const auto &Obj : Map.objects()) {
// N_AST objects (swiftmodule files) should get dumped directly into the
// appropriate DWARF section.
if (Obj->getType() == MachO::N_AST) {
Options.FileType == OutputFileType::Object)
return MachOUtils::generateDsymCompanion(
Options.VFS, Map, Options.Translator,
- *Streamer->getAsmPrinter().OutStreamer, OutFile);
+ *Streamer->getAsmPrinter().OutStreamer, OutFile, RelocationsToApply);
Streamer->finish();
return true;
}
-static bool isMachOPairedReloc(uint64_t RelocType, uint64_t Arch) {
- switch (Arch) {
- case Triple::x86:
- return RelocType == MachO::GENERIC_RELOC_SECTDIFF ||
- RelocType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF;
- case Triple::x86_64:
- return RelocType == MachO::X86_64_RELOC_SUBTRACTOR;
- case Triple::arm:
- case Triple::thumb:
- return RelocType == MachO::ARM_RELOC_SECTDIFF ||
- RelocType == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
- RelocType == MachO::ARM_RELOC_HALF ||
- RelocType == MachO::ARM_RELOC_HALF_SECTDIFF;
- case Triple::aarch64:
- return RelocType == MachO::ARM64_RELOC_SUBTRACTOR;
- default:
- return false;
- }
-}
-
/// Iterate over the relocations of the given \p Section and
/// store the ones that correspond to debug map entries into the
/// ValidRelocs array.
object::DataRefImpl RelocDataRef = Reloc.getRawDataRefImpl();
MachO::any_relocation_info MachOReloc = Obj.getRelocation(RelocDataRef);
- if (isMachOPairedReloc(Obj.getAnyRelocationType(MachOReloc),
+ if (object::MachOObjectFile::isMachOPairedReloc(Obj.getAnyRelocationType(MachOReloc),
Obj.getArch())) {
SkipNext = true;
Linker.reportWarning("unsupported relocation in " + *Section.getName() +