[AMDGPU] Test codegen'ing True16 additions.
[llvm-project.git] / llvm / lib / DWARFLinkerParallel / DWARFLinkerImpl.cpp
blob34e09fada1dfbe3a6c5cab97dac1241bd794ab80
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 //===----------------------------------------------------------------------===//
9 #include "DWARFLinkerImpl.h"
10 #include "DIEGenerator.h"
11 #include "DependencyTracker.h"
12 #include "llvm/Support/FormatVariadic.h"
13 #include "llvm/Support/Parallel.h"
14 #include "llvm/Support/ThreadPool.h"
16 namespace llvm {
17 namespace dwarflinker_parallel {
19 Error DWARFLinkerImpl::createEmitter(const Triple &TheTriple,
20 OutputFileType FileType,
21 raw_pwrite_stream &OutFile) {
23 TheDwarfEmitter = std::make_unique<DwarfEmitterImpl>(FileType, OutFile);
25 return TheDwarfEmitter->init(TheTriple, "__DWARF");
28 ExtraDwarfEmitter *DWARFLinkerImpl::getEmitter() {
29 return TheDwarfEmitter.get();
32 void DWARFLinkerImpl::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader,
33 CompileUnitHandlerTy OnCUDieLoaded) {
34 ObjectContexts.emplace_back(std::make_unique<LinkContext>(
35 GlobalData, File, ClangModules, UniqueUnitID,
36 (TheDwarfEmitter.get() == nullptr ? std::optional<Triple>(std::nullopt)
37 : TheDwarfEmitter->getTargetTriple())));
39 if (ObjectContexts.back()->InputDWARFFile.Dwarf) {
40 for (const std::unique_ptr<DWARFUnit> &CU :
41 ObjectContexts.back()->InputDWARFFile.Dwarf->compile_units()) {
42 DWARFDie CUDie = CU->getUnitDIE();
43 OverallNumberOfCU++;
45 if (!CUDie)
46 continue;
48 OnCUDieLoaded(*CU);
50 // Register mofule reference.
51 if (!GlobalData.getOptions().UpdateIndexTablesOnly)
52 ObjectContexts.back()->registerModuleReference(CUDie, Loader,
53 OnCUDieLoaded);
58 Error DWARFLinkerImpl::link() {
59 // reset compile unit unique ID counter.
60 UniqueUnitID = 0;
62 if (Error Err = validateAndUpdateOptions())
63 return Err;
65 dwarf::FormParams GlobalFormat = {GlobalData.getOptions().TargetDWARFVersion,
66 0, dwarf::DwarfFormat::DWARF32};
67 support::endianness GlobalEndianness = support::endian::system_endianness();
69 if (TheDwarfEmitter) {
70 GlobalEndianness = TheDwarfEmitter->getTargetTriple().isLittleEndian()
71 ? support::endianness::little
72 : support::endianness::big;
75 for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
76 if (Context->InputDWARFFile.Dwarf.get() == nullptr) {
77 Context->setOutputFormat(Context->getFormParams(), GlobalEndianness);
78 continue;
81 if (GlobalData.getOptions().Verbose) {
82 outs() << "OBJECT: " << Context->InputDWARFFile.FileName << "\n";
84 for (const std::unique_ptr<DWARFUnit> &OrigCU :
85 Context->InputDWARFFile.Dwarf->compile_units()) {
86 outs() << "Input compilation unit:";
87 DIDumpOptions DumpOpts;
88 DumpOpts.ChildRecurseDepth = 0;
89 DumpOpts.Verbose = GlobalData.getOptions().Verbose;
90 OrigCU->getUnitDIE().dump(outs(), 0, DumpOpts);
94 // Verify input DWARF if requested.
95 if (GlobalData.getOptions().VerifyInputDWARF)
96 verifyInput(Context->InputDWARFFile);
98 if (!TheDwarfEmitter)
99 GlobalEndianness = Context->getEndianness();
100 GlobalFormat.AddrSize =
101 std::max(GlobalFormat.AddrSize, Context->getFormParams().AddrSize);
103 Context->setOutputFormat(Context->getFormParams(), GlobalEndianness);
106 if (GlobalFormat.AddrSize == 0) {
107 if (TheDwarfEmitter)
108 GlobalFormat.AddrSize =
109 TheDwarfEmitter->getTargetTriple().isArch32Bit() ? 4 : 8;
110 else
111 GlobalFormat.AddrSize = 8;
114 CommonSections.setOutputFormat(GlobalFormat, GlobalEndianness);
116 // Set parallel options.
117 if (GlobalData.getOptions().Threads == 0)
118 parallel::strategy = optimal_concurrency(OverallNumberOfCU);
119 else
120 parallel::strategy = hardware_concurrency(GlobalData.getOptions().Threads);
122 // Link object files.
123 if (GlobalData.getOptions().Threads == 1) {
124 for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
125 // Link object file.
126 if (Error Err = Context->link())
127 GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
129 Context->InputDWARFFile.unload();
131 } else {
132 ThreadPool Pool(parallel::strategy);
133 for (std::unique_ptr<LinkContext> &Context : ObjectContexts)
134 Pool.async([&]() {
135 // Link object file.
136 if (Error Err = Context->link())
137 GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
139 Context->InputDWARFFile.unload();
142 Pool.wait();
145 // At this stage each compile units are cloned to their own set of debug
146 // sections. Now, update patches, assign offsets and assemble final file
147 // glueing debug tables from each compile unit.
148 glueCompileUnitsAndWriteToTheOutput();
150 return Error::success();
153 void DWARFLinkerImpl::verifyInput(const DWARFFile &File) {
154 assert(File.Dwarf);
156 std::string Buffer;
157 raw_string_ostream OS(Buffer);
158 DIDumpOptions DumpOpts;
159 if (!File.Dwarf->verify(OS, DumpOpts.noImplicitRecursion())) {
160 if (GlobalData.getOptions().InputVerificationHandler)
161 GlobalData.getOptions().InputVerificationHandler(File, OS.str());
165 Error DWARFLinkerImpl::validateAndUpdateOptions() {
166 if (GlobalData.getOptions().TargetDWARFVersion == 0)
167 return createStringError(std::errc::invalid_argument,
168 "target DWARF version is not set");
170 GlobalData.Options.NoOutput = TheDwarfEmitter.get() == nullptr;
172 if (GlobalData.getOptions().Verbose && GlobalData.getOptions().Threads != 1) {
173 GlobalData.Options.Threads = 1;
174 GlobalData.warn(
175 "set number of threads to 1 to make --verbose to work properly.", "");
178 return Error::success();
181 /// Resolve the relative path to a build artifact referenced by DWARF by
182 /// applying DW_AT_comp_dir.
183 static void resolveRelativeObjectPath(SmallVectorImpl<char> &Buf, DWARFDie CU) {
184 sys::path::append(Buf, dwarf::toString(CU.find(dwarf::DW_AT_comp_dir), ""));
187 static uint64_t getDwoId(const DWARFDie &CUDie) {
188 auto DwoId = dwarf::toUnsigned(
189 CUDie.find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
190 if (DwoId)
191 return *DwoId;
192 return 0;
195 static std::string
196 remapPath(StringRef Path,
197 const DWARFLinker::ObjectPrefixMapTy &ObjectPrefixMap) {
198 if (ObjectPrefixMap.empty())
199 return Path.str();
201 SmallString<256> p = Path;
202 for (const auto &Entry : ObjectPrefixMap)
203 if (llvm::sys::path::replace_path_prefix(p, Entry.first, Entry.second))
204 break;
205 return p.str().str();
208 static std::string getPCMFile(const DWARFDie &CUDie,
209 DWARFLinker::ObjectPrefixMapTy *ObjectPrefixMap) {
210 std::string PCMFile = dwarf::toString(
211 CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
213 if (PCMFile.empty())
214 return PCMFile;
216 if (ObjectPrefixMap)
217 PCMFile = remapPath(PCMFile, *ObjectPrefixMap);
219 return PCMFile;
222 std::pair<bool, bool> DWARFLinkerImpl::LinkContext::isClangModuleRef(
223 const DWARFDie &CUDie, std::string &PCMFile, unsigned Indent, bool Quiet) {
224 if (PCMFile.empty())
225 return std::make_pair(false, false);
227 // Clang module DWARF skeleton CUs abuse this for the path to the module.
228 uint64_t DwoId = getDwoId(CUDie);
230 std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
231 if (Name.empty()) {
232 if (!Quiet)
233 GlobalData.warn("anonymous module skeleton CU for " + PCMFile + ".",
234 InputDWARFFile.FileName);
235 return std::make_pair(true, true);
238 if (!Quiet && GlobalData.getOptions().Verbose) {
239 outs().indent(Indent);
240 outs() << "Found clang module reference " << PCMFile;
243 auto Cached = ClangModules.find(PCMFile);
244 if (Cached != ClangModules.end()) {
245 // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
246 // fixed in clang, only warn about DWO_id mismatches in verbose mode.
247 // ASTFileSignatures will change randomly when a module is rebuilt.
248 if (!Quiet && GlobalData.getOptions().Verbose && (Cached->second != DwoId))
249 GlobalData.warn(
250 Twine("hash mismatch: this object file was built against a "
251 "different version of the module ") +
252 PCMFile + ".",
253 InputDWARFFile.FileName);
254 if (!Quiet && GlobalData.getOptions().Verbose)
255 outs() << " [cached].\n";
256 return std::make_pair(true, true);
259 return std::make_pair(true, false);
262 /// If this compile unit is really a skeleton CU that points to a
263 /// clang module, register it in ClangModules and return true.
265 /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
266 /// pointing to the module, and a DW_AT_gnu_dwo_id with the module
267 /// hash.
268 bool DWARFLinkerImpl::LinkContext::registerModuleReference(
269 const DWARFDie &CUDie, ObjFileLoaderTy Loader,
270 CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {
271 std::string PCMFile =
272 getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);
273 std::pair<bool, bool> IsClangModuleRef =
274 isClangModuleRef(CUDie, PCMFile, Indent, false);
276 if (!IsClangModuleRef.first)
277 return false;
279 if (IsClangModuleRef.second)
280 return true;
282 if (GlobalData.getOptions().Verbose)
283 outs() << " ...\n";
285 // Cyclic dependencies are disallowed by Clang, but we still
286 // shouldn't run into an infinite loop, so mark it as processed now.
287 ClangModules.insert({PCMFile, getDwoId(CUDie)});
289 if (Error E =
290 loadClangModule(Loader, CUDie, PCMFile, OnCUDieLoaded, Indent + 2)) {
291 consumeError(std::move(E));
292 return false;
294 return true;
297 Error DWARFLinkerImpl::LinkContext::loadClangModule(
298 ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile,
299 CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {
301 uint64_t DwoId = getDwoId(CUDie);
302 std::string ModuleName = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
304 /// Using a SmallString<0> because loadClangModule() is recursive.
305 SmallString<0> Path(GlobalData.getOptions().PrependPath);
306 if (sys::path::is_relative(PCMFile))
307 resolveRelativeObjectPath(Path, CUDie);
308 sys::path::append(Path, PCMFile);
309 // Don't use the cached binary holder because we have no thread-safety
310 // guarantee and the lifetime is limited.
312 if (Loader == nullptr) {
313 GlobalData.error("cann't load clang module: loader is not specified.",
314 InputDWARFFile.FileName);
315 return Error::success();
318 auto ErrOrObj = Loader(InputDWARFFile.FileName, Path);
319 if (!ErrOrObj)
320 return Error::success();
322 std::unique_ptr<CompileUnit> Unit;
323 for (const auto &CU : ErrOrObj->Dwarf->compile_units()) {
324 OnCUDieLoaded(*CU);
325 // Recursively get all modules imported by this one.
326 auto ChildCUDie = CU->getUnitDIE();
327 if (!ChildCUDie)
328 continue;
329 if (!registerModuleReference(ChildCUDie, Loader, OnCUDieLoaded, Indent)) {
330 if (Unit) {
331 std::string Err =
332 (PCMFile +
333 ": Clang modules are expected to have exactly 1 compile unit.\n");
334 GlobalData.error(Err, InputDWARFFile.FileName);
335 return make_error<StringError>(Err, inconvertibleErrorCode());
337 // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
338 // fixed in clang, only warn about DWO_id mismatches in verbose mode.
339 // ASTFileSignatures will change randomly when a module is rebuilt.
340 uint64_t PCMDwoId = getDwoId(ChildCUDie);
341 if (PCMDwoId != DwoId) {
342 if (GlobalData.getOptions().Verbose)
343 GlobalData.warn(
344 Twine("hash mismatch: this object file was built against a "
345 "different version of the module ") +
346 PCMFile + ".",
347 InputDWARFFile.FileName);
348 // Update the cache entry with the DwoId of the module loaded from disk.
349 ClangModules[PCMFile] = PCMDwoId;
352 // Empty modules units should not be cloned.
353 if (!ChildCUDie.hasChildren())
354 continue;
356 // Add this module.
357 Unit = std::make_unique<CompileUnit>(
358 GlobalData, *CU, UniqueUnitID.fetch_add(1), ModuleName, *ErrOrObj,
359 getUnitForOffset, CU->getFormParams(), getEndianness());
363 if (Unit) {
364 ModulesCompileUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
365 // Preload line table, as it can't be loaded asynchronously.
366 ModulesCompileUnits.back().Unit->loadLineTable();
369 return Error::success();
372 Error DWARFLinkerImpl::LinkContext::link() {
373 InterCUProcessingStarted = false;
374 if (!InputDWARFFile.Dwarf)
375 return Error::success();
377 // Preload macro tables, as they can't be loaded asynchronously.
378 InputDWARFFile.Dwarf->getDebugMacinfo();
379 InputDWARFFile.Dwarf->getDebugMacro();
381 // Link modules compile units first.
382 parallelForEach(ModulesCompileUnits, [&](RefModuleUnit &RefModule) {
383 linkSingleCompileUnit(*RefModule.Unit);
386 // Check for live relocations. If there is no any live relocation then we
387 // can skip entire object file.
388 if (!GlobalData.getOptions().UpdateIndexTablesOnly &&
389 !InputDWARFFile.Addresses->hasValidRelocs()) {
390 if (GlobalData.getOptions().Verbose)
391 outs() << "No valid relocations found. Skipping.\n";
392 return Error::success();
395 OriginalDebugInfoSize = getInputDebugInfoSize();
397 // Create CompileUnit structures to keep information about source
398 // DWARFUnit`s, load line tables.
399 for (const auto &OrigCU : InputDWARFFile.Dwarf->compile_units()) {
400 // Load only unit DIE at this stage.
401 auto CUDie = OrigCU->getUnitDIE();
402 std::string PCMFile =
403 getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);
405 // The !isClangModuleRef condition effectively skips over fully resolved
406 // skeleton units.
407 if (!CUDie || GlobalData.getOptions().UpdateIndexTablesOnly ||
408 !isClangModuleRef(CUDie, PCMFile, 0, true).first) {
409 CompileUnits.emplace_back(std::make_unique<CompileUnit>(
410 GlobalData, *OrigCU, UniqueUnitID.fetch_add(1), "", InputDWARFFile,
411 getUnitForOffset, OrigCU->getFormParams(), getEndianness()));
413 // Preload line table, as it can't be loaded asynchronously.
414 CompileUnits.back()->loadLineTable();
418 HasNewInterconnectedCUs = false;
420 // Link self-sufficient compile units and discover inter-connected compile
421 // units.
422 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
423 linkSingleCompileUnit(*CU);
426 // Link all inter-connected units.
427 if (HasNewInterconnectedCUs) {
428 InterCUProcessingStarted = true;
430 do {
431 HasNewInterconnectedCUs = false;
433 // Load inter-connected units.
434 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
435 if (CU->isInterconnectedCU()) {
436 CU->maybeResetToLoadedStage();
437 linkSingleCompileUnit(*CU, CompileUnit::Stage::Loaded);
441 // Do liveness analysis for inter-connected units.
442 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
443 linkSingleCompileUnit(*CU, CompileUnit::Stage::LivenessAnalysisDone);
445 } while (HasNewInterconnectedCUs);
447 // Clone inter-connected units.
448 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
449 linkSingleCompileUnit(*CU, CompileUnit::Stage::Cloned);
452 // Update patches for inter-connected units.
453 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
454 linkSingleCompileUnit(*CU, CompileUnit::Stage::PatchesUpdated);
457 // Release data.
458 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
459 linkSingleCompileUnit(*CU, CompileUnit::Stage::Cleaned);
463 if (GlobalData.getOptions().UpdateIndexTablesOnly) {
464 // Emit Invariant sections.
466 if (Error Err = emitInvariantSections())
467 return Err;
468 } else if (!CompileUnits.empty()) {
469 // Emit .debug_frame section.
471 Error ResultErr = Error::success();
472 parallel::TaskGroup TGroup;
473 // We use task group here as PerThreadBumpPtrAllocator should be called from
474 // the threads created by ThreadPoolExecutor.
475 TGroup.spawn([&]() {
476 if (Error Err = cloneAndEmitDebugFrame())
477 ResultErr = std::move(Err);
479 return ResultErr;
482 return Error::success();
485 void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit(
486 CompileUnit &CU, enum CompileUnit::Stage DoUntilStage) {
487 while (CU.getStage() < DoUntilStage) {
488 if (InterCUProcessingStarted != CU.isInterconnectedCU())
489 return;
491 switch (CU.getStage()) {
492 case CompileUnit::Stage::CreatedNotLoaded: {
493 // Load input compilation unit DIEs.
494 // Analyze properties of DIEs.
495 if (!CU.loadInputDIEs()) {
496 // We do not need to do liveness analysis for invalud compilation unit.
497 CU.setStage(CompileUnit::Stage::LivenessAnalysisDone);
498 } else {
499 CU.analyzeDWARFStructure();
501 // The registerModuleReference() condition effectively skips
502 // over fully resolved skeleton units. This second pass of
503 // registerModuleReferences doesn't do any new work, but it
504 // will collect top-level errors, which are suppressed. Module
505 // warnings were already displayed in the first iteration.
506 if (registerModuleReference(
507 CU.getOrigUnit().getUnitDIE(), nullptr,
508 [](const DWARFUnit &) {}, 0))
509 CU.setStage(CompileUnit::Stage::PatchesUpdated);
510 else
511 CU.setStage(CompileUnit::Stage::Loaded);
513 } break;
515 case CompileUnit::Stage::Loaded: {
516 // Mark all the DIEs that need to be present in the generated output.
517 // If ODR requested, build type names.
518 if (!DependencyTracker(*this).resolveDependenciesAndMarkLiveness(CU)) {
519 assert(HasNewInterconnectedCUs);
520 return;
523 CU.setStage(CompileUnit::Stage::LivenessAnalysisDone);
524 } break;
526 case CompileUnit::Stage::LivenessAnalysisDone:
528 #ifndef NDEBUG
529 DependencyTracker::verifyKeepChain(CU);
530 #endif
532 // Clone input compile unit.
533 if (CU.isClangModule() || GlobalData.getOptions().UpdateIndexTablesOnly ||
534 CU.getContaingFile().Addresses->hasValidRelocs()) {
535 if (Error Err = CU.cloneAndEmit(TargetTriple))
536 CU.error(std::move(Err));
539 CU.setStage(CompileUnit::Stage::Cloned);
540 break;
542 case CompileUnit::Stage::Cloned:
543 // Update DIEs referencies.
544 CU.updateDieRefPatchesWithClonedOffsets();
545 CU.setStage(CompileUnit::Stage::PatchesUpdated);
546 break;
548 case CompileUnit::Stage::PatchesUpdated:
549 // Cleanup resources.
550 CU.cleanupDataAfterClonning();
551 CU.setStage(CompileUnit::Stage::Cleaned);
552 break;
554 case CompileUnit::Stage::Cleaned:
555 assert(false);
556 break;
561 Error DWARFLinkerImpl::LinkContext::emitInvariantSections() {
562 if (GlobalData.getOptions().NoOutput)
563 return Error::success();
565 getOrCreateSectionDescriptor(DebugSectionKind::DebugLoc).OS
566 << InputDWARFFile.Dwarf->getDWARFObj().getLocSection().Data;
567 getOrCreateSectionDescriptor(DebugSectionKind::DebugLocLists).OS
568 << InputDWARFFile.Dwarf->getDWARFObj().getLoclistsSection().Data;
569 getOrCreateSectionDescriptor(DebugSectionKind::DebugRange).OS
570 << InputDWARFFile.Dwarf->getDWARFObj().getRangesSection().Data;
571 getOrCreateSectionDescriptor(DebugSectionKind::DebugRngLists).OS
572 << InputDWARFFile.Dwarf->getDWARFObj().getRnglistsSection().Data;
573 getOrCreateSectionDescriptor(DebugSectionKind::DebugARanges).OS
574 << InputDWARFFile.Dwarf->getDWARFObj().getArangesSection();
575 getOrCreateSectionDescriptor(DebugSectionKind::DebugFrame).OS
576 << InputDWARFFile.Dwarf->getDWARFObj().getFrameSection().Data;
577 getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr).OS
578 << InputDWARFFile.Dwarf->getDWARFObj().getAddrSection().Data;
580 return Error::success();
583 Error DWARFLinkerImpl::LinkContext::cloneAndEmitDebugFrame() {
584 if (GlobalData.getOptions().NoOutput)
585 return Error::success();
587 if (InputDWARFFile.Dwarf.get() == nullptr)
588 return Error::success();
590 const DWARFObject &InputDWARFObj = InputDWARFFile.Dwarf->getDWARFObj();
592 StringRef OrigFrameData = InputDWARFObj.getFrameSection().Data;
593 if (OrigFrameData.empty())
594 return Error::success();
596 RangesTy AllUnitsRanges;
597 for (std::unique_ptr<CompileUnit> &Unit : CompileUnits) {
598 for (auto CurRange : Unit->getFunctionRanges())
599 AllUnitsRanges.insert(CurRange.Range, CurRange.Value);
602 unsigned SrcAddrSize = InputDWARFObj.getAddressSize();
604 SectionDescriptor &OutSection =
605 getOrCreateSectionDescriptor(DebugSectionKind::DebugFrame);
607 DataExtractor Data(OrigFrameData, InputDWARFObj.isLittleEndian(), 0);
608 uint64_t InputOffset = 0;
610 // Store the data of the CIEs defined in this object, keyed by their
611 // offsets.
612 DenseMap<uint64_t, StringRef> LocalCIES;
614 /// The CIEs that have been emitted in the output section. The actual CIE
615 /// data serves a the key to this StringMap.
616 StringMap<uint32_t> EmittedCIEs;
618 while (Data.isValidOffset(InputOffset)) {
619 uint64_t EntryOffset = InputOffset;
620 uint32_t InitialLength = Data.getU32(&InputOffset);
621 if (InitialLength == 0xFFFFFFFF)
622 return createFileError(InputDWARFObj.getFileName(),
623 createStringError(std::errc::invalid_argument,
624 "Dwarf64 bits no supported"));
626 uint32_t CIEId = Data.getU32(&InputOffset);
627 if (CIEId == 0xFFFFFFFF) {
628 // This is a CIE, store it.
629 StringRef CIEData = OrigFrameData.substr(EntryOffset, InitialLength + 4);
630 LocalCIES[EntryOffset] = CIEData;
631 // The -4 is to account for the CIEId we just read.
632 InputOffset += InitialLength - 4;
633 continue;
636 uint64_t Loc = Data.getUnsigned(&InputOffset, SrcAddrSize);
638 // Some compilers seem to emit frame info that doesn't start at
639 // the function entry point, thus we can't just lookup the address
640 // in the debug map. Use the AddressInfo's range map to see if the FDE
641 // describes something that we can relocate.
642 std::optional<AddressRangeValuePair> Range =
643 AllUnitsRanges.getRangeThatContains(Loc);
644 if (!Range) {
645 // The +4 is to account for the size of the InitialLength field itself.
646 InputOffset = EntryOffset + InitialLength + 4;
647 continue;
650 // This is an FDE, and we have a mapping.
651 // Have we already emitted a corresponding CIE?
652 StringRef CIEData = LocalCIES[CIEId];
653 if (CIEData.empty())
654 return createFileError(
655 InputDWARFObj.getFileName(),
656 createStringError(std::errc::invalid_argument,
657 "Inconsistent debug_frame content. Dropping."));
659 uint64_t OffsetToCIERecord = OutSection.OS.tell();
661 // Look if we already emitted a CIE that corresponds to the
662 // referenced one (the CIE data is the key of that lookup).
663 auto IteratorInserted =
664 EmittedCIEs.insert(std::make_pair(CIEData, OffsetToCIERecord));
665 OffsetToCIERecord = IteratorInserted.first->getValue();
667 // Emit CIE for this ID if it is not emitted yet.
668 if (IteratorInserted.second)
669 OutSection.OS << CIEData;
671 // Remember offset to the FDE record, so that we might update
672 // field referencing CIE record(containing OffsetToCIERecord),
673 // when final offsets are known. OffsetToCIERecord(which is written later)
674 // is local to the current .debug_frame section, it should be updated
675 // with final offset of the .debug_frame section.
676 OutSection.notePatch(
677 DebugOffsetPatch{OutSection.OS.tell() + 4, &OutSection, true});
679 // Emit the FDE with updated address and CIE pointer.
680 // (4 + AddrSize) is the size of the CIEId + initial_location
681 // fields that will get reconstructed by emitFDE().
682 unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);
683 emitFDE(OffsetToCIERecord, SrcAddrSize, Loc + Range->Value,
684 OrigFrameData.substr(InputOffset, FDERemainingBytes), OutSection);
685 InputOffset += FDERemainingBytes;
688 return Error::success();
691 /// Emit a FDE into the debug_frame section. \p FDEBytes
692 /// contains the FDE data without the length, CIE offset and address
693 /// which will be replaced with the parameter values.
694 void DWARFLinkerImpl::LinkContext::emitFDE(uint32_t CIEOffset,
695 uint32_t AddrSize, uint64_t Address,
696 StringRef FDEBytes,
697 SectionDescriptor &Section) {
698 Section.emitIntVal(FDEBytes.size() + 4 + AddrSize, 4);
699 Section.emitIntVal(CIEOffset, 4);
700 Section.emitIntVal(Address, AddrSize);
701 Section.OS.write(FDEBytes.data(), FDEBytes.size());
704 void DWARFLinkerImpl::glueCompileUnitsAndWriteToTheOutput() {
705 if (GlobalData.getOptions().NoOutput)
706 return;
708 // Go through all object files, all compile units and assign
709 // offsets to them.
710 assignOffsets();
712 // Patch size/offsets fields according to the assigned CU offsets.
713 patchOffsetsAndSizes();
715 // FIXME: Build accelerator tables.
717 // Emit common sections.
718 emitCommonSections();
720 // Cleanup data.
721 cleanupDataAfterOutputSectionsAreGenerated();
723 // Write debug tables from all object files/compile units into the
724 // resulting file.
725 writeDWARFToTheOutput();
727 if (GlobalData.getOptions().Statistics)
728 printStatistic();
731 void DWARFLinkerImpl::printStatistic() {
733 // For each object file map how many bytes were emitted.
734 StringMap<DebugInfoSize> SizeByObject;
736 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
737 uint64_t AllDebugInfoSectionsSize = 0;
739 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
740 if (std::optional<SectionDescriptor *> DebugInfo =
741 CU->getSectionDescriptor(DebugSectionKind::DebugInfo))
742 AllDebugInfoSectionsSize += (*DebugInfo)->getContents().size();
744 SizeByObject[Context->InputDWARFFile.FileName].Input =
745 Context->OriginalDebugInfoSize;
746 SizeByObject[Context->InputDWARFFile.FileName].Output =
747 AllDebugInfoSectionsSize;
750 // Create a vector sorted in descending order by output size.
751 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
752 for (auto &E : SizeByObject)
753 Sorted.emplace_back(E.first(), E.second);
754 llvm::sort(Sorted, [](auto &LHS, auto &RHS) {
755 return LHS.second.Output > RHS.second.Output;
758 auto ComputePercentange = [](int64_t Input, int64_t Output) -> float {
759 const float Difference = Output - Input;
760 const float Sum = Input + Output;
761 if (Sum == 0)
762 return 0;
763 return (Difference / (Sum / 2));
766 int64_t InputTotal = 0;
767 int64_t OutputTotal = 0;
768 const char *FormatStr = "{0,-45} {1,10}b {2,10}b {3,8:P}\n";
770 // Print header.
771 outs() << ".debug_info section size (in bytes)\n";
772 outs() << "----------------------------------------------------------------"
773 "---------------\n";
774 outs() << "Filename Object "
775 " dSYM Change\n";
776 outs() << "----------------------------------------------------------------"
777 "---------------\n";
779 // Print body.
780 for (auto &E : Sorted) {
781 InputTotal += E.second.Input;
782 OutputTotal += E.second.Output;
783 llvm::outs() << formatv(
784 FormatStr, sys::path::filename(E.first).take_back(45), E.second.Input,
785 E.second.Output, ComputePercentange(E.second.Input, E.second.Output));
787 // Print total and footer.
788 outs() << "----------------------------------------------------------------"
789 "---------------\n";
790 llvm::outs() << formatv(FormatStr, "Total", InputTotal, OutputTotal,
791 ComputePercentange(InputTotal, OutputTotal));
792 outs() << "----------------------------------------------------------------"
793 "---------------\n\n";
796 void DWARFLinkerImpl::assignOffsets() {
797 parallel::TaskGroup TGroup;
798 TGroup.spawn([&]() { assignOffsetsToStrings(); });
799 TGroup.spawn([&]() { assignOffsetsToSections(); });
802 void DWARFLinkerImpl::assignOffsetsToStrings() {
803 size_t CurDebugStrIndex = 1; // start from 1 to take into account zero entry.
804 uint64_t CurDebugStrOffset =
805 1; // start from 1 to take into account zero entry.
806 size_t CurDebugLineStrIndex = 0;
807 uint64_t CurDebugLineStrOffset = 0;
809 // To save space we do not create any separate string table.
810 // We use already allocated string patches and assign offsets
811 // to them in the natural order.
812 // ASSUMPTION: strings should be stored into .debug_str/.debug_line_str
813 // sections in the same order as they were assigned offsets.
815 forEachObjectSectionsSet([&](OutputSections &SectionsSet) {
816 SectionsSet.forEach([&](SectionDescriptor &OutSection) {
817 assignOffsetsToStringsImpl(OutSection.ListDebugStrPatch, CurDebugStrIndex,
818 CurDebugStrOffset, DebugStrStrings);
820 assignOffsetsToStringsImpl(OutSection.ListDebugLineStrPatch,
821 CurDebugLineStrIndex, CurDebugLineStrOffset,
822 DebugLineStrStrings);
827 template <typename PatchTy>
828 void DWARFLinkerImpl::assignOffsetsToStringsImpl(
829 ArrayList<PatchTy> &Patches, size_t &IndexAccumulator,
830 uint64_t &OffsetAccumulator,
831 StringEntryToDwarfStringPoolEntryMap &StringsForEmission) {
833 // Enumerates all patches, adds string into the
834 // StringEntry->DwarfStringPoolEntry map, assign offset and index to the
835 // string if it is not indexed yet.
836 Patches.forEach([&](PatchTy &Patch) {
837 DwarfStringPoolEntryWithExtString *Entry =
838 StringsForEmission.add(Patch.String);
839 assert(Entry != nullptr);
841 if (!Entry->isIndexed()) {
842 Entry->Offset = OffsetAccumulator;
843 OffsetAccumulator += Entry->String.size() + 1;
844 Entry->Index = IndexAccumulator++;
849 void DWARFLinkerImpl::assignOffsetsToSections() {
850 std::array<uint64_t, SectionKindsNum> SectionSizesAccumulator = {0};
852 forEachObjectSectionsSet([&](OutputSections &UnitSections) {
853 UnitSections.assignSectionsOffsetAndAccumulateSize(SectionSizesAccumulator);
857 void DWARFLinkerImpl::forEachObjectSectionsSet(
858 function_ref<void(OutputSections &)> SectionsSetHandler) {
859 // Handle all modules first(before regular compilation units).
860 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
861 for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
862 SectionsSetHandler(*ModuleUnit.Unit);
864 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
865 // Handle object file common sections.
866 SectionsSetHandler(*Context);
868 // Handle compilation units.
869 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
870 SectionsSetHandler(*CU);
874 void DWARFLinkerImpl::patchOffsetsAndSizes() {
875 forEachObjectSectionsSet([&](OutputSections &SectionsSet) {
876 SectionsSet.forEach([&](SectionDescriptor &OutSection) {
877 SectionsSet.applyPatches(OutSection, DebugStrStrings,
878 DebugLineStrStrings);
883 template <typename PatchTy>
884 void DWARFLinkerImpl::emitStringsImpl(
885 ArrayList<PatchTy> &StringPatches,
886 const StringEntryToDwarfStringPoolEntryMap &Strings, uint64_t &NextOffset,
887 SectionDescriptor &OutSection) {
888 // Enumerate all string patches and write strings into the destination
889 // section. We enumerate patches to have a predictable order of strings(i.e.
890 // strings are emitted in the order as they appear in the patches).
891 StringPatches.forEach([&](const PatchTy &Patch) {
892 DwarfStringPoolEntryWithExtString *StringToEmit =
893 Strings.getExistingEntry(Patch.String);
894 assert(StringToEmit->isIndexed());
896 // Patches can refer the same strings. We use accumulated NextOffset
897 // to understand whether corresponding string is already emitted.
898 // Skip patch if string is already emitted.
899 if (StringToEmit->Offset >= NextOffset) {
900 NextOffset = StringToEmit->Offset + StringToEmit->String.size() + 1;
901 // Emit the string itself.
902 OutSection.emitInplaceString(StringToEmit->String);
907 void DWARFLinkerImpl::emitCommonSections() {
908 parallel::TaskGroup TG;
910 SectionDescriptor &OutDebugStrSection =
911 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugStr);
912 SectionDescriptor &OutDebugLineStrSection =
913 CommonSections.getOrCreateSectionDescriptor(
914 DebugSectionKind::DebugLineStr);
916 // Emit .debug_str section.
917 TG.spawn([&]() {
918 uint64_t DebugStrNextOffset = 0;
920 // Emit zero length string. Accelerator tables does not work correctly
921 // if the first string is not zero length string.
922 OutDebugStrSection.emitInplaceString("");
923 DebugStrNextOffset++;
925 forEachObjectSectionsSet([&](OutputSections &Sections) {
926 Sections.forEach([&](SectionDescriptor &Section) {
927 emitStringsImpl(Section.ListDebugStrPatch, DebugStrStrings,
928 DebugStrNextOffset, OutDebugStrSection);
933 // Emit .debug_line_str section.
934 TG.spawn([&]() {
935 uint64_t DebugLineStrNextOffset = 0;
937 forEachObjectSectionsSet([&](OutputSections &Sections) {
938 Sections.forEach([&](SectionDescriptor &Section) {
939 emitStringsImpl(Section.ListDebugLineStrPatch, DebugLineStrStrings,
940 DebugLineStrNextOffset, OutDebugLineStrSection);
946 void DWARFLinkerImpl::cleanupDataAfterOutputSectionsAreGenerated() {
947 GlobalData.getStringPool().clear();
948 DebugStrStrings.clear();
949 DebugLineStrStrings.clear();
952 void DWARFLinkerImpl::writeDWARFToTheOutput() {
953 bool HasAbbreviations = false;
955 forEachObjectSectionsSet([&](OutputSections &Sections) {
956 Sections.forEach([&](SectionDescriptor &OutSection) {
957 if (!HasAbbreviations && !OutSection.getContents().empty() &&
958 OutSection.getKind() == DebugSectionKind::DebugAbbrev)
959 HasAbbreviations = true;
961 // Emit section content.
962 TheDwarfEmitter->emitSectionContents(OutSection.getContents(),
963 OutSection.getName());
964 OutSection.erase();
968 CommonSections.forEach([&](SectionDescriptor &OutSection) {
969 // Emit section content.
970 TheDwarfEmitter->emitSectionContents(OutSection.getContents(),
971 OutSection.getName());
972 OutSection.erase();
975 if (!HasAbbreviations) {
976 const SmallVector<std::unique_ptr<DIEAbbrev>> Abbreviations;
977 TheDwarfEmitter->emitAbbrevs(Abbreviations, 3);
981 } // end of namespace dwarflinker_parallel
982 } // namespace llvm