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.cpp
35291 views
1
//=== DWARFLinkerImpl.cpp -------------------------------------------------===//
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
#include "DWARFLinkerImpl.h"
10
#include "DIEGenerator.h"
11
#include "DependencyTracker.h"
12
#include "llvm/DWARFLinker/Utils.h"
13
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
14
#include "llvm/Support/FormatVariadic.h"
15
#include "llvm/Support/Parallel.h"
16
#include "llvm/Support/ThreadPool.h"
17
18
using namespace llvm;
19
using namespace dwarf_linker;
20
using namespace dwarf_linker::parallel;
21
22
DWARFLinkerImpl::DWARFLinkerImpl(MessageHandlerTy ErrorHandler,
23
MessageHandlerTy WarningHandler)
24
: UniqueUnitID(0), DebugStrStrings(GlobalData),
25
DebugLineStrStrings(GlobalData), CommonSections(GlobalData) {
26
GlobalData.setErrorHandler(ErrorHandler);
27
GlobalData.setWarningHandler(WarningHandler);
28
}
29
30
DWARFLinkerImpl::LinkContext::LinkContext(LinkingGlobalData &GlobalData,
31
DWARFFile &File,
32
StringMap<uint64_t> &ClangModules,
33
std::atomic<size_t> &UniqueUnitID)
34
: OutputSections(GlobalData), InputDWARFFile(File),
35
ClangModules(ClangModules), UniqueUnitID(UniqueUnitID) {
36
37
if (File.Dwarf) {
38
if (!File.Dwarf->compile_units().empty())
39
CompileUnits.reserve(File.Dwarf->getNumCompileUnits());
40
41
// Set context format&endianness based on the input file.
42
Format.Version = File.Dwarf->getMaxVersion();
43
Format.AddrSize = File.Dwarf->getCUAddrSize();
44
Endianness = File.Dwarf->isLittleEndian() ? llvm::endianness::little
45
: llvm::endianness::big;
46
}
47
}
48
49
DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit(
50
DWARFFile &File, std::unique_ptr<CompileUnit> Unit)
51
: File(File), Unit(std::move(Unit)) {}
52
53
DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit(
54
LinkContext::RefModuleUnit &&Other)
55
: File(Other.File), Unit(std::move(Other.Unit)) {}
56
57
void DWARFLinkerImpl::LinkContext::addModulesCompileUnit(
58
LinkContext::RefModuleUnit &&Unit) {
59
ModulesCompileUnits.emplace_back(std::move(Unit));
60
}
61
62
void DWARFLinkerImpl::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader,
63
CompileUnitHandlerTy OnCUDieLoaded) {
64
ObjectContexts.emplace_back(std::make_unique<LinkContext>(
65
GlobalData, File, ClangModules, UniqueUnitID));
66
67
if (ObjectContexts.back()->InputDWARFFile.Dwarf) {
68
for (const std::unique_ptr<DWARFUnit> &CU :
69
ObjectContexts.back()->InputDWARFFile.Dwarf->compile_units()) {
70
DWARFDie CUDie = CU->getUnitDIE();
71
OverallNumberOfCU++;
72
73
if (!CUDie)
74
continue;
75
76
OnCUDieLoaded(*CU);
77
78
// Register mofule reference.
79
if (!GlobalData.getOptions().UpdateIndexTablesOnly)
80
ObjectContexts.back()->registerModuleReference(CUDie, Loader,
81
OnCUDieLoaded);
82
}
83
}
84
}
85
86
void DWARFLinkerImpl::setEstimatedObjfilesAmount(unsigned ObjFilesNum) {
87
ObjectContexts.reserve(ObjFilesNum);
88
}
89
90
Error DWARFLinkerImpl::link() {
91
// reset compile unit unique ID counter.
92
UniqueUnitID = 0;
93
94
if (Error Err = validateAndUpdateOptions())
95
return Err;
96
97
dwarf::FormParams GlobalFormat = {GlobalData.getOptions().TargetDWARFVersion,
98
0, dwarf::DwarfFormat::DWARF32};
99
llvm::endianness GlobalEndianness = llvm::endianness::native;
100
101
if (std::optional<std::reference_wrapper<const Triple>> CurTriple =
102
GlobalData.getTargetTriple()) {
103
GlobalEndianness = (*CurTriple).get().isLittleEndian()
104
? llvm::endianness::little
105
: llvm::endianness::big;
106
}
107
std::optional<uint16_t> Language;
108
109
for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
110
if (Context->InputDWARFFile.Dwarf == nullptr) {
111
Context->setOutputFormat(Context->getFormParams(), GlobalEndianness);
112
continue;
113
}
114
115
if (GlobalData.getOptions().Verbose) {
116
outs() << "DEBUG MAP OBJECT: " << Context->InputDWARFFile.FileName
117
<< "\n";
118
119
for (const std::unique_ptr<DWARFUnit> &OrigCU :
120
Context->InputDWARFFile.Dwarf->compile_units()) {
121
outs() << "Input compilation unit:";
122
DIDumpOptions DumpOpts;
123
DumpOpts.ChildRecurseDepth = 0;
124
DumpOpts.Verbose = GlobalData.getOptions().Verbose;
125
OrigCU->getUnitDIE().dump(outs(), 0, DumpOpts);
126
}
127
}
128
129
// Verify input DWARF if requested.
130
if (GlobalData.getOptions().VerifyInputDWARF)
131
verifyInput(Context->InputDWARFFile);
132
133
if (!GlobalData.getTargetTriple())
134
GlobalEndianness = Context->getEndianness();
135
GlobalFormat.AddrSize =
136
std::max(GlobalFormat.AddrSize, Context->getFormParams().AddrSize);
137
138
Context->setOutputFormat(Context->getFormParams(), GlobalEndianness);
139
140
// FIXME: move creation of CompileUnits into the addObjectFile.
141
// This would allow to not scan for context Language and Modules state
142
// twice. And then following handling might be removed.
143
for (const std::unique_ptr<DWARFUnit> &OrigCU :
144
Context->InputDWARFFile.Dwarf->compile_units()) {
145
DWARFDie UnitDie = OrigCU->getUnitDIE();
146
147
if (!Language) {
148
if (std::optional<DWARFFormValue> Val =
149
UnitDie.find(dwarf::DW_AT_language)) {
150
uint16_t LangVal = dwarf::toUnsigned(Val, 0);
151
if (isODRLanguage(LangVal))
152
Language = LangVal;
153
}
154
}
155
}
156
}
157
158
if (GlobalFormat.AddrSize == 0) {
159
if (std::optional<std::reference_wrapper<const Triple>> TargetTriple =
160
GlobalData.getTargetTriple())
161
GlobalFormat.AddrSize = (*TargetTriple).get().isArch32Bit() ? 4 : 8;
162
else
163
GlobalFormat.AddrSize = 8;
164
}
165
166
CommonSections.setOutputFormat(GlobalFormat, GlobalEndianness);
167
168
if (!GlobalData.Options.NoODR && Language.has_value()) {
169
llvm::parallel::TaskGroup TGroup;
170
TGroup.spawn([&]() {
171
ArtificialTypeUnit = std::make_unique<TypeUnit>(
172
GlobalData, UniqueUnitID++, Language, GlobalFormat, GlobalEndianness);
173
});
174
}
175
176
// Set parallel options.
177
if (GlobalData.getOptions().Threads == 0)
178
llvm::parallel::strategy = optimal_concurrency(OverallNumberOfCU);
179
else
180
llvm::parallel::strategy =
181
hardware_concurrency(GlobalData.getOptions().Threads);
182
183
// Link object files.
184
if (GlobalData.getOptions().Threads == 1) {
185
for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
186
// Link object file.
187
if (Error Err = Context->link(ArtificialTypeUnit.get()))
188
GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
189
190
Context->InputDWARFFile.unload();
191
}
192
} else {
193
DefaultThreadPool Pool(llvm::parallel::strategy);
194
for (std::unique_ptr<LinkContext> &Context : ObjectContexts)
195
Pool.async([&]() {
196
// Link object file.
197
if (Error Err = Context->link(ArtificialTypeUnit.get()))
198
GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
199
200
Context->InputDWARFFile.unload();
201
});
202
203
Pool.wait();
204
}
205
206
if (ArtificialTypeUnit != nullptr && !ArtificialTypeUnit->getTypePool()
207
.getRoot()
208
->getValue()
209
.load()
210
->Children.empty()) {
211
if (GlobalData.getTargetTriple().has_value())
212
if (Error Err = ArtificialTypeUnit->finishCloningAndEmit(
213
(*GlobalData.getTargetTriple()).get()))
214
return Err;
215
}
216
217
// At this stage each compile units are cloned to their own set of debug
218
// sections. Now, update patches, assign offsets and assemble final file
219
// glueing debug tables from each compile unit.
220
glueCompileUnitsAndWriteToTheOutput();
221
222
return Error::success();
223
}
224
225
void DWARFLinkerImpl::verifyInput(const DWARFFile &File) {
226
assert(File.Dwarf);
227
228
std::string Buffer;
229
raw_string_ostream OS(Buffer);
230
DIDumpOptions DumpOpts;
231
if (!File.Dwarf->verify(OS, DumpOpts.noImplicitRecursion())) {
232
if (GlobalData.getOptions().InputVerificationHandler)
233
GlobalData.getOptions().InputVerificationHandler(File, OS.str());
234
}
235
}
236
237
Error DWARFLinkerImpl::validateAndUpdateOptions() {
238
if (GlobalData.getOptions().TargetDWARFVersion == 0)
239
return createStringError(std::errc::invalid_argument,
240
"target DWARF version is not set");
241
242
if (GlobalData.getOptions().Verbose && GlobalData.getOptions().Threads != 1) {
243
GlobalData.Options.Threads = 1;
244
GlobalData.warn(
245
"set number of threads to 1 to make --verbose to work properly.", "");
246
}
247
248
// Do not do types deduplication in case --update.
249
if (GlobalData.getOptions().UpdateIndexTablesOnly &&
250
!GlobalData.Options.NoODR)
251
GlobalData.Options.NoODR = true;
252
253
return Error::success();
254
}
255
256
/// Resolve the relative path to a build artifact referenced by DWARF by
257
/// applying DW_AT_comp_dir.
258
static void resolveRelativeObjectPath(SmallVectorImpl<char> &Buf, DWARFDie CU) {
259
sys::path::append(Buf, dwarf::toString(CU.find(dwarf::DW_AT_comp_dir), ""));
260
}
261
262
static uint64_t getDwoId(const DWARFDie &CUDie) {
263
auto DwoId = dwarf::toUnsigned(
264
CUDie.find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
265
if (DwoId)
266
return *DwoId;
267
return 0;
268
}
269
270
static std::string
271
remapPath(StringRef Path,
272
const DWARFLinker::ObjectPrefixMapTy &ObjectPrefixMap) {
273
if (ObjectPrefixMap.empty())
274
return Path.str();
275
276
SmallString<256> p = Path;
277
for (const auto &Entry : ObjectPrefixMap)
278
if (llvm::sys::path::replace_path_prefix(p, Entry.first, Entry.second))
279
break;
280
return p.str().str();
281
}
282
283
static std::string getPCMFile(const DWARFDie &CUDie,
284
DWARFLinker::ObjectPrefixMapTy *ObjectPrefixMap) {
285
std::string PCMFile = dwarf::toString(
286
CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
287
288
if (PCMFile.empty())
289
return PCMFile;
290
291
if (ObjectPrefixMap)
292
PCMFile = remapPath(PCMFile, *ObjectPrefixMap);
293
294
return PCMFile;
295
}
296
297
std::pair<bool, bool> DWARFLinkerImpl::LinkContext::isClangModuleRef(
298
const DWARFDie &CUDie, std::string &PCMFile, unsigned Indent, bool Quiet) {
299
if (PCMFile.empty())
300
return std::make_pair(false, false);
301
302
// Clang module DWARF skeleton CUs abuse this for the path to the module.
303
uint64_t DwoId = getDwoId(CUDie);
304
305
std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
306
if (Name.empty()) {
307
if (!Quiet)
308
GlobalData.warn("anonymous module skeleton CU for " + PCMFile + ".",
309
InputDWARFFile.FileName);
310
return std::make_pair(true, true);
311
}
312
313
if (!Quiet && GlobalData.getOptions().Verbose) {
314
outs().indent(Indent);
315
outs() << "Found clang module reference " << PCMFile;
316
}
317
318
auto Cached = ClangModules.find(PCMFile);
319
if (Cached != ClangModules.end()) {
320
// FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
321
// fixed in clang, only warn about DWO_id mismatches in verbose mode.
322
// ASTFileSignatures will change randomly when a module is rebuilt.
323
if (!Quiet && GlobalData.getOptions().Verbose && (Cached->second != DwoId))
324
GlobalData.warn(
325
Twine("hash mismatch: this object file was built against a "
326
"different version of the module ") +
327
PCMFile + ".",
328
InputDWARFFile.FileName);
329
if (!Quiet && GlobalData.getOptions().Verbose)
330
outs() << " [cached].\n";
331
return std::make_pair(true, true);
332
}
333
334
return std::make_pair(true, false);
335
}
336
337
/// If this compile unit is really a skeleton CU that points to a
338
/// clang module, register it in ClangModules and return true.
339
///
340
/// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
341
/// pointing to the module, and a DW_AT_gnu_dwo_id with the module
342
/// hash.
343
bool DWARFLinkerImpl::LinkContext::registerModuleReference(
344
const DWARFDie &CUDie, ObjFileLoaderTy Loader,
345
CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {
346
std::string PCMFile =
347
getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);
348
std::pair<bool, bool> IsClangModuleRef =
349
isClangModuleRef(CUDie, PCMFile, Indent, false);
350
351
if (!IsClangModuleRef.first)
352
return false;
353
354
if (IsClangModuleRef.second)
355
return true;
356
357
if (GlobalData.getOptions().Verbose)
358
outs() << " ...\n";
359
360
// Cyclic dependencies are disallowed by Clang, but we still
361
// shouldn't run into an infinite loop, so mark it as processed now.
362
ClangModules.insert({PCMFile, getDwoId(CUDie)});
363
364
if (Error E =
365
loadClangModule(Loader, CUDie, PCMFile, OnCUDieLoaded, Indent + 2)) {
366
consumeError(std::move(E));
367
return false;
368
}
369
return true;
370
}
371
372
Error DWARFLinkerImpl::LinkContext::loadClangModule(
373
ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile,
374
CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {
375
376
uint64_t DwoId = getDwoId(CUDie);
377
std::string ModuleName = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
378
379
/// Using a SmallString<0> because loadClangModule() is recursive.
380
SmallString<0> Path(GlobalData.getOptions().PrependPath);
381
if (sys::path::is_relative(PCMFile))
382
resolveRelativeObjectPath(Path, CUDie);
383
sys::path::append(Path, PCMFile);
384
// Don't use the cached binary holder because we have no thread-safety
385
// guarantee and the lifetime is limited.
386
387
if (Loader == nullptr) {
388
GlobalData.error("cann't load clang module: loader is not specified.",
389
InputDWARFFile.FileName);
390
return Error::success();
391
}
392
393
auto ErrOrObj = Loader(InputDWARFFile.FileName, Path);
394
if (!ErrOrObj)
395
return Error::success();
396
397
std::unique_ptr<CompileUnit> Unit;
398
for (const auto &CU : ErrOrObj->Dwarf->compile_units()) {
399
OnCUDieLoaded(*CU);
400
// Recursively get all modules imported by this one.
401
auto ChildCUDie = CU->getUnitDIE();
402
if (!ChildCUDie)
403
continue;
404
if (!registerModuleReference(ChildCUDie, Loader, OnCUDieLoaded, Indent)) {
405
if (Unit) {
406
std::string Err =
407
(PCMFile +
408
": Clang modules are expected to have exactly 1 compile unit.\n");
409
GlobalData.error(Err, InputDWARFFile.FileName);
410
return make_error<StringError>(Err, inconvertibleErrorCode());
411
}
412
// FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
413
// fixed in clang, only warn about DWO_id mismatches in verbose mode.
414
// ASTFileSignatures will change randomly when a module is rebuilt.
415
uint64_t PCMDwoId = getDwoId(ChildCUDie);
416
if (PCMDwoId != DwoId) {
417
if (GlobalData.getOptions().Verbose)
418
GlobalData.warn(
419
Twine("hash mismatch: this object file was built against a "
420
"different version of the module ") +
421
PCMFile + ".",
422
InputDWARFFile.FileName);
423
// Update the cache entry with the DwoId of the module loaded from disk.
424
ClangModules[PCMFile] = PCMDwoId;
425
}
426
427
// Empty modules units should not be cloned.
428
if (!ChildCUDie.hasChildren())
429
continue;
430
431
// Add this module.
432
Unit = std::make_unique<CompileUnit>(
433
GlobalData, *CU, UniqueUnitID.fetch_add(1), ModuleName, *ErrOrObj,
434
getUnitForOffset, CU->getFormParams(), getEndianness());
435
}
436
}
437
438
if (Unit) {
439
ModulesCompileUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
440
// Preload line table, as it can't be loaded asynchronously.
441
ModulesCompileUnits.back().Unit->loadLineTable();
442
}
443
444
return Error::success();
445
}
446
447
Error DWARFLinkerImpl::LinkContext::link(TypeUnit *ArtificialTypeUnit) {
448
InterCUProcessingStarted = false;
449
if (!InputDWARFFile.Dwarf)
450
return Error::success();
451
452
// Preload macro tables, as they can't be loaded asynchronously.
453
InputDWARFFile.Dwarf->getDebugMacinfo();
454
InputDWARFFile.Dwarf->getDebugMacro();
455
456
// Link modules compile units first.
457
parallelForEach(ModulesCompileUnits, [&](RefModuleUnit &RefModule) {
458
linkSingleCompileUnit(*RefModule.Unit, ArtificialTypeUnit);
459
});
460
461
// Check for live relocations. If there is no any live relocation then we
462
// can skip entire object file.
463
if (!GlobalData.getOptions().UpdateIndexTablesOnly &&
464
!InputDWARFFile.Addresses->hasValidRelocs()) {
465
if (GlobalData.getOptions().Verbose)
466
outs() << "No valid relocations found. Skipping.\n";
467
return Error::success();
468
}
469
470
OriginalDebugInfoSize = getInputDebugInfoSize();
471
472
// Create CompileUnit structures to keep information about source
473
// DWARFUnit`s, load line tables.
474
for (const auto &OrigCU : InputDWARFFile.Dwarf->compile_units()) {
475
// Load only unit DIE at this stage.
476
auto CUDie = OrigCU->getUnitDIE();
477
std::string PCMFile =
478
getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);
479
480
// The !isClangModuleRef condition effectively skips over fully resolved
481
// skeleton units.
482
if (!CUDie || GlobalData.getOptions().UpdateIndexTablesOnly ||
483
!isClangModuleRef(CUDie, PCMFile, 0, true).first) {
484
CompileUnits.emplace_back(std::make_unique<CompileUnit>(
485
GlobalData, *OrigCU, UniqueUnitID.fetch_add(1), "", InputDWARFFile,
486
getUnitForOffset, OrigCU->getFormParams(), getEndianness()));
487
488
// Preload line table, as it can't be loaded asynchronously.
489
CompileUnits.back()->loadLineTable();
490
}
491
};
492
493
HasNewInterconnectedCUs = false;
494
495
// Link self-sufficient compile units and discover inter-connected compile
496
// units.
497
parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
498
linkSingleCompileUnit(*CU, ArtificialTypeUnit);
499
});
500
501
// Link all inter-connected units.
502
if (HasNewInterconnectedCUs) {
503
InterCUProcessingStarted = true;
504
505
if (Error Err = finiteLoop([&]() -> Expected<bool> {
506
HasNewInterconnectedCUs = false;
507
508
// Load inter-connected units.
509
parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
510
if (CU->isInterconnectedCU()) {
511
CU->maybeResetToLoadedStage();
512
linkSingleCompileUnit(*CU, ArtificialTypeUnit,
513
CompileUnit::Stage::Loaded);
514
}
515
});
516
517
// Do liveness analysis for inter-connected units.
518
parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
519
linkSingleCompileUnit(*CU, ArtificialTypeUnit,
520
CompileUnit::Stage::LivenessAnalysisDone);
521
});
522
523
return HasNewInterconnectedCUs.load();
524
}))
525
return Err;
526
527
// Update dependencies.
528
if (Error Err = finiteLoop([&]() -> Expected<bool> {
529
HasNewGlobalDependency = false;
530
parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
531
linkSingleCompileUnit(
532
*CU, ArtificialTypeUnit,
533
CompileUnit::Stage::UpdateDependenciesCompleteness);
534
});
535
return HasNewGlobalDependency.load();
536
}))
537
return Err;
538
parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
539
if (CU->isInterconnectedCU() &&
540
CU->getStage() == CompileUnit::Stage::LivenessAnalysisDone)
541
CU->setStage(CompileUnit::Stage::UpdateDependenciesCompleteness);
542
});
543
544
// Assign type names.
545
parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
546
linkSingleCompileUnit(*CU, ArtificialTypeUnit,
547
CompileUnit::Stage::TypeNamesAssigned);
548
});
549
550
// Clone inter-connected units.
551
parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
552
linkSingleCompileUnit(*CU, ArtificialTypeUnit,
553
CompileUnit::Stage::Cloned);
554
});
555
556
// Update patches for inter-connected units.
557
parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
558
linkSingleCompileUnit(*CU, ArtificialTypeUnit,
559
CompileUnit::Stage::PatchesUpdated);
560
});
561
562
// Release data.
563
parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
564
linkSingleCompileUnit(*CU, ArtificialTypeUnit,
565
CompileUnit::Stage::Cleaned);
566
});
567
}
568
569
if (GlobalData.getOptions().UpdateIndexTablesOnly) {
570
// Emit Invariant sections.
571
572
if (Error Err = emitInvariantSections())
573
return Err;
574
} else if (!CompileUnits.empty()) {
575
// Emit .debug_frame section.
576
577
Error ResultErr = Error::success();
578
llvm::parallel::TaskGroup TGroup;
579
// We use task group here as PerThreadBumpPtrAllocator should be called from
580
// the threads created by ThreadPoolExecutor.
581
TGroup.spawn([&]() {
582
if (Error Err = cloneAndEmitDebugFrame())
583
ResultErr = std::move(Err);
584
});
585
return ResultErr;
586
}
587
588
return Error::success();
589
}
590
591
void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit(
592
CompileUnit &CU, TypeUnit *ArtificialTypeUnit,
593
enum CompileUnit::Stage DoUntilStage) {
594
if (InterCUProcessingStarted != CU.isInterconnectedCU())
595
return;
596
597
if (Error Err = finiteLoop([&]() -> Expected<bool> {
598
if (CU.getStage() >= DoUntilStage)
599
return false;
600
601
switch (CU.getStage()) {
602
case CompileUnit::Stage::CreatedNotLoaded: {
603
// Load input compilation unit DIEs.
604
// Analyze properties of DIEs.
605
if (!CU.loadInputDIEs()) {
606
// We do not need to do liveness analysis for invalid compilation
607
// unit.
608
CU.setStage(CompileUnit::Stage::Skipped);
609
} else {
610
CU.analyzeDWARFStructure();
611
612
// The registerModuleReference() condition effectively skips
613
// over fully resolved skeleton units. This second pass of
614
// registerModuleReferences doesn't do any new work, but it
615
// will collect top-level errors, which are suppressed. Module
616
// warnings were already displayed in the first iteration.
617
if (registerModuleReference(
618
CU.getOrigUnit().getUnitDIE(), nullptr,
619
[](const DWARFUnit &) {}, 0))
620
CU.setStage(CompileUnit::Stage::PatchesUpdated);
621
else
622
CU.setStage(CompileUnit::Stage::Loaded);
623
}
624
} break;
625
626
case CompileUnit::Stage::Loaded: {
627
// Mark all the DIEs that need to be present in the generated output.
628
// If ODR requested, build type names.
629
if (!CU.resolveDependenciesAndMarkLiveness(InterCUProcessingStarted,
630
HasNewInterconnectedCUs)) {
631
assert(HasNewInterconnectedCUs &&
632
"Flag indicating new inter-connections is not set");
633
return false;
634
}
635
636
CU.setStage(CompileUnit::Stage::LivenessAnalysisDone);
637
} break;
638
639
case CompileUnit::Stage::LivenessAnalysisDone: {
640
if (InterCUProcessingStarted) {
641
if (CU.updateDependenciesCompleteness())
642
HasNewGlobalDependency = true;
643
return false;
644
} else {
645
if (Error Err = finiteLoop([&]() -> Expected<bool> {
646
return CU.updateDependenciesCompleteness();
647
}))
648
return std::move(Err);
649
650
CU.setStage(CompileUnit::Stage::UpdateDependenciesCompleteness);
651
}
652
} break;
653
654
case CompileUnit::Stage::UpdateDependenciesCompleteness:
655
#ifndef NDEBUG
656
CU.verifyDependencies();
657
#endif
658
659
if (ArtificialTypeUnit) {
660
if (Error Err =
661
CU.assignTypeNames(ArtificialTypeUnit->getTypePool()))
662
return std::move(Err);
663
}
664
CU.setStage(CompileUnit::Stage::TypeNamesAssigned);
665
break;
666
667
case CompileUnit::Stage::TypeNamesAssigned:
668
// Clone input compile unit.
669
if (CU.isClangModule() ||
670
GlobalData.getOptions().UpdateIndexTablesOnly ||
671
CU.getContaingFile().Addresses->hasValidRelocs()) {
672
if (Error Err = CU.cloneAndEmit(GlobalData.getTargetTriple(),
673
ArtificialTypeUnit))
674
return std::move(Err);
675
}
676
677
CU.setStage(CompileUnit::Stage::Cloned);
678
break;
679
680
case CompileUnit::Stage::Cloned:
681
// Update DIEs referencies.
682
CU.updateDieRefPatchesWithClonedOffsets();
683
CU.setStage(CompileUnit::Stage::PatchesUpdated);
684
break;
685
686
case CompileUnit::Stage::PatchesUpdated:
687
// Cleanup resources.
688
CU.cleanupDataAfterClonning();
689
CU.setStage(CompileUnit::Stage::Cleaned);
690
break;
691
692
case CompileUnit::Stage::Cleaned:
693
assert(false);
694
break;
695
696
case CompileUnit::Stage::Skipped:
697
// Nothing to do.
698
break;
699
}
700
701
return true;
702
})) {
703
CU.error(std::move(Err));
704
CU.cleanupDataAfterClonning();
705
CU.setStage(CompileUnit::Stage::Skipped);
706
}
707
}
708
709
Error DWARFLinkerImpl::LinkContext::emitInvariantSections() {
710
if (!GlobalData.getTargetTriple().has_value())
711
return Error::success();
712
713
getOrCreateSectionDescriptor(DebugSectionKind::DebugLoc).OS
714
<< InputDWARFFile.Dwarf->getDWARFObj().getLocSection().Data;
715
getOrCreateSectionDescriptor(DebugSectionKind::DebugLocLists).OS
716
<< InputDWARFFile.Dwarf->getDWARFObj().getLoclistsSection().Data;
717
getOrCreateSectionDescriptor(DebugSectionKind::DebugRange).OS
718
<< InputDWARFFile.Dwarf->getDWARFObj().getRangesSection().Data;
719
getOrCreateSectionDescriptor(DebugSectionKind::DebugRngLists).OS
720
<< InputDWARFFile.Dwarf->getDWARFObj().getRnglistsSection().Data;
721
getOrCreateSectionDescriptor(DebugSectionKind::DebugARanges).OS
722
<< InputDWARFFile.Dwarf->getDWARFObj().getArangesSection();
723
getOrCreateSectionDescriptor(DebugSectionKind::DebugFrame).OS
724
<< InputDWARFFile.Dwarf->getDWARFObj().getFrameSection().Data;
725
getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr).OS
726
<< InputDWARFFile.Dwarf->getDWARFObj().getAddrSection().Data;
727
728
return Error::success();
729
}
730
731
Error DWARFLinkerImpl::LinkContext::cloneAndEmitDebugFrame() {
732
if (!GlobalData.getTargetTriple().has_value())
733
return Error::success();
734
735
if (InputDWARFFile.Dwarf == nullptr)
736
return Error::success();
737
738
const DWARFObject &InputDWARFObj = InputDWARFFile.Dwarf->getDWARFObj();
739
740
StringRef OrigFrameData = InputDWARFObj.getFrameSection().Data;
741
if (OrigFrameData.empty())
742
return Error::success();
743
744
RangesTy AllUnitsRanges;
745
for (std::unique_ptr<CompileUnit> &Unit : CompileUnits) {
746
for (auto CurRange : Unit->getFunctionRanges())
747
AllUnitsRanges.insert(CurRange.Range, CurRange.Value);
748
}
749
750
unsigned SrcAddrSize = InputDWARFObj.getAddressSize();
751
752
SectionDescriptor &OutSection =
753
getOrCreateSectionDescriptor(DebugSectionKind::DebugFrame);
754
755
DataExtractor Data(OrigFrameData, InputDWARFObj.isLittleEndian(), 0);
756
uint64_t InputOffset = 0;
757
758
// Store the data of the CIEs defined in this object, keyed by their
759
// offsets.
760
DenseMap<uint64_t, StringRef> LocalCIES;
761
762
/// The CIEs that have been emitted in the output section. The actual CIE
763
/// data serves a the key to this StringMap.
764
StringMap<uint32_t> EmittedCIEs;
765
766
while (Data.isValidOffset(InputOffset)) {
767
uint64_t EntryOffset = InputOffset;
768
uint32_t InitialLength = Data.getU32(&InputOffset);
769
if (InitialLength == 0xFFFFFFFF)
770
return createFileError(InputDWARFObj.getFileName(),
771
createStringError(std::errc::invalid_argument,
772
"Dwarf64 bits no supported"));
773
774
uint32_t CIEId = Data.getU32(&InputOffset);
775
if (CIEId == 0xFFFFFFFF) {
776
// This is a CIE, store it.
777
StringRef CIEData = OrigFrameData.substr(EntryOffset, InitialLength + 4);
778
LocalCIES[EntryOffset] = CIEData;
779
// The -4 is to account for the CIEId we just read.
780
InputOffset += InitialLength - 4;
781
continue;
782
}
783
784
uint64_t Loc = Data.getUnsigned(&InputOffset, SrcAddrSize);
785
786
// Some compilers seem to emit frame info that doesn't start at
787
// the function entry point, thus we can't just lookup the address
788
// in the debug map. Use the AddressInfo's range map to see if the FDE
789
// describes something that we can relocate.
790
std::optional<AddressRangeValuePair> Range =
791
AllUnitsRanges.getRangeThatContains(Loc);
792
if (!Range) {
793
// The +4 is to account for the size of the InitialLength field itself.
794
InputOffset = EntryOffset + InitialLength + 4;
795
continue;
796
}
797
798
// This is an FDE, and we have a mapping.
799
// Have we already emitted a corresponding CIE?
800
StringRef CIEData = LocalCIES[CIEId];
801
if (CIEData.empty())
802
return createFileError(
803
InputDWARFObj.getFileName(),
804
createStringError(std::errc::invalid_argument,
805
"Inconsistent debug_frame content. Dropping."));
806
807
uint64_t OffsetToCIERecord = OutSection.OS.tell();
808
809
// Look if we already emitted a CIE that corresponds to the
810
// referenced one (the CIE data is the key of that lookup).
811
auto IteratorInserted =
812
EmittedCIEs.insert(std::make_pair(CIEData, OffsetToCIERecord));
813
OffsetToCIERecord = IteratorInserted.first->getValue();
814
815
// Emit CIE for this ID if it is not emitted yet.
816
if (IteratorInserted.second)
817
OutSection.OS << CIEData;
818
819
// Remember offset to the FDE record, so that we might update
820
// field referencing CIE record(containing OffsetToCIERecord),
821
// when final offsets are known. OffsetToCIERecord(which is written later)
822
// is local to the current .debug_frame section, it should be updated
823
// with final offset of the .debug_frame section.
824
OutSection.notePatch(
825
DebugOffsetPatch{OutSection.OS.tell() + 4, &OutSection, true});
826
827
// Emit the FDE with updated address and CIE pointer.
828
// (4 + AddrSize) is the size of the CIEId + initial_location
829
// fields that will get reconstructed by emitFDE().
830
unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);
831
emitFDE(OffsetToCIERecord, SrcAddrSize, Loc + Range->Value,
832
OrigFrameData.substr(InputOffset, FDERemainingBytes), OutSection);
833
InputOffset += FDERemainingBytes;
834
}
835
836
return Error::success();
837
}
838
839
/// Emit a FDE into the debug_frame section. \p FDEBytes
840
/// contains the FDE data without the length, CIE offset and address
841
/// which will be replaced with the parameter values.
842
void DWARFLinkerImpl::LinkContext::emitFDE(uint32_t CIEOffset,
843
uint32_t AddrSize, uint64_t Address,
844
StringRef FDEBytes,
845
SectionDescriptor &Section) {
846
Section.emitIntVal(FDEBytes.size() + 4 + AddrSize, 4);
847
Section.emitIntVal(CIEOffset, 4);
848
Section.emitIntVal(Address, AddrSize);
849
Section.OS.write(FDEBytes.data(), FDEBytes.size());
850
}
851
852
void DWARFLinkerImpl::glueCompileUnitsAndWriteToTheOutput() {
853
if (!GlobalData.getTargetTriple().has_value())
854
return;
855
assert(SectionHandler);
856
857
// Go through all object files, all compile units and assign
858
// offsets to them.
859
assignOffsets();
860
861
// Patch size/offsets fields according to the assigned CU offsets.
862
patchOffsetsAndSizes();
863
864
// Emit common sections and write debug tables from all object files/compile
865
// units into the resulting file.
866
emitCommonSectionsAndWriteCompileUnitsToTheOutput();
867
868
if (ArtificialTypeUnit != nullptr)
869
ArtificialTypeUnit.reset();
870
871
// Write common debug sections into the resulting file.
872
writeCommonSectionsToTheOutput();
873
874
// Cleanup data.
875
cleanupDataAfterDWARFOutputIsWritten();
876
877
if (GlobalData.getOptions().Statistics)
878
printStatistic();
879
}
880
881
void DWARFLinkerImpl::printStatistic() {
882
883
// For each object file map how many bytes were emitted.
884
StringMap<DebugInfoSize> SizeByObject;
885
886
for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
887
uint64_t AllDebugInfoSectionsSize = 0;
888
889
for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
890
if (std::optional<SectionDescriptor *> DebugInfo =
891
CU->tryGetSectionDescriptor(DebugSectionKind::DebugInfo))
892
AllDebugInfoSectionsSize += (*DebugInfo)->getContents().size();
893
894
SizeByObject[Context->InputDWARFFile.FileName].Input =
895
Context->OriginalDebugInfoSize;
896
SizeByObject[Context->InputDWARFFile.FileName].Output =
897
AllDebugInfoSectionsSize;
898
}
899
900
// Create a vector sorted in descending order by output size.
901
std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
902
for (auto &E : SizeByObject)
903
Sorted.emplace_back(E.first(), E.second);
904
llvm::sort(Sorted, [](auto &LHS, auto &RHS) {
905
return LHS.second.Output > RHS.second.Output;
906
});
907
908
auto ComputePercentange = [](int64_t Input, int64_t Output) -> float {
909
const float Difference = Output - Input;
910
const float Sum = Input + Output;
911
if (Sum == 0)
912
return 0;
913
return (Difference / (Sum / 2));
914
};
915
916
int64_t InputTotal = 0;
917
int64_t OutputTotal = 0;
918
const char *FormatStr = "{0,-45} {1,10}b {2,10}b {3,8:P}\n";
919
920
// Print header.
921
outs() << ".debug_info section size (in bytes)\n";
922
outs() << "----------------------------------------------------------------"
923
"---------------\n";
924
outs() << "Filename Object "
925
" dSYM Change\n";
926
outs() << "----------------------------------------------------------------"
927
"---------------\n";
928
929
// Print body.
930
for (auto &E : Sorted) {
931
InputTotal += E.second.Input;
932
OutputTotal += E.second.Output;
933
llvm::outs() << formatv(
934
FormatStr, sys::path::filename(E.first).take_back(45), E.second.Input,
935
E.second.Output, ComputePercentange(E.second.Input, E.second.Output));
936
}
937
// Print total and footer.
938
outs() << "----------------------------------------------------------------"
939
"---------------\n";
940
llvm::outs() << formatv(FormatStr, "Total", InputTotal, OutputTotal,
941
ComputePercentange(InputTotal, OutputTotal));
942
outs() << "----------------------------------------------------------------"
943
"---------------\n\n";
944
}
945
946
void DWARFLinkerImpl::assignOffsets() {
947
llvm::parallel::TaskGroup TGroup;
948
TGroup.spawn([&]() { assignOffsetsToStrings(); });
949
TGroup.spawn([&]() { assignOffsetsToSections(); });
950
}
951
952
void DWARFLinkerImpl::assignOffsetsToStrings() {
953
size_t CurDebugStrIndex = 1; // start from 1 to take into account zero entry.
954
uint64_t CurDebugStrOffset =
955
1; // start from 1 to take into account zero entry.
956
size_t CurDebugLineStrIndex = 0;
957
uint64_t CurDebugLineStrOffset = 0;
958
959
// Enumerates all strings, add them into the DwarfStringPoolEntry map,
960
// assign offset and index to the string if it is not indexed yet.
961
forEachOutputString([&](StringDestinationKind Kind,
962
const StringEntry *String) {
963
switch (Kind) {
964
case StringDestinationKind::DebugStr: {
965
DwarfStringPoolEntryWithExtString *Entry = DebugStrStrings.add(String);
966
assert(Entry != nullptr);
967
968
if (!Entry->isIndexed()) {
969
Entry->Offset = CurDebugStrOffset;
970
CurDebugStrOffset += Entry->String.size() + 1;
971
Entry->Index = CurDebugStrIndex++;
972
}
973
} break;
974
case StringDestinationKind::DebugLineStr: {
975
DwarfStringPoolEntryWithExtString *Entry =
976
DebugLineStrStrings.add(String);
977
assert(Entry != nullptr);
978
979
if (!Entry->isIndexed()) {
980
Entry->Offset = CurDebugLineStrOffset;
981
CurDebugLineStrOffset += Entry->String.size() + 1;
982
Entry->Index = CurDebugLineStrIndex++;
983
}
984
} break;
985
}
986
});
987
}
988
989
void DWARFLinkerImpl::assignOffsetsToSections() {
990
std::array<uint64_t, SectionKindsNum> SectionSizesAccumulator = {0};
991
992
forEachObjectSectionsSet([&](OutputSections &UnitSections) {
993
UnitSections.assignSectionsOffsetAndAccumulateSize(SectionSizesAccumulator);
994
});
995
}
996
997
void DWARFLinkerImpl::forEachOutputString(
998
function_ref<void(StringDestinationKind Kind, const StringEntry *String)>
999
StringHandler) {
1000
// To save space we do not create any separate string table.
1001
// We use already allocated string patches and accelerator entries:
1002
// enumerate them in natural order and assign offsets.
1003
// ASSUMPTION: strings should be stored into .debug_str/.debug_line_str
1004
// sections in the same order as they were assigned offsets.
1005
forEachCompileUnit([&](CompileUnit *CU) {
1006
CU->forEach([&](SectionDescriptor &OutSection) {
1007
OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
1008
StringHandler(StringDestinationKind::DebugStr, Patch.String);
1009
});
1010
1011
OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
1012
StringHandler(StringDestinationKind::DebugLineStr, Patch.String);
1013
});
1014
});
1015
1016
CU->forEachAcceleratorRecord([&](DwarfUnit::AccelInfo &Info) {
1017
StringHandler(DebugStr, Info.String);
1018
});
1019
});
1020
1021
if (ArtificialTypeUnit != nullptr) {
1022
ArtificialTypeUnit->forEach([&](SectionDescriptor &OutSection) {
1023
OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
1024
StringHandler(StringDestinationKind::DebugStr, Patch.String);
1025
});
1026
1027
OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
1028
StringHandler(StringDestinationKind::DebugLineStr, Patch.String);
1029
});
1030
1031
OutSection.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) {
1032
if (Patch.Die == nullptr)
1033
return;
1034
1035
StringHandler(StringDestinationKind::DebugStr, Patch.String);
1036
});
1037
1038
OutSection.ListDebugTypeLineStrPatch.forEach(
1039
[&](DebugTypeLineStrPatch &Patch) {
1040
if (Patch.Die == nullptr)
1041
return;
1042
1043
StringHandler(StringDestinationKind::DebugStr, Patch.String);
1044
});
1045
});
1046
}
1047
}
1048
1049
void DWARFLinkerImpl::forEachObjectSectionsSet(
1050
function_ref<void(OutputSections &)> SectionsSetHandler) {
1051
// Handle artificial type unit first.
1052
if (ArtificialTypeUnit != nullptr)
1053
SectionsSetHandler(*ArtificialTypeUnit);
1054
1055
// Then all modules(before regular compilation units).
1056
for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1057
for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
1058
if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
1059
SectionsSetHandler(*ModuleUnit.Unit);
1060
1061
// Finally all compilation units.
1062
for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
1063
// Handle object file common sections.
1064
SectionsSetHandler(*Context);
1065
1066
// Handle compilation units.
1067
for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
1068
if (CU->getStage() != CompileUnit::Stage::Skipped)
1069
SectionsSetHandler(*CU);
1070
}
1071
}
1072
1073
void DWARFLinkerImpl::forEachCompileAndTypeUnit(
1074
function_ref<void(DwarfUnit *CU)> UnitHandler) {
1075
if (ArtificialTypeUnit != nullptr)
1076
UnitHandler(ArtificialTypeUnit.get());
1077
1078
// Enumerate module units.
1079
for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1080
for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
1081
if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
1082
UnitHandler(ModuleUnit.Unit.get());
1083
1084
// Enumerate compile units.
1085
for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1086
for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
1087
if (CU->getStage() != CompileUnit::Stage::Skipped)
1088
UnitHandler(CU.get());
1089
}
1090
1091
void DWARFLinkerImpl::forEachCompileUnit(
1092
function_ref<void(CompileUnit *CU)> UnitHandler) {
1093
// Enumerate module units.
1094
for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1095
for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
1096
if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
1097
UnitHandler(ModuleUnit.Unit.get());
1098
1099
// Enumerate compile units.
1100
for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1101
for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
1102
if (CU->getStage() != CompileUnit::Stage::Skipped)
1103
UnitHandler(CU.get());
1104
}
1105
1106
void DWARFLinkerImpl::patchOffsetsAndSizes() {
1107
forEachObjectSectionsSet([&](OutputSections &SectionsSet) {
1108
SectionsSet.forEach([&](SectionDescriptor &OutSection) {
1109
SectionsSet.applyPatches(OutSection, DebugStrStrings, DebugLineStrStrings,
1110
ArtificialTypeUnit.get());
1111
});
1112
});
1113
}
1114
1115
void DWARFLinkerImpl::emitCommonSectionsAndWriteCompileUnitsToTheOutput() {
1116
llvm::parallel::TaskGroup TG;
1117
1118
// Create section descriptors ahead if they are not exist at the moment.
1119
// SectionDescriptors container is not thread safe. Thus we should be sure
1120
// that descriptors would not be created in following parallel tasks.
1121
1122
CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugStr);
1123
CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugLineStr);
1124
1125
if (llvm::is_contained(GlobalData.Options.AccelTables,
1126
AccelTableKind::Apple)) {
1127
CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleNames);
1128
CommonSections.getOrCreateSectionDescriptor(
1129
DebugSectionKind::AppleNamespaces);
1130
CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleObjC);
1131
CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleTypes);
1132
}
1133
1134
if (llvm::is_contained(GlobalData.Options.AccelTables,
1135
AccelTableKind::DebugNames))
1136
CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugNames);
1137
1138
// Emit .debug_str and .debug_line_str sections.
1139
TG.spawn([&]() { emitStringSections(); });
1140
1141
if (llvm::is_contained(GlobalData.Options.AccelTables,
1142
AccelTableKind::Apple)) {
1143
// Emit apple accelerator sections.
1144
TG.spawn([&]() {
1145
emitAppleAcceleratorSections((*GlobalData.getTargetTriple()).get());
1146
});
1147
}
1148
1149
if (llvm::is_contained(GlobalData.Options.AccelTables,
1150
AccelTableKind::DebugNames)) {
1151
// Emit .debug_names section.
1152
TG.spawn([&]() {
1153
emitDWARFv5DebugNamesSection((*GlobalData.getTargetTriple()).get());
1154
});
1155
}
1156
1157
// Write compile units to the output file.
1158
TG.spawn([&]() { writeCompileUnitsToTheOutput(); });
1159
}
1160
1161
void DWARFLinkerImpl::emitStringSections() {
1162
uint64_t DebugStrNextOffset = 0;
1163
uint64_t DebugLineStrNextOffset = 0;
1164
1165
// Emit zero length string. Accelerator tables does not work correctly
1166
// if the first string is not zero length string.
1167
CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)
1168
.emitInplaceString("");
1169
DebugStrNextOffset++;
1170
1171
forEachOutputString(
1172
[&](StringDestinationKind Kind, const StringEntry *String) {
1173
switch (Kind) {
1174
case StringDestinationKind::DebugStr: {
1175
DwarfStringPoolEntryWithExtString *StringToEmit =
1176
DebugStrStrings.getExistingEntry(String);
1177
assert(StringToEmit->isIndexed());
1178
1179
// Strings may be repeated. Use accumulated DebugStrNextOffset
1180
// to understand whether corresponding string is already emitted.
1181
// Skip string if its offset less than accumulated offset.
1182
if (StringToEmit->Offset >= DebugStrNextOffset) {
1183
DebugStrNextOffset =
1184
StringToEmit->Offset + StringToEmit->String.size() + 1;
1185
// Emit the string itself.
1186
CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)
1187
.emitInplaceString(StringToEmit->String);
1188
}
1189
} break;
1190
case StringDestinationKind::DebugLineStr: {
1191
DwarfStringPoolEntryWithExtString *StringToEmit =
1192
DebugLineStrStrings.getExistingEntry(String);
1193
assert(StringToEmit->isIndexed());
1194
1195
// Strings may be repeated. Use accumulated DebugLineStrStrings
1196
// to understand whether corresponding string is already emitted.
1197
// Skip string if its offset less than accumulated offset.
1198
if (StringToEmit->Offset >= DebugLineStrNextOffset) {
1199
DebugLineStrNextOffset =
1200
StringToEmit->Offset + StringToEmit->String.size() + 1;
1201
// Emit the string itself.
1202
CommonSections.getSectionDescriptor(DebugSectionKind::DebugLineStr)
1203
.emitInplaceString(StringToEmit->String);
1204
}
1205
} break;
1206
}
1207
});
1208
}
1209
1210
void DWARFLinkerImpl::emitAppleAcceleratorSections(const Triple &TargetTriple) {
1211
AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces;
1212
AccelTable<AppleAccelTableStaticOffsetData> AppleNames;
1213
AccelTable<AppleAccelTableStaticOffsetData> AppleObjC;
1214
AccelTable<AppleAccelTableStaticTypeData> AppleTypes;
1215
1216
forEachCompileAndTypeUnit([&](DwarfUnit *CU) {
1217
CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
1218
uint64_t OutOffset = Info.OutOffset;
1219
switch (Info.Type) {
1220
case DwarfUnit::AccelType::None: {
1221
llvm_unreachable("Unknown accelerator record");
1222
} break;
1223
case DwarfUnit::AccelType::Namespace: {
1224
AppleNamespaces.addName(
1225
*DebugStrStrings.getExistingEntry(Info.String),
1226
CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1227
OutOffset);
1228
} break;
1229
case DwarfUnit::AccelType::Name: {
1230
AppleNames.addName(
1231
*DebugStrStrings.getExistingEntry(Info.String),
1232
CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1233
OutOffset);
1234
} break;
1235
case DwarfUnit::AccelType::ObjC: {
1236
AppleObjC.addName(
1237
*DebugStrStrings.getExistingEntry(Info.String),
1238
CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1239
OutOffset);
1240
} break;
1241
case DwarfUnit::AccelType::Type: {
1242
AppleTypes.addName(
1243
*DebugStrStrings.getExistingEntry(Info.String),
1244
CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1245
OutOffset,
1246
Info.Tag,
1247
Info.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation
1248
: 0,
1249
Info.QualifiedNameHash);
1250
} break;
1251
}
1252
});
1253
});
1254
1255
{
1256
// FIXME: we use AsmPrinter to emit accelerator sections.
1257
// It might be beneficial to directly emit accelerator data
1258
// to the raw_svector_ostream.
1259
SectionDescriptor &OutSection =
1260
CommonSections.getSectionDescriptor(DebugSectionKind::AppleNamespaces);
1261
DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
1262
OutSection.OS);
1263
if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1264
consumeError(std::move(Err));
1265
return;
1266
}
1267
1268
// Emit table.
1269
Emitter.emitAppleNamespaces(AppleNamespaces);
1270
Emitter.finish();
1271
1272
// Set start offset and size for output section.
1273
OutSection.setSizesForSectionCreatedByAsmPrinter();
1274
}
1275
1276
{
1277
// FIXME: we use AsmPrinter to emit accelerator sections.
1278
// It might be beneficial to directly emit accelerator data
1279
// to the raw_svector_ostream.
1280
SectionDescriptor &OutSection =
1281
CommonSections.getSectionDescriptor(DebugSectionKind::AppleNames);
1282
DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
1283
OutSection.OS);
1284
if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1285
consumeError(std::move(Err));
1286
return;
1287
}
1288
1289
// Emit table.
1290
Emitter.emitAppleNames(AppleNames);
1291
Emitter.finish();
1292
1293
// Set start offset ans size for output section.
1294
OutSection.setSizesForSectionCreatedByAsmPrinter();
1295
}
1296
1297
{
1298
// FIXME: we use AsmPrinter to emit accelerator sections.
1299
// It might be beneficial to directly emit accelerator data
1300
// to the raw_svector_ostream.
1301
SectionDescriptor &OutSection =
1302
CommonSections.getSectionDescriptor(DebugSectionKind::AppleObjC);
1303
DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
1304
OutSection.OS);
1305
if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1306
consumeError(std::move(Err));
1307
return;
1308
}
1309
1310
// Emit table.
1311
Emitter.emitAppleObjc(AppleObjC);
1312
Emitter.finish();
1313
1314
// Set start offset ans size for output section.
1315
OutSection.setSizesForSectionCreatedByAsmPrinter();
1316
}
1317
1318
{
1319
// FIXME: we use AsmPrinter to emit accelerator sections.
1320
// It might be beneficial to directly emit accelerator data
1321
// to the raw_svector_ostream.
1322
SectionDescriptor &OutSection =
1323
CommonSections.getSectionDescriptor(DebugSectionKind::AppleTypes);
1324
DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
1325
OutSection.OS);
1326
if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1327
consumeError(std::move(Err));
1328
return;
1329
}
1330
1331
// Emit table.
1332
Emitter.emitAppleTypes(AppleTypes);
1333
Emitter.finish();
1334
1335
// Set start offset ans size for output section.
1336
OutSection.setSizesForSectionCreatedByAsmPrinter();
1337
}
1338
}
1339
1340
void DWARFLinkerImpl::emitDWARFv5DebugNamesSection(const Triple &TargetTriple) {
1341
std::unique_ptr<DWARF5AccelTable> DebugNames;
1342
1343
DebugNamesUnitsOffsets CompUnits;
1344
CompUnitIDToIdx CUidToIdx;
1345
1346
unsigned Id = 0;
1347
1348
forEachCompileAndTypeUnit([&](DwarfUnit *CU) {
1349
bool HasRecords = false;
1350
CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
1351
if (DebugNames == nullptr)
1352
DebugNames = std::make_unique<DWARF5AccelTable>();
1353
1354
HasRecords = true;
1355
switch (Info.Type) {
1356
case DwarfUnit::AccelType::Name:
1357
case DwarfUnit::AccelType::Namespace:
1358
case DwarfUnit::AccelType::Type: {
1359
DebugNames->addName(*DebugStrStrings.getExistingEntry(Info.String),
1360
Info.OutOffset, std::nullopt /*ParentDIEOffset*/,
1361
Info.Tag, CU->getUniqueID(),
1362
CU->getTag() == dwarf::DW_TAG_type_unit);
1363
} break;
1364
1365
default:
1366
break; // Nothing to do.
1367
};
1368
});
1369
1370
if (HasRecords) {
1371
CompUnits.push_back(
1372
CU->getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)
1373
.StartOffset);
1374
CUidToIdx[CU->getUniqueID()] = Id++;
1375
}
1376
});
1377
1378
if (DebugNames != nullptr) {
1379
// FIXME: we use AsmPrinter to emit accelerator sections.
1380
// It might be beneficial to directly emit accelerator data
1381
// to the raw_svector_ostream.
1382
SectionDescriptor &OutSection =
1383
CommonSections.getSectionDescriptor(DebugSectionKind::DebugNames);
1384
DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
1385
OutSection.OS);
1386
if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1387
consumeError(std::move(Err));
1388
return;
1389
}
1390
1391
// Emit table.
1392
Emitter.emitDebugNames(*DebugNames, CompUnits, CUidToIdx);
1393
Emitter.finish();
1394
1395
// Set start offset ans size for output section.
1396
OutSection.setSizesForSectionCreatedByAsmPrinter();
1397
}
1398
}
1399
1400
void DWARFLinkerImpl::cleanupDataAfterDWARFOutputIsWritten() {
1401
GlobalData.getStringPool().clear();
1402
DebugStrStrings.clear();
1403
DebugLineStrStrings.clear();
1404
}
1405
1406
void DWARFLinkerImpl::writeCompileUnitsToTheOutput() {
1407
// Enumerate all sections and store them into the final emitter.
1408
forEachObjectSectionsSet([&](OutputSections &Sections) {
1409
Sections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {
1410
// Emit section content.
1411
SectionHandler(OutSection);
1412
});
1413
});
1414
}
1415
1416
void DWARFLinkerImpl::writeCommonSectionsToTheOutput() {
1417
CommonSections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {
1418
SectionHandler(OutSection);
1419
});
1420
}
1421
1422