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