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