Path: blob/main/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h
35292 views
//===- DWARFLinkerImpl.h ----------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERIMPL_H9#define LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERIMPL_H1011#include "DWARFEmitterImpl.h"12#include "DWARFLinkerCompileUnit.h"13#include "DWARFLinkerTypeUnit.h"14#include "StringEntryToDwarfStringPoolEntryMap.h"15#include "llvm/ADT/AddressRanges.h"16#include "llvm/CodeGen/AccelTable.h"17#include "llvm/DWARFLinker/Parallel/DWARFLinker.h"18#include "llvm/DWARFLinker/StringPool.h"1920namespace llvm {21namespace dwarf_linker {22namespace parallel {2324/// This class links debug info.25class DWARFLinkerImpl : public DWARFLinker {26public:27DWARFLinkerImpl(MessageHandlerTy ErrorHandler,28MessageHandlerTy WarningHandler);2930/// Add object file to be linked. Pre-load compile unit die. Call31/// \p OnCUDieLoaded for each compile unit die. If specified \p File32/// has reference to the Clang module then such module would be33/// pre-loaded by \p Loader for !Update case.34///35/// \pre NoODR, Update options should be set before call to addObjectFile.36void addObjectFile(37DWARFFile &File, ObjFileLoaderTy Loader = nullptr,3839CompileUnitHandlerTy OnCUDieLoaded = [](const DWARFUnit &) {}) override;4041/// Link debug info for added files.42Error link() override;4344/// Set output DWARF handler. May be not set if output generation is not45/// necessary.46void setOutputDWARFHandler(const Triple &TargetTriple,47SectionHandlerTy SectionHandler) override {48GlobalData.setTargetTriple(TargetTriple);49this->SectionHandler = SectionHandler;50}5152/// \defgroup Methods setting various linking options:53///54/// @{55///5657/// Allows to generate log of linking process to the standard output.58void setVerbosity(bool Verbose) override {59GlobalData.Options.Verbose = Verbose;60}6162/// Print statistics to standard output.63void setStatistics(bool Statistics) override {64GlobalData.Options.Statistics = Statistics;65}6667/// Verify the input DWARF.68void setVerifyInputDWARF(bool Verify) override {69GlobalData.Options.VerifyInputDWARF = Verify;70}7172/// Do not unique types according to ODR.73void setNoODR(bool NoODR) override { GlobalData.Options.NoODR = NoODR; }7475/// Update index tables only(do not modify rest of DWARF).76void setUpdateIndexTablesOnly(bool UpdateIndexTablesOnly) override {77GlobalData.Options.UpdateIndexTablesOnly = UpdateIndexTablesOnly;78}7980/// Allow generating valid, but non-deterministic output.81void82setAllowNonDeterministicOutput(bool AllowNonDeterministicOutput) override {83GlobalData.Options.AllowNonDeterministicOutput =84AllowNonDeterministicOutput;85}8687/// Set to keep the enclosing function for a static variable.88void setKeepFunctionForStatic(bool KeepFunctionForStatic) override {89GlobalData.Options.KeepFunctionForStatic = KeepFunctionForStatic;90}9192/// Use specified number of threads for parallel files linking.93void setNumThreads(unsigned NumThreads) override {94GlobalData.Options.Threads = NumThreads;95}9697/// Add kind of accelerator tables to be generated.98void addAccelTableKind(AccelTableKind Kind) override {99assert(!llvm::is_contained(GlobalData.getOptions().AccelTables, Kind));100GlobalData.Options.AccelTables.emplace_back(Kind);101}102103/// Set prepend path for clang modules.104void setPrependPath(StringRef Ppath) override {105GlobalData.Options.PrependPath = Ppath;106}107108/// Set estimated objects files amount, for preliminary data allocation.109void setEstimatedObjfilesAmount(unsigned ObjFilesNum) override;110111/// Set verification handler which would be used to report verification112/// errors.113void114setInputVerificationHandler(InputVerificationHandlerTy Handler) override {115GlobalData.Options.InputVerificationHandler = Handler;116}117118/// Set map for Swift interfaces.119void setSwiftInterfacesMap(SwiftInterfacesMapTy *Map) override {120GlobalData.Options.ParseableSwiftInterfaces = Map;121}122123/// Set prefix map for objects.124void setObjectPrefixMap(ObjectPrefixMapTy *Map) override {125GlobalData.Options.ObjectPrefixMap = Map;126}127128/// Set target DWARF version.129Error setTargetDWARFVersion(uint16_t TargetDWARFVersion) override {130if ((TargetDWARFVersion < 1) || (TargetDWARFVersion > 5))131return createStringError(std::errc::invalid_argument,132"unsupported DWARF version: %d",133TargetDWARFVersion);134135GlobalData.Options.TargetDWARFVersion = TargetDWARFVersion;136return Error::success();137}138/// @}139140protected:141/// Verify input DWARF file.142void verifyInput(const DWARFFile &File);143144/// Validate specified options.145Error validateAndUpdateOptions();146147/// Take already linked compile units and glue them into single file.148void glueCompileUnitsAndWriteToTheOutput();149150/// Hold the input and output of the debug info size in bytes.151struct DebugInfoSize {152uint64_t Input;153uint64_t Output;154};155156friend class DependencyTracker;157/// Keeps track of data associated with one object during linking.158/// i.e. source file descriptor, compilation units, output data159/// for compilation units common tables.160struct LinkContext : public OutputSections {161using UnitListTy = SmallVector<std::unique_ptr<CompileUnit>>;162163/// Keep information for referenced clang module: already loaded DWARF info164/// of the clang module and a CompileUnit of the module.165struct RefModuleUnit {166RefModuleUnit(DWARFFile &File, std::unique_ptr<CompileUnit> Unit);167RefModuleUnit(RefModuleUnit &&Other);168RefModuleUnit(const RefModuleUnit &) = delete;169170DWARFFile &File;171std::unique_ptr<CompileUnit> Unit;172};173using ModuleUnitListTy = SmallVector<RefModuleUnit>;174175/// Object file descriptor.176DWARFFile &InputDWARFFile;177178/// Set of Compilation Units(may be accessed asynchroniously for reading).179UnitListTy CompileUnits;180181/// Set of Compile Units for modules.182ModuleUnitListTy ModulesCompileUnits;183184/// Size of Debug info before optimizing.185uint64_t OriginalDebugInfoSize = 0;186187/// Flag indicating that all inter-connected units are loaded188/// and the dwarf linking process for these units is started.189bool InterCUProcessingStarted = false;190191StringMap<uint64_t> &ClangModules;192193/// Flag indicating that new inter-connected compilation units were194/// discovered. It is used for restarting units processing195/// if new inter-connected units were found.196std::atomic<bool> HasNewInterconnectedCUs = {false};197198std::atomic<bool> HasNewGlobalDependency = {false};199200/// Counter for compile units ID.201std::atomic<size_t> &UniqueUnitID;202203LinkContext(LinkingGlobalData &GlobalData, DWARFFile &File,204StringMap<uint64_t> &ClangModules,205std::atomic<size_t> &UniqueUnitID);206207/// Check whether specified \p CUDie is a Clang module reference.208/// if \p Quiet is false then display error messages.209/// \return first == true if CUDie is a Clang module reference.210/// second == true if module is already loaded.211std::pair<bool, bool> isClangModuleRef(const DWARFDie &CUDie,212std::string &PCMFile,213unsigned Indent, bool Quiet);214215/// If this compile unit is really a skeleton CU that points to a216/// clang module, register it in ClangModules and return true.217///218/// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name219/// pointing to the module, and a DW_AT_gnu_dwo_id with the module220/// hash.221bool registerModuleReference(const DWARFDie &CUDie, ObjFileLoaderTy Loader,222CompileUnitHandlerTy OnCUDieLoaded,223unsigned Indent = 0);224225/// Recursively add the debug info in this clang module .pcm226/// file (and all the modules imported by it in a bottom-up fashion)227/// to ModuleUnits.228Error loadClangModule(ObjFileLoaderTy Loader, const DWARFDie &CUDie,229const std::string &PCMFile,230CompileUnitHandlerTy OnCUDieLoaded,231unsigned Indent = 0);232233/// Add Compile Unit corresponding to the module.234void addModulesCompileUnit(RefModuleUnit &&Unit);235236/// Computes the total size of the debug info.237uint64_t getInputDebugInfoSize() const {238uint64_t Size = 0;239240if (InputDWARFFile.Dwarf == nullptr)241return Size;242243for (auto &Unit : InputDWARFFile.Dwarf->compile_units())244Size += Unit->getLength();245246return Size;247}248249/// Link compile units for this context.250Error link(TypeUnit *ArtificialTypeUnit);251252/// Link specified compile unit until specified stage.253void linkSingleCompileUnit(254CompileUnit &CU, TypeUnit *ArtificialTypeUnit,255enum CompileUnit::Stage DoUntilStage = CompileUnit::Stage::Cleaned);256257/// Emit invariant sections.258Error emitInvariantSections();259260/// Clone and emit .debug_frame.261Error cloneAndEmitDebugFrame();262263/// Emit FDE record.264void emitFDE(uint32_t CIEOffset, uint32_t AddrSize, uint64_t Address,265StringRef FDEBytes, SectionDescriptor &Section);266267std::function<CompileUnit *(uint64_t)> getUnitForOffset =268[&](uint64_t Offset) -> CompileUnit * {269auto CU = llvm::upper_bound(270CompileUnits, Offset,271[](uint64_t LHS, const std::unique_ptr<CompileUnit> &RHS) {272return LHS < RHS->getOrigUnit().getNextUnitOffset();273});274275return CU != CompileUnits.end() ? CU->get() : nullptr;276};277};278279/// Enumerate all compile units and assign offsets to their sections and280/// strings.281void assignOffsets();282283/// Enumerate all compile units and assign offsets to their sections.284void assignOffsetsToSections();285286/// Enumerate all compile units and assign offsets to their strings.287void assignOffsetsToStrings();288289/// Print statistic for processed Debug Info.290void printStatistic();291292enum StringDestinationKind : uint8_t { DebugStr, DebugLineStr };293294/// Enumerates all strings.295void forEachOutputString(296function_ref<void(StringDestinationKind, const StringEntry *)>297StringHandler);298299/// Enumerates sections for modules, invariant for object files, compile300/// units.301void forEachObjectSectionsSet(302function_ref<void(OutputSections &SectionsSet)> SectionsSetHandler);303304/// Enumerates all compile and type units.305void forEachCompileAndTypeUnit(function_ref<void(DwarfUnit *CU)> UnitHandler);306307/// Enumerates all comple units.308void forEachCompileUnit(function_ref<void(CompileUnit *CU)> UnitHandler);309310/// Enumerates all patches and update them with the correct values.311void patchOffsetsAndSizes();312313/// Emit debug sections common for all input files.314void emitCommonSectionsAndWriteCompileUnitsToTheOutput();315316/// Emit apple accelerator sections.317void emitAppleAcceleratorSections(const Triple &TargetTriple);318319/// Emit .debug_names section.320void emitDWARFv5DebugNamesSection(const Triple &TargetTriple);321322/// Emit string sections.323void emitStringSections();324325/// Cleanup data(string pools) after output sections are generated.326void cleanupDataAfterDWARFOutputIsWritten();327328/// Enumerate all compile units and put their data into the output stream.329void writeCompileUnitsToTheOutput();330331/// Enumerate common sections and put their data into the output stream.332void writeCommonSectionsToTheOutput();333334/// \defgroup Data members accessed asinchroniously.335///336/// @{337338/// Unique ID for compile unit.339std::atomic<size_t> UniqueUnitID;340341/// Mapping the PCM filename to the DwoId.342StringMap<uint64_t> ClangModules;343std::mutex ClangModulesMutex;344345/// Type unit.346std::unique_ptr<TypeUnit> ArtificialTypeUnit;347/// @}348349/// \defgroup Data members accessed sequentially.350///351/// @{352/// Data global for the whole linking process.353LinkingGlobalData GlobalData;354355/// DwarfStringPoolEntries for .debug_str section.356StringEntryToDwarfStringPoolEntryMap DebugStrStrings;357358/// DwarfStringPoolEntries for .debug_line_str section.359StringEntryToDwarfStringPoolEntryMap DebugLineStrStrings;360361/// Keeps all linking contexts.362SmallVector<std::unique_ptr<LinkContext>> ObjectContexts;363364/// Common sections.365OutputSections CommonSections;366367/// Hanler for output sections.368SectionHandlerTy SectionHandler = nullptr;369370/// Overall compile units number.371uint64_t OverallNumberOfCU = 0;372/// @}373};374375} // end of namespace parallel376} // end of namespace dwarf_linker377} // end of namespace llvm378379#endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERIMPL_H380381382