10b57cec5SDimitry Andric //===- BTFDebug.cpp - BTF Generator ---------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains support for writing BTF debug info. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "BTFDebug.h" 140b57cec5SDimitry Andric #include "BPF.h" 150b57cec5SDimitry Andric #include "BPFCORE.h" 160b57cec5SDimitry Andric #include "MCTargetDesc/BPFMCTargetDesc.h" 170b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 180b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h" 205f757f3fSDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 21*0fca6ea1SDimitry Andric #include "llvm/IR/Module.h" 220b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 230b57cec5SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h" 240b57cec5SDimitry Andric #include "llvm/MC/MCSectionELF.h" 250b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 260b57cec5SDimitry Andric #include "llvm/Support/LineIterator.h" 2781ad6265SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 28e8d8bef9SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h" 29bdd1243dSDimitry Andric #include <optional> 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric using namespace llvm; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric static const char *BTFKindStr[] = { 340b57cec5SDimitry Andric #define HANDLE_BTF_KIND(ID, NAME) "BTF_KIND_" #NAME, 3506c3fb27SDimitry Andric #include "llvm/DebugInfo/BTF/BTF.def" 360b57cec5SDimitry Andric }; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric /// Emit a BTF common type. 390b57cec5SDimitry Andric void BTFTypeBase::emitType(MCStreamer &OS) { 400b57cec5SDimitry Andric OS.AddComment(std::string(BTFKindStr[Kind]) + "(id = " + std::to_string(Id) + 410b57cec5SDimitry Andric ")"); 425ffd83dbSDimitry Andric OS.emitInt32(BTFType.NameOff); 430b57cec5SDimitry Andric OS.AddComment("0x" + Twine::utohexstr(BTFType.Info)); 445ffd83dbSDimitry Andric OS.emitInt32(BTFType.Info); 455ffd83dbSDimitry Andric OS.emitInt32(BTFType.Size); 460b57cec5SDimitry Andric } 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric BTFTypeDerived::BTFTypeDerived(const DIDerivedType *DTy, unsigned Tag, 490b57cec5SDimitry Andric bool NeedsFixup) 50349cc55cSDimitry Andric : DTy(DTy), NeedsFixup(NeedsFixup), Name(DTy->getName()) { 510b57cec5SDimitry Andric switch (Tag) { 520b57cec5SDimitry Andric case dwarf::DW_TAG_pointer_type: 530b57cec5SDimitry Andric Kind = BTF::BTF_KIND_PTR; 540b57cec5SDimitry Andric break; 550b57cec5SDimitry Andric case dwarf::DW_TAG_const_type: 560b57cec5SDimitry Andric Kind = BTF::BTF_KIND_CONST; 570b57cec5SDimitry Andric break; 580b57cec5SDimitry Andric case dwarf::DW_TAG_volatile_type: 590b57cec5SDimitry Andric Kind = BTF::BTF_KIND_VOLATILE; 600b57cec5SDimitry Andric break; 610b57cec5SDimitry Andric case dwarf::DW_TAG_typedef: 620b57cec5SDimitry Andric Kind = BTF::BTF_KIND_TYPEDEF; 630b57cec5SDimitry Andric break; 640b57cec5SDimitry Andric case dwarf::DW_TAG_restrict_type: 650b57cec5SDimitry Andric Kind = BTF::BTF_KIND_RESTRICT; 660b57cec5SDimitry Andric break; 670b57cec5SDimitry Andric default: 680b57cec5SDimitry Andric llvm_unreachable("Unknown DIDerivedType Tag"); 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric BTFType.Info = Kind << 24; 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric 73349cc55cSDimitry Andric /// Used by DW_TAG_pointer_type only. 74349cc55cSDimitry Andric BTFTypeDerived::BTFTypeDerived(unsigned NextTypeId, unsigned Tag, 75349cc55cSDimitry Andric StringRef Name) 76349cc55cSDimitry Andric : DTy(nullptr), NeedsFixup(false), Name(Name) { 77349cc55cSDimitry Andric Kind = BTF::BTF_KIND_PTR; 78349cc55cSDimitry Andric BTFType.Info = Kind << 24; 79349cc55cSDimitry Andric BTFType.Type = NextTypeId; 80349cc55cSDimitry Andric } 81349cc55cSDimitry Andric 820b57cec5SDimitry Andric void BTFTypeDerived::completeType(BTFDebug &BDebug) { 830b57cec5SDimitry Andric if (IsCompleted) 840b57cec5SDimitry Andric return; 850b57cec5SDimitry Andric IsCompleted = true; 860b57cec5SDimitry Andric 87349cc55cSDimitry Andric BTFType.NameOff = BDebug.addString(Name); 880b57cec5SDimitry Andric 89349cc55cSDimitry Andric if (NeedsFixup || !DTy) 900b57cec5SDimitry Andric return; 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric // The base type for PTR/CONST/VOLATILE could be void. 930b57cec5SDimitry Andric const DIType *ResolvedType = DTy->getBaseType(); 940b57cec5SDimitry Andric if (!ResolvedType) { 950b57cec5SDimitry Andric assert((Kind == BTF::BTF_KIND_PTR || Kind == BTF::BTF_KIND_CONST || 960b57cec5SDimitry Andric Kind == BTF::BTF_KIND_VOLATILE) && 970b57cec5SDimitry Andric "Invalid null basetype"); 980b57cec5SDimitry Andric BTFType.Type = 0; 990b57cec5SDimitry Andric } else { 1000b57cec5SDimitry Andric BTFType.Type = BDebug.getTypeId(ResolvedType); 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric void BTFTypeDerived::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); } 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric void BTFTypeDerived::setPointeeType(uint32_t PointeeType) { 1070b57cec5SDimitry Andric BTFType.Type = PointeeType; 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric /// Represent a struct/union forward declaration. 1110b57cec5SDimitry Andric BTFTypeFwd::BTFTypeFwd(StringRef Name, bool IsUnion) : Name(Name) { 1120b57cec5SDimitry Andric Kind = BTF::BTF_KIND_FWD; 1130b57cec5SDimitry Andric BTFType.Info = IsUnion << 31 | Kind << 24; 1140b57cec5SDimitry Andric BTFType.Type = 0; 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric void BTFTypeFwd::completeType(BTFDebug &BDebug) { 1180b57cec5SDimitry Andric if (IsCompleted) 1190b57cec5SDimitry Andric return; 1200b57cec5SDimitry Andric IsCompleted = true; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric BTFType.NameOff = BDebug.addString(Name); 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric void BTFTypeFwd::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); } 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric BTFTypeInt::BTFTypeInt(uint32_t Encoding, uint32_t SizeInBits, 1280b57cec5SDimitry Andric uint32_t OffsetInBits, StringRef TypeName) 1290b57cec5SDimitry Andric : Name(TypeName) { 1300b57cec5SDimitry Andric // Translate IR int encoding to BTF int encoding. 1310b57cec5SDimitry Andric uint8_t BTFEncoding; 1320b57cec5SDimitry Andric switch (Encoding) { 1330b57cec5SDimitry Andric case dwarf::DW_ATE_boolean: 1340b57cec5SDimitry Andric BTFEncoding = BTF::INT_BOOL; 1350b57cec5SDimitry Andric break; 1360b57cec5SDimitry Andric case dwarf::DW_ATE_signed: 1370b57cec5SDimitry Andric case dwarf::DW_ATE_signed_char: 1380b57cec5SDimitry Andric BTFEncoding = BTF::INT_SIGNED; 1390b57cec5SDimitry Andric break; 1400b57cec5SDimitry Andric case dwarf::DW_ATE_unsigned: 1410b57cec5SDimitry Andric case dwarf::DW_ATE_unsigned_char: 1420b57cec5SDimitry Andric BTFEncoding = 0; 1430b57cec5SDimitry Andric break; 1440b57cec5SDimitry Andric default: 1450b57cec5SDimitry Andric llvm_unreachable("Unknown BTFTypeInt Encoding"); 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric Kind = BTF::BTF_KIND_INT; 1490b57cec5SDimitry Andric BTFType.Info = Kind << 24; 1500b57cec5SDimitry Andric BTFType.Size = roundupToBytes(SizeInBits); 1510b57cec5SDimitry Andric IntVal = (BTFEncoding << 24) | OffsetInBits << 16 | SizeInBits; 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric void BTFTypeInt::completeType(BTFDebug &BDebug) { 1550b57cec5SDimitry Andric if (IsCompleted) 1560b57cec5SDimitry Andric return; 1570b57cec5SDimitry Andric IsCompleted = true; 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric BTFType.NameOff = BDebug.addString(Name); 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric void BTFTypeInt::emitType(MCStreamer &OS) { 1630b57cec5SDimitry Andric BTFTypeBase::emitType(OS); 1640b57cec5SDimitry Andric OS.AddComment("0x" + Twine::utohexstr(IntVal)); 1655ffd83dbSDimitry Andric OS.emitInt32(IntVal); 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric 16881ad6265SDimitry Andric BTFTypeEnum::BTFTypeEnum(const DICompositeType *ETy, uint32_t VLen, 16981ad6265SDimitry Andric bool IsSigned) : ETy(ETy) { 1700b57cec5SDimitry Andric Kind = BTF::BTF_KIND_ENUM; 17181ad6265SDimitry Andric BTFType.Info = IsSigned << 31 | Kind << 24 | VLen; 1720b57cec5SDimitry Andric BTFType.Size = roundupToBytes(ETy->getSizeInBits()); 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric void BTFTypeEnum::completeType(BTFDebug &BDebug) { 1760b57cec5SDimitry Andric if (IsCompleted) 1770b57cec5SDimitry Andric return; 1780b57cec5SDimitry Andric IsCompleted = true; 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric BTFType.NameOff = BDebug.addString(ETy->getName()); 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric DINodeArray Elements = ETy->getElements(); 1830b57cec5SDimitry Andric for (const auto Element : Elements) { 1840b57cec5SDimitry Andric const auto *Enum = cast<DIEnumerator>(Element); 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric struct BTF::BTFEnum BTFEnum; 1870b57cec5SDimitry Andric BTFEnum.NameOff = BDebug.addString(Enum->getName()); 1880b57cec5SDimitry Andric // BTF enum value is 32bit, enforce it. 1895ffd83dbSDimitry Andric uint32_t Value; 1905ffd83dbSDimitry Andric if (Enum->isUnsigned()) 1915ffd83dbSDimitry Andric Value = static_cast<uint32_t>(Enum->getValue().getZExtValue()); 1925ffd83dbSDimitry Andric else 1935ffd83dbSDimitry Andric Value = static_cast<uint32_t>(Enum->getValue().getSExtValue()); 1945ffd83dbSDimitry Andric BTFEnum.Val = Value; 1950b57cec5SDimitry Andric EnumValues.push_back(BTFEnum); 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric void BTFTypeEnum::emitType(MCStreamer &OS) { 2000b57cec5SDimitry Andric BTFTypeBase::emitType(OS); 2010b57cec5SDimitry Andric for (const auto &Enum : EnumValues) { 2025ffd83dbSDimitry Andric OS.emitInt32(Enum.NameOff); 2035ffd83dbSDimitry Andric OS.emitInt32(Enum.Val); 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric 20781ad6265SDimitry Andric BTFTypeEnum64::BTFTypeEnum64(const DICompositeType *ETy, uint32_t VLen, 20881ad6265SDimitry Andric bool IsSigned) : ETy(ETy) { 20981ad6265SDimitry Andric Kind = BTF::BTF_KIND_ENUM64; 21081ad6265SDimitry Andric BTFType.Info = IsSigned << 31 | Kind << 24 | VLen; 21181ad6265SDimitry Andric BTFType.Size = roundupToBytes(ETy->getSizeInBits()); 21281ad6265SDimitry Andric } 21381ad6265SDimitry Andric 21481ad6265SDimitry Andric void BTFTypeEnum64::completeType(BTFDebug &BDebug) { 21581ad6265SDimitry Andric if (IsCompleted) 21681ad6265SDimitry Andric return; 21781ad6265SDimitry Andric IsCompleted = true; 21881ad6265SDimitry Andric 21981ad6265SDimitry Andric BTFType.NameOff = BDebug.addString(ETy->getName()); 22081ad6265SDimitry Andric 22181ad6265SDimitry Andric DINodeArray Elements = ETy->getElements(); 22281ad6265SDimitry Andric for (const auto Element : Elements) { 22381ad6265SDimitry Andric const auto *Enum = cast<DIEnumerator>(Element); 22481ad6265SDimitry Andric 22581ad6265SDimitry Andric struct BTF::BTFEnum64 BTFEnum; 22681ad6265SDimitry Andric BTFEnum.NameOff = BDebug.addString(Enum->getName()); 22781ad6265SDimitry Andric uint64_t Value; 22881ad6265SDimitry Andric if (Enum->isUnsigned()) 22981ad6265SDimitry Andric Value = static_cast<uint64_t>(Enum->getValue().getZExtValue()); 23081ad6265SDimitry Andric else 23181ad6265SDimitry Andric Value = static_cast<uint64_t>(Enum->getValue().getSExtValue()); 23281ad6265SDimitry Andric BTFEnum.Val_Lo32 = Value; 23381ad6265SDimitry Andric BTFEnum.Val_Hi32 = Value >> 32; 23481ad6265SDimitry Andric EnumValues.push_back(BTFEnum); 23581ad6265SDimitry Andric } 23681ad6265SDimitry Andric } 23781ad6265SDimitry Andric 23881ad6265SDimitry Andric void BTFTypeEnum64::emitType(MCStreamer &OS) { 23981ad6265SDimitry Andric BTFTypeBase::emitType(OS); 24081ad6265SDimitry Andric for (const auto &Enum : EnumValues) { 24181ad6265SDimitry Andric OS.emitInt32(Enum.NameOff); 24281ad6265SDimitry Andric OS.AddComment("0x" + Twine::utohexstr(Enum.Val_Lo32)); 24381ad6265SDimitry Andric OS.emitInt32(Enum.Val_Lo32); 24481ad6265SDimitry Andric OS.AddComment("0x" + Twine::utohexstr(Enum.Val_Hi32)); 24581ad6265SDimitry Andric OS.emitInt32(Enum.Val_Hi32); 24681ad6265SDimitry Andric } 24781ad6265SDimitry Andric } 24881ad6265SDimitry Andric 2498bcb0991SDimitry Andric BTFTypeArray::BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems) { 2500b57cec5SDimitry Andric Kind = BTF::BTF_KIND_ARRAY; 2510b57cec5SDimitry Andric BTFType.NameOff = 0; 2520b57cec5SDimitry Andric BTFType.Info = Kind << 24; 2530b57cec5SDimitry Andric BTFType.Size = 0; 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric ArrayInfo.ElemType = ElemTypeId; 2560b57cec5SDimitry Andric ArrayInfo.Nelems = NumElems; 2570b57cec5SDimitry Andric } 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric /// Represent a BTF array. 2600b57cec5SDimitry Andric void BTFTypeArray::completeType(BTFDebug &BDebug) { 2610b57cec5SDimitry Andric if (IsCompleted) 2620b57cec5SDimitry Andric return; 2630b57cec5SDimitry Andric IsCompleted = true; 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric // The IR does not really have a type for the index. 2660b57cec5SDimitry Andric // A special type for array index should have been 2670b57cec5SDimitry Andric // created during initial type traversal. Just 2680b57cec5SDimitry Andric // retrieve that type id. 2690b57cec5SDimitry Andric ArrayInfo.IndexType = BDebug.getArrayIndexTypeId(); 2700b57cec5SDimitry Andric } 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric void BTFTypeArray::emitType(MCStreamer &OS) { 2730b57cec5SDimitry Andric BTFTypeBase::emitType(OS); 2745ffd83dbSDimitry Andric OS.emitInt32(ArrayInfo.ElemType); 2755ffd83dbSDimitry Andric OS.emitInt32(ArrayInfo.IndexType); 2765ffd83dbSDimitry Andric OS.emitInt32(ArrayInfo.Nelems); 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric /// Represent either a struct or a union. 2800b57cec5SDimitry Andric BTFTypeStruct::BTFTypeStruct(const DICompositeType *STy, bool IsStruct, 2810b57cec5SDimitry Andric bool HasBitField, uint32_t Vlen) 2820b57cec5SDimitry Andric : STy(STy), HasBitField(HasBitField) { 2830b57cec5SDimitry Andric Kind = IsStruct ? BTF::BTF_KIND_STRUCT : BTF::BTF_KIND_UNION; 2840b57cec5SDimitry Andric BTFType.Size = roundupToBytes(STy->getSizeInBits()); 2850b57cec5SDimitry Andric BTFType.Info = (HasBitField << 31) | (Kind << 24) | Vlen; 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric void BTFTypeStruct::completeType(BTFDebug &BDebug) { 2890b57cec5SDimitry Andric if (IsCompleted) 2900b57cec5SDimitry Andric return; 2910b57cec5SDimitry Andric IsCompleted = true; 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric BTFType.NameOff = BDebug.addString(STy->getName()); 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric // Add struct/union members. 2960b57cec5SDimitry Andric const DINodeArray Elements = STy->getElements(); 2970b57cec5SDimitry Andric for (const auto *Element : Elements) { 2980b57cec5SDimitry Andric struct BTF::BTFMember BTFMember; 2990b57cec5SDimitry Andric const auto *DDTy = cast<DIDerivedType>(Element); 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric BTFMember.NameOff = BDebug.addString(DDTy->getName()); 3020b57cec5SDimitry Andric if (HasBitField) { 3030b57cec5SDimitry Andric uint8_t BitFieldSize = DDTy->isBitField() ? DDTy->getSizeInBits() : 0; 3040b57cec5SDimitry Andric BTFMember.Offset = BitFieldSize << 24 | DDTy->getOffsetInBits(); 3050b57cec5SDimitry Andric } else { 3060b57cec5SDimitry Andric BTFMember.Offset = DDTy->getOffsetInBits(); 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric const auto *BaseTy = DDTy->getBaseType(); 3090b57cec5SDimitry Andric BTFMember.Type = BDebug.getTypeId(BaseTy); 3100b57cec5SDimitry Andric Members.push_back(BTFMember); 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric } 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric void BTFTypeStruct::emitType(MCStreamer &OS) { 3150b57cec5SDimitry Andric BTFTypeBase::emitType(OS); 3160b57cec5SDimitry Andric for (const auto &Member : Members) { 3175ffd83dbSDimitry Andric OS.emitInt32(Member.NameOff); 3185ffd83dbSDimitry Andric OS.emitInt32(Member.Type); 3190b57cec5SDimitry Andric OS.AddComment("0x" + Twine::utohexstr(Member.Offset)); 3205ffd83dbSDimitry Andric OS.emitInt32(Member.Offset); 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric 3245ffd83dbSDimitry Andric std::string BTFTypeStruct::getName() { return std::string(STy->getName()); } 3250b57cec5SDimitry Andric 3260b57cec5SDimitry Andric /// The Func kind represents both subprogram and pointee of function 3270b57cec5SDimitry Andric /// pointers. If the FuncName is empty, it represents a pointee of function 3280b57cec5SDimitry Andric /// pointer. Otherwise, it represents a subprogram. The func arg names 3290b57cec5SDimitry Andric /// are empty for pointee of function pointer case, and are valid names 3300b57cec5SDimitry Andric /// for subprogram. 3310b57cec5SDimitry Andric BTFTypeFuncProto::BTFTypeFuncProto( 3320b57cec5SDimitry Andric const DISubroutineType *STy, uint32_t VLen, 3330b57cec5SDimitry Andric const std::unordered_map<uint32_t, StringRef> &FuncArgNames) 3340b57cec5SDimitry Andric : STy(STy), FuncArgNames(FuncArgNames) { 3350b57cec5SDimitry Andric Kind = BTF::BTF_KIND_FUNC_PROTO; 3360b57cec5SDimitry Andric BTFType.Info = (Kind << 24) | VLen; 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric void BTFTypeFuncProto::completeType(BTFDebug &BDebug) { 3400b57cec5SDimitry Andric if (IsCompleted) 3410b57cec5SDimitry Andric return; 3420b57cec5SDimitry Andric IsCompleted = true; 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric DITypeRefArray Elements = STy->getTypeArray(); 3450b57cec5SDimitry Andric auto RetType = Elements[0]; 3460b57cec5SDimitry Andric BTFType.Type = RetType ? BDebug.getTypeId(RetType) : 0; 3470b57cec5SDimitry Andric BTFType.NameOff = 0; 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric // For null parameter which is typically the last one 3500b57cec5SDimitry Andric // to represent the vararg, encode the NameOff/Type to be 0. 3510b57cec5SDimitry Andric for (unsigned I = 1, N = Elements.size(); I < N; ++I) { 3520b57cec5SDimitry Andric struct BTF::BTFParam Param; 3530b57cec5SDimitry Andric auto Element = Elements[I]; 3540b57cec5SDimitry Andric if (Element) { 3550b57cec5SDimitry Andric Param.NameOff = BDebug.addString(FuncArgNames[I]); 3560b57cec5SDimitry Andric Param.Type = BDebug.getTypeId(Element); 3570b57cec5SDimitry Andric } else { 3580b57cec5SDimitry Andric Param.NameOff = 0; 3590b57cec5SDimitry Andric Param.Type = 0; 3600b57cec5SDimitry Andric } 3610b57cec5SDimitry Andric Parameters.push_back(Param); 3620b57cec5SDimitry Andric } 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric void BTFTypeFuncProto::emitType(MCStreamer &OS) { 3660b57cec5SDimitry Andric BTFTypeBase::emitType(OS); 3670b57cec5SDimitry Andric for (const auto &Param : Parameters) { 3685ffd83dbSDimitry Andric OS.emitInt32(Param.NameOff); 3695ffd83dbSDimitry Andric OS.emitInt32(Param.Type); 3700b57cec5SDimitry Andric } 3710b57cec5SDimitry Andric } 3720b57cec5SDimitry Andric 373480093f4SDimitry Andric BTFTypeFunc::BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId, 374480093f4SDimitry Andric uint32_t Scope) 3750b57cec5SDimitry Andric : Name(FuncName) { 3760b57cec5SDimitry Andric Kind = BTF::BTF_KIND_FUNC; 377480093f4SDimitry Andric BTFType.Info = (Kind << 24) | Scope; 3780b57cec5SDimitry Andric BTFType.Type = ProtoTypeId; 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric void BTFTypeFunc::completeType(BTFDebug &BDebug) { 3820b57cec5SDimitry Andric if (IsCompleted) 3830b57cec5SDimitry Andric return; 3840b57cec5SDimitry Andric IsCompleted = true; 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric BTFType.NameOff = BDebug.addString(Name); 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric void BTFTypeFunc::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); } 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric BTFKindVar::BTFKindVar(StringRef VarName, uint32_t TypeId, uint32_t VarInfo) 3920b57cec5SDimitry Andric : Name(VarName) { 3930b57cec5SDimitry Andric Kind = BTF::BTF_KIND_VAR; 3940b57cec5SDimitry Andric BTFType.Info = Kind << 24; 3950b57cec5SDimitry Andric BTFType.Type = TypeId; 3960b57cec5SDimitry Andric Info = VarInfo; 3970b57cec5SDimitry Andric } 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric void BTFKindVar::completeType(BTFDebug &BDebug) { 4000b57cec5SDimitry Andric BTFType.NameOff = BDebug.addString(Name); 4010b57cec5SDimitry Andric } 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric void BTFKindVar::emitType(MCStreamer &OS) { 4040b57cec5SDimitry Andric BTFTypeBase::emitType(OS); 4055ffd83dbSDimitry Andric OS.emitInt32(Info); 4060b57cec5SDimitry Andric } 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric BTFKindDataSec::BTFKindDataSec(AsmPrinter *AsmPrt, std::string SecName) 4090b57cec5SDimitry Andric : Asm(AsmPrt), Name(SecName) { 4100b57cec5SDimitry Andric Kind = BTF::BTF_KIND_DATASEC; 4110b57cec5SDimitry Andric BTFType.Info = Kind << 24; 4120b57cec5SDimitry Andric BTFType.Size = 0; 4130b57cec5SDimitry Andric } 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric void BTFKindDataSec::completeType(BTFDebug &BDebug) { 4160b57cec5SDimitry Andric BTFType.NameOff = BDebug.addString(Name); 4170b57cec5SDimitry Andric BTFType.Info |= Vars.size(); 4180b57cec5SDimitry Andric } 4190b57cec5SDimitry Andric 4200b57cec5SDimitry Andric void BTFKindDataSec::emitType(MCStreamer &OS) { 4210b57cec5SDimitry Andric BTFTypeBase::emitType(OS); 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric for (const auto &V : Vars) { 4245ffd83dbSDimitry Andric OS.emitInt32(std::get<0>(V)); 4255ffd83dbSDimitry Andric Asm->emitLabelReference(std::get<1>(V), 4); 4265ffd83dbSDimitry Andric OS.emitInt32(std::get<2>(V)); 4270b57cec5SDimitry Andric } 4280b57cec5SDimitry Andric } 4290b57cec5SDimitry Andric 43023408297SDimitry Andric BTFTypeFloat::BTFTypeFloat(uint32_t SizeInBits, StringRef TypeName) 43123408297SDimitry Andric : Name(TypeName) { 43223408297SDimitry Andric Kind = BTF::BTF_KIND_FLOAT; 43323408297SDimitry Andric BTFType.Info = Kind << 24; 43423408297SDimitry Andric BTFType.Size = roundupToBytes(SizeInBits); 43523408297SDimitry Andric } 43623408297SDimitry Andric 43723408297SDimitry Andric void BTFTypeFloat::completeType(BTFDebug &BDebug) { 43823408297SDimitry Andric if (IsCompleted) 43923408297SDimitry Andric return; 44023408297SDimitry Andric IsCompleted = true; 44123408297SDimitry Andric 44223408297SDimitry Andric BTFType.NameOff = BDebug.addString(Name); 44323408297SDimitry Andric } 44423408297SDimitry Andric 445349cc55cSDimitry Andric BTFTypeDeclTag::BTFTypeDeclTag(uint32_t BaseTypeId, int ComponentIdx, 446349cc55cSDimitry Andric StringRef Tag) 447349cc55cSDimitry Andric : Tag(Tag) { 448349cc55cSDimitry Andric Kind = BTF::BTF_KIND_DECL_TAG; 449349cc55cSDimitry Andric BTFType.Info = Kind << 24; 450349cc55cSDimitry Andric BTFType.Type = BaseTypeId; 451349cc55cSDimitry Andric Info = ComponentIdx; 452349cc55cSDimitry Andric } 453349cc55cSDimitry Andric 454349cc55cSDimitry Andric void BTFTypeDeclTag::completeType(BTFDebug &BDebug) { 455349cc55cSDimitry Andric if (IsCompleted) 456349cc55cSDimitry Andric return; 457349cc55cSDimitry Andric IsCompleted = true; 458349cc55cSDimitry Andric 459349cc55cSDimitry Andric BTFType.NameOff = BDebug.addString(Tag); 460349cc55cSDimitry Andric } 461349cc55cSDimitry Andric 462349cc55cSDimitry Andric void BTFTypeDeclTag::emitType(MCStreamer &OS) { 463349cc55cSDimitry Andric BTFTypeBase::emitType(OS); 464349cc55cSDimitry Andric OS.emitInt32(Info); 465349cc55cSDimitry Andric } 466349cc55cSDimitry Andric 467349cc55cSDimitry Andric BTFTypeTypeTag::BTFTypeTypeTag(uint32_t NextTypeId, StringRef Tag) 468349cc55cSDimitry Andric : DTy(nullptr), Tag(Tag) { 469349cc55cSDimitry Andric Kind = BTF::BTF_KIND_TYPE_TAG; 470349cc55cSDimitry Andric BTFType.Info = Kind << 24; 471349cc55cSDimitry Andric BTFType.Type = NextTypeId; 472349cc55cSDimitry Andric } 473349cc55cSDimitry Andric 474349cc55cSDimitry Andric BTFTypeTypeTag::BTFTypeTypeTag(const DIDerivedType *DTy, StringRef Tag) 475349cc55cSDimitry Andric : DTy(DTy), Tag(Tag) { 476349cc55cSDimitry Andric Kind = BTF::BTF_KIND_TYPE_TAG; 477349cc55cSDimitry Andric BTFType.Info = Kind << 24; 478349cc55cSDimitry Andric } 479349cc55cSDimitry Andric 480349cc55cSDimitry Andric void BTFTypeTypeTag::completeType(BTFDebug &BDebug) { 481349cc55cSDimitry Andric if (IsCompleted) 482349cc55cSDimitry Andric return; 483349cc55cSDimitry Andric IsCompleted = true; 484349cc55cSDimitry Andric BTFType.NameOff = BDebug.addString(Tag); 485349cc55cSDimitry Andric if (DTy) { 486349cc55cSDimitry Andric const DIType *ResolvedType = DTy->getBaseType(); 487349cc55cSDimitry Andric if (!ResolvedType) 488349cc55cSDimitry Andric BTFType.Type = 0; 489349cc55cSDimitry Andric else 490349cc55cSDimitry Andric BTFType.Type = BDebug.getTypeId(ResolvedType); 491349cc55cSDimitry Andric } 492349cc55cSDimitry Andric } 493349cc55cSDimitry Andric 4940b57cec5SDimitry Andric uint32_t BTFStringTable::addString(StringRef S) { 4950b57cec5SDimitry Andric // Check whether the string already exists. 4960b57cec5SDimitry Andric for (auto &OffsetM : OffsetToIdMap) { 4970b57cec5SDimitry Andric if (Table[OffsetM.second] == S) 4980b57cec5SDimitry Andric return OffsetM.first; 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric // Not find, add to the string table. 5010b57cec5SDimitry Andric uint32_t Offset = Size; 5020b57cec5SDimitry Andric OffsetToIdMap[Offset] = Table.size(); 5035ffd83dbSDimitry Andric Table.push_back(std::string(S)); 5040b57cec5SDimitry Andric Size += S.size() + 1; 5050b57cec5SDimitry Andric return Offset; 5060b57cec5SDimitry Andric } 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric BTFDebug::BTFDebug(AsmPrinter *AP) 5090b57cec5SDimitry Andric : DebugHandlerBase(AP), OS(*Asm->OutStreamer), SkipInstruction(false), 5100b57cec5SDimitry Andric LineInfoGenerated(false), SecNameOff(0), ArrayIndexTypeId(0), 5110b57cec5SDimitry Andric MapDefNotCollected(true) { 5120b57cec5SDimitry Andric addString("\0"); 5130b57cec5SDimitry Andric } 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry, 5160b57cec5SDimitry Andric const DIType *Ty) { 5170b57cec5SDimitry Andric TypeEntry->setId(TypeEntries.size() + 1); 5180b57cec5SDimitry Andric uint32_t Id = TypeEntry->getId(); 5190b57cec5SDimitry Andric DIToIdMap[Ty] = Id; 5200b57cec5SDimitry Andric TypeEntries.push_back(std::move(TypeEntry)); 5210b57cec5SDimitry Andric return Id; 5220b57cec5SDimitry Andric } 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry) { 5250b57cec5SDimitry Andric TypeEntry->setId(TypeEntries.size() + 1); 5260b57cec5SDimitry Andric uint32_t Id = TypeEntry->getId(); 5270b57cec5SDimitry Andric TypeEntries.push_back(std::move(TypeEntry)); 5280b57cec5SDimitry Andric return Id; 5290b57cec5SDimitry Andric } 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric void BTFDebug::visitBasicType(const DIBasicType *BTy, uint32_t &TypeId) { 53223408297SDimitry Andric // Only int and binary floating point types are supported in BTF. 5330b57cec5SDimitry Andric uint32_t Encoding = BTy->getEncoding(); 53423408297SDimitry Andric std::unique_ptr<BTFTypeBase> TypeEntry; 53523408297SDimitry Andric switch (Encoding) { 53623408297SDimitry Andric case dwarf::DW_ATE_boolean: 53723408297SDimitry Andric case dwarf::DW_ATE_signed: 53823408297SDimitry Andric case dwarf::DW_ATE_signed_char: 53923408297SDimitry Andric case dwarf::DW_ATE_unsigned: 54023408297SDimitry Andric case dwarf::DW_ATE_unsigned_char: 5410b57cec5SDimitry Andric // Create a BTF type instance for this DIBasicType and put it into 5420b57cec5SDimitry Andric // DIToIdMap for cross-type reference check. 54323408297SDimitry Andric TypeEntry = std::make_unique<BTFTypeInt>( 5440b57cec5SDimitry Andric Encoding, BTy->getSizeInBits(), BTy->getOffsetInBits(), BTy->getName()); 54523408297SDimitry Andric break; 54623408297SDimitry Andric case dwarf::DW_ATE_float: 54723408297SDimitry Andric TypeEntry = 54823408297SDimitry Andric std::make_unique<BTFTypeFloat>(BTy->getSizeInBits(), BTy->getName()); 54923408297SDimitry Andric break; 55023408297SDimitry Andric default: 55123408297SDimitry Andric return; 55223408297SDimitry Andric } 55323408297SDimitry Andric 5540b57cec5SDimitry Andric TypeId = addType(std::move(TypeEntry), BTy); 5550b57cec5SDimitry Andric } 5560b57cec5SDimitry Andric 5570b57cec5SDimitry Andric /// Handle subprogram or subroutine types. 5580b57cec5SDimitry Andric void BTFDebug::visitSubroutineType( 5590b57cec5SDimitry Andric const DISubroutineType *STy, bool ForSubprog, 5600b57cec5SDimitry Andric const std::unordered_map<uint32_t, StringRef> &FuncArgNames, 5610b57cec5SDimitry Andric uint32_t &TypeId) { 5620b57cec5SDimitry Andric DITypeRefArray Elements = STy->getTypeArray(); 5630b57cec5SDimitry Andric uint32_t VLen = Elements.size() - 1; 5640b57cec5SDimitry Andric if (VLen > BTF::MAX_VLEN) 5650b57cec5SDimitry Andric return; 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric // Subprogram has a valid non-zero-length name, and the pointee of 5680b57cec5SDimitry Andric // a function pointer has an empty name. The subprogram type will 5690b57cec5SDimitry Andric // not be added to DIToIdMap as it should not be referenced by 5700b57cec5SDimitry Andric // any other types. 5718bcb0991SDimitry Andric auto TypeEntry = std::make_unique<BTFTypeFuncProto>(STy, VLen, FuncArgNames); 5720b57cec5SDimitry Andric if (ForSubprog) 5730b57cec5SDimitry Andric TypeId = addType(std::move(TypeEntry)); // For subprogram 5740b57cec5SDimitry Andric else 5750b57cec5SDimitry Andric TypeId = addType(std::move(TypeEntry), STy); // For func ptr 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andric // Visit return type and func arg types. 5780b57cec5SDimitry Andric for (const auto Element : Elements) { 5790b57cec5SDimitry Andric visitTypeEntry(Element); 5800b57cec5SDimitry Andric } 5810b57cec5SDimitry Andric } 5820b57cec5SDimitry Andric 583349cc55cSDimitry Andric void BTFDebug::processDeclAnnotations(DINodeArray Annotations, 584349cc55cSDimitry Andric uint32_t BaseTypeId, 585349cc55cSDimitry Andric int ComponentIdx) { 586349cc55cSDimitry Andric if (!Annotations) 587349cc55cSDimitry Andric return; 588349cc55cSDimitry Andric 589349cc55cSDimitry Andric for (const Metadata *Annotation : Annotations->operands()) { 590349cc55cSDimitry Andric const MDNode *MD = cast<MDNode>(Annotation); 591349cc55cSDimitry Andric const MDString *Name = cast<MDString>(MD->getOperand(0)); 592*0fca6ea1SDimitry Andric if (Name->getString() != "btf_decl_tag") 593349cc55cSDimitry Andric continue; 594349cc55cSDimitry Andric 595349cc55cSDimitry Andric const MDString *Value = cast<MDString>(MD->getOperand(1)); 596349cc55cSDimitry Andric auto TypeEntry = std::make_unique<BTFTypeDeclTag>(BaseTypeId, ComponentIdx, 597349cc55cSDimitry Andric Value->getString()); 598349cc55cSDimitry Andric addType(std::move(TypeEntry)); 599349cc55cSDimitry Andric } 600349cc55cSDimitry Andric } 601349cc55cSDimitry Andric 602bdd1243dSDimitry Andric uint32_t BTFDebug::processDISubprogram(const DISubprogram *SP, 603bdd1243dSDimitry Andric uint32_t ProtoTypeId, uint8_t Scope) { 604bdd1243dSDimitry Andric auto FuncTypeEntry = 605bdd1243dSDimitry Andric std::make_unique<BTFTypeFunc>(SP->getName(), ProtoTypeId, Scope); 606bdd1243dSDimitry Andric uint32_t FuncId = addType(std::move(FuncTypeEntry)); 607bdd1243dSDimitry Andric 608bdd1243dSDimitry Andric // Process argument annotations. 609bdd1243dSDimitry Andric for (const DINode *DN : SP->getRetainedNodes()) { 610bdd1243dSDimitry Andric if (const auto *DV = dyn_cast<DILocalVariable>(DN)) { 611bdd1243dSDimitry Andric uint32_t Arg = DV->getArg(); 612bdd1243dSDimitry Andric if (Arg) 613bdd1243dSDimitry Andric processDeclAnnotations(DV->getAnnotations(), FuncId, Arg - 1); 614bdd1243dSDimitry Andric } 615bdd1243dSDimitry Andric } 616bdd1243dSDimitry Andric processDeclAnnotations(SP->getAnnotations(), FuncId, -1); 617bdd1243dSDimitry Andric 618bdd1243dSDimitry Andric return FuncId; 619bdd1243dSDimitry Andric } 620bdd1243dSDimitry Andric 62181ad6265SDimitry Andric /// Generate btf_type_tag chains. 62281ad6265SDimitry Andric int BTFDebug::genBTFTypeTags(const DIDerivedType *DTy, int BaseTypeId) { 62381ad6265SDimitry Andric SmallVector<const MDString *, 4> MDStrs; 62481ad6265SDimitry Andric DINodeArray Annots = DTy->getAnnotations(); 62581ad6265SDimitry Andric if (Annots) { 62681ad6265SDimitry Andric // For type with "int __tag1 __tag2 *p", the MDStrs will have 62781ad6265SDimitry Andric // content: [__tag1, __tag2]. 62881ad6265SDimitry Andric for (const Metadata *Annotations : Annots->operands()) { 62981ad6265SDimitry Andric const MDNode *MD = cast<MDNode>(Annotations); 63081ad6265SDimitry Andric const MDString *Name = cast<MDString>(MD->getOperand(0)); 631*0fca6ea1SDimitry Andric if (Name->getString() != "btf_type_tag") 63281ad6265SDimitry Andric continue; 63381ad6265SDimitry Andric MDStrs.push_back(cast<MDString>(MD->getOperand(1))); 63481ad6265SDimitry Andric } 63581ad6265SDimitry Andric } 63681ad6265SDimitry Andric 63781ad6265SDimitry Andric if (MDStrs.size() == 0) 63881ad6265SDimitry Andric return -1; 63981ad6265SDimitry Andric 64081ad6265SDimitry Andric // With MDStrs [__tag1, __tag2], the output type chain looks like 64181ad6265SDimitry Andric // PTR -> __tag2 -> __tag1 -> BaseType 64281ad6265SDimitry Andric // In the below, we construct BTF types with the order of __tag1, __tag2 64381ad6265SDimitry Andric // and PTR. 64481ad6265SDimitry Andric unsigned TmpTypeId; 64581ad6265SDimitry Andric std::unique_ptr<BTFTypeTypeTag> TypeEntry; 64681ad6265SDimitry Andric if (BaseTypeId >= 0) 64781ad6265SDimitry Andric TypeEntry = 64881ad6265SDimitry Andric std::make_unique<BTFTypeTypeTag>(BaseTypeId, MDStrs[0]->getString()); 64981ad6265SDimitry Andric else 65081ad6265SDimitry Andric TypeEntry = std::make_unique<BTFTypeTypeTag>(DTy, MDStrs[0]->getString()); 65181ad6265SDimitry Andric TmpTypeId = addType(std::move(TypeEntry)); 65281ad6265SDimitry Andric 65381ad6265SDimitry Andric for (unsigned I = 1; I < MDStrs.size(); I++) { 65481ad6265SDimitry Andric const MDString *Value = MDStrs[I]; 65581ad6265SDimitry Andric TypeEntry = std::make_unique<BTFTypeTypeTag>(TmpTypeId, Value->getString()); 65681ad6265SDimitry Andric TmpTypeId = addType(std::move(TypeEntry)); 65781ad6265SDimitry Andric } 65881ad6265SDimitry Andric return TmpTypeId; 65981ad6265SDimitry Andric } 66081ad6265SDimitry Andric 6610b57cec5SDimitry Andric /// Handle structure/union types. 6620b57cec5SDimitry Andric void BTFDebug::visitStructType(const DICompositeType *CTy, bool IsStruct, 6630b57cec5SDimitry Andric uint32_t &TypeId) { 6640b57cec5SDimitry Andric const DINodeArray Elements = CTy->getElements(); 6650b57cec5SDimitry Andric uint32_t VLen = Elements.size(); 6660b57cec5SDimitry Andric if (VLen > BTF::MAX_VLEN) 6670b57cec5SDimitry Andric return; 6680b57cec5SDimitry Andric 6690b57cec5SDimitry Andric // Check whether we have any bitfield members or not 6700b57cec5SDimitry Andric bool HasBitField = false; 6710b57cec5SDimitry Andric for (const auto *Element : Elements) { 6720b57cec5SDimitry Andric auto E = cast<DIDerivedType>(Element); 6730b57cec5SDimitry Andric if (E->isBitField()) { 6740b57cec5SDimitry Andric HasBitField = true; 6750b57cec5SDimitry Andric break; 6760b57cec5SDimitry Andric } 6770b57cec5SDimitry Andric } 6780b57cec5SDimitry Andric 6790b57cec5SDimitry Andric auto TypeEntry = 6808bcb0991SDimitry Andric std::make_unique<BTFTypeStruct>(CTy, IsStruct, HasBitField, VLen); 6810b57cec5SDimitry Andric StructTypes.push_back(TypeEntry.get()); 6820b57cec5SDimitry Andric TypeId = addType(std::move(TypeEntry), CTy); 6830b57cec5SDimitry Andric 684349cc55cSDimitry Andric // Check struct/union annotations 685349cc55cSDimitry Andric processDeclAnnotations(CTy->getAnnotations(), TypeId, -1); 686349cc55cSDimitry Andric 6870b57cec5SDimitry Andric // Visit all struct members. 688349cc55cSDimitry Andric int FieldNo = 0; 689349cc55cSDimitry Andric for (const auto *Element : Elements) { 690349cc55cSDimitry Andric const auto Elem = cast<DIDerivedType>(Element); 691349cc55cSDimitry Andric visitTypeEntry(Elem); 692349cc55cSDimitry Andric processDeclAnnotations(Elem->getAnnotations(), TypeId, FieldNo); 693349cc55cSDimitry Andric FieldNo++; 694349cc55cSDimitry Andric } 6950b57cec5SDimitry Andric } 6960b57cec5SDimitry Andric 6970b57cec5SDimitry Andric void BTFDebug::visitArrayType(const DICompositeType *CTy, uint32_t &TypeId) { 6980b57cec5SDimitry Andric // Visit array element type. 6998bcb0991SDimitry Andric uint32_t ElemTypeId; 7000b57cec5SDimitry Andric const DIType *ElemType = CTy->getBaseType(); 7010b57cec5SDimitry Andric visitTypeEntry(ElemType, ElemTypeId, false, false); 7020b57cec5SDimitry Andric 7030b57cec5SDimitry Andric // Visit array dimensions. 7040b57cec5SDimitry Andric DINodeArray Elements = CTy->getElements(); 7050b57cec5SDimitry Andric for (int I = Elements.size() - 1; I >= 0; --I) { 7060b57cec5SDimitry Andric if (auto *Element = dyn_cast_or_null<DINode>(Elements[I])) 7070b57cec5SDimitry Andric if (Element->getTag() == dwarf::DW_TAG_subrange_type) { 7080b57cec5SDimitry Andric const DISubrange *SR = cast<DISubrange>(Element); 7090b57cec5SDimitry Andric auto *CI = SR->getCount().dyn_cast<ConstantInt *>(); 7100b57cec5SDimitry Andric int64_t Count = CI->getSExtValue(); 7110b57cec5SDimitry Andric 7128bcb0991SDimitry Andric // For struct s { int b; char c[]; }, the c[] will be represented 7138bcb0991SDimitry Andric // as an array with Count = -1. 7140b57cec5SDimitry Andric auto TypeEntry = 7158bcb0991SDimitry Andric std::make_unique<BTFTypeArray>(ElemTypeId, 7168bcb0991SDimitry Andric Count >= 0 ? Count : 0); 7170b57cec5SDimitry Andric if (I == 0) 7180b57cec5SDimitry Andric ElemTypeId = addType(std::move(TypeEntry), CTy); 7190b57cec5SDimitry Andric else 7200b57cec5SDimitry Andric ElemTypeId = addType(std::move(TypeEntry)); 7210b57cec5SDimitry Andric } 7220b57cec5SDimitry Andric } 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric // The array TypeId is the type id of the outermost dimension. 7250b57cec5SDimitry Andric TypeId = ElemTypeId; 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric // The IR does not have a type for array index while BTF wants one. 7280b57cec5SDimitry Andric // So create an array index type if there is none. 7290b57cec5SDimitry Andric if (!ArrayIndexTypeId) { 7308bcb0991SDimitry Andric auto TypeEntry = std::make_unique<BTFTypeInt>(dwarf::DW_ATE_unsigned, 32, 7310b57cec5SDimitry Andric 0, "__ARRAY_SIZE_TYPE__"); 7320b57cec5SDimitry Andric ArrayIndexTypeId = addType(std::move(TypeEntry)); 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric } 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric void BTFDebug::visitEnumType(const DICompositeType *CTy, uint32_t &TypeId) { 7370b57cec5SDimitry Andric DINodeArray Elements = CTy->getElements(); 7380b57cec5SDimitry Andric uint32_t VLen = Elements.size(); 7390b57cec5SDimitry Andric if (VLen > BTF::MAX_VLEN) 7400b57cec5SDimitry Andric return; 7410b57cec5SDimitry Andric 74281ad6265SDimitry Andric bool IsSigned = false; 74381ad6265SDimitry Andric unsigned NumBits = 32; 74481ad6265SDimitry Andric // No BaseType implies forward declaration in which case a 74581ad6265SDimitry Andric // BTFTypeEnum with Vlen = 0 is emitted. 74681ad6265SDimitry Andric if (CTy->getBaseType() != nullptr) { 74781ad6265SDimitry Andric const auto *BTy = cast<DIBasicType>(CTy->getBaseType()); 74881ad6265SDimitry Andric IsSigned = BTy->getEncoding() == dwarf::DW_ATE_signed || 74981ad6265SDimitry Andric BTy->getEncoding() == dwarf::DW_ATE_signed_char; 75081ad6265SDimitry Andric NumBits = BTy->getSizeInBits(); 75181ad6265SDimitry Andric } 75281ad6265SDimitry Andric 75381ad6265SDimitry Andric if (NumBits <= 32) { 75481ad6265SDimitry Andric auto TypeEntry = std::make_unique<BTFTypeEnum>(CTy, VLen, IsSigned); 7550b57cec5SDimitry Andric TypeId = addType(std::move(TypeEntry), CTy); 75681ad6265SDimitry Andric } else { 75781ad6265SDimitry Andric assert(NumBits == 64); 75881ad6265SDimitry Andric auto TypeEntry = std::make_unique<BTFTypeEnum64>(CTy, VLen, IsSigned); 75981ad6265SDimitry Andric TypeId = addType(std::move(TypeEntry), CTy); 76081ad6265SDimitry Andric } 7610b57cec5SDimitry Andric // No need to visit base type as BTF does not encode it. 7620b57cec5SDimitry Andric } 7630b57cec5SDimitry Andric 7640b57cec5SDimitry Andric /// Handle structure/union forward declarations. 7650b57cec5SDimitry Andric void BTFDebug::visitFwdDeclType(const DICompositeType *CTy, bool IsUnion, 7660b57cec5SDimitry Andric uint32_t &TypeId) { 7678bcb0991SDimitry Andric auto TypeEntry = std::make_unique<BTFTypeFwd>(CTy->getName(), IsUnion); 7680b57cec5SDimitry Andric TypeId = addType(std::move(TypeEntry), CTy); 7690b57cec5SDimitry Andric } 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric /// Handle structure, union, array and enumeration types. 7720b57cec5SDimitry Andric void BTFDebug::visitCompositeType(const DICompositeType *CTy, 7730b57cec5SDimitry Andric uint32_t &TypeId) { 7740b57cec5SDimitry Andric auto Tag = CTy->getTag(); 7750b57cec5SDimitry Andric if (Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) { 7760b57cec5SDimitry Andric // Handle forward declaration differently as it does not have members. 7770b57cec5SDimitry Andric if (CTy->isForwardDecl()) 7780b57cec5SDimitry Andric visitFwdDeclType(CTy, Tag == dwarf::DW_TAG_union_type, TypeId); 7790b57cec5SDimitry Andric else 7800b57cec5SDimitry Andric visitStructType(CTy, Tag == dwarf::DW_TAG_structure_type, TypeId); 7810b57cec5SDimitry Andric } else if (Tag == dwarf::DW_TAG_array_type) 7820b57cec5SDimitry Andric visitArrayType(CTy, TypeId); 7830b57cec5SDimitry Andric else if (Tag == dwarf::DW_TAG_enumeration_type) 7840b57cec5SDimitry Andric visitEnumType(CTy, TypeId); 7850b57cec5SDimitry Andric } 7860b57cec5SDimitry Andric 7871ac55f4cSDimitry Andric bool BTFDebug::IsForwardDeclCandidate(const DIType *Base) { 7881ac55f4cSDimitry Andric if (const auto *CTy = dyn_cast<DICompositeType>(Base)) { 7891ac55f4cSDimitry Andric auto CTag = CTy->getTag(); 7901ac55f4cSDimitry Andric if ((CTag == dwarf::DW_TAG_structure_type || 7911ac55f4cSDimitry Andric CTag == dwarf::DW_TAG_union_type) && 7921ac55f4cSDimitry Andric !CTy->getName().empty() && !CTy->isForwardDecl()) 7931ac55f4cSDimitry Andric return true; 7941ac55f4cSDimitry Andric } 7951ac55f4cSDimitry Andric return false; 7961ac55f4cSDimitry Andric } 7971ac55f4cSDimitry Andric 7980b57cec5SDimitry Andric /// Handle pointer, typedef, const, volatile, restrict and member types. 7990b57cec5SDimitry Andric void BTFDebug::visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId, 8000b57cec5SDimitry Andric bool CheckPointer, bool SeenPointer) { 8010b57cec5SDimitry Andric unsigned Tag = DTy->getTag(); 8020b57cec5SDimitry Andric 8030b57cec5SDimitry Andric /// Try to avoid chasing pointees, esp. structure pointees which may 8040b57cec5SDimitry Andric /// unnecessary bring in a lot of types. 8050b57cec5SDimitry Andric if (CheckPointer && !SeenPointer) { 8060b57cec5SDimitry Andric SeenPointer = Tag == dwarf::DW_TAG_pointer_type; 8070b57cec5SDimitry Andric } 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric if (CheckPointer && SeenPointer) { 8100b57cec5SDimitry Andric const DIType *Base = DTy->getBaseType(); 8110b57cec5SDimitry Andric if (Base) { 8121ac55f4cSDimitry Andric if (IsForwardDeclCandidate(Base)) { 8130b57cec5SDimitry Andric /// Find a candidate, generate a fixup. Later on the struct/union 8140b57cec5SDimitry Andric /// pointee type will be replaced with either a real type or 8150b57cec5SDimitry Andric /// a forward declaration. 8168bcb0991SDimitry Andric auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy, Tag, true); 8171ac55f4cSDimitry Andric auto &Fixup = FixupDerivedTypes[cast<DICompositeType>(Base)]; 81881ad6265SDimitry Andric Fixup.push_back(std::make_pair(DTy, TypeEntry.get())); 8190b57cec5SDimitry Andric TypeId = addType(std::move(TypeEntry), DTy); 8200b57cec5SDimitry Andric return; 8210b57cec5SDimitry Andric } 8220b57cec5SDimitry Andric } 8230b57cec5SDimitry Andric } 8240b57cec5SDimitry Andric 825349cc55cSDimitry Andric if (Tag == dwarf::DW_TAG_pointer_type) { 82681ad6265SDimitry Andric int TmpTypeId = genBTFTypeTags(DTy, -1); 82781ad6265SDimitry Andric if (TmpTypeId >= 0) { 828349cc55cSDimitry Andric auto TypeDEntry = 829349cc55cSDimitry Andric std::make_unique<BTFTypeDerived>(TmpTypeId, Tag, DTy->getName()); 830349cc55cSDimitry Andric TypeId = addType(std::move(TypeDEntry), DTy); 831349cc55cSDimitry Andric } else { 832349cc55cSDimitry Andric auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy, Tag, false); 833349cc55cSDimitry Andric TypeId = addType(std::move(TypeEntry), DTy); 834349cc55cSDimitry Andric } 835349cc55cSDimitry Andric } else if (Tag == dwarf::DW_TAG_typedef || Tag == dwarf::DW_TAG_const_type || 836349cc55cSDimitry Andric Tag == dwarf::DW_TAG_volatile_type || 8370b57cec5SDimitry Andric Tag == dwarf::DW_TAG_restrict_type) { 8388bcb0991SDimitry Andric auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy, Tag, false); 8390b57cec5SDimitry Andric TypeId = addType(std::move(TypeEntry), DTy); 840349cc55cSDimitry Andric if (Tag == dwarf::DW_TAG_typedef) 841349cc55cSDimitry Andric processDeclAnnotations(DTy->getAnnotations(), TypeId, -1); 8420b57cec5SDimitry Andric } else if (Tag != dwarf::DW_TAG_member) { 8430b57cec5SDimitry Andric return; 8440b57cec5SDimitry Andric } 8450b57cec5SDimitry Andric 8460b57cec5SDimitry Andric // Visit base type of pointer, typedef, const, volatile, restrict or 8470b57cec5SDimitry Andric // struct/union member. 8480b57cec5SDimitry Andric uint32_t TempTypeId = 0; 8490b57cec5SDimitry Andric if (Tag == dwarf::DW_TAG_member) 8500b57cec5SDimitry Andric visitTypeEntry(DTy->getBaseType(), TempTypeId, true, false); 8510b57cec5SDimitry Andric else 8520b57cec5SDimitry Andric visitTypeEntry(DTy->getBaseType(), TempTypeId, CheckPointer, SeenPointer); 8530b57cec5SDimitry Andric } 8540b57cec5SDimitry Andric 8551ac55f4cSDimitry Andric /// Visit a type entry. CheckPointer is true if the type has 8561ac55f4cSDimitry Andric /// one of its predecessors as one struct/union member. SeenPointer 8571ac55f4cSDimitry Andric /// is true if CheckPointer is true and one of its predecessors 8581ac55f4cSDimitry Andric /// is a pointer. The goal of CheckPointer and SeenPointer is to 8591ac55f4cSDimitry Andric /// do pruning for struct/union types so some of these types 8601ac55f4cSDimitry Andric /// will not be emitted in BTF and rather forward declarations 8611ac55f4cSDimitry Andric /// will be generated. 8620b57cec5SDimitry Andric void BTFDebug::visitTypeEntry(const DIType *Ty, uint32_t &TypeId, 8630b57cec5SDimitry Andric bool CheckPointer, bool SeenPointer) { 8640b57cec5SDimitry Andric if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) { 8650b57cec5SDimitry Andric TypeId = DIToIdMap[Ty]; 8660946e70aSDimitry Andric 8670946e70aSDimitry Andric // To handle the case like the following: 8680946e70aSDimitry Andric // struct t; 8690946e70aSDimitry Andric // typedef struct t _t; 8700946e70aSDimitry Andric // struct s1 { _t *c; }; 8710946e70aSDimitry Andric // int test1(struct s1 *arg) { ... } 8720946e70aSDimitry Andric // 8730946e70aSDimitry Andric // struct t { int a; int b; }; 8740946e70aSDimitry Andric // struct s2 { _t c; } 8750946e70aSDimitry Andric // int test2(struct s2 *arg) { ... } 8760946e70aSDimitry Andric // 8770946e70aSDimitry Andric // During traversing test1() argument, "_t" is recorded 8780946e70aSDimitry Andric // in DIToIdMap and a forward declaration fixup is created 8790946e70aSDimitry Andric // for "struct t" to avoid pointee type traversal. 8800946e70aSDimitry Andric // 8810946e70aSDimitry Andric // During traversing test2() argument, even if we see "_t" is 8820946e70aSDimitry Andric // already defined, we should keep moving to eventually 8830946e70aSDimitry Andric // bring in types for "struct t". Otherwise, the "struct s2" 8840946e70aSDimitry Andric // definition won't be correct. 88581ad6265SDimitry Andric // 88681ad6265SDimitry Andric // In the above, we have following debuginfo: 88781ad6265SDimitry Andric // {ptr, struct_member} -> typedef -> struct 88881ad6265SDimitry Andric // and BTF type for 'typedef' is generated while 'struct' may 88981ad6265SDimitry Andric // be in FixUp. But let us generalize the above to handle 89081ad6265SDimitry Andric // {different types} -> [various derived types]+ -> another type. 89181ad6265SDimitry Andric // For example, 89281ad6265SDimitry Andric // {func_param, struct_member} -> const -> ptr -> volatile -> struct 89381ad6265SDimitry Andric // We will traverse const/ptr/volatile which already have corresponding 89481ad6265SDimitry Andric // BTF types and generate type for 'struct' which might be in Fixup 89581ad6265SDimitry Andric // state. 8960946e70aSDimitry Andric if (Ty && (!CheckPointer || !SeenPointer)) { 8970946e70aSDimitry Andric if (const auto *DTy = dyn_cast<DIDerivedType>(Ty)) { 89881ad6265SDimitry Andric while (DTy) { 89981ad6265SDimitry Andric const DIType *BaseTy = DTy->getBaseType(); 90081ad6265SDimitry Andric if (!BaseTy) 90181ad6265SDimitry Andric break; 90281ad6265SDimitry Andric 90381ad6265SDimitry Andric if (DIToIdMap.find(BaseTy) != DIToIdMap.end()) { 90481ad6265SDimitry Andric DTy = dyn_cast<DIDerivedType>(BaseTy); 90581ad6265SDimitry Andric } else { 9061ac55f4cSDimitry Andric if (CheckPointer && DTy->getTag() == dwarf::DW_TAG_pointer_type) { 9071ac55f4cSDimitry Andric SeenPointer = true; 9081ac55f4cSDimitry Andric if (IsForwardDeclCandidate(BaseTy)) 9091ac55f4cSDimitry Andric break; 9101ac55f4cSDimitry Andric } 9110946e70aSDimitry Andric uint32_t TmpTypeId; 91281ad6265SDimitry Andric visitTypeEntry(BaseTy, TmpTypeId, CheckPointer, SeenPointer); 91381ad6265SDimitry Andric break; 91481ad6265SDimitry Andric } 9150946e70aSDimitry Andric } 9160946e70aSDimitry Andric } 9170946e70aSDimitry Andric } 9180946e70aSDimitry Andric 9190b57cec5SDimitry Andric return; 9200b57cec5SDimitry Andric } 9210b57cec5SDimitry Andric 9220b57cec5SDimitry Andric if (const auto *BTy = dyn_cast<DIBasicType>(Ty)) 9230b57cec5SDimitry Andric visitBasicType(BTy, TypeId); 9240b57cec5SDimitry Andric else if (const auto *STy = dyn_cast<DISubroutineType>(Ty)) 9250b57cec5SDimitry Andric visitSubroutineType(STy, false, std::unordered_map<uint32_t, StringRef>(), 9260b57cec5SDimitry Andric TypeId); 9270b57cec5SDimitry Andric else if (const auto *CTy = dyn_cast<DICompositeType>(Ty)) 9280b57cec5SDimitry Andric visitCompositeType(CTy, TypeId); 9290b57cec5SDimitry Andric else if (const auto *DTy = dyn_cast<DIDerivedType>(Ty)) 9300b57cec5SDimitry Andric visitDerivedType(DTy, TypeId, CheckPointer, SeenPointer); 9310b57cec5SDimitry Andric else 9320b57cec5SDimitry Andric llvm_unreachable("Unknown DIType"); 9330b57cec5SDimitry Andric } 9340b57cec5SDimitry Andric 9350b57cec5SDimitry Andric void BTFDebug::visitTypeEntry(const DIType *Ty) { 9360b57cec5SDimitry Andric uint32_t TypeId; 9370b57cec5SDimitry Andric visitTypeEntry(Ty, TypeId, false, false); 9380b57cec5SDimitry Andric } 9390b57cec5SDimitry Andric 9400b57cec5SDimitry Andric void BTFDebug::visitMapDefType(const DIType *Ty, uint32_t &TypeId) { 9410b57cec5SDimitry Andric if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) { 9420b57cec5SDimitry Andric TypeId = DIToIdMap[Ty]; 9430b57cec5SDimitry Andric return; 9440b57cec5SDimitry Andric } 9450b57cec5SDimitry Andric 9465ffd83dbSDimitry Andric // MapDef type may be a struct type or a non-pointer derived type 9475ffd83dbSDimitry Andric const DIType *OrigTy = Ty; 9485ffd83dbSDimitry Andric while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) { 9495ffd83dbSDimitry Andric auto Tag = DTy->getTag(); 9505ffd83dbSDimitry Andric if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type && 9515ffd83dbSDimitry Andric Tag != dwarf::DW_TAG_volatile_type && 9525ffd83dbSDimitry Andric Tag != dwarf::DW_TAG_restrict_type) 9535ffd83dbSDimitry Andric break; 9545ffd83dbSDimitry Andric Ty = DTy->getBaseType(); 9555ffd83dbSDimitry Andric } 9565ffd83dbSDimitry Andric 9570b57cec5SDimitry Andric const auto *CTy = dyn_cast<DICompositeType>(Ty); 9580b57cec5SDimitry Andric if (!CTy) 9590b57cec5SDimitry Andric return; 9600b57cec5SDimitry Andric 9610b57cec5SDimitry Andric auto Tag = CTy->getTag(); 9620b57cec5SDimitry Andric if (Tag != dwarf::DW_TAG_structure_type || CTy->isForwardDecl()) 9630b57cec5SDimitry Andric return; 9640b57cec5SDimitry Andric 9655ffd83dbSDimitry Andric // Visit all struct members to ensure pointee type is visited 9660b57cec5SDimitry Andric const DINodeArray Elements = CTy->getElements(); 9670b57cec5SDimitry Andric for (const auto *Element : Elements) { 9680b57cec5SDimitry Andric const auto *MemberType = cast<DIDerivedType>(Element); 9690b57cec5SDimitry Andric visitTypeEntry(MemberType->getBaseType()); 9700b57cec5SDimitry Andric } 9715ffd83dbSDimitry Andric 9725ffd83dbSDimitry Andric // Visit this type, struct or a const/typedef/volatile/restrict type 9735ffd83dbSDimitry Andric visitTypeEntry(OrigTy, TypeId, false, false); 9740b57cec5SDimitry Andric } 9750b57cec5SDimitry Andric 9760b57cec5SDimitry Andric /// Read file contents from the actual file or from the source 977*0fca6ea1SDimitry Andric std::string BTFDebug::populateFileContent(const DIFile *File) { 9780b57cec5SDimitry Andric std::string FileName; 9790b57cec5SDimitry Andric 9805f757f3fSDimitry Andric if (!File->getFilename().starts_with("/") && File->getDirectory().size()) 9810b57cec5SDimitry Andric FileName = File->getDirectory().str() + "/" + File->getFilename().str(); 9820b57cec5SDimitry Andric else 9835ffd83dbSDimitry Andric FileName = std::string(File->getFilename()); 9840b57cec5SDimitry Andric 9850b57cec5SDimitry Andric // No need to populate the contends if it has been populated! 98606c3fb27SDimitry Andric if (FileContent.contains(FileName)) 9870b57cec5SDimitry Andric return FileName; 9880b57cec5SDimitry Andric 9890b57cec5SDimitry Andric std::vector<std::string> Content; 9900b57cec5SDimitry Andric std::string Line; 9910b57cec5SDimitry Andric Content.push_back(Line); // Line 0 for empty string 9920b57cec5SDimitry Andric 9930b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> Buf; 9940b57cec5SDimitry Andric auto Source = File->getSource(); 9950b57cec5SDimitry Andric if (Source) 9960b57cec5SDimitry Andric Buf = MemoryBuffer::getMemBufferCopy(*Source); 9970b57cec5SDimitry Andric else if (ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 9980b57cec5SDimitry Andric MemoryBuffer::getFile(FileName)) 9990b57cec5SDimitry Andric Buf = std::move(*BufOrErr); 10000b57cec5SDimitry Andric if (Buf) 10010b57cec5SDimitry Andric for (line_iterator I(*Buf, false), E; I != E; ++I) 10025ffd83dbSDimitry Andric Content.push_back(std::string(*I)); 10030b57cec5SDimitry Andric 10040b57cec5SDimitry Andric FileContent[FileName] = Content; 10050b57cec5SDimitry Andric return FileName; 10060b57cec5SDimitry Andric } 10070b57cec5SDimitry Andric 1008*0fca6ea1SDimitry Andric void BTFDebug::constructLineInfo(MCSymbol *Label, const DIFile *File, 10090b57cec5SDimitry Andric uint32_t Line, uint32_t Column) { 1010*0fca6ea1SDimitry Andric std::string FileName = populateFileContent(File); 10110b57cec5SDimitry Andric BTFLineInfo LineInfo; 10120b57cec5SDimitry Andric 10130b57cec5SDimitry Andric LineInfo.Label = Label; 10140b57cec5SDimitry Andric LineInfo.FileNameOff = addString(FileName); 10150b57cec5SDimitry Andric // If file content is not available, let LineOff = 0. 10160b57cec5SDimitry Andric if (Line < FileContent[FileName].size()) 10170b57cec5SDimitry Andric LineInfo.LineOff = addString(FileContent[FileName][Line]); 10180b57cec5SDimitry Andric else 10190b57cec5SDimitry Andric LineInfo.LineOff = 0; 10200b57cec5SDimitry Andric LineInfo.LineNum = Line; 10210b57cec5SDimitry Andric LineInfo.ColumnNum = Column; 10220b57cec5SDimitry Andric LineInfoTable[SecNameOff].push_back(LineInfo); 10230b57cec5SDimitry Andric } 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric void BTFDebug::emitCommonHeader() { 10260b57cec5SDimitry Andric OS.AddComment("0x" + Twine::utohexstr(BTF::MAGIC)); 10275ffd83dbSDimitry Andric OS.emitIntValue(BTF::MAGIC, 2); 10285ffd83dbSDimitry Andric OS.emitInt8(BTF::VERSION); 10295ffd83dbSDimitry Andric OS.emitInt8(0); 10300b57cec5SDimitry Andric } 10310b57cec5SDimitry Andric 10320b57cec5SDimitry Andric void BTFDebug::emitBTFSection() { 10330b57cec5SDimitry Andric // Do not emit section if no types and only "" string. 10340b57cec5SDimitry Andric if (!TypeEntries.size() && StringTable.getSize() == 1) 10350b57cec5SDimitry Andric return; 10360b57cec5SDimitry Andric 10370b57cec5SDimitry Andric MCContext &Ctx = OS.getContext(); 1038349cc55cSDimitry Andric MCSectionELF *Sec = Ctx.getELFSection(".BTF", ELF::SHT_PROGBITS, 0); 1039349cc55cSDimitry Andric Sec->setAlignment(Align(4)); 104081ad6265SDimitry Andric OS.switchSection(Sec); 10410b57cec5SDimitry Andric 10420b57cec5SDimitry Andric // Emit header. 10430b57cec5SDimitry Andric emitCommonHeader(); 10445ffd83dbSDimitry Andric OS.emitInt32(BTF::HeaderSize); 10450b57cec5SDimitry Andric 10460b57cec5SDimitry Andric uint32_t TypeLen = 0, StrLen; 10470b57cec5SDimitry Andric for (const auto &TypeEntry : TypeEntries) 10480b57cec5SDimitry Andric TypeLen += TypeEntry->getSize(); 10490b57cec5SDimitry Andric StrLen = StringTable.getSize(); 10500b57cec5SDimitry Andric 10515ffd83dbSDimitry Andric OS.emitInt32(0); 10525ffd83dbSDimitry Andric OS.emitInt32(TypeLen); 10535ffd83dbSDimitry Andric OS.emitInt32(TypeLen); 10545ffd83dbSDimitry Andric OS.emitInt32(StrLen); 10550b57cec5SDimitry Andric 10560b57cec5SDimitry Andric // Emit type table. 10570b57cec5SDimitry Andric for (const auto &TypeEntry : TypeEntries) 10580b57cec5SDimitry Andric TypeEntry->emitType(OS); 10590b57cec5SDimitry Andric 10600b57cec5SDimitry Andric // Emit string table. 10610b57cec5SDimitry Andric uint32_t StringOffset = 0; 10620b57cec5SDimitry Andric for (const auto &S : StringTable.getTable()) { 10630b57cec5SDimitry Andric OS.AddComment("string offset=" + std::to_string(StringOffset)); 10645ffd83dbSDimitry Andric OS.emitBytes(S); 10655ffd83dbSDimitry Andric OS.emitBytes(StringRef("\0", 1)); 10660b57cec5SDimitry Andric StringOffset += S.size() + 1; 10670b57cec5SDimitry Andric } 10680b57cec5SDimitry Andric } 10690b57cec5SDimitry Andric 10700b57cec5SDimitry Andric void BTFDebug::emitBTFExtSection() { 10718bcb0991SDimitry Andric // Do not emit section if empty FuncInfoTable and LineInfoTable 10728bcb0991SDimitry Andric // and FieldRelocTable. 10730b57cec5SDimitry Andric if (!FuncInfoTable.size() && !LineInfoTable.size() && 10748bcb0991SDimitry Andric !FieldRelocTable.size()) 10750b57cec5SDimitry Andric return; 10760b57cec5SDimitry Andric 10770b57cec5SDimitry Andric MCContext &Ctx = OS.getContext(); 1078349cc55cSDimitry Andric MCSectionELF *Sec = Ctx.getELFSection(".BTF.ext", ELF::SHT_PROGBITS, 0); 1079349cc55cSDimitry Andric Sec->setAlignment(Align(4)); 108081ad6265SDimitry Andric OS.switchSection(Sec); 10810b57cec5SDimitry Andric 10820b57cec5SDimitry Andric // Emit header. 10830b57cec5SDimitry Andric emitCommonHeader(); 10845ffd83dbSDimitry Andric OS.emitInt32(BTF::ExtHeaderSize); 10850b57cec5SDimitry Andric 10860b57cec5SDimitry Andric // Account for FuncInfo/LineInfo record size as well. 10870b57cec5SDimitry Andric uint32_t FuncLen = 4, LineLen = 4; 10888bcb0991SDimitry Andric // Do not account for optional FieldReloc. 10898bcb0991SDimitry Andric uint32_t FieldRelocLen = 0; 10900b57cec5SDimitry Andric for (const auto &FuncSec : FuncInfoTable) { 10910b57cec5SDimitry Andric FuncLen += BTF::SecFuncInfoSize; 10920b57cec5SDimitry Andric FuncLen += FuncSec.second.size() * BTF::BPFFuncInfoSize; 10930b57cec5SDimitry Andric } 10940b57cec5SDimitry Andric for (const auto &LineSec : LineInfoTable) { 10950b57cec5SDimitry Andric LineLen += BTF::SecLineInfoSize; 10960b57cec5SDimitry Andric LineLen += LineSec.second.size() * BTF::BPFLineInfoSize; 10970b57cec5SDimitry Andric } 10988bcb0991SDimitry Andric for (const auto &FieldRelocSec : FieldRelocTable) { 10998bcb0991SDimitry Andric FieldRelocLen += BTF::SecFieldRelocSize; 11008bcb0991SDimitry Andric FieldRelocLen += FieldRelocSec.second.size() * BTF::BPFFieldRelocSize; 11010b57cec5SDimitry Andric } 11020b57cec5SDimitry Andric 11038bcb0991SDimitry Andric if (FieldRelocLen) 11048bcb0991SDimitry Andric FieldRelocLen += 4; 11050b57cec5SDimitry Andric 11065ffd83dbSDimitry Andric OS.emitInt32(0); 11075ffd83dbSDimitry Andric OS.emitInt32(FuncLen); 11085ffd83dbSDimitry Andric OS.emitInt32(FuncLen); 11095ffd83dbSDimitry Andric OS.emitInt32(LineLen); 11105ffd83dbSDimitry Andric OS.emitInt32(FuncLen + LineLen); 11115ffd83dbSDimitry Andric OS.emitInt32(FieldRelocLen); 11120b57cec5SDimitry Andric 11130b57cec5SDimitry Andric // Emit func_info table. 11140b57cec5SDimitry Andric OS.AddComment("FuncInfo"); 11155ffd83dbSDimitry Andric OS.emitInt32(BTF::BPFFuncInfoSize); 11160b57cec5SDimitry Andric for (const auto &FuncSec : FuncInfoTable) { 11170b57cec5SDimitry Andric OS.AddComment("FuncInfo section string offset=" + 11180b57cec5SDimitry Andric std::to_string(FuncSec.first)); 11195ffd83dbSDimitry Andric OS.emitInt32(FuncSec.first); 11205ffd83dbSDimitry Andric OS.emitInt32(FuncSec.second.size()); 11210b57cec5SDimitry Andric for (const auto &FuncInfo : FuncSec.second) { 11225ffd83dbSDimitry Andric Asm->emitLabelReference(FuncInfo.Label, 4); 11235ffd83dbSDimitry Andric OS.emitInt32(FuncInfo.TypeId); 11240b57cec5SDimitry Andric } 11250b57cec5SDimitry Andric } 11260b57cec5SDimitry Andric 11270b57cec5SDimitry Andric // Emit line_info table. 11280b57cec5SDimitry Andric OS.AddComment("LineInfo"); 11295ffd83dbSDimitry Andric OS.emitInt32(BTF::BPFLineInfoSize); 11300b57cec5SDimitry Andric for (const auto &LineSec : LineInfoTable) { 11310b57cec5SDimitry Andric OS.AddComment("LineInfo section string offset=" + 11320b57cec5SDimitry Andric std::to_string(LineSec.first)); 11335ffd83dbSDimitry Andric OS.emitInt32(LineSec.first); 11345ffd83dbSDimitry Andric OS.emitInt32(LineSec.second.size()); 11350b57cec5SDimitry Andric for (const auto &LineInfo : LineSec.second) { 11365ffd83dbSDimitry Andric Asm->emitLabelReference(LineInfo.Label, 4); 11375ffd83dbSDimitry Andric OS.emitInt32(LineInfo.FileNameOff); 11385ffd83dbSDimitry Andric OS.emitInt32(LineInfo.LineOff); 11390b57cec5SDimitry Andric OS.AddComment("Line " + std::to_string(LineInfo.LineNum) + " Col " + 11400b57cec5SDimitry Andric std::to_string(LineInfo.ColumnNum)); 11415ffd83dbSDimitry Andric OS.emitInt32(LineInfo.LineNum << 10 | LineInfo.ColumnNum); 11420b57cec5SDimitry Andric } 11430b57cec5SDimitry Andric } 11440b57cec5SDimitry Andric 11458bcb0991SDimitry Andric // Emit field reloc table. 11468bcb0991SDimitry Andric if (FieldRelocLen) { 11478bcb0991SDimitry Andric OS.AddComment("FieldReloc"); 11485ffd83dbSDimitry Andric OS.emitInt32(BTF::BPFFieldRelocSize); 11498bcb0991SDimitry Andric for (const auto &FieldRelocSec : FieldRelocTable) { 11508bcb0991SDimitry Andric OS.AddComment("Field reloc section string offset=" + 11518bcb0991SDimitry Andric std::to_string(FieldRelocSec.first)); 11525ffd83dbSDimitry Andric OS.emitInt32(FieldRelocSec.first); 11535ffd83dbSDimitry Andric OS.emitInt32(FieldRelocSec.second.size()); 11548bcb0991SDimitry Andric for (const auto &FieldRelocInfo : FieldRelocSec.second) { 11555ffd83dbSDimitry Andric Asm->emitLabelReference(FieldRelocInfo.Label, 4); 11565ffd83dbSDimitry Andric OS.emitInt32(FieldRelocInfo.TypeID); 11575ffd83dbSDimitry Andric OS.emitInt32(FieldRelocInfo.OffsetNameOff); 11585ffd83dbSDimitry Andric OS.emitInt32(FieldRelocInfo.RelocKind); 11590b57cec5SDimitry Andric } 11600b57cec5SDimitry Andric } 11610b57cec5SDimitry Andric } 11620b57cec5SDimitry Andric } 11630b57cec5SDimitry Andric 11640b57cec5SDimitry Andric void BTFDebug::beginFunctionImpl(const MachineFunction *MF) { 11650b57cec5SDimitry Andric auto *SP = MF->getFunction().getSubprogram(); 11660b57cec5SDimitry Andric auto *Unit = SP->getUnit(); 11670b57cec5SDimitry Andric 11680b57cec5SDimitry Andric if (Unit->getEmissionKind() == DICompileUnit::NoDebug) { 11690b57cec5SDimitry Andric SkipInstruction = true; 11700b57cec5SDimitry Andric return; 11710b57cec5SDimitry Andric } 11720b57cec5SDimitry Andric SkipInstruction = false; 11730b57cec5SDimitry Andric 11740b57cec5SDimitry Andric // Collect MapDef types. Map definition needs to collect 11750b57cec5SDimitry Andric // pointee types. Do it first. Otherwise, for the following 11760b57cec5SDimitry Andric // case: 11770b57cec5SDimitry Andric // struct m { ...}; 11780b57cec5SDimitry Andric // struct t { 11790b57cec5SDimitry Andric // struct m *key; 11800b57cec5SDimitry Andric // }; 11810b57cec5SDimitry Andric // foo(struct t *arg); 11820b57cec5SDimitry Andric // 11830b57cec5SDimitry Andric // struct mapdef { 11840b57cec5SDimitry Andric // ... 11850b57cec5SDimitry Andric // struct m *key; 11860b57cec5SDimitry Andric // ... 11870b57cec5SDimitry Andric // } __attribute__((section(".maps"))) hash_map; 11880b57cec5SDimitry Andric // 11890b57cec5SDimitry Andric // If subroutine foo is traversed first, a type chain 11900b57cec5SDimitry Andric // "ptr->struct m(fwd)" will be created and later on 11910b57cec5SDimitry Andric // when traversing mapdef, since "ptr->struct m" exists, 11920b57cec5SDimitry Andric // the traversal of "struct m" will be omitted. 11930b57cec5SDimitry Andric if (MapDefNotCollected) { 11940b57cec5SDimitry Andric processGlobals(true); 11950b57cec5SDimitry Andric MapDefNotCollected = false; 11960b57cec5SDimitry Andric } 11970b57cec5SDimitry Andric 11980b57cec5SDimitry Andric // Collect all types locally referenced in this function. 11990b57cec5SDimitry Andric // Use RetainedNodes so we can collect all argument names 12000b57cec5SDimitry Andric // even if the argument is not used. 12010b57cec5SDimitry Andric std::unordered_map<uint32_t, StringRef> FuncArgNames; 12020b57cec5SDimitry Andric for (const DINode *DN : SP->getRetainedNodes()) { 12030b57cec5SDimitry Andric if (const auto *DV = dyn_cast<DILocalVariable>(DN)) { 12040b57cec5SDimitry Andric // Collect function arguments for subprogram func type. 12050b57cec5SDimitry Andric uint32_t Arg = DV->getArg(); 12060b57cec5SDimitry Andric if (Arg) { 12070b57cec5SDimitry Andric visitTypeEntry(DV->getType()); 12080b57cec5SDimitry Andric FuncArgNames[Arg] = DV->getName(); 12090b57cec5SDimitry Andric } 12100b57cec5SDimitry Andric } 12110b57cec5SDimitry Andric } 12120b57cec5SDimitry Andric 12130b57cec5SDimitry Andric // Construct subprogram func proto type. 12140b57cec5SDimitry Andric uint32_t ProtoTypeId; 12150b57cec5SDimitry Andric visitSubroutineType(SP->getType(), true, FuncArgNames, ProtoTypeId); 12160b57cec5SDimitry Andric 12170b57cec5SDimitry Andric // Construct subprogram func type 1218480093f4SDimitry Andric uint8_t Scope = SP->isLocalToUnit() ? BTF::FUNC_STATIC : BTF::FUNC_GLOBAL; 1219bdd1243dSDimitry Andric uint32_t FuncTypeId = processDISubprogram(SP, ProtoTypeId, Scope); 1220349cc55cSDimitry Andric 12210b57cec5SDimitry Andric for (const auto &TypeEntry : TypeEntries) 12220b57cec5SDimitry Andric TypeEntry->completeType(*this); 12230b57cec5SDimitry Andric 12240b57cec5SDimitry Andric // Construct funcinfo and the first lineinfo for the function. 12250b57cec5SDimitry Andric MCSymbol *FuncLabel = Asm->getFunctionBegin(); 12260b57cec5SDimitry Andric BTFFuncInfo FuncInfo; 12270b57cec5SDimitry Andric FuncInfo.Label = FuncLabel; 12280b57cec5SDimitry Andric FuncInfo.TypeId = FuncTypeId; 12290b57cec5SDimitry Andric if (FuncLabel->isInSection()) { 12300b57cec5SDimitry Andric MCSection &Section = FuncLabel->getSection(); 12310b57cec5SDimitry Andric const MCSectionELF *SectionELF = dyn_cast<MCSectionELF>(&Section); 12320b57cec5SDimitry Andric assert(SectionELF && "Null section for Function Label"); 12335ffd83dbSDimitry Andric SecNameOff = addString(SectionELF->getName()); 12340b57cec5SDimitry Andric } else { 12350b57cec5SDimitry Andric SecNameOff = addString(".text"); 12360b57cec5SDimitry Andric } 12370b57cec5SDimitry Andric FuncInfoTable[SecNameOff].push_back(FuncInfo); 12380b57cec5SDimitry Andric } 12390b57cec5SDimitry Andric 12400b57cec5SDimitry Andric void BTFDebug::endFunctionImpl(const MachineFunction *MF) { 12410b57cec5SDimitry Andric SkipInstruction = false; 12420b57cec5SDimitry Andric LineInfoGenerated = false; 12430b57cec5SDimitry Andric SecNameOff = 0; 12440b57cec5SDimitry Andric } 12450b57cec5SDimitry Andric 12465ffd83dbSDimitry Andric /// On-demand populate types as requested from abstract member 12475ffd83dbSDimitry Andric /// accessing or preserve debuginfo type. 12485ffd83dbSDimitry Andric unsigned BTFDebug::populateType(const DIType *Ty) { 12490b57cec5SDimitry Andric unsigned Id; 12500b57cec5SDimitry Andric visitTypeEntry(Ty, Id, false, false); 12510b57cec5SDimitry Andric for (const auto &TypeEntry : TypeEntries) 12520b57cec5SDimitry Andric TypeEntry->completeType(*this); 12530b57cec5SDimitry Andric return Id; 12540b57cec5SDimitry Andric } 12550b57cec5SDimitry Andric 12568bcb0991SDimitry Andric /// Generate a struct member field relocation. 12575ffd83dbSDimitry Andric void BTFDebug::generatePatchImmReloc(const MCSymbol *ORSym, uint32_t RootId, 12585ffd83dbSDimitry Andric const GlobalVariable *GVar, bool IsAma) { 12595ffd83dbSDimitry Andric BTFFieldReloc FieldReloc; 12605ffd83dbSDimitry Andric FieldReloc.Label = ORSym; 12615ffd83dbSDimitry Andric FieldReloc.TypeID = RootId; 12625ffd83dbSDimitry Andric 12635ffd83dbSDimitry Andric StringRef AccessPattern = GVar->getName(); 12648bcb0991SDimitry Andric size_t FirstDollar = AccessPattern.find_first_of('$'); 12655ffd83dbSDimitry Andric if (IsAma) { 12668bcb0991SDimitry Andric size_t FirstColon = AccessPattern.find_first_of(':'); 12678bcb0991SDimitry Andric size_t SecondColon = AccessPattern.find_first_of(':', FirstColon + 1); 12688bcb0991SDimitry Andric StringRef IndexPattern = AccessPattern.substr(FirstDollar + 1); 12698bcb0991SDimitry Andric StringRef RelocKindStr = AccessPattern.substr(FirstColon + 1, 12708bcb0991SDimitry Andric SecondColon - FirstColon); 12718bcb0991SDimitry Andric StringRef PatchImmStr = AccessPattern.substr(SecondColon + 1, 12728bcb0991SDimitry Andric FirstDollar - SecondColon); 12730b57cec5SDimitry Andric 12748bcb0991SDimitry Andric FieldReloc.OffsetNameOff = addString(IndexPattern); 12755ffd83dbSDimitry Andric FieldReloc.RelocKind = std::stoull(std::string(RelocKindStr)); 1276e8d8bef9SDimitry Andric PatchImms[GVar] = std::make_pair(std::stoll(std::string(PatchImmStr)), 1277e8d8bef9SDimitry Andric FieldReloc.RelocKind); 12785ffd83dbSDimitry Andric } else { 12795ffd83dbSDimitry Andric StringRef RelocStr = AccessPattern.substr(FirstDollar + 1); 12805ffd83dbSDimitry Andric FieldReloc.OffsetNameOff = addString("0"); 12815ffd83dbSDimitry Andric FieldReloc.RelocKind = std::stoull(std::string(RelocStr)); 1282e8d8bef9SDimitry Andric PatchImms[GVar] = std::make_pair(RootId, FieldReloc.RelocKind); 12835ffd83dbSDimitry Andric } 12848bcb0991SDimitry Andric FieldRelocTable[SecNameOff].push_back(FieldReloc); 12850b57cec5SDimitry Andric } 12860b57cec5SDimitry Andric 1287fe6060f1SDimitry Andric void BTFDebug::processGlobalValue(const MachineOperand &MO) { 12880b57cec5SDimitry Andric // check whether this is a candidate or not 12890b57cec5SDimitry Andric if (MO.isGlobal()) { 12900b57cec5SDimitry Andric const GlobalValue *GVal = MO.getGlobal(); 12910b57cec5SDimitry Andric auto *GVar = dyn_cast<GlobalVariable>(GVal); 1292fe6060f1SDimitry Andric if (!GVar) { 1293fe6060f1SDimitry Andric // Not a global variable. Maybe an extern function reference. 1294fe6060f1SDimitry Andric processFuncPrototypes(dyn_cast<Function>(GVal)); 12955ffd83dbSDimitry Andric return; 1296fe6060f1SDimitry Andric } 12975ffd83dbSDimitry Andric 12985ffd83dbSDimitry Andric if (!GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr) && 12995ffd83dbSDimitry Andric !GVar->hasAttribute(BPFCoreSharedInfo::TypeIdAttr)) 13005ffd83dbSDimitry Andric return; 13015ffd83dbSDimitry Andric 13020b57cec5SDimitry Andric MCSymbol *ORSym = OS.getContext().createTempSymbol(); 13035ffd83dbSDimitry Andric OS.emitLabel(ORSym); 13040b57cec5SDimitry Andric 13050b57cec5SDimitry Andric MDNode *MDN = GVar->getMetadata(LLVMContext::MD_preserve_access_index); 13065ffd83dbSDimitry Andric uint32_t RootId = populateType(dyn_cast<DIType>(MDN)); 13075ffd83dbSDimitry Andric generatePatchImmReloc(ORSym, RootId, GVar, 13085ffd83dbSDimitry Andric GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)); 13090b57cec5SDimitry Andric } 13100b57cec5SDimitry Andric } 13110b57cec5SDimitry Andric 13120b57cec5SDimitry Andric void BTFDebug::beginInstruction(const MachineInstr *MI) { 13130b57cec5SDimitry Andric DebugHandlerBase::beginInstruction(MI); 13140b57cec5SDimitry Andric 13150b57cec5SDimitry Andric if (SkipInstruction || MI->isMetaInstruction() || 13160b57cec5SDimitry Andric MI->getFlag(MachineInstr::FrameSetup)) 13170b57cec5SDimitry Andric return; 13180b57cec5SDimitry Andric 13190b57cec5SDimitry Andric if (MI->isInlineAsm()) { 13200b57cec5SDimitry Andric // Count the number of register definitions to find the asm string. 13210b57cec5SDimitry Andric unsigned NumDefs = 0; 13225f757f3fSDimitry Andric while (true) { 13235f757f3fSDimitry Andric const MachineOperand &MO = MI->getOperand(NumDefs); 13245f757f3fSDimitry Andric if (MO.isReg() && MO.isDef()) { 13255f757f3fSDimitry Andric ++NumDefs; 13265f757f3fSDimitry Andric continue; 13275f757f3fSDimitry Andric } 13280b57cec5SDimitry Andric // Skip this inline asm instruction if the asmstr is empty. 13295f757f3fSDimitry Andric const char *AsmStr = MO.getSymbolName(); 13300b57cec5SDimitry Andric if (AsmStr[0] == 0) 13310b57cec5SDimitry Andric return; 13325f757f3fSDimitry Andric break; 13335f757f3fSDimitry Andric } 13340b57cec5SDimitry Andric } 13350b57cec5SDimitry Andric 1336480093f4SDimitry Andric if (MI->getOpcode() == BPF::LD_imm64) { 1337480093f4SDimitry Andric // If the insn is "r2 = LD_imm64 @<an AmaAttr global>", 1338480093f4SDimitry Andric // add this insn into the .BTF.ext FieldReloc subsection. 1339480093f4SDimitry Andric // Relocation looks like: 1340480093f4SDimitry Andric // . SecName: 1341480093f4SDimitry Andric // . InstOffset 1342480093f4SDimitry Andric // . TypeID 1343480093f4SDimitry Andric // . OffSetNameOff 1344480093f4SDimitry Andric // . RelocType 1345480093f4SDimitry Andric // Later, the insn is replaced with "r2 = <offset>" 1346480093f4SDimitry Andric // where "<offset>" equals to the offset based on current 1347480093f4SDimitry Andric // type definitions. 13485ffd83dbSDimitry Andric // 13495ffd83dbSDimitry Andric // If the insn is "r2 = LD_imm64 @<an TypeIdAttr global>", 13505ffd83dbSDimitry Andric // The LD_imm64 result will be replaced with a btf type id. 1351fe6060f1SDimitry Andric processGlobalValue(MI->getOperand(1)); 13525f757f3fSDimitry Andric } else if (MI->getOpcode() == BPF::CORE_LD64 || 13535f757f3fSDimitry Andric MI->getOpcode() == BPF::CORE_LD32 || 13545f757f3fSDimitry Andric MI->getOpcode() == BPF::CORE_ST || 1355480093f4SDimitry Andric MI->getOpcode() == BPF::CORE_SHIFT) { 1356480093f4SDimitry Andric // relocation insn is a load, store or shift insn. 1357fe6060f1SDimitry Andric processGlobalValue(MI->getOperand(3)); 1358480093f4SDimitry Andric } else if (MI->getOpcode() == BPF::JAL) { 1359480093f4SDimitry Andric // check extern function references 1360480093f4SDimitry Andric const MachineOperand &MO = MI->getOperand(0); 1361480093f4SDimitry Andric if (MO.isGlobal()) { 1362480093f4SDimitry Andric processFuncPrototypes(dyn_cast<Function>(MO.getGlobal())); 1363480093f4SDimitry Andric } 1364480093f4SDimitry Andric } 13650b57cec5SDimitry Andric 1366e8d8bef9SDimitry Andric if (!CurMI) // no debug info 1367e8d8bef9SDimitry Andric return; 1368e8d8bef9SDimitry Andric 1369*0fca6ea1SDimitry Andric // Skip this instruction if no DebugLoc, the DebugLoc 1370*0fca6ea1SDimitry Andric // is the same as the previous instruction or Line is 0. 13710b57cec5SDimitry Andric const DebugLoc &DL = MI->getDebugLoc(); 1372*0fca6ea1SDimitry Andric if (!DL || PrevInstLoc == DL || DL.getLine() == 0) { 13730b57cec5SDimitry Andric // This instruction will be skipped, no LineInfo has 13740b57cec5SDimitry Andric // been generated, construct one based on function signature. 13750b57cec5SDimitry Andric if (LineInfoGenerated == false) { 13760b57cec5SDimitry Andric auto *S = MI->getMF()->getFunction().getSubprogram(); 13778a4dda33SDimitry Andric if (!S) 13788a4dda33SDimitry Andric return; 13790b57cec5SDimitry Andric MCSymbol *FuncLabel = Asm->getFunctionBegin(); 1380*0fca6ea1SDimitry Andric constructLineInfo(FuncLabel, S->getFile(), S->getLine(), 0); 13810b57cec5SDimitry Andric LineInfoGenerated = true; 13820b57cec5SDimitry Andric } 13830b57cec5SDimitry Andric 13840b57cec5SDimitry Andric return; 13850b57cec5SDimitry Andric } 13860b57cec5SDimitry Andric 13870b57cec5SDimitry Andric // Create a temporary label to remember the insn for lineinfo. 13880b57cec5SDimitry Andric MCSymbol *LineSym = OS.getContext().createTempSymbol(); 13895ffd83dbSDimitry Andric OS.emitLabel(LineSym); 13900b57cec5SDimitry Andric 13910b57cec5SDimitry Andric // Construct the lineinfo. 1392*0fca6ea1SDimitry Andric constructLineInfo(LineSym, DL->getFile(), DL.getLine(), DL.getCol()); 13930b57cec5SDimitry Andric 13940b57cec5SDimitry Andric LineInfoGenerated = true; 13950b57cec5SDimitry Andric PrevInstLoc = DL; 13960b57cec5SDimitry Andric } 13970b57cec5SDimitry Andric 13980b57cec5SDimitry Andric void BTFDebug::processGlobals(bool ProcessingMapDef) { 13990b57cec5SDimitry Andric // Collect all types referenced by globals. 14000b57cec5SDimitry Andric const Module *M = MMI->getModule(); 14010b57cec5SDimitry Andric for (const GlobalVariable &Global : M->globals()) { 14020b57cec5SDimitry Andric // Decide the section name. 14030b57cec5SDimitry Andric StringRef SecName; 1404bdd1243dSDimitry Andric std::optional<SectionKind> GVKind; 1405bdd1243dSDimitry Andric 1406bdd1243dSDimitry Andric if (!Global.isDeclarationForLinker()) 1407bdd1243dSDimitry Andric GVKind = TargetLoweringObjectFile::getKindForGlobal(&Global, Asm->TM); 1408bdd1243dSDimitry Andric 1409bdd1243dSDimitry Andric if (Global.isDeclarationForLinker()) 1410bdd1243dSDimitry Andric SecName = Global.hasSection() ? Global.getSection() : ""; 1411bdd1243dSDimitry Andric else if (GVKind->isCommon()) 1412bdd1243dSDimitry Andric SecName = ".bss"; 1413bdd1243dSDimitry Andric else { 1414bdd1243dSDimitry Andric TargetLoweringObjectFile *TLOF = Asm->TM.getObjFileLowering(); 1415bdd1243dSDimitry Andric MCSection *Sec = TLOF->SectionForGlobal(&Global, Asm->TM); 1416bdd1243dSDimitry Andric SecName = Sec->getName(); 14170b57cec5SDimitry Andric } 14180b57cec5SDimitry Andric 14195f757f3fSDimitry Andric if (ProcessingMapDef != SecName.starts_with(".maps")) 14200b57cec5SDimitry Andric continue; 14210b57cec5SDimitry Andric 1422e8d8bef9SDimitry Andric // Create a .rodata datasec if the global variable is an initialized 1423e8d8bef9SDimitry Andric // constant with private linkage and if it won't be in .rodata.str<#> 1424e8d8bef9SDimitry Andric // and .rodata.cst<#> sections. 1425e8d8bef9SDimitry Andric if (SecName == ".rodata" && Global.hasPrivateLinkage() && 1426e8d8bef9SDimitry Andric DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) { 1427e8d8bef9SDimitry Andric // skip .rodata.str<#> and .rodata.cst<#> sections 1428bdd1243dSDimitry Andric if (!GVKind->isMergeableCString() && !GVKind->isMergeableConst()) { 1429e8d8bef9SDimitry Andric DataSecEntries[std::string(SecName)] = 1430e8d8bef9SDimitry Andric std::make_unique<BTFKindDataSec>(Asm, std::string(SecName)); 1431e8d8bef9SDimitry Andric } 1432e8d8bef9SDimitry Andric } 1433e8d8bef9SDimitry Andric 14340b57cec5SDimitry Andric SmallVector<DIGlobalVariableExpression *, 1> GVs; 14350b57cec5SDimitry Andric Global.getDebugInfo(GVs); 1436480093f4SDimitry Andric 1437480093f4SDimitry Andric // No type information, mostly internal, skip it. 1438480093f4SDimitry Andric if (GVs.size() == 0) 1439480093f4SDimitry Andric continue; 1440480093f4SDimitry Andric 14410b57cec5SDimitry Andric uint32_t GVTypeId = 0; 1442349cc55cSDimitry Andric DIGlobalVariable *DIGlobal = nullptr; 14430b57cec5SDimitry Andric for (auto *GVE : GVs) { 1444349cc55cSDimitry Andric DIGlobal = GVE->getVariable(); 14455f757f3fSDimitry Andric if (SecName.starts_with(".maps")) 1446349cc55cSDimitry Andric visitMapDefType(DIGlobal->getType(), GVTypeId); 14470b57cec5SDimitry Andric else 1448349cc55cSDimitry Andric visitTypeEntry(DIGlobal->getType(), GVTypeId, false, false); 14490b57cec5SDimitry Andric break; 14500b57cec5SDimitry Andric } 14510b57cec5SDimitry Andric 14520b57cec5SDimitry Andric // Only support the following globals: 14530b57cec5SDimitry Andric // . static variables 1454480093f4SDimitry Andric // . non-static weak or non-weak global variables 1455480093f4SDimitry Andric // . weak or non-weak extern global variables 1456480093f4SDimitry Andric // Whether DataSec is readonly or not can be found from corresponding ELF 1457480093f4SDimitry Andric // section flags. Whether a BTF_KIND_VAR is a weak symbol or not 1458480093f4SDimitry Andric // can be found from the corresponding ELF symbol table. 14590b57cec5SDimitry Andric auto Linkage = Global.getLinkage(); 14600b57cec5SDimitry Andric if (Linkage != GlobalValue::InternalLinkage && 1461480093f4SDimitry Andric Linkage != GlobalValue::ExternalLinkage && 1462480093f4SDimitry Andric Linkage != GlobalValue::WeakAnyLinkage && 146323408297SDimitry Andric Linkage != GlobalValue::WeakODRLinkage && 1464480093f4SDimitry Andric Linkage != GlobalValue::ExternalWeakLinkage) 14650b57cec5SDimitry Andric continue; 14660b57cec5SDimitry Andric 1467480093f4SDimitry Andric uint32_t GVarInfo; 1468480093f4SDimitry Andric if (Linkage == GlobalValue::InternalLinkage) { 1469480093f4SDimitry Andric GVarInfo = BTF::VAR_STATIC; 1470480093f4SDimitry Andric } else if (Global.hasInitializer()) { 1471480093f4SDimitry Andric GVarInfo = BTF::VAR_GLOBAL_ALLOCATED; 1472480093f4SDimitry Andric } else { 1473480093f4SDimitry Andric GVarInfo = BTF::VAR_GLOBAL_EXTERNAL; 1474480093f4SDimitry Andric } 1475480093f4SDimitry Andric 14760b57cec5SDimitry Andric auto VarEntry = 14778bcb0991SDimitry Andric std::make_unique<BTFKindVar>(Global.getName(), GVTypeId, GVarInfo); 14780b57cec5SDimitry Andric uint32_t VarId = addType(std::move(VarEntry)); 14790b57cec5SDimitry Andric 1480349cc55cSDimitry Andric processDeclAnnotations(DIGlobal->getAnnotations(), VarId, -1); 1481349cc55cSDimitry Andric 1482fe6060f1SDimitry Andric // An empty SecName means an extern variable without section attribute. 1483fe6060f1SDimitry Andric if (SecName.empty()) 1484fe6060f1SDimitry Andric continue; 1485480093f4SDimitry Andric 14860b57cec5SDimitry Andric // Find or create a DataSec 14875ffd83dbSDimitry Andric if (DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) { 14885ffd83dbSDimitry Andric DataSecEntries[std::string(SecName)] = 14895ffd83dbSDimitry Andric std::make_unique<BTFKindDataSec>(Asm, std::string(SecName)); 14900b57cec5SDimitry Andric } 14910b57cec5SDimitry Andric 14920b57cec5SDimitry Andric // Calculate symbol size 1493*0fca6ea1SDimitry Andric const DataLayout &DL = Global.getDataLayout(); 149404eeddc0SDimitry Andric uint32_t Size = DL.getTypeAllocSize(Global.getValueType()); 14950b57cec5SDimitry Andric 149623408297SDimitry Andric DataSecEntries[std::string(SecName)]->addDataSecEntry(VarId, 149723408297SDimitry Andric Asm->getSymbol(&Global), Size); 1498*0fca6ea1SDimitry Andric 1499*0fca6ea1SDimitry Andric if (Global.hasInitializer()) 1500*0fca6ea1SDimitry Andric processGlobalInitializer(Global.getInitializer()); 1501*0fca6ea1SDimitry Andric } 1502*0fca6ea1SDimitry Andric } 1503*0fca6ea1SDimitry Andric 1504*0fca6ea1SDimitry Andric /// Process global variable initializer in pursuit for function 1505*0fca6ea1SDimitry Andric /// pointers. Add discovered (extern) functions to BTF. Some (extern) 1506*0fca6ea1SDimitry Andric /// functions might have been missed otherwise. Every symbol needs BTF 1507*0fca6ea1SDimitry Andric /// info when linking with bpftool. Primary use case: "static" 1508*0fca6ea1SDimitry Andric /// initialization of BPF maps. 1509*0fca6ea1SDimitry Andric /// 1510*0fca6ea1SDimitry Andric /// struct { 1511*0fca6ea1SDimitry Andric /// __uint(type, BPF_MAP_TYPE_PROG_ARRAY); 1512*0fca6ea1SDimitry Andric /// ... 1513*0fca6ea1SDimitry Andric /// } prog_map SEC(".maps") = { .values = { extern_func } }; 1514*0fca6ea1SDimitry Andric /// 1515*0fca6ea1SDimitry Andric void BTFDebug::processGlobalInitializer(const Constant *C) { 1516*0fca6ea1SDimitry Andric if (auto *Fn = dyn_cast<Function>(C)) 1517*0fca6ea1SDimitry Andric processFuncPrototypes(Fn); 1518*0fca6ea1SDimitry Andric if (auto *CA = dyn_cast<ConstantAggregate>(C)) { 1519*0fca6ea1SDimitry Andric for (unsigned I = 0, N = CA->getNumOperands(); I < N; ++I) 1520*0fca6ea1SDimitry Andric processGlobalInitializer(CA->getOperand(I)); 15210b57cec5SDimitry Andric } 15220b57cec5SDimitry Andric } 15230b57cec5SDimitry Andric 15240b57cec5SDimitry Andric /// Emit proper patchable instructions. 15250b57cec5SDimitry Andric bool BTFDebug::InstLower(const MachineInstr *MI, MCInst &OutMI) { 15260b57cec5SDimitry Andric if (MI->getOpcode() == BPF::LD_imm64) { 15270b57cec5SDimitry Andric const MachineOperand &MO = MI->getOperand(1); 15280b57cec5SDimitry Andric if (MO.isGlobal()) { 15290b57cec5SDimitry Andric const GlobalValue *GVal = MO.getGlobal(); 15300b57cec5SDimitry Andric auto *GVar = dyn_cast<GlobalVariable>(GVal); 15315ffd83dbSDimitry Andric if (GVar) { 15325ffd83dbSDimitry Andric // Emit "mov ri, <imm>" 1533e8d8bef9SDimitry Andric int64_t Imm; 1534e8d8bef9SDimitry Andric uint32_t Reloc; 15355ffd83dbSDimitry Andric if (GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr) || 1536e8d8bef9SDimitry Andric GVar->hasAttribute(BPFCoreSharedInfo::TypeIdAttr)) { 1537e8d8bef9SDimitry Andric Imm = PatchImms[GVar].first; 1538e8d8bef9SDimitry Andric Reloc = PatchImms[GVar].second; 1539e8d8bef9SDimitry Andric } else { 15405ffd83dbSDimitry Andric return false; 1541e8d8bef9SDimitry Andric } 15425ffd83dbSDimitry Andric 15435f757f3fSDimitry Andric if (Reloc == BTF::ENUM_VALUE_EXISTENCE || Reloc == BTF::ENUM_VALUE || 15445f757f3fSDimitry Andric Reloc == BTF::BTF_TYPE_ID_LOCAL || Reloc == BTF::BTF_TYPE_ID_REMOTE) 1545e8d8bef9SDimitry Andric OutMI.setOpcode(BPF::LD_imm64); 1546e8d8bef9SDimitry Andric else 15470b57cec5SDimitry Andric OutMI.setOpcode(BPF::MOV_ri); 15480b57cec5SDimitry Andric OutMI.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); 15490b57cec5SDimitry Andric OutMI.addOperand(MCOperand::createImm(Imm)); 15500b57cec5SDimitry Andric return true; 15510b57cec5SDimitry Andric } 15520b57cec5SDimitry Andric } 15535f757f3fSDimitry Andric } else if (MI->getOpcode() == BPF::CORE_LD64 || 15545f757f3fSDimitry Andric MI->getOpcode() == BPF::CORE_LD32 || 15555f757f3fSDimitry Andric MI->getOpcode() == BPF::CORE_ST || 1556480093f4SDimitry Andric MI->getOpcode() == BPF::CORE_SHIFT) { 1557480093f4SDimitry Andric const MachineOperand &MO = MI->getOperand(3); 1558480093f4SDimitry Andric if (MO.isGlobal()) { 1559480093f4SDimitry Andric const GlobalValue *GVal = MO.getGlobal(); 1560480093f4SDimitry Andric auto *GVar = dyn_cast<GlobalVariable>(GVal); 1561480093f4SDimitry Andric if (GVar && GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) { 1562e8d8bef9SDimitry Andric uint32_t Imm = PatchImms[GVar].first; 1563480093f4SDimitry Andric OutMI.setOpcode(MI->getOperand(1).getImm()); 1564480093f4SDimitry Andric if (MI->getOperand(0).isImm()) 1565480093f4SDimitry Andric OutMI.addOperand(MCOperand::createImm(MI->getOperand(0).getImm())); 1566480093f4SDimitry Andric else 1567480093f4SDimitry Andric OutMI.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); 1568480093f4SDimitry Andric OutMI.addOperand(MCOperand::createReg(MI->getOperand(2).getReg())); 1569480093f4SDimitry Andric OutMI.addOperand(MCOperand::createImm(Imm)); 1570480093f4SDimitry Andric return true; 1571480093f4SDimitry Andric } 1572480093f4SDimitry Andric } 15730b57cec5SDimitry Andric } 15740b57cec5SDimitry Andric return false; 15750b57cec5SDimitry Andric } 15760b57cec5SDimitry Andric 1577480093f4SDimitry Andric void BTFDebug::processFuncPrototypes(const Function *F) { 1578480093f4SDimitry Andric if (!F) 1579480093f4SDimitry Andric return; 1580480093f4SDimitry Andric 1581480093f4SDimitry Andric const DISubprogram *SP = F->getSubprogram(); 1582480093f4SDimitry Andric if (!SP || SP->isDefinition()) 1583480093f4SDimitry Andric return; 1584480093f4SDimitry Andric 1585480093f4SDimitry Andric // Do not emit again if already emitted. 158681ad6265SDimitry Andric if (!ProtoFunctions.insert(F).second) 1587480093f4SDimitry Andric return; 1588480093f4SDimitry Andric 1589480093f4SDimitry Andric uint32_t ProtoTypeId; 1590480093f4SDimitry Andric const std::unordered_map<uint32_t, StringRef> FuncArgNames; 1591480093f4SDimitry Andric visitSubroutineType(SP->getType(), false, FuncArgNames, ProtoTypeId); 1592bdd1243dSDimitry Andric uint32_t FuncId = processDISubprogram(SP, ProtoTypeId, BTF::FUNC_EXTERN); 1593349cc55cSDimitry Andric 159423408297SDimitry Andric if (F->hasSection()) { 159523408297SDimitry Andric StringRef SecName = F->getSection(); 159623408297SDimitry Andric 159723408297SDimitry Andric if (DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) { 159823408297SDimitry Andric DataSecEntries[std::string(SecName)] = 159923408297SDimitry Andric std::make_unique<BTFKindDataSec>(Asm, std::string(SecName)); 160023408297SDimitry Andric } 160123408297SDimitry Andric 160223408297SDimitry Andric // We really don't know func size, set it to 0. 160323408297SDimitry Andric DataSecEntries[std::string(SecName)]->addDataSecEntry(FuncId, 160423408297SDimitry Andric Asm->getSymbol(F), 0); 160523408297SDimitry Andric } 1606480093f4SDimitry Andric } 1607480093f4SDimitry Andric 16080b57cec5SDimitry Andric void BTFDebug::endModule() { 16090b57cec5SDimitry Andric // Collect MapDef globals if not collected yet. 16100b57cec5SDimitry Andric if (MapDefNotCollected) { 16110b57cec5SDimitry Andric processGlobals(true); 16120b57cec5SDimitry Andric MapDefNotCollected = false; 16130b57cec5SDimitry Andric } 16140b57cec5SDimitry Andric 16150b57cec5SDimitry Andric // Collect global types/variables except MapDef globals. 16160b57cec5SDimitry Andric processGlobals(false); 1617480093f4SDimitry Andric 16180b57cec5SDimitry Andric for (auto &DataSec : DataSecEntries) 16190b57cec5SDimitry Andric addType(std::move(DataSec.second)); 16200b57cec5SDimitry Andric 16210b57cec5SDimitry Andric // Fixups 16220b57cec5SDimitry Andric for (auto &Fixup : FixupDerivedTypes) { 162381ad6265SDimitry Andric const DICompositeType *CTy = Fixup.first; 162481ad6265SDimitry Andric StringRef TypeName = CTy->getName(); 162581ad6265SDimitry Andric bool IsUnion = CTy->getTag() == dwarf::DW_TAG_union_type; 16260b57cec5SDimitry Andric 16270b57cec5SDimitry Andric // Search through struct types 16280b57cec5SDimitry Andric uint32_t StructTypeId = 0; 16290b57cec5SDimitry Andric for (const auto &StructType : StructTypes) { 16300b57cec5SDimitry Andric if (StructType->getName() == TypeName) { 16310b57cec5SDimitry Andric StructTypeId = StructType->getId(); 16320b57cec5SDimitry Andric break; 16330b57cec5SDimitry Andric } 16340b57cec5SDimitry Andric } 16350b57cec5SDimitry Andric 16360b57cec5SDimitry Andric if (StructTypeId == 0) { 16378bcb0991SDimitry Andric auto FwdTypeEntry = std::make_unique<BTFTypeFwd>(TypeName, IsUnion); 16380b57cec5SDimitry Andric StructTypeId = addType(std::move(FwdTypeEntry)); 16390b57cec5SDimitry Andric } 16400b57cec5SDimitry Andric 164181ad6265SDimitry Andric for (auto &TypeInfo : Fixup.second) { 164281ad6265SDimitry Andric const DIDerivedType *DTy = TypeInfo.first; 164381ad6265SDimitry Andric BTFTypeDerived *BDType = TypeInfo.second; 164481ad6265SDimitry Andric 164581ad6265SDimitry Andric int TmpTypeId = genBTFTypeTags(DTy, StructTypeId); 164681ad6265SDimitry Andric if (TmpTypeId >= 0) 164781ad6265SDimitry Andric BDType->setPointeeType(TmpTypeId); 164881ad6265SDimitry Andric else 164981ad6265SDimitry Andric BDType->setPointeeType(StructTypeId); 16500b57cec5SDimitry Andric } 16510b57cec5SDimitry Andric } 16520b57cec5SDimitry Andric 16530b57cec5SDimitry Andric // Complete BTF type cross refereences. 16540b57cec5SDimitry Andric for (const auto &TypeEntry : TypeEntries) 16550b57cec5SDimitry Andric TypeEntry->completeType(*this); 16560b57cec5SDimitry Andric 16570b57cec5SDimitry Andric // Emit BTF sections. 16580b57cec5SDimitry Andric emitBTFSection(); 16590b57cec5SDimitry Andric emitBTFExtSection(); 16600b57cec5SDimitry Andric } 1661