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 | UnitTag = OutUnitDIE->getTag(); |
83 | } |
84 | } |
85 | |
86 | /// Returns unit DWARF tag. |
87 | dwarf::Tag getTag() const { return UnitTag; } |
88 | |
89 | /// \defgroup Methods used to emit unit's debug info: |
90 | /// |
91 | /// @{ |
92 | /// Emit unit's abbreviations. |
93 | Error emitAbbreviations(); |
94 | |
95 | /// Emit .debug_info section for unit DIEs. |
96 | Error emitDebugInfo(const Triple &TargetTriple); |
97 | |
98 | /// Emit .debug_line section. |
99 | Error emitDebugLine(const Triple &TargetTriple, |
100 | const DWARFDebugLine::LineTable &OutLineTable); |
101 | |
102 | /// Emit the .debug_str_offsets section for current unit. |
103 | Error emitDebugStringOffsetSection(); |
104 | /// @} |
105 | |
106 | /// \defgroup Methods used for reporting warnings and errors: |
107 | /// |
108 | /// @{ |
109 | void warn(const Twine &Warning) { GlobalData.warn(Warning, Context: getUnitName()); } |
110 | |
111 | void error(const Twine &Err) { GlobalData.warn(Warning: Err, Context: getUnitName()); } |
112 | /// @} |
113 | |
114 | /// \defgroup Methods and data members used for building accelerator tables: |
115 | /// |
116 | /// @{ |
117 | |
118 | enum class AccelType : uint8_t { None, Name, Namespace, ObjC, Type }; |
119 | |
120 | /// This structure keeps fields which would be used for creating accelerator |
121 | /// table. |
122 | struct AccelInfo { |
123 | AccelInfo() { |
124 | AvoidForPubSections = false; |
125 | ObjcClassImplementation = false; |
126 | } |
127 | |
128 | /// Name of the entry. |
129 | StringEntry *String = nullptr; |
130 | |
131 | /// Output offset of the DIE this entry describes. |
132 | uint64_t OutOffset; |
133 | |
134 | /// Hash of the fully qualified name. |
135 | uint32_t QualifiedNameHash = 0; |
136 | |
137 | /// Tag of the DIE this entry describes. |
138 | dwarf::Tag Tag = dwarf::DW_TAG_null; |
139 | |
140 | /// Type of this accelerator record. |
141 | AccelType Type = AccelType::None; |
142 | |
143 | /// Avoid emitting this entry for pub sections. |
144 | bool AvoidForPubSections : 1; |
145 | |
146 | /// Is this an ObjC class implementation? |
147 | bool ObjcClassImplementation : 1; |
148 | }; |
149 | |
150 | /// Emit .debug_pubnames and .debug_pubtypes for \p Unit. |
151 | void emitPubAccelerators(); |
152 | |
153 | /// Enumerates accelerator data. |
154 | virtual void |
155 | forEachAcceleratorRecord(function_ref<void(AccelInfo &)> Handler) = 0; |
156 | |
157 | /// @} |
158 | |
159 | /// Returns index(inside .debug_str_offsets) of specified string. |
160 | virtual uint64_t getDebugStrIndex(const StringEntry *String) { |
161 | return DebugStringIndexMap.getValueIndex(Value: String); |
162 | } |
163 | |
164 | protected: |
165 | /// Emit single abbreviation entry. |
166 | void emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev, |
167 | SectionDescriptor &AbbrevSection); |
168 | |
169 | /// Emit single pubnames/pubtypes accelerator entry. |
170 | std::optional<uint64_t> |
171 | emitPubAcceleratorEntry(SectionDescriptor &OutSection, const AccelInfo &Info, |
172 | std::optional<uint64_t> LengthOffset); |
173 | |
174 | /// Unique ID for the unit. |
175 | unsigned ID = 0; |
176 | |
177 | /// The name of this unit. |
178 | std::string UnitName; |
179 | |
180 | /// The DW_AT_LLVM_sysroot of this unit. |
181 | std::string SysRoot; |
182 | |
183 | /// If this is a Clang module, this holds the module's name. |
184 | std::string ClangModuleName; |
185 | |
186 | uint64_t UnitSize = 0; |
187 | |
188 | /// DWARF unit tag. |
189 | dwarf::Tag UnitTag = dwarf::DW_TAG_null; |
190 | |
191 | /// true if current unit references_to/is_referenced by other unit. |
192 | std::atomic<bool> IsInterconnectedCU = {false}; |
193 | |
194 | /// FoldingSet that uniques the abbreviations. |
195 | FoldingSet<DIEAbbrev> AbbreviationsSet; |
196 | |
197 | /// Storage for the unique Abbreviations. |
198 | std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations; |
199 | |
200 | /// Output unit DIE. |
201 | DIE *OutUnitDIE = nullptr; |
202 | |
203 | /// Cache for file names for this unit. |
204 | using FileNamesCache = |
205 | DenseMap<uint64_t, std::pair<std::string, std::string>>; |
206 | FileNamesCache FileNames; |
207 | |
208 | /// Maps a string into the index inside .debug_str_offsets section. |
209 | IndexedValuesMap<const StringEntry *> DebugStringIndexMap; |
210 | }; |
211 | |
212 | inline bool isODRLanguage(uint16_t Language) { |
213 | switch (Language) { |
214 | case dwarf::DW_LANG_C_plus_plus: |
215 | case dwarf::DW_LANG_C_plus_plus_03: |
216 | case dwarf::DW_LANG_C_plus_plus_11: |
217 | case dwarf::DW_LANG_C_plus_plus_14: |
218 | case dwarf::DW_LANG_ObjC_plus_plus: |
219 | return true; |
220 | default: |
221 | return false; |
222 | }; |
223 | |
224 | return false; |
225 | } |
226 | |
227 | } // end of namespace parallel |
228 | } // end of namespace dwarf_linker |
229 | } // end of namespace llvm |
230 | |
231 | #endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERUNIT_H |
232 | |