[llvm] 9b3af5e - [dsymutil] Apply relocations present in Swift reflection sections

Augusto Noronha via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 17 10:23:41 PDT 2022


Author: Augusto Noronha
Date: 2022-03-17T14:23:20-03:00
New Revision: 9b3af5e7b70239516cbe56f82fb195f8a55d3a2e

URL: https://github.com/llvm/llvm-project/commit/9b3af5e7b70239516cbe56f82fb195f8a55d3a2e
DIFF: https://github.com/llvm/llvm-project/commit/9b3af5e7b70239516cbe56f82fb195f8a55d3a2e.diff

LOG: [dsymutil] Apply relocations present in Swift reflection sections

The strippable Swift reflection sections contain subtractor relocations
that need to be applied. There are two situations we need to support.
1) Both symbols used in the relocation come from the .o file (for
   example, one symbol lives in __swift5_fieldmd and the second in
   __swift5_reflstr).
2) One symbol comes from th .o file and the second from the main
   binary (for example, __swift5_fieldmd and __swift5_typeref).

Differential Revision: https://reviews.llvm.org/D120574

Added: 
    

Modified: 
    llvm/include/llvm/Object/MachO.h
    llvm/include/llvm/Object/ObjectFile.h
    llvm/lib/Object/MachOObjectFile.cpp
    llvm/lib/Object/ObjectFile.cpp
    llvm/test/tools/dsymutil/X86/reflection-dump.test
    llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
    llvm/tools/dsymutil/DwarfLinkerForBinary.h
    llvm/tools/dsymutil/MachOUtils.cpp
    llvm/tools/dsymutil/MachOUtils.h

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h
index c248c9d0dc032..4ec366055db64 100644
--- a/llvm/include/llvm/Object/MachO.h
+++ b/llvm/include/llvm/Object/MachO.h
@@ -391,6 +391,8 @@ class MachOObjectFile : public ObjectFile {
   create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits,
          uint32_t UniversalCputype = 0, uint32_t UniversalIndex = 0);
 
+  static bool isMachOPairedReloc(uint64_t RelocType, uint64_t Arch);
+
   void moveSymbolNext(DataRefImpl &Symb) const override;
 
   uint64_t getNValue(DataRefImpl Sym) const;

diff  --git a/llvm/include/llvm/Object/ObjectFile.h b/llvm/include/llvm/Object/ObjectFile.h
index 1faa070052d5e..8754c229bd4b9 100644
--- a/llvm/include/llvm/Object/ObjectFile.h
+++ b/llvm/include/llvm/Object/ObjectFile.h
@@ -350,6 +350,11 @@ class ObjectFile : public SymbolicFile {
   /// True if this is a relocatable object (.o/.obj).
   virtual bool isRelocatableObject() const = 0;
 
+  /// True if the reflection section can be stripped by the linker.
+  bool isReflectionSectionStrippable(
+      llvm::binaryformat::Swift5ReflectionSectionKind ReflectionSectionKind)
+      const;
+
   /// @returns Pointer to ObjectFile subclass to handle this type of object.
   /// @param ObjectPath The path to the object file. ObjectPath.isObject must
   ///        return true.

diff  --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp
index a3e051664223b..e408062622aa4 100644
--- a/llvm/lib/Object/MachOObjectFile.cpp
+++ b/llvm/lib/Object/MachOObjectFile.cpp
@@ -4973,3 +4973,23 @@ MachOObjectFile::mapReflectionSectionNameToEnumValue(
       .Default(llvm::binaryformat::Swift5ReflectionSectionKind::unknown);
 #undef HANDLE_SWIFT_SECTION
 }
+
+bool MachOObjectFile::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;
+  }
+}

diff  --git a/llvm/lib/Object/ObjectFile.cpp b/llvm/lib/Object/ObjectFile.cpp
index 2e3c2ed34df8f..fed6726467422 100644
--- a/llvm/lib/Object/ObjectFile.cpp
+++ b/llvm/lib/Object/ObjectFile.cpp
@@ -198,3 +198,12 @@ ObjectFile::createObjectFile(StringRef ObjectPath) {
 
   return OwningBinary<ObjectFile>(std::move(Obj), std::move(Buffer));
 }
