[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / llvm / tools / dsymutil / DwarfLinkerForBinary.cpp
blob5f43680ba498438baa5efab6b3ad78ac432da72b
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 //===----------------------------------------------------------------------===//
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>
103 namespace llvm {
105 static mc::RegisterMCTargetOptionsFlags MOF;
107 namespace dsymutil {
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();
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;
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';
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);
142 return Error::success();
145 /// Report a warning to the user, optionally including information about a
146 /// specific \p DIE related to the warning.
147 void DwarfLinkerForBinary::reportWarning(const Twine &Warning,
148 StringRef Context,
149 const DWARFDie *DIE) const {
151 warn(Warning, Context);
153 if (!Options.Verbose || !DIE)
154 return;
156 DIDumpOptions DumpOpts;
157 DumpOpts.ChildRecurseDepth = 0;
158 DumpOpts.Verbose = Options.Verbose;
160 WithColor::note() << " in DIE:\n";
161 DIE->dump(errs(), 6 /* Indent */, DumpOpts);
164 bool DwarfLinkerForBinary::createStreamer(const Triple &TheTriple,
165 raw_fd_ostream &OutFile) {
166 if (Options.NoOutput)
167 return true;
169 Streamer = std::make_unique<DwarfStreamer>(
170 Options.FileType, OutFile, Options.Translator,
171 [&](const Twine &Error, StringRef Context, const DWARFDie *) {
172 error(Error, Context);
174 [&](const Twine &Warning, StringRef Context, const DWARFDie *) {
175 warn(Warning, Context);
177 return Streamer->init(TheTriple, "__DWARF");
180 ErrorOr<const object::ObjectFile &>
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));
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));
202 return *Object;
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));
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));
220 Linker.reportWarning(Message, DMO.getObjectFilename());
221 return Error(Error::success());
224 if (!NewE)
225 return Error::success();
227 return createFileError(FE->getFileName(), std::move(NewE));
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();
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);
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;
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);
262 if (Error E = RL.serialize(OS, Options.RemarksFormat))
263 return E;
265 return Error::success();
268 ErrorOr<DWARFFile &>
269 DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj,
270 const DebugMap &DebugMap,
271 remarks::RemarkLinker &RL) {
272 auto ErrorOrObj = loadObject(Obj, DebugMap.getTriple());
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));
280 ObjectsForLinking.push_back(std::make_unique<DWARFFile>(
281 Obj.getObjectFilename(), ContextForLinking.back().get(),
282 AddressMapForLinking.back().get(),
283 Obj.empty() ? Obj.getWarnings() : EmptyWarnings));
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));
290 return errorToErrorCode(std::move(NewE));
292 return *ObjectsForLinking.back();
295 return ErrorOrObj.getError();
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) {
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;
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;
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;
330 NameOrErr->consume_back("__TEXT");
331 auto ReflectionSectionKind =
332 Object->mapReflectionSectionNameToEnumValue(*NameOrErr);
333 if (Object->isReflectionSectionStrippable(ReflectionSectionKind)) {
334 return true;
338 return false;
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>
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;
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;
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;
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);
389 return SectionToOffset;
392 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);
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;
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 {};
424 if ((*Section)->getObject()->section_end() == *Section)
425 return {};
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);
435 int64_t SectionStartInLinkedBinary =
436 SectionToOffsetInDwarf[ReflSectionKind];
438 auto Addr = SectionStartInLinkedBinary + SymbolAddressInSection;
439 return Addr;
442 // The first symbol should always be in the section we're currently
443 // iterating over.
444 auto FirstSymbolAddress = CalculateAddressOfSymbolInDwarfSegment();
445 ++It;
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;
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();
475 if (!FirstSymbolAddress || !SecondSymbolAddress)
476 continue;
478 auto SectionName = Section.getName();
479 if (!SectionName)
480 continue;
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);
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;
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;
519 NameOrErr->consume_back("__TEXT");
520 auto ReflSectionKind =
521 MO->mapReflectionSectionNameToEnumValue(*NameOrErr);
522 if (MO->isReflectionSectionStrippable(ReflSectionKind))
523 SwiftSections[ReflSectionKind] = Section;
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());
552 bool DwarfLinkerForBinary::link(const DebugMap &Map) {
553 if (!createStreamer(Map.getTriple(), OutFile))
554 return false;
556 ObjectsForLinking.clear();
557 ContextForLinking.clear();
558 AddressMapForLinking.clear();
560 DebugMap DebugMap(Map.getTriple(), Map.getBinaryPath());
562 DWARFLinker GeneralLinker(Streamer.get(), DwarfLinkerClient::Dsymutil);
564 remarks::RemarkLinker RL;
565 if (!Options.RemarksPrependPath.empty())
566 RL.setExternalFilePrependPath(Options.RemarksPrependPath);
567 GeneralLinker.setObjectPrefixMap(&Options.ObjectPrefixMap);
569 std::function<StringRef(StringRef)> TranslationLambda = [&](StringRef Input) {
570 assert(Options.Translator);
571 return Options.Translator(Input);
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);
590 GeneralLinker.setErrorHandler(
591 [&](const Twine &Error, StringRef Context, const DWARFDie *) {
592 error(Error, Context);
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);
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(")");
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;
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;
641 return ErrorOrObj.getError();
644 llvm_unreachable("Unhandled DebugMap object");
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);
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);
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";
671 StringRef File = Obj->getObjectFilename();
672 auto ErrorOrMem = MemoryBuffer::getFile(File);
673 if (!ErrorOrMem) {
674 warn("Could not open '" + File + "'\n");
675 continue;
677 sys::fs::file_status Stat;
678 if (auto Err = sys::fs::status(File, Stat)) {
679 warn(Err.message());
680 continue;
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;
699 // Copy the module into the .swift_ast section.
700 if (!Options.NoOutput)
701 Streamer->emitSwiftAST((*ErrorOrMem)->getBuffer());
703 continue;
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());
715 // link debug info for loaded object files.
716 if (Error E = GeneralLinker.link())
717 return error(toString(std::move(E)));
719 StringRef ArchName = Map.getTriple().getArchName();
720 if (Error E = emitRemarks(Options, Map.getBinaryPath(), ArchName, RL))
721 return error(toString(std::move(E)));
723 if (Options.NoOutput)
724 return true;
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)));
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);
739 Streamer->finish();
740 return true;
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.
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;
755 DataExtractor Data(*ContentsOrErr, Obj.isLittleEndian(), 0);
756 bool SkipNext = false;
758 for (const object::RelocationRef &Reloc : Section.relocations()) {
759 if (SkipNext) {
760 SkipNext = false;
761 continue;
764 object::DataRefImpl RelocDataRef = Reloc.getRawDataRefImpl();
765 MachO::any_relocation_info MachOReloc = Obj.getRelocation(RelocDataRef);
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;
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;
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;
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;
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;
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);
821 /// Dispatch the valid relocation finding logic to the
822 /// appropriate handler depending on the object file format.
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;
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;
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.
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());
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);
867 return FoundValidRelocs;
870 std::vector<DwarfLinkerForBinary::AddressManager::ValidReloc>
871 DwarfLinkerForBinary::AddressManager::getRelocations(
872 const std::vector<ValidReloc> &Relocs, uint64_t StartPos, uint64_t EndPos) {
873 std::vector<DwarfLinkerForBinary::AddressManager::ValidReloc> Res;
875 auto CurReloc = partition_point(Relocs, [StartPos](const ValidReloc &Reloc) {
876 return Reloc.Offset < StartPos;
879 while (CurReloc != Relocs.end() && CurReloc->Offset >= StartPos &&
880 CurReloc->Offset < EndPos) {
881 Res.push_back(*CurReloc);
882 CurReloc++;
885 return Res;
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();
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));
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;
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);
913 if (Relocs.size() == 0)
914 return false;
916 if (Linker.Options.Verbose)
917 printReloc(Relocs[0]);
918 fillDieInfo(Relocs[0], Info);
920 return true;
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>
929 getAttributeOffsets(const DWARFAbbreviationDeclaration *Abbrev, unsigned Idx,
930 uint64_t Offset, const DWARFUnit &Unit) {
931 DataExtractor Data = Unit.getDebugInfoExtractor();
933 for (unsigned I = 0; I < Idx; ++I)
934 DWARFFormValue::skipValue(Abbrev->getFormByIndex(I), Data, &Offset,
935 Unit.getFormParams());
937 uint64_t End = Offset;
938 DWARFFormValue::skipValue(Abbrev->getFormByIndex(Idx), Data, &End,
939 Unit.getFormParams());
941 return std::make_pair(Offset, End);
944 bool DwarfLinkerForBinary::AddressManager::isLiveVariable(
945 const DWARFDie &DIE, CompileUnit::DIEInfo &MyInfo) {
946 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
948 Optional<uint32_t> LocationIdx =
949 Abbrev->findAttributeIndex(dwarf::DW_AT_location);
950 if (!LocationIdx)
951 return false;
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());
958 // FIXME: Support relocations debug_addr.
959 return hasValidRelocationAt(ValidDebugInfoRelocs, LocationOffset,
960 LocationEndOffset, MyInfo);
963 bool DwarfLinkerForBinary::AddressManager::isLiveSubprogram(
964 const DWARFDie &DIE, CompileUnit::DIEInfo &MyInfo) {
965 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
967 Optional<uint32_t> LowPcIdx = Abbrev->findAttributeIndex(dwarf::DW_AT_low_pc);
968 if (!LowPcIdx)
969 return false;
971 dwarf::Form Form = Abbrev->getFormByIndex(*LowPcIdx);
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);
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);
995 return false;
998 uint64_t
999 DwarfLinkerForBinary::AddressManager::relocate(const ValidReloc &Reloc) const {
1000 return Reloc.Mapping->getValue().BinaryAddress + Reloc.Addend;
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.
1007 /// Like for findValidRelocs(), this function must be called with
1008 /// monotonic \p BaseOffset values.
1010 /// \returns whether any reloc has been applied.
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());
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));
1025 assert(CurReloc.Size <= sizeof(Buf));
1026 memcpy(&Data[CurReloc.Offset - BaseOffset], Buf, CurReloc.Size);
1029 return Relocs.size() > 0;
1032 llvm::Expected<uint64_t>
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);
1042 return relocate(Relocs[0]);
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);
1051 } // namespace dsymutil
1052 } // namespace llvm