438 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file contains support for writing BTF debug info.11///12//===----------------------------------------------------------------------===//13 14#ifndef LLVM_LIB_TARGET_BPF_BTFDEBUG_H15#define LLVM_LIB_TARGET_BPF_BTFDEBUG_H16 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 25namespace llvm {26 27class AsmPrinter;28class BTFDebug;29class DIType;30class GlobalVariable;31class MachineFunction;32class MachineInstr;33class MachineOperand;34class MCInst;35class MCStreamer;36class MCSymbol;37 38/// The base class for BTF type generation.39class BTFTypeBase {40protected:41 uint8_t Kind;42 bool IsCompleted;43 uint32_t Id;44 struct BTF::CommonType BTFType;45 46public: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 types55 /// have been visited so their BTF type id's are available56 /// 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.64class BTFTypeDerived : public BTFTypeBase {65 const DIDerivedType *DTy;66 bool NeedsFixup;67 StringRef Name;68 69public: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.78class BTFTypeFwd : public BTFTypeBase {79 StringRef Name;80 81public:82 BTFTypeFwd(StringRef Name, bool IsUnion);83 void completeType(BTFDebug &BDebug) override;84 void emitType(MCStreamer &OS) override;85};86 87/// Handle int type.88class BTFTypeInt : public BTFTypeBase {89 StringRef Name;90 uint32_t IntVal; ///< Encoding, offset, bits91 92public: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.101class BTFTypeEnum : public BTFTypeBase {102 const DICompositeType *ETy;103 std::vector<struct BTF::BTFEnum> EnumValues;104 105public: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.115class BTFTypeArray : public BTFTypeBase {116 struct BTF::BTFArray ArrayInfo;117 118public: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.126class BTFTypeStruct : public BTFTypeBase {127 const DICompositeType *STy;128 bool HasBitField;129 std::vector<struct BTF::BTFMember> Members;130 131public: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.143class BTFTypeFuncProto : public BTFTypeBase {144 const DISubroutineType *STy;145 std::unordered_map<uint32_t, StringRef> FuncArgNames;146 std::vector<struct BTF::BTFParam> Parameters;147 148public: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 subprogram159class BTFTypeFunc : public BTFTypeBase {160 StringRef Name;161 162public: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 instances170class BTFKindVar : public BTFTypeBase {171 StringRef Name;172 uint32_t Info;173 174public: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 sections182class BTFKindDataSec : public BTFTypeBase {183 AsmPrinter *Asm;184 std::string Name;185 std::vector<std::tuple<uint32_t, const MCSymbol *, uint32_t>> Vars;186 187public: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(std::make_tuple(Id, Sym, 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.201class BTFTypeFloat : public BTFTypeBase {202 StringRef Name;203 204public:205 BTFTypeFloat(uint32_t SizeInBits, StringRef TypeName);206 void completeType(BTFDebug &BDebug) override;207};208 209/// Handle decl tags.210class BTFTypeDeclTag : public BTFTypeBase {211 uint32_t Info;212 StringRef Tag;213 214public: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.222class BTFTypeEnum64 : public BTFTypeBase {223 const DICompositeType *ETy;224 std::vector<struct BTF::BTFEnum64> EnumValues;225 226public: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 235class BTFTypeTypeTag : public BTFTypeBase {236 const DIDerivedType *DTy;237 StringRef Tag;238 239public: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.246class BTFStringTable {247 /// String table size in bytes.248 uint32_t Size;249 /// A mapping from string table offset to the index250 /// of the Table. It is used to avoid putting251 /// 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 256public: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 offset261 /// in the table.262 uint32_t addString(StringRef S);263};264 265/// Represent one func and its type id.266struct BTFFuncInfo {267 const MCSymbol *Label; ///< Func MCSymbol268 uint32_t TypeId; ///< Type id referring to .BTF type section269};270 271/// Represent one line info.272struct BTFLineInfo {273 MCSymbol *Label; ///< MCSymbol identifying insn for the lineinfo274 uint32_t FileNameOff; ///< file name offset in the .BTF string table275 uint32_t LineOff; ///< line offset in the .BTF string table276 uint32_t LineNum; ///< the line number277 uint32_t ColumnNum; ///< the column number278};279 280/// Represent one field relocation.281struct BTFFieldReloc {282 const MCSymbol *Label; ///< MCSymbol identifying insn for the reloc283 uint32_t TypeID; ///< Type ID284 uint32_t OffsetNameOff; ///< The string to traverse types285 uint32_t RelocKind; ///< What to patch the instruction286};287 288/// Collect and emit BTF information.289class 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>, std::less<>>304 DataSecEntries;305 std::vector<BTFTypeStruct *> StructTypes;306 std::map<const GlobalVariable *, std::pair<int64_t, uint32_t>> PatchImms;307 std::map<const DICompositeType *,308 std::vector<std::pair<const DIDerivedType *, BTFTypeDerived *>>>309 FixupDerivedTypes;310 std::set<const Function *>ProtoFunctions;311 312 /// Add types to TypeEntries.313 /// @{314 /// Add types to TypeEntries and DIToIdMap.315 uint32_t addType(std::unique_ptr<BTFTypeBase> TypeEntry, const DIType *Ty);316 /// Add types to TypeEntries only and return type id.317 uint32_t addType(std::unique_ptr<BTFTypeBase> TypeEntry);318 /// @}319 320 /// IR type visiting functions.321 /// @{322 void visitTypeEntry(const DIType *Ty);323 void visitTypeEntry(const DIType *Ty, uint32_t &TypeId, bool CheckPointer,324 bool SeenPointer);325 void visitBasicType(const DIBasicType *BTy, uint32_t &TypeId);326 void visitSubroutineType(327 const DISubroutineType *STy, bool ForSubprog,328 const std::unordered_map<uint32_t, StringRef> &FuncArgNames,329 uint32_t &TypeId);330 void visitFwdDeclType(const DICompositeType *CTy, bool IsUnion,331 uint32_t &TypeId);332 void visitCompositeType(const DICompositeType *CTy, uint32_t &TypeId);333 void visitStructType(const DICompositeType *STy, bool IsStruct,334 uint32_t &TypeId);335 void visitArrayType(const DICompositeType *ATy, uint32_t &TypeId);336 void visitEnumType(const DICompositeType *ETy, uint32_t &TypeId);337 void visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId,338 bool CheckPointer, bool SeenPointer);339 void visitMapDefType(const DIType *Ty, uint32_t &TypeId);340 /// @}341 342 /// Check whether the type is a forward declaration candidate or not.343 bool IsForwardDeclCandidate(const DIType *Base);344 345 /// Get the file content for the subprogram. Certain lines of the file346 /// later may be put into string table and referenced by line info.347 std::string populateFileContent(const DIFile *File);348 349 /// Construct a line info.350 void constructLineInfo(MCSymbol *Label, const DIFile *File, uint32_t Line,351 uint32_t Column);352 353 /// Generate types and variables for globals.354 void processGlobals(bool ProcessingMapDef);355 356 /// Process global variable initializer in pursuit for function357 /// pointers.358 void processGlobalInitializer(const Constant *C);359 360 /// Generate types for function prototypes.361 void processFuncPrototypes(const Function *);362 363 /// Generate types for decl annotations.364 void processDeclAnnotations(DINodeArray Annotations, uint32_t BaseTypeId,365 int ComponentId);366 367 /// Generate types for DISubprogram and it's arguments.368 uint32_t processDISubprogram(const DISubprogram *SP, uint32_t ProtoTypeId,369 uint8_t Scope);370 371 /// Generate BTF type_tag's. If BaseTypeId is nonnegative, the last372 /// BTF type_tag in the chain points to BaseTypeId. Otherwise, it points to373 /// the base type of DTy. Return the type id of the first BTF type_tag374 /// in the chain. If no type_tag's are generated, a negative value375 /// is returned.376 int genBTFTypeTags(const DIDerivedType *DTy, int BaseTypeId);377 378 /// Generate one field relocation record.379 void generatePatchImmReloc(const MCSymbol *ORSym, uint32_t RootId,380 const GlobalVariable *, bool IsAma);381 382 /// Populating unprocessed type on demand.383 unsigned populateType(const DIType *Ty);384 385 /// Process global variables referenced by relocation instructions386 /// and extern function references.387 void processGlobalValue(const MachineOperand &MO);388 389 /// Emit common header of .BTF and .BTF.ext sections.390 void emitCommonHeader();391 392 /// Emit the .BTF section.393 void emitBTFSection();394 395 /// Emit the .BTF.ext section.396 void emitBTFExtSection();397 398protected:399 /// Gather pre-function debug information.400 void beginFunctionImpl(const MachineFunction *MF) override;401 402 /// Post process after all instructions in this function are processed.403 void endFunctionImpl(const MachineFunction *MF) override;404 405public:406 BTFDebug(AsmPrinter *AP);407 408 ///409 bool InstLower(const MachineInstr *MI, MCInst &OutMI);410 411 /// Get the special array index type id.412 uint32_t getArrayIndexTypeId() {413 assert(ArrayIndexTypeId);414 return ArrayIndexTypeId;415 }416 417 /// Add string to the string table.418 size_t addString(StringRef S) { return StringTable.addString(S); }419 420 /// Get the type id for a particular DIType.421 uint32_t getTypeId(const DIType *Ty) {422 assert(Ty && "Invalid null Type");423 assert(DIToIdMap.find(Ty) != DIToIdMap.end() &&424 "DIType not added in the BDIToIdMap");425 return DIToIdMap[Ty];426 }427 428 /// Process beginning of an instruction.429 void beginInstruction(const MachineInstr *MI) override;430 431 /// Complete all the types and emit the BTF sections.432 void endModule() override;433};434 435} // end namespace llvm436 437#endif438