1 //=== DWARFLinkerImpl.cpp -------------------------------------------------===//
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
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"
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();
50 // Register mofule reference.
51 if (!GlobalData
.getOptions().UpdateIndexTablesOnly
)
52 ObjectContexts
.back()->registerModuleReference(CUDie
, Loader
,
58 Error
DWARFLinkerImpl::link() {
59 // reset compile unit unique ID counter.
62 if (Error Err
= validateAndUpdateOptions())
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
);
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
);
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) {
108 GlobalFormat
.AddrSize
=
109 TheDwarfEmitter
->getTargetTriple().isArch32Bit() ? 4 : 8;
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
);
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
) {
126 if (Error Err
= Context
->link())
127 GlobalData
.error(std::move(Err
), Context
->InputDWARFFile
.FileName
);
129 Context
->InputDWARFFile
.unload();
132 ThreadPool
Pool(parallel::strategy
);
133 for (std::unique_ptr
<LinkContext
> &Context
: ObjectContexts
)
136 if (Error Err
= Context
->link())
137 GlobalData
.error(std::move(Err
), Context
->InputDWARFFile
.FileName
);
139 Context
->InputDWARFFile
.unload();
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
) {
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;
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
}));
196 remapPath(StringRef Path
,
197 const DWARFLinker::ObjectPrefixMapTy
&ObjectPrefixMap
) {
198 if (ObjectPrefixMap
.empty())
201 SmallString
<256> p
= Path
;
202 for (const auto &Entry
: ObjectPrefixMap
)
203 if (llvm::sys::path::replace_path_prefix(p
, Entry
.first
, Entry
.second
))
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
}), "");
217 PCMFile
= remapPath(PCMFile
, *ObjectPrefixMap
);
222 std::pair
<bool, bool> DWARFLinkerImpl::LinkContext::isClangModuleRef(
223 const DWARFDie
&CUDie
, std::string
&PCMFile
, unsigned Indent
, bool Quiet
) {
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
), "");
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
))
250 Twine("hash mismatch: this object file was built against a "
251 "different version of the module ") +
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
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
)
279 if (IsClangModuleRef
.second
)
282 if (GlobalData
.getOptions().Verbose
)
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
)});
290 loadClangModule(Loader
, CUDie
, PCMFile
, OnCUDieLoaded
, Indent
+ 2)) {
291 consumeError(std::move(E
));
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
);
320 return Error::success();
322 std::unique_ptr
<CompileUnit
> Unit
;
323 for (const auto &CU
: ErrOrObj
->Dwarf
->compile_units()) {
325 // Recursively get all modules imported by this one.
326 auto ChildCUDie
= CU
->getUnitDIE();
329 if (!registerModuleReference(ChildCUDie
, Loader
, OnCUDieLoaded
, Indent
)) {
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
)
344 Twine("hash mismatch: this object file was built against a "
345 "different version of the module ") +
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())
357 Unit
= std::make_unique
<CompileUnit
>(
358 GlobalData
, *CU
, UniqueUnitID
.fetch_add(1), ModuleName
, *ErrOrObj
,
359 getUnitForOffset
, CU
->getFormParams(), getEndianness());
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
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
422 parallelForEach(CompileUnits
, [&](std::unique_ptr
<CompileUnit
> &CU
) {
423 linkSingleCompileUnit(*CU
);
426 // Link all inter-connected units.
427 if (HasNewInterconnectedCUs
) {
428 InterCUProcessingStarted
= true;
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
);
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())
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.
476 if (Error Err
= cloneAndEmitDebugFrame())
477 ResultErr
= std::move(Err
);
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())
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
);
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
);
511 CU
.setStage(CompileUnit::Stage::Loaded
);
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
);
523 CU
.setStage(CompileUnit::Stage::LivenessAnalysisDone
);
526 case CompileUnit::Stage::LivenessAnalysisDone
:
529 DependencyTracker::verifyKeepChain(CU
);
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
);
542 case CompileUnit::Stage::Cloned
:
543 // Update DIEs referencies.
544 CU
.updateDieRefPatchesWithClonedOffsets();
545 CU
.setStage(CompileUnit::Stage::PatchesUpdated
);
548 case CompileUnit::Stage::PatchesUpdated
:
549 // Cleanup resources.
550 CU
.cleanupDataAfterClonning();
551 CU
.setStage(CompileUnit::Stage::Cleaned
);
554 case CompileUnit::Stage::Cleaned
:
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
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;
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
);
645 // The +4 is to account for the size of the InitialLength field itself.
646 InputOffset
= EntryOffset
+ InitialLength
+ 4;
650 // This is an FDE, and we have a mapping.
651 // Have we already emitted a corresponding CIE?
652 StringRef CIEData
= LocalCIES
[CIEId
];
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
,
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
)
708 // Go through all object files, all compile units and assign
712 // Patch size/offsets fields according to the assigned CU offsets.
713 patchOffsetsAndSizes();
715 // FIXME: Build accelerator tables.
717 // Emit common sections.
718 emitCommonSections();
721 cleanupDataAfterOutputSectionsAreGenerated();
723 // Write debug tables from all object files/compile units into the
725 writeDWARFToTheOutput();
727 if (GlobalData
.getOptions().Statistics
)
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
;
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";
771 outs() << ".debug_info section size (in bytes)\n";
772 outs() << "----------------------------------------------------------------"
774 outs() << "Filename Object "
776 outs() << "----------------------------------------------------------------"
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() << "----------------------------------------------------------------"
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.
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.
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());
968 CommonSections
.forEach([&](SectionDescriptor
&OutSection
) {
969 // Emit section content.
970 TheDwarfEmitter
->emitSectionContents(OutSection
.getContents(),
971 OutSection
.getName());
975 if (!HasAbbreviations
) {
976 const SmallVector
<std::unique_ptr
<DIEAbbrev
>> Abbreviations
;
977 TheDwarfEmitter
->emitAbbrevs(Abbreviations
, 3);
981 } // end of namespace dwarflinker_parallel