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