| //===- 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; | |
| 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<struct BTF::BTFEnum> 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<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; | |
| }; | |
| /// 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<struct BTF::BTFEnum64> 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<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<const DICompositeType *, | |
| std::vector<std::pair<const DIDerivedType *, 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 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]; | |
| } | |
| 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 |