368 lines
12 KiB
C
368 lines
12 KiB
C
|
//===- 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 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 *, 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 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
|