Jonas Devlieghere 32a6e9d669
[dsymutil] Remove support for obfuscated bitcode (#85713)
Remove support for obfuscated bitcode in dsymutil and the DWARF linker.
We no longer support bitcode submissions and the obfuscation support has
been removed from the rest of the compiler.

rdar://123863918
2024-03-19 12:30:50 -07:00

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);
/// 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.
///
/// @{
/// Data global for the whole linking process.
LinkingGlobalData GlobalData;
/// 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;
/// @}
};
} // end of namespace parallel
} // end of namespace dwarf_linker
} // end of namespace llvm
#endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERIMPL_H