brintos

brintos / llvm-project-archived public Read only

0
0
Text · 51.0 KiB · e9ee3ce Raw
1419 lines · cpp
1//=== DWARFLinkerImpl.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "DWARFLinkerImpl.h"10#include "DependencyTracker.h"11#include "llvm/DWARFLinker/Utils.h"12#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"13#include "llvm/Support/FormatVariadic.h"14#include "llvm/Support/Parallel.h"15#include "llvm/Support/ThreadPool.h"16 17using namespace llvm;18using namespace dwarf_linker;19using namespace dwarf_linker::parallel;20 21DWARFLinkerImpl::DWARFLinkerImpl(MessageHandlerTy ErrorHandler,22                                 MessageHandlerTy WarningHandler)23    : UniqueUnitID(0), DebugStrStrings(GlobalData),24      DebugLineStrStrings(GlobalData), CommonSections(GlobalData) {25  GlobalData.setErrorHandler(ErrorHandler);26  GlobalData.setWarningHandler(WarningHandler);27}28 29DWARFLinkerImpl::LinkContext::LinkContext(LinkingGlobalData &GlobalData,30                                          DWARFFile &File,31                                          StringMap<uint64_t> &ClangModules,32                                          std::atomic<size_t> &UniqueUnitID)33    : OutputSections(GlobalData), InputDWARFFile(File),34      ClangModules(ClangModules), UniqueUnitID(UniqueUnitID) {35 36  if (File.Dwarf) {37    if (!File.Dwarf->compile_units().empty())38      CompileUnits.reserve(File.Dwarf->getNumCompileUnits());39 40    // Set context format&endianness based on the input file.41    Format.Version = File.Dwarf->getMaxVersion();42    Format.AddrSize = File.Dwarf->getCUAddrSize();43    Endianness = File.Dwarf->isLittleEndian() ? llvm::endianness::little44                                              : llvm::endianness::big;45  }46}47 48DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit(49    DWARFFile &File, std::unique_ptr<CompileUnit> Unit)50    : File(File), Unit(std::move(Unit)) {}51 52DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit(53    LinkContext::RefModuleUnit &&Other)54    : File(Other.File), Unit(std::move(Other.Unit)) {}55 56void DWARFLinkerImpl::LinkContext::addModulesCompileUnit(57    LinkContext::RefModuleUnit &&Unit) {58  ModulesCompileUnits.emplace_back(std::move(Unit));59}60 61void DWARFLinkerImpl::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader,62                                    CompileUnitHandlerTy OnCUDieLoaded) {63  ObjectContexts.emplace_back(std::make_unique<LinkContext>(64      GlobalData, File, ClangModules, UniqueUnitID));65 66  if (ObjectContexts.back()->InputDWARFFile.Dwarf) {67    for (const std::unique_ptr<DWARFUnit> &CU :68         ObjectContexts.back()->InputDWARFFile.Dwarf->compile_units()) {69      DWARFDie CUDie = CU->getUnitDIE();70      OverallNumberOfCU++;71 72      if (!CUDie)73        continue;74 75      OnCUDieLoaded(*CU);76 77      // Register mofule reference.78      if (!GlobalData.getOptions().UpdateIndexTablesOnly)79        ObjectContexts.back()->registerModuleReference(CUDie, Loader,80                                                       OnCUDieLoaded);81    }82  }83}84 85void DWARFLinkerImpl::setEstimatedObjfilesAmount(unsigned ObjFilesNum) {86  ObjectContexts.reserve(ObjFilesNum);87}88 89Error DWARFLinkerImpl::link() {90  // reset compile unit unique ID counter.91  UniqueUnitID = 0;92 93  if (Error Err = validateAndUpdateOptions())94    return Err;95 96  dwarf::FormParams GlobalFormat = {GlobalData.getOptions().TargetDWARFVersion,97                                    0, dwarf::DwarfFormat::DWARF32};98  llvm::endianness GlobalEndianness = llvm::endianness::native;99 100  if (std::optional<std::reference_wrapper<const Triple>> CurTriple =101          GlobalData.getTargetTriple()) {102    GlobalEndianness = (*CurTriple).get().isLittleEndian()103                           ? llvm::endianness::little104                           : llvm::endianness::big;105  }106  std::optional<uint16_t> Language;107 108  for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {109    if (Context->InputDWARFFile.Dwarf == nullptr) {110      Context->setOutputFormat(Context->getFormParams(), GlobalEndianness);111      continue;112    }113 114    if (GlobalData.getOptions().Verbose) {115      outs() << "DEBUG MAP OBJECT: " << Context->InputDWARFFile.FileName116             << "\n";117 118      for (const std::unique_ptr<DWARFUnit> &OrigCU :119           Context->InputDWARFFile.Dwarf->compile_units()) {120        outs() << "Input compilation unit:";121        DIDumpOptions DumpOpts;122        DumpOpts.ChildRecurseDepth = 0;123        DumpOpts.Verbose = GlobalData.getOptions().Verbose;124        OrigCU->getUnitDIE().dump(outs(), 0, DumpOpts);125      }126    }127 128    // Verify input DWARF if requested.129    if (GlobalData.getOptions().VerifyInputDWARF)130      verifyInput(Context->InputDWARFFile);131 132    if (!GlobalData.getTargetTriple())133      GlobalEndianness = Context->getEndianness();134    GlobalFormat.AddrSize =135        std::max(GlobalFormat.AddrSize, Context->getFormParams().AddrSize);136 137    Context->setOutputFormat(Context->getFormParams(), GlobalEndianness);138 139    // FIXME: move creation of CompileUnits into the addObjectFile.140    // This would allow to not scan for context Language and Modules state141    // twice. And then following handling might be removed.142    for (const std::unique_ptr<DWARFUnit> &OrigCU :143         Context->InputDWARFFile.Dwarf->compile_units()) {144      DWARFDie UnitDie = OrigCU->getUnitDIE();145 146      if (!Language) {147        if (std::optional<DWARFFormValue> Val =148                UnitDie.find(dwarf::DW_AT_language)) {149          uint16_t LangVal = dwarf::toUnsigned(Val, 0);150          if (isODRLanguage(LangVal))151            Language = LangVal;152        }153      }154    }155  }156 157  if (GlobalFormat.AddrSize == 0) {158    if (std::optional<std::reference_wrapper<const Triple>> TargetTriple =159            GlobalData.getTargetTriple())160      GlobalFormat.AddrSize = (*TargetTriple).get().isArch32Bit() ? 4 : 8;161    else162      GlobalFormat.AddrSize = 8;163  }164 165  CommonSections.setOutputFormat(GlobalFormat, GlobalEndianness);166 167  if (!GlobalData.Options.NoODR && Language.has_value()) {168    llvm::parallel::TaskGroup TGroup;169    TGroup.spawn([&]() {170      ArtificialTypeUnit = std::make_unique<TypeUnit>(171          GlobalData, UniqueUnitID++, Language, GlobalFormat, GlobalEndianness);172    });173  }174 175  // Set parallel options.176  if (GlobalData.getOptions().Threads == 0)177    llvm::parallel::strategy = optimal_concurrency(OverallNumberOfCU);178  else179    llvm::parallel::strategy =180        hardware_concurrency(GlobalData.getOptions().Threads);181 182  // Link object files.183  if (GlobalData.getOptions().Threads == 1) {184    for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {185      // Link object file.186      if (Error Err = Context->link(ArtificialTypeUnit.get()))187        GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);188 189      Context->InputDWARFFile.unload();190    }191  } else {192    DefaultThreadPool Pool(llvm::parallel::strategy);193    for (std::unique_ptr<LinkContext> &Context : ObjectContexts)194      Pool.async([&]() {195        // Link object file.196        if (Error Err = Context->link(ArtificialTypeUnit.get()))197          GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);198 199        Context->InputDWARFFile.unload();200      });201 202    Pool.wait();203  }204 205  if (ArtificialTypeUnit != nullptr && !ArtificialTypeUnit->getTypePool()206                                            .getRoot()207                                            ->getValue()208                                            .load()209                                            ->Children.empty()) {210    if (GlobalData.getTargetTriple().has_value())211      if (Error Err = ArtificialTypeUnit->finishCloningAndEmit(212              (*GlobalData.getTargetTriple()).get()))213        return Err;214  }215 216  // At this stage each compile units are cloned to their own set of debug217  // sections. Now, update patches, assign offsets and assemble final file218  // glueing debug tables from each compile unit.219  glueCompileUnitsAndWriteToTheOutput();220 221  return Error::success();222}223 224void DWARFLinkerImpl::verifyInput(const DWARFFile &File) {225  assert(File.Dwarf);226 227  std::string Buffer;228  raw_string_ostream OS(Buffer);229  DIDumpOptions DumpOpts;230  if (!File.Dwarf->verify(OS, DumpOpts.noImplicitRecursion())) {231    if (GlobalData.getOptions().InputVerificationHandler)232      GlobalData.getOptions().InputVerificationHandler(File, OS.str());233  }234}235 236Error DWARFLinkerImpl::validateAndUpdateOptions() {237  if (GlobalData.getOptions().TargetDWARFVersion == 0)238    return createStringError(std::errc::invalid_argument,239                             "target DWARF version is not set");240 241  if (GlobalData.getOptions().Verbose && GlobalData.getOptions().Threads != 1) {242    GlobalData.Options.Threads = 1;243    GlobalData.warn(244        "set number of threads to 1 to make --verbose to work properly.", "");245  }246 247  // Do not do types deduplication in case --update.248  if (GlobalData.getOptions().UpdateIndexTablesOnly &&249      !GlobalData.Options.NoODR)250    GlobalData.Options.NoODR = true;251 252  return Error::success();253}254 255/// Resolve the relative path to a build artifact referenced by DWARF by256/// applying DW_AT_comp_dir.257static void resolveRelativeObjectPath(SmallVectorImpl<char> &Buf, DWARFDie CU) {258  sys::path::append(Buf, dwarf::toString(CU.find(dwarf::DW_AT_comp_dir), ""));259}260 261static uint64_t getDwoId(const DWARFDie &CUDie) {262  auto DwoId = dwarf::toUnsigned(263      CUDie.find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));264  if (DwoId)265    return *DwoId;266  return 0;267}268 269static std::string270remapPath(StringRef Path,271          const DWARFLinker::ObjectPrefixMapTy &ObjectPrefixMap) {272  if (ObjectPrefixMap.empty())273    return Path.str();274 275  SmallString<256> p = Path;276  for (const auto &Entry : ObjectPrefixMap)277    if (llvm::sys::path::replace_path_prefix(p, Entry.first, Entry.second))278      break;279  return p.str().str();280}281 282static std::string getPCMFile(const DWARFDie &CUDie,283                              DWARFLinker::ObjectPrefixMapTy *ObjectPrefixMap) {284  std::string PCMFile = dwarf::toString(285      CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");286 287  if (PCMFile.empty())288    return PCMFile;289 290  if (ObjectPrefixMap)291    PCMFile = remapPath(PCMFile, *ObjectPrefixMap);292 293  return PCMFile;294}295 296std::pair<bool, bool> DWARFLinkerImpl::LinkContext::isClangModuleRef(297    const DWARFDie &CUDie, std::string &PCMFile, unsigned Indent, bool Quiet) {298  if (PCMFile.empty())299    return std::make_pair(false, false);300 301  // Clang module DWARF skeleton CUs abuse this for the path to the module.302  uint64_t DwoId = getDwoId(CUDie);303 304  std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");305  if (Name.empty()) {306    if (!Quiet)307      GlobalData.warn("anonymous module skeleton CU for " + PCMFile + ".",308                      InputDWARFFile.FileName);309    return std::make_pair(true, true);310  }311 312  if (!Quiet && GlobalData.getOptions().Verbose) {313    outs().indent(Indent);314    outs() << "Found clang module reference " << PCMFile;315  }316 317  auto Cached = ClangModules.find(PCMFile);318  if (Cached != ClangModules.end()) {319    // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is320    // fixed in clang, only warn about DWO_id mismatches in verbose mode.321    // ASTFileSignatures will change randomly when a module is rebuilt.322    if (!Quiet && GlobalData.getOptions().Verbose && (Cached->second != DwoId))323      GlobalData.warn(324          Twine("hash mismatch: this object file was built against a "325                "different version of the module ") +326              PCMFile + ".",327          InputDWARFFile.FileName);328    if (!Quiet && GlobalData.getOptions().Verbose)329      outs() << " [cached].\n";330    return std::make_pair(true, true);331  }332 333  return std::make_pair(true, false);334}335 336/// If this compile unit is really a skeleton CU that points to a337/// clang module, register it in ClangModules and return true.338///339/// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name340/// pointing to the module, and a DW_AT_gnu_dwo_id with the module341/// hash.342bool DWARFLinkerImpl::LinkContext::registerModuleReference(343    const DWARFDie &CUDie, ObjFileLoaderTy Loader,344    CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {345  std::string PCMFile =346      getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);347  std::pair<bool, bool> IsClangModuleRef =348      isClangModuleRef(CUDie, PCMFile, Indent, false);349 350  if (!IsClangModuleRef.first)351    return false;352 353  if (IsClangModuleRef.second)354    return true;355 356  if (GlobalData.getOptions().Verbose)357    outs() << " ...\n";358 359  // Cyclic dependencies are disallowed by Clang, but we still360  // shouldn't run into an infinite loop, so mark it as processed now.361  ClangModules.insert({PCMFile, getDwoId(CUDie)});362 363  if (Error E =364          loadClangModule(Loader, CUDie, PCMFile, OnCUDieLoaded, Indent + 2)) {365    consumeError(std::move(E));366    return false;367  }368  return true;369}370 371Error DWARFLinkerImpl::LinkContext::loadClangModule(372    ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile,373    CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {374 375  uint64_t DwoId = getDwoId(CUDie);376  std::string ModuleName = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");377 378  /// Using a SmallString<0> because loadClangModule() is recursive.379  SmallString<0> Path(GlobalData.getOptions().PrependPath);380  if (sys::path::is_relative(PCMFile))381    resolveRelativeObjectPath(Path, CUDie);382  sys::path::append(Path, PCMFile);383  // Don't use the cached binary holder because we have no thread-safety384  // guarantee and the lifetime is limited.385 386  if (Loader == nullptr) {387    GlobalData.error("cann't load clang module: loader is not specified.",388                     InputDWARFFile.FileName);389    return Error::success();390  }391 392  auto ErrOrObj = Loader(InputDWARFFile.FileName, Path);393  if (!ErrOrObj)394    return Error::success();395 396  std::unique_ptr<CompileUnit> Unit;397  for (const auto &CU : ErrOrObj->Dwarf->compile_units()) {398    OnCUDieLoaded(*CU);399    // Recursively get all modules imported by this one.400    auto ChildCUDie = CU->getUnitDIE();401    if (!ChildCUDie)402      continue;403    if (!registerModuleReference(ChildCUDie, Loader, OnCUDieLoaded, Indent)) {404      if (Unit) {405        std::string Err =406            (PCMFile +407             ": Clang modules are expected to have exactly 1 compile unit.\n");408        GlobalData.error(Err, InputDWARFFile.FileName);409        return make_error<StringError>(Err, inconvertibleErrorCode());410      }411      // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is412      // fixed in clang, only warn about DWO_id mismatches in verbose mode.413      // ASTFileSignatures will change randomly when a module is rebuilt.414      uint64_t PCMDwoId = getDwoId(ChildCUDie);415      if (PCMDwoId != DwoId) {416        if (GlobalData.getOptions().Verbose)417          GlobalData.warn(418              Twine("hash mismatch: this object file was built against a "419                    "different version of the module ") +420                  PCMFile + ".",421              InputDWARFFile.FileName);422        // Update the cache entry with the DwoId of the module loaded from disk.423        ClangModules[PCMFile] = PCMDwoId;424      }425 426      // Empty modules units should not be cloned.427      if (!ChildCUDie.hasChildren())428        continue;429 430      // Add this module.431      Unit = std::make_unique<CompileUnit>(432          GlobalData, *CU, UniqueUnitID.fetch_add(1), ModuleName, *ErrOrObj,433          getUnitForOffset, CU->getFormParams(), getEndianness());434    }435  }436 437  if (Unit) {438    ModulesCompileUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});439    // Preload line table, as it can't be loaded asynchronously.440    ModulesCompileUnits.back().Unit->loadLineTable();441  }442 443  return Error::success();444}445 446Error DWARFLinkerImpl::LinkContext::link(TypeUnit *ArtificialTypeUnit) {447  InterCUProcessingStarted = false;448  if (!InputDWARFFile.Dwarf)449    return Error::success();450 451  // Preload macro tables, as they can't be loaded asynchronously.452  InputDWARFFile.Dwarf->getDebugMacinfo();453  InputDWARFFile.Dwarf->getDebugMacro();454 455  // Link modules compile units first.456  parallelForEach(ModulesCompileUnits, [&](RefModuleUnit &RefModule) {457    linkSingleCompileUnit(*RefModule.Unit, ArtificialTypeUnit);458  });459 460  // Check for live relocations. If there is no any live relocation then we461  // can skip entire object file.462  if (!GlobalData.getOptions().UpdateIndexTablesOnly &&463      !InputDWARFFile.Addresses->hasValidRelocs()) {464    if (GlobalData.getOptions().Verbose)465      outs() << "No valid relocations found. Skipping.\n";466    return Error::success();467  }468 469  OriginalDebugInfoSize = getInputDebugInfoSize();470 471  // Create CompileUnit structures to keep information about source472  // DWARFUnit`s, load line tables.473  for (const auto &OrigCU : InputDWARFFile.Dwarf->compile_units()) {474    // Load only unit DIE at this stage.475    auto CUDie = OrigCU->getUnitDIE();476    std::string PCMFile =477        getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);478 479    // The !isClangModuleRef condition effectively skips over fully resolved480    // skeleton units.481    if (!CUDie || GlobalData.getOptions().UpdateIndexTablesOnly ||482        !isClangModuleRef(CUDie, PCMFile, 0, true).first) {483      CompileUnits.emplace_back(std::make_unique<CompileUnit>(484          GlobalData, *OrigCU, UniqueUnitID.fetch_add(1), "", InputDWARFFile,485          getUnitForOffset, OrigCU->getFormParams(), getEndianness()));486 487      // Preload line table, as it can't be loaded asynchronously.488      CompileUnits.back()->loadLineTable();489    }490  };491 492  HasNewInterconnectedCUs = false;493 494  // Link self-sufficient compile units and discover inter-connected compile495  // units.496  parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {497    linkSingleCompileUnit(*CU, ArtificialTypeUnit);498  });499 500  // Link all inter-connected units.501  if (HasNewInterconnectedCUs) {502    InterCUProcessingStarted = true;503 504    if (Error Err = finiteLoop([&]() -> Expected<bool> {505          HasNewInterconnectedCUs = false;506 507          // Load inter-connected units.508          parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {509            if (CU->isInterconnectedCU()) {510              CU->maybeResetToLoadedStage();511              linkSingleCompileUnit(*CU, ArtificialTypeUnit,512                                    CompileUnit::Stage::Loaded);513            }514          });515 516          // Do liveness analysis for inter-connected units.517          parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {518            linkSingleCompileUnit(*CU, ArtificialTypeUnit,519                                  CompileUnit::Stage::LivenessAnalysisDone);520          });521 522          return HasNewInterconnectedCUs.load();523        }))524      return Err;525 526    // Update dependencies.527    if (Error Err = finiteLoop([&]() -> Expected<bool> {528          HasNewGlobalDependency = false;529          parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {530            linkSingleCompileUnit(531                *CU, ArtificialTypeUnit,532                CompileUnit::Stage::UpdateDependenciesCompleteness);533          });534          return HasNewGlobalDependency.load();535        }))536      return Err;537    parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {538      if (CU->isInterconnectedCU() &&539          CU->getStage() == CompileUnit::Stage::LivenessAnalysisDone)540        CU->setStage(CompileUnit::Stage::UpdateDependenciesCompleteness);541    });542 543    // Assign type names.544    parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {545      linkSingleCompileUnit(*CU, ArtificialTypeUnit,546                            CompileUnit::Stage::TypeNamesAssigned);547    });548 549    // Clone inter-connected units.550    parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {551      linkSingleCompileUnit(*CU, ArtificialTypeUnit,552                            CompileUnit::Stage::Cloned);553    });554 555    // Update patches for inter-connected units.556    parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {557      linkSingleCompileUnit(*CU, ArtificialTypeUnit,558                            CompileUnit::Stage::PatchesUpdated);559    });560 561    // Release data.562    parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {563      linkSingleCompileUnit(*CU, ArtificialTypeUnit,564                            CompileUnit::Stage::Cleaned);565    });566  }567 568  if (GlobalData.getOptions().UpdateIndexTablesOnly) {569    // Emit Invariant sections.570 571    if (Error Err = emitInvariantSections())572      return Err;573  } else if (!CompileUnits.empty()) {574    // Emit .debug_frame section.575 576    Error ResultErr = Error::success();577    llvm::parallel::TaskGroup TGroup;578    // We use task group here as PerThreadBumpPtrAllocator should be called from579    // the threads created by ThreadPoolExecutor.580    TGroup.spawn([&]() {581      if (Error Err = cloneAndEmitDebugFrame())582        ResultErr = std::move(Err);583    });584    return ResultErr;585  }586 587  return Error::success();588}589 590void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit(591    CompileUnit &CU, TypeUnit *ArtificialTypeUnit,592    enum CompileUnit::Stage DoUntilStage) {593  if (InterCUProcessingStarted != CU.isInterconnectedCU())594    return;595 596  if (Error Err = finiteLoop([&]() -> Expected<bool> {597        if (CU.getStage() >= DoUntilStage)598          return false;599 600        switch (CU.getStage()) {601        case CompileUnit::Stage::CreatedNotLoaded: {602          // Load input compilation unit DIEs.603          // Analyze properties of DIEs.604          if (!CU.loadInputDIEs()) {605            // We do not need to do liveness analysis for invalid compilation606            // unit.607            CU.setStage(CompileUnit::Stage::Skipped);608          } else {609            CU.analyzeDWARFStructure();610 611            // The registerModuleReference() condition effectively skips612            // over fully resolved skeleton units. This second pass of613            // registerModuleReferences doesn't do any new work, but it614            // will collect top-level errors, which are suppressed. Module615            // warnings were already displayed in the first iteration.616            if (registerModuleReference(617                    CU.getOrigUnit().getUnitDIE(), nullptr,618                    [](const DWARFUnit &) {}, 0))619              CU.setStage(CompileUnit::Stage::PatchesUpdated);620            else621              CU.setStage(CompileUnit::Stage::Loaded);622          }623        } break;624 625        case CompileUnit::Stage::Loaded: {626          // Mark all the DIEs that need to be present in the generated output.627          // If ODR requested, build type names.628          if (!CU.resolveDependenciesAndMarkLiveness(InterCUProcessingStarted,629                                                     HasNewInterconnectedCUs)) {630            assert(HasNewInterconnectedCUs &&631                   "Flag indicating new inter-connections is not set");632            return false;633          }634 635          CU.setStage(CompileUnit::Stage::LivenessAnalysisDone);636        } break;637 638        case CompileUnit::Stage::LivenessAnalysisDone: {639          if (InterCUProcessingStarted) {640            if (CU.updateDependenciesCompleteness())641              HasNewGlobalDependency = true;642            return false;643          } else {644            if (Error Err = finiteLoop([&]() -> Expected<bool> {645                  return CU.updateDependenciesCompleteness();646                }))647              return std::move(Err);648 649            CU.setStage(CompileUnit::Stage::UpdateDependenciesCompleteness);650          }651        } break;652 653        case CompileUnit::Stage::UpdateDependenciesCompleteness:654#ifndef NDEBUG655          CU.verifyDependencies();656#endif657 658          if (ArtificialTypeUnit) {659            if (Error Err =660                    CU.assignTypeNames(ArtificialTypeUnit->getTypePool()))661              return std::move(Err);662          }663          CU.setStage(CompileUnit::Stage::TypeNamesAssigned);664          break;665 666        case CompileUnit::Stage::TypeNamesAssigned:667          // Clone input compile unit.668          if (CU.isClangModule() ||669              GlobalData.getOptions().UpdateIndexTablesOnly ||670              CU.getContaingFile().Addresses->hasValidRelocs()) {671            if (Error Err = CU.cloneAndEmit(GlobalData.getTargetTriple(),672                                            ArtificialTypeUnit))673              return std::move(Err);674          }675 676          CU.setStage(CompileUnit::Stage::Cloned);677          break;678 679        case CompileUnit::Stage::Cloned:680          // Update DIEs referencies.681          CU.updateDieRefPatchesWithClonedOffsets();682          CU.setStage(CompileUnit::Stage::PatchesUpdated);683          break;684 685        case CompileUnit::Stage::PatchesUpdated:686          // Cleanup resources.687          CU.cleanupDataAfterClonning();688          CU.setStage(CompileUnit::Stage::Cleaned);689          break;690 691        case CompileUnit::Stage::Cleaned:692          assert(false);693          break;694 695        case CompileUnit::Stage::Skipped:696          // Nothing to do.697          break;698        }699 700        return true;701      })) {702    CU.error(std::move(Err));703    CU.cleanupDataAfterClonning();704    CU.setStage(CompileUnit::Stage::Skipped);705  }706}707 708Error DWARFLinkerImpl::LinkContext::emitInvariantSections() {709  if (!GlobalData.getTargetTriple().has_value())710    return Error::success();711 712  getOrCreateSectionDescriptor(DebugSectionKind::DebugLoc).OS713      << InputDWARFFile.Dwarf->getDWARFObj().getLocSection().Data;714  getOrCreateSectionDescriptor(DebugSectionKind::DebugLocLists).OS715      << InputDWARFFile.Dwarf->getDWARFObj().getLoclistsSection().Data;716  getOrCreateSectionDescriptor(DebugSectionKind::DebugRange).OS717      << InputDWARFFile.Dwarf->getDWARFObj().getRangesSection().Data;718  getOrCreateSectionDescriptor(DebugSectionKind::DebugRngLists).OS719      << InputDWARFFile.Dwarf->getDWARFObj().getRnglistsSection().Data;720  getOrCreateSectionDescriptor(DebugSectionKind::DebugARanges).OS721      << InputDWARFFile.Dwarf->getDWARFObj().getArangesSection();722  getOrCreateSectionDescriptor(DebugSectionKind::DebugFrame).OS723      << InputDWARFFile.Dwarf->getDWARFObj().getFrameSection().Data;724  getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr).OS725      << InputDWARFFile.Dwarf->getDWARFObj().getAddrSection().Data;726 727  return Error::success();728}729 730Error DWARFLinkerImpl::LinkContext::cloneAndEmitDebugFrame() {731  if (!GlobalData.getTargetTriple().has_value())732    return Error::success();733 734  if (InputDWARFFile.Dwarf == nullptr)735    return Error::success();736 737  const DWARFObject &InputDWARFObj = InputDWARFFile.Dwarf->getDWARFObj();738 739  StringRef OrigFrameData = InputDWARFObj.getFrameSection().Data;740  if (OrigFrameData.empty())741    return Error::success();742 743  RangesTy AllUnitsRanges;744  for (std::unique_ptr<CompileUnit> &Unit : CompileUnits) {745    for (auto CurRange : Unit->getFunctionRanges())746      AllUnitsRanges.insert(CurRange.Range, CurRange.Value);747  }748 749  unsigned SrcAddrSize = InputDWARFObj.getAddressSize();750 751  SectionDescriptor &OutSection =752      getOrCreateSectionDescriptor(DebugSectionKind::DebugFrame);753 754  DataExtractor Data(OrigFrameData, InputDWARFObj.isLittleEndian(), 0);755  uint64_t InputOffset = 0;756 757  // Store the data of the CIEs defined in this object, keyed by their758  // offsets.759  DenseMap<uint64_t, StringRef> LocalCIES;760 761  /// The CIEs that have been emitted in the output section. The actual CIE762  /// data serves a the key to this StringMap.763  StringMap<uint32_t> EmittedCIEs;764 765  while (Data.isValidOffset(InputOffset)) {766    uint64_t EntryOffset = InputOffset;767    uint32_t InitialLength = Data.getU32(&InputOffset);768    if (InitialLength == 0xFFFFFFFF)769      return createFileError(InputDWARFObj.getFileName(),770                             createStringError(std::errc::invalid_argument,771                                               "Dwarf64 bits no supported"));772 773    uint32_t CIEId = Data.getU32(&InputOffset);774    if (CIEId == 0xFFFFFFFF) {775      // This is a CIE, store it.776      StringRef CIEData = OrigFrameData.substr(EntryOffset, InitialLength + 4);777      LocalCIES[EntryOffset] = CIEData;778      // The -4 is to account for the CIEId we just read.779      InputOffset += InitialLength - 4;780      continue;781    }782 783    uint64_t Loc = Data.getUnsigned(&InputOffset, SrcAddrSize);784 785    // Some compilers seem to emit frame info that doesn't start at786    // the function entry point, thus we can't just lookup the address787    // in the debug map. Use the AddressInfo's range map to see if the FDE788    // describes something that we can relocate.789    std::optional<AddressRangeValuePair> Range =790        AllUnitsRanges.getRangeThatContains(Loc);791    if (!Range) {792      // The +4 is to account for the size of the InitialLength field itself.793      InputOffset = EntryOffset + InitialLength + 4;794      continue;795    }796 797    // This is an FDE, and we have a mapping.798    // Have we already emitted a corresponding CIE?799    StringRef CIEData = LocalCIES[CIEId];800    if (CIEData.empty())801      return createFileError(802          InputDWARFObj.getFileName(),803          createStringError(std::errc::invalid_argument,804                            "Inconsistent debug_frame content. Dropping."));805 806    uint64_t OffsetToCIERecord = OutSection.OS.tell();807 808    // Look if we already emitted a CIE that corresponds to the809    // referenced one (the CIE data is the key of that lookup).810    auto IteratorInserted =811        EmittedCIEs.insert(std::make_pair(CIEData, OffsetToCIERecord));812    OffsetToCIERecord = IteratorInserted.first->getValue();813 814    // Emit CIE for this ID if it is not emitted yet.815    if (IteratorInserted.second)816      OutSection.OS << CIEData;817 818    // Remember offset to the FDE record, so that we might update819    // field referencing CIE record(containing OffsetToCIERecord),820    // when final offsets are known. OffsetToCIERecord(which is written later)821    // is local to the current .debug_frame section, it should be updated822    // with final offset of the .debug_frame section.823    OutSection.notePatch(824        DebugOffsetPatch{OutSection.OS.tell() + 4, &OutSection, true});825 826    // Emit the FDE with updated address and CIE pointer.827    // (4 + AddrSize) is the size of the CIEId + initial_location828    // fields that will get reconstructed by emitFDE().829    unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);830    emitFDE(OffsetToCIERecord, SrcAddrSize, Loc + Range->Value,831            OrigFrameData.substr(InputOffset, FDERemainingBytes), OutSection);832    InputOffset += FDERemainingBytes;833  }834 835  return Error::success();836}837 838/// Emit a FDE into the debug_frame section. \p FDEBytes839/// contains the FDE data without the length, CIE offset and address840/// which will be replaced with the parameter values.841void DWARFLinkerImpl::LinkContext::emitFDE(uint32_t CIEOffset,842                                           uint32_t AddrSize, uint64_t Address,843                                           StringRef FDEBytes,844                                           SectionDescriptor &Section) {845  Section.emitIntVal(FDEBytes.size() + 4 + AddrSize, 4);846  Section.emitIntVal(CIEOffset, 4);847  Section.emitIntVal(Address, AddrSize);848  Section.OS.write(FDEBytes.data(), FDEBytes.size());849}850 851void DWARFLinkerImpl::glueCompileUnitsAndWriteToTheOutput() {852  if (!GlobalData.getTargetTriple().has_value())853    return;854  assert(SectionHandler);855 856  // Go through all object files, all compile units and assign857  // offsets to them.858  assignOffsets();859 860  // Patch size/offsets fields according to the assigned CU offsets.861  patchOffsetsAndSizes();862 863  // Emit common sections and write debug tables from all object files/compile864  // units into the resulting file.865  emitCommonSectionsAndWriteCompileUnitsToTheOutput();866 867  if (ArtificialTypeUnit != nullptr)868    ArtificialTypeUnit.reset();869 870  // Write common debug sections into the resulting file.871  writeCommonSectionsToTheOutput();872 873  // Cleanup data.874  cleanupDataAfterDWARFOutputIsWritten();875 876  if (GlobalData.getOptions().Statistics)877    printStatistic();878}879 880void DWARFLinkerImpl::printStatistic() {881 882  // For each object file map how many bytes were emitted.883  StringMap<DebugInfoSize> SizeByObject;884 885  for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {886    uint64_t AllDebugInfoSectionsSize = 0;887 888    for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)889      if (std::optional<SectionDescriptor *> DebugInfo =890              CU->tryGetSectionDescriptor(DebugSectionKind::DebugInfo))891        AllDebugInfoSectionsSize += (*DebugInfo)->getContents().size();892 893    auto &Size = SizeByObject[Context->InputDWARFFile.FileName];894    Size.Input = Context->OriginalDebugInfoSize;895    Size.Output = AllDebugInfoSectionsSize;896  }897 898  // Create a vector sorted in descending order by output size.899  std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;900  for (auto &E : SizeByObject)901    Sorted.emplace_back(E.first(), E.second);902  llvm::sort(Sorted, [](auto &LHS, auto &RHS) {903    return LHS.second.Output > RHS.second.Output;904  });905 906  auto ComputePercentange = [](int64_t Input, int64_t Output) -> float {907    const float Difference = Output - Input;908    const float Sum = Input + Output;909    if (Sum == 0)910      return 0;911    return (Difference / (Sum / 2));912  };913 914  int64_t InputTotal = 0;915  int64_t OutputTotal = 0;916  const char *FormatStr = "{0,-45} {1,10}b  {2,10}b {3,8:P}\n";917 918  // Print header.919  outs() << ".debug_info section size (in bytes)\n";920  outs() << "----------------------------------------------------------------"921            "---------------\n";922  outs() << "Filename                                           Object       "923            "  dSYM   Change\n";924  outs() << "----------------------------------------------------------------"925            "---------------\n";926 927  // Print body.928  for (auto &E : Sorted) {929    InputTotal += E.second.Input;930    OutputTotal += E.second.Output;931    llvm::outs() << formatv(932        FormatStr, sys::path::filename(E.first).take_back(45), E.second.Input,933        E.second.Output, ComputePercentange(E.second.Input, E.second.Output));934  }935  // Print total and footer.936  outs() << "----------------------------------------------------------------"937            "---------------\n";938  llvm::outs() << formatv(FormatStr, "Total", InputTotal, OutputTotal,939                          ComputePercentange(InputTotal, OutputTotal));940  outs() << "----------------------------------------------------------------"941            "---------------\n\n";942}943 944void DWARFLinkerImpl::assignOffsets() {945  llvm::parallel::TaskGroup TGroup;946  TGroup.spawn([&]() { assignOffsetsToStrings(); });947  TGroup.spawn([&]() { assignOffsetsToSections(); });948}949 950void DWARFLinkerImpl::assignOffsetsToStrings() {951  size_t CurDebugStrIndex = 1; // start from 1 to take into account zero entry.952  uint64_t CurDebugStrOffset =953      1; // start from 1 to take into account zero entry.954  size_t CurDebugLineStrIndex = 0;955  uint64_t CurDebugLineStrOffset = 0;956 957  // Enumerates all strings, add them into the DwarfStringPoolEntry map,958  // assign offset and index to the string if it is not indexed yet.959  forEachOutputString([&](StringDestinationKind Kind,960                          const StringEntry *String) {961    switch (Kind) {962    case StringDestinationKind::DebugStr: {963      DwarfStringPoolEntryWithExtString *Entry = DebugStrStrings.add(String);964      assert(Entry != nullptr);965 966      if (!Entry->isIndexed()) {967        Entry->Offset = CurDebugStrOffset;968        CurDebugStrOffset += Entry->String.size() + 1;969        Entry->Index = CurDebugStrIndex++;970      }971    } break;972    case StringDestinationKind::DebugLineStr: {973      DwarfStringPoolEntryWithExtString *Entry =974          DebugLineStrStrings.add(String);975      assert(Entry != nullptr);976 977      if (!Entry->isIndexed()) {978        Entry->Offset = CurDebugLineStrOffset;979        CurDebugLineStrOffset += Entry->String.size() + 1;980        Entry->Index = CurDebugLineStrIndex++;981      }982    } break;983    }984  });985}986 987void DWARFLinkerImpl::assignOffsetsToSections() {988  std::array<uint64_t, SectionKindsNum> SectionSizesAccumulator = {0};989 990  forEachObjectSectionsSet([&](OutputSections &UnitSections) {991    UnitSections.assignSectionsOffsetAndAccumulateSize(SectionSizesAccumulator);992  });993}994 995void DWARFLinkerImpl::forEachOutputString(996    function_ref<void(StringDestinationKind Kind, const StringEntry *String)>997        StringHandler) {998  // To save space we do not create any separate string table.999  // We use already allocated string patches and accelerator entries:1000  // enumerate them in natural order and assign offsets.1001  // ASSUMPTION: strings should be stored into .debug_str/.debug_line_str1002  // sections in the same order as they were assigned offsets.1003  forEachCompileUnit([&](CompileUnit *CU) {1004    CU->forEach([&](SectionDescriptor &OutSection) {1005      OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {1006        StringHandler(StringDestinationKind::DebugStr, Patch.String);1007      });1008 1009      OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {1010        StringHandler(StringDestinationKind::DebugLineStr, Patch.String);1011      });1012    });1013 1014    CU->forEachAcceleratorRecord([&](DwarfUnit::AccelInfo &Info) {1015      StringHandler(DebugStr, Info.String);1016    });1017  });1018 1019  if (ArtificialTypeUnit != nullptr) {1020    ArtificialTypeUnit->forEach([&](SectionDescriptor &OutSection) {1021      OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {1022        StringHandler(StringDestinationKind::DebugStr, Patch.String);1023      });1024 1025      OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {1026        StringHandler(StringDestinationKind::DebugLineStr, Patch.String);1027      });1028 1029      OutSection.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) {1030        if (Patch.Die == nullptr)1031          return;1032 1033        StringHandler(StringDestinationKind::DebugStr, Patch.String);1034      });1035 1036      OutSection.ListDebugTypeLineStrPatch.forEach(1037          [&](DebugTypeLineStrPatch &Patch) {1038            if (Patch.Die == nullptr)1039              return;1040 1041            StringHandler(StringDestinationKind::DebugStr, Patch.String);1042          });1043    });1044  }1045}1046 1047void DWARFLinkerImpl::forEachObjectSectionsSet(1048    function_ref<void(OutputSections &)> SectionsSetHandler) {1049  // Handle artificial type unit first.1050  if (ArtificialTypeUnit != nullptr)1051    SectionsSetHandler(*ArtificialTypeUnit);1052 1053  // Then all modules(before regular compilation units).1054  for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)1055    for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)1056      if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)1057        SectionsSetHandler(*ModuleUnit.Unit);1058 1059  // Finally all compilation units.1060  for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {1061    // Handle object file common sections.1062    SectionsSetHandler(*Context);1063 1064    // Handle compilation units.1065    for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)1066      if (CU->getStage() != CompileUnit::Stage::Skipped)1067        SectionsSetHandler(*CU);1068  }1069}1070 1071void DWARFLinkerImpl::forEachCompileAndTypeUnit(1072    function_ref<void(DwarfUnit *CU)> UnitHandler) {1073  if (ArtificialTypeUnit != nullptr)1074    UnitHandler(ArtificialTypeUnit.get());1075 1076  // Enumerate module units.1077  for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)1078    for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)1079      if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)1080        UnitHandler(ModuleUnit.Unit.get());1081 1082  // Enumerate compile units.1083  for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)1084    for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)1085      if (CU->getStage() != CompileUnit::Stage::Skipped)1086        UnitHandler(CU.get());1087}1088 1089void DWARFLinkerImpl::forEachCompileUnit(1090    function_ref<void(CompileUnit *CU)> UnitHandler) {1091  // Enumerate module units.1092  for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)1093    for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)1094      if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)1095        UnitHandler(ModuleUnit.Unit.get());1096 1097  // Enumerate compile units.1098  for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)1099    for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)1100      if (CU->getStage() != CompileUnit::Stage::Skipped)1101        UnitHandler(CU.get());1102}1103 1104void DWARFLinkerImpl::patchOffsetsAndSizes() {1105  forEachObjectSectionsSet([&](OutputSections &SectionsSet) {1106    SectionsSet.forEach([&](SectionDescriptor &OutSection) {1107      SectionsSet.applyPatches(OutSection, DebugStrStrings, DebugLineStrStrings,1108                               ArtificialTypeUnit.get());1109    });1110  });1111}1112 1113void DWARFLinkerImpl::emitCommonSectionsAndWriteCompileUnitsToTheOutput() {1114  llvm::parallel::TaskGroup TG;1115 1116  // Create section descriptors ahead if they are not exist at the moment.1117  // SectionDescriptors container is not thread safe. Thus we should be sure1118  // that descriptors would not be created in following parallel tasks.1119 1120  CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugStr);1121  CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugLineStr);1122 1123  if (llvm::is_contained(GlobalData.Options.AccelTables,1124                         AccelTableKind::Apple)) {1125    CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleNames);1126    CommonSections.getOrCreateSectionDescriptor(1127        DebugSectionKind::AppleNamespaces);1128    CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleObjC);1129    CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleTypes);1130  }1131 1132  if (llvm::is_contained(GlobalData.Options.AccelTables,1133                         AccelTableKind::DebugNames))1134    CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugNames);1135 1136  // Emit .debug_str and .debug_line_str sections.1137  TG.spawn([&]() { emitStringSections(); });1138 1139  if (llvm::is_contained(GlobalData.Options.AccelTables,1140                         AccelTableKind::Apple)) {1141    // Emit apple accelerator sections.1142    TG.spawn([&]() {1143      emitAppleAcceleratorSections((*GlobalData.getTargetTriple()).get());1144    });1145  }1146 1147  if (llvm::is_contained(GlobalData.Options.AccelTables,1148                         AccelTableKind::DebugNames)) {1149    // Emit .debug_names section.1150    TG.spawn([&]() {1151      emitDWARFv5DebugNamesSection((*GlobalData.getTargetTriple()).get());1152    });1153  }1154 1155  // Write compile units to the output file.1156  TG.spawn([&]() { writeCompileUnitsToTheOutput(); });1157}1158 1159void DWARFLinkerImpl::emitStringSections() {1160  uint64_t DebugStrNextOffset = 0;1161  uint64_t DebugLineStrNextOffset = 0;1162 1163  // Emit zero length string. Accelerator tables does not work correctly1164  // if the first string is not zero length string.1165  CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)1166      .emitInplaceString("");1167  DebugStrNextOffset++;1168 1169  forEachOutputString(1170      [&](StringDestinationKind Kind, const StringEntry *String) {1171        switch (Kind) {1172        case StringDestinationKind::DebugStr: {1173          DwarfStringPoolEntryWithExtString *StringToEmit =1174              DebugStrStrings.getExistingEntry(String);1175          assert(StringToEmit->isIndexed());1176 1177          // Strings may be repeated. Use accumulated DebugStrNextOffset1178          // to understand whether corresponding string is already emitted.1179          // Skip string if its offset less than accumulated offset.1180          if (StringToEmit->Offset >= DebugStrNextOffset) {1181            DebugStrNextOffset =1182                StringToEmit->Offset + StringToEmit->String.size() + 1;1183            // Emit the string itself.1184            CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)1185                .emitInplaceString(StringToEmit->String);1186          }1187        } break;1188        case StringDestinationKind::DebugLineStr: {1189          DwarfStringPoolEntryWithExtString *StringToEmit =1190              DebugLineStrStrings.getExistingEntry(String);1191          assert(StringToEmit->isIndexed());1192 1193          // Strings may be repeated. Use accumulated DebugLineStrStrings1194          // to understand whether corresponding string is already emitted.1195          // Skip string if its offset less than accumulated offset.1196          if (StringToEmit->Offset >= DebugLineStrNextOffset) {1197            DebugLineStrNextOffset =1198                StringToEmit->Offset + StringToEmit->String.size() + 1;1199            // Emit the string itself.1200            CommonSections.getSectionDescriptor(DebugSectionKind::DebugLineStr)1201                .emitInplaceString(StringToEmit->String);1202          }1203        } break;1204        }1205      });1206}1207 1208void DWARFLinkerImpl::emitAppleAcceleratorSections(const Triple &TargetTriple) {1209  AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces;1210  AccelTable<AppleAccelTableStaticOffsetData> AppleNames;1211  AccelTable<AppleAccelTableStaticOffsetData> AppleObjC;1212  AccelTable<AppleAccelTableStaticTypeData> AppleTypes;1213 1214  forEachCompileAndTypeUnit([&](DwarfUnit *CU) {1215    CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {1216      uint64_t OutOffset = Info.OutOffset;1217      switch (Info.Type) {1218      case DwarfUnit::AccelType::None: {1219        llvm_unreachable("Unknown accelerator record");1220      } break;1221      case DwarfUnit::AccelType::Namespace: {1222        AppleNamespaces.addName(1223            *DebugStrStrings.getExistingEntry(Info.String),1224            CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +1225                OutOffset);1226      } break;1227      case DwarfUnit::AccelType::Name: {1228        AppleNames.addName(1229            *DebugStrStrings.getExistingEntry(Info.String),1230            CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +1231                OutOffset);1232      } break;1233      case DwarfUnit::AccelType::ObjC: {1234        AppleObjC.addName(1235            *DebugStrStrings.getExistingEntry(Info.String),1236            CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +1237                OutOffset);1238      } break;1239      case DwarfUnit::AccelType::Type: {1240        AppleTypes.addName(1241            *DebugStrStrings.getExistingEntry(Info.String),1242            CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +1243                OutOffset,1244            Info.Tag,1245            Info.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation1246                                         : 0,1247            Info.QualifiedNameHash);1248      } break;1249      }1250    });1251  });1252 1253  {1254    // FIXME: we use AsmPrinter to emit accelerator sections.1255    // It might be beneficial to directly emit accelerator data1256    // to the raw_svector_ostream.1257    SectionDescriptor &OutSection =1258        CommonSections.getSectionDescriptor(DebugSectionKind::AppleNamespaces);1259    DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,1260                             OutSection.OS);1261    if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {1262      consumeError(std::move(Err));1263      return;1264    }1265 1266    // Emit table.1267    Emitter.emitAppleNamespaces(AppleNamespaces);1268    Emitter.finish();1269 1270    // Set start offset and size for output section.1271    OutSection.setSizesForSectionCreatedByAsmPrinter();1272  }1273 1274  {1275    // FIXME: we use AsmPrinter to emit accelerator sections.1276    // It might be beneficial to directly emit accelerator data1277    // to the raw_svector_ostream.1278    SectionDescriptor &OutSection =1279        CommonSections.getSectionDescriptor(DebugSectionKind::AppleNames);1280    DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,1281                             OutSection.OS);1282    if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {1283      consumeError(std::move(Err));1284      return;1285    }1286 1287    // Emit table.1288    Emitter.emitAppleNames(AppleNames);1289    Emitter.finish();1290 1291    // Set start offset ans size for output section.1292    OutSection.setSizesForSectionCreatedByAsmPrinter();1293  }1294 1295  {1296    // FIXME: we use AsmPrinter to emit accelerator sections.1297    // It might be beneficial to directly emit accelerator data1298    // to the raw_svector_ostream.1299    SectionDescriptor &OutSection =1300        CommonSections.getSectionDescriptor(DebugSectionKind::AppleObjC);1301    DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,1302                             OutSection.OS);1303    if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {1304      consumeError(std::move(Err));1305      return;1306    }1307 1308    // Emit table.1309    Emitter.emitAppleObjc(AppleObjC);1310    Emitter.finish();1311 1312    // Set start offset ans size for output section.1313    OutSection.setSizesForSectionCreatedByAsmPrinter();1314  }1315 1316  {1317    // FIXME: we use AsmPrinter to emit accelerator sections.1318    // It might be beneficial to directly emit accelerator data1319    // to the raw_svector_ostream.1320    SectionDescriptor &OutSection =1321        CommonSections.getSectionDescriptor(DebugSectionKind::AppleTypes);1322    DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,1323                             OutSection.OS);1324    if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {1325      consumeError(std::move(Err));1326      return;1327    }1328 1329    // Emit table.1330    Emitter.emitAppleTypes(AppleTypes);1331    Emitter.finish();1332 1333    // Set start offset ans size for output section.1334    OutSection.setSizesForSectionCreatedByAsmPrinter();1335  }1336}1337 1338void DWARFLinkerImpl::emitDWARFv5DebugNamesSection(const Triple &TargetTriple) {1339  std::unique_ptr<DWARF5AccelTable> DebugNames;1340 1341  DebugNamesUnitsOffsets CompUnits;1342  CompUnitIDToIdx CUidToIdx;1343 1344  unsigned Id = 0;1345 1346  forEachCompileAndTypeUnit([&](DwarfUnit *CU) {1347    bool HasRecords = false;1348    CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {1349      if (DebugNames == nullptr)1350        DebugNames = std::make_unique<DWARF5AccelTable>();1351 1352      HasRecords = true;1353      switch (Info.Type) {1354      case DwarfUnit::AccelType::Name:1355      case DwarfUnit::AccelType::Namespace:1356      case DwarfUnit::AccelType::Type: {1357        DebugNames->addName(*DebugStrStrings.getExistingEntry(Info.String),1358                            Info.OutOffset, std::nullopt /*ParentDIEOffset*/,1359                            Info.Tag, CU->getUniqueID(),1360                            CU->getTag() == dwarf::DW_TAG_type_unit);1361      } break;1362 1363      default:1364        break; // Nothing to do.1365      };1366    });1367 1368    if (HasRecords) {1369      CompUnits.push_back(1370          CU->getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)1371              .StartOffset);1372      CUidToIdx[CU->getUniqueID()] = Id++;1373    }1374  });1375 1376  if (DebugNames != nullptr) {1377    // FIXME: we use AsmPrinter to emit accelerator sections.1378    // It might be beneficial to directly emit accelerator data1379    // to the raw_svector_ostream.1380    SectionDescriptor &OutSection =1381        CommonSections.getSectionDescriptor(DebugSectionKind::DebugNames);1382    DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,1383                             OutSection.OS);1384    if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {1385      consumeError(std::move(Err));1386      return;1387    }1388 1389    // Emit table.1390    Emitter.emitDebugNames(*DebugNames, CompUnits, CUidToIdx);1391    Emitter.finish();1392 1393    // Set start offset ans size for output section.1394    OutSection.setSizesForSectionCreatedByAsmPrinter();1395  }1396}1397 1398void DWARFLinkerImpl::cleanupDataAfterDWARFOutputIsWritten() {1399  GlobalData.getStringPool().clear();1400  DebugStrStrings.clear();1401  DebugLineStrStrings.clear();1402}1403 1404void DWARFLinkerImpl::writeCompileUnitsToTheOutput() {1405  // Enumerate all sections and store them into the final emitter.1406  forEachObjectSectionsSet([&](OutputSections &Sections) {1407    Sections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {1408      // Emit section content.1409      SectionHandler(OutSection);1410    });1411  });1412}1413 1414void DWARFLinkerImpl::writeCommonSectionsToTheOutput() {1415  CommonSections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {1416    SectionHandler(OutSection);1417  });1418}1419