aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/BPF/BTFDebug.h
blob: 2fdcf8500b7f6265ccd207ca8914471223e88c0b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
//===- BTFDebug.h -----------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains support for writing BTF debug info.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_BPF_BTFDEBUG_H
#define LLVM_LIB_TARGET_BPF_BTFDEBUG_H

#include "llvm/ADT/StringMap.h"
#include "llvm/CodeGen/DebugHandlerBase.h"
#include <cstdint>
#include <map>
#include <set>
#include <unordered_map>
#include "BTF.h"

namespace llvm {

class AsmPrinter;
class BTFDebug;
class DIType;
class GlobalVariable;
class MachineFunction;
class MachineInstr;
class MachineOperand;
class MCInst;
class MCStreamer;
class MCSymbol;

/// The base class for BTF type generation.
class BTFTypeBase {
protected:
  uint8_t Kind;
  bool IsCompleted;
  uint32_t Id;
  struct BTF::CommonType BTFType;

public:
  BTFTypeBase() : IsCompleted(false) {}
  virtual ~BTFTypeBase() = default;
  void setId(uint32_t Id) { this->Id = Id; }
  uint32_t getId() { return Id; }
  uint32_t roundupToBytes(uint32_t NumBits) { return (NumBits + 7) >> 3; }
  /// Get the size of this BTF type entry.
  virtual uint32_t getSize() { return BTF::CommonTypeSize; }
  /// Complete BTF type generation after all related DebugInfo types
  /// have been visited so their BTF type id's are available
  /// for cross referece.
  virtual void completeType(BTFDebug &BDebug) {}
  /// Emit types for this BTF type entry.
  virtual void emitType(MCStreamer &OS);
};

/// Handle several derived types include pointer, const,
/// volatile, typedef and restrict.
class BTFTypeDerived : public BTFTypeBase {
  const DIDerivedType *DTy;
  bool NeedsFixup;

public:
  BTFTypeDerived(const DIDerivedType *Ty, unsigned Tag, bool NeedsFixup);
  void completeType(BTFDebug &BDebug) override;
  void emitType(MCStreamer &OS) override;
  void setPointeeType(uint32_t PointeeType);
};

/// Handle struct or union forward declaration.
class BTFTypeFwd : public BTFTypeBase {
  StringRef Name;

public:
  BTFTypeFwd(StringRef Name, bool IsUnion);
  void completeType(BTFDebug &BDebug) override;
  void emitType(MCStreamer &OS) override;
};

/// Handle int type.
class BTFTypeInt : public BTFTypeBase {
  StringRef Name;
  uint32_t IntVal; ///< Encoding, offset, bits

public:
  BTFTypeInt(uint32_t Encoding, uint32_t SizeInBits, uint32_t OffsetInBits,
             StringRef TypeName);
  uint32_t getSize() override { return BTFTypeBase::getSize() + sizeof(uint32_t); }
  void completeType(BTFDebug &BDebug) override;
  void emitType(MCStreamer &OS) override;
};

/// Handle enumerate type.
class BTFTypeEnum : public BTFTypeBase {
  const DICompositeType *ETy;
  std::vector<struct BTF::BTFEnum> EnumValues;

public:
  BTFTypeEnum(const DICompositeType *ETy, uint32_t NumValues);
  uint32_t getSize() override {
    return BTFTypeBase::getSize() + EnumValues.size() * BTF::BTFEnumSize;
  }
  void completeType(BTFDebug &BDebug) override;
  void emitType(MCStreamer &OS) override;
};

/// Handle array type.
class BTFTypeArray : public BTFTypeBase {
  struct BTF::BTFArray ArrayInfo;

public:
  BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems);
  uint32_t getSize() override { return BTFTypeBase::getSize() + BTF::BTFArraySize; }
  void completeType(BTFDebug &BDebug) override;
  void emitType(MCStreamer &OS) override;
};

/// Handle struct/union type.
class BTFTypeStruct : public BTFTypeBase {
  const DICompositeType *STy;
  bool HasBitField;
  std::vector<struct BTF::BTFMember> Members;

public:
  BTFTypeStruct(const DICompositeType *STy, bool IsStruct, bool HasBitField,
                uint32_t NumMembers);
  uint32_t getSize() override {
    return BTFTypeBase::getSize() + Members.size() * BTF::BTFMemberSize;
  }
  void completeType(BTFDebug &BDebug) override;
  void emitType(MCStreamer &OS) override;
  std::string getName();
};

