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