//===- 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/CodeGen/MachineInstr.h"
#include <set>
#include <unordered_map>
#include "BTF.h"
namespace llvm {
class AsmPrinter;
class BTFDebug;
class DIType;
class GlobalVariable;
class MCStreamer;
class MCSymbol;
class MachineFunction;
/// 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 addVar(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;
};
/// 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 *, 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 relocation instructions.
void processReloc(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