brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.8 KiB · 597bb1b Raw
381 lines · c
1//===- DWARFLinkerImpl.h ----------------------------------------*- C++ -*-===//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#ifndef LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERIMPL_H10#define LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERIMPL_H11 12#include "DWARFEmitterImpl.h"13#include "DWARFLinkerCompileUnit.h"14#include "DWARFLinkerTypeUnit.h"15#include "StringEntryToDwarfStringPoolEntryMap.h"16#include "llvm/ADT/AddressRanges.h"17#include "llvm/CodeGen/AccelTable.h"18#include "llvm/DWARFLinker/Parallel/DWARFLinker.h"19#include "llvm/DWARFLinker/StringPool.h"20 21namespace llvm {22namespace dwarf_linker {23namespace parallel {24 25/// This class links debug info.26class DWARFLinkerImpl : public DWARFLinker {27public:28  DWARFLinkerImpl(MessageHandlerTy ErrorHandler,29                  MessageHandlerTy WarningHandler);30 31  /// Add object file to be linked. Pre-load compile unit die. Call32  /// \p OnCUDieLoaded for each compile unit die. If specified \p File33  /// has reference to the Clang module then such module would be34  /// pre-loaded by \p Loader for !Update case.35  ///36  /// \pre NoODR, Update options should be set before call to addObjectFile.37  void addObjectFile(38      DWARFFile &File, ObjFileLoaderTy Loader = nullptr,39 40      CompileUnitHandlerTy OnCUDieLoaded = [](const DWARFUnit &) {}) override;41 42  /// Link debug info for added files.43  Error link() override;44 45  /// Set output DWARF handler. May be not set if output generation is not46  /// necessary.47  void setOutputDWARFHandler(const Triple &TargetTriple,48                             SectionHandlerTy SectionHandler) override {49    GlobalData.setTargetTriple(TargetTriple);50    this->SectionHandler = SectionHandler;51  }52 53  /// \defgroup Methods setting various linking options:54  ///55  /// @{56  ///57 58  /// Allows to generate log of linking process to the standard output.59  void setVerbosity(bool Verbose) override {60    GlobalData.Options.Verbose = Verbose;61  }62 63  /// Print statistics to standard output.64  void setStatistics(bool Statistics) override {65    GlobalData.Options.Statistics = Statistics;66  }67 68  /// Verify the input DWARF.69  void setVerifyInputDWARF(bool Verify) override {70    GlobalData.Options.VerifyInputDWARF = Verify;71  }72 73  /// Do not unique types according to ODR.74  void setNoODR(bool NoODR) override { GlobalData.Options.NoODR = NoODR; }75 76  /// Update index tables only(do not modify rest of DWARF).77  void setUpdateIndexTablesOnly(bool UpdateIndexTablesOnly) override {78    GlobalData.Options.UpdateIndexTablesOnly = UpdateIndexTablesOnly;79  }80 81  /// Allow generating valid, but non-deterministic output.82  void83  setAllowNonDeterministicOutput(bool AllowNonDeterministicOutput) override {84    GlobalData.Options.AllowNonDeterministicOutput =85        AllowNonDeterministicOutput;86  }87 88  /// Set to keep the enclosing function for a static variable.89  void setKeepFunctionForStatic(bool KeepFunctionForStatic) override {90    GlobalData.Options.KeepFunctionForStatic = KeepFunctionForStatic;91  }92 93  /// Use specified number of threads for parallel files linking.94  void setNumThreads(unsigned NumThreads) override {95    GlobalData.Options.Threads = NumThreads;96  }97 98  /// Add kind of accelerator tables to be generated.99  void addAccelTableKind(AccelTableKind Kind) override {100    assert(!llvm::is_contained(GlobalData.getOptions().AccelTables, Kind));101    GlobalData.Options.AccelTables.emplace_back(Kind);102  }103 104  /// Set prepend path for clang modules.105  void setPrependPath(StringRef Ppath) override {106    GlobalData.Options.PrependPath = Ppath;107  }108 109  /// Set estimated objects files amount, for preliminary data allocation.110  void setEstimatedObjfilesAmount(unsigned ObjFilesNum) override;111 112  /// Set verification handler which would be used to report verification113  /// errors.114  void115  setInputVerificationHandler(InputVerificationHandlerTy Handler) override {116    GlobalData.Options.InputVerificationHandler = Handler;117  }118 119  /// Set map for Swift interfaces.120  void setSwiftInterfacesMap(SwiftInterfacesMapTy *Map) override {121    GlobalData.Options.ParseableSwiftInterfaces = Map;122  }123 124  /// Set prefix map for objects.125  void setObjectPrefixMap(ObjectPrefixMapTy *Map) override {126    GlobalData.Options.ObjectPrefixMap = Map;127  }128 129  /// Set target DWARF version.130  Error setTargetDWARFVersion(uint16_t TargetDWARFVersion) override {131    if ((TargetDWARFVersion < 1) || (TargetDWARFVersion > 5))132      return createStringError(std::errc::invalid_argument,133                               "unsupported DWARF version: %d",134                               TargetDWARFVersion);135 136    GlobalData.Options.TargetDWARFVersion = TargetDWARFVersion;137    return Error::success();138  }139  /// @}140 141protected:142  /// Verify input DWARF file.143  void verifyInput(const DWARFFile &File);144 145  /// Validate specified options.146  Error validateAndUpdateOptions();147 148  /// Take already linked compile units and glue them into single file.149  void glueCompileUnitsAndWriteToTheOutput();150 151  /// Hold the input and output of the debug info size in bytes.152  struct DebugInfoSize {153    uint64_t Input;154    uint64_t Output;155  };156 157  friend class DependencyTracker;158  /// Keeps track of data associated with one object during linking.159  /// i.e. source file descriptor, compilation units, output data160  /// for compilation units common tables.161  struct LinkContext : public OutputSections {162    using UnitListTy = SmallVector<std::unique_ptr<CompileUnit>>;163 164    /// Keep information for referenced clang module: already loaded DWARF info165    /// of the clang module and a CompileUnit of the module.166    struct RefModuleUnit {167      RefModuleUnit(DWARFFile &File, std::unique_ptr<CompileUnit> Unit);168      RefModuleUnit(RefModuleUnit &&Other);169      RefModuleUnit(const RefModuleUnit &) = delete;170 171      DWARFFile &File;172      std::unique_ptr<CompileUnit> Unit;173    };174    using ModuleUnitListTy = SmallVector<RefModuleUnit>;175 176    /// Object file descriptor.177    DWARFFile &InputDWARFFile;178 179    /// Set of Compilation Units(may be accessed asynchroniously for reading).180    UnitListTy CompileUnits;181 182    /// Set of Compile Units for modules.183    ModuleUnitListTy ModulesCompileUnits;184 185    /// Size of Debug info before optimizing.186    uint64_t OriginalDebugInfoSize = 0;187 188    /// Flag indicating that all inter-connected units are loaded189    /// and the dwarf linking process for these units is started.190    bool InterCUProcessingStarted = false;191 192    StringMap<uint64_t> &ClangModules;193 194    /// Flag indicating that new inter-connected compilation units were195    /// discovered. It is used for restarting units processing196    /// if new inter-connected units were found.197    std::atomic<bool> HasNewInterconnectedCUs = {false};198 199    std::atomic<bool> HasNewGlobalDependency = {false};200 201    /// Counter for compile units ID.202    std::atomic<size_t> &UniqueUnitID;203 204    LinkContext(LinkingGlobalData &GlobalData, DWARFFile &File,205                StringMap<uint64_t> &ClangModules,206                std::atomic<size_t> &UniqueUnitID);207 208    /// Check whether specified \p CUDie is a Clang module reference.209    /// if \p Quiet is false then display error messages.210    /// \return first == true if CUDie is a Clang module reference.211    ///         second == true if module is already loaded.212    std::pair<bool, bool> isClangModuleRef(const DWARFDie &CUDie,213                                           std::string &PCMFile,214                                           unsigned Indent, bool Quiet);215 216    /// If this compile unit is really a skeleton CU that points to a217    /// clang module, register it in ClangModules and return true.218    ///219    /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name220    /// pointing to the module, and a DW_AT_gnu_dwo_id with the module221    /// hash.222    bool registerModuleReference(const DWARFDie &CUDie, ObjFileLoaderTy Loader,223                                 CompileUnitHandlerTy OnCUDieLoaded,224                                 unsigned Indent = 0);225 226    /// Recursively add the debug info in this clang module .pcm227    /// file (and all the modules imported by it in a bottom-up fashion)228    /// to ModuleUnits.229    Error loadClangModule(ObjFileLoaderTy Loader, const DWARFDie &CUDie,230                          const std::string &PCMFile,231                          CompileUnitHandlerTy OnCUDieLoaded,232                          unsigned Indent = 0);233 234    /// Add Compile Unit corresponding to the module.235    void addModulesCompileUnit(RefModuleUnit &&Unit);236 237    /// Computes the total size of the debug info.238    uint64_t getInputDebugInfoSize() const {239      uint64_t Size = 0;240 241      if (InputDWARFFile.Dwarf == nullptr)242        return Size;243 244      for (auto &Unit : InputDWARFFile.Dwarf->compile_units())245        Size += Unit->getLength();246 247      return Size;248    }249 250    /// Link compile units for this context.251    Error link(TypeUnit *ArtificialTypeUnit);252 253    /// Link specified compile unit until specified stage.254    void linkSingleCompileUnit(255        CompileUnit &CU, TypeUnit *ArtificialTypeUnit,256        enum CompileUnit::Stage DoUntilStage = CompileUnit::Stage::Cleaned);257 258    /// Emit invariant sections.259    Error emitInvariantSections();260 261    /// Clone and emit .debug_frame.262    Error cloneAndEmitDebugFrame();263 264    /// Emit FDE record.265    void emitFDE(uint32_t CIEOffset, uint32_t AddrSize, uint64_t Address,266                 StringRef FDEBytes, SectionDescriptor &Section);267 268    std::function<CompileUnit *(uint64_t)> getUnitForOffset =269        [&](uint64_t Offset) -> CompileUnit * {270      auto CU = llvm::upper_bound(271          CompileUnits, Offset,272          [](uint64_t LHS, const std::unique_ptr<CompileUnit> &RHS) {273            return LHS < RHS->getOrigUnit().getNextUnitOffset();274          });275 276      return CU != CompileUnits.end() ? CU->get() : nullptr;277    };278  };279 280  /// Enumerate all compile units and assign offsets to their sections and281  /// strings.282  void assignOffsets();283 284  /// Enumerate all compile units and assign offsets to their sections.285  void assignOffsetsToSections();286 287  /// Enumerate all compile units and assign offsets to their strings.288  void assignOffsetsToStrings();289 290  /// Print statistic for processed Debug Info.291  void printStatistic();292 293  enum StringDestinationKind : uint8_t { DebugStr, DebugLineStr };294 295  /// Enumerates all strings.296  void forEachOutputString(297      function_ref<void(StringDestinationKind, const StringEntry *)>298          StringHandler);299 300  /// Enumerates sections for modules, invariant for object files, compile301  /// units.302  void forEachObjectSectionsSet(303      function_ref<void(OutputSections &SectionsSet)> SectionsSetHandler);304 305  /// Enumerates all compile and type units.306  void forEachCompileAndTypeUnit(function_ref<void(DwarfUnit *CU)> UnitHandler);307 308  /// Enumerates all comple units.309  void forEachCompileUnit(function_ref<void(CompileUnit *CU)> UnitHandler);310 311  /// Enumerates all patches and update them with the correct values.312  void patchOffsetsAndSizes();313 314  /// Emit debug sections common for all input files.315  void emitCommonSectionsAndWriteCompileUnitsToTheOutput();316 317  /// Emit apple accelerator sections.318  void emitAppleAcceleratorSections(const Triple &TargetTriple);319 320  /// Emit .debug_names section.321  void emitDWARFv5DebugNamesSection(const Triple &TargetTriple);322 323  /// Emit string sections.324  void emitStringSections();325 326  /// Cleanup data(string pools) after output sections are generated.327  void cleanupDataAfterDWARFOutputIsWritten();328 329  /// Enumerate all compile units and put their data into the output stream.330  void writeCompileUnitsToTheOutput();331 332  /// Enumerate common sections and put their data into the output stream.333  void writeCommonSectionsToTheOutput();334 335  /// \defgroup Data members accessed asinchroniously.336  ///337  /// @{338 339  /// Unique ID for compile unit.340  std::atomic<size_t> UniqueUnitID;341 342  /// Mapping the PCM filename to the DwoId.343  StringMap<uint64_t> ClangModules;344  std::mutex ClangModulesMutex;345 346  /// Type unit.347  std::unique_ptr<TypeUnit> ArtificialTypeUnit;348  /// @}349 350  /// \defgroup Data members accessed sequentially.351  ///352  /// @{353  /// Data global for the whole linking process.354  LinkingGlobalData GlobalData;355 356  /// DwarfStringPoolEntries for .debug_str section.357  StringEntryToDwarfStringPoolEntryMap DebugStrStrings;358 359  /// DwarfStringPoolEntries for .debug_line_str section.360  StringEntryToDwarfStringPoolEntryMap DebugLineStrStrings;361 362  /// Keeps all linking contexts.363  SmallVector<std::unique_ptr<LinkContext>> ObjectContexts;364 365  /// Common sections.366  OutputSections CommonSections;367 368  /// Hanler for output sections.369  SectionHandlerTy SectionHandler = nullptr;370 371  /// Overall compile units number.372  uint64_t OverallNumberOfCU = 0;373  /// @}374};375 376} // end of namespace parallel377} // end of namespace dwarf_linker378} // end of namespace llvm379 380#endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERIMPL_H381