Path: blob/main/contrib/llvm-project/llvm/lib/Target/BPF/BTFDebug.cpp
35269 views
//===- BTFDebug.cpp - BTF Generator ---------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains support for writing BTF debug info.9//10//===----------------------------------------------------------------------===//1112#include "BTFDebug.h"13#include "BPF.h"14#include "BPFCORE.h"15#include "MCTargetDesc/BPFMCTargetDesc.h"16#include "llvm/BinaryFormat/ELF.h"17#include "llvm/CodeGen/AsmPrinter.h"18#include "llvm/CodeGen/MachineModuleInfo.h"19#include "llvm/CodeGen/MachineOperand.h"20#include "llvm/IR/Module.h"21#include "llvm/MC/MCContext.h"22#include "llvm/MC/MCObjectFileInfo.h"23#include "llvm/MC/MCSectionELF.h"24#include "llvm/MC/MCStreamer.h"25#include "llvm/Support/LineIterator.h"26#include "llvm/Support/MemoryBuffer.h"27#include "llvm/Target/TargetLoweringObjectFile.h"28#include <optional>2930using namespace llvm;3132static const char *BTFKindStr[] = {33#define HANDLE_BTF_KIND(ID, NAME) "BTF_KIND_" #NAME,34#include "llvm/DebugInfo/BTF/BTF.def"35};3637/// Emit a BTF common type.38void BTFTypeBase::emitType(MCStreamer &OS) {39OS.AddComment(std::string(BTFKindStr[Kind]) + "(id = " + std::to_string(Id) +40")");41OS.emitInt32(BTFType.NameOff);42OS.AddComment("0x" + Twine::utohexstr(BTFType.Info));43OS.emitInt32(BTFType.Info);44OS.emitInt32(BTFType.Size);45}4647BTFTypeDerived::BTFTypeDerived(const DIDerivedType *DTy, unsigned Tag,48bool NeedsFixup)49: DTy(DTy), NeedsFixup(NeedsFixup), Name(DTy->getName()) {50switch (Tag) {51case dwarf::DW_TAG_pointer_type:52Kind = BTF::BTF_KIND_PTR;53break;54case dwarf::DW_TAG_const_type:55Kind = BTF::BTF_KIND_CONST;56break;57case dwarf::DW_TAG_volatile_type:58Kind = BTF::BTF_KIND_VOLATILE;59break;60case dwarf::DW_TAG_typedef:61Kind = BTF::BTF_KIND_TYPEDEF;62break;63case dwarf::DW_TAG_restrict_type:64Kind = BTF::BTF_KIND_RESTRICT;65break;66default:67llvm_unreachable("Unknown DIDerivedType Tag");68}69BTFType.Info = Kind << 24;70}7172/// Used by DW_TAG_pointer_type only.73BTFTypeDerived::BTFTypeDerived(unsigned NextTypeId, unsigned Tag,74StringRef Name)75: DTy(nullptr), NeedsFixup(false), Name(Name) {76Kind = BTF::BTF_KIND_PTR;77BTFType.Info = Kind << 24;78BTFType.Type = NextTypeId;79}8081void BTFTypeDerived::completeType(BTFDebug &BDebug) {82if (IsCompleted)83return;84IsCompleted = true;8586BTFType.NameOff = BDebug.addString(Name);8788if (NeedsFixup || !DTy)89return;9091// The base type for PTR/CONST/VOLATILE could be void.92const DIType *ResolvedType = DTy->getBaseType();93if (!ResolvedType) {94assert((Kind == BTF::BTF_KIND_PTR || Kind == BTF::BTF_KIND_CONST ||95Kind == BTF::BTF_KIND_VOLATILE) &&96"Invalid null basetype");97BTFType.Type = 0;98} else {99BTFType.Type = BDebug.getTypeId(ResolvedType);100}101}102103void BTFTypeDerived::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); }104105void BTFTypeDerived::setPointeeType(uint32_t PointeeType) {106BTFType.Type = PointeeType;107}108109/// Represent a struct/union forward declaration.110BTFTypeFwd::BTFTypeFwd(StringRef Name, bool IsUnion) : Name(Name) {111Kind = BTF::BTF_KIND_FWD;112BTFType.Info = IsUnion << 31 | Kind << 24;113BTFType.Type = 0;114}115116void BTFTypeFwd::completeType(BTFDebug &BDebug) {117if (IsCompleted)118return;119IsCompleted = true;120121BTFType.NameOff = BDebug.addString(Name);122}123124void BTFTypeFwd::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); }125126BTFTypeInt::BTFTypeInt(uint32_t Encoding, uint32_t SizeInBits,127uint32_t OffsetInBits, StringRef TypeName)128: Name(TypeName) {129// Translate IR int encoding to BTF int encoding.130uint8_t BTFEncoding;131switch (Encoding) {132case dwarf::DW_ATE_boolean:133BTFEncoding = BTF::INT_BOOL;134break;135case dwarf::DW_ATE_signed:136case dwarf::DW_ATE_signed_char:137BTFEncoding = BTF::INT_SIGNED;138break;139case dwarf::DW_ATE_unsigned:140case dwarf::DW_ATE_unsigned_char:141BTFEncoding = 0;142break;143default:144llvm_unreachable("Unknown BTFTypeInt Encoding");145}146147Kind = BTF::BTF_KIND_INT;148BTFType.Info = Kind << 24;149BTFType.Size = roundupToBytes(SizeInBits);150IntVal = (BTFEncoding << 24) | OffsetInBits << 16 | SizeInBits;151}152153void BTFTypeInt::completeType(BTFDebug &BDebug) {154if (IsCompleted)155return;156IsCompleted = true;157158BTFType.NameOff = BDebug.addString(Name);159}160161void BTFTypeInt::emitType(MCStreamer &OS) {162BTFTypeBase::emitType(OS);163OS.AddComment("0x" + Twine::utohexstr(IntVal));164OS.emitInt32(IntVal);165}166167BTFTypeEnum::BTFTypeEnum(const DICompositeType *ETy, uint32_t VLen,168bool IsSigned) : ETy(ETy) {169Kind = BTF::BTF_KIND_ENUM;170BTFType.Info = IsSigned << 31 | Kind << 24 | VLen;171BTFType.Size = roundupToBytes(ETy->getSizeInBits());172}173174void BTFTypeEnum::completeType(BTFDebug &BDebug) {175if (IsCompleted)176return;177IsCompleted = true;178179BTFType.NameOff = BDebug.addString(ETy->getName());180181DINodeArray Elements = ETy->getElements();182for (const auto Element : Elements) {183const auto *Enum = cast<DIEnumerator>(Element);184185struct BTF::BTFEnum BTFEnum;186BTFEnum.NameOff = BDebug.addString(Enum->getName());187// BTF enum value is 32bit, enforce it.188uint32_t Value;189if (Enum->isUnsigned())190Value = static_cast<uint32_t>(Enum->getValue().getZExtValue());191else192Value = static_cast<uint32_t>(Enum->getValue().getSExtValue());193BTFEnum.Val = Value;194EnumValues.push_back(BTFEnum);195}196}197198void BTFTypeEnum::emitType(MCStreamer &OS) {199BTFTypeBase::emitType(OS);200for (const auto &Enum : EnumValues) {201OS.emitInt32(Enum.NameOff);202OS.emitInt32(Enum.Val);203}204}205206BTFTypeEnum64::BTFTypeEnum64(const DICompositeType *ETy, uint32_t VLen,207bool IsSigned) : ETy(ETy) {208Kind = BTF::BTF_KIND_ENUM64;209BTFType.Info = IsSigned << 31 | Kind << 24 | VLen;210BTFType.Size = roundupToBytes(ETy->getSizeInBits());211}212213void BTFTypeEnum64::completeType(BTFDebug &BDebug) {214if (IsCompleted)215return;216IsCompleted = true;217218BTFType.NameOff = BDebug.addString(ETy->getName());219220DINodeArray Elements = ETy->getElements();221for (const auto Element : Elements) {222const auto *Enum = cast<DIEnumerator>(Element);223224struct BTF::BTFEnum64 BTFEnum;225BTFEnum.NameOff = BDebug.addString(Enum->getName());226uint64_t Value;227if (Enum->isUnsigned())228Value = static_cast<uint64_t>(Enum->getValue().getZExtValue());229else230Value = static_cast<uint64_t>(Enum->getValue().getSExtValue());231BTFEnum.Val_Lo32 = Value;232BTFEnum.Val_Hi32 = Value >> 32;233EnumValues.push_back(BTFEnum);234}235}236237void BTFTypeEnum64::emitType(MCStreamer &OS) {238BTFTypeBase::emitType(OS);239for (const auto &Enum : EnumValues) {240OS.emitInt32(Enum.NameOff);241OS.AddComment("0x" + Twine::utohexstr(Enum.Val_Lo32));242OS.emitInt32(Enum.Val_Lo32);243OS.AddComment("0x" + Twine::utohexstr(Enum.Val_Hi32));244OS.emitInt32(Enum.Val_Hi32);245}246}247248BTFTypeArray::BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems) {249Kind = BTF::BTF_KIND_ARRAY;250BTFType.NameOff = 0;251BTFType.Info = Kind << 24;252BTFType.Size = 0;253254ArrayInfo.ElemType = ElemTypeId;255ArrayInfo.Nelems = NumElems;256}257258/// Represent a BTF array.259void BTFTypeArray::completeType(BTFDebug &BDebug) {260if (IsCompleted)261return;262IsCompleted = true;263264// The IR does not really have a type for the index.265// A special type for array index should have been266// created during initial type traversal. Just267// retrieve that type id.268ArrayInfo.IndexType = BDebug.getArrayIndexTypeId();269}270271void BTFTypeArray::emitType(MCStreamer &OS) {272BTFTypeBase::emitType(OS);273OS.emitInt32(ArrayInfo.ElemType);274OS.emitInt32(ArrayInfo.IndexType);275OS.emitInt32(ArrayInfo.Nelems);276}277278/// Represent either a struct or a union.279BTFTypeStruct::BTFTypeStruct(const DICompositeType *STy, bool IsStruct,280bool HasBitField, uint32_t Vlen)281: STy(STy), HasBitField(HasBitField) {282Kind = IsStruct ? BTF::BTF_KIND_STRUCT : BTF::BTF_KIND_UNION;283BTFType.Size = roundupToBytes(STy->getSizeInBits());284BTFType.Info = (HasBitField << 31) | (Kind << 24) | Vlen;285}286287void BTFTypeStruct::completeType(BTFDebug &BDebug) {288if (IsCompleted)289return;290IsCompleted = true;291292BTFType.NameOff = BDebug.addString(STy->getName());293294// Add struct/union members.295const DINodeArray Elements = STy->getElements();296for (const auto *Element : Elements) {297struct BTF::BTFMember BTFMember;298const auto *DDTy = cast<DIDerivedType>(Element);299300BTFMember.NameOff = BDebug.addString(DDTy->getName());301if (HasBitField) {302uint8_t BitFieldSize = DDTy->isBitField() ? DDTy->getSizeInBits() : 0;303BTFMember.Offset = BitFieldSize << 24 | DDTy->getOffsetInBits();304} else {305BTFMember.Offset = DDTy->getOffsetInBits();306}307const auto *BaseTy = DDTy->getBaseType();308BTFMember.Type = BDebug.getTypeId(BaseTy);309Members.push_back(BTFMember);310}311}312313void BTFTypeStruct::emitType(MCStreamer &OS) {314BTFTypeBase::emitType(OS);315for (const auto &Member : Members) {316OS.emitInt32(Member.NameOff);317OS.emitInt32(Member.Type);318OS.AddComment("0x" + Twine::utohexstr(Member.Offset));319OS.emitInt32(Member.Offset);320}321}322323std::string BTFTypeStruct::getName() { return std::string(STy->getName()); }324325/// The Func kind represents both subprogram and pointee of function326/// pointers. If the FuncName is empty, it represents a pointee of function327/// pointer. Otherwise, it represents a subprogram. The func arg names328/// are empty for pointee of function pointer case, and are valid names329/// for subprogram.330BTFTypeFuncProto::BTFTypeFuncProto(331const DISubroutineType *STy, uint32_t VLen,332const std::unordered_map<uint32_t, StringRef> &FuncArgNames)333: STy(STy), FuncArgNames(FuncArgNames) {334Kind = BTF::BTF_KIND_FUNC_PROTO;335BTFType.Info = (Kind << 24) | VLen;336}337338void BTFTypeFuncProto::completeType(BTFDebug &BDebug) {339if (IsCompleted)340return;341IsCompleted = true;342343DITypeRefArray Elements = STy->getTypeArray();344auto RetType = Elements[0];345BTFType.Type = RetType ? BDebug.getTypeId(RetType) : 0;346BTFType.NameOff = 0;347348// For null parameter which is typically the last one349// to represent the vararg, encode the NameOff/Type to be 0.350for (unsigned I = 1, N = Elements.size(); I < N; ++I) {351struct BTF::BTFParam Param;352auto Element = Elements[I];353if (Element) {354Param.NameOff = BDebug.addString(FuncArgNames[I]);355Param.Type = BDebug.getTypeId(Element);356} else {357Param.NameOff = 0;358Param.Type = 0;359}360Parameters.push_back(Param);361}362}363364void BTFTypeFuncProto::emitType(MCStreamer &OS) {365BTFTypeBase::emitType(OS);366for (const auto &Param : Parameters) {367OS.emitInt32(Param.NameOff);368OS.emitInt32(Param.Type);369}370}371372BTFTypeFunc::BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId,373uint32_t Scope)374: Name(FuncName) {375Kind = BTF::BTF_KIND_FUNC;376BTFType.Info = (Kind << 24) | Scope;377BTFType.Type = ProtoTypeId;378}379380void BTFTypeFunc::completeType(BTFDebug &BDebug) {381if (IsCompleted)382return;383IsCompleted = true;384385BTFType.NameOff = BDebug.addString(Name);386}387388void BTFTypeFunc::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); }389390BTFKindVar::BTFKindVar(StringRef VarName, uint32_t TypeId, uint32_t VarInfo)391: Name(VarName) {392Kind = BTF::BTF_KIND_VAR;393BTFType.Info = Kind << 24;394BTFType.Type = TypeId;395Info = VarInfo;396}397398void BTFKindVar::completeType(BTFDebug &BDebug) {399BTFType.NameOff = BDebug.addString(Name);400}401402void BTFKindVar::emitType(MCStreamer &OS) {403BTFTypeBase::emitType(OS);404OS.emitInt32(Info);405}406407BTFKindDataSec::BTFKindDataSec(AsmPrinter *AsmPrt, std::string SecName)408: Asm(AsmPrt), Name(SecName) {409Kind = BTF::BTF_KIND_DATASEC;410BTFType.Info = Kind << 24;411BTFType.Size = 0;412}413414void BTFKindDataSec::completeType(BTFDebug &BDebug) {415BTFType.NameOff = BDebug.addString(Name);416BTFType.Info |= Vars.size();417}418419void BTFKindDataSec::emitType(MCStreamer &OS) {420BTFTypeBase::emitType(OS);421422for (const auto &V : Vars) {423OS.emitInt32(std::get<0>(V));424Asm->emitLabelReference(std::get<1>(V), 4);425OS.emitInt32(std::get<2>(V));426}427}428429BTFTypeFloat::BTFTypeFloat(uint32_t SizeInBits, StringRef TypeName)430: Name(TypeName) {431Kind = BTF::BTF_KIND_FLOAT;432BTFType.Info = Kind << 24;433BTFType.Size = roundupToBytes(SizeInBits);434}435436void BTFTypeFloat::completeType(BTFDebug &BDebug) {437if (IsCompleted)438return;439IsCompleted = true;440441BTFType.NameOff = BDebug.addString(Name);442}443444BTFTypeDeclTag::BTFTypeDeclTag(uint32_t BaseTypeId, int ComponentIdx,445StringRef Tag)446: Tag(Tag) {447Kind = BTF::BTF_KIND_DECL_TAG;448BTFType.Info = Kind << 24;449BTFType.Type = BaseTypeId;450Info = ComponentIdx;451}452453void BTFTypeDeclTag::completeType(BTFDebug &BDebug) {454if (IsCompleted)455return;456IsCompleted = true;457458BTFType.NameOff = BDebug.addString(Tag);459}460461void BTFTypeDeclTag::emitType(MCStreamer &OS) {462BTFTypeBase::emitType(OS);463OS.emitInt32(Info);464}465466BTFTypeTypeTag::BTFTypeTypeTag(uint32_t NextTypeId, StringRef Tag)467: DTy(nullptr), Tag(Tag) {468Kind = BTF::BTF_KIND_TYPE_TAG;469BTFType.Info = Kind << 24;470BTFType.Type = NextTypeId;471}472473BTFTypeTypeTag::BTFTypeTypeTag(const DIDerivedType *DTy, StringRef Tag)474: DTy(DTy), Tag(Tag) {475Kind = BTF::BTF_KIND_TYPE_TAG;476BTFType.Info = Kind << 24;477}478479void BTFTypeTypeTag::completeType(BTFDebug &BDebug) {480if (IsCompleted)481return;482IsCompleted = true;483BTFType.NameOff = BDebug.addString(Tag);484if (DTy) {485const DIType *ResolvedType = DTy->getBaseType();486if (!ResolvedType)487BTFType.Type = 0;488else489BTFType.Type = BDebug.getTypeId(ResolvedType);490}491}492493uint32_t BTFStringTable::addString(StringRef S) {494// Check whether the string already exists.495for (auto &OffsetM : OffsetToIdMap) {496if (Table[OffsetM.second] == S)497return OffsetM.first;498}499// Not find, add to the string table.500uint32_t Offset = Size;501OffsetToIdMap[Offset] = Table.size();502Table.push_back(std::string(S));503Size += S.size() + 1;504return Offset;505}506507BTFDebug::BTFDebug(AsmPrinter *AP)508: DebugHandlerBase(AP), OS(*Asm->OutStreamer), SkipInstruction(false),509LineInfoGenerated(false), SecNameOff(0), ArrayIndexTypeId(0),510MapDefNotCollected(true) {511addString("\0");512}513514uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry,515const DIType *Ty) {516TypeEntry->setId(TypeEntries.size() + 1);517uint32_t Id = TypeEntry->getId();518DIToIdMap[Ty] = Id;519TypeEntries.push_back(std::move(TypeEntry));520return Id;521}522523uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry) {524TypeEntry->setId(TypeEntries.size() + 1);525uint32_t Id = TypeEntry->getId();526TypeEntries.push_back(std::move(TypeEntry));527return Id;528}529530void BTFDebug::visitBasicType(const DIBasicType *BTy, uint32_t &TypeId) {531// Only int and binary floating point types are supported in BTF.532uint32_t Encoding = BTy->getEncoding();533std::unique_ptr<BTFTypeBase> TypeEntry;534switch (Encoding) {535case dwarf::DW_ATE_boolean:536case dwarf::DW_ATE_signed:537case dwarf::DW_ATE_signed_char:538case dwarf::DW_ATE_unsigned:539case dwarf::DW_ATE_unsigned_char:540// Create a BTF type instance for this DIBasicType and put it into541// DIToIdMap for cross-type reference check.542TypeEntry = std::make_unique<BTFTypeInt>(543Encoding, BTy->getSizeInBits(), BTy->getOffsetInBits(), BTy->getName());544break;545case dwarf::DW_ATE_float:546TypeEntry =547std::make_unique<BTFTypeFloat>(BTy->getSizeInBits(), BTy->getName());548break;549default:550return;551}552553TypeId = addType(std::move(TypeEntry), BTy);554}555556/// Handle subprogram or subroutine types.557void BTFDebug::visitSubroutineType(558const DISubroutineType *STy, bool ForSubprog,559const std::unordered_map<uint32_t, StringRef> &FuncArgNames,560uint32_t &TypeId) {561DITypeRefArray Elements = STy->getTypeArray();562uint32_t VLen = Elements.size() - 1;563if (VLen > BTF::MAX_VLEN)564return;565566// Subprogram has a valid non-zero-length name, and the pointee of567// a function pointer has an empty name. The subprogram type will568// not be added to DIToIdMap as it should not be referenced by569// any other types.570auto TypeEntry = std::make_unique<BTFTypeFuncProto>(STy, VLen, FuncArgNames);571if (ForSubprog)572TypeId = addType(std::move(TypeEntry)); // For subprogram573else574TypeId = addType(std::move(TypeEntry), STy); // For func ptr575576// Visit return type and func arg types.577for (const auto Element : Elements) {578visitTypeEntry(Element);579}580}581582void BTFDebug::processDeclAnnotations(DINodeArray Annotations,583uint32_t BaseTypeId,584int ComponentIdx) {585if (!Annotations)586return;587588for (const Metadata *Annotation : Annotations->operands()) {589const MDNode *MD = cast<MDNode>(Annotation);590const MDString *Name = cast<MDString>(MD->getOperand(0));591if (Name->getString() != "btf_decl_tag")592continue;593594const MDString *Value = cast<MDString>(MD->getOperand(1));595auto TypeEntry = std::make_unique<BTFTypeDeclTag>(BaseTypeId, ComponentIdx,596Value->getString());597addType(std::move(TypeEntry));598}599}600601uint32_t BTFDebug::processDISubprogram(const DISubprogram *SP,602uint32_t ProtoTypeId, uint8_t Scope) {603auto FuncTypeEntry =604std::make_unique<BTFTypeFunc>(SP->getName(), ProtoTypeId, Scope);605uint32_t FuncId = addType(std::move(FuncTypeEntry));606607// Process argument annotations.608for (const DINode *DN : SP->getRetainedNodes()) {609if (const auto *DV = dyn_cast<DILocalVariable>(DN)) {610uint32_t Arg = DV->getArg();611if (Arg)612processDeclAnnotations(DV->getAnnotations(), FuncId, Arg - 1);613}614}615processDeclAnnotations(SP->getAnnotations(), FuncId, -1);616617return FuncId;618}619620/// Generate btf_type_tag chains.621int BTFDebug::genBTFTypeTags(const DIDerivedType *DTy, int BaseTypeId) {622SmallVector<const MDString *, 4> MDStrs;623DINodeArray Annots = DTy->getAnnotations();624if (Annots) {625// For type with "int __tag1 __tag2 *p", the MDStrs will have626// content: [__tag1, __tag2].627for (const Metadata *Annotations : Annots->operands()) {628const MDNode *MD = cast<MDNode>(Annotations);629const MDString *Name = cast<MDString>(MD->getOperand(0));630if (Name->getString() != "btf_type_tag")631continue;632MDStrs.push_back(cast<MDString>(MD->getOperand(1)));633}634}635636if (MDStrs.size() == 0)637return -1;638639// With MDStrs [__tag1, __tag2], the output type chain looks like640// PTR -> __tag2 -> __tag1 -> BaseType641// In the below, we construct BTF types with the order of __tag1, __tag2642// and PTR.643unsigned TmpTypeId;644std::unique_ptr<BTFTypeTypeTag> TypeEntry;645if (BaseTypeId >= 0)646TypeEntry =647std::make_unique<BTFTypeTypeTag>(BaseTypeId, MDStrs[0]->getString());648else649TypeEntry = std::make_unique<BTFTypeTypeTag>(DTy, MDStrs[0]->getString());650TmpTypeId = addType(std::move(TypeEntry));651652for (unsigned I = 1; I < MDStrs.size(); I++) {653const MDString *Value = MDStrs[I];654TypeEntry = std::make_unique<BTFTypeTypeTag>(TmpTypeId, Value->getString());655TmpTypeId = addType(std::move(TypeEntry));656}657return TmpTypeId;658}659660/// Handle structure/union types.661void BTFDebug::visitStructType(const DICompositeType *CTy, bool IsStruct,662uint32_t &TypeId) {663const DINodeArray Elements = CTy->getElements();664uint32_t VLen = Elements.size();665if (VLen > BTF::MAX_VLEN)666return;667668// Check whether we have any bitfield members or not669bool HasBitField = false;670for (const auto *Element : Elements) {671auto E = cast<DIDerivedType>(Element);672if (E->isBitField()) {673HasBitField = true;674break;675}676}677678auto TypeEntry =679std::make_unique<BTFTypeStruct>(CTy, IsStruct, HasBitField, VLen);680StructTypes.push_back(TypeEntry.get());681TypeId = addType(std::move(TypeEntry), CTy);682683// Check struct/union annotations684processDeclAnnotations(CTy->getAnnotations(), TypeId, -1);685686// Visit all struct members.687int FieldNo = 0;688for (const auto *Element : Elements) {689const auto Elem = cast<DIDerivedType>(Element);690visitTypeEntry(Elem);691processDeclAnnotations(Elem->getAnnotations(), TypeId, FieldNo);692FieldNo++;693}694}695696void BTFDebug::visitArrayType(const DICompositeType *CTy, uint32_t &TypeId) {697// Visit array element type.698uint32_t ElemTypeId;699const DIType *ElemType = CTy->getBaseType();700visitTypeEntry(ElemType, ElemTypeId, false, false);701702// Visit array dimensions.703DINodeArray Elements = CTy->getElements();704for (int I = Elements.size() - 1; I >= 0; --I) {705if (auto *Element = dyn_cast_or_null<DINode>(Elements[I]))706if (Element->getTag() == dwarf::DW_TAG_subrange_type) {707const DISubrange *SR = cast<DISubrange>(Element);708auto *CI = SR->getCount().dyn_cast<ConstantInt *>();709int64_t Count = CI->getSExtValue();710711// For struct s { int b; char c[]; }, the c[] will be represented712// as an array with Count = -1.713auto TypeEntry =714std::make_unique<BTFTypeArray>(ElemTypeId,715Count >= 0 ? Count : 0);716if (I == 0)717ElemTypeId = addType(std::move(TypeEntry), CTy);718else719ElemTypeId = addType(std::move(TypeEntry));720}721}722723// The array TypeId is the type id of the outermost dimension.724TypeId = ElemTypeId;725726// The IR does not have a type for array index while BTF wants one.727// So create an array index type if there is none.728if (!ArrayIndexTypeId) {729auto TypeEntry = std::make_unique<BTFTypeInt>(dwarf::DW_ATE_unsigned, 32,7300, "__ARRAY_SIZE_TYPE__");731ArrayIndexTypeId = addType(std::move(TypeEntry));732}733}734735void BTFDebug::visitEnumType(const DICompositeType *CTy, uint32_t &TypeId) {736DINodeArray Elements = CTy->getElements();737uint32_t VLen = Elements.size();738if (VLen > BTF::MAX_VLEN)739return;740741bool IsSigned = false;742unsigned NumBits = 32;743// No BaseType implies forward declaration in which case a744// BTFTypeEnum with Vlen = 0 is emitted.745if (CTy->getBaseType() != nullptr) {746const auto *BTy = cast<DIBasicType>(CTy->getBaseType());747IsSigned = BTy->getEncoding() == dwarf::DW_ATE_signed ||748BTy->getEncoding() == dwarf::DW_ATE_signed_char;749NumBits = BTy->getSizeInBits();750}751752if (NumBits <= 32) {753auto TypeEntry = std::make_unique<BTFTypeEnum>(CTy, VLen, IsSigned);754TypeId = addType(std::move(TypeEntry), CTy);755} else {756assert(NumBits == 64);757auto TypeEntry = std::make_unique<BTFTypeEnum64>(CTy, VLen, IsSigned);758TypeId = addType(std::move(TypeEntry), CTy);759}760// No need to visit base type as BTF does not encode it.761}762763/// Handle structure/union forward declarations.764void BTFDebug::visitFwdDeclType(const DICompositeType *CTy, bool IsUnion,765uint32_t &TypeId) {766auto TypeEntry = std::make_unique<BTFTypeFwd>(CTy->getName(), IsUnion);767TypeId = addType(std::move(TypeEntry), CTy);768}769770/// Handle structure, union, array and enumeration types.771void BTFDebug::visitCompositeType(const DICompositeType *CTy,772uint32_t &TypeId) {773auto Tag = CTy->getTag();774if (Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) {775// Handle forward declaration differently as it does not have members.776if (CTy->isForwardDecl())777visitFwdDeclType(CTy, Tag == dwarf::DW_TAG_union_type, TypeId);778else779visitStructType(CTy, Tag == dwarf::DW_TAG_structure_type, TypeId);780} else if (Tag == dwarf::DW_TAG_array_type)781visitArrayType(CTy, TypeId);782else if (Tag == dwarf::DW_TAG_enumeration_type)783visitEnumType(CTy, TypeId);784}785786bool BTFDebug::IsForwardDeclCandidate(const DIType *Base) {787if (const auto *CTy = dyn_cast<DICompositeType>(Base)) {788auto CTag = CTy->getTag();789if ((CTag == dwarf::DW_TAG_structure_type ||790CTag == dwarf::DW_TAG_union_type) &&791!CTy->getName().empty() && !CTy->isForwardDecl())792return true;793}794return false;795}796797/// Handle pointer, typedef, const, volatile, restrict and member types.798void BTFDebug::visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId,799bool CheckPointer, bool SeenPointer) {800unsigned Tag = DTy->getTag();801802/// Try to avoid chasing pointees, esp. structure pointees which may803/// unnecessary bring in a lot of types.804if (CheckPointer && !SeenPointer) {805SeenPointer = Tag == dwarf::DW_TAG_pointer_type;806}807808if (CheckPointer && SeenPointer) {809const DIType *Base = DTy->getBaseType();810if (Base) {811if (IsForwardDeclCandidate(Base)) {812/// Find a candidate, generate a fixup. Later on the struct/union813/// pointee type will be replaced with either a real type or814/// a forward declaration.815auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy, Tag, true);816auto &Fixup = FixupDerivedTypes[cast<DICompositeType>(Base)];817Fixup.push_back(std::make_pair(DTy, TypeEntry.get()));818TypeId = addType(std::move(TypeEntry), DTy);819return;820}821}822}823824if (Tag == dwarf::DW_TAG_pointer_type) {825int TmpTypeId = genBTFTypeTags(DTy, -1);826if (TmpTypeId >= 0) {827auto TypeDEntry =828std::make_unique<BTFTypeDerived>(TmpTypeId, Tag, DTy->getName());829TypeId = addType(std::move(TypeDEntry), DTy);830} else {831auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy, Tag, false);832TypeId = addType(std::move(TypeEntry), DTy);833}834} else if (Tag == dwarf::DW_TAG_typedef || Tag == dwarf::DW_TAG_const_type ||835Tag == dwarf::DW_TAG_volatile_type ||836Tag == dwarf::DW_TAG_restrict_type) {837auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy, Tag, false);838TypeId = addType(std::move(TypeEntry), DTy);839if (Tag == dwarf::DW_TAG_typedef)840processDeclAnnotations(DTy->getAnnotations(), TypeId, -1);841} else if (Tag != dwarf::DW_TAG_member) {842return;843}844845// Visit base type of pointer, typedef, const, volatile, restrict or846// struct/union member.847uint32_t TempTypeId = 0;848if (Tag == dwarf::DW_TAG_member)849visitTypeEntry(DTy->getBaseType(), TempTypeId, true, false);850else851visitTypeEntry(DTy->getBaseType(), TempTypeId, CheckPointer, SeenPointer);852}853854/// Visit a type entry. CheckPointer is true if the type has855/// one of its predecessors as one struct/union member. SeenPointer856/// is true if CheckPointer is true and one of its predecessors857/// is a pointer. The goal of CheckPointer and SeenPointer is to858/// do pruning for struct/union types so some of these types859/// will not be emitted in BTF and rather forward declarations860/// will be generated.861void BTFDebug::visitTypeEntry(const DIType *Ty, uint32_t &TypeId,862bool CheckPointer, bool SeenPointer) {863if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {864TypeId = DIToIdMap[Ty];865866// To handle the case like the following:867// struct t;868// typedef struct t _t;869// struct s1 { _t *c; };870// int test1(struct s1 *arg) { ... }871//872// struct t { int a; int b; };873// struct s2 { _t c; }874// int test2(struct s2 *arg) { ... }875//876// During traversing test1() argument, "_t" is recorded877// in DIToIdMap and a forward declaration fixup is created878// for "struct t" to avoid pointee type traversal.879//880// During traversing test2() argument, even if we see "_t" is881// already defined, we should keep moving to eventually882// bring in types for "struct t". Otherwise, the "struct s2"883// definition won't be correct.884//885// In the above, we have following debuginfo:886// {ptr, struct_member} -> typedef -> struct887// and BTF type for 'typedef' is generated while 'struct' may888// be in FixUp. But let us generalize the above to handle889// {different types} -> [various derived types]+ -> another type.890// For example,891// {func_param, struct_member} -> const -> ptr -> volatile -> struct892// We will traverse const/ptr/volatile which already have corresponding893// BTF types and generate type for 'struct' which might be in Fixup894// state.895if (Ty && (!CheckPointer || !SeenPointer)) {896if (const auto *DTy = dyn_cast<DIDerivedType>(Ty)) {897while (DTy) {898const DIType *BaseTy = DTy->getBaseType();899if (!BaseTy)900break;901902if (DIToIdMap.find(BaseTy) != DIToIdMap.end()) {903DTy = dyn_cast<DIDerivedType>(BaseTy);904} else {905if (CheckPointer && DTy->getTag() == dwarf::DW_TAG_pointer_type) {906SeenPointer = true;907if (IsForwardDeclCandidate(BaseTy))908break;909}910uint32_t TmpTypeId;911visitTypeEntry(BaseTy, TmpTypeId, CheckPointer, SeenPointer);912break;913}914}915}916}917918return;919}920921if (const auto *BTy = dyn_cast<DIBasicType>(Ty))922visitBasicType(BTy, TypeId);923else if (const auto *STy = dyn_cast<DISubroutineType>(Ty))924visitSubroutineType(STy, false, std::unordered_map<uint32_t, StringRef>(),925TypeId);926else if (const auto *CTy = dyn_cast<DICompositeType>(Ty))927visitCompositeType(CTy, TypeId);928else if (const auto *DTy = dyn_cast<DIDerivedType>(Ty))929visitDerivedType(DTy, TypeId, CheckPointer, SeenPointer);930else931llvm_unreachable("Unknown DIType");932}933934void BTFDebug::visitTypeEntry(const DIType *Ty) {935uint32_t TypeId;936visitTypeEntry(Ty, TypeId, false, false);937}938939void BTFDebug::visitMapDefType(const DIType *Ty, uint32_t &TypeId) {940if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {941TypeId = DIToIdMap[Ty];942return;943}944945// MapDef type may be a struct type or a non-pointer derived type946const DIType *OrigTy = Ty;947while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) {948auto Tag = DTy->getTag();949if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type &&950Tag != dwarf::DW_TAG_volatile_type &&951Tag != dwarf::DW_TAG_restrict_type)952break;953Ty = DTy->getBaseType();954}955956const auto *CTy = dyn_cast<DICompositeType>(Ty);957if (!CTy)958return;959960auto Tag = CTy->getTag();961if (Tag != dwarf::DW_TAG_structure_type || CTy->isForwardDecl())962return;963964// Visit all struct members to ensure pointee type is visited965const DINodeArray Elements = CTy->getElements();966for (const auto *Element : Elements) {967const auto *MemberType = cast<DIDerivedType>(Element);968visitTypeEntry(MemberType->getBaseType());969}970971// Visit this type, struct or a const/typedef/volatile/restrict type972visitTypeEntry(OrigTy, TypeId, false, false);973}974975/// Read file contents from the actual file or from the source976std::string BTFDebug::populateFileContent(const DIFile *File) {977std::string FileName;978979if (!File->getFilename().starts_with("/") && File->getDirectory().size())980FileName = File->getDirectory().str() + "/" + File->getFilename().str();981else982FileName = std::string(File->getFilename());983984// No need to populate the contends if it has been populated!985if (FileContent.contains(FileName))986return FileName;987988std::vector<std::string> Content;989std::string Line;990Content.push_back(Line); // Line 0 for empty string991992std::unique_ptr<MemoryBuffer> Buf;993auto Source = File->getSource();994if (Source)995Buf = MemoryBuffer::getMemBufferCopy(*Source);996else if (ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =997MemoryBuffer::getFile(FileName))998Buf = std::move(*BufOrErr);999if (Buf)1000for (line_iterator I(*Buf, false), E; I != E; ++I)1001Content.push_back(std::string(*I));10021003FileContent[FileName] = Content;1004return FileName;1005}10061007void BTFDebug::constructLineInfo(MCSymbol *Label, const DIFile *File,1008uint32_t Line, uint32_t Column) {1009std::string FileName = populateFileContent(File);1010BTFLineInfo LineInfo;10111012LineInfo.Label = Label;1013LineInfo.FileNameOff = addString(FileName);1014// If file content is not available, let LineOff = 0.1015if (Line < FileContent[FileName].size())1016LineInfo.LineOff = addString(FileContent[FileName][Line]);1017else1018LineInfo.LineOff = 0;1019LineInfo.LineNum = Line;1020LineInfo.ColumnNum = Column;1021LineInfoTable[SecNameOff].push_back(LineInfo);1022}10231024void BTFDebug::emitCommonHeader() {1025OS.AddComment("0x" + Twine::utohexstr(BTF::MAGIC));1026OS.emitIntValue(BTF::MAGIC, 2);1027OS.emitInt8(BTF::VERSION);1028OS.emitInt8(0);1029}10301031void BTFDebug::emitBTFSection() {1032// Do not emit section if no types and only "" string.1033if (!TypeEntries.size() && StringTable.getSize() == 1)1034return;10351036MCContext &Ctx = OS.getContext();1037MCSectionELF *Sec = Ctx.getELFSection(".BTF", ELF::SHT_PROGBITS, 0);1038Sec->setAlignment(Align(4));1039OS.switchSection(Sec);10401041// Emit header.1042emitCommonHeader();1043OS.emitInt32(BTF::HeaderSize);10441045uint32_t TypeLen = 0, StrLen;1046for (const auto &TypeEntry : TypeEntries)1047TypeLen += TypeEntry->getSize();1048StrLen = StringTable.getSize();10491050OS.emitInt32(0);1051OS.emitInt32(TypeLen);1052OS.emitInt32(TypeLen);1053OS.emitInt32(StrLen);10541055// Emit type table.1056for (const auto &TypeEntry : TypeEntries)1057TypeEntry->emitType(OS);10581059// Emit string table.1060uint32_t StringOffset = 0;1061for (const auto &S : StringTable.getTable()) {1062OS.AddComment("string offset=" + std::to_string(StringOffset));1063OS.emitBytes(S);1064OS.emitBytes(StringRef("\0", 1));1065StringOffset += S.size() + 1;1066}1067}10681069void BTFDebug::emitBTFExtSection() {1070// Do not emit section if empty FuncInfoTable and LineInfoTable1071// and FieldRelocTable.1072if (!FuncInfoTable.size() && !LineInfoTable.size() &&1073!FieldRelocTable.size())1074return;10751076MCContext &Ctx = OS.getContext();1077MCSectionELF *Sec = Ctx.getELFSection(".BTF.ext", ELF::SHT_PROGBITS, 0);1078Sec->setAlignment(Align(4));1079OS.switchSection(Sec);10801081// Emit header.1082emitCommonHeader();1083OS.emitInt32(BTF::ExtHeaderSize);10841085// Account for FuncInfo/LineInfo record size as well.1086uint32_t FuncLen = 4, LineLen = 4;1087// Do not account for optional FieldReloc.1088uint32_t FieldRelocLen = 0;1089for (const auto &FuncSec : FuncInfoTable) {1090FuncLen += BTF::SecFuncInfoSize;1091FuncLen += FuncSec.second.size() * BTF::BPFFuncInfoSize;1092}1093for (const auto &LineSec : LineInfoTable) {1094LineLen += BTF::SecLineInfoSize;1095LineLen += LineSec.second.size() * BTF::BPFLineInfoSize;1096}1097for (const auto &FieldRelocSec : FieldRelocTable) {1098FieldRelocLen += BTF::SecFieldRelocSize;1099FieldRelocLen += FieldRelocSec.second.size() * BTF::BPFFieldRelocSize;1100}11011102if (FieldRelocLen)1103FieldRelocLen += 4;11041105OS.emitInt32(0);1106OS.emitInt32(FuncLen);1107OS.emitInt32(FuncLen);1108OS.emitInt32(LineLen);1109OS.emitInt32(FuncLen + LineLen);1110OS.emitInt32(FieldRelocLen);11111112// Emit func_info table.1113OS.AddComment("FuncInfo");1114OS.emitInt32(BTF::BPFFuncInfoSize);1115for (const auto &FuncSec : FuncInfoTable) {1116OS.AddComment("FuncInfo section string offset=" +1117std::to_string(FuncSec.first));1118OS.emitInt32(FuncSec.first);1119OS.emitInt32(FuncSec.second.size());1120for (const auto &FuncInfo : FuncSec.second) {1121Asm->emitLabelReference(FuncInfo.Label, 4);1122OS.emitInt32(FuncInfo.TypeId);1123}1124}11251126// Emit line_info table.1127OS.AddComment("LineInfo");1128OS.emitInt32(BTF::BPFLineInfoSize);1129for (const auto &LineSec : LineInfoTable) {1130OS.AddComment("LineInfo section string offset=" +1131std::to_string(LineSec.first));1132OS.emitInt32(LineSec.first);1133OS.emitInt32(LineSec.second.size());1134for (const auto &LineInfo : LineSec.second) {1135Asm->emitLabelReference(LineInfo.Label, 4);1136OS.emitInt32(LineInfo.FileNameOff);1137OS.emitInt32(LineInfo.LineOff);1138OS.AddComment("Line " + std::to_string(LineInfo.LineNum) + " Col " +1139std::to_string(LineInfo.ColumnNum));1140OS.emitInt32(LineInfo.LineNum << 10 | LineInfo.ColumnNum);1141}1142}11431144// Emit field reloc table.1145if (FieldRelocLen) {1146OS.AddComment("FieldReloc");1147OS.emitInt32(BTF::BPFFieldRelocSize);1148for (const auto &FieldRelocSec : FieldRelocTable) {1149OS.AddComment("Field reloc section string offset=" +1150std::to_string(FieldRelocSec.first));1151OS.emitInt32(FieldRelocSec.first);1152OS.emitInt32(FieldRelocSec.second.size());1153for (const auto &FieldRelocInfo : FieldRelocSec.second) {1154Asm->emitLabelReference(FieldRelocInfo.Label, 4);1155OS.emitInt32(FieldRelocInfo.TypeID);1156OS.emitInt32(FieldRelocInfo.OffsetNameOff);1157OS.emitInt32(FieldRelocInfo.RelocKind);1158}1159}1160}1161}11621163void BTFDebug::beginFunctionImpl(const MachineFunction *MF) {1164auto *SP = MF->getFunction().getSubprogram();1165auto *Unit = SP->getUnit();11661167if (Unit->getEmissionKind() == DICompileUnit::NoDebug) {1168SkipInstruction = true;1169return;1170}1171SkipInstruction = false;11721173// Collect MapDef types. Map definition needs to collect1174// pointee types. Do it first. Otherwise, for the following1175// case:1176// struct m { ...};1177// struct t {1178// struct m *key;1179// };1180// foo(struct t *arg);1181//1182// struct mapdef {1183// ...1184// struct m *key;1185// ...1186// } __attribute__((section(".maps"))) hash_map;1187//1188// If subroutine foo is traversed first, a type chain1189// "ptr->struct m(fwd)" will be created and later on1190// when traversing mapdef, since "ptr->struct m" exists,1191// the traversal of "struct m" will be omitted.1192if (MapDefNotCollected) {1193processGlobals(true);1194MapDefNotCollected = false;1195}11961197// Collect all types locally referenced in this function.1198// Use RetainedNodes so we can collect all argument names1199// even if the argument is not used.1200std::unordered_map<uint32_t, StringRef> FuncArgNames;1201for (const DINode *DN : SP->getRetainedNodes()) {1202if (const auto *DV = dyn_cast<DILocalVariable>(DN)) {1203// Collect function arguments for subprogram func type.1204uint32_t Arg = DV->getArg();1205if (Arg) {1206visitTypeEntry(DV->getType());1207FuncArgNames[Arg] = DV->getName();1208}1209}1210}12111212// Construct subprogram func proto type.1213uint32_t ProtoTypeId;1214visitSubroutineType(SP->getType(), true, FuncArgNames, ProtoTypeId);12151216// Construct subprogram func type1217uint8_t Scope = SP->isLocalToUnit() ? BTF::FUNC_STATIC : BTF::FUNC_GLOBAL;1218uint32_t FuncTypeId = processDISubprogram(SP, ProtoTypeId, Scope);12191220for (const auto &TypeEntry : TypeEntries)1221TypeEntry->completeType(*this);12221223// Construct funcinfo and the first lineinfo for the function.1224MCSymbol *FuncLabel = Asm->getFunctionBegin();1225BTFFuncInfo FuncInfo;1226FuncInfo.Label = FuncLabel;1227FuncInfo.TypeId = FuncTypeId;1228if (FuncLabel->isInSection()) {1229MCSection &Section = FuncLabel->getSection();1230const MCSectionELF *SectionELF = dyn_cast<MCSectionELF>(&Section);1231assert(SectionELF && "Null section for Function Label");1232SecNameOff = addString(SectionELF->getName());1233} else {1234SecNameOff = addString(".text");1235}1236FuncInfoTable[SecNameOff].push_back(FuncInfo);1237}12381239void BTFDebug::endFunctionImpl(const MachineFunction *MF) {1240SkipInstruction = false;1241LineInfoGenerated = false;1242SecNameOff = 0;1243}12441245/// On-demand populate types as requested from abstract member1246/// accessing or preserve debuginfo type.1247unsigned BTFDebug::populateType(const DIType *Ty) {1248unsigned Id;1249visitTypeEntry(Ty, Id, false, false);1250for (const auto &TypeEntry : TypeEntries)1251TypeEntry->completeType(*this);1252return Id;1253}12541255/// Generate a struct member field relocation.1256void BTFDebug::generatePatchImmReloc(const MCSymbol *ORSym, uint32_t RootId,1257const GlobalVariable *GVar, bool IsAma) {1258BTFFieldReloc FieldReloc;1259FieldReloc.Label = ORSym;1260FieldReloc.TypeID = RootId;12611262StringRef AccessPattern = GVar->getName();1263size_t FirstDollar = AccessPattern.find_first_of('$');1264if (IsAma) {1265size_t FirstColon = AccessPattern.find_first_of(':');1266size_t SecondColon = AccessPattern.find_first_of(':', FirstColon + 1);1267StringRef IndexPattern = AccessPattern.substr(FirstDollar + 1);1268StringRef RelocKindStr = AccessPattern.substr(FirstColon + 1,1269SecondColon - FirstColon);1270StringRef PatchImmStr = AccessPattern.substr(SecondColon + 1,1271FirstDollar - SecondColon);12721273FieldReloc.OffsetNameOff = addString(IndexPattern);1274FieldReloc.RelocKind = std::stoull(std::string(RelocKindStr));1275PatchImms[GVar] = std::make_pair(std::stoll(std::string(PatchImmStr)),1276FieldReloc.RelocKind);1277} else {1278StringRef RelocStr = AccessPattern.substr(FirstDollar + 1);1279FieldReloc.OffsetNameOff = addString("0");1280FieldReloc.RelocKind = std::stoull(std::string(RelocStr));1281PatchImms[GVar] = std::make_pair(RootId, FieldReloc.RelocKind);1282}1283FieldRelocTable[SecNameOff].push_back(FieldReloc);1284}12851286void BTFDebug::processGlobalValue(const MachineOperand &MO) {1287// check whether this is a candidate or not1288if (MO.isGlobal()) {1289const GlobalValue *GVal = MO.getGlobal();1290auto *GVar = dyn_cast<GlobalVariable>(GVal);1291if (!GVar) {1292// Not a global variable. Maybe an extern function reference.1293processFuncPrototypes(dyn_cast<Function>(GVal));1294return;1295}12961297if (!GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr) &&1298!GVar->hasAttribute(BPFCoreSharedInfo::TypeIdAttr))1299return;13001301MCSymbol *ORSym = OS.getContext().createTempSymbol();1302OS.emitLabel(ORSym);13031304MDNode *MDN = GVar->getMetadata(LLVMContext::MD_preserve_access_index);1305uint32_t RootId = populateType(dyn_cast<DIType>(MDN));1306generatePatchImmReloc(ORSym, RootId, GVar,1307GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr));1308}1309}13101311void BTFDebug::beginInstruction(const MachineInstr *MI) {1312DebugHandlerBase::beginInstruction(MI);13131314if (SkipInstruction || MI->isMetaInstruction() ||1315MI->getFlag(MachineInstr::FrameSetup))1316return;13171318if (MI->isInlineAsm()) {1319// Count the number of register definitions to find the asm string.1320unsigned NumDefs = 0;1321while (true) {1322const MachineOperand &MO = MI->getOperand(NumDefs);1323if (MO.isReg() && MO.isDef()) {1324++NumDefs;1325continue;1326}1327// Skip this inline asm instruction if the asmstr is empty.1328const char *AsmStr = MO.getSymbolName();1329if (AsmStr[0] == 0)1330return;1331break;1332}1333}13341335if (MI->getOpcode() == BPF::LD_imm64) {1336// If the insn is "r2 = LD_imm64 @<an AmaAttr global>",1337// add this insn into the .BTF.ext FieldReloc subsection.1338// Relocation looks like:1339// . SecName:1340// . InstOffset1341// . TypeID1342// . OffSetNameOff1343// . RelocType1344// Later, the insn is replaced with "r2 = <offset>"1345// where "<offset>" equals to the offset based on current1346// type definitions.1347//1348// If the insn is "r2 = LD_imm64 @<an TypeIdAttr global>",1349// The LD_imm64 result will be replaced with a btf type id.1350processGlobalValue(MI->getOperand(1));1351} else if (MI->getOpcode() == BPF::CORE_LD64 ||1352MI->getOpcode() == BPF::CORE_LD32 ||1353MI->getOpcode() == BPF::CORE_ST ||1354MI->getOpcode() == BPF::CORE_SHIFT) {1355// relocation insn is a load, store or shift insn.1356processGlobalValue(MI->getOperand(3));1357} else if (MI->getOpcode() == BPF::JAL) {1358// check extern function references1359const MachineOperand &MO = MI->getOperand(0);1360if (MO.isGlobal()) {1361processFuncPrototypes(dyn_cast<Function>(MO.getGlobal()));1362}1363}13641365if (!CurMI) // no debug info1366return;13671368// Skip this instruction if no DebugLoc, the DebugLoc1369// is the same as the previous instruction or Line is 0.1370const DebugLoc &DL = MI->getDebugLoc();1371if (!DL || PrevInstLoc == DL || DL.getLine() == 0) {1372// This instruction will be skipped, no LineInfo has1373// been generated, construct one based on function signature.1374if (LineInfoGenerated == false) {1375auto *S = MI->getMF()->getFunction().getSubprogram();1376if (!S)1377return;1378MCSymbol *FuncLabel = Asm->getFunctionBegin();1379constructLineInfo(FuncLabel, S->getFile(), S->getLine(), 0);1380LineInfoGenerated = true;1381}13821383return;1384}13851386// Create a temporary label to remember the insn for lineinfo.1387MCSymbol *LineSym = OS.getContext().createTempSymbol();1388OS.emitLabel(LineSym);13891390// Construct the lineinfo.1391constructLineInfo(LineSym, DL->getFile(), DL.getLine(), DL.getCol());13921393LineInfoGenerated = true;1394PrevInstLoc = DL;1395}13961397void BTFDebug::processGlobals(bool ProcessingMapDef) {1398// Collect all types referenced by globals.1399const Module *M = MMI->getModule();1400for (const GlobalVariable &Global : M->globals()) {1401// Decide the section name.1402StringRef SecName;1403std::optional<SectionKind> GVKind;14041405if (!Global.isDeclarationForLinker())1406GVKind = TargetLoweringObjectFile::getKindForGlobal(&Global, Asm->TM);14071408if (Global.isDeclarationForLinker())1409SecName = Global.hasSection() ? Global.getSection() : "";1410else if (GVKind->isCommon())1411SecName = ".bss";1412else {1413TargetLoweringObjectFile *TLOF = Asm->TM.getObjFileLowering();1414MCSection *Sec = TLOF->SectionForGlobal(&Global, Asm->TM);1415SecName = Sec->getName();1416}14171418if (ProcessingMapDef != SecName.starts_with(".maps"))1419continue;14201421// Create a .rodata datasec if the global variable is an initialized1422// constant with private linkage and if it won't be in .rodata.str<#>1423// and .rodata.cst<#> sections.1424if (SecName == ".rodata" && Global.hasPrivateLinkage() &&1425DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {1426// skip .rodata.str<#> and .rodata.cst<#> sections1427if (!GVKind->isMergeableCString() && !GVKind->isMergeableConst()) {1428DataSecEntries[std::string(SecName)] =1429std::make_unique<BTFKindDataSec>(Asm, std::string(SecName));1430}1431}14321433SmallVector<DIGlobalVariableExpression *, 1> GVs;1434Global.getDebugInfo(GVs);14351436// No type information, mostly internal, skip it.1437if (GVs.size() == 0)1438continue;14391440uint32_t GVTypeId = 0;1441DIGlobalVariable *DIGlobal = nullptr;1442for (auto *GVE : GVs) {1443DIGlobal = GVE->getVariable();1444if (SecName.starts_with(".maps"))1445visitMapDefType(DIGlobal->getType(), GVTypeId);1446else1447visitTypeEntry(DIGlobal->getType(), GVTypeId, false, false);1448break;1449}14501451// Only support the following globals:1452// . static variables1453// . non-static weak or non-weak global variables1454// . weak or non-weak extern global variables1455// Whether DataSec is readonly or not can be found from corresponding ELF1456// section flags. Whether a BTF_KIND_VAR is a weak symbol or not1457// can be found from the corresponding ELF symbol table.1458auto Linkage = Global.getLinkage();1459if (Linkage != GlobalValue::InternalLinkage &&1460Linkage != GlobalValue::ExternalLinkage &&1461Linkage != GlobalValue::WeakAnyLinkage &&1462Linkage != GlobalValue::WeakODRLinkage &&1463Linkage != GlobalValue::ExternalWeakLinkage)1464continue;14651466uint32_t GVarInfo;1467if (Linkage == GlobalValue::InternalLinkage) {1468GVarInfo = BTF::VAR_STATIC;1469} else if (Global.hasInitializer()) {1470GVarInfo = BTF::VAR_GLOBAL_ALLOCATED;1471} else {1472GVarInfo = BTF::VAR_GLOBAL_EXTERNAL;1473}14741475auto VarEntry =1476std::make_unique<BTFKindVar>(Global.getName(), GVTypeId, GVarInfo);1477uint32_t VarId = addType(std::move(VarEntry));14781479processDeclAnnotations(DIGlobal->getAnnotations(), VarId, -1);14801481// An empty SecName means an extern variable without section attribute.1482if (SecName.empty())1483continue;14841485// Find or create a DataSec1486if (DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {1487DataSecEntries[std::string(SecName)] =1488std::make_unique<BTFKindDataSec>(Asm, std::string(SecName));1489}14901491// Calculate symbol size1492const DataLayout &DL = Global.getDataLayout();1493uint32_t Size = DL.getTypeAllocSize(Global.getValueType());14941495DataSecEntries[std::string(SecName)]->addDataSecEntry(VarId,1496Asm->getSymbol(&Global), Size);14971498if (Global.hasInitializer())1499processGlobalInitializer(Global.getInitializer());1500}1501}15021503/// Process global variable initializer in pursuit for function1504/// pointers. Add discovered (extern) functions to BTF. Some (extern)1505/// functions might have been missed otherwise. Every symbol needs BTF1506/// info when linking with bpftool. Primary use case: "static"1507/// initialization of BPF maps.1508///1509/// struct {1510/// __uint(type, BPF_MAP_TYPE_PROG_ARRAY);1511/// ...1512/// } prog_map SEC(".maps") = { .values = { extern_func } };1513///1514void BTFDebug::processGlobalInitializer(const Constant *C) {1515if (auto *Fn = dyn_cast<Function>(C))1516processFuncPrototypes(Fn);1517if (auto *CA = dyn_cast<ConstantAggregate>(C)) {1518for (unsigned I = 0, N = CA->getNumOperands(); I < N; ++I)1519processGlobalInitializer(CA->getOperand(I));1520}1521}15221523/// Emit proper patchable instructions.1524bool BTFDebug::InstLower(const MachineInstr *MI, MCInst &OutMI) {1525if (MI->getOpcode() == BPF::LD_imm64) {1526const MachineOperand &MO = MI->getOperand(1);1527if (MO.isGlobal()) {1528const GlobalValue *GVal = MO.getGlobal();1529auto *GVar = dyn_cast<GlobalVariable>(GVal);1530if (GVar) {1531// Emit "mov ri, <imm>"1532int64_t Imm;1533uint32_t Reloc;1534if (GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr) ||1535GVar->hasAttribute(BPFCoreSharedInfo::TypeIdAttr)) {1536Imm = PatchImms[GVar].first;1537Reloc = PatchImms[GVar].second;1538} else {1539return false;1540}15411542if (Reloc == BTF::ENUM_VALUE_EXISTENCE || Reloc == BTF::ENUM_VALUE ||1543Reloc == BTF::BTF_TYPE_ID_LOCAL || Reloc == BTF::BTF_TYPE_ID_REMOTE)1544OutMI.setOpcode(BPF::LD_imm64);1545else1546OutMI.setOpcode(BPF::MOV_ri);1547OutMI.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));1548OutMI.addOperand(MCOperand::createImm(Imm));1549return true;1550}1551}1552} else if (MI->getOpcode() == BPF::CORE_LD64 ||1553MI->getOpcode() == BPF::CORE_LD32 ||1554MI->getOpcode() == BPF::CORE_ST ||1555MI->getOpcode() == BPF::CORE_SHIFT) {1556const MachineOperand &MO = MI->getOperand(3);1557if (MO.isGlobal()) {1558const GlobalValue *GVal = MO.getGlobal();1559auto *GVar = dyn_cast<GlobalVariable>(GVal);1560if (GVar && GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) {1561uint32_t Imm = PatchImms[GVar].first;1562OutMI.setOpcode(MI->getOperand(1).getImm());1563if (MI->getOperand(0).isImm())1564OutMI.addOperand(MCOperand::createImm(MI->getOperand(0).getImm()));1565else1566OutMI.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));1567OutMI.addOperand(MCOperand::createReg(MI->getOperand(2).getReg()));1568OutMI.addOperand(MCOperand::createImm(Imm));1569return true;1570}1571}1572}1573return false;1574}15751576void BTFDebug::processFuncPrototypes(const Function *F) {1577if (!F)1578return;15791580const DISubprogram *SP = F->getSubprogram();1581if (!SP || SP->isDefinition())1582return;15831584// Do not emit again if already emitted.1585if (!ProtoFunctions.insert(F).second)1586return;15871588uint32_t ProtoTypeId;1589const std::unordered_map<uint32_t, StringRef> FuncArgNames;1590visitSubroutineType(SP->getType(), false, FuncArgNames, ProtoTypeId);1591uint32_t FuncId = processDISubprogram(SP, ProtoTypeId, BTF::FUNC_EXTERN);15921593if (F->hasSection()) {1594StringRef SecName = F->getSection();15951596if (DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {1597DataSecEntries[std::string(SecName)] =1598std::make_unique<BTFKindDataSec>(Asm, std::string(SecName));1599}16001601// We really don't know func size, set it to 0.1602DataSecEntries[std::string(SecName)]->addDataSecEntry(FuncId,1603Asm->getSymbol(F), 0);1604}1605}16061607void BTFDebug::endModule() {1608// Collect MapDef globals if not collected yet.1609if (MapDefNotCollected) {1610processGlobals(true);1611MapDefNotCollected = false;1612}16131614// Collect global types/variables except MapDef globals.1615processGlobals(false);16161617for (auto &DataSec : DataSecEntries)1618addType(std::move(DataSec.second));16191620// Fixups1621for (auto &Fixup : FixupDerivedTypes) {1622const DICompositeType *CTy = Fixup.first;1623StringRef TypeName = CTy->getName();1624bool IsUnion = CTy->getTag() == dwarf::DW_TAG_union_type;16251626// Search through struct types1627uint32_t StructTypeId = 0;1628for (const auto &StructType : StructTypes) {1629if (StructType->getName() == TypeName) {1630StructTypeId = StructType->getId();1631break;1632}1633}16341635if (StructTypeId == 0) {1636auto FwdTypeEntry = std::make_unique<BTFTypeFwd>(TypeName, IsUnion);1637StructTypeId = addType(std::move(FwdTypeEntry));1638}16391640for (auto &TypeInfo : Fixup.second) {1641const DIDerivedType *DTy = TypeInfo.first;1642BTFTypeDerived *BDType = TypeInfo.second;16431644int TmpTypeId = genBTFTypeTags(DTy, StructTypeId);1645if (TmpTypeId >= 0)1646BDType->setPointeeType(TmpTypeId);1647else1648BDType->setPointeeType(StructTypeId);1649}1650}16511652// Complete BTF type cross refereences.1653for (const auto &TypeEntry : TypeEntries)1654TypeEntry->completeType(*this);16551656// Emit BTF sections.1657emitBTFSection();1658emitBTFExtSection();1659}166016611662