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/ADT/SmallString.h"
18#include "llvm/CodeGen/AccelTable.h"
19#include "llvm/DWARFLinker/Parallel/DWARFLinker.h"
20#include "llvm/DWARFLinker/StringPool.h"
21
22namespace llvm {
23namespace dwarf_linker {
24namespace parallel {
25
26/// This class links debug info.
27class DWARFLinkerImpl : public DWARFLinker {
28public:
29 DWARFLinkerImpl(MessageHandlerTy ErrorHandler,
30 MessageHandlerTy WarningHandler);
31
32 /// Add object file to be linked. Pre-load compile unit die. Call
33 /// \p OnCUDieLoaded for each compile unit die. If specified \p File
34 /// has reference to the Clang module then such module would be
35 /// pre-loaded by \p Loader for !Update case.
36 ///
37 /// \pre NoODR, Update options should be set before call to addObjectFile.
38 void addObjectFile(
39 DWARFFile &File, ObjFileLoaderTy Loader = nullptr,
40
41 CompileUnitHandlerTy OnCUDieLoaded = [](const DWARFUnit &) {}) override;
42
43 /// Link debug info for added files.
44 Error link() override;
45
46 /// Set output DWARF handler. May be not set if output generation is not
47 /// necessary.
48 void setOutputDWARFHandler(const Triple &TargetTriple,
49 SectionHandlerTy SectionHandler) override {
50 GlobalData.setTargetTriple(TargetTriple);
51 this->SectionHandler = SectionHandler;
52 }
53
54 /// \defgroup Methods setting various linking options:
55 ///
56 /// @{
57 ///
58
59 /// Allows to generate log of linking process to the standard output.
60 void setVerbosity(bool Verbose) override {
61 GlobalData.Options.Verbose = Verbose;
62 }
63
64 /// Print statistics to standard output.
65 void setStatistics(bool Statistics) override {
66 GlobalData.Options.Statistics = Statistics;
67 }
68
69 /// Verify the input DWARF.
70 void setVerifyInputDWARF(bool Verify) override {
71 GlobalData.Options.VerifyInputDWARF = Verify;
72 }
73
74 /// Do not unique types according to ODR.
75 void setNoODR(bool NoODR) override { GlobalData.Options.NoODR = NoODR; }
76
77 /// Update index tables only(do not modify rest of DWARF).
78 void setUpdateIndexTablesOnly(bool UpdateIndexTablesOnly) override {
79 GlobalData.Options.UpdateIndexTablesOnly = UpdateIndexTablesOnly;
80 }
81
82 /// Set to keep the enclosing function for a static variable.
83 void setKeepFunctionForStatic(bool KeepFunctionForStatic) override {
84 GlobalData.Options.KeepFunctionForStatic = KeepFunctionForStatic;
85 }
86
87 /// Use specified number of threads for parallel files linking.
88 void setNumThreads(unsigned NumThreads) override {
89 GlobalData.Options.Threads = NumThreads;
90 }
91
92 /// Use the specified thread pool to link the object files.
93 void setThreadPool(ThreadPoolInterface *Pool) override { ThreadPool = Pool; }
94
95 /// Add kind of accelerator tables to be generated.
96 void addAccelTableKind(AccelTableKind Kind) override {
97 assert(!llvm::is_contained(GlobalData.getOptions().AccelTables, Kind));
98 GlobalData.Options.AccelTables.emplace_back(Args&: Kind);
99 }
100
101 /// Set prepend path for clang modules.
102 void setPrependPath(StringRef Ppath) override {
103 GlobalData.Options.PrependPath = Ppath;
104 }
105
106 /// Set estimated objects files amount, for preliminary data allocation.
107 void setEstimatedObjfilesAmount(unsigned ObjFilesNum) override;
108
109 /// Set verification handler which would be used to report verification
110 /// errors.
111 void
112 setInputVerificationHandler(InputVerificationHandlerTy Handler) override {
113 GlobalData.Options.InputVerificationHandler = Handler;
114 }
115
116 /// Set map for Swift interfaces.
117 void setSwiftInterfacesMap(SwiftInterfacesMapTy *Map) override {
118 GlobalData.Options.ParseableSwiftInterfaces = Map;
119 }
120
121 /// Set prefix map for objects.
122 void setObjectPrefixMap(ObjectPrefixMapTy *Map) override {
123 GlobalData.Options.ObjectPrefixMap = Map;
124 }
125
126 /// Set target DWARF version.
127 Error setTargetDWARFVersion(uint16_t TargetDWARFVersion) override {
128 if ((TargetDWARFVersion < 1) || (TargetDWARFVersion > 5))
129 return createStringError(EC: std::errc::invalid_argument,
130 Fmt: "unsupported DWARF version: %d",
131 Vals: TargetDWARFVersion);
132
133 GlobalData.Options.TargetDWARFVersion = TargetDWARFVersion;
134 return Error::success();
135 }
136 /// @}
137
138protected:
139 /// Verify input DWARF file.
140 void verifyInput(const DWARFFile &File);
141
142 /// Validate specified options.
143 Error validateAndUpdateOptions();
144
145 /// Take already linked compile units and glue them into single file.
146 void glueCompileUnitsAndWriteToTheOutput();
147
148 /// Hold the input and output of the debug info size in bytes.
149 struct DebugInfoSize {
150 uint64_t Input;
151 uint64_t Output;
152 };
153
154 friend class DependencyTracker;
155 /// Keeps track of data associated with one object during linking.
156 /// i.e. source file descriptor, compilation units, output data
157 /// for compilation units common tables.
158 struct LinkContext : public OutputSections {
159 using UnitListTy = SmallVector<std::unique_ptr<CompileUnit>>;
160
161 /// Object file descriptor.
162 DWARFFile &InputDWARFFile;
163
164 /// Set of Compilation Units(may be accessed asynchroniously for reading).
165 UnitListTy CompileUnits;
166
167 /// Set of Compile Units for modules.
168 UnitListTy ModulesCompileUnits;
169
170 /// Index of this object file in the link order (used for deterministic
171 /// type DIE allocation).
172 uint64_t ObjectFileIdx = 0;
173
174 /// Size of Debug info before optimizing.
175 uint64_t OriginalDebugInfoSize = 0;
176
177 /// Flag indicating that all inter-connected units are loaded
178 /// and the dwarf linking process for these units is started.
179 bool InterCUProcessingStarted = false;
180
181 StringMap<uint64_t> &ClangModules;
182
183 uint64_t &ModuleUnitIdx;
184
185 /// Flag indicating that new inter-connected compilation units were
186 /// discovered. It is used for restarting units processing
187 /// if new inter-connected units were found.
188 std::atomic<bool> HasNewInterconnectedCUs = {false};
189
190 std::atomic<bool> HasNewGlobalDependency = {false};
191
192 /// Counter for compile units ID.
193 std::atomic<size_t> &UniqueUnitID;
194
195 LinkContext(LinkingGlobalData &GlobalData, DWARFFile &File,
196 uint64_t ObjFileIdx, StringMap<uint64_t> &ClangModules,
197 uint64_t &ModuleUnitIdx, std::atomic<size_t> &UniqueUnitID);
198
199 /// Check whether specified \p CUDie is a Clang module reference.
200 /// if \p Quiet is false then display error messages.
201 /// \return first == true if CUDie is a Clang module reference.
202 /// second == true if module is already loaded.
203 std::pair<bool, bool> isClangModuleRef(const DWARFDie &CUDie,
204 std::string &PCMFile,
205 unsigned Indent, bool Quiet);
206
207 /// If this compile unit is really a skeleton CU that points to a
208 /// clang module, register it in ClangModules and return true.
209 ///
210 /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
211 /// pointing to the module, and a DW_AT_gnu_dwo_id with the module
212 /// hash.
213 bool registerModuleReference(const DWARFDie &CUDie, ObjFileLoaderTy Loader,
214 CompileUnitHandlerTy OnCUDieLoaded,
215 unsigned Indent = 0);
216
217 /// Recursively add the debug info in this clang module .pcm
218 /// file (and all the modules imported by it in a bottom-up fashion)
219 /// to ModuleUnits.
220 Error loadClangModule(ObjFileLoaderTy Loader, const DWARFDie &CUDie,
221 const std::string &PCMFile,
222 CompileUnitHandlerTy OnCUDieLoaded,
223 unsigned Indent = 0);
224
225 /// Computes the total size of the debug info.
226 uint64_t getInputDebugInfoSize() const {
227 uint64_t Size = 0;
228
229 if (InputDWARFFile.Dwarf == nullptr)
230 return Size;
231
232 for (auto &Unit : InputDWARFFile.Dwarf->compile_units())
233 Size += Unit->getLength();
234
235 return Size;
236 }
237
238 /// Section + local offset of a .debug_frame CIE that has been (or will
239 /// be) emitted by some LinkContext. Stored in CIERegistry so that any
240 /// FDE referencing the same CIE bytes can resolve its CIE_pointer to
241 /// OwnerSection->StartOffset + LocalOffset at output time, even when
242 /// the FDE lives in a different LinkContext's section.
243 struct CIELocation {
244 SectionDescriptor *OwnerSection;
245 uint32_t LocalOffset;
246 };
247
248 /// Linker-wide registry for .debug_frame CIEs. The key is the raw CIE
249 /// bytes. Populated by a serial pass over ObjectContexts (so ownership
250 /// is deterministic — first LinkContext wins) and then consumed
251 /// read-only by a parallel emission pass that writes each context's
252 /// .debug_frame section. SectionDescriptor pointers remain valid until
253 /// linking completes because they live in std::map-held shared_ptrs.
254 using CIERegistry = StringMap<CIELocation>;
255
256 /// Result of scanning one LinkContext's input .debug_frame. Produced
257 /// by scanFrameData() during the parallel link phase and consumed by
258 /// the serial CIE-registry merge and parallel emission passes. Owns a
259 /// copy of the raw frame bytes so the StringRef views below remain
260 /// valid after the input DWARFContext is unloaded.
261 struct FrameScanResult {
262 /// Owning copy of the input .debug_frame bytes.
263 SmallString<0> FrameData;
264
265 /// Address size of the input object, used by emitFDE to size the
266 /// FDE's initial_location field.
267 unsigned AddressSize = 0;
268
269 /// Unique CIEs referenced by at least one retained FDE in this
270 /// context, in first-reference order. Each element is a view into
271 /// FrameData and is a key into the linker-wide CIERegistry.
272 SmallVector<StringRef> CIEs;
273
274 /// FDEs retained for emission. CIEBytes is the registry key;
275 /// Instructions is the FDE body after the initial_length /
276 /// CIE_pointer / initial_location fields.
277 struct FDE {
278 StringRef CIEBytes;
279 uint64_t Address = 0;
280 StringRef Instructions;
281 };
282 SmallVector<FDE> FDEs;
283
284 /// CIEs this context owns, set during the serial CIE-registry
285 /// merge. Emission writes these at local offsets 0,
286 /// OwnedCIEs[0].size(), ... in order.
287 SmallVector<StringRef> OwnedCIEs;
288 };
289 std::unique_ptr<FrameScanResult> FrameScan;
290
291 /// Link compile units for this context.
292 Error link(TypeUnit *ArtificialTypeUnit);
293
294 /// Link specified compile unit until specified stage.
295 void linkSingleCompileUnit(
296 CompileUnit &CU, TypeUnit *ArtificialTypeUnit,
297 enum CompileUnit::Stage DoUntilStage = CompileUnit::Stage::Cleaned);
298
299 /// Emit invariant sections.
300 Error emitInvariantSections();
301
302 /// Unload the input DWARFContext after scanning the input .debug_frame into
303 /// FrameScan.
304 Error unloadInput();
305
306 /// Parse this context's input .debug_frame into FrameScan. Deferred
307 /// CIE/FDE emission happens later against the scan result alone.
308 Error scanFrameData();
309
310 /// Register this context's CIEs with the linker-wide registry.
311 void registerCIEs(CIERegistry &CIEs);
312
313 /// Emit this context's .debug_frame section. Safe to call in parallel
314 /// across contexts because each call writes only to its own
315 /// SectionDescriptor.
316 Error emitDebugFrame(const CIERegistry &CIEs);
317
318 /// Emit FDE record.
319 void emitFDE(uint32_t CIEOffset, uint32_t AddrSize, uint64_t Address,
320 StringRef FDEBytes, SectionDescriptor &Section);
321
322 std::function<CompileUnit *(uint64_t)> getUnitForOffset =
323 [&](uint64_t Offset) -> CompileUnit * {
324 auto CU = llvm::upper_bound(
325 Range&: CompileUnits, Value&: Offset,
326 C: [](uint64_t LHS, const std::unique_ptr<CompileUnit> &RHS) {
327 return LHS < RHS->getOrigUnit().getNextUnitOffset();
328 });
329
330 return CU != CompileUnits.end() ? CU->get() : nullptr;
331 };
332 };
333
334 /// Enumerate all compile units and assign offsets to their sections and
335 /// strings.
336 void assignOffsets();
337
338 /// Enumerate all compile units and assign offsets to their sections.
339 void assignOffsetsToSections();
340
341 /// Enumerate all compile units and assign offsets to their strings.
342 void assignOffsetsToStrings();
343
344 /// Print statistic for processed Debug Info.
345 void printStatistic();
346
347 enum StringDestinationKind : uint8_t { DebugStr, DebugLineStr };
348
349 /// Enumerates all strings.
350 void forEachOutputString(
351 function_ref<void(StringDestinationKind, const StringEntry *)>
352 StringHandler);
353
354 /// Enumerates sections for modules, invariant for object files, compile
355 /// units.
356 void forEachObjectSectionsSet(
357 function_ref<void(OutputSections &SectionsSet)> SectionsSetHandler);
358
359 /// Enumerates all compile and type units.
360 void forEachCompileAndTypeUnit(function_ref<void(DwarfUnit *CU)> UnitHandler);
361
362 /// Enumerates all comple units.
363 void forEachCompileUnit(function_ref<void(CompileUnit *CU)> UnitHandler);
364
365 /// Enumerates all patches and update them with the correct values.
366 void patchOffsetsAndSizes();
367
368 /// Emit debug sections common for all input files.
369 void emitCommonSectionsAndWriteCompileUnitsToTheOutput();
370
371 /// Emit apple accelerator sections.
372 void emitAppleAcceleratorSections(const Triple &TargetTriple);
373
374 /// Emit .debug_names section.
375 void emitDWARFv5DebugNamesSection(const Triple &TargetTriple);
376
377 /// Emit string sections.
378 void emitStringSections();
379
380 /// Cleanup data(string pools) after output sections are generated.
381 void cleanupDataAfterDWARFOutputIsWritten();
382
383 /// Enumerate all compile units and put their data into the output stream.
384 void writeCompileUnitsToTheOutput();
385
386 /// Enumerate common sections and put their data into the output stream.
387 void writeCommonSectionsToTheOutput();
388
389 /// The object file index given to every clang module unit. It sorts below
390 /// every object file's, which makes a module unit outrank all of them: the
391 /// definition a module gives of what it defines wins over the copy an
392 /// importer carries.
393 static constexpr uint64_t ModuleUnitObjFileIdx = 0;
394
395 /// Object file indices follow the module units'.
396 static constexpr uint64_t FirstObjFileIdx = ModuleUnitObjFileIdx + 1;
397
398 /// \defgroup Data members accessed asinchroniously.
399 ///
400 /// @{
401
402 /// Unique ID for compile unit.
403 std::atomic<size_t> UniqueUnitID;
404
405 /// Mapping the PCM filename to the DwoId. Only ever touched from
406 /// addObjectFile(), which runs serially, so it needs no synchronization.
407 StringMap<uint64_t> ClangModules;
408
409 /// Numbers the clang module units of the whole link, so that they form one
410 /// priority sequence regardless of which object file referenced a .pcm first.
411 uint64_t ModuleUnitIdx = 0;
412
413 /// Type unit.
414 std::unique_ptr<TypeUnit> ArtificialTypeUnit;
415 /// @}
416
417 /// \defgroup Data members accessed sequentially.
418 ///
419 /// @{
420 /// Data global for the whole linking process.
421 LinkingGlobalData GlobalData;
422
423 /// DwarfStringPoolEntries for .debug_str section.
424 StringEntryToDwarfStringPoolEntryMap DebugStrStrings;
425
426 /// DwarfStringPoolEntries for .debug_line_str section.
427 StringEntryToDwarfStringPoolEntryMap DebugLineStrStrings;
428
429 /// Keeps all linking contexts.
430 SmallVector<std::unique_ptr<LinkContext>> ObjectContexts;
431
432 /// Common sections.
433 OutputSections CommonSections;
434
435 /// Hanler for output sections.
436 SectionHandlerTy SectionHandler = nullptr;
437
438 /// Thread pool that links the object files, or null to use a private pool.
439 ThreadPoolInterface *ThreadPool = nullptr;
440 /// @}
441};
442
443} // end of namespace parallel
444} // end of namespace dwarf_linker
445} // end of namespace llvm
446
447#endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERIMPL_H
448