1 | //===- BTFDebug.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 | /// \file |
10 | /// This file contains support for writing BTF debug info. |
11 | /// |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_LIB_TARGET_BPF_BTFDEBUG_H |
15 | #define LLVM_LIB_TARGET_BPF_BTFDEBUG_H |
16 | |
17 | #include "llvm/ADT/StringMap.h" |
18 | #include "llvm/CodeGen/DebugHandlerBase.h" |
19 | #include "llvm/DebugInfo/BTF/BTF.h" |
20 | #include <cstdint> |
21 | #include <map> |
22 | #include <set> |
23 | #include <unordered_map> |
24 | |
25 | namespace llvm { |
26 | |
27 | class AsmPrinter; |
28 | class BTFDebug; |
29 | class DIType; |
30 | class GlobalVariable; |
31 | class MachineFunction; |
32 | class MachineInstr; |
33 | class MachineOperand; |
34 | class MCInst; |
35 | class MCStreamer; |
36 | class MCSymbol; |
37 | |
38 | /// The base class for BTF type generation. |
39 | class BTFTypeBase { |
40 | protected: |
41 | uint8_t Kind; |
42 | bool IsCompleted; |
43 | uint32_t Id; |
44 | struct BTF::CommonType BTFType; |
45 | |
46 | public: |
47 | BTFTypeBase() : IsCompleted(false) {} |
48 | virtual ~BTFTypeBase() = default; |
49 | void setId(uint32_t Id) { this->Id = Id; } |
50 | uint32_t getId() { return Id; } |
51 | uint32_t roundupToBytes(uint32_t NumBits) { return (NumBits + 7) >> 3; } |
52 | /// Get the size of this BTF type entry. |
53 | virtual uint32_t getSize() { return BTF::CommonTypeSize; } |
54 | /// Complete BTF type generation after all related DebugInfo types |
55 | /// have been visited so their BTF type id's are available |
56 | /// for cross referece. |
57 | virtual void completeType(BTFDebug &BDebug) {} |
58 | /// Emit types for this BTF type entry. |
59 | virtual void emitType(MCStreamer &OS); |
60 | }; |
61 | |
62 | /// Handle several derived types include pointer, const, |
63 | /// volatile, typedef and restrict. |
64 | class BTFTypeDerived : public BTFTypeBase { |
65 | const DIDerivedType *DTy; |
66 | bool NeedsFixup; |
67 | StringRef Name; |
68 | |
69 | public: |
70 | BTFTypeDerived(const DIDerivedType *Ty, unsigned Tag, bool NeedsFixup); |
71 | BTFTypeDerived(unsigned NextTypeId, unsigned Tag, StringRef Name); |
72 | void completeType(BTFDebug &BDebug) override; |
73 | void emitType(MCStreamer &OS) override; |
74 | void setPointeeType(uint32_t PointeeType); |
75 | }; |
76 | |
77 | /// Handle struct or union forward declaration. |
78 | class BTFTypeFwd : public BTFTypeBase { |
79 | StringRef Name; |
80 | |
81 | public: |
82 | BTFTypeFwd(StringRef Name, bool IsUnion); |
83 | void completeType(BTFDebug &BDebug) override; |
84 | void emitType(MCStreamer &OS) override; |
85 | }; |
86 | |
87 | /// Handle int type. |
88 | class BTFTypeInt : public BTFTypeBase { |
89 | StringRef Name; |
90 | uint32_t IntVal; ///< Encoding, offset, bits |
91 | |
92 | public: |
93 | BTFTypeInt(uint32_t Encoding, uint32_t SizeInBits, uint32_t OffsetInBits, |
94 | StringRef TypeName); |
95 | uint32_t getSize() override { return BTFTypeBase::getSize() + sizeof(uint32_t); } |
96 | void completeType(BTFDebug &BDebug) override; |
97 | void emitType(MCStreamer &OS) override; |
98 | }; |
99 | |
100 | /// Handle enumerate type. |
101 | class BTFTypeEnum : public BTFTypeBase { |
102 | const DICompositeType *ETy; |
103 | std::vector<struct BTF::BTFEnum> EnumValues; |
104 | |
105 | public: |
106 | BTFTypeEnum(const DICompositeType *ETy, uint32_t NumValues, bool IsSigned); |
107 | uint32_t getSize() override { |
108 | return BTFTypeBase::getSize() + EnumValues.size() * BTF::BTFEnumSize; |
109 | } |
110 | void completeType(BTFDebug &BDebug) override; |
111 | void emitType(MCStreamer &OS) override; |
112 | }; |
113 | |
114 | /// Handle array type. |
115 | class BTFTypeArray : public BTFTypeBase { |
116 | struct BTF::BTFArray ArrayInfo; |
117 | |
118 | public: |
119 | BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems); |
120 | uint32_t getSize() override { return BTFTypeBase::getSize() + BTF::BTFArraySize; } |
121 | void completeType(BTFDebug &BDebug) override; |
122 | void emitType(MCStreamer &OS) override; |
123 | }; |
124 | |
125 | /// Handle struct/union type. |
126 | class BTFTypeStruct : public BTFTypeBase { |
127 | const DICompositeType *STy; |
128 | bool HasBitField; |
129 | std::vector<struct BTF::BTFMember> Members; |
130 | |
131 | public: |
132 | BTFTypeStruct(const DICompositeType *STy, bool IsStruct, bool HasBitField, |
133 | uint32_t NumMembers); |
134 | uint32_t getSize() override { |
135 | return BTFTypeBase::getSize() + Members.size() * BTF::BTFMemberSize; |
136 | } |
137 | void completeType(BTFDebug &BDebug) override; |
138 | void emitType(MCStreamer &OS) override; |
139 | std::string getName(); |
140 | }; |
141 | |
142 | /// Handle function pointer. |
143 | class BTFTypeFuncProto : public BTFTypeBase { |
144 | const DISubroutineType *STy; |
145 | std::unordered_map<uint32_t, StringRef> FuncArgNames; |
146 | std::vector<struct BTF::BTFParam> Parameters; |
147 | |
148 | public: |
149 | BTFTypeFuncProto(const DISubroutineType *STy, uint32_t NumParams, |
150 | const std::unordered_map<uint32_t, StringRef> &FuncArgNames); |
151 | uint32_t getSize() override { |
152 | return BTFTypeBase::getSize() + Parameters.size() * BTF::BTFParamSize; |
153 | } |
154 | void completeType(BTFDebug &BDebug) override; |
155 | void emitType(MCStreamer &OS) override; |
156 | }; |
157 | |
158 | /// Handle subprogram |
159 | class BTFTypeFunc : public BTFTypeBase { |
160 | StringRef Name; |
161 | |
162 | public: |
163 | BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId, uint32_t Scope); |
164 | uint32_t getSize() override { return BTFTypeBase::getSize(); } |
165 | void completeType(BTFDebug &BDebug) override; |
166 | void emitType(MCStreamer &OS) override; |
167 | }; |
168 | |
169 | /// Handle variable instances |
170 | class BTFKindVar : public BTFTypeBase { |
171 | StringRef Name; |
172 | uint32_t Info; |
173 | |
174 | public: |
175 | BTFKindVar(StringRef VarName, uint32_t TypeId, uint32_t VarInfo); |
176 | uint32_t getSize() override { return BTFTypeBase::getSize() + 4; } |
177 | void completeType(BTFDebug &BDebug) override; |
178 | void emitType(MCStreamer &OS) override; |
179 | }; |
180 | |
181 | /// Handle data sections |
182 | class BTFKindDataSec : public BTFTypeBase { |
183 | AsmPrinter *Asm; |
184 | std::string Name; |
185 | std::vector<std::tuple<uint32_t, const MCSymbol *, uint32_t>> Vars; |
186 | |
187 | public: |
188 | BTFKindDataSec(AsmPrinter *AsmPrt, std::string SecName); |
189 | uint32_t getSize() override { |
190 | return BTFTypeBase::getSize() + BTF::BTFDataSecVarSize * Vars.size(); |
191 | } |
192 | void addDataSecEntry(uint32_t Id, const MCSymbol *Sym, uint32_t Size) { |
193 | Vars.push_back(x: std::make_tuple(args&: Id, args&: Sym, args&: Size)); |
194 | } |
195 | std::string getName() { return Name; } |
196 | void completeType(BTFDebug &BDebug) override; |
197 | void emitType(MCStreamer &OS) override; |
198 | }; |
199 | |
200 | /// Handle binary floating point type. |
201 | class BTFTypeFloat : public BTFTypeBase { |
202 | StringRef Name; |
203 | |
204 | public: |
205 | BTFTypeFloat(uint32_t SizeInBits, StringRef TypeName); |
206 | void completeType(BTFDebug &BDebug) override; |
207 | }; |
208 | |
209 | /// Handle decl tags. |
210 | class BTFTypeDeclTag : public BTFTypeBase { |
211 | uint32_t Info; |
212 | StringRef Tag; |
213 | |
214 | public: |
215 | BTFTypeDeclTag(uint32_t BaseTypeId, int ComponentId, StringRef Tag); |
216 | uint32_t getSize() override { return BTFTypeBase::getSize() + 4; } |
217 | void completeType(BTFDebug &BDebug) override; |
218 | void emitType(MCStreamer &OS) override; |
219 | }; |
220 | |
221 | /// Handle 64-bit enumerate type. |
222 | class BTFTypeEnum64 : public BTFTypeBase { |
223 | const DICompositeType *ETy; |
224 | std::vector<struct BTF::BTFEnum64> EnumValues; |
225 | |
226 | public: |
227 | BTFTypeEnum64(const DICompositeType *ETy, uint32_t NumValues, bool IsSigned); |
228 | uint32_t getSize() override { |
229 | return BTFTypeBase::getSize() + EnumValues.size() * BTF::BTFEnum64Size; |
230 | } |
231 | void completeType(BTFDebug &BDebug) override; |
232 | void emitType(MCStreamer &OS) override; |
233 | }; |
234 | |
235 | class BTFTypeTypeTag : public BTFTypeBase { |
236 | const DIDerivedType *DTy; |
237 | StringRef Tag; |
238 | |
239 | public: |
240 | BTFTypeTypeTag(uint32_t NextTypeId, StringRef Tag); |
241 | BTFTypeTypeTag(const DIDerivedType *DTy, StringRef Tag); |
242 | void completeType(BTFDebug &BDebug) override; |
243 | }; |
244 | |
245 | /// String table. |
246 | class BTFStringTable { |
247 | /// String table size in bytes. |
248 | uint32_t Size; |
249 | /// A mapping from string table offset to the index |
250 | /// of the Table. It is used to avoid putting |
251 | /// duplicated strings in the table. |
252 | std::map<uint32_t, uint32_t> OffsetToIdMap; |
253 | /// A vector of strings to represent the string table. |
254 | std::vector<std::string> Table; |
255 | |
256 | public: |
257 | BTFStringTable() : Size(0) {} |
258 | uint32_t getSize() { return Size; } |
259 | std::vector<std::string> &getTable() { return Table; } |
260 | /// Add a string to the string table and returns its offset |
261 | /// in the table. |
262 | uint32_t addString(StringRef S); |
263 | }; |
264 | |
265 | /// Represent one func and its type id. |
266 | struct BTFFuncInfo { |
267 | const MCSymbol *Label; ///< Func MCSymbol |
268 | uint32_t TypeId; ///< Type id referring to .BTF type section |
269 | }; |
270 | |
271 | /// Represent one line info. |
272 | struct BTFLineInfo { |
273 | MCSymbol *Label; ///< MCSymbol identifying insn for the lineinfo |
274 | uint32_t FileNameOff; ///< file name offset in the .BTF string table |
275 | uint32_t LineOff; ///< line offset in the .BTF string table |
276 | uint32_t LineNum; ///< the line number |
277 | uint32_t ColumnNum; ///< the column number |
278 | }; |
279 | |
280 | /// Represent one field relocation. |
281 | struct BTFFieldReloc { |
282 | const MCSymbol *Label; ///< MCSymbol identifying insn for the reloc |
283 | uint32_t TypeID; ///< Type ID |
284 | uint32_t OffsetNameOff; ///< The string to traverse types |
285 | uint32_t RelocKind; ///< What to patch the instruction |
286 | }; |
287 | |
288 | /// Collect and emit BTF information. |
289 | class BTFDebug : public DebugHandlerBase { |
290 | MCStreamer &OS; |
291 | bool SkipInstruction; |
292 | bool LineInfoGenerated; |
293 | uint32_t SecNameOff; |
294 | uint32_t ArrayIndexTypeId; |
295 | bool MapDefNotCollected; |
296 | BTFStringTable StringTable; |
297 | std::vector<std::unique_ptr<BTFTypeBase>> TypeEntries; |
298 | std::unordered_map<const DIType *, uint32_t> DIToIdMap; |
299 | std::map<uint32_t, std::vector<BTFFuncInfo>> FuncInfoTable; |
300 | std::map<uint32_t, std::vector<BTFLineInfo>> LineInfoTable; |
301 | std::map<uint32_t, std::vector<BTFFieldReloc>> FieldRelocTable; |
302 | StringMap<std::vector<std::string>> FileContent; |
303 | std::map<std::string, std::unique_ptr<BTFKindDataSec>> DataSecEntries; |
304 | std::vector<BTFTypeStruct *> StructTypes; |
305 | std::map<const GlobalVariable *, std::pair<int64_t, uint32_t>> PatchImms; |
306 | std::map<const DICompositeType *, |
307 | std::vector<std::pair<const DIDerivedType *, BTFTypeDerived *>>> |
308 | FixupDerivedTypes; |
309 | std::set<const Function *>ProtoFunctions; |
310 | |
311 | /// Add types to TypeEntries. |
312 | /// @{ |
313 | /// Add types to TypeEntries and DIToIdMap. |
314 | uint32_t addType(std::unique_ptr<BTFTypeBase> TypeEntry, const DIType *Ty); |
315 | /// Add types to TypeEntries only and return type id. |
316 | uint32_t addType(std::unique_ptr<BTFTypeBase> TypeEntry); |
317 | /// @} |
318 | |
319 | /// IR type visiting functions. |
320 | /// @{ |
321 | void visitTypeEntry(const DIType *Ty); |
322 | void visitTypeEntry(const DIType *Ty, uint32_t &TypeId, bool CheckPointer, |
323 | bool SeenPointer); |
324 | void visitBasicType(const DIBasicType *BTy, uint32_t &TypeId); |
325 | void visitSubroutineType( |
326 | const DISubroutineType *STy, bool ForSubprog, |
327 | const std::unordered_map<uint32_t, StringRef> &FuncArgNames, |
328 | uint32_t &TypeId); |
329 | void visitFwdDeclType(const DICompositeType *CTy, bool IsUnion, |
330 | uint32_t &TypeId); |
331 | void visitCompositeType(const DICompositeType *CTy, uint32_t &TypeId); |
332 | void visitStructType(const DICompositeType *STy, bool IsStruct, |
333 | uint32_t &TypeId); |
334 | void visitArrayType(const DICompositeType *ATy, uint32_t &TypeId); |
335 | void visitEnumType(const DICompositeType *ETy, uint32_t &TypeId); |
336 | void visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId, |
337 | bool CheckPointer, bool SeenPointer); |
338 | void visitMapDefType(const DIType *Ty, uint32_t &TypeId); |
339 | /// @} |
340 | |
341 | /// Check whether the type is a forward declaration candidate or not. |
342 | bool IsForwardDeclCandidate(const DIType *Base); |
343 | |
344 | /// Get the file content for the subprogram. Certain lines of the file |
345 | /// later may be put into string table and referenced by line info. |
346 | std::string populateFileContent(const DIFile *File); |
347 | |
348 | /// Construct a line info. |
349 | void constructLineInfo(MCSymbol *Label, const DIFile *File, uint32_t Line, |
350 | uint32_t Column); |
351 | |
352 | /// Generate types and variables for globals. |
353 | void processGlobals(bool ProcessingMapDef); |
354 | |
355 | /// Process global variable initializer in pursuit for function |
356 | /// pointers. |
357 | void processGlobalInitializer(const Constant *C); |
358 | |
359 | /// Generate types for function prototypes. |
360 | void processFuncPrototypes(const Function *); |
361 | |
362 | /// Generate types for decl annotations. |
363 | void processDeclAnnotations(DINodeArray Annotations, uint32_t BaseTypeId, |
364 | int ComponentId); |
365 | |
366 | /// Generate types for DISubprogram and it's arguments. |
367 | uint32_t processDISubprogram(const DISubprogram *SP, uint32_t ProtoTypeId, |
368 | uint8_t Scope); |
369 | |
370 | /// Generate BTF type_tag's. If BaseTypeId is nonnegative, the last |
371 | /// BTF type_tag in the chain points to BaseTypeId. Otherwise, it points to |
372 | /// the base type of DTy. Return the type id of the first BTF type_tag |
373 | /// in the chain. If no type_tag's are generated, a negative value |
374 | /// is returned. |
375 | int genBTFTypeTags(const DIDerivedType *DTy, int BaseTypeId); |
376 | |
377 | /// Generate one field relocation record. |
378 | void generatePatchImmReloc(const MCSymbol *ORSym, uint32_t RootId, |
379 | const GlobalVariable *, bool IsAma); |
380 | |
381 | /// Populating unprocessed type on demand. |
382 | unsigned populateType(const DIType *Ty); |
383 | |
384 | /// Process global variables referenced by relocation instructions |
385 | /// and extern function references. |
386 | void processGlobalValue(const MachineOperand &MO); |
387 | |
388 | /// Emit common header of .BTF and .BTF.ext sections. |
389 | void (); |
390 | |
391 | /// Emit the .BTF section. |
392 | void emitBTFSection(); |
393 | |
394 | /// Emit the .BTF.ext section. |
395 | void emitBTFExtSection(); |
396 | |
397 | protected: |
398 | /// Gather pre-function debug information. |
399 | void beginFunctionImpl(const MachineFunction *MF) override; |
400 | |
401 | /// Post process after all instructions in this function are processed. |
402 | void endFunctionImpl(const MachineFunction *MF) override; |
403 | |
404 | public: |
405 | BTFDebug(AsmPrinter *AP); |
406 | |
407 | /// |
408 | bool InstLower(const MachineInstr *MI, MCInst &OutMI); |
409 | |
410 | /// Get the special array index type id. |
411 | uint32_t getArrayIndexTypeId() { |
412 | assert(ArrayIndexTypeId); |
413 | return ArrayIndexTypeId; |
414 | } |
415 | |
416 | /// Add string to the string table. |
417 | size_t addString(StringRef S) { return StringTable.addString(S); } |
418 | |
419 | /// Get the type id for a particular DIType. |
420 | uint32_t getTypeId(const DIType *Ty) { |
421 | assert(Ty && "Invalid null Type" ); |
422 | assert(DIToIdMap.find(Ty) != DIToIdMap.end() && |
423 | "DIType not added in the BDIToIdMap" ); |
424 | return DIToIdMap[Ty]; |
425 | } |
426 | |
427 | /// Process beginning of an instruction. |
428 | void beginInstruction(const MachineInstr *MI) override; |
429 | |
430 | /// Complete all the types and emit the BTF sections. |
431 | void endModule() override; |
432 | }; |
433 | |
434 | } // end namespace llvm |
435 | |
436 | #endif |
437 | |