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