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:
~DwarfUnit()31 virtual ~DwarfUnit() {}
DwarfUnit(LinkingGlobalData & GlobalData,unsigned ID,StringRef ClangModuleName)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.
getUniqueID()38 unsigned getUniqueID() const { return ID; }
39
40 /// Returns size of this(newly generated) compile unit.
getUnitSize()41 uint64_t getUnitSize() const { return UnitSize; }
42
43 /// Returns this unit name.
getUnitName()44 StringRef getUnitName() const { return UnitName; }
45
46 /// Return the DW_AT_LLVM_sysroot of the compile unit or an empty StringRef.
getSysRoot()47 StringRef getSysRoot() { return SysRoot; }
48
49 /// Return true if this compile unit is from Clang module.
isClangModule()50 bool isClangModule() const { return !ClangModuleName.empty(); }
51
52 /// Return Clang module name;
getClangModuleName()53 const std::string &getClangModuleName() const { return ClangModuleName; }
54
55 /// Return global data.
getGlobalData()56 LinkingGlobalData &getGlobalData() { return GlobalData; }
57
58 /// Returns true if unit is inter-connected(it references/referenced by other
59 /// unit).
isInterconnectedCU()60 bool isInterconnectedCU() const { return IsInterconnectedCU; }
61
62 /// Mark this unit as inter-connected(it references/referenced by other unit).
setInterconnectedCU()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.
getAbbreviations()69 const std::vector<std::unique_ptr<DIEAbbrev>> &getAbbreviations() const {
70 return Abbreviations;
71 }
72
73 /// Returns output unit DIE.
getOutUnitDIE()74 DIE *getOutUnitDIE() { return OutUnitDIE; }
75
76 /// Set output unit DIE.
setOutUnitDIE(DIE * UnitDie)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.
getTag()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 /// @{
warn(const Twine & Warning)109 void warn(const Twine &Warning) { GlobalData.warn(Warning, getUnitName()); }
110
error(const Twine & Err)111 void error(const Twine &Err) { GlobalData.warn(Err, 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 {
AccelInfoAccelInfo123 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.
getDebugStrIndex(const StringEntry * String)160 virtual uint64_t getDebugStrIndex(const StringEntry *String) {
161 return DebugStringIndexMap.getValueIndex(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
isODRLanguage(uint16_t Language)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