1//===- DWARFLinker.h --------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_DWARFLINKER_PARALLEL_DWARFLINKER_H
10#define LLVM_DWARFLINKER_PARALLEL_DWARFLINKER_H
11
12#include "llvm/CodeGen/AsmPrinter.h"
13#include "llvm/DWARFLinker/DWARFFile.h"
14#include "llvm/DWARFLinker/DWARFLinkerBase.h"
15#include "llvm/DebugInfo/DWARF/DWARFContext.h"
16#include "llvm/DebugInfo/DWARF/DWARFDie.h"
17#include "llvm/MC/MCDwarf.h"
18#include "llvm/TargetParser/Triple.h"
19
20/// ------------------------------------------------------------------
21/// The core of the Dwarf linking logic.
22///
23/// The generation of the dwarf information from the object files will be
24/// driven by the selection of 'root DIEs', which are DIEs that
25/// describe variables or functions that resolves to the corresponding
26/// code section(and thus have entries in the Addresses map). All the debug
27/// information that will be generated(the DIEs, but also the line
28/// tables, ranges, ...) is derived from that set of root DIEs.
29///
30/// The root DIEs are identified because they contain relocations that
31/// points to code section(the low_pc for a function, the location for
32/// a variable). These relocations are gathered as a very first step
33/// when we start processing a object file by AddressesMap.
34///
35/// The overall linking process looks like this:
36///
37/// parrallel_for_each(ObjectFile) {
38/// for_each (Compile Unit) {
39/// 1. Load Clang modules.
40/// }
41///
42/// parrallel_for_each(Compile Unit) {
43/// 1. Load input DWARF for Compile Unit.
44/// 2. Report warnings for Clang modules.
45/// 3. Analyze live DIEs and type names(if ODR deduplication is requested).
46/// 4. Clone DIEs(Generate output DIEs and resulting DWARF tables).
47/// The result is in an OutDebugInfoBytes, which is an ELF file
48/// containing DWARF tables corresponding to the current compile unit.
49/// 5. Cleanup Input and Output DIEs.
50/// }
51///
52/// Deallocate loaded Object file.
53/// }
54///
55/// if (ODR deduplication is requested)
56/// Generate an artificial compilation unit ("Type Table": used to partially
57/// generate DIEs at the clone stage).
58///
59/// for_each (ObjectFile) {
60/// for_each (Compile Unit) {
61/// 1. Set offsets to Compile Units DWARF tables.
62/// 2. Sort offsets/attributes/patches to have a predictable result.
63/// 3. Patch size/offsets fields.
64/// 4. Generate index tables.
65/// 5. Move DWARF tables of compile units into the resulting file.
66/// }
67/// }
68///
69/// Every compile unit is processed separately, visited only once
70/// (except case inter-CU references exist), and used data is freed
71/// after the compile unit is processed. The resulting file is glued together
72/// from the generated debug tables which correspond to separate compile units.
73///
74/// Handling inter-CU references: inter-CU references are hard to process
75/// using only one pass. f.e. if CU1 references CU100 and CU100 references
76/// CU1, we could not finish handling of CU1 until we finished CU100.
77/// Thus we either need to load all CUs into the memory, either load CUs several
78/// times. This implementation loads inter-connected CU into memory at the first
79/// pass and processes them at the second pass.
80///
81/// ODR deduplication: Artificial compilation unit will be constructed to keep
82/// type dies. All types are moved into that compilation unit. Type's references
83/// are patched so that they point to the corresponding types from artificial
84/// compilation unit. All partial type definitions would be merged into single
85/// type definition.
86///
87
88namespace llvm {
89namespace dwarf_linker {
90namespace parallel {
91
92/// This structure keeps data of the concrete section.
93struct SectionDescriptorBase {
94 SectionDescriptorBase(DebugSectionKind SectionKind, dwarf::FormParams Format,
95 llvm::endianness Endianess)
96 : SectionKind(SectionKind), Format(Format), Endianess(Endianess) {}
97 virtual ~SectionDescriptorBase() = default;
98 /// Returns section content.
99 virtual StringRef getContents() = 0;
100 /// Returns section kind.
101 DebugSectionKind getKind() { return SectionKind; }
102 /// Returns section name.
103 const StringLiteral &getName() const { return getSectionName(SectionKind); }
104 /// Returns endianess used by section.
105 llvm::endianness getEndianess() const { return Endianess; }
106 /// Returns FormParams used by section.
107 dwarf::FormParams getFormParams() const { return Format; }
108
109protected:
110 /// The section kind.
111 DebugSectionKind SectionKind = DebugSectionKind::NumberOfEnumEntries;
112 /// Output format.
113 dwarf::FormParams Format = {.Version: 4, .AddrSize: 4, .Format: dwarf::DWARF32};
114 llvm::endianness Endianess = llvm::endianness::little;
115};
116
117using SectionHandlerTy =
118 std::function<void(std::shared_ptr<SectionDescriptorBase> Section)>;
119
120class DWARFLinker : public DWARFLinkerBase {
121public:
122 virtual ~DWARFLinker() = default;
123
124 /// Creates dwarf linker instance.
125 static std::unique_ptr<DWARFLinker>
126 createLinker(MessageHandlerTy ErrorHandler, MessageHandlerTy WarningHandler);
127
128 /// Set output DWARF handler. Result of linking DWARF is set of sections
129 /// containing final debug info. DWARFLinkerBase::link() pass generated
130 /// sections using specified \p SectionHandler.
131 virtual void setOutputDWARFHandler(const Triple &TargetTriple,
132 SectionHandlerTy SectionHandler) = 0;
133};
134
135} // end of namespace parallel
136} // end of namespace dwarf_linker
137} // end of namespace llvm
138
139#endif // LLVM_DWARFLINKER_PARALLEL_DWARFLINKER_H
140

source code of llvm/include/llvm/DWARFLinker/Parallel/DWARFLinker.h