//===- 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 "llvm/DebugInfo/BTF/BTF.h" #include #include #include #include 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; StringRef Name; public: BTFTypeDerived(const DIDerivedType *Ty, unsigned Tag, bool NeedsFixup); BTFTypeDerived(unsigned NextTypeId, unsigned Tag, StringRef Name); 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 EnumValues; public: BTFTypeEnum(const DICompositeType *ETy, uint32_t NumValues, bool IsSigned); 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 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 FuncArgNames; std::vector Parameters; public: BTFTypeFuncProto(const DISubroutineType *STy, uint32_t NumParams, const std::unordered_map &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> 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; }; /// Handle decl tags. class BTFTypeDeclTag : public BTFTypeBase { uint32_t Info; StringRef Tag; public: BTFTypeDeclTag(uint32_t BaseTypeId, int ComponentId, StringRef Tag); uint32_t getSize() override { return BTFTypeBase::getSize() + 4; } void completeType(BTFDebug &BDebug) override; void emitType(MCStreamer &OS) override; }; /// Handle 64-bit enumerate type. class BTFTypeEnum64 : public BTFTypeBase { const DICompositeType *ETy; std::vector EnumValues; public: BTFTypeEnum64(const DICompositeType *ETy, uint32_t NumValues, bool IsSigned); uint32_t getSize() override { return BTFTypeBase::getSize() + EnumValues.size() * BTF::BTFEnum64Size; } void completeType(BTFDebug &BDebug) override; void emitType(MCStreamer &OS) override; }; class BTFTypeTypeTag : public BTFTypeBase { const DIDerivedType *DTy; StringRef Tag; public: BTFTypeTypeTag(uint32_t NextTypeId, StringRef Tag); BTFTypeTypeTag(const DIDerivedType *DTy, StringRef Tag); 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 OffsetToIdMap; /// A vector of strings to represent the string table. std::vector Table; public: BTFStringTable() : Size(0) {} uint32_t getSize() { return Size; } std::vector &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> TypeEntries; std::unordered_map DIToIdMap; std::map> FuncInfoTable; std::map> LineInfoTable; std::map> FieldRelocTable; StringMap> FileContent; std::map> DataSecEntries; std::vector StructTypes; std::map> PatchImms; std::map>> FixupDerivedTypes; std::setProtoFunctions; /// Add types to TypeEntries. /// @{ /// Add types to TypeEntries and DIToIdMap. uint32_t addType(std::unique_ptr TypeEntry, const DIType *Ty); /// Add types to TypeEntries only and return type id. uint32_t addType(std::unique_ptr 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 &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); /// @} /// Check whether the type is a forward declaration candidate or not. bool IsForwardDeclCandidate(const DIType *Base); /// 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 DIFile *File); /// Construct a line info. void constructLineInfo(MCSymbol *Label, const DIFile *File, uint32_t Line, uint32_t Column); /// Generate types and variables for globals. void processGlobals(bool ProcessingMapDef); /// Process global variable initializer in pursuit for function /// pointers. void processGlobalInitializer(const Constant *C); /// Generate types for function prototypes. void processFuncPrototypes(const Function *); /// Generate types for decl annotations. void processDeclAnnotations(DINodeArray Annotations, uint32_t BaseTypeId, int ComponentId); /// Generate types for DISubprogram and it's arguments. uint32_t processDISubprogram(const DISubprogram *SP, uint32_t ProtoTypeId, uint8_t Scope); /// Generate BTF type_tag's. If BaseTypeId is nonnegative, the last /// BTF type_tag in the chain points to BaseTypeId. Otherwise, it points to /// the base type of DTy. Return the type id of the first BTF type_tag /// in the chain. If no type_tag's are generated, a negative value /// is returned. int genBTFTypeTags(const DIDerivedType *DTy, int BaseTypeId); /// 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]; } /// 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