1 | //===- DWARFLinkerUnit.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_LIB_DWARFLINKER_PARALLEL_DWARFLINKERUNIT_H |
10 | #define LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERUNIT_H |
11 | |
12 | #include "DWARFLinkerGlobalData.h" |
13 | #include "OutputSections.h" |
14 | #include "llvm/CodeGen/DIE.h" |
15 | #include "llvm/DWARFLinker/IndexedValuesMap.h" |
16 | #include "llvm/DWARFLinker/Parallel/DWARFLinker.h" |
17 | #include "llvm/DWARFLinker/StringPool.h" |
18 | #include "llvm/DebugInfo/DWARF/DWARFUnit.h" |
19 | #include "llvm/Support/LEB128.h" |
20 | |
21 | namespace llvm { |
22 | namespace dwarf_linker { |
23 | namespace parallel { |
24 | |
25 | class DwarfUnit; |
26 | using MacroOffset2UnitMapTy = DenseMap<uint64_t, DwarfUnit *>; |
27 | |
28 | /// Base class for all Dwarf units(Compile unit/Type table unit). |
29 | class DwarfUnit : public OutputSections { |
30 | public: |
31 | virtual ~DwarfUnit() {} |
32 | DwarfUnit(LinkingGlobalData &GlobalData, unsigned ID, |
33 | StringRef ClangModuleName) |
34 | : OutputSections(GlobalData), ID(ID), ClangModuleName(ClangModuleName), |
35 | OutUnitDIE(nullptr) {} |
36 | |
37 | /// Unique id of the unit. |
38 | unsigned getUniqueID() const { return ID; } |
39 | |
40 | /// Returns size of this(newly generated) compile unit. |
41 | uint64_t getUnitSize() const { return UnitSize; } |
42 | |
43 | /// Returns this unit name. |
44 | StringRef getUnitName() const { return UnitName; } |
45 | |
46 | /// Return the DW_AT_LLVM_sysroot of the compile unit or an empty StringRef. |
47 | StringRef getSysRoot() { return SysRoot; } |
48 | |
49 | /// Return true if this compile unit is from Clang module. |
50 | bool isClangModule() const { return !ClangModuleName.empty(); } |
51 | |
52 | /// Return Clang module name; |
53 | const std::string &getClangModuleName() const { return ClangModuleName; } |
54 | |
55 | /// Return global data. |
56 | LinkingGlobalData &getGlobalData() { return GlobalData; } |
57 | |
58 | /// Returns true if unit is inter-connected(it references/referenced by other |
59 | /// unit). |
60 | bool isInterconnectedCU() const { return IsInterconnectedCU; } |
61 | |
62 | /// Mark this unit as inter-connected(it references/referenced by other unit). |
63 | void setInterconnectedCU() { IsInterconnectedCU = true; } |
64 | |
65 | /// Adds \p Abbrev into unit`s abbreviation table. |
66 | void assignAbbrev(DIEAbbrev &Abbrev); |
67 | |
68 | /// Returns abbreviations for this compile unit. |
69 | const std::vector<std::unique_ptr<DIEAbbrev>> &getAbbreviations() const { |
70 | return Abbreviations; |
71 | } |
72 | |
73 | /// Returns output unit DIE. |
74 | DIE *getOutUnitDIE() { return OutUnitDIE; } |
75 | |
76 | /// Set output unit DIE. |
77 | void setOutUnitDIE(DIE *UnitDie) { |
78 | OutUnitDIE = UnitDie; |
79 | |
80 | if (OutUnitDIE != nullptr) |
81 | UnitSize = getDebugInfoHeaderSize() + OutUnitDIE->getSize(); |
82 | } |
83 | |
84 | /// \defgroup Methods used to emit unit's debug info: |
85 | /// |
86 | /// @{ |
87 | /// Emit unit's abbreviations. |
88 | Error emitAbbreviations(); |
89 | |
90 | /// Emit .debug_info section for unit DIEs. |
91 | Error emitDebugInfo(const Triple &TargetTriple); |
92 | |
93 | /// Emit .debug_line section. |
94 | Error emitDebugLine(const Triple &TargetTriple, |
95 | const DWARFDebugLine::LineTable &OutLineTable); |
96 | |
97 | /// Emit the .debug_str_offsets section for current unit. |
98 | Error emitDebugStringOffsetSection(); |
99 | /// @} |
100 | |
101 | /// \defgroup Methods used for reporting warnings and errors: |
102 | /// |
103 | /// @{ |
104 | void warn(const Twine &Warning) { GlobalData.warn(Warning, Context: getUnitName()); } |
105 | |
106 | void error(const Twine &Err) { GlobalData.warn(Warning: Err, Context: getUnitName()); } |
107 | /// @} |
108 | |
109 | /// \defgroup Methods and data members used for building accelerator tables: |
110 | /// |
111 | /// @{ |
112 | |
113 | enum class AccelType : uint8_t { None, Name, Namespace, ObjC, Type }; |
114 | |
115 | /// This structure keeps fields which would be used for creating accelerator |
116 | /// table. |
117 | struct AccelInfo { |
118 | AccelInfo() { |
119 | AvoidForPubSections = false; |
120 | ObjcClassImplementation = false; |
121 | } |
122 | |
123 | /// Name of the entry. |
124 | StringEntry *String = nullptr; |
125 | |
126 | /// Output offset of the DIE this entry describes. |
127 | uint64_t OutOffset; |
128 | |
129 | /// Hash of the fully qualified name. |
130 | uint32_t QualifiedNameHash = 0; |
131 | |
132 | /// Tag of the DIE this entry describes. |
133 | dwarf::Tag Tag = dwarf::DW_TAG_null; |
134 | |
135 | /// Type of this accelerator record. |
136 | AccelType Type = AccelType::None; |
137 | |
138 | /// Avoid emitting this entry for pub sections. |
139 | bool AvoidForPubSections : 1; |
140 | |
141 | /// Is this an ObjC class implementation? |
142 | bool ObjcClassImplementation : 1; |
143 | }; |
144 | |
145 | /// Emit .debug_pubnames and .debug_pubtypes for \p Unit. |
146 | void emitPubAccelerators(); |
147 | |
148 | /// Enumerates accelerator data. |
149 | virtual void |
150 | forEachAcceleratorRecord(function_ref<void(AccelInfo &)> Handler) = 0; |
151 | |
152 | /// @} |
153 | |
154 | /// Returns index(inside .debug_str_offsets) of specified string. |
155 | virtual uint64_t getDebugStrIndex(const StringEntry *String) { |
156 | return DebugStringIndexMap.getValueIndex(Value: String); |
157 | } |
158 | |
159 | protected: |
160 | /// Emit single abbreviation entry. |
161 | void emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev, |
162 | SectionDescriptor &AbbrevSection); |
163 | |
164 | /// Emit single pubnames/pubtypes accelerator entry. |
165 | std::optional<uint64_t> |
166 | emitPubAcceleratorEntry(SectionDescriptor &OutSection, const AccelInfo &Info, |
167 | std::optional<uint64_t> LengthOffset); |
168 | |
169 | /// Unique ID for the unit. |
170 | unsigned ID = 0; |
171 | |
172 | /// The name of this unit. |
173 | std::string UnitName; |
174 | |
175 | /// The DW_AT_LLVM_sysroot of this unit. |
176 | std::string SysRoot; |
177 | |
178 | /// If this is a Clang module, this holds the module's name. |
179 | std::string ClangModuleName; |
180 | |
181 | uint64_t UnitSize = 0; |
182 | |
183 | /// true if current unit references_to/is_referenced by other unit. |
184 | std::atomic<bool> IsInterconnectedCU = {false}; |
185 | |
186 | /// FoldingSet that uniques the abbreviations. |
187 | FoldingSet<DIEAbbrev> AbbreviationsSet; |
188 | |
189 | /// Storage for the unique Abbreviations. |
190 | std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations; |
191 | |
192 | /// Output unit DIE. |
193 | DIE *OutUnitDIE = nullptr; |
194 | |
195 | /// Cache for file names for this unit. |
196 | using FileNamesCache = |
197 | DenseMap<uint64_t, std::pair<std::string, std::string>>; |
198 | FileNamesCache FileNames; |
199 | |
200 | /// Maps a string into the index inside .debug_str_offsets section. |
201 | IndexedValuesMap<const StringEntry *> DebugStringIndexMap; |
202 | }; |
203 | |
204 | inline bool isODRLanguage(uint16_t Language) { |
205 | switch (Language) { |
206 | case dwarf::DW_LANG_C_plus_plus: |
207 | case dwarf::DW_LANG_C_plus_plus_03: |
208 | case dwarf::DW_LANG_C_plus_plus_11: |
209 | case dwarf::DW_LANG_C_plus_plus_14: |
210 | case dwarf::DW_LANG_ObjC_plus_plus: |
211 | return true; |
212 | default: |
213 | return false; |
214 | }; |
215 | |
216 | return false; |
217 | } |
218 | |
219 | } // end of namespace parallel |
220 | } // end of namespace dwarf_linker |
221 | } // end of namespace llvm |
222 | |
223 | #endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERUNIT_H |
224 | |