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
24namespace llvm {
25
26class AsmPrinter;
27class BTFDebug;
28class DIType;
29class GlobalVariable;
30class MCStreamer;
31class MCSymbol;
32class MachineFunction;
33
34/// The base class for BTF type generation.
35class BTFTypeBase {
36protected:
37  uint8_t Kind;
38  bool IsCompleted;
39  uint32_t Id;
40  struct BTF::CommonType BTFType;
41
42public:
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.
60class BTFTypeDerived : public BTFTypeBase {
61  const DIDerivedType *DTy;
62  bool NeedsFixup;
63
64public:
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.
72class BTFTypeFwd : public BTFTypeBase {
73  StringRef Name;
74
75public:
76  BTFTypeFwd(StringRef Name, bool IsUnion);
77  void completeType(BTFDebug &BDebug) override;
78  void emitType(MCStreamer &OS) override;
79};
80
81/// Handle int type.
82class BTFTypeInt : public BTFTypeBase {
83  StringRef Name;
84  uint32_t IntVal; ///< Encoding, offset, bits
85
86public:
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.
95class BTFTypeEnum : public BTFTypeBase {
96  const DICompositeType *ETy;
97  std::vector<struct BTF::BTFEnum> EnumValues;
98
99public:
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.
109class BTFTypeArray : public BTFTypeBase {
110  struct BTF::BTFArray ArrayInfo;
111
112public:
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.
120class BTFTypeStruct : public BTFTypeBase {
121  const DICompositeType *STy;
122  bool HasBitField;
123  std::vector<struct BTF::BTFMember> Members;
124
125public:
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.
137class BTFTypeFuncProto : public BTFTypeBase {
138  const DISubroutineType *STy;
139  std::unordered_map<uint32_t, StringRef> FuncArgNames;
140  std::vector<struct BTF::BTFParam> Parameters;
141
142public:
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
153class BTFTypeFunc : public BTFTypeBase {
154  StringRef Name;
155
156public:
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
164class BTFKindVar : public BTFTypeBase {
165  StringRef Name;
166  uint32_t Info;
167
168public:
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
176class BTFKindDataSec : public BTFTypeBase {
177  AsmPrinter *Asm;
178  std::string Name;
179  std::vector<std::tuple<uint32_t, const MCSymbol *, uint32_t>> Vars;
180
181public:
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.
195class 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
205public:
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.
215struct 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.
221struct 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.
230struct 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.
238class 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
322protected:
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
329public:
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