+
+bool ObjectFile::isReflectionSectionStrippable(
+    llvm::binaryformat::Swift5ReflectionSectionKind ReflectionSectionKind)
+    const {
+  using llvm::binaryformat::Swift5ReflectionSectionKind;
+  return ReflectionSectionKind == Swift5ReflectionSectionKind::fieldmd ||
+         ReflectionSectionKind == Swift5ReflectionSectionKind::reflstr ||
+         ReflectionSectionKind == Swift5ReflectionSectionKind::assocty;
+}

diff  --git a/llvm/test/tools/dsymutil/X86/reflection-dump.test b/llvm/test/tools/dsymutil/X86/reflection-dump.test
index 12cf11ed75127..bcee07d5929eb 100644
--- a/llvm/test/tools/dsymutil/X86/reflection-dump.test
+++ b/llvm/test/tools/dsymutil/X86/reflection-dump.test
@@ -11,46 +11,34 @@ RUN: llvm-objdump -s %t.dir/main.dSYM/Contents/Resources/DWARF/main | FileCheck
 
 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 

diff  --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
index a1d5e656a62e5..76dac490f7eee 100644
--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
@@ -296,12 +296,11 @@ DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj,
   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) {
 
@@ -330,8 +329,9 @@ static bool binaryHasSwiftReflectionSections(const DebugMap &Map,
         continue;
       }
       NameOrErr->consume_back("__TEXT");
-      if (Object->mapReflectionSectionNameToEnumValue(*NameOrErr) !=
-          llvm::binaryformat::Swift5ReflectionSectionKind::unknown) {
+      auto ReflectionSectionKind =
+          Object->mapReflectionSectionNameToEnumValue(*NameOrErr);
+      if (Object->isReflectionSectionStrippable(ReflectionSectionKind)) {
         return true;
       }
     }
@@ -339,30 +339,208 @@ static bool binaryHasSwiftReflectionSections(const DebugMap &Map,
   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 
diff erent 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());
     }
   }
 }
@@ -467,15 +645,19 @@ bool DwarfLinkerForBinary::link(const DebugMap &Map) {
   // 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) {
@@ -547,32 +729,12 @@ bool DwarfLinkerForBinary::link(const DebugMap &Map) {
       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.
@@ -597,7 +759,7 @@ void DwarfLinkerForBinary::AddressManager::findValidRelocsMachO(
     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() +

diff  --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.h b/llvm/tools/dsymutil/DwarfLinkerForBinary.h
index dc4691b69c553..3a363d82ef16a 100644
--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.h
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.h
@@ -12,6 +12,7 @@
 #include "BinaryHolder.h"
 #include "DebugMap.h"
 #include "LinkUtils.h"
+#include "MachOUtils.h"
 #include "llvm/DWARFLinker/DWARFLinker.h"
 #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
 #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
@@ -203,6 +204,20 @@ class DwarfLinkerForBinary {
                                   const DebugMap &DebugMap,
                                   remarks::RemarkLinker &RL);
 
+  void 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;
+
+  void copySwiftReflectionMetadata(
+      const llvm::dsymutil::DebugMapObject *Obj, DwarfStreamer *Streamer,
+      const std::vector<uint64_t> &SectionToOffsetInDwarf,
+      std::vector<MachOUtils::DwarfRelocationApplicationInfo>
+          &RelocationsToApply);
+
   raw_fd_ostream &OutFile;
   BinaryHolder &BinHolder;
   LinkOptions Options;

diff  --git a/llvm/tools/dsymutil/MachOUtils.cpp b/llvm/tools/dsymutil/MachOUtils.cpp
index 324e87b311efb..3bf455eb4eae6 100644
--- a/llvm/tools/dsymutil/MachOUtils.cpp
+++ b/llvm/tools/dsymutil/MachOUtils.cpp
@@ -351,9 +351,11 @@ static unsigned segmentLoadCommandSize(bool Is64Bit, unsigned NumSections) {
 // Stream a dSYM companion binary file corresponding to the binary referenced
 // by \a DM to \a OutFile. The passed \a MS MCStreamer is setup to write to
 // \a OutFile and it must be using a MachObjectWriter object to do so.
-bool generateDsymCompanion(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
-                           const DebugMap &DM, SymbolMapTranslator &Translator,
-                           MCStreamer &MS, raw_fd_ostream &OutFile) {
+bool generateDsymCompanion(
+    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, const DebugMap &DM,
+    SymbolMapTranslator &Translator, MCStreamer &MS, raw_fd_ostream &OutFile,
+    const std::vector<MachOUtils::DwarfRelocationApplicationInfo>
+        &RelocationsToApply) {
   auto &ObjectStreamer = static_cast<MCObjectStreamer &>(MS);
   MCAssembler &MCAsm = ObjectStreamer.getAssembler();
   auto &Writer = static_cast<MachObjectWriter &>(MCAsm.getWriter());
@@ -619,6 +621,25 @@ bool generateDsymCompanion(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
     MCAsm.writeSectionData(OutFile, &Sec, Layout);
   }
 
+  // Apply relocations to the contents of the DWARF segment.
+  // We do this here because the final value written depend on the DWARF vm
+  // addr, which is only calculated in this function.
+  if (!RelocationsToApply.empty()) {
+    if (!OutFile.supportsSeeking())
+      report_fatal_error(
+          "Cannot apply relocations to file that doesn't support seeking!");
+
+    uint64_t Pos = OutFile.tell();
+    for (auto &RelocationToApply : RelocationsToApply) {
+      OutFile.seek(DwarfSegmentStart + RelocationToApply.AddressFromDwarfStart);
+      int32_t Value = RelocationToApply.Value;
+      if (RelocationToApply.ShouldSubtractDwarfVM)
+        Value -= DwarfVMAddr;
+      OutFile.write((char *)&Value, sizeof(int32_t));
+    }
+    OutFile.seek(Pos);
+  }
+
   return true;
 }
 } // namespace MachOUtils

diff  --git a/llvm/tools/dsymutil/MachOUtils.h b/llvm/tools/dsymutil/MachOUtils.h
index b1cdd44d38e60..8cc4e73e59f14 100644
--- a/llvm/tools/dsymutil/MachOUtils.h
+++ b/llvm/tools/dsymutil/MachOUtils.h
@@ -37,13 +37,29 @@ struct ArchAndFile {
   ~ArchAndFile();
 };
 
+struct DwarfRelocationApplicationInfo {
+  // The position in the stream that should be patched, starting from the
+  // Dwarf's segment file address.
+  uint64_t AddressFromDwarfStart;
+  int32_t Value;
+  // If we should subtract the Dwarf segment's VM address from value before
+  // writing it.
+  bool ShouldSubtractDwarfVM;
+
+  DwarfRelocationApplicationInfo(uint64_t AddressFromDwarfVM, uint32_t Value,
+                                 bool ShouldSubtractDwarfVM)
+      : AddressFromDwarfStart(AddressFromDwarfVM), Value(Value),
+        ShouldSubtractDwarfVM(ShouldSubtractDwarfVM) {}
+};
+
 bool generateUniversalBinary(SmallVectorImpl<ArchAndFile> &ArchFiles,
                              StringRef OutputFileName, const LinkOptions &,
                              StringRef SDKPath);
-
-bool generateDsymCompanion(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
-                           const DebugMap &DM, SymbolMapTranslator &Translator,
-                           MCStreamer &MS, raw_fd_ostream &OutFile);
+bool generateDsymCompanion(
+    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, const DebugMap &DM,
+    SymbolMapTranslator &Translator, MCStreamer &MS, raw_fd_ostream &OutFile,
+    const std::vector<MachOUtils::DwarfRelocationApplicationInfo>
+        &RelocationsToApply);
 
 std::string getArchName(StringRef Arch);
 } // namespace MachOUtils


        


More information about the llvm-commits mailing list