381 lines
13 KiB
C++
381 lines
13 KiB
C++
//===- DWARFLinkerImpl.h ----------------------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERIMPL_H
|
|
#define LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERIMPL_H
|
|
|
|
#include "DWARFEmitterImpl.h"
|
|
#include "DWARFLinkerCompileUnit.h"
|
|
#include "DWARFLinkerTypeUnit.h"
|
|
#include "StringEntryToDwarfStringPoolEntryMap.h"
|
|
#include "llvm/ADT/AddressRanges.h"
|
|
#include "llvm/CodeGen/AccelTable.h"
|
|
#include "llvm/DWARFLinker/Parallel/DWARFLinker.h"
|
|
#include "llvm/DWARFLinker/StringPool.h"
|
|
|
|
namespace llvm {
|
|
namespace dwarf_linker {
|
|
namespace parallel {
|
|
|
|
/// This class links debug info.
|
|
class DWARFLinkerImpl : public DWARFLinker {
|
|
public:
|
|
DWARFLinkerImpl(MessageHandlerTy ErrorHandler,
|
|
MessageHandlerTy WarningHandler,
|
|
TranslatorFuncTy StringsTranslator);
|
|
|
|
/// Add object file to be linked. Pre-load compile unit die. Call
|
|
/// \p OnCUDieLoaded for each compile unit die. If specified \p File
|
|
/// has reference to the Clang module then such module would be
|
|
/// pre-loaded by \p Loader for !Update case.
|
|
///
|
|
/// \pre NoODR, Update options should be set before call to addObjectFile.
|
|
void addObjectFile(
|
|
DWARFFile &File, ObjFileLoaderTy Loader = nullptr,
|
|
|
|
CompileUnitHandlerTy OnCUDieLoaded = [](const DWARFUnit &) {}) override;
|
|
|
|
/// Link debug info for added files.
|
|
Error link() override;
|
|
|
|
/// Set output DWARF handler. May be not set if output generation is not
|
|
/// necessary.
|
|
void setOutputDWARFHandler(const Triple &TargetTriple,
|
|
SectionHandlerTy SectionHandler) override {
|
|
GlobalData.setTargetTriple(TargetTriple);
|
|
this->SectionHandler = SectionHandler;
|
|
}
|
|
|
|
/// \defgroup Methods setting various linking options:
|
|
///
|
|
/// @{
|
|
///
|
|
|
|
/// Allows to generate log of linking process to the standard output.
|
|
void setVerbosity(bool Verbose) override {
|
|
GlobalData.Options.Verbose = Verbose;
|
|
}
|
|
|
|
/// Print statistics to standard output.
|
|
void setStatistics(bool Statistics) override {
|
|
GlobalData.Options.Statistics = Statistics;
|
|
}
|
|
|
|
/// Verify the input DWARF.
|
|
void setVerifyInputDWARF(bool Verify) override {
|
|
GlobalData.Options.VerifyInputDWARF = Verify;
|
|
}
|
|
|
|
/// Do not unique types according to ODR.
|
|
void setNoODR(bool NoODR) override { GlobalData.Options.NoODR = NoODR; }
|
|
|
|
/// Update index tables only(do not modify rest of DWARF).
|
|
void setUpdateIndexTablesOnly(bool UpdateIndexTablesOnly) override {
|
|
GlobalData.Options.UpdateIndexTablesOnly = UpdateIndexTablesOnly;
|
|
}
|
|
|
|
/// Allow generating valid, but non-deterministic output.
|
|
void
|
|
setAllowNonDeterministicOutput(bool AllowNonDeterministicOutput) override {
|
|
GlobalData.Options.AllowNonDeterministicOutput =
|
|
AllowNonDeterministicOutput;
|
|
}
|
|
|
|
/// Set to keep the enclosing function for a static variable.
|
|
void setKeepFunctionForStatic(bool KeepFunctionForStatic) override {
|
|
GlobalData.Options.KeepFunctionForStatic = KeepFunctionForStatic;
|
|
}
|
|
|
|
/// Use specified number of threads for parallel files linking.
|
|
void setNumThreads(unsigned NumThreads) override {
|
|
GlobalData.Options.Threads = NumThreads;
|
|
}
|
|
|
|
/// Add kind of accelerator tables to be generated.
|
|
void addAccelTableKind(AccelTableKind Kind) override {
|
|
assert(!llvm::is_contained(GlobalData.getOptions().AccelTables, Kind));
|
|
GlobalData.Options.AccelTables.emplace_back(Kind);
|
|
}
|
|
|
|
/// Set prepend path for clang modules.
|
|
void setPrependPath(StringRef Ppath) override {
|
|
GlobalData.Options.PrependPath = Ppath;
|
|
}
|
|
|
|
/// Set estimated objects files amount, for preliminary data allocation.
|
|
void setEstimatedObjfilesAmount(unsigned ObjFilesNum) override;
|
|
|
|
/// Set verification handler which would be used to report verification
|
|
/// errors.
|
|
void
|
|
setInputVerificationHandler(InputVerificationHandlerTy Handler) override {
|
|
GlobalData.Options.InputVerificationHandler = Handler;
|
|
}
|
|
|
|
/// Set map for Swift interfaces.
|
|
void setSwiftInterfacesMap(SwiftInterfacesMapTy *Map) override {
|
|
GlobalData.Options.ParseableSwiftInterfaces = Map;
|
|
}
|
|
|
|
/// Set prefix map for objects.
|
|
void setObjectPrefixMap(ObjectPrefixMapTy *Map) override {
|
|
GlobalData.Options.ObjectPrefixMap = Map;
|
|
}
|
|
|
|
/// Set target DWARF version.
|
|
Error setTargetDWARFVersion(uint16_t TargetDWARFVersion) override {
|
|
if ((TargetDWARFVersion < 1) || (TargetDWARFVersion > 5))
|
|
return createStringError(std::errc::invalid_argument,
|
|
"unsupported DWARF version: %d",
|
|
TargetDWARFVersion);
|
|
|
|
GlobalData.Options.TargetDWARFVersion = TargetDWARFVersion;
|
|
return Error::success();
|
|
}
|
|
/// @}
|
|
|
|
protected:
|
|
/// Verify input DWARF file.
|
|
void verifyInput(const DWARFFile &File);
|
|
|
|
/// Validate specified options.
|
|
Error validateAndUpdateOptions();
|
|
|
|
/// Take already linked compile units and glue them into single file.
|
|
void glueCompileUnitsAndWriteToTheOutput();
|
|
|
|
/// Hold the input and output of the debug info size in bytes.
|
|
struct DebugInfoSize {
|
|
uint64_t Input;
|
|
uint64_t Output;
|
|
};
|
|
|
|
friend class DependencyTracker;
|
|
/// Keeps track of data associated with one object during linking.
|
|
/// i.e. source file descriptor, compilation units, output data
|
|
/// for compilation units common tables.
|
|
struct LinkContext : public OutputSections {
|
|
using UnitListTy = SmallVector<std::unique_ptr<CompileUnit>>;
|
|
|
|
/// Keep information for referenced clang module: already loaded DWARF info
|
|
/// of the clang module and a CompileUnit of the module.
|
|
struct RefModuleUnit {
|
|
RefModuleUnit(DWARFFile &File, std::unique_ptr<CompileUnit> Unit);
|
|
RefModuleUnit(RefModuleUnit &&Other);
|
|
RefModuleUnit(const RefModuleUnit &) = delete;
|
|
|
|
DWARFFile &File;
|
|
std::unique_ptr<CompileUnit> Unit;
|
|
};
|
|
using ModuleUnitListTy = SmallVector<RefModuleUnit>;
|
|
|
|
/// Object file descriptor.
|
|
DWARFFile &InputDWARFFile;
|
|
|
|
/// Set of Compilation Units(may be accessed asynchroniously for reading).
|
|
UnitListTy CompileUnits;
|
|
|
|
/// Set of Compile Units for modules.
|
|
ModuleUnitListTy ModulesCompileUnits;
|
|
|
|
/// Size of Debug info before optimizing.
|
|
uint64_t OriginalDebugInfoSize = 0;
|
|
|
|
/// Flag indicating that all inter-connected units are loaded
|
|
/// and the dwarf linking process for these units is started.
|
|
bool InterCUProcessingStarted = false;
|
|
|
|
StringMap<uint64_t> &ClangModules;
|
|
|
|
/// Flag indicating that new inter-connected compilation units were
|
|
/// discovered. It is used for restarting units processing
|
|
/// if new inter-connected units were found.
|
|
std::atomic<bool> HasNewInterconnectedCUs = {false};
|
|
|
|
std::atomic<bool> HasNewGlobalDependency = {false};
|
|
|
|
/// Counter for compile units ID.
|
|
std::atomic<size_t> &UniqueUnitID;
|
|
|
|
LinkContext(LinkingGlobalData &GlobalData, DWARFFile &File,
|
|
StringMap<uint64_t> &ClangModules,
|
|
std::atomic<size_t> &UniqueUnitID);
|
|
|
|
/// Check whether specified \p CUDie is a Clang module reference.
|
|
/// if \p Quiet is false then display error messages.
|
|
/// \return first == true if CUDie is a Clang module reference.
|
|
/// second == true if module is already loaded.
|
|
std::pair<bool, bool> isClangModuleRef(const DWARFDie &CUDie,
|
|
std::string &PCMFile,
|
|
unsigned Indent, bool Quiet);
|
|
|
|
/// If this compile unit is really a skeleton CU that points to a
|
|
/// clang module, register it in ClangModules and return true.
|
|
///
|
|
/// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
|
|
/// pointing to the module, and a DW_AT_gnu_dwo_id with the module
|
|
/// hash.
|
|
bool registerModuleReference(const DWARFDie &CUDie, ObjFileLoaderTy Loader,
|
|
CompileUnitHandlerTy OnCUDieLoaded,
|
|
unsigned Indent = 0);
|
|
|
|
/// Recursively add the debug info in this clang module .pcm
|
|
/// file (and all the modules imported by it in a bottom-up fashion)
|
|
/// to ModuleUnits.
|
|
Error loadClangModule(ObjFileLoaderTy Loader, const DWARFDie &CUDie,
|
|
const std::string &PCMFile,
|
|
CompileUnitHandlerTy OnCUDieLoaded,
|
|
unsigned Indent = 0);
|
|
|
|
/// Add Compile Unit corresponding to the module.
|
|
void addModulesCompileUnit(RefModuleUnit &&Unit);
|
|
|
|
/// Computes the total size of the debug info.
|
|
uint64_t getInputDebugInfoSize() const {
|
|
uint64_t Size = 0;
|
|
|
|
if (InputDWARFFile.Dwarf == nullptr)
|
|
return Size;
|
|
|
|
for (auto &Unit : InputDWARFFile.Dwarf->compile_units())
|
|
Size += Unit->getLength();
|
|
|
|
return Size;
|
|
}
|
|
|
|
/// Link compile units for this context.
|
|
Error link(TypeUnit *ArtificialTypeUnit);
|
|
|
|
/// Link specified compile unit until specified stage.
|
|
void linkSingleCompileUnit(
|
|
CompileUnit &CU, TypeUnit *ArtificialTypeUnit,
|
|
enum CompileUnit::Stage DoUntilStage = CompileUnit::Stage::Cleaned);
|
|
|
|
/// Emit invariant sections.
|
|
Error emitInvariantSections();
|
|
|
|
/// Clone and emit .debug_frame.
|
|
Error cloneAndEmitDebugFrame();
|
|
|
|
/// Emit FDE record.
|
|
void emitFDE(uint32_t CIEOffset, uint32_t AddrSize, uint64_t Address,
|
|
StringRef FDEBytes, SectionDescriptor &Section);
|
|
|
|
std::function<CompileUnit *(uint64_t)> getUnitForOffset =
|
|
[&](uint64_t Offset) -> CompileUnit * {
|
|
auto CU = llvm::upper_bound(
|
|
CompileUnits, Offset,
|
|
[](uint64_t LHS, const std::unique_ptr<CompileUnit> &RHS) {
|
|
return LHS < RHS->getOrigUnit().getNextUnitOffset();
|
|
});
|
|
|
|
return CU != CompileUnits.end() ? CU->get() : nullptr;
|
|
};
|
|
};
|
|
|
|
/// Enumerate all compile units and assign offsets to their sections and
|
|
/// strings.
|
|
void assignOffsets();
|
|
|
|
/// Enumerate all compile units and assign offsets to their sections.
|
|
void assignOffsetsToSections();
|
|
|
|
/// Enumerate all compile units and assign offsets to their strings.
|
|
void assignOffsetsToStrings();
|
|
|
|
/// Print statistic for processed Debug Info.
|
|
void printStatistic();
|
|
|
|
enum StringDestinationKind : uint8_t { DebugStr, DebugLineStr };
|
|
|
|
/// Enumerates all strings.
|
|
void forEachOutputString(
|
|
function_ref<void(StringDestinationKind, const StringEntry *)>
|
|
StringHandler);
|
|
|
|
/// Enumerates sections for modules, invariant for object files, compile
|
|
/// units.
|
|
void forEachObjectSectionsSet(
|
|
function_ref<void(OutputSections &SectionsSet)> SectionsSetHandler);
|
|
|
|
/// Enumerates all compile and type units.
|
|
void forEachCompileAndTypeUnit(function_ref<void(DwarfUnit *CU)> UnitHandler);
|
|
|
|
/// Enumerates all comple units.
|
|
void forEachCompileUnit(function_ref<void(CompileUnit *CU)> UnitHandler);
|
|
|
|
/// Enumerates all patches and update them with the correct values.
|
|
void patchOffsetsAndSizes();
|
|
|
|
/// Emit debug sections common for all input files.
|
|
void emitCommonSectionsAndWriteCompileUnitsToTheOutput();
|
|
|
|
/// Emit apple accelerator sections.
|
|
void emitAppleAcceleratorSections(const Triple &TargetTriple);
|
|
|
|
/// Emit .debug_names section.
|
|
void emitDWARFv5DebugNamesSection(const Triple &TargetTriple);
|
|
|
|
/// Emit string sections.
|
|
void emitStringSections();
|
|
|
|
/// Cleanup data(string pools) after output sections are generated.
|
|
void cleanupDataAfterDWARFOutputIsWritten();
|
|
|
|
/// Enumerate all compile units and put their data into the output stream.
|
|
void writeCompileUnitsToTheOutput();
|
|
|
|
/// Enumerate common sections and put their data into the output stream.
|
|
void writeCommonSectionsToTheOutput();
|
|
|
|
/// \defgroup Data members accessed asinchroniously.
|
|
///
|
|
/// @{
|
|
|
|
/// Unique ID for compile unit.
|
|
std::atomic<size_t> UniqueUnitID;
|
|
|
|
/// Mapping the PCM filename to the DwoId.
|
|
StringMap<uint64_t> ClangModules;
|
|
std::mutex ClangModulesMutex;
|
|
|
|
/// Type unit.
|
|
std::unique_ptr<TypeUnit> ArtificialTypeUnit;
|
|
/// @}
|
|
|
|
/// \defgroup Data members accessed sequentially.
|
|
///
|
|
/// @{
|
|
/// DwarfStringPoolEntries for .debug_str section.
|
|
StringEntryToDwarfStringPoolEntryMap DebugStrStrings;
|
|
|
|
/// DwarfStringPoolEntries for .debug_line_str section.
|
|
StringEntryToDwarfStringPoolEntryMap DebugLineStrStrings;
|
|
|
|
/// Keeps all linking contexts.
|
|
SmallVector<std::unique_ptr<LinkContext>> ObjectContexts;
|
|
|
|
/// Common sections.
|
|
OutputSections CommonSections;
|
|
|
|
/// Hanler for output sections.
|
|
SectionHandlerTy SectionHandler = nullptr;
|
|
|
|
/// Overall compile units number.
|
|
uint64_t OverallNumberOfCU = 0;
|
|
|
|
/// Data global for the whole linking process.
|
|
LinkingGlobalData GlobalData;
|
|
/// @}
|
|
};
|
|
|
|
} // end of namespace parallel
|
|
} // end of namespace dwarf_linker
|
|
} // end of namespace llvm
|
|
|
|
#endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERIMPL_H
|