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 <cstdint>
20 #include <map>
21 #include <set>
22 #include <unordered_map>
23 #include "BTF.h"
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 
68 public:
69   BTFTypeDerived(const DIDerivedType *Ty, unsigned Tag, bool NeedsFixup);
70   void completeType(BTFDebug &BDebug) override;
71   void emitType(MCStreamer &OS) override;
72   void setPointeeType(uint32_t PointeeType);
73 };
74 
75 /// Handle struct or union forward declaration.
76 class BTFTypeFwd : public BTFTypeBase {
77   StringRef Name;
78 
79 public:
80   BTFTypeFwd(StringRef Name, bool IsUnion);
81   void completeType(BTFDebug &BDebug) override;
82   void emitType(MCStreamer &OS) override;
83 };
84 
85 /// Handle int type.
86 class BTFTypeInt : public BTFTypeBase {
87   StringRef Name;
88   uint32_t IntVal; ///< Encoding, offset, bits
89 
90 public:
91   BTFTypeInt(uint32_t Encoding, uint32_t SizeInBits, uint32_t OffsetInBits,
92              StringRef TypeName);
93   uint32_t getSize() override { return BTFTypeBase::getSize() + sizeof(uint32_t); }
94   void completeType(BTFDebug &BDebug) override;
95   void emitType(MCStreamer &OS) override;
96 };
97 
98 /// Handle enumerate type.
99 class BTFTypeEnum : public BTFTypeBase {
100   const DICompositeType *ETy;
101   std::vector<struct BTF::BTFEnum> EnumValues;
102 
103 public:
104   BTFTypeEnum(const DICompositeType *ETy, uint32_t NumValues);
105   uint32_t getSize() override {
106     return BTFTypeBase::getSize() + EnumValues.size() * BTF::BTFEnumSize;
107   }
108   void completeType(BTFDebug &BDebug) override;
109   void emitType(MCStreamer &OS) override;
110 };
111 
112 /// Handle array type.
113 class BTFTypeArray : public BTFTypeBase {
114   struct BTF::BTFArray ArrayInfo;
115 
116 public:
117   BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems);
118   uint32_t getSize() override { return BTFTypeBase::getSize() + BTF::BTFArraySize; }
119   void completeType(BTFDebug &BDebug) override;
120   void emitType(MCStreamer &OS) override;
121 };
122 
123 /// Handle struct/union type.
124 class BTFTypeStruct : public BTFTypeBase {
125   const DICompositeType *STy;
126   bool HasBitField;
127   std::vector<struct BTF::BTFMember> Members;
128 
129 public:
130   BTFTypeStruct(const DICompositeType *STy, bool IsStruct, bool HasBitField,
131                 uint32_t NumMembers);
132   uint32_t getSize() override {
133     return BTFTypeBase::getSize() + Members.size() * BTF::BTFMemberSize;
134   }
135   void completeType(BTFDebug &BDebug) override;
136   void emitType(MCStreamer &OS) override;
137   std::string getName();
138 };
139 
140 /// Handle function pointer.
141 class BTFTypeFuncProto : public BTFTypeBase {
142   const DISubroutineType *STy;
143   std::unordered_map<uint32_t, StringRef> FuncArgNames;
144   std::vector<struct BTF::BTFParam> Parameters;
145 
146 public:
147   BTFTypeFuncProto(const DISubroutineType *STy, uint32_t NumParams,
148                    const std::unordered_map<uint32_t, StringRef> &FuncArgNames);
149   uint32_t getSize() override {
150     return BTFTypeBase::getSize() + Parameters.size() * BTF::BTFParamSize;
151   }
152   void completeType(BTFDebug &BDebug) override;
153   void emitType(MCStreamer &OS) override;
154 };
155 
156 /// Handle subprogram
157 class BTFTypeFunc : public BTFTypeBase {
158   StringRef Name;
159 
160 public:
161   BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId, uint32_t Scope);
162   uint32_t getSize() override { return BTFTypeBase::getSize(); }
163   void completeType(BTFDebug &BDebug) override;
164   void emitType(MCStreamer &OS) override;
165 };
166 
167 /// Handle variable instances
168 class BTFKindVar : public BTFTypeBase {
169   StringRef Name;
170   uint32_t Info;
171 
172 public:
173   BTFKindVar(StringRef VarName, uint32_t TypeId, uint32_t VarInfo);
174   uint32_t getSize() override { return BTFTypeBase::getSize() + 4; }
175   void completeType(BTFDebug &BDebug) override;
176   void emitType(MCStreamer &OS) override;
177 };
178 
179 /// Handle data sections
180 class BTFKindDataSec : public BTFTypeBase {
181   AsmPrinter *Asm;
182   std::string Name;
183   std::vector<std::tuple<uint32_t, const MCSymbol *, uint32_t>> Vars;
184 
185 public:
186   BTFKindDataSec(AsmPrinter *AsmPrt, std::string SecName);
187   uint32_t getSize() override {
188     return BTFTypeBase::getSize() + BTF::BTFDataSecVarSize * Vars.size();
189   }
190   void addDataSecEntry(uint32_t Id, const MCSymbol *Sym, uint32_t Size) {
191     Vars.push_back(std::make_tuple(Id, Sym, Size));
192   }
193   std::string getName() { return Name; }
194   void completeType(BTFDebug &BDebug) override;
195   void emitType(MCStreamer &OS) override;
196 };
197 
198 /// Handle binary floating point type.
199 class BTFTypeFloat : public BTFTypeBase {
200   StringRef Name;
201 
202 public:
203   BTFTypeFloat(uint32_t SizeInBits, StringRef TypeName);
204   void completeType(BTFDebug &BDebug) override;
205 };
206 
207 /// Handle tags.
208 class BTFTypeTag : public BTFTypeBase {
209   uint32_t Info;
210   StringRef Tag;
211 
212 public:
213   BTFTypeTag(uint32_t BaseTypeId, int ComponentId, StringRef Tag);
214   uint32_t getSize() override { return BTFTypeBase::getSize() + 4; }
215   void completeType(BTFDebug &BDebug) override;
216   void emitType(MCStreamer &OS) override;
217 };
218 
219 /// String table.
220 class BTFStringTable {
221   /// String table size in bytes.
222   uint32_t Size;
223   /// A mapping from string table offset to the index
224   /// of the Table. It is used to avoid putting
225   /// duplicated strings in the table.
226   std::map<uint32_t, uint32_t> OffsetToIdMap;
227   /// A vector of strings to represent the string table.
228   std::vector<std::string> Table;
229 
230 public:
231   BTFStringTable() : Size(0) {}
232   uint32_t getSize() { return Size; }
233   std::vector<std::string> &getTable() { return Table; }
234   /// Add a string to the string table and returns its offset
235   /// in the table.
236   uint32_t addString(StringRef S);
237 };
238 
239 /// Represent one func and its type id.
240 struct BTFFuncInfo {
241   const MCSymbol *Label; ///< Func MCSymbol
242   uint32_t TypeId;       ///< Type id referring to .BTF type section
243 };
244 
245 /// Represent one line info.
246 struct BTFLineInfo {
247   MCSymbol *Label;      ///< MCSymbol identifying insn for the lineinfo
248   uint32_t FileNameOff; ///< file name offset in the .BTF string table
249   uint32_t LineOff;     ///< line offset in the .BTF string table
250   uint32_t LineNum;     ///< the line number
251   uint32_t ColumnNum;   ///< the column number
252 };
253 
254 /// Represent one field relocation.
255 struct BTFFieldReloc {
256   const MCSymbol *Label;  ///< MCSymbol identifying insn for the reloc
257   uint32_t TypeID;        ///< Type ID
258   uint32_t OffsetNameOff; ///< The string to traverse types
259   uint32_t RelocKind;     ///< What to patch the instruction
260 };
261 
262 /// Collect and emit BTF information.
263 class BTFDebug : public DebugHandlerBase {
264   MCStreamer &OS;
265   bool SkipInstruction;
266   bool LineInfoGenerated;
267   uint32_t SecNameOff;
268   uint32_t ArrayIndexTypeId;
269   bool MapDefNotCollected;
270   BTFStringTable StringTable;
271   std::vector<std::unique_ptr<BTFTypeBase>> TypeEntries;
272   std::unordered_map<const DIType *, uint32_t> DIToIdMap;
273   std::map<uint32_t, std::vector<BTFFuncInfo>> FuncInfoTable;
274   std::map<uint32_t, std::vector<BTFLineInfo>> LineInfoTable;
275   std::map<uint32_t, std::vector<BTFFieldReloc>> FieldRelocTable;
276   StringMap<std::vector<std::string>> FileContent;
277   std::map<std::string, std::unique_ptr<BTFKindDataSec>> DataSecEntries;
278   std::vector<BTFTypeStruct *> StructTypes;
279   std::map<const GlobalVariable *, std::pair<int64_t, uint32_t>> PatchImms;
280   std::map<StringRef, std::pair<bool, std::vector<BTFTypeDerived *>>>
281       FixupDerivedTypes;
282   std::set<const Function *>ProtoFunctions;
283 
284   /// Add types to TypeEntries.
285   /// @{
286   /// Add types to TypeEntries and DIToIdMap.
287   uint32_t addType(std::unique_ptr<BTFTypeBase> TypeEntry, const DIType *Ty);
288   /// Add types to TypeEntries only and return type id.
289   uint32_t addType(std::unique_ptr<BTFTypeBase> TypeEntry);
290   /// @}
291 
292   /// IR type visiting functions.
293   /// @{
294   void visitTypeEntry(const DIType *Ty);
295   void visitTypeEntry(const DIType *Ty, uint32_t &TypeId, bool CheckPointer,
296                       bool SeenPointer);
297   void visitBasicType(const DIBasicType *BTy, uint32_t &TypeId);
298   void visitSubroutineType(
299       const DISubroutineType *STy, bool ForSubprog,
300       const std::unordered_map<uint32_t, StringRef> &FuncArgNames,
301       uint32_t &TypeId);
302   void visitFwdDeclType(const DICompositeType *CTy, bool IsUnion,
303                         uint32_t &TypeId);
304   void visitCompositeType(const DICompositeType *CTy, uint32_t &TypeId);
305   void visitStructType(const DICompositeType *STy, bool IsStruct,
306                        uint32_t &TypeId);
307   void visitArrayType(const DICompositeType *ATy, uint32_t &TypeId);
308   void visitEnumType(const DICompositeType *ETy, uint32_t &TypeId);
309   void visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId,
310                         bool CheckPointer, bool SeenPointer);
311   void visitMapDefType(const DIType *Ty, uint32_t &TypeId);
312   /// @}
313 
314   /// Get the file content for the subprogram. Certain lines of the file
315   /// later may be put into string table and referenced by line info.
316   std::string populateFileContent(const DISubprogram *SP);
317 
318   /// Construct a line info.
319   void constructLineInfo(const DISubprogram *SP, MCSymbol *Label, uint32_t Line,
320                          uint32_t Column);
321 
322   /// Generate types and variables for globals.
323   void processGlobals(bool ProcessingMapDef);
324 
325   /// Generate types for function prototypes.
326   void processFuncPrototypes(const Function *);
327 
328   /// Generate types for annotations.
329   void processAnnotations(DINodeArray Annotations, uint32_t BaseTypeId,
330                           int ComponentId);
331 
332   /// Generate one field relocation record.
333   void generatePatchImmReloc(const MCSymbol *ORSym, uint32_t RootId,
334                              const GlobalVariable *, bool IsAma);
335 
336   /// Populating unprocessed type on demand.
337   unsigned populateType(const DIType *Ty);
338 
339   /// Process global variables referenced by relocation instructions
340   /// and extern function references.
341   void processGlobalValue(const MachineOperand &MO);
342 
343   /// Emit common header of .BTF and .BTF.ext sections.
344   void emitCommonHeader();
345 
346   /// Emit the .BTF section.
347   void emitBTFSection();
348 
349   /// Emit the .BTF.ext section.
350   void emitBTFExtSection();
351 
352 protected:
353   /// Gather pre-function debug information.
354   void beginFunctionImpl(const MachineFunction *MF) override;
355 
356   /// Post process after all instructions in this function are processed.
357   void endFunctionImpl(const MachineFunction *MF) override;
358 
359 public:
360   BTFDebug(AsmPrinter *AP);
361 
362   ///
363   bool InstLower(const MachineInstr *MI, MCInst &OutMI);
364 
365   /// Get the special array index type id.
366   uint32_t getArrayIndexTypeId() {
367     assert(ArrayIndexTypeId);
368     return ArrayIndexTypeId;
369   }
370 
371   /// Add string to the string table.
372   size_t addString(StringRef S) { return StringTable.addString(S); }
373 
374   /// Get the type id for a particular DIType.
375   uint32_t getTypeId(const DIType *Ty) {
376     assert(Ty && "Invalid null Type");
377     assert(DIToIdMap.find(Ty) != DIToIdMap.end() &&
378            "DIType not added in the BDIToIdMap");
379     return DIToIdMap[Ty];
380   }
381 
382   void setSymbolSize(const MCSymbol *Symbol, uint64_t Size) override {}
383 
384   /// Process beginning of an instruction.
385   void beginInstruction(const MachineInstr *MI) override;
386 
387   /// Complete all the types and emit the BTF sections.
388   void endModule() override;
389 };
390 
391 } // end namespace llvm
392 
393 #endif
394