1 //===- tools/dsymutil/DwarfLinkerForBinary.cpp ----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "DwarfLinkerForBinary.h"
10 #include "BinaryHolder.h"
11 #include "DebugMap.h"
12 #include "MachOUtils.h"
13 #include "dsymutil.h"
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/ADT/BitVector.h"
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/DenseMapInfo.h"
18 #include "llvm/ADT/DenseSet.h"
19 #include "llvm/ADT/FoldingSet.h"
20 #include "llvm/ADT/Hashing.h"
21 #include "llvm/ADT/PointerIntPair.h"
22 #include "llvm/ADT/STLExtras.h"
23 #include "llvm/ADT/SmallString.h"
24 #include "llvm/ADT/StringMap.h"
25 #include "llvm/ADT/StringRef.h"
26 #include "llvm/ADT/Triple.h"
27 #include "llvm/ADT/Twine.h"
28 #include "llvm/BinaryFormat/Dwarf.h"
29 #include "llvm/BinaryFormat/MachO.h"
30 #include "llvm/BinaryFormat/Swift.h"
31 #include "llvm/CodeGen/AccelTable.h"
32 #include "llvm/CodeGen/AsmPrinter.h"
33 #include "llvm/CodeGen/DIE.h"
34 #include "llvm/CodeGen/NonRelocatableStringpool.h"
35 #include "llvm/Config/config.h"
36 #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
37 #include "llvm/DebugInfo/DIContext.h"
38 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
39 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
40 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
41 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
42 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
43 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
44 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
45 #include "llvm/DebugInfo/DWARF/DWARFSection.h"
46 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
47 #include "llvm/MC/MCAsmBackend.h"
48 #include "llvm/MC/MCAsmInfo.h"
49 #include "llvm/MC/MCCodeEmitter.h"
50 #include "llvm/MC/MCContext.h"
51 #include "llvm/MC/MCDwarf.h"
52 #include "llvm/MC/MCInstrInfo.h"
53 #include "llvm/MC/MCObjectFileInfo.h"
54 #include "llvm/MC/MCObjectWriter.h"
55 #include "llvm/MC/MCRegisterInfo.h"
56 #include "llvm/MC/MCSection.h"
57 #include "llvm/MC/MCStreamer.h"
58 #include "llvm/MC/MCSubtargetInfo.h"
59 #include "llvm/MC/MCTargetOptions.h"
60 #include "llvm/MC/MCTargetOptionsCommandFlags.h"
61 #include "llvm/MC/TargetRegistry.h"
62 #include "llvm/Object/MachO.h"
63 #include "llvm/Object/ObjectFile.h"
64 #include "llvm/Object/SymbolicFile.h"
65 #include "llvm/Support/Allocator.h"
66 #include "llvm/Support/Casting.h"
67 #include "llvm/Support/Compiler.h"
68 #include "llvm/Support/DJB.h"
69 #include "llvm/Support/DataExtractor.h"
70 #include "llvm/Support/Error.h"
71 #include "llvm/Support/ErrorHandling.h"
72 #include "llvm/Support/ErrorOr.h"
73 #include "llvm/Support/FileSystem.h"
74 #include "llvm/Support/Format.h"
75 #include "llvm/Support/LEB128.h"
76 #include "llvm/Support/MathExtras.h"
77 #include "llvm/Support/MemoryBuffer.h"
78 #include "llvm/Support/Path.h"
79 #include "llvm/Support/ThreadPool.h"
80 #include "llvm/Support/ToolOutputFile.h"
81 #include "llvm/Support/WithColor.h"
82 #include "llvm/Support/raw_ostream.h"
83 #include "llvm/Target/TargetMachine.h"
84 #include "llvm/Target/TargetOptions.h"
85 #include <algorithm>
86 #include <cassert>
87 #include <cinttypes>
88 #include <climits>
89 #include <cstdint>
90 #include <cstdlib>
91 #include <cstring>
92 #include <limits>
93 #include <map>
94 #include <memory>
95 #include <optional>
96 #include <string>
97 #include <system_error>
98 #include <tuple>
99 #include <utility>
100 #include <vector>
101 
102 namespace llvm {
103 
104 static mc::RegisterMCTargetOptionsFlags MOF;
105 
106 namespace dsymutil {
107 
copySwiftInterfaces(const std::map<std::string,std::string> & ParseableSwiftInterfaces,StringRef Architecture,const LinkOptions & Options)108 static Error copySwiftInterfaces(
109     const std::map<std::string, std::string> &ParseableSwiftInterfaces,
110     StringRef Architecture, const LinkOptions &Options) {
111   std::error_code EC;
112   SmallString<128> InputPath;
113   SmallString<128> Path;
114   sys::path::append(Path, *Options.ResourceDir, "Swift", Architecture);
115   if ((EC = sys::fs::create_directories(Path.str(), true,
116                                         sys::fs::perms::all_all)))
117     return make_error<StringError>(
118         "cannot create directory: " + toString(errorCodeToError(EC)), EC);
119   unsigned BaseLength = Path.size();
120 
121   for (auto &I : ParseableSwiftInterfaces) {
122     StringRef ModuleName = I.first;
123     StringRef InterfaceFile = I.second;
124     if (!Options.PrependPath.empty()) {
125       InputPath.clear();
126       sys::path::append(InputPath, Options.PrependPath, InterfaceFile);
127       InterfaceFile = InputPath;
128     }
129     sys::path::append(Path, ModuleName);
130     Path.append(".swiftinterface");
131     if (Options.Verbose)
132       outs() << "copy parseable Swift interface " << InterfaceFile << " -> "
133              << Path.str() << '\n';
134 
135     // copy_file attempts an APFS clone first, so this should be cheap.
136     if ((EC = sys::fs::copy_file(InterfaceFile, Path.str())))
137       warn(Twine("cannot copy parseable Swift interface ") + InterfaceFile +
138            ": " + toString(errorCodeToError(EC)));
139     Path.resize(BaseLength);
140   }
141   return Error::success();
142 }
143 
144 /// Report a warning to the user, optionally including information about a
145 /// specific \p DIE related to the warning.
reportWarning(const Twine & Warning,StringRef Context,const DWARFDie * DIE) const146 void DwarfLinkerForBinary::reportWarning(const Twine &Warning,
147                                          StringRef Context,
148                                          const DWARFDie *DIE) const {
149 
150   warn(Warning, Context);
151 
152   if (!Options.Verbose || !DIE)
153     return;
154 
155   DIDumpOptions DumpOpts;
156   DumpOpts.ChildRecurseDepth = 0;
157   DumpOpts.Verbose = Options.Verbose;
158 
159   WithColor::note() << "    in DIE:\n";
160   DIE->dump(errs(), 6 /* Indent */, DumpOpts);
161 }
162 
createStreamer(const Triple & TheTriple,raw_fd_ostream & OutFile)163 bool DwarfLinkerForBinary::createStreamer(const Triple &TheTriple,
164                                           raw_fd_ostream &OutFile) {
165   if (Options.NoOutput)
166     return true;
167 
168   Streamer = std::make_unique<DwarfStreamer>(
169       Options.FileType, OutFile, Options.Translator,
170       [&](const Twine &Error, StringRef Context, const DWARFDie *) {
171         error(Error, Context);
172       },
173       [&](const Twine &Warning, StringRef Context, const DWARFDie *) {
174         warn(Warning, Context);
175       });
176   return Streamer->init(TheTriple, "__DWARF");
177 }
178 
179 ErrorOr<const object::ObjectFile &>
loadObject(const DebugMapObject & Obj,const Triple & Triple)180 DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj,
181                                  const Triple &Triple) {
182   auto ObjectEntry =
183       BinHolder.getObjectEntry(Obj.getObjectFilename(), Obj.getTimestamp());
184   if (!ObjectEntry) {
185     auto Err = ObjectEntry.takeError();
186     reportWarning(Twine(Obj.getObjectFilename()) + ": " +
187                       toString(std::move(Err)),
188                   Obj.getObjectFilename());
189     return errorToErrorCode(std::move(Err));
190   }
191 
192   auto Object = ObjectEntry->getObject(Triple);
193   if (!Object) {
194     auto Err = Object.takeError();
195     reportWarning(Twine(Obj.getObjectFilename()) + ": " +
196                       toString(std::move(Err)),
197                   Obj.getObjectFilename());
198     return errorToErrorCode(std::move(Err));
199   }
200 
201   return *Object;
202 }
203 
remarksErrorHandler(const DebugMapObject & DMO,DwarfLinkerForBinary & Linker,std::unique_ptr<FileError> FE)204 static Error remarksErrorHandler(const DebugMapObject &DMO,
205                                  DwarfLinkerForBinary &Linker,
206                                  std::unique_ptr<FileError> FE) {
207   bool IsArchive = DMO.getObjectFilename().endswith(")");
208   // Don't report errors for missing remark files from static
209   // archives.
210   if (!IsArchive)
211     return Error(std::move(FE));
212 
213   std::string Message = FE->message();
214   Error E = FE->takeError();
215   Error NewE = handleErrors(std::move(E), [&](std::unique_ptr<ECError> EC) {
216     if (EC->convertToErrorCode() != std::errc::no_such_file_or_directory)
217       return Error(std::move(EC));
218 
219     Linker.reportWarning(Message, DMO.getObjectFilename());
220     return Error(Error::success());
221   });
222 
223   if (!NewE)
224     return Error::success();
225 
226   return createFileError(FE->getFileName(), std::move(NewE));
227 }
228 
emitRemarks(const LinkOptions & Options,StringRef BinaryPath,StringRef ArchName,const remarks::RemarkLinker & RL)229 static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath,
230                          StringRef ArchName, const remarks::RemarkLinker &RL) {
231   // Make sure we don't create the directories and the file if there is nothing
232   // to serialize.
233   if (RL.empty())
234     return Error::success();
235 
236   SmallString<128> InputPath;
237   SmallString<128> Path;
238   // Create the "Remarks" directory in the "Resources" directory.
239   sys::path::append(Path, *Options.ResourceDir, "Remarks");
240   if (std::error_code EC = sys::fs::create_directories(Path.str(), true,
241                                                        sys::fs::perms::all_all))
242     return errorCodeToError(EC);
243 
244   // Append the file name.
245   // For fat binaries, also append a dash and the architecture name.
246   sys::path::append(Path, sys::path::filename(BinaryPath));
247   if (Options.NumDebugMaps > 1) {
248     // More than one debug map means we have a fat binary.
249     Path += '-';
250     Path += ArchName;
251   }
252 
253   std::error_code EC;
254   raw_fd_ostream OS(Options.NoOutput ? "-" : Path.str(), EC,
255                     Options.RemarksFormat == remarks::Format::Bitstream
256                         ? sys::fs::OF_None
257                         : sys::fs::OF_Text);
258   if (EC)
259     return errorCodeToError(EC);
260 
261   if (Error E = RL.serialize(OS, Options.RemarksFormat))
262     return E;
263 
264   return Error::success();
265 }
266 
267 ErrorOr<DWARFFile &>
loadObject(const DebugMapObject & Obj,const DebugMap & DebugMap,remarks::RemarkLinker & RL)268 DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj,
269                                  const DebugMap &DebugMap,
270                                  remarks::RemarkLinker &RL) {
271   auto ErrorOrObj = loadObject(Obj, DebugMap.getTriple());
272 
273   if (ErrorOrObj) {
274     ContextForLinking.push_back(
275         std::unique_ptr<DWARFContext>(DWARFContext::create(*ErrorOrObj)));
276     AddressMapForLinking.push_back(
277         std::make_unique<AddressManager>(*this, *ErrorOrObj, Obj));
278 
279     ObjectsForLinking.push_back(std::make_unique<DWARFFile>(
280         Obj.getObjectFilename(), ContextForLinking.back().get(),
281         AddressMapForLinking.back().get(),
282         Obj.empty() ? Obj.getWarnings() : EmptyWarnings));
283 
284     Error E = RL.link(*ErrorOrObj);
285     if (Error NewE = handleErrors(
286             std::move(E), [&](std::unique_ptr<FileError> EC) -> Error {
287               return remarksErrorHandler(Obj, *this, std::move(EC));
288             }))
289       return errorToErrorCode(std::move(NewE));
290 
291     return *ObjectsForLinking.back();
292   }
293 
294   return ErrorOrObj.getError();
295 }
296 
binaryHasStrippableSwiftReflectionSections(const DebugMap & Map,const LinkOptions & Options,BinaryHolder & BinHolder)297 static bool binaryHasStrippableSwiftReflectionSections(
298     const DebugMap &Map, const LinkOptions &Options, BinaryHolder &BinHolder) {
299   // If the input binary has strippable swift5 reflection sections, there is no
300   // need to copy them to the .dSYM. Only copy them for binaries where the
301   // linker omitted the reflection metadata.
302   if (!Map.getBinaryPath().empty() &&
303       Options.FileType == OutputFileType::Object) {
304 
305     auto ObjectEntry = BinHolder.getObjectEntry(Map.getBinaryPath());
306     // If ObjectEntry or Object has an error, no binary exists, therefore no
307     // reflection sections exist.
308     if (!ObjectEntry) {
309       // Any errors will be diagnosed later in the main loop, ignore them here.
310       llvm::consumeError(ObjectEntry.takeError());
311       return false;
312     }
313 
314     auto Object =
315         ObjectEntry->getObjectAs<object::MachOObjectFile>(Map.getTriple());
316     if (!Object) {
317       // Any errors will be diagnosed later in the main loop, ignore them here.
318       llvm::consumeError(Object.takeError());
319       return false;
320     }
321 
322     for (auto &Section : Object->sections()) {
323       llvm::Expected<llvm::StringRef> NameOrErr =
324           Object->getSectionName(Section.getRawDataRefImpl());
325       if (!NameOrErr) {
326         llvm::consumeError(NameOrErr.takeError());
327         continue;
328       }
329       NameOrErr->consume_back("__TEXT");
330       auto ReflectionSectionKind =
331           Object->mapReflectionSectionNameToEnumValue(*NameOrErr);
332       if (Object->isReflectionSectionStrippable(ReflectionSectionKind)) {
333         return true;
334       }
335     }
336   }
337   return false;
338 }
339 
340 /// Calculate the start of the strippable swift reflection sections in Dwarf.
341 /// Note that there's an assumption that the reflection sections will appear
342 /// in alphabetic order.
343 static std::vector<uint64_t>
calculateStartOfStrippableReflectionSections(const DebugMap & Map)344 calculateStartOfStrippableReflectionSections(const DebugMap &Map) {
345   using llvm::binaryformat::Swift5ReflectionSectionKind;
346   uint64_t AssocTySize = 0;
347   uint64_t FieldMdSize = 0;
348   for (const auto &Obj : Map.objects()) {
349     auto OF =
350         llvm::object::ObjectFile::createObjectFile(Obj->getObjectFilename());
351     if (!OF) {
352       llvm::consumeError(OF.takeError());
353       continue;
354     }
355     if (auto *MO = dyn_cast<llvm::object::MachOObjectFile>(OF->getBinary())) {
356       for (auto &Section : MO->sections()) {
357         llvm::Expected<llvm::StringRef> NameOrErr =
358             MO->getSectionName(Section.getRawDataRefImpl());
359         if (!NameOrErr) {
360           llvm::consumeError(NameOrErr.takeError());
361           continue;
362         }
363         NameOrErr->consume_back("__TEXT");
364         auto ReflSectionKind =
365             MO->mapReflectionSectionNameToEnumValue(*NameOrErr);
366         switch (ReflSectionKind) {
367         case Swift5ReflectionSectionKind::assocty:
368           AssocTySize += Section.getSize();
369           break;
370         case Swift5ReflectionSectionKind::fieldmd:
371           FieldMdSize += Section.getSize();
372           break;
373         default:
374           break;
375         }
376       }
377     }
378   }
379   // Initialize the vector with enough space to fit every reflection section
380   // kind.
381   std::vector<uint64_t> SectionToOffset(Swift5ReflectionSectionKind::last, 0);
382   SectionToOffset[Swift5ReflectionSectionKind::assocty] = 0;
383   SectionToOffset[Swift5ReflectionSectionKind::fieldmd] =
384       llvm::alignTo(AssocTySize, 4);
385   SectionToOffset[Swift5ReflectionSectionKind::reflstr] = llvm::alignTo(
386       SectionToOffset[Swift5ReflectionSectionKind::fieldmd] + FieldMdSize, 4);
387 
388   return SectionToOffset;
389 }
390 
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) const391 void DwarfLinkerForBinary::collectRelocationsToApplyToSwiftReflectionSections(
392     const object::SectionRef &Section, StringRef &Contents,
393     const llvm::object::MachOObjectFile *MO,
394     const std::vector<uint64_t> &SectionToOffsetInDwarf,
395     const llvm::dsymutil::DebugMapObject *Obj,
396     std::vector<MachOUtils::DwarfRelocationApplicationInfo> &RelocationsToApply)
397     const {
398   for (auto It = Section.relocation_begin(); It != Section.relocation_end();
399        ++It) {
400     object::DataRefImpl RelocDataRef = It->getRawDataRefImpl();
401     MachO::any_relocation_info MachOReloc = MO->getRelocation(RelocDataRef);
402 
403     if (!object::MachOObjectFile::isMachOPairedReloc(
404             MO->getAnyRelocationType(MachOReloc), MO->getArch())) {
405       reportWarning(
406           "Unimplemented relocation type in strippable reflection section ",
407           Obj->getObjectFilename());
408       continue;
409     }
410 
411     auto CalculateAddressOfSymbolInDwarfSegment =
412         [&]() -> std::optional<int64_t> {
413       auto Symbol = It->getSymbol();
414       auto SymbolAbsoluteAddress = Symbol->getAddress();
415       if (!SymbolAbsoluteAddress)
416         return {};
417       auto Section = Symbol->getSection();
418       if (!Section) {
419         llvm::consumeError(Section.takeError());
420         return {};
421       }
422 
423       if ((*Section)->getObject()->section_end() == *Section)
424         return {};
425 
426       auto SectionStart = (*Section)->getAddress();
427       auto SymbolAddressInSection = *SymbolAbsoluteAddress - SectionStart;
428       auto SectionName = (*Section)->getName();
429       if (!SectionName)
430         return {};
431       auto ReflSectionKind =
432           MO->mapReflectionSectionNameToEnumValue(*SectionName);
433 
434       int64_t SectionStartInLinkedBinary =
435           SectionToOffsetInDwarf[ReflSectionKind];
436 
437       auto Addr = SectionStartInLinkedBinary + SymbolAddressInSection;
438       return Addr;
439     };
440 
441     // The first symbol should always be in the section we're currently
442     // iterating over.
443     auto FirstSymbolAddress = CalculateAddressOfSymbolInDwarfSegment();
444     ++It;
445 
446     bool ShouldSubtractDwarfVM = false;
447     // For the second symbol there are two possibilities.
448     std::optional<int64_t> SecondSymbolAddress;
449     auto Sym = It->getSymbol();
450     if (Sym != MO->symbol_end()) {
451       Expected<StringRef> SymbolName = Sym->getName();
452       if (SymbolName) {
453         if (const auto *Mapping = Obj->lookupSymbol(*SymbolName)) {
454           // First possibility: the symbol exists in the binary, and exists in a
455           // non-strippable section (for example, typeref, or __TEXT,__const),
456           // in which case we look up its address in the  binary, which dsymutil
457           // will copy verbatim.
458           SecondSymbolAddress = Mapping->getValue().BinaryAddress;
459           // Since the symbols live in different segments, we have to substract
460           // the start of the Dwarf's vmaddr so the value calculated points to
461           // the correct place.
462           ShouldSubtractDwarfVM = true;
463         }
464       }
465     }
466 
467     if (!SecondSymbolAddress) {
468       // Second possibility, this symbol is not present in the main binary, and
469       // must be in one of the strippable sections (for example, reflstr).
470       // Calculate its address in the same way as we did the first one.
471       SecondSymbolAddress = CalculateAddressOfSymbolInDwarfSegment();
472     }
473 
474     if (!FirstSymbolAddress || !SecondSymbolAddress)
475       continue;
476 
477     auto SectionName = Section.getName();
478     if (!SectionName)
479       continue;
480 
481     int32_t Addend;
482     memcpy(&Addend, Contents.data() + It->getOffset(), sizeof(int32_t));
483     int32_t Value = (*SecondSymbolAddress + Addend) - *FirstSymbolAddress;
484     auto ReflSectionKind =
485         MO->mapReflectionSectionNameToEnumValue(*SectionName);
486     uint64_t AddressFromDwarfVM =
487         SectionToOffsetInDwarf[ReflSectionKind] + It->getOffset();
488     RelocationsToApply.emplace_back(AddressFromDwarfVM, Value,
489                                     ShouldSubtractDwarfVM);
490   }
491 }
492 
copySwiftReflectionMetadata(const llvm::dsymutil::DebugMapObject * Obj,DwarfStreamer * Streamer,std::vector<uint64_t> & SectionToOffsetInDwarf,std::vector<MachOUtils::DwarfRelocationApplicationInfo> & RelocationsToApply)493 void DwarfLinkerForBinary::copySwiftReflectionMetadata(
494     const llvm::dsymutil::DebugMapObject *Obj, DwarfStreamer *Streamer,
495     std::vector<uint64_t> &SectionToOffsetInDwarf,
496     std::vector<MachOUtils::DwarfRelocationApplicationInfo>
497         &RelocationsToApply) {
498   using binaryformat::Swift5ReflectionSectionKind;
499   auto OF =
500       llvm::object::ObjectFile::createObjectFile(Obj->getObjectFilename());
501   if (!OF) {
502     llvm::consumeError(OF.takeError());
503     return;
504   }
505   if (auto *MO = dyn_cast<llvm::object::MachOObjectFile>(OF->getBinary())) {
506     // Collect the swift reflection sections before emitting them. This is
507     // done so we control the order they're emitted.
508     std::array<std::optional<object::SectionRef>,
509                Swift5ReflectionSectionKind::last + 1>
510         SwiftSections;
511     for (auto &Section : MO->sections()) {
512       llvm::Expected<llvm::StringRef> NameOrErr =
513           MO->getSectionName(Section.getRawDataRefImpl());
514       if (!NameOrErr) {
515         llvm::consumeError(NameOrErr.takeError());
516         continue;
517       }
518       NameOrErr->consume_back("__TEXT");
519       auto ReflSectionKind =
520           MO->mapReflectionSectionNameToEnumValue(*NameOrErr);
521       if (MO->isReflectionSectionStrippable(ReflSectionKind))
522         SwiftSections[ReflSectionKind] = Section;
523     }
524     // Make sure we copy the sections in alphabetic order.
525     auto SectionKindsToEmit = {Swift5ReflectionSectionKind::assocty,
526                                Swift5ReflectionSectionKind::fieldmd,
527                                Swift5ReflectionSectionKind::reflstr};
528     for (auto SectionKind : SectionKindsToEmit) {
529       if (!SwiftSections[SectionKind])
530         continue;
531       auto &Section = *SwiftSections[SectionKind];
532       llvm::Expected<llvm::StringRef> SectionContents = Section.getContents();
533       if (!SectionContents)
534         continue;
535       const auto *MO =
536           llvm::cast<llvm::object::MachOObjectFile>(Section.getObject());
537       collectRelocationsToApplyToSwiftReflectionSections(
538           Section, *SectionContents, MO, SectionToOffsetInDwarf, Obj,
539           RelocationsToApply);
540       // Update the section start with the current section's contribution, so
541       // the next section we copy from a different .o file points to the correct
542       // place.
543       SectionToOffsetInDwarf[SectionKind] += Section.getSize();
544       Streamer->emitSwiftReflectionSection(SectionKind, *SectionContents,
545                                            Section.getAlignment().value(),
546                                            Section.getSize());
547     }
548   }
549 }
550 
link(const DebugMap & Map)551 bool DwarfLinkerForBinary::link(const DebugMap &Map) {
552   if (!createStreamer(Map.getTriple(), OutFile))
553     return false;
554 
555   ObjectsForLinking.clear();
556   ContextForLinking.clear();
557   AddressMapForLinking.clear();
558 
559   DebugMap DebugMap(Map.getTriple(), Map.getBinaryPath());
560 
561   DWARFLinker GeneralLinker(Streamer.get(), DwarfLinkerClient::Dsymutil);
562 
563   remarks::RemarkLinker RL;
564   if (!Options.RemarksPrependPath.empty())
565     RL.setExternalFilePrependPath(Options.RemarksPrependPath);
566   GeneralLinker.setObjectPrefixMap(&Options.ObjectPrefixMap);
567 
568   std::function<StringRef(StringRef)> TranslationLambda = [&](StringRef Input) {
569     assert(Options.Translator);
570     return Options.Translator(Input);
571   };
572 
573   GeneralLinker.setVerbosity(Options.Verbose);
574   GeneralLinker.setStatistics(Options.Statistics);
575   GeneralLinker.setVerifyInputDWARF(Options.VerifyInputDWARF);
576   GeneralLinker.setNoOutput(Options.NoOutput);
577   GeneralLinker.setNoODR(Options.NoODR);
578   GeneralLinker.setUpdate(Options.Update);
579   GeneralLinker.setNumThreads(Options.Threads);
580   GeneralLinker.setPrependPath(Options.PrependPath);
581   GeneralLinker.setKeepFunctionForStatic(Options.KeepFunctionForStatic);
582   if (Options.Translator)
583     GeneralLinker.setStringsTranslator(TranslationLambda);
584   GeneralLinker.setWarningHandler(
585       [&](const Twine &Warning, StringRef Context, const DWARFDie *DIE) {
586         reportWarning(Warning, Context, DIE);
587       });
588   GeneralLinker.setErrorHandler(
589       [&](const Twine &Error, StringRef Context, const DWARFDie *) {
590         error(Error, Context);
591       });
592   objFileLoader Loader = [&DebugMap, &RL,
593                           this](StringRef ContainerName,
594                                 StringRef Path) -> ErrorOr<DWARFFile &> {
595     auto &Obj = DebugMap.addDebugMapObject(
596         Path, sys::TimePoint<std::chrono::seconds>(), MachO::N_OSO);
597 
598     if (auto ErrorOrObj = loadObject(Obj, DebugMap, RL)) {
599       return *ErrorOrObj;
600     } else {
601       // Try and emit more helpful warnings by applying some heuristics.
602       StringRef ObjFile = ContainerName;
603       bool IsClangModule = sys::path::extension(Path).equals(".pcm");
604       bool IsArchive = ObjFile.endswith(")");
605 
606       if (IsClangModule) {
607         StringRef ModuleCacheDir = sys::path::parent_path(Path);
608         if (sys::fs::exists(ModuleCacheDir)) {
609           // If the module's parent directory exists, we assume that the
610           // module cache has expired and was pruned by clang.  A more
611           // adventurous dsymutil would invoke clang to rebuild the module
612           // now.
613           if (!ModuleCacheHintDisplayed) {
614             WithColor::note()
615                 << "The clang module cache may have expired since "
616                    "this object file was built. Rebuilding the "
617                    "object file will rebuild the module cache.\n";
618             ModuleCacheHintDisplayed = true;
619           }
620         } else if (IsArchive) {
621           // If the module cache directory doesn't exist at all and the
622           // object file is inside a static library, we assume that the
623           // static library was built on a different machine. We don't want
624           // to discourage module debugging for convenience libraries within
625           // a project though.
626           if (!ArchiveHintDisplayed) {
627             WithColor::note()
628                 << "Linking a static library that was built with "
629                    "-gmodules, but the module cache was not found.  "
630                    "Redistributable static libraries should never be "
631                    "built with module debugging enabled.  The debug "
632                    "experience will be degraded due to incomplete "
633                    "debug information.\n";
634             ArchiveHintDisplayed = true;
635           }
636         }
637       }
638 
639       return ErrorOrObj.getError();
640     }
641 
642     llvm_unreachable("Unhandled DebugMap object");
643   };
644   GeneralLinker.setSwiftInterfacesMap(&ParseableSwiftInterfaces);
645   bool ReflectionSectionsPresentInBinary = false;
646   // If there is no output specified, no point in checking the binary for swift5
647   // reflection sections.
648   if (!Options.NoOutput) {
649     ReflectionSectionsPresentInBinary =
650         binaryHasStrippableSwiftReflectionSections(Map, Options, BinHolder);
651   }
652 
653   std::vector<MachOUtils::DwarfRelocationApplicationInfo> RelocationsToApply;
654   if (!Options.NoOutput && !ReflectionSectionsPresentInBinary) {
655     auto SectionToOffsetInDwarf =
656         calculateStartOfStrippableReflectionSections(Map);
657     for (const auto &Obj : Map.objects())
658       copySwiftReflectionMetadata(Obj.get(), Streamer.get(),
659                                   SectionToOffsetInDwarf, RelocationsToApply);
660   }
661 
662   uint16_t MaxDWARFVersion = 0;
663   std::function<void(const DWARFUnit &Unit)> OnCUDieLoaded =
664       [&MaxDWARFVersion](const DWARFUnit &Unit) {
665         MaxDWARFVersion = std::max(Unit.getVersion(), MaxDWARFVersion);
666       };
667 
668   for (const auto &Obj : Map.objects()) {
669     // N_AST objects (swiftmodule files) should get dumped directly into the
670     // appropriate DWARF section.
671     if (Obj->getType() == MachO::N_AST) {
672       if (Options.Verbose)
673         outs() << "DEBUG MAP OBJECT: " << Obj->getObjectFilename() << "\n";
674 
675       StringRef File = Obj->getObjectFilename();
676       auto ErrorOrMem = MemoryBuffer::getFile(File);
677       if (!ErrorOrMem) {
678         warn("Could not open '" + File + "'\n");
679         continue;
680       }
681       sys::fs::file_status Stat;
682       if (auto Err = sys::fs::status(File, Stat)) {
683         warn(Err.message());
684         continue;
685       }
686       if (!Options.NoTimestamp) {
687         // The modification can have sub-second precision so we need to cast
688         // away the extra precision that's not present in the debug map.
689         auto ModificationTime =
690             std::chrono::time_point_cast<std::chrono::seconds>(
691                 Stat.getLastModificationTime());
692         if (Obj->getTimestamp() != sys::TimePoint<>() &&
693             ModificationTime != Obj->getTimestamp()) {
694           // Not using the helper here as we can easily stream TimePoint<>.
695           WithColor::warning()
696               << File << ": timestamp mismatch between swift interface file ("
697               << sys::TimePoint<>(ModificationTime) << ") and debug map ("
698               << sys::TimePoint<>(Obj->getTimestamp()) << ")\n";
699           continue;
700         }
701       }
702 
703       // Copy the module into the .swift_ast section.
704       if (!Options.NoOutput)
705         Streamer->emitSwiftAST((*ErrorOrMem)->getBuffer());
706 
707       continue;
708     }
709 
710     if (auto ErrorOrObj = loadObject(*Obj, Map, RL))
711       GeneralLinker.addObjectFile(*ErrorOrObj, Loader, OnCUDieLoaded);
712     else {
713       ObjectsForLinking.push_back(std::make_unique<DWARFFile>(
714           Obj->getObjectFilename(), nullptr, nullptr,
715           Obj->empty() ? Obj->getWarnings() : EmptyWarnings));
716       GeneralLinker.addObjectFile(*ObjectsForLinking.back());
717     }
718   }
719 
720   // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway.
721   if (MaxDWARFVersion == 0)
722     MaxDWARFVersion = 3;
723 
724   if (Error E = GeneralLinker.setTargetDWARFVersion(MaxDWARFVersion))
725     return error(toString(std::move(E)));
726 
727   switch (Options.TheAccelTableKind) {
728   case DsymutilAccelTableKind::Apple:
729     GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::Apple);
730     break;
731   case DsymutilAccelTableKind::Dwarf:
732     GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::DebugNames);
733     break;
734   case DsymutilAccelTableKind::Pub:
735     GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::Pub);
736     break;
737   case DsymutilAccelTableKind::Default:
738     if (MaxDWARFVersion >= 5)
739       GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::DebugNames);
740     else
741       GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::Apple);
742     break;
743   case DsymutilAccelTableKind::None:
744     // Nothing to do.
745     break;
746   }
747 
748   // link debug info for loaded object files.
749   if (Error E = GeneralLinker.link())
750     return error(toString(std::move(E)));
751 
752   StringRef ArchName = Map.getTriple().getArchName();
753   if (Error E = emitRemarks(Options, Map.getBinaryPath(), ArchName, RL))
754     return error(toString(std::move(E)));
755 
756   if (Options.NoOutput)
757     return true;
758 
759   if (Options.ResourceDir && !ParseableSwiftInterfaces.empty()) {
760     StringRef ArchName = Triple::getArchTypeName(Map.getTriple().getArch());
761     if (auto E =
762             copySwiftInterfaces(ParseableSwiftInterfaces, ArchName, Options))
763       return error(toString(std::move(E)));
764   }
765 
766   if (Map.getTriple().isOSDarwin() && !Map.getBinaryPath().empty() &&
767       Options.FileType == OutputFileType::Object)
768     return MachOUtils::generateDsymCompanion(
769         Options.VFS, Map, Options.Translator,
770         *Streamer->getAsmPrinter().OutStreamer, OutFile, RelocationsToApply);
771 
772   Streamer->finish();
773   return true;
774 }
775 
776 /// Iterate over the relocations of the given \p Section and
777 /// store the ones that correspond to debug map entries into the
778 /// ValidRelocs array.
findValidRelocsMachO(const object::SectionRef & Section,const object::MachOObjectFile & Obj,const DebugMapObject & DMO,std::vector<ValidReloc> & ValidRelocs)779 void DwarfLinkerForBinary::AddressManager::findValidRelocsMachO(
780     const object::SectionRef &Section, const object::MachOObjectFile &Obj,
781     const DebugMapObject &DMO, std::vector<ValidReloc> &ValidRelocs) {
782   Expected<StringRef> ContentsOrErr = Section.getContents();
783   if (!ContentsOrErr) {
784     consumeError(ContentsOrErr.takeError());
785     Linker.reportWarning("error reading section", DMO.getObjectFilename());
786     return;
787   }
788   DataExtractor Data(*ContentsOrErr, Obj.isLittleEndian(), 0);
789   bool SkipNext = false;
790 
791   for (const object::RelocationRef &Reloc : Section.relocations()) {
792     if (SkipNext) {
793       SkipNext = false;
794       continue;
795     }
796 
797     object::DataRefImpl RelocDataRef = Reloc.getRawDataRefImpl();
798     MachO::any_relocation_info MachOReloc = Obj.getRelocation(RelocDataRef);
799 
800     if (object::MachOObjectFile::isMachOPairedReloc(Obj.getAnyRelocationType(MachOReloc),
801                            Obj.getArch())) {
802       SkipNext = true;
803       Linker.reportWarning("unsupported relocation in " + *Section.getName() +
804                                " section.",
805                            DMO.getObjectFilename());
806       continue;
807     }
808 
809     unsigned RelocSize = 1 << Obj.getAnyRelocationLength(MachOReloc);
810     uint64_t Offset64 = Reloc.getOffset();
811     if ((RelocSize != 4 && RelocSize != 8)) {
812       Linker.reportWarning("unsupported relocation in " + *Section.getName() +
813                                " section.",
814                            DMO.getObjectFilename());
815       continue;
816     }
817     uint64_t OffsetCopy = Offset64;
818     // Mach-o uses REL relocations, the addend is at the relocation offset.
819     uint64_t Addend = Data.getUnsigned(&OffsetCopy, RelocSize);
820     uint64_t SymAddress;
821     int64_t SymOffset;
822 
823     if (Obj.isRelocationScattered(MachOReloc)) {
824       // The address of the base symbol for scattered relocations is
825       // stored in the reloc itself. The actual addend will store the
826       // base address plus the offset.
827       SymAddress = Obj.getScatteredRelocationValue(MachOReloc);
828       SymOffset = int64_t(Addend) - SymAddress;
829     } else {
830       SymAddress = Addend;
831       SymOffset = 0;
832     }
833 
834     auto Sym = Reloc.getSymbol();
835     if (Sym != Obj.symbol_end()) {
836       Expected<StringRef> SymbolName = Sym->getName();
837       if (!SymbolName) {
838         consumeError(SymbolName.takeError());
839         Linker.reportWarning("error getting relocation symbol name.",
840                              DMO.getObjectFilename());
841         continue;
842       }
843       if (const auto *Mapping = DMO.lookupSymbol(*SymbolName))
844         ValidRelocs.emplace_back(Offset64, RelocSize, Addend, Mapping);
845     } else if (const auto *Mapping = DMO.lookupObjectAddress(SymAddress)) {
846       // Do not store the addend. The addend was the address of the symbol in
847       // the object file, the address in the binary that is stored in the debug
848       // map doesn't need to be offset.
849       ValidRelocs.emplace_back(Offset64, RelocSize, SymOffset, Mapping);
850     }
851   }
852 }
853 
854 /// Dispatch the valid relocation finding logic to the
855 /// appropriate handler depending on the object file format.
findValidRelocs(const object::SectionRef & Section,const object::ObjectFile & Obj,const DebugMapObject & DMO,std::vector<ValidReloc> & Relocs)856 bool DwarfLinkerForBinary::AddressManager::findValidRelocs(
857     const object::SectionRef &Section, const object::ObjectFile &Obj,
858     const DebugMapObject &DMO, std::vector<ValidReloc> &Relocs) {
859   // Dispatch to the right handler depending on the file type.
860   if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(&Obj))
861     findValidRelocsMachO(Section, *MachOObj, DMO, Relocs);
862   else
863     Linker.reportWarning(Twine("unsupported object file type: ") +
864                              Obj.getFileName(),
865                          DMO.getObjectFilename());
866   if (Relocs.empty())
867     return false;
868 
869   // Sort the relocations by offset. We will walk the DIEs linearly in
870   // the file, this allows us to just keep an index in the relocation
871   // array that we advance during our walk, rather than resorting to
872   // some associative container. See DwarfLinkerForBinary::NextValidReloc.
873   llvm::sort(Relocs);
874   return true;
875 }
876 
877 /// Look for relocations in the debug_info and debug_addr section that match
878 /// entries in the debug map. These relocations will drive the Dwarf link by
879 /// indicating which DIEs refer to symbols present in the linked binary.
880 /// \returns whether there are any valid relocations in the debug info.
findValidRelocsInDebugSections(const object::ObjectFile & Obj,const DebugMapObject & DMO)881 bool DwarfLinkerForBinary::AddressManager::findValidRelocsInDebugSections(
882     const object::ObjectFile &Obj, const DebugMapObject &DMO) {
883   // Find the debug_info section.
884   bool FoundValidRelocs = false;
885   for (const object::SectionRef &Section : Obj.sections()) {
886     StringRef SectionName;
887     if (Expected<StringRef> NameOrErr = Section.getName())
888       SectionName = *NameOrErr;
889     else
890       consumeError(NameOrErr.takeError());
891 
892     SectionName = SectionName.substr(SectionName.find_first_not_of("._"));
893     if (SectionName == "debug_info")
894       FoundValidRelocs |=
895           findValidRelocs(Section, Obj, DMO, ValidDebugInfoRelocs);
896     if (SectionName == "debug_addr")
897       FoundValidRelocs |=
898           findValidRelocs(Section, Obj, DMO, ValidDebugAddrRelocs);
899   }
900   return FoundValidRelocs;
901 }
902 
903 std::vector<DwarfLinkerForBinary::AddressManager::ValidReloc>
getRelocations(const std::vector<ValidReloc> & Relocs,uint64_t StartPos,uint64_t EndPos)904 DwarfLinkerForBinary::AddressManager::getRelocations(
905     const std::vector<ValidReloc> &Relocs, uint64_t StartPos, uint64_t EndPos) {
906   std::vector<DwarfLinkerForBinary::AddressManager::ValidReloc> Res;
907 
908   auto CurReloc = partition_point(Relocs, [StartPos](const ValidReloc &Reloc) {
909     return Reloc.Offset < StartPos;
910   });
911 
912   while (CurReloc != Relocs.end() && CurReloc->Offset >= StartPos &&
913          CurReloc->Offset < EndPos) {
914     Res.push_back(*CurReloc);
915     CurReloc++;
916   }
917 
918   return Res;
919 }
920 
printReloc(const ValidReloc & Reloc)921 void DwarfLinkerForBinary::AddressManager::printReloc(const ValidReloc &Reloc) {
922   const auto &Mapping = Reloc.Mapping->getValue();
923   const uint64_t ObjectAddress = Mapping.ObjectAddress
924                                      ? uint64_t(*Mapping.ObjectAddress)
925                                      : std::numeric_limits<uint64_t>::max();
926 
927   outs() << "Found valid debug map entry: " << Reloc.Mapping->getKey() << "\t"
928          << format("0x%016" PRIx64 " => 0x%016" PRIx64 "\n", ObjectAddress,
929                    uint64_t(Mapping.BinaryAddress));
930 }
931 
fillDieInfo(const ValidReloc & Reloc,CompileUnit::DIEInfo & Info)932 void DwarfLinkerForBinary::AddressManager::fillDieInfo(
933     const ValidReloc &Reloc, CompileUnit::DIEInfo &Info) {
934   Info.AddrAdjust = relocate(Reloc);
935   if (Reloc.Mapping->getValue().ObjectAddress)
936     Info.AddrAdjust -= uint64_t(*Reloc.Mapping->getValue().ObjectAddress);
937   Info.InDebugMap = true;
938 }
939 
hasValidRelocationAt(const std::vector<ValidReloc> & AllRelocs,uint64_t StartOffset,uint64_t EndOffset,CompileUnit::DIEInfo & Info)940 bool DwarfLinkerForBinary::AddressManager::hasValidRelocationAt(
941     const std::vector<ValidReloc> &AllRelocs, uint64_t StartOffset,
942     uint64_t EndOffset, CompileUnit::DIEInfo &Info) {
943   std::vector<ValidReloc> Relocs =
944       getRelocations(AllRelocs, StartOffset, EndOffset);
945 
946   if (Relocs.size() == 0)
947     return false;
948 
949   if (Linker.Options.Verbose)
950     printReloc(Relocs[0]);
951   fillDieInfo(Relocs[0], Info);
952 
953   return true;
954 }
955 
956 /// Get the starting and ending (exclusive) offset for the
957 /// attribute with index \p Idx descibed by \p Abbrev. \p Offset is
958 /// supposed to point to the position of the first attribute described
959 /// by \p Abbrev.
960 /// \return [StartOffset, EndOffset) as a pair.
961 static std::pair<uint64_t, uint64_t>
getAttributeOffsets(const DWARFAbbreviationDeclaration * Abbrev,unsigned Idx,uint64_t Offset,const DWARFUnit & Unit)962 getAttributeOffsets(const DWARFAbbreviationDeclaration *Abbrev, unsigned Idx,
963                     uint64_t Offset, const DWARFUnit &Unit) {
964   DataExtractor Data = Unit.getDebugInfoExtractor();
965 
966   for (unsigned I = 0; I < Idx; ++I)
967     DWARFFormValue::skipValue(Abbrev->getFormByIndex(I), Data, &Offset,
968                               Unit.getFormParams());
969 
970   uint64_t End = Offset;
971   DWARFFormValue::skipValue(Abbrev->getFormByIndex(Idx), Data, &End,
972                             Unit.getFormParams());
973 
974   return std::make_pair(Offset, End);
975 }
976 
isLiveVariable(const DWARFDie & DIE,CompileUnit::DIEInfo & MyInfo)977 bool DwarfLinkerForBinary::AddressManager::isLiveVariable(
978     const DWARFDie &DIE, CompileUnit::DIEInfo &MyInfo) {
979   const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
980 
981   std::optional<uint32_t> LocationIdx =
982       Abbrev->findAttributeIndex(dwarf::DW_AT_location);
983   if (!LocationIdx)
984     return false;
985 
986   uint64_t Offset = DIE.getOffset() + getULEB128Size(Abbrev->getCode());
987   uint64_t LocationOffset, LocationEndOffset;
988   std::tie(LocationOffset, LocationEndOffset) =
989       getAttributeOffsets(Abbrev, *LocationIdx, Offset, *DIE.getDwarfUnit());
990 
991   // FIXME: Support relocations debug_addr.
992   return hasValidRelocationAt(ValidDebugInfoRelocs, LocationOffset,
993                               LocationEndOffset, MyInfo);
994 }
995 
isLiveSubprogram(const DWARFDie & DIE,CompileUnit::DIEInfo & MyInfo)996 bool DwarfLinkerForBinary::AddressManager::isLiveSubprogram(
997     const DWARFDie &DIE, CompileUnit::DIEInfo &MyInfo) {
998   const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
999 
1000   std::optional<uint32_t> LowPcIdx =
1001       Abbrev->findAttributeIndex(dwarf::DW_AT_low_pc);
1002   if (!LowPcIdx)
1003     return false;
1004 
1005   dwarf::Form Form = Abbrev->getFormByIndex(*LowPcIdx);
1006 
1007   if (Form == dwarf::DW_FORM_addr) {
1008     uint64_t Offset = DIE.getOffset() + getULEB128Size(Abbrev->getCode());
1009     uint64_t LowPcOffset, LowPcEndOffset;
1010     std::tie(LowPcOffset, LowPcEndOffset) =
1011         getAttributeOffsets(Abbrev, *LowPcIdx, Offset, *DIE.getDwarfUnit());
1012     return hasValidRelocationAt(ValidDebugInfoRelocs, LowPcOffset,
1013                                 LowPcEndOffset, MyInfo);
1014   }
1015 
1016   if (Form == dwarf::DW_FORM_addrx) {
1017     std::optional<DWARFFormValue> AddrValue = DIE.find(dwarf::DW_AT_low_pc);
1018     if (std::optional<uint64_t> AddrOffsetSectionBase =
1019             DIE.getDwarfUnit()->getAddrOffsetSectionBase()) {
1020       uint64_t StartOffset = *AddrOffsetSectionBase + AddrValue->getRawUValue();
1021       uint64_t EndOffset =
1022           StartOffset + DIE.getDwarfUnit()->getAddressByteSize();
1023       return hasValidRelocationAt(ValidDebugAddrRelocs, StartOffset, EndOffset,
1024                                   MyInfo);
1025     } else
1026       Linker.reportWarning("no base offset for address table", SrcFileName);
1027   }
1028 
1029   return false;
1030 }
1031 
1032 uint64_t
relocate(const ValidReloc & Reloc) const1033 DwarfLinkerForBinary::AddressManager::relocate(const ValidReloc &Reloc) const {
1034   return Reloc.Mapping->getValue().BinaryAddress + Reloc.Addend;
1035 }
1036 
1037 /// Apply the valid relocations found by findValidRelocs() to
1038 /// the buffer \p Data, taking into account that Data is at \p BaseOffset
1039 /// in the debug_info section.
1040 ///
1041 /// Like for findValidRelocs(), this function must be called with
1042 /// monotonic \p BaseOffset values.
1043 ///
1044 /// \returns whether any reloc has been applied.
applyValidRelocs(MutableArrayRef<char> Data,uint64_t BaseOffset,bool IsLittleEndian)1045 bool DwarfLinkerForBinary::AddressManager::applyValidRelocs(
1046     MutableArrayRef<char> Data, uint64_t BaseOffset, bool IsLittleEndian) {
1047   std::vector<ValidReloc> Relocs = getRelocations(
1048       ValidDebugInfoRelocs, BaseOffset, BaseOffset + Data.size());
1049 
1050   for (const ValidReloc &CurReloc : Relocs) {
1051     assert(CurReloc.Offset - BaseOffset < Data.size());
1052     assert(CurReloc.Offset - BaseOffset + CurReloc.Size <= Data.size());
1053     char Buf[8];
1054     uint64_t Value = relocate(CurReloc);
1055     for (unsigned I = 0; I != CurReloc.Size; ++I) {
1056       unsigned Index = IsLittleEndian ? I : (CurReloc.Size - I - 1);
1057       Buf[I] = uint8_t(Value >> (Index * 8));
1058     }
1059     assert(CurReloc.Size <= sizeof(Buf));
1060     memcpy(&Data[CurReloc.Offset - BaseOffset], Buf, CurReloc.Size);
1061   }
1062 
1063   return Relocs.size() > 0;
1064 }
1065 
1066 llvm::Expected<uint64_t>
relocateIndexedAddr(uint64_t StartOffset,uint64_t EndOffset)1067 DwarfLinkerForBinary::AddressManager::relocateIndexedAddr(uint64_t StartOffset,
1068                                                           uint64_t EndOffset) {
1069   std::vector<ValidReloc> Relocs =
1070       getRelocations(ValidDebugAddrRelocs, StartOffset, EndOffset);
1071   if (Relocs.size() == 0)
1072     return createStringError(
1073         std::make_error_code(std::errc::invalid_argument),
1074         "no relocation for offset %llu in debug_addr section", StartOffset);
1075 
1076   return relocate(Relocs[0]);
1077 }
1078 
linkDwarf(raw_fd_ostream & OutFile,BinaryHolder & BinHolder,const DebugMap & DM,LinkOptions Options)1079 bool linkDwarf(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
1080                const DebugMap &DM, LinkOptions Options) {
1081   DwarfLinkerForBinary Linker(OutFile, BinHolder, std::move(Options));
1082   return Linker.link(DM);
1083 }
1084 
1085 } // namespace dsymutil
1086 } // namespace llvm
1087