/// Handle function pointer.
class BTFTypeFuncProto : public BTFTypeBase {
  const DISubroutineType *STy;
  std::unordered_map<uint32_t, StringRef> FuncArgNames;
  std::vector<struct BTF::BTFParam> Parameters;

public:
  BTFTypeFuncProto(const DISubroutineType *STy, uint32_t NumParams,
                   const std::unordered_map<uint32_t, StringRef> &FuncArgNames);
  uint32_t getSize() override {
    return BTFTypeBase::getSize() + Parameters.size() * BTF::BTFParamSize;
  }
  void completeType(BTFDebug &BDebug) override;
  void emitType(MCStreamer &OS) override;
};

/// Handle subprogram
class BTFTypeFunc : public BTFTypeBase {
  StringRef Name;

public:
  BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId, uint32_t Scope);
  uint32_t getSize() override { return BTFTypeBase::getSize(); }
  void completeType(BTFDebug &BDebug) override;
  void emitType(MCStreamer &OS) override;
};

/// Handle variable instances
class BTFKindVar : public BTFTypeBase {
  StringRef Name;
  uint32_t Info;

public:
  BTFKindVar(StringRef VarName, uint32_t TypeId, uint32_t VarInfo);
  uint32_t getSize() override { return BTFTypeBase::getSize() + 4; }
  void completeType(BTFDebug &BDebug) override;
  void emitType(MCStreamer &OS) override;
};

/// Handle data sections
class BTFKindDataSec : public BTFTypeBase {
  AsmPrinter *Asm;
  std::string Name;
  std::vector<std::tuple<uint32_t, const MCSymbol *, uint32_t>> Vars;

public:
  BTFKindDataSec(AsmPrinter *AsmPrt, std::string SecName);
  uint32_t getSize() override {
    return BTFTypeBase::getSize() + BTF::BTFDataSecVarSize * Vars.size();
  }
  void addDataSecEntry(uint32_t Id, const MCSymbol *Sym, uint32_t Size) {
    Vars.push_back(std::make_tuple(Id, Sym, Size));
  }
  std::string getName() { return Name; }
  void completeType(BTFDebug &BDebug) override;
  void emitType(MCStreamer &OS) override;
};

/// Handle binary floating point type.
class BTFTypeFloat : public BTFTypeBase {
  StringRef Name;

public:
  BTFTypeFloat(uint32_t SizeInBits, StringRef TypeName);
  void completeType(BTFDebug &BDebug) override;
};

/// String table.
class BTFStringTable {
  /// String table size in bytes.
  uint32_t Size;
  /// A mapping from string table offset to the index
  /// of the Table. It is used to avoid putting
  /// duplicated strings in the table.
  std::map<uint32_t, uint32_t> OffsetToIdMap;
  /// A vector of strings to represent the string table.
  std::vector<std::string> Table;

public:
  BTFStringTable() : Size(0) {}
  uint32_t getSize() { return Size; }
  std::vector<std::string> &getTable() { return Table; }
  /// Add a string to the string table and returns its offset
  /// in the table.
  uint32_t addString(StringRef S);
};

/// Represent one func and its type id.
struct BTFFuncInfo {
  const MCSymbol *Label; ///< Func MCSymbol
  uint32_t TypeId;       ///< Type id referring to .BTF type section
};

/// Represent one line info.
struct BTFLineInfo {
  MCSymbol *Label;      ///< MCSymbol identifying insn for the lineinfo
  uint32_t FileNameOff; ///< file name offset in the .BTF string table
  uint32_t LineOff;     ///< line offset in the .BTF string table
  uint32_t LineNum;     ///< the line number
  uint32_t ColumnNum;   ///< the column number
};

/// Represent one field relocation.
struct BTFFieldReloc {
  const MCSymbol *Label;  ///< MCSymbol identifying insn for the reloc
  uint32_t TypeID;        ///< Type ID
  uint32_t OffsetNameOff; ///< The string to traverse types
  uint32_t RelocKind;     ///< What to patch the instruction
};

