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