diff --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h --- a/llvm/include/llvm/Object/MachO.h +++ b/llvm/include/llvm/Object/MachO.h @@ -391,6 +391,8 @@ 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 --- a/llvm/include/llvm/Object/ObjectFile.h +++ b/llvm/include/llvm/Object/ObjectFile.h @@ -350,6 +350,11 @@ /// 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 --- a/llvm/lib/Object/MachOObjectFile.cpp +++ b/llvm/lib/Object/MachOObjectFile.cpp @@ -4973,3 +4973,23 @@ .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 --- a/llvm/lib/Object/ObjectFile.cpp +++ b/llvm/lib/Object/ObjectFile.cpp @@ -198,3 +198,12 @@ return OwningBinary(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 --- a/llvm/test/tools/dsymutil/X86/reflection-dump.test +++ b/llvm/test/tools/dsymutil/X86/reflection-dump.test @@ -11,46 +11,34 @@ 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.h b/llvm/tools/dsymutil/DwarfLinkerForBinary.h --- 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 @@ const DebugMap &DebugMap, remarks::RemarkLinker &RL); + void collectRelocationsToApplyToSwiftReflectionSections( + const object::SectionRef &Section, StringRef &Contents, + const llvm::object::MachOObjectFile *MO, + const std::vector &SectionToOffsetInDwarf, + const llvm::dsymutil::DebugMapObject *Obj, + std::vector + &RelocationsToApply) const; + + void copySwiftReflectionMetadata( + const llvm::dsymutil::DebugMapObject *Obj, DwarfStreamer *Streamer, + const std::vector &SectionToOffsetInDwarf, + std::vector + &RelocationsToApply); + raw_fd_ostream &OutFile; BinaryHolder &BinHolder; LinkOptions Options; diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -296,12 +296,11 @@ 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 @@ 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 @@ 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 +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(OF->getBinary())) { + for (auto &Section : MO->sections()) { + llvm::Expected 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 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 &SectionToOffsetInDwarf, + const llvm::dsymutil::DebugMapObject *Obj, + std::vector &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 { + 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 SecondSymbolAddress; + auto Sym = It->getSymbol(); + if (Sym != MO->symbol_end()) { + Expected 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 &SectionToOffsetInDwarf, + std::vector + &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(OF->getBinary())) { - for (auto &Section : OF->getBinary()->sections()) { + } + if (auto *MO = dyn_cast(OF->getBinary())) { + // Collect the swift reflection sections before emitting them. This is + // done so we control the order they're emitted. + std::unordered_map + SwiftSections; + for (auto &Section : MO->sections()) { llvm::Expected 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 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(Section.getObject()); + collectRelocationsToApplyToSwiftReflectionSections( + Section, *SectionContents, MO, SectionToOffsetInDwarf, Obj, + RelocationsToApply); + Streamer->emitSwiftReflectionSection(SectionKind, *SectionContents, + Section.getAlignment(), + Section.getSize()); } } } @@ -467,15 +645,19 @@ // 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 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 @@ 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 @@ 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/MachOUtils.h b/llvm/tools/dsymutil/MachOUtils.h --- a/llvm/tools/dsymutil/MachOUtils.h +++ b/llvm/tools/dsymutil/MachOUtils.h @@ -37,13 +37,29 @@ ~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 &ArchFiles, StringRef OutputFileName, const LinkOptions &, StringRef SDKPath); - -bool generateDsymCompanion(llvm::IntrusiveRefCntPtr VFS, - const DebugMap &DM, SymbolMapTranslator &Translator, - MCStreamer &MS, raw_fd_ostream &OutFile); +bool generateDsymCompanion( + llvm::IntrusiveRefCntPtr VFS, const DebugMap &DM, + SymbolMapTranslator &Translator, MCStreamer &MS, raw_fd_ostream &OutFile, + const std::vector + &RelocationsToApply); std::string getArchName(StringRef Arch); } // namespace MachOUtils diff --git a/llvm/tools/dsymutil/MachOUtils.cpp b/llvm/tools/dsymutil/MachOUtils.cpp --- a/llvm/tools/dsymutil/MachOUtils.cpp +++ b/llvm/tools/dsymutil/MachOUtils.cpp @@ -351,9 +351,11 @@ // 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 VFS, - const DebugMap &DM, SymbolMapTranslator &Translator, - MCStreamer &MS, raw_fd_ostream &OutFile) { +bool generateDsymCompanion( + llvm::IntrusiveRefCntPtr VFS, const DebugMap &DM, + SymbolMapTranslator &Translator, MCStreamer &MS, raw_fd_ostream &OutFile, + const std::vector + &RelocationsToApply) { auto &ObjectStreamer = static_cast(MS); MCAssembler &MCAsm = ObjectStreamer.getAssembler(); auto &Writer = static_cast(MCAsm.getWriter()); @@ -619,6 +621,25 @@ 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