/// Collect and emit BTF information.
class BTFDebug : public DebugHandlerBase {
  MCStreamer &OS;
  bool SkipInstruction;
  bool LineInfoGenerated;
  uint32_t SecNameOff;
  uint32_t ArrayIndexTypeId;
  bool MapDefNotCollected;
  BTFStringTable StringTable;
  std::vector<std::unique_ptr<BTFTypeBase>> TypeEntries;
  std::unordered_map<const DIType *, uint32_t> DIToIdMap;
  std::map<uint32_t, std::vector<BTFFuncInfo>> FuncInfoTable;
  std::map<uint32_t, std::vector<BTFLineInfo>> LineInfoTable;
  std::map<uint32_t, std::vector<BTFFieldReloc>> FieldRelocTable;
  StringMap<std::vector<std::string>> FileContent;
  std::map<std::string, std::unique_ptr<BTFKindDataSec>> DataSecEntries;
  std::vector<BTFTypeStruct *> StructTypes;
  std::map<const GlobalVariable *, std::pair<int64_t, uint32_t>> PatchImms;
  std::map<StringRef, std::pair<bool, std::vector<BTFTypeDerived *>>>
      FixupDerivedTypes;
  std::set<const Function *>ProtoFunctions;

  /// Add types to TypeEntries.
  /// @{
  /// Add types to TypeEntries and DIToIdMap.
  uint32_t addType(std::unique_ptr<BTFTypeBase> TypeEntry, const DIType *Ty);
  /// Add types to TypeEntries only and return type id.
  uint32_t addType(std::unique_ptr<BTFTypeBase> TypeEntry);
  /// @}

  /// IR type visiting functions.
  /// @{
  void visitTypeEntry(const DIType *Ty);
  void visitTypeEntry(const DIType *Ty, uint32_t &TypeId, bool CheckPointer,
                      bool SeenPointer);
  void visitBasicType(const DIBasicType *BTy, uint32_t &TypeId);
  void visitSubroutineType(
      const DISubroutineType *STy, bool ForSubprog,
      const std::unordered_map<uint32_t, StringRef> &FuncArgNames,
      uint32_t &TypeId);
  void visitFwdDeclType(const DICompositeType *CTy, bool IsUnion,
                        uint32_t &TypeId);
  void visitCompositeType(const DICompositeType *CTy, uint32_t &TypeId);
  void visitStructType(const DICompositeType *STy, bool IsStruct,
                       uint32_t &TypeId);
  void visitArrayType(const DICompositeType *ATy, uint32_t &TypeId);
  void visitEnumType(const DICompositeType *ETy, uint32_t &TypeId);
  void visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId,
                        bool CheckPointer, bool SeenPointer);
  void visitMapDefType(const DIType *Ty, uint32_t &TypeId);
  /// @}

  /// Get the file content for the subprogram. Certain lines of the file
  /// later may be put into string table and referenced by line info.
  std::string populateFileContent(const DISubprogram *SP);

  /// Construct a line info.
  void constructLineInfo(const DISubprogram *SP, MCSymbol *Label, uint32_t Line,
                         uint32_t Column);

  /// Generate types and variables for globals.
  void processGlobals(bool ProcessingMapDef);

  /// Generate types for function prototypes.
  void processFuncPrototypes(const Function *);

  /// Generate one field relocation record.
  void generatePatchImmReloc(const MCSymbol *ORSym, uint32_t RootId,
                             const GlobalVariable *, bool IsAma);

  /// Populating unprocessed type on demand.
  unsigned populateType(const DIType *Ty);

  /// Process global variables referenced by relocation instructions
  /// and extern function references.
  void processGlobalValue(const MachineOperand &MO);

  /// Emit common header of .BTF and .BTF.ext sections.
  void emitCommonHeader();

  /// Emit the .BTF section.
  void emitBTFSection();

  /// Emit the .BTF.ext section.
  void emitBTFExtSection();

protected:
  /// Gather pre-function debug information.
  void beginFunctionImpl(const MachineFunction *MF) override;

  /// Post process after all instructions in this function are processed.
  void endFunctionImpl(const MachineFunction *MF) override;

public:
  BTFDebug(AsmPrinter *AP);

  ///
  bool InstLower(const MachineInstr *MI, MCInst &OutMI);

  /// Get the special array index type id.
  uint32_t getArrayIndexTypeId() {
    assert(ArrayIndexTypeId);
    return ArrayIndexTypeId;
  }

  /// Add string to the string table.
  size_t addString(StringRef S) { return StringTable.addString(S); }

  /// Get the type id for a particular DIType.
  uint32_t getTypeId(const DIType *Ty) {
    assert(Ty && "Invalid null Type");
    assert(DIToIdMap.find(Ty) != DIToIdMap.end() &&
           "DIType not added in the BDIToIdMap");
    return DIToIdMap[Ty];
  }

  void setSymbolSize(const MCSymbol *Symbol, uint64_t Size) override {}

  /// Process beginning of an instruction.
  void beginInstruction(const MachineInstr *MI) override;

  /// Complete all the types and emit the BTF sections.
  void endModule() override;
};

} // end namespace llvm

#endif