Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / lib / DWARFLinkerParallel / DWARFLinkerImpl.cpp
bloba755d540aef99e113ba29a112584d95f330f5cff
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 llvm::endianness GlobalEndianness = llvm::endianness::native;
69 if (TheDwarfEmitter) {
70 GlobalEndianness = TheDwarfEmitter->getTargetTriple().isLittleEndian()
71 ? llvm::endianness::little
72 : llvm::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 // Emit common sections and write debug tables from all object files/compile
716 // units into the resulting file.
717 emitCommonSectionsAndWriteCompileUnitsToTheOutput();
719 // Write common debug sections into the resulting file.
720 writeCommonSectionsToTheOutput();
722 // Cleanup data.
723 cleanupDataAfterDWARFOutputIsWritten();
725 if (GlobalData.getOptions().Statistics)
726 printStatistic();
729 void DWARFLinkerImpl::printStatistic() {
731 // For each object file map how many bytes were emitted.
732 StringMap<DebugInfoSize> SizeByObject;
734 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
735 uint64_t AllDebugInfoSectionsSize = 0;
737 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
738 if (std::optional<SectionDescriptor *> DebugInfo =
739 CU->tryGetSectionDescriptor(DebugSectionKind::DebugInfo))
740 AllDebugInfoSectionsSize += (*DebugInfo)->getContents().size();
742 SizeByObject[Context->InputDWARFFile.FileName].Input =
743 Context->OriginalDebugInfoSize;
744 SizeByObject[Context->InputDWARFFile.FileName].Output =
745 AllDebugInfoSectionsSize;
748 // Create a vector sorted in descending order by output size.
749 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
750 for (auto &E : SizeByObject)
751 Sorted.emplace_back(E.first(), E.second);
752 llvm::sort(Sorted, [](auto &LHS, auto &RHS) {
753 return LHS.second.Output > RHS.second.Output;
756 auto ComputePercentange = [](int64_t Input, int64_t Output) -> float {
757 const float Difference = Output - Input;
758 const float Sum = Input + Output;
759 if (Sum == 0)
760 return 0;
761 return (Difference / (Sum / 2));
764 int64_t InputTotal = 0;
765 int64_t OutputTotal = 0;
766 const char *FormatStr = "{0,-45} {1,10}b {2,10}b {3,8:P}\n";
768 // Print header.
769 outs() << ".debug_info section size (in bytes)\n";
770 outs() << "----------------------------------------------------------------"
771 "---------------\n";
772 outs() << "Filename Object "
773 " dSYM Change\n";
774 outs() << "----------------------------------------------------------------"
775 "---------------\n";
777 // Print body.
778 for (auto &E : Sorted) {
779 InputTotal += E.second.Input;
780 OutputTotal += E.second.Output;
781 llvm::outs() << formatv(
782 FormatStr, sys::path::filename(E.first).take_back(45), E.second.Input,
783 E.second.Output, ComputePercentange(E.second.Input, E.second.Output));
785 // Print total and footer.
786 outs() << "----------------------------------------------------------------"
787 "---------------\n";
788 llvm::outs() << formatv(FormatStr, "Total", InputTotal, OutputTotal,
789 ComputePercentange(InputTotal, OutputTotal));
790 outs() << "----------------------------------------------------------------"
791 "---------------\n\n";
794 void DWARFLinkerImpl::assignOffsets() {
795 parallel::TaskGroup TGroup;
796 TGroup.spawn([&]() { assignOffsetsToStrings(); });
797 TGroup.spawn([&]() { assignOffsetsToSections(); });
800 void DWARFLinkerImpl::assignOffsetsToStrings() {
801 size_t CurDebugStrIndex = 1; // start from 1 to take into account zero entry.
802 uint64_t CurDebugStrOffset =
803 1; // start from 1 to take into account zero entry.
804 size_t CurDebugLineStrIndex = 0;
805 uint64_t CurDebugLineStrOffset = 0;
807 // Enumerates all strings, add them into the DwarfStringPoolEntry map,
808 // assign offset and index to the string if it is not indexed yet.
809 forEachOutputString([&](StringDestinationKind Kind,
810 const StringEntry *String) {
811 switch (Kind) {
812 case StringDestinationKind::DebugStr: {
813 DwarfStringPoolEntryWithExtString *Entry = DebugStrStrings.add(String);
814 assert(Entry != nullptr);
816 if (!Entry->isIndexed()) {
817 Entry->Offset = CurDebugStrOffset;
818 CurDebugStrOffset += Entry->String.size() + 1;
819 Entry->Index = CurDebugStrIndex++;
821 } break;
822 case StringDestinationKind::DebugLineStr: {
823 DwarfStringPoolEntryWithExtString *Entry =
824 DebugLineStrStrings.add(String);
825 assert(Entry != nullptr);
827 if (!Entry->isIndexed()) {
828 Entry->Offset = CurDebugLineStrOffset;
829 CurDebugLineStrOffset += Entry->String.size() + 1;
830 Entry->Index = CurDebugLineStrIndex++;
832 } break;
837 void DWARFLinkerImpl::assignOffsetsToSections() {
838 std::array<uint64_t, SectionKindsNum> SectionSizesAccumulator = {0};
840 forEachObjectSectionsSet([&](OutputSections &UnitSections) {
841 UnitSections.assignSectionsOffsetAndAccumulateSize(SectionSizesAccumulator);
845 void DWARFLinkerImpl::forEachOutputString(
846 function_ref<void(StringDestinationKind Kind, const StringEntry *String)>
847 StringHandler) {
848 // To save space we do not create any separate string table.
849 // We use already allocated string patches and accelerator entries:
850 // enumerate them in natural order and assign offsets.
851 // ASSUMPTION: strings should be stored into .debug_str/.debug_line_str
852 // sections in the same order as they were assigned offsets.
853 forEachCompileUnit([&](CompileUnit *CU) {
854 CU->forEach([&](SectionDescriptor &OutSection) {
855 OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
856 StringHandler(StringDestinationKind::DebugStr, Patch.String);
859 OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
860 StringHandler(StringDestinationKind::DebugLineStr, Patch.String);
864 CU->AcceleratorRecords.forEach([&](DwarfUnit::AccelInfo &Info) {
865 StringHandler(DebugStr, Info.String);
870 void DWARFLinkerImpl::forEachObjectSectionsSet(
871 function_ref<void(OutputSections &)> SectionsSetHandler) {
872 // Handle all modules first(before regular compilation units).
873 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
874 for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
875 SectionsSetHandler(*ModuleUnit.Unit);
877 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
878 // Handle object file common sections.
879 SectionsSetHandler(*Context);
881 // Handle compilation units.
882 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
883 SectionsSetHandler(*CU);
887 void DWARFLinkerImpl::forEachCompileUnit(
888 function_ref<void(CompileUnit *CU)> UnitHandler) {
889 // Enumerate module units.
890 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
891 for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
892 UnitHandler(ModuleUnit.Unit.get());
894 // Enumerate compile units.
895 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
896 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
897 UnitHandler(CU.get());
900 void DWARFLinkerImpl::patchOffsetsAndSizes() {
901 forEachObjectSectionsSet([&](OutputSections &SectionsSet) {
902 SectionsSet.forEach([&](SectionDescriptor &OutSection) {
903 SectionsSet.applyPatches(OutSection, DebugStrStrings,
904 DebugLineStrStrings);
909 void DWARFLinkerImpl::emitCommonSectionsAndWriteCompileUnitsToTheOutput() {
910 parallel::TaskGroup TG;
912 // Create section descriptors ahead if they are not exist at the moment.
913 // SectionDescriptors container is not thread safe. Thus we should be sure
914 // that descriptors would not be created in following parallel tasks.
916 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugStr);
917 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugLineStr);
919 if (llvm::is_contained(GlobalData.Options.AccelTables,
920 AccelTableKind::Apple)) {
921 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleNames);
922 CommonSections.getOrCreateSectionDescriptor(
923 DebugSectionKind::AppleNamespaces);
924 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleObjC);
925 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleTypes);
928 if (llvm::is_contained(GlobalData.Options.AccelTables,
929 AccelTableKind::DebugNames))
930 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugNames);
932 const Triple &TargetTriple = TheDwarfEmitter->getTargetTriple();
934 // Emit .debug_str and .debug_line_str sections.
935 TG.spawn([&]() { emitStringSections(); });
937 if (llvm::is_contained(GlobalData.Options.AccelTables,
938 AccelTableKind::Apple)) {
939 // Emit apple accelerator sections.
940 TG.spawn([&]() { emitAppleAcceleratorSections(TargetTriple); });
943 if (llvm::is_contained(GlobalData.Options.AccelTables,
944 AccelTableKind::DebugNames)) {
945 // Emit .debug_names section.
946 TG.spawn([&]() { emitDWARFv5DebugNamesSection(TargetTriple); });
949 // Write compile units to the output file.
950 TG.spawn([&]() { writeCompileUnitsToTheOutput(); });
953 void DWARFLinkerImpl::emitStringSections() {
954 uint64_t DebugStrNextOffset = 0;
955 uint64_t DebugLineStrNextOffset = 0;
957 // Emit zero length string. Accelerator tables does not work correctly
958 // if the first string is not zero length string.
959 CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)
960 .emitInplaceString("");
961 DebugStrNextOffset++;
963 forEachOutputString(
964 [&](StringDestinationKind Kind, const StringEntry *String) {
965 switch (Kind) {
966 case StringDestinationKind::DebugStr: {
967 DwarfStringPoolEntryWithExtString *StringToEmit =
968 DebugStrStrings.getExistingEntry(String);
969 assert(StringToEmit->isIndexed());
971 // Strings may be repeated. Use accumulated DebugStrNextOffset
972 // to understand whether corresponding string is already emitted.
973 // Skip string if its offset less than accumulated offset.
974 if (StringToEmit->Offset >= DebugStrNextOffset) {
975 DebugStrNextOffset =
976 StringToEmit->Offset + StringToEmit->String.size() + 1;
977 // Emit the string itself.
978 CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)
979 .emitInplaceString(StringToEmit->String);
981 } break;
982 case StringDestinationKind::DebugLineStr: {
983 DwarfStringPoolEntryWithExtString *StringToEmit =
984 DebugLineStrStrings.getExistingEntry(String);
985 assert(StringToEmit->isIndexed());
987 // Strings may be repeated. Use accumulated DebugLineStrStrings
988 // to understand whether corresponding string is already emitted.
989 // Skip string if its offset less than accumulated offset.
990 if (StringToEmit->Offset >= DebugLineStrNextOffset) {
991 DebugLineStrNextOffset =
992 StringToEmit->Offset + StringToEmit->String.size() + 1;
993 // Emit the string itself.
994 CommonSections.getSectionDescriptor(DebugSectionKind::DebugLineStr)
995 .emitInplaceString(StringToEmit->String);
997 } break;
1002 void DWARFLinkerImpl::emitAppleAcceleratorSections(const Triple &TargetTriple) {
1003 AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces;
1004 AccelTable<AppleAccelTableStaticOffsetData> AppleNames;
1005 AccelTable<AppleAccelTableStaticOffsetData> AppleObjC;
1006 AccelTable<AppleAccelTableStaticTypeData> AppleTypes;
1008 forEachCompileUnit([&](CompileUnit *CU) {
1009 CU->AcceleratorRecords.forEach([&](const DwarfUnit::AccelInfo &Info) {
1010 switch (Info.Type) {
1011 case DwarfUnit::AccelType::None: {
1012 llvm_unreachable("Unknown accelerator record");
1013 } break;
1014 case DwarfUnit::AccelType::Namespace: {
1015 AppleNamespaces.addName(
1016 *DebugStrStrings.getExistingEntry(Info.String),
1017 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1018 Info.OutOffset);
1019 } break;
1020 case DwarfUnit::AccelType::Name: {
1021 AppleNames.addName(
1022 *DebugStrStrings.getExistingEntry(Info.String),
1023 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1024 Info.OutOffset);
1025 } break;
1026 case DwarfUnit::AccelType::ObjC: {
1027 AppleObjC.addName(
1028 *DebugStrStrings.getExistingEntry(Info.String),
1029 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1030 Info.OutOffset);
1031 } break;
1032 case DwarfUnit::AccelType::Type: {
1033 AppleTypes.addName(
1034 *DebugStrStrings.getExistingEntry(Info.String),
1035 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1036 Info.OutOffset,
1037 Info.Tag,
1038 Info.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation
1039 : 0,
1040 Info.QualifiedNameHash);
1041 } break;
1047 // FIXME: we use AsmPrinter to emit accelerator sections.
1048 // It might be beneficial to directly emit accelerator data
1049 // to the raw_svector_ostream.
1050 SectionDescriptor &OutSection =
1051 CommonSections.getSectionDescriptor(DebugSectionKind::AppleNamespaces);
1052 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
1053 OutSection.OS);
1054 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1055 consumeError(std::move(Err));
1056 return;
1059 // Emit table.
1060 Emitter.emitAppleNamespaces(AppleNamespaces);
1061 Emitter.finish();
1063 // Set start offset and size for output section.
1064 OutSection.setSizesForSectionCreatedByAsmPrinter();
1068 // FIXME: we use AsmPrinter to emit accelerator sections.
1069 // It might be beneficial to directly emit accelerator data
1070 // to the raw_svector_ostream.
1071 SectionDescriptor &OutSection =
1072 CommonSections.getSectionDescriptor(DebugSectionKind::AppleNames);
1073 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
1074 OutSection.OS);
1075 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1076 consumeError(std::move(Err));
1077 return;
1080 // Emit table.
1081 Emitter.emitAppleNames(AppleNames);
1082 Emitter.finish();
1084 // Set start offset ans size for output section.
1085 OutSection.setSizesForSectionCreatedByAsmPrinter();
1089 // FIXME: we use AsmPrinter to emit accelerator sections.
1090 // It might be beneficial to directly emit accelerator data
1091 // to the raw_svector_ostream.
1092 SectionDescriptor &OutSection =
1093 CommonSections.getSectionDescriptor(DebugSectionKind::AppleObjC);
1094 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
1095 OutSection.OS);
1096 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1097 consumeError(std::move(Err));
1098 return;
1101 // Emit table.
1102 Emitter.emitAppleObjc(AppleObjC);
1103 Emitter.finish();
1105 // Set start offset ans size for output section.
1106 OutSection.setSizesForSectionCreatedByAsmPrinter();
1110 // FIXME: we use AsmPrinter to emit accelerator sections.
1111 // It might be beneficial to directly emit accelerator data
1112 // to the raw_svector_ostream.
1113 SectionDescriptor &OutSection =
1114 CommonSections.getSectionDescriptor(DebugSectionKind::AppleTypes);
1115 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
1116 OutSection.OS);
1117 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1118 consumeError(std::move(Err));
1119 return;
1122 // Emit table.
1123 Emitter.emitAppleTypes(AppleTypes);
1124 Emitter.finish();
1126 // Set start offset ans size for output section.
1127 OutSection.setSizesForSectionCreatedByAsmPrinter();
1131 void DWARFLinkerImpl::emitDWARFv5DebugNamesSection(const Triple &TargetTriple) {
1132 std::unique_ptr<DWARF5AccelTable> DebugNames;
1134 DebugNamesUnitsOffsets CompUnits;
1135 CompUnitIDToIdx CUidToIdx;
1137 unsigned Id = 0;
1139 forEachCompileUnit([&](CompileUnit *CU) {
1140 CompUnits.push_back(
1141 CU->getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)
1142 .StartOffset);
1143 CUidToIdx[CU->getUniqueID()] = Id++;
1145 CU->AcceleratorRecords.forEach([&](const DwarfUnit::AccelInfo &Info) {
1146 if (DebugNames.get() == nullptr)
1147 DebugNames = std::make_unique<DWARF5AccelTable>();
1149 switch (Info.Type) {
1150 case DwarfUnit::AccelType::Name:
1151 case DwarfUnit::AccelType::Namespace:
1152 case DwarfUnit::AccelType::Type: {
1153 DebugNames->addName(*DebugStrStrings.getExistingEntry(Info.String),
1154 Info.OutOffset, Info.Tag, CU->getUniqueID());
1155 } break;
1157 default:
1158 break; // Nothing to do.
1163 if (DebugNames.get() != nullptr) {
1164 // FIXME: we use AsmPrinter to emit accelerator sections.
1165 // It might be beneficial to directly emit accelerator data
1166 // to the raw_svector_ostream.
1167 SectionDescriptor &OutSection =
1168 CommonSections.getSectionDescriptor(DebugSectionKind::DebugNames);
1169 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
1170 OutSection.OS);
1171 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1172 consumeError(std::move(Err));
1173 return;
1176 // Emit table.
1177 Emitter.emitDebugNames(*DebugNames, CompUnits, CUidToIdx);
1178 Emitter.finish();
1180 // Set start offset ans size for output section.
1181 OutSection.setSizesForSectionCreatedByAsmPrinter();
1185 void DWARFLinkerImpl::cleanupDataAfterDWARFOutputIsWritten() {
1186 GlobalData.getStringPool().clear();
1187 DebugStrStrings.clear();
1188 DebugLineStrStrings.clear();
1191 void DWARFLinkerImpl::writeCompileUnitsToTheOutput() {
1192 bool HasAbbreviations = false;
1194 // Enumerate all sections and store them into the final emitter.
1195 forEachObjectSectionsSet([&](OutputSections &Sections) {
1196 Sections.forEach([&](SectionDescriptor &OutSection) {
1197 if (!HasAbbreviations && !OutSection.getContents().empty() &&
1198 OutSection.getKind() == DebugSectionKind::DebugAbbrev)
1199 HasAbbreviations = true;
1201 // Emit section content.
1202 TheDwarfEmitter->emitSectionContents(OutSection.getContents(),
1203 OutSection.getName());
1204 OutSection.clearSectionContent();
1208 if (!HasAbbreviations) {
1209 const SmallVector<std::unique_ptr<DIEAbbrev>> Abbreviations;
1210 TheDwarfEmitter->emitAbbrevs(Abbreviations, 3);
1214 void DWARFLinkerImpl::writeCommonSectionsToTheOutput() {
1215 CommonSections.forEach([&](SectionDescriptor &OutSection) {
1216 // Emit section content.
1217 TheDwarfEmitter->emitSectionContents(OutSection.getContents(),
1218 OutSection.getName());
1219 OutSection.clearSectionContent();
1223 } // end of namespace dwarflinker_parallel
1224 } // namespace llvm