xref: /openbsd-src/gnu/llvm/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp (revision 73471bf04ceb096474c7f0fa83b1b65c70a787a1)
109467b48Spatrick //===- tools/dsymutil/DwarfLinkerForBinary.cpp ----------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick 
909467b48Spatrick #include "DwarfLinkerForBinary.h"
1009467b48Spatrick #include "BinaryHolder.h"
1109467b48Spatrick #include "DebugMap.h"
1209467b48Spatrick #include "MachOUtils.h"
1309467b48Spatrick #include "dsymutil.h"
1409467b48Spatrick #include "llvm/ADT/ArrayRef.h"
1509467b48Spatrick #include "llvm/ADT/BitVector.h"
1609467b48Spatrick #include "llvm/ADT/DenseMap.h"
1709467b48Spatrick #include "llvm/ADT/DenseMapInfo.h"
1809467b48Spatrick #include "llvm/ADT/DenseSet.h"
1909467b48Spatrick #include "llvm/ADT/FoldingSet.h"
2009467b48Spatrick #include "llvm/ADT/Hashing.h"
2109467b48Spatrick #include "llvm/ADT/IntervalMap.h"
2209467b48Spatrick #include "llvm/ADT/None.h"
2309467b48Spatrick #include "llvm/ADT/Optional.h"
2409467b48Spatrick #include "llvm/ADT/PointerIntPair.h"
2509467b48Spatrick #include "llvm/ADT/STLExtras.h"
2609467b48Spatrick #include "llvm/ADT/SmallString.h"
2709467b48Spatrick #include "llvm/ADT/StringMap.h"
2809467b48Spatrick #include "llvm/ADT/StringRef.h"
2909467b48Spatrick #include "llvm/ADT/Triple.h"
3009467b48Spatrick #include "llvm/ADT/Twine.h"
3109467b48Spatrick #include "llvm/BinaryFormat/Dwarf.h"
3209467b48Spatrick #include "llvm/BinaryFormat/MachO.h"
3309467b48Spatrick #include "llvm/CodeGen/AccelTable.h"
3409467b48Spatrick #include "llvm/CodeGen/AsmPrinter.h"
3509467b48Spatrick #include "llvm/CodeGen/DIE.h"
3609467b48Spatrick #include "llvm/CodeGen/NonRelocatableStringpool.h"
3709467b48Spatrick #include "llvm/Config/config.h"
3809467b48Spatrick #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
3909467b48Spatrick #include "llvm/DebugInfo/DIContext.h"
4009467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
4109467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFContext.h"
4209467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
4309467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
4409467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
4509467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDie.h"
4609467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
4709467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFSection.h"
4809467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
4909467b48Spatrick #include "llvm/MC/MCAsmBackend.h"
5009467b48Spatrick #include "llvm/MC/MCAsmInfo.h"
5109467b48Spatrick #include "llvm/MC/MCCodeEmitter.h"
5209467b48Spatrick #include "llvm/MC/MCContext.h"
5309467b48Spatrick #include "llvm/MC/MCDwarf.h"
5409467b48Spatrick #include "llvm/MC/MCInstrInfo.h"
5509467b48Spatrick #include "llvm/MC/MCObjectFileInfo.h"
5609467b48Spatrick #include "llvm/MC/MCObjectWriter.h"
5709467b48Spatrick #include "llvm/MC/MCRegisterInfo.h"
5809467b48Spatrick #include "llvm/MC/MCSection.h"
5909467b48Spatrick #include "llvm/MC/MCStreamer.h"
6009467b48Spatrick #include "llvm/MC/MCSubtargetInfo.h"
6109467b48Spatrick #include "llvm/MC/MCTargetOptions.h"
6209467b48Spatrick #include "llvm/Object/MachO.h"
6309467b48Spatrick #include "llvm/Object/ObjectFile.h"
6409467b48Spatrick #include "llvm/Object/SymbolicFile.h"
6509467b48Spatrick #include "llvm/Support/Allocator.h"
6609467b48Spatrick #include "llvm/Support/Casting.h"
6709467b48Spatrick #include "llvm/Support/Compiler.h"
6809467b48Spatrick #include "llvm/Support/DJB.h"
6909467b48Spatrick #include "llvm/Support/DataExtractor.h"
7009467b48Spatrick #include "llvm/Support/Error.h"
7109467b48Spatrick #include "llvm/Support/ErrorHandling.h"
7209467b48Spatrick #include "llvm/Support/ErrorOr.h"
7309467b48Spatrick #include "llvm/Support/FileSystem.h"
7409467b48Spatrick #include "llvm/Support/Format.h"
7509467b48Spatrick #include "llvm/Support/LEB128.h"
7609467b48Spatrick #include "llvm/Support/MathExtras.h"
7709467b48Spatrick #include "llvm/Support/MemoryBuffer.h"
7809467b48Spatrick #include "llvm/Support/Path.h"
7909467b48Spatrick #include "llvm/Support/TargetRegistry.h"
8009467b48Spatrick #include "llvm/Support/ThreadPool.h"
8109467b48Spatrick #include "llvm/Support/ToolOutputFile.h"
8209467b48Spatrick #include "llvm/Support/WithColor.h"
8309467b48Spatrick #include "llvm/Support/raw_ostream.h"
8409467b48Spatrick #include "llvm/Target/TargetMachine.h"
8509467b48Spatrick #include "llvm/Target/TargetOptions.h"
86097a140dSpatrick #include "llvm/MC/MCTargetOptionsCommandFlags.h"
8709467b48Spatrick #include <algorithm>
8809467b48Spatrick #include <cassert>
8909467b48Spatrick #include <cinttypes>
9009467b48Spatrick #include <climits>
9109467b48Spatrick #include <cstdint>
9209467b48Spatrick #include <cstdlib>
9309467b48Spatrick #include <cstring>
9409467b48Spatrick #include <limits>
9509467b48Spatrick #include <map>
9609467b48Spatrick #include <memory>
9709467b48Spatrick #include <string>
9809467b48Spatrick #include <system_error>
9909467b48Spatrick #include <tuple>
10009467b48Spatrick #include <utility>
10109467b48Spatrick #include <vector>
10209467b48Spatrick 
10309467b48Spatrick namespace llvm {
104097a140dSpatrick 
105097a140dSpatrick static mc::RegisterMCTargetOptionsFlags MOF;
106097a140dSpatrick 
10709467b48Spatrick namespace dsymutil {
10809467b48Spatrick 
10909467b48Spatrick static Error copySwiftInterfaces(
11009467b48Spatrick     const std::map<std::string, std::string> &ParseableSwiftInterfaces,
11109467b48Spatrick     StringRef Architecture, const LinkOptions &Options) {
11209467b48Spatrick   std::error_code EC;
11309467b48Spatrick   SmallString<128> InputPath;
11409467b48Spatrick   SmallString<128> Path;
11509467b48Spatrick   sys::path::append(Path, *Options.ResourceDir, "Swift", Architecture);
11609467b48Spatrick   if ((EC = sys::fs::create_directories(Path.str(), true,
11709467b48Spatrick                                         sys::fs::perms::all_all)))
11809467b48Spatrick     return make_error<StringError>(
11909467b48Spatrick         "cannot create directory: " + toString(errorCodeToError(EC)), EC);
12009467b48Spatrick   unsigned BaseLength = Path.size();
12109467b48Spatrick 
12209467b48Spatrick   for (auto &I : ParseableSwiftInterfaces) {
12309467b48Spatrick     StringRef ModuleName = I.first;
12409467b48Spatrick     StringRef InterfaceFile = I.second;
12509467b48Spatrick     if (!Options.PrependPath.empty()) {
12609467b48Spatrick       InputPath.clear();
12709467b48Spatrick       sys::path::append(InputPath, Options.PrependPath, InterfaceFile);
12809467b48Spatrick       InterfaceFile = InputPath;
12909467b48Spatrick     }
13009467b48Spatrick     sys::path::append(Path, ModuleName);
13109467b48Spatrick     Path.append(".swiftinterface");
13209467b48Spatrick     if (Options.Verbose)
13309467b48Spatrick       outs() << "copy parseable Swift interface " << InterfaceFile << " -> "
13409467b48Spatrick              << Path.str() << '\n';
13509467b48Spatrick 
13609467b48Spatrick     // copy_file attempts an APFS clone first, so this should be cheap.
13709467b48Spatrick     if ((EC = sys::fs::copy_file(InterfaceFile, Path.str())))
13809467b48Spatrick       warn(Twine("cannot copy parseable Swift interface ") + InterfaceFile +
13909467b48Spatrick            ": " + toString(errorCodeToError(EC)));
14009467b48Spatrick     Path.resize(BaseLength);
14109467b48Spatrick   }
14209467b48Spatrick   return Error::success();
14309467b48Spatrick }
14409467b48Spatrick 
145097a140dSpatrick /// Report a warning to the user, optionally including information about a
146097a140dSpatrick /// specific \p DIE related to the warning.
147097a140dSpatrick void DwarfLinkerForBinary::reportWarning(const Twine &Warning,
148097a140dSpatrick                                          StringRef Context,
149097a140dSpatrick                                          const DWARFDie *DIE) const {
150097a140dSpatrick 
151097a140dSpatrick   warn(Warning, Context);
152097a140dSpatrick 
153097a140dSpatrick   if (!Options.Verbose || !DIE)
154097a140dSpatrick     return;
155097a140dSpatrick 
156097a140dSpatrick   DIDumpOptions DumpOpts;
157097a140dSpatrick   DumpOpts.ChildRecurseDepth = 0;
158097a140dSpatrick   DumpOpts.Verbose = Options.Verbose;
159097a140dSpatrick 
160097a140dSpatrick   WithColor::note() << "    in DIE:\n";
161097a140dSpatrick   DIE->dump(errs(), 6 /* Indent */, DumpOpts);
162097a140dSpatrick }
163097a140dSpatrick 
164097a140dSpatrick bool DwarfLinkerForBinary::createStreamer(const Triple &TheTriple,
165097a140dSpatrick                                           raw_fd_ostream &OutFile) {
166097a140dSpatrick   if (Options.NoOutput)
167097a140dSpatrick     return true;
168097a140dSpatrick 
169097a140dSpatrick   Streamer = std::make_unique<DwarfStreamer>(
170*73471bf0Spatrick       Options.FileType, OutFile, Options.Translator,
171097a140dSpatrick       [&](const Twine &Error, StringRef Context, const DWARFDie *) {
172097a140dSpatrick         error(Error, Context);
173097a140dSpatrick       },
174097a140dSpatrick       [&](const Twine &Warning, StringRef Context, const DWARFDie *) {
175097a140dSpatrick         warn(Warning, Context);
176097a140dSpatrick       });
177097a140dSpatrick   return Streamer->init(TheTriple);
178097a140dSpatrick }
179097a140dSpatrick 
180097a140dSpatrick ErrorOr<const object::ObjectFile &>
181097a140dSpatrick DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj,
182097a140dSpatrick                                  const Triple &Triple) {
183097a140dSpatrick   auto ObjectEntry =
184097a140dSpatrick       BinHolder.getObjectEntry(Obj.getObjectFilename(), Obj.getTimestamp());
185097a140dSpatrick   if (!ObjectEntry) {
186097a140dSpatrick     auto Err = ObjectEntry.takeError();
187097a140dSpatrick     reportWarning(Twine(Obj.getObjectFilename()) + ": " +
188097a140dSpatrick                       toString(std::move(Err)),
189097a140dSpatrick                   Obj.getObjectFilename());
190097a140dSpatrick     return errorToErrorCode(std::move(Err));
191097a140dSpatrick   }
192097a140dSpatrick 
193097a140dSpatrick   auto Object = ObjectEntry->getObject(Triple);
194097a140dSpatrick   if (!Object) {
195097a140dSpatrick     auto Err = Object.takeError();
196097a140dSpatrick     reportWarning(Twine(Obj.getObjectFilename()) + ": " +
197097a140dSpatrick                       toString(std::move(Err)),
198097a140dSpatrick                   Obj.getObjectFilename());
199097a140dSpatrick     return errorToErrorCode(std::move(Err));
200097a140dSpatrick   }
201097a140dSpatrick 
202097a140dSpatrick   return *Object;
203097a140dSpatrick }
204097a140dSpatrick 
205097a140dSpatrick static Error remarksErrorHandler(const DebugMapObject &DMO,
206097a140dSpatrick                                  DwarfLinkerForBinary &Linker,
207097a140dSpatrick                                  std::unique_ptr<FileError> FE) {
208097a140dSpatrick   bool IsArchive = DMO.getObjectFilename().endswith(")");
209097a140dSpatrick   // Don't report errors for missing remark files from static
210097a140dSpatrick   // archives.
211097a140dSpatrick   if (!IsArchive)
212097a140dSpatrick     return Error(std::move(FE));
213097a140dSpatrick 
214097a140dSpatrick   std::string Message = FE->message();
215097a140dSpatrick   Error E = FE->takeError();
216097a140dSpatrick   Error NewE = handleErrors(std::move(E), [&](std::unique_ptr<ECError> EC) {
217097a140dSpatrick     if (EC->convertToErrorCode() != std::errc::no_such_file_or_directory)
218097a140dSpatrick       return Error(std::move(EC));
219097a140dSpatrick 
220097a140dSpatrick     Linker.reportWarning(Message, DMO.getObjectFilename());
221097a140dSpatrick     return Error(Error::success());
222097a140dSpatrick   });
223097a140dSpatrick 
224097a140dSpatrick   if (!NewE)
225097a140dSpatrick     return Error::success();
226097a140dSpatrick 
227097a140dSpatrick   return createFileError(FE->getFileName(), std::move(NewE));
228097a140dSpatrick }
229097a140dSpatrick 
23009467b48Spatrick static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath,
23109467b48Spatrick                          StringRef ArchName, const remarks::RemarkLinker &RL) {
23209467b48Spatrick   // Make sure we don't create the directories and the file if there is nothing
23309467b48Spatrick   // to serialize.
23409467b48Spatrick   if (RL.empty())
23509467b48Spatrick     return Error::success();
23609467b48Spatrick 
23709467b48Spatrick   SmallString<128> InputPath;
23809467b48Spatrick   SmallString<128> Path;
23909467b48Spatrick   // Create the "Remarks" directory in the "Resources" directory.
24009467b48Spatrick   sys::path::append(Path, *Options.ResourceDir, "Remarks");
24109467b48Spatrick   if (std::error_code EC = sys::fs::create_directories(Path.str(), true,
24209467b48Spatrick                                                        sys::fs::perms::all_all))
24309467b48Spatrick     return errorCodeToError(EC);
24409467b48Spatrick 
24509467b48Spatrick   // Append the file name.
24609467b48Spatrick   // For fat binaries, also append a dash and the architecture name.
24709467b48Spatrick   sys::path::append(Path, sys::path::filename(BinaryPath));
24809467b48Spatrick   if (Options.NumDebugMaps > 1) {
24909467b48Spatrick     // More than one debug map means we have a fat binary.
25009467b48Spatrick     Path += '-';
25109467b48Spatrick     Path += ArchName;
25209467b48Spatrick   }
25309467b48Spatrick 
25409467b48Spatrick   std::error_code EC;
255*73471bf0Spatrick   raw_fd_ostream OS(Options.NoOutput ? "-" : Path.str(), EC,
256*73471bf0Spatrick                     Options.RemarksFormat == remarks::Format::Bitstream
257*73471bf0Spatrick                         ? sys::fs::OF_None
258*73471bf0Spatrick                         : sys::fs::OF_Text);
25909467b48Spatrick   if (EC)
26009467b48Spatrick     return errorCodeToError(EC);
26109467b48Spatrick 
26209467b48Spatrick   if (Error E = RL.serialize(OS, Options.RemarksFormat))
26309467b48Spatrick     return E;
26409467b48Spatrick 
26509467b48Spatrick   return Error::success();
26609467b48Spatrick }
26709467b48Spatrick 
268*73471bf0Spatrick ErrorOr<DWARFFile &>
269097a140dSpatrick DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj,
270097a140dSpatrick                                  const DebugMap &DebugMap,
271097a140dSpatrick                                  remarks::RemarkLinker &RL) {
272097a140dSpatrick   auto ErrorOrObj = loadObject(Obj, DebugMap.getTriple());
273097a140dSpatrick 
274097a140dSpatrick   if (ErrorOrObj) {
275097a140dSpatrick     ContextForLinking.push_back(
276097a140dSpatrick         std::unique_ptr<DWARFContext>(DWARFContext::create(*ErrorOrObj)));
277097a140dSpatrick     AddressMapForLinking.push_back(
278097a140dSpatrick         std::make_unique<AddressManager>(*this, *ErrorOrObj, Obj));
279097a140dSpatrick 
280*73471bf0Spatrick     ObjectsForLinking.push_back(std::make_unique<DWARFFile>(
281097a140dSpatrick         Obj.getObjectFilename(), ContextForLinking.back().get(),
282097a140dSpatrick         AddressMapForLinking.back().get(),
283097a140dSpatrick         Obj.empty() ? Obj.getWarnings() : EmptyWarnings));
284097a140dSpatrick 
285097a140dSpatrick     Error E = RL.link(*ErrorOrObj);
286097a140dSpatrick     if (Error NewE = handleErrors(
287097a140dSpatrick             std::move(E), [&](std::unique_ptr<FileError> EC) -> Error {
288097a140dSpatrick               return remarksErrorHandler(Obj, *this, std::move(EC));
289097a140dSpatrick             }))
290097a140dSpatrick       return errorToErrorCode(std::move(NewE));
291097a140dSpatrick 
292097a140dSpatrick     return *ObjectsForLinking.back();
293097a140dSpatrick   }
294097a140dSpatrick 
295097a140dSpatrick   return ErrorOrObj.getError();
296097a140dSpatrick }
297097a140dSpatrick 
29809467b48Spatrick bool DwarfLinkerForBinary::link(const DebugMap &Map) {
29909467b48Spatrick   if (!createStreamer(Map.getTriple(), OutFile))
30009467b48Spatrick     return false;
30109467b48Spatrick 
302097a140dSpatrick   ObjectsForLinking.clear();
303097a140dSpatrick   ContextForLinking.clear();
304097a140dSpatrick   AddressMapForLinking.clear();
30509467b48Spatrick 
306097a140dSpatrick   DebugMap DebugMap(Map.getTriple(), Map.getBinaryPath());
307097a140dSpatrick 
308097a140dSpatrick   DWARFLinker GeneralLinker(Streamer.get(), DwarfLinkerClient::Dsymutil);
309097a140dSpatrick 
310097a140dSpatrick   remarks::RemarkLinker RL;
311097a140dSpatrick   if (!Options.RemarksPrependPath.empty())
312097a140dSpatrick     RL.setExternalFilePrependPath(Options.RemarksPrependPath);
313097a140dSpatrick   GeneralLinker.setObjectPrefixMap(&Options.ObjectPrefixMap);
314097a140dSpatrick 
315097a140dSpatrick   std::function<StringRef(StringRef)> TranslationLambda = [&](StringRef Input) {
316097a140dSpatrick     assert(Options.Translator);
317097a140dSpatrick     return Options.Translator(Input);
318097a140dSpatrick   };
319097a140dSpatrick 
320097a140dSpatrick   GeneralLinker.setVerbosity(Options.Verbose);
321097a140dSpatrick   GeneralLinker.setStatistics(Options.Statistics);
322097a140dSpatrick   GeneralLinker.setNoOutput(Options.NoOutput);
323097a140dSpatrick   GeneralLinker.setNoODR(Options.NoODR);
324097a140dSpatrick   GeneralLinker.setUpdate(Options.Update);
325097a140dSpatrick   GeneralLinker.setNumThreads(Options.Threads);
326097a140dSpatrick   GeneralLinker.setAccelTableKind(Options.TheAccelTableKind);
327097a140dSpatrick   GeneralLinker.setPrependPath(Options.PrependPath);
328*73471bf0Spatrick   GeneralLinker.setKeepFunctionForStatic(Options.KeepFunctionForStatic);
329097a140dSpatrick   if (Options.Translator)
330097a140dSpatrick     GeneralLinker.setStringsTranslator(TranslationLambda);
331097a140dSpatrick   GeneralLinker.setWarningHandler(
332097a140dSpatrick       [&](const Twine &Warning, StringRef Context, const DWARFDie *DIE) {
333097a140dSpatrick         reportWarning(Warning, Context, DIE);
334097a140dSpatrick       });
335097a140dSpatrick   GeneralLinker.setErrorHandler(
336097a140dSpatrick       [&](const Twine &Error, StringRef Context, const DWARFDie *) {
337097a140dSpatrick         error(Error, Context);
338097a140dSpatrick       });
339097a140dSpatrick   GeneralLinker.setObjFileLoader(
340097a140dSpatrick       [&DebugMap, &RL, this](StringRef ContainerName,
341*73471bf0Spatrick                              StringRef Path) -> ErrorOr<DWARFFile &> {
342097a140dSpatrick         auto &Obj = DebugMap.addDebugMapObject(
343097a140dSpatrick             Path, sys::TimePoint<std::chrono::seconds>(), MachO::N_OSO);
344097a140dSpatrick 
345097a140dSpatrick         if (auto ErrorOrObj = loadObject(Obj, DebugMap, RL)) {
346097a140dSpatrick           return *ErrorOrObj;
347097a140dSpatrick         } else {
348097a140dSpatrick           // Try and emit more helpful warnings by applying some heuristics.
349097a140dSpatrick           StringRef ObjFile = ContainerName;
350097a140dSpatrick           bool IsClangModule = sys::path::extension(Path).equals(".pcm");
351097a140dSpatrick           bool IsArchive = ObjFile.endswith(")");
352097a140dSpatrick 
353097a140dSpatrick           if (IsClangModule) {
354097a140dSpatrick             StringRef ModuleCacheDir = sys::path::parent_path(Path);
355097a140dSpatrick             if (sys::fs::exists(ModuleCacheDir)) {
356097a140dSpatrick               // If the module's parent directory exists, we assume that the
357097a140dSpatrick               // module cache has expired and was pruned by clang.  A more
358097a140dSpatrick               // adventurous dsymutil would invoke clang to rebuild the module
359097a140dSpatrick               // now.
360097a140dSpatrick               if (!ModuleCacheHintDisplayed) {
361097a140dSpatrick                 WithColor::note()
362097a140dSpatrick                     << "The clang module cache may have expired since "
363097a140dSpatrick                        "this object file was built. Rebuilding the "
364097a140dSpatrick                        "object file will rebuild the module cache.\n";
365097a140dSpatrick                 ModuleCacheHintDisplayed = true;
366097a140dSpatrick               }
367097a140dSpatrick             } else if (IsArchive) {
368097a140dSpatrick               // If the module cache directory doesn't exist at all and the
369097a140dSpatrick               // object file is inside a static library, we assume that the
370097a140dSpatrick               // static library was built on a different machine. We don't want
371097a140dSpatrick               // to discourage module debugging for convenience libraries within
372097a140dSpatrick               // a project though.
373097a140dSpatrick               if (!ArchiveHintDisplayed) {
374097a140dSpatrick                 WithColor::note()
375097a140dSpatrick                     << "Linking a static library that was built with "
376097a140dSpatrick                        "-gmodules, but the module cache was not found.  "
377097a140dSpatrick                        "Redistributable static libraries should never be "
378097a140dSpatrick                        "built with module debugging enabled.  The debug "
379097a140dSpatrick                        "experience will be degraded due to incomplete "
380097a140dSpatrick                        "debug information.\n";
381097a140dSpatrick                 ArchiveHintDisplayed = true;
382097a140dSpatrick               }
383097a140dSpatrick             }
384097a140dSpatrick           }
385097a140dSpatrick 
386097a140dSpatrick           return ErrorOrObj.getError();
387097a140dSpatrick         }
388097a140dSpatrick 
389097a140dSpatrick         llvm_unreachable("Unhandled DebugMap object");
390097a140dSpatrick       });
391097a140dSpatrick   GeneralLinker.setSwiftInterfacesMap(&ParseableSwiftInterfaces);
392097a140dSpatrick 
39309467b48Spatrick   for (const auto &Obj : Map.objects()) {
39409467b48Spatrick     // N_AST objects (swiftmodule files) should get dumped directly into the
39509467b48Spatrick     // appropriate DWARF section.
396097a140dSpatrick     if (Obj->getType() == MachO::N_AST) {
397097a140dSpatrick       if (Options.Verbose)
398097a140dSpatrick         outs() << "DEBUG MAP OBJECT: " << Obj->getObjectFilename() << "\n";
399097a140dSpatrick 
400097a140dSpatrick       StringRef File = Obj->getObjectFilename();
40109467b48Spatrick       auto ErrorOrMem = MemoryBuffer::getFile(File);
40209467b48Spatrick       if (!ErrorOrMem) {
40309467b48Spatrick         warn("Could not open '" + File + "'\n");
40409467b48Spatrick         continue;
40509467b48Spatrick       }
40609467b48Spatrick       sys::fs::file_status Stat;
40709467b48Spatrick       if (auto Err = sys::fs::status(File, Stat)) {
40809467b48Spatrick         warn(Err.message());
40909467b48Spatrick         continue;
41009467b48Spatrick       }
41109467b48Spatrick       if (!Options.NoTimestamp) {
41209467b48Spatrick         // The modification can have sub-second precision so we need to cast
41309467b48Spatrick         // away the extra precision that's not present in the debug map.
41409467b48Spatrick         auto ModificationTime =
41509467b48Spatrick             std::chrono::time_point_cast<std::chrono::seconds>(
41609467b48Spatrick                 Stat.getLastModificationTime());
417097a140dSpatrick         if (ModificationTime != Obj->getTimestamp()) {
41809467b48Spatrick           // Not using the helper here as we can easily stream TimePoint<>.
419*73471bf0Spatrick           WithColor::warning()
420*73471bf0Spatrick               << File << ": timestamp mismatch between swift interface file ("
421*73471bf0Spatrick               << sys::TimePoint<>(Obj->getTimestamp()) << ") and debug map ("
422*73471bf0Spatrick               << sys::TimePoint<>(Obj->getTimestamp()) << ")\n";
42309467b48Spatrick           continue;
42409467b48Spatrick         }
42509467b48Spatrick       }
42609467b48Spatrick 
42709467b48Spatrick       // Copy the module into the .swift_ast section.
42809467b48Spatrick       if (!Options.NoOutput)
42909467b48Spatrick         Streamer->emitSwiftAST((*ErrorOrMem)->getBuffer());
430097a140dSpatrick 
43109467b48Spatrick       continue;
43209467b48Spatrick     }
43309467b48Spatrick 
434097a140dSpatrick     if (auto ErrorOrObj = loadObject(*Obj, Map, RL))
435097a140dSpatrick       GeneralLinker.addObjectFile(*ErrorOrObj);
436097a140dSpatrick     else {
437*73471bf0Spatrick       ObjectsForLinking.push_back(std::make_unique<DWARFFile>(
438097a140dSpatrick           Obj->getObjectFilename(), nullptr, nullptr,
439097a140dSpatrick           Obj->empty() ? Obj->getWarnings() : EmptyWarnings));
440097a140dSpatrick       GeneralLinker.addObjectFile(*ObjectsForLinking.back());
44109467b48Spatrick     }
44209467b48Spatrick   }
44309467b48Spatrick 
444097a140dSpatrick   // link debug info for loaded object files.
445097a140dSpatrick   GeneralLinker.link();
44609467b48Spatrick 
44709467b48Spatrick   StringRef ArchName = Map.getTriple().getArchName();
448097a140dSpatrick   if (Error E = emitRemarks(Options, Map.getBinaryPath(), ArchName, RL))
44909467b48Spatrick     return error(toString(std::move(E)));
45009467b48Spatrick 
45109467b48Spatrick   if (Options.NoOutput)
45209467b48Spatrick     return true;
45309467b48Spatrick 
45409467b48Spatrick   if (Options.ResourceDir && !ParseableSwiftInterfaces.empty()) {
45509467b48Spatrick     StringRef ArchName = Triple::getArchTypeName(Map.getTriple().getArch());
45609467b48Spatrick     if (auto E =
45709467b48Spatrick             copySwiftInterfaces(ParseableSwiftInterfaces, ArchName, Options))
45809467b48Spatrick       return error(toString(std::move(E)));
45909467b48Spatrick   }
46009467b48Spatrick 
461097a140dSpatrick   if (Map.getTriple().isOSDarwin() && !Map.getBinaryPath().empty() &&
462097a140dSpatrick       Options.FileType == OutputFileType::Object)
463097a140dSpatrick     return MachOUtils::generateDsymCompanion(
464097a140dSpatrick         Options.VFS, Map, Options.Translator,
465097a140dSpatrick         *Streamer->getAsmPrinter().OutStreamer, OutFile);
466097a140dSpatrick 
467097a140dSpatrick   Streamer->finish();
468097a140dSpatrick   return true;
469097a140dSpatrick }
470097a140dSpatrick 
471097a140dSpatrick static bool isMachOPairedReloc(uint64_t RelocType, uint64_t Arch) {
472097a140dSpatrick   switch (Arch) {
473097a140dSpatrick   case Triple::x86:
474097a140dSpatrick     return RelocType == MachO::GENERIC_RELOC_SECTDIFF ||
475097a140dSpatrick            RelocType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF;
476097a140dSpatrick   case Triple::x86_64:
477097a140dSpatrick     return RelocType == MachO::X86_64_RELOC_SUBTRACTOR;
478097a140dSpatrick   case Triple::arm:
479097a140dSpatrick   case Triple::thumb:
480097a140dSpatrick     return RelocType == MachO::ARM_RELOC_SECTDIFF ||
481097a140dSpatrick            RelocType == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
482097a140dSpatrick            RelocType == MachO::ARM_RELOC_HALF ||
483097a140dSpatrick            RelocType == MachO::ARM_RELOC_HALF_SECTDIFF;
484097a140dSpatrick   case Triple::aarch64:
485097a140dSpatrick     return RelocType == MachO::ARM64_RELOC_SUBTRACTOR;
486097a140dSpatrick   default:
487097a140dSpatrick     return false;
488097a140dSpatrick   }
489097a140dSpatrick }
490097a140dSpatrick 
491097a140dSpatrick /// Iterate over the relocations of the given \p Section and
492097a140dSpatrick /// store the ones that correspond to debug map entries into the
493097a140dSpatrick /// ValidRelocs array.
494097a140dSpatrick void DwarfLinkerForBinary::AddressManager::findValidRelocsMachO(
495097a140dSpatrick     const object::SectionRef &Section, const object::MachOObjectFile &Obj,
496*73471bf0Spatrick     const DebugMapObject &DMO, std::vector<ValidReloc> &ValidRelocs) {
497097a140dSpatrick   Expected<StringRef> ContentsOrErr = Section.getContents();
498097a140dSpatrick   if (!ContentsOrErr) {
499097a140dSpatrick     consumeError(ContentsOrErr.takeError());
500097a140dSpatrick     Linker.reportWarning("error reading section", DMO.getObjectFilename());
501097a140dSpatrick     return;
502097a140dSpatrick   }
503097a140dSpatrick   DataExtractor Data(*ContentsOrErr, Obj.isLittleEndian(), 0);
504097a140dSpatrick   bool SkipNext = false;
505097a140dSpatrick 
506097a140dSpatrick   for (const object::RelocationRef &Reloc : Section.relocations()) {
507097a140dSpatrick     if (SkipNext) {
508097a140dSpatrick       SkipNext = false;
509097a140dSpatrick       continue;
510097a140dSpatrick     }
511097a140dSpatrick 
512097a140dSpatrick     object::DataRefImpl RelocDataRef = Reloc.getRawDataRefImpl();
513097a140dSpatrick     MachO::any_relocation_info MachOReloc = Obj.getRelocation(RelocDataRef);
514097a140dSpatrick 
515097a140dSpatrick     if (isMachOPairedReloc(Obj.getAnyRelocationType(MachOReloc),
516097a140dSpatrick                            Obj.getArch())) {
517097a140dSpatrick       SkipNext = true;
518*73471bf0Spatrick       Linker.reportWarning("unsupported relocation in " + *Section.getName() +
519*73471bf0Spatrick                                " section.",
520097a140dSpatrick                            DMO.getObjectFilename());
521097a140dSpatrick       continue;
522097a140dSpatrick     }
523097a140dSpatrick 
524097a140dSpatrick     unsigned RelocSize = 1 << Obj.getAnyRelocationLength(MachOReloc);
525097a140dSpatrick     uint64_t Offset64 = Reloc.getOffset();
526097a140dSpatrick     if ((RelocSize != 4 && RelocSize != 8)) {
527*73471bf0Spatrick       Linker.reportWarning("unsupported relocation in " + *Section.getName() +
528*73471bf0Spatrick                                " section.",
529097a140dSpatrick                            DMO.getObjectFilename());
530097a140dSpatrick       continue;
531097a140dSpatrick     }
532097a140dSpatrick     uint64_t OffsetCopy = Offset64;
533097a140dSpatrick     // Mach-o uses REL relocations, the addend is at the relocation offset.
534097a140dSpatrick     uint64_t Addend = Data.getUnsigned(&OffsetCopy, RelocSize);
535097a140dSpatrick     uint64_t SymAddress;
536097a140dSpatrick     int64_t SymOffset;
537097a140dSpatrick 
538097a140dSpatrick     if (Obj.isRelocationScattered(MachOReloc)) {
539097a140dSpatrick       // The address of the base symbol for scattered relocations is
540097a140dSpatrick       // stored in the reloc itself. The actual addend will store the
541097a140dSpatrick       // base address plus the offset.
542097a140dSpatrick       SymAddress = Obj.getScatteredRelocationValue(MachOReloc);
543097a140dSpatrick       SymOffset = int64_t(Addend) - SymAddress;
544097a140dSpatrick     } else {
545097a140dSpatrick       SymAddress = Addend;
546097a140dSpatrick       SymOffset = 0;
547097a140dSpatrick     }
548097a140dSpatrick 
549097a140dSpatrick     auto Sym = Reloc.getSymbol();
550097a140dSpatrick     if (Sym != Obj.symbol_end()) {
551097a140dSpatrick       Expected<StringRef> SymbolName = Sym->getName();
552097a140dSpatrick       if (!SymbolName) {
553097a140dSpatrick         consumeError(SymbolName.takeError());
554097a140dSpatrick         Linker.reportWarning("error getting relocation symbol name.",
555097a140dSpatrick                              DMO.getObjectFilename());
556097a140dSpatrick         continue;
557097a140dSpatrick       }
558097a140dSpatrick       if (const auto *Mapping = DMO.lookupSymbol(*SymbolName))
559097a140dSpatrick         ValidRelocs.emplace_back(Offset64, RelocSize, Addend, Mapping);
560097a140dSpatrick     } else if (const auto *Mapping = DMO.lookupObjectAddress(SymAddress)) {
561097a140dSpatrick       // Do not store the addend. The addend was the address of the symbol in
562097a140dSpatrick       // the object file, the address in the binary that is stored in the debug
563097a140dSpatrick       // map doesn't need to be offset.
564097a140dSpatrick       ValidRelocs.emplace_back(Offset64, RelocSize, SymOffset, Mapping);
565097a140dSpatrick     }
566097a140dSpatrick   }
567097a140dSpatrick }
568097a140dSpatrick 
569097a140dSpatrick /// Dispatch the valid relocation finding logic to the
570097a140dSpatrick /// appropriate handler depending on the object file format.
571097a140dSpatrick bool DwarfLinkerForBinary::AddressManager::findValidRelocs(
572097a140dSpatrick     const object::SectionRef &Section, const object::ObjectFile &Obj,
573*73471bf0Spatrick     const DebugMapObject &DMO, std::vector<ValidReloc> &Relocs) {
574097a140dSpatrick   // Dispatch to the right handler depending on the file type.
575097a140dSpatrick   if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(&Obj))
576*73471bf0Spatrick     findValidRelocsMachO(Section, *MachOObj, DMO, Relocs);
577097a140dSpatrick   else
578097a140dSpatrick     Linker.reportWarning(Twine("unsupported object file type: ") +
579097a140dSpatrick                              Obj.getFileName(),
580097a140dSpatrick                          DMO.getObjectFilename());
581*73471bf0Spatrick   if (Relocs.empty())
582097a140dSpatrick     return false;
583097a140dSpatrick 
584097a140dSpatrick   // Sort the relocations by offset. We will walk the DIEs linearly in
585097a140dSpatrick   // the file, this allows us to just keep an index in the relocation
586097a140dSpatrick   // array that we advance during our walk, rather than resorting to
587097a140dSpatrick   // some associative container. See DwarfLinkerForBinary::NextValidReloc.
588*73471bf0Spatrick   llvm::sort(Relocs);
589097a140dSpatrick   return true;
590097a140dSpatrick }
591097a140dSpatrick 
592*73471bf0Spatrick /// Look for relocations in the debug_info and debug_addr section that match
593*73471bf0Spatrick /// entries in the debug map. These relocations will drive the Dwarf link by
594*73471bf0Spatrick /// indicating which DIEs refer to symbols present in the linked binary.
595097a140dSpatrick /// \returns whether there are any valid relocations in the debug info.
596*73471bf0Spatrick bool DwarfLinkerForBinary::AddressManager::findValidRelocsInDebugSections(
597097a140dSpatrick     const object::ObjectFile &Obj, const DebugMapObject &DMO) {
598097a140dSpatrick   // Find the debug_info section.
599*73471bf0Spatrick   bool FoundValidRelocs = false;
600097a140dSpatrick   for (const object::SectionRef &Section : Obj.sections()) {
601097a140dSpatrick     StringRef SectionName;
602097a140dSpatrick     if (Expected<StringRef> NameOrErr = Section.getName())
603097a140dSpatrick       SectionName = *NameOrErr;
604097a140dSpatrick     else
605097a140dSpatrick       consumeError(NameOrErr.takeError());
606097a140dSpatrick 
607097a140dSpatrick     SectionName = SectionName.substr(SectionName.find_first_not_of("._"));
608*73471bf0Spatrick     if (SectionName == "debug_info")
609*73471bf0Spatrick       FoundValidRelocs |=
610*73471bf0Spatrick           findValidRelocs(Section, Obj, DMO, ValidDebugInfoRelocs);
611*73471bf0Spatrick     if (SectionName == "debug_addr")
612*73471bf0Spatrick       FoundValidRelocs |=
613*73471bf0Spatrick           findValidRelocs(Section, Obj, DMO, ValidDebugAddrRelocs);
614097a140dSpatrick   }
615*73471bf0Spatrick   return FoundValidRelocs;
616097a140dSpatrick }
617097a140dSpatrick 
618*73471bf0Spatrick std::vector<DwarfLinkerForBinary::AddressManager::ValidReloc>
619*73471bf0Spatrick DwarfLinkerForBinary::AddressManager::getRelocations(
620*73471bf0Spatrick     const std::vector<ValidReloc> &Relocs, uint64_t StartPos, uint64_t EndPos) {
621*73471bf0Spatrick   std::vector<DwarfLinkerForBinary::AddressManager::ValidReloc> Res;
622097a140dSpatrick 
623*73471bf0Spatrick   auto CurReloc = partition_point(Relocs, [StartPos](const ValidReloc &Reloc) {
624*73471bf0Spatrick     return Reloc.Offset < StartPos;
625*73471bf0Spatrick   });
626097a140dSpatrick 
627*73471bf0Spatrick   while (CurReloc != Relocs.end() && CurReloc->Offset >= StartPos &&
628*73471bf0Spatrick          CurReloc->Offset < EndPos) {
629*73471bf0Spatrick     Res.push_back(*CurReloc);
630*73471bf0Spatrick     CurReloc++;
631*73471bf0Spatrick   }
632097a140dSpatrick 
633*73471bf0Spatrick   return Res;
634*73471bf0Spatrick }
635097a140dSpatrick 
636*73471bf0Spatrick void DwarfLinkerForBinary::AddressManager::printReloc(const ValidReloc &Reloc) {
637*73471bf0Spatrick   const auto &Mapping = Reloc.Mapping->getValue();
638097a140dSpatrick   const uint64_t ObjectAddress = Mapping.ObjectAddress
639097a140dSpatrick                                      ? uint64_t(*Mapping.ObjectAddress)
640097a140dSpatrick                                      : std::numeric_limits<uint64_t>::max();
641097a140dSpatrick 
642*73471bf0Spatrick   outs() << "Found valid debug map entry: " << Reloc.Mapping->getKey() << "\t"
643*73471bf0Spatrick          << format("0x%016" PRIx64 " => 0x%016" PRIx64 "\n", ObjectAddress,
644*73471bf0Spatrick                    uint64_t(Mapping.BinaryAddress));
645*73471bf0Spatrick }
646*73471bf0Spatrick 
647*73471bf0Spatrick void DwarfLinkerForBinary::AddressManager::fillDieInfo(
648*73471bf0Spatrick     const ValidReloc &Reloc, CompileUnit::DIEInfo &Info) {
649*73471bf0Spatrick   Info.AddrAdjust = relocate(Reloc);
650*73471bf0Spatrick   if (Reloc.Mapping->getValue().ObjectAddress)
651*73471bf0Spatrick     Info.AddrAdjust -= uint64_t(*Reloc.Mapping->getValue().ObjectAddress);
652097a140dSpatrick   Info.InDebugMap = true;
653*73471bf0Spatrick }
654*73471bf0Spatrick 
655*73471bf0Spatrick bool DwarfLinkerForBinary::AddressManager::hasValidRelocationAt(
656*73471bf0Spatrick     const std::vector<ValidReloc> &AllRelocs, uint64_t StartOffset,
657*73471bf0Spatrick     uint64_t EndOffset, CompileUnit::DIEInfo &Info) {
658*73471bf0Spatrick   std::vector<ValidReloc> Relocs =
659*73471bf0Spatrick       getRelocations(AllRelocs, StartOffset, EndOffset);
660*73471bf0Spatrick 
661*73471bf0Spatrick   if (Relocs.size() == 0)
662*73471bf0Spatrick     return false;
663*73471bf0Spatrick 
664*73471bf0Spatrick   if (Linker.Options.Verbose)
665*73471bf0Spatrick     printReloc(Relocs[0]);
666*73471bf0Spatrick   fillDieInfo(Relocs[0], Info);
667*73471bf0Spatrick 
668097a140dSpatrick   return true;
669097a140dSpatrick }
670097a140dSpatrick 
671*73471bf0Spatrick /// Get the starting and ending (exclusive) offset for the
672*73471bf0Spatrick /// attribute with index \p Idx descibed by \p Abbrev. \p Offset is
673*73471bf0Spatrick /// supposed to point to the position of the first attribute described
674*73471bf0Spatrick /// by \p Abbrev.
675*73471bf0Spatrick /// \return [StartOffset, EndOffset) as a pair.
676*73471bf0Spatrick static std::pair<uint64_t, uint64_t>
677*73471bf0Spatrick getAttributeOffsets(const DWARFAbbreviationDeclaration *Abbrev, unsigned Idx,
678*73471bf0Spatrick                     uint64_t Offset, const DWARFUnit &Unit) {
679*73471bf0Spatrick   DataExtractor Data = Unit.getDebugInfoExtractor();
680*73471bf0Spatrick 
681*73471bf0Spatrick   for (unsigned I = 0; I < Idx; ++I)
682*73471bf0Spatrick     DWARFFormValue::skipValue(Abbrev->getFormByIndex(I), Data, &Offset,
683*73471bf0Spatrick                               Unit.getFormParams());
684*73471bf0Spatrick 
685*73471bf0Spatrick   uint64_t End = Offset;
686*73471bf0Spatrick   DWARFFormValue::skipValue(Abbrev->getFormByIndex(Idx), Data, &End,
687*73471bf0Spatrick                             Unit.getFormParams());
688*73471bf0Spatrick 
689*73471bf0Spatrick   return std::make_pair(Offset, End);
690*73471bf0Spatrick }
691*73471bf0Spatrick 
692*73471bf0Spatrick bool DwarfLinkerForBinary::AddressManager::hasLiveMemoryLocation(
693*73471bf0Spatrick     const DWARFDie &DIE, CompileUnit::DIEInfo &MyInfo) {
694*73471bf0Spatrick   const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
695*73471bf0Spatrick 
696*73471bf0Spatrick   Optional<uint32_t> LocationIdx =
697*73471bf0Spatrick       Abbrev->findAttributeIndex(dwarf::DW_AT_location);
698*73471bf0Spatrick   if (!LocationIdx)
699*73471bf0Spatrick     return false;
700*73471bf0Spatrick 
701*73471bf0Spatrick   uint64_t Offset = DIE.getOffset() + getULEB128Size(Abbrev->getCode());
702*73471bf0Spatrick   uint64_t LocationOffset, LocationEndOffset;
703*73471bf0Spatrick   std::tie(LocationOffset, LocationEndOffset) =
704*73471bf0Spatrick       getAttributeOffsets(Abbrev, *LocationIdx, Offset, *DIE.getDwarfUnit());
705*73471bf0Spatrick 
706*73471bf0Spatrick   // FIXME: Support relocations debug_addr.
707*73471bf0Spatrick   return hasValidRelocationAt(ValidDebugInfoRelocs, LocationOffset,
708*73471bf0Spatrick                               LocationEndOffset, MyInfo);
709*73471bf0Spatrick }
710*73471bf0Spatrick 
711*73471bf0Spatrick bool DwarfLinkerForBinary::AddressManager::hasLiveAddressRange(
712*73471bf0Spatrick     const DWARFDie &DIE, CompileUnit::DIEInfo &MyInfo) {
713*73471bf0Spatrick   const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
714*73471bf0Spatrick 
715*73471bf0Spatrick   Optional<uint32_t> LowPcIdx = Abbrev->findAttributeIndex(dwarf::DW_AT_low_pc);
716*73471bf0Spatrick   if (!LowPcIdx)
717*73471bf0Spatrick     return false;
718*73471bf0Spatrick 
719*73471bf0Spatrick   dwarf::Form Form = Abbrev->getFormByIndex(*LowPcIdx);
720*73471bf0Spatrick 
721*73471bf0Spatrick   if (Form == dwarf::DW_FORM_addr) {
722*73471bf0Spatrick     uint64_t Offset = DIE.getOffset() + getULEB128Size(Abbrev->getCode());
723*73471bf0Spatrick     uint64_t LowPcOffset, LowPcEndOffset;
724*73471bf0Spatrick     std::tie(LowPcOffset, LowPcEndOffset) =
725*73471bf0Spatrick         getAttributeOffsets(Abbrev, *LowPcIdx, Offset, *DIE.getDwarfUnit());
726*73471bf0Spatrick     return hasValidRelocationAt(ValidDebugInfoRelocs, LowPcOffset,
727*73471bf0Spatrick                                 LowPcEndOffset, MyInfo);
728*73471bf0Spatrick   }
729*73471bf0Spatrick 
730*73471bf0Spatrick   if (Form == dwarf::DW_FORM_addrx) {
731*73471bf0Spatrick     Optional<DWARFFormValue> AddrValue = DIE.find(dwarf::DW_AT_low_pc);
732*73471bf0Spatrick     if (Optional<uint64_t> AddrOffsetSectionBase =
733*73471bf0Spatrick             DIE.getDwarfUnit()->getAddrOffsetSectionBase()) {
734*73471bf0Spatrick       uint64_t StartOffset = *AddrOffsetSectionBase + AddrValue->getRawUValue();
735*73471bf0Spatrick       uint64_t EndOffset =
736*73471bf0Spatrick           StartOffset + DIE.getDwarfUnit()->getAddressByteSize();
737*73471bf0Spatrick       return hasValidRelocationAt(ValidDebugAddrRelocs, StartOffset, EndOffset,
738*73471bf0Spatrick                                   MyInfo);
739*73471bf0Spatrick     } else
740*73471bf0Spatrick       Linker.reportWarning("no base offset for address table", SrcFileName);
741*73471bf0Spatrick   }
742*73471bf0Spatrick 
743*73471bf0Spatrick   return false;
744*73471bf0Spatrick }
745*73471bf0Spatrick 
746*73471bf0Spatrick uint64_t
747*73471bf0Spatrick DwarfLinkerForBinary::AddressManager::relocate(const ValidReloc &Reloc) const {
748*73471bf0Spatrick   return Reloc.Mapping->getValue().BinaryAddress + Reloc.Addend;
749*73471bf0Spatrick }
750*73471bf0Spatrick 
751097a140dSpatrick /// Apply the valid relocations found by findValidRelocs() to
752097a140dSpatrick /// the buffer \p Data, taking into account that Data is at \p BaseOffset
753097a140dSpatrick /// in the debug_info section.
754097a140dSpatrick ///
755097a140dSpatrick /// Like for findValidRelocs(), this function must be called with
756097a140dSpatrick /// monotonic \p BaseOffset values.
757097a140dSpatrick ///
758097a140dSpatrick /// \returns whether any reloc has been applied.
759097a140dSpatrick bool DwarfLinkerForBinary::AddressManager::applyValidRelocs(
760097a140dSpatrick     MutableArrayRef<char> Data, uint64_t BaseOffset, bool IsLittleEndian) {
761097a140dSpatrick   assert(areRelocationsResolved());
762*73471bf0Spatrick   std::vector<ValidReloc> Relocs = getRelocations(
763*73471bf0Spatrick       ValidDebugInfoRelocs, BaseOffset, BaseOffset + Data.size());
764097a140dSpatrick 
765*73471bf0Spatrick   for (const ValidReloc &CurReloc : Relocs) {
766*73471bf0Spatrick     assert(CurReloc.Offset - BaseOffset < Data.size());
767*73471bf0Spatrick     assert(CurReloc.Offset - BaseOffset + CurReloc.Size <= Data.size());
768097a140dSpatrick     char Buf[8];
769*73471bf0Spatrick     uint64_t Value = relocate(CurReloc);
770*73471bf0Spatrick     for (unsigned I = 0; I != CurReloc.Size; ++I) {
771*73471bf0Spatrick       unsigned Index = IsLittleEndian ? I : (CurReloc.Size - I - 1);
772097a140dSpatrick       Buf[I] = uint8_t(Value >> (Index * 8));
773097a140dSpatrick     }
774*73471bf0Spatrick     assert(CurReloc.Size <= sizeof(Buf));
775*73471bf0Spatrick     memcpy(&Data[CurReloc.Offset - BaseOffset], Buf, CurReloc.Size);
776097a140dSpatrick   }
777097a140dSpatrick 
778*73471bf0Spatrick   return Relocs.size() > 0;
779*73471bf0Spatrick }
780*73471bf0Spatrick 
781*73471bf0Spatrick llvm::Expected<uint64_t>
782*73471bf0Spatrick DwarfLinkerForBinary::AddressManager::relocateIndexedAddr(uint64_t StartOffset,
783*73471bf0Spatrick                                                           uint64_t EndOffset) {
784*73471bf0Spatrick   std::vector<ValidReloc> Relocs =
785*73471bf0Spatrick       getRelocations(ValidDebugAddrRelocs, StartOffset, EndOffset);
786*73471bf0Spatrick   if (Relocs.size() == 0)
787*73471bf0Spatrick     return createStringError(
788*73471bf0Spatrick         std::make_error_code(std::errc::invalid_argument),
789*73471bf0Spatrick         "no relocation for offset %llu in debug_addr section", StartOffset);
790*73471bf0Spatrick 
791*73471bf0Spatrick   return relocate(Relocs[0]);
792097a140dSpatrick }
79309467b48Spatrick 
79409467b48Spatrick bool linkDwarf(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
79509467b48Spatrick                const DebugMap &DM, LinkOptions Options) {
79609467b48Spatrick   DwarfLinkerForBinary Linker(OutFile, BinHolder, std::move(Options));
79709467b48Spatrick   return Linker.link(DM);
79809467b48Spatrick }
79909467b48Spatrick 
80009467b48Spatrick } // namespace dsymutil
80109467b48Spatrick } // namespace llvm
802