17b410ac3SYonghong Song //===- BTFDebug.cpp - BTF Generator ---------------------------------------===//
27b410ac3SYonghong Song //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67b410ac3SYonghong Song //
77b410ac3SYonghong Song //===----------------------------------------------------------------------===//
87b410ac3SYonghong Song //
97b410ac3SYonghong Song // This file contains support for writing BTF debug info.
107b410ac3SYonghong Song //
117b410ac3SYonghong Song //===----------------------------------------------------------------------===//
127b410ac3SYonghong Song
137b410ac3SYonghong Song #include "BTFDebug.h"
14d3d88d08SYonghong Song #include "BPF.h"
15d3d88d08SYonghong Song #include "BPFCORE.h"
16d3d88d08SYonghong Song #include "MCTargetDesc/BPFMCTargetDesc.h"
177b410ac3SYonghong Song #include "llvm/BinaryFormat/ELF.h"
187b410ac3SYonghong Song #include "llvm/CodeGen/AsmPrinter.h"
197b410ac3SYonghong Song #include "llvm/CodeGen/MachineModuleInfo.h"
207b410ac3SYonghong Song #include "llvm/MC/MCContext.h"
217b410ac3SYonghong Song #include "llvm/MC/MCObjectFileInfo.h"
227b410ac3SYonghong Song #include "llvm/MC/MCSectionELF.h"
237b410ac3SYonghong Song #include "llvm/MC/MCStreamer.h"
2483db8871SFangrui Song #include "llvm/Support/LineIterator.h"
25ed98c1b3Sserge-sans-paille #include "llvm/Support/MemoryBuffer.h"
260e347c0fSYonghong Song #include "llvm/Target/TargetLoweringObjectFile.h"
277b410ac3SYonghong Song
287b410ac3SYonghong Song using namespace llvm;
297b410ac3SYonghong Song
307b410ac3SYonghong Song static const char *BTFKindStr[] = {
317b410ac3SYonghong Song #define HANDLE_BTF_KIND(ID, NAME) "BTF_KIND_" #NAME,
327b410ac3SYonghong Song #include "BTF.def"
337b410ac3SYonghong Song };
347b410ac3SYonghong Song
357b410ac3SYonghong Song /// Emit a BTF common type.
emitType(MCStreamer & OS)367b410ac3SYonghong Song void BTFTypeBase::emitType(MCStreamer &OS) {
377b410ac3SYonghong Song OS.AddComment(std::string(BTFKindStr[Kind]) + "(id = " + std::to_string(Id) +
387b410ac3SYonghong Song ")");
39692e0c96SFangrui Song OS.emitInt32(BTFType.NameOff);
407b410ac3SYonghong Song OS.AddComment("0x" + Twine::utohexstr(BTFType.Info));
41692e0c96SFangrui Song OS.emitInt32(BTFType.Info);
42692e0c96SFangrui Song OS.emitInt32(BTFType.Size);
437b410ac3SYonghong Song }
447b410ac3SYonghong Song
BTFTypeDerived(const DIDerivedType * DTy,unsigned Tag,bool NeedsFixup)45d3d88d08SYonghong Song BTFTypeDerived::BTFTypeDerived(const DIDerivedType *DTy, unsigned Tag,
46d3d88d08SYonghong Song bool NeedsFixup)
478d499bd5SYonghong Song : DTy(DTy), NeedsFixup(NeedsFixup), Name(DTy->getName()) {
487b410ac3SYonghong Song switch (Tag) {
497b410ac3SYonghong Song case dwarf::DW_TAG_pointer_type:
507b410ac3SYonghong Song Kind = BTF::BTF_KIND_PTR;
517b410ac3SYonghong Song break;
527b410ac3SYonghong Song case dwarf::DW_TAG_const_type:
537b410ac3SYonghong Song Kind = BTF::BTF_KIND_CONST;
547b410ac3SYonghong Song break;
557b410ac3SYonghong Song case dwarf::DW_TAG_volatile_type:
567b410ac3SYonghong Song Kind = BTF::BTF_KIND_VOLATILE;
577b410ac3SYonghong Song break;
587b410ac3SYonghong Song case dwarf::DW_TAG_typedef:
597b410ac3SYonghong Song Kind = BTF::BTF_KIND_TYPEDEF;
607b410ac3SYonghong Song break;
617b410ac3SYonghong Song case dwarf::DW_TAG_restrict_type:
627b410ac3SYonghong Song Kind = BTF::BTF_KIND_RESTRICT;
637b410ac3SYonghong Song break;
647b410ac3SYonghong Song default:
657b410ac3SYonghong Song llvm_unreachable("Unknown DIDerivedType Tag");
667b410ac3SYonghong Song }
677b410ac3SYonghong Song BTFType.Info = Kind << 24;
687b410ac3SYonghong Song }
697b410ac3SYonghong Song
708d499bd5SYonghong Song /// Used by DW_TAG_pointer_type only.
BTFTypeDerived(unsigned NextTypeId,unsigned Tag,StringRef Name)718d499bd5SYonghong Song BTFTypeDerived::BTFTypeDerived(unsigned NextTypeId, unsigned Tag,
728d499bd5SYonghong Song StringRef Name)
738d499bd5SYonghong Song : DTy(nullptr), NeedsFixup(false), Name(Name) {
748d499bd5SYonghong Song Kind = BTF::BTF_KIND_PTR;
758d499bd5SYonghong Song BTFType.Info = Kind << 24;
768d499bd5SYonghong Song BTFType.Type = NextTypeId;
778d499bd5SYonghong Song }
788d499bd5SYonghong Song
completeType(BTFDebug & BDebug)797b410ac3SYonghong Song void BTFTypeDerived::completeType(BTFDebug &BDebug) {
80d3d88d08SYonghong Song if (IsCompleted)
81d3d88d08SYonghong Song return;
82d3d88d08SYonghong Song IsCompleted = true;
83d3d88d08SYonghong Song
848d499bd5SYonghong Song BTFType.NameOff = BDebug.addString(Name);
857b410ac3SYonghong Song
868d499bd5SYonghong Song if (NeedsFixup || !DTy)
87d3d88d08SYonghong Song return;
88d3d88d08SYonghong Song
897b410ac3SYonghong Song // The base type for PTR/CONST/VOLATILE could be void.
90da82ce99SFangrui Song const DIType *ResolvedType = DTy->getBaseType();
917b410ac3SYonghong Song if (!ResolvedType) {
927b410ac3SYonghong Song assert((Kind == BTF::BTF_KIND_PTR || Kind == BTF::BTF_KIND_CONST ||
937b410ac3SYonghong Song Kind == BTF::BTF_KIND_VOLATILE) &&
947b410ac3SYonghong Song "Invalid null basetype");
957b410ac3SYonghong Song BTFType.Type = 0;
967b410ac3SYonghong Song } else {
977b410ac3SYonghong Song BTFType.Type = BDebug.getTypeId(ResolvedType);
987b410ac3SYonghong Song }
997b410ac3SYonghong Song }
1007b410ac3SYonghong Song
emitType(MCStreamer & OS)1017b410ac3SYonghong Song void BTFTypeDerived::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); }
1027b410ac3SYonghong Song
setPointeeType(uint32_t PointeeType)103d3d88d08SYonghong Song void BTFTypeDerived::setPointeeType(uint32_t PointeeType) {
104d3d88d08SYonghong Song BTFType.Type = PointeeType;
105d3d88d08SYonghong Song }
106d3d88d08SYonghong Song
1077b410ac3SYonghong Song /// Represent a struct/union forward declaration.
BTFTypeFwd(StringRef Name,bool IsUnion)1087b410ac3SYonghong Song BTFTypeFwd::BTFTypeFwd(StringRef Name, bool IsUnion) : Name(Name) {
1097b410ac3SYonghong Song Kind = BTF::BTF_KIND_FWD;
1107b410ac3SYonghong Song BTFType.Info = IsUnion << 31 | Kind << 24;
1117b410ac3SYonghong Song BTFType.Type = 0;
1127b410ac3SYonghong Song }
1137b410ac3SYonghong Song
completeType(BTFDebug & BDebug)1147b410ac3SYonghong Song void BTFTypeFwd::completeType(BTFDebug &BDebug) {
115d3d88d08SYonghong Song if (IsCompleted)
116d3d88d08SYonghong Song return;
117d3d88d08SYonghong Song IsCompleted = true;
118d3d88d08SYonghong Song
1197b410ac3SYonghong Song BTFType.NameOff = BDebug.addString(Name);
1207b410ac3SYonghong Song }
1217b410ac3SYonghong Song
emitType(MCStreamer & OS)1227b410ac3SYonghong Song void BTFTypeFwd::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); }
1237b410ac3SYonghong Song
BTFTypeInt(uint32_t Encoding,uint32_t SizeInBits,uint32_t OffsetInBits,StringRef TypeName)1247b410ac3SYonghong Song BTFTypeInt::BTFTypeInt(uint32_t Encoding, uint32_t SizeInBits,
1257b410ac3SYonghong Song uint32_t OffsetInBits, StringRef TypeName)
1267b410ac3SYonghong Song : Name(TypeName) {
1277b410ac3SYonghong Song // Translate IR int encoding to BTF int encoding.
1287b410ac3SYonghong Song uint8_t BTFEncoding;
1297b410ac3SYonghong Song switch (Encoding) {
1307b410ac3SYonghong Song case dwarf::DW_ATE_boolean:
1317b410ac3SYonghong Song BTFEncoding = BTF::INT_BOOL;
1327b410ac3SYonghong Song break;
1337b410ac3SYonghong Song case dwarf::DW_ATE_signed:
1347b410ac3SYonghong Song case dwarf::DW_ATE_signed_char:
1357b410ac3SYonghong Song BTFEncoding = BTF::INT_SIGNED;
1367b410ac3SYonghong Song break;
1377b410ac3SYonghong Song case dwarf::DW_ATE_unsigned:
1387b410ac3SYonghong Song case dwarf::DW_ATE_unsigned_char:
1397b410ac3SYonghong Song BTFEncoding = 0;
1407b410ac3SYonghong Song break;
1417b410ac3SYonghong Song default:
1427b410ac3SYonghong Song llvm_unreachable("Unknown BTFTypeInt Encoding");
1437b410ac3SYonghong Song }
1447b410ac3SYonghong Song
1457b410ac3SYonghong Song Kind = BTF::BTF_KIND_INT;
1467b410ac3SYonghong Song BTFType.Info = Kind << 24;
1477b410ac3SYonghong Song BTFType.Size = roundupToBytes(SizeInBits);
1487b410ac3SYonghong Song IntVal = (BTFEncoding << 24) | OffsetInBits << 16 | SizeInBits;
1497b410ac3SYonghong Song }
1507b410ac3SYonghong Song
completeType(BTFDebug & BDebug)1517b410ac3SYonghong Song void BTFTypeInt::completeType(BTFDebug &BDebug) {
152d3d88d08SYonghong Song if (IsCompleted)
153d3d88d08SYonghong Song return;
154d3d88d08SYonghong Song IsCompleted = true;
155d3d88d08SYonghong Song
1567b410ac3SYonghong Song BTFType.NameOff = BDebug.addString(Name);
1577b410ac3SYonghong Song }
1587b410ac3SYonghong Song
emitType(MCStreamer & OS)1597b410ac3SYonghong Song void BTFTypeInt::emitType(MCStreamer &OS) {
1607b410ac3SYonghong Song BTFTypeBase::emitType(OS);
1617b410ac3SYonghong Song OS.AddComment("0x" + Twine::utohexstr(IntVal));
162692e0c96SFangrui Song OS.emitInt32(IntVal);
1637b410ac3SYonghong Song }
1647b410ac3SYonghong Song
BTFTypeEnum(const DICompositeType * ETy,uint32_t VLen,bool IsSigned)165dc1c43d7SYonghong Song BTFTypeEnum::BTFTypeEnum(const DICompositeType *ETy, uint32_t VLen,
166dc1c43d7SYonghong Song bool IsSigned) : ETy(ETy) {
1677b410ac3SYonghong Song Kind = BTF::BTF_KIND_ENUM;
168dc1c43d7SYonghong Song BTFType.Info = IsSigned << 31 | Kind << 24 | VLen;
1697b410ac3SYonghong Song BTFType.Size = roundupToBytes(ETy->getSizeInBits());
1707b410ac3SYonghong Song }
1717b410ac3SYonghong Song
completeType(BTFDebug & BDebug)1727b410ac3SYonghong Song void BTFTypeEnum::completeType(BTFDebug &BDebug) {
173d3d88d08SYonghong Song if (IsCompleted)
174d3d88d08SYonghong Song return;
175d3d88d08SYonghong Song IsCompleted = true;
176d3d88d08SYonghong Song
1777b410ac3SYonghong Song BTFType.NameOff = BDebug.addString(ETy->getName());
1787b410ac3SYonghong Song
1797b410ac3SYonghong Song DINodeArray Elements = ETy->getElements();
1807b410ac3SYonghong Song for (const auto Element : Elements) {
1817b410ac3SYonghong Song const auto *Enum = cast<DIEnumerator>(Element);
1827b410ac3SYonghong Song
1837b410ac3SYonghong Song struct BTF::BTFEnum BTFEnum;
1847b410ac3SYonghong Song BTFEnum.NameOff = BDebug.addString(Enum->getName());
1857b410ac3SYonghong Song // BTF enum value is 32bit, enforce it.
186aad3d578SLemonBoy uint32_t Value;
187aad3d578SLemonBoy if (Enum->isUnsigned())
188aad3d578SLemonBoy Value = static_cast<uint32_t>(Enum->getValue().getZExtValue());
189aad3d578SLemonBoy else
190aad3d578SLemonBoy Value = static_cast<uint32_t>(Enum->getValue().getSExtValue());
191aad3d578SLemonBoy BTFEnum.Val = Value;
1927b410ac3SYonghong Song EnumValues.push_back(BTFEnum);
1937b410ac3SYonghong Song }
1947b410ac3SYonghong Song }
1957b410ac3SYonghong Song
emitType(MCStreamer & OS)1967b410ac3SYonghong Song void BTFTypeEnum::emitType(MCStreamer &OS) {
1977b410ac3SYonghong Song BTFTypeBase::emitType(OS);
1987b410ac3SYonghong Song for (const auto &Enum : EnumValues) {
199692e0c96SFangrui Song OS.emitInt32(Enum.NameOff);
200692e0c96SFangrui Song OS.emitInt32(Enum.Val);
2017b410ac3SYonghong Song }
2027b410ac3SYonghong Song }
2037b410ac3SYonghong Song
BTFTypeEnum64(const DICompositeType * ETy,uint32_t VLen,bool IsSigned)204dc1c43d7SYonghong Song BTFTypeEnum64::BTFTypeEnum64(const DICompositeType *ETy, uint32_t VLen,
205dc1c43d7SYonghong Song bool IsSigned) : ETy(ETy) {
206dc1c43d7SYonghong Song Kind = BTF::BTF_KIND_ENUM64;
207dc1c43d7SYonghong Song BTFType.Info = IsSigned << 31 | Kind << 24 | VLen;
208dc1c43d7SYonghong Song BTFType.Size = roundupToBytes(ETy->getSizeInBits());
209dc1c43d7SYonghong Song }
210dc1c43d7SYonghong Song
completeType(BTFDebug & BDebug)211dc1c43d7SYonghong Song void BTFTypeEnum64::completeType(BTFDebug &BDebug) {
212dc1c43d7SYonghong Song if (IsCompleted)
213dc1c43d7SYonghong Song return;
214dc1c43d7SYonghong Song IsCompleted = true;
215dc1c43d7SYonghong Song
216dc1c43d7SYonghong Song BTFType.NameOff = BDebug.addString(ETy->getName());
217dc1c43d7SYonghong Song
218dc1c43d7SYonghong Song DINodeArray Elements = ETy->getElements();
219dc1c43d7SYonghong Song for (const auto Element : Elements) {
220dc1c43d7SYonghong Song const auto *Enum = cast<DIEnumerator>(Element);
221dc1c43d7SYonghong Song
222dc1c43d7SYonghong Song struct BTF::BTFEnum64 BTFEnum;
223dc1c43d7SYonghong Song BTFEnum.NameOff = BDebug.addString(Enum->getName());
224dc1c43d7SYonghong Song uint64_t Value;
225dc1c43d7SYonghong Song if (Enum->isUnsigned())
226dc1c43d7SYonghong Song Value = static_cast<uint64_t>(Enum->getValue().getZExtValue());
227dc1c43d7SYonghong Song else
228dc1c43d7SYonghong Song Value = static_cast<uint64_t>(Enum->getValue().getSExtValue());
229dc1c43d7SYonghong Song BTFEnum.Val_Lo32 = Value;
230dc1c43d7SYonghong Song BTFEnum.Val_Hi32 = Value >> 32;
231dc1c43d7SYonghong Song EnumValues.push_back(BTFEnum);
232dc1c43d7SYonghong Song }
233dc1c43d7SYonghong Song }
234dc1c43d7SYonghong Song
emitType(MCStreamer & OS)235dc1c43d7SYonghong Song void BTFTypeEnum64::emitType(MCStreamer &OS) {
236dc1c43d7SYonghong Song BTFTypeBase::emitType(OS);
237dc1c43d7SYonghong Song for (const auto &Enum : EnumValues) {
238dc1c43d7SYonghong Song OS.emitInt32(Enum.NameOff);
239dc1c43d7SYonghong Song OS.AddComment("0x" + Twine::utohexstr(Enum.Val_Lo32));
240dc1c43d7SYonghong Song OS.emitInt32(Enum.Val_Lo32);
241dc1c43d7SYonghong Song OS.AddComment("0x" + Twine::utohexstr(Enum.Val_Hi32));
242dc1c43d7SYonghong Song OS.emitInt32(Enum.Val_Hi32);
243dc1c43d7SYonghong Song }
244dc1c43d7SYonghong Song }
245dc1c43d7SYonghong Song
BTFTypeArray(uint32_t ElemTypeId,uint32_t NumElems)24637d24a69SYonghong Song BTFTypeArray::BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems) {
2477b410ac3SYonghong Song Kind = BTF::BTF_KIND_ARRAY;
248360a4e2cSYonghong Song BTFType.NameOff = 0;
2497b410ac3SYonghong Song BTFType.Info = Kind << 24;
2507b410ac3SYonghong Song BTFType.Size = 0;
2517b410ac3SYonghong Song
252360a4e2cSYonghong Song ArrayInfo.ElemType = ElemTypeId;
253360a4e2cSYonghong Song ArrayInfo.Nelems = NumElems;
254360a4e2cSYonghong Song }
255360a4e2cSYonghong Song
256360a4e2cSYonghong Song /// Represent a BTF array.
completeType(BTFDebug & BDebug)257360a4e2cSYonghong Song void BTFTypeArray::completeType(BTFDebug &BDebug) {
258d3d88d08SYonghong Song if (IsCompleted)
259d3d88d08SYonghong Song return;
260d3d88d08SYonghong Song IsCompleted = true;
2617b410ac3SYonghong Song
2627b410ac3SYonghong Song // The IR does not really have a type for the index.
2637b410ac3SYonghong Song // A special type for array index should have been
2647b410ac3SYonghong Song // created during initial type traversal. Just
2657b410ac3SYonghong Song // retrieve that type id.
2667b410ac3SYonghong Song ArrayInfo.IndexType = BDebug.getArrayIndexTypeId();
2677b410ac3SYonghong Song }
2687b410ac3SYonghong Song
emitType(MCStreamer & OS)2697b410ac3SYonghong Song void BTFTypeArray::emitType(MCStreamer &OS) {
2707b410ac3SYonghong Song BTFTypeBase::emitType(OS);
271692e0c96SFangrui Song OS.emitInt32(ArrayInfo.ElemType);
272692e0c96SFangrui Song OS.emitInt32(ArrayInfo.IndexType);
273692e0c96SFangrui Song OS.emitInt32(ArrayInfo.Nelems);
2747b410ac3SYonghong Song }
2757b410ac3SYonghong Song
2767b410ac3SYonghong Song /// Represent either a struct or a union.
BTFTypeStruct(const DICompositeType * STy,bool IsStruct,bool HasBitField,uint32_t Vlen)2777b410ac3SYonghong Song BTFTypeStruct::BTFTypeStruct(const DICompositeType *STy, bool IsStruct,
2787b410ac3SYonghong Song bool HasBitField, uint32_t Vlen)
2797b410ac3SYonghong Song : STy(STy), HasBitField(HasBitField) {
2807b410ac3SYonghong Song Kind = IsStruct ? BTF::BTF_KIND_STRUCT : BTF::BTF_KIND_UNION;
2817b410ac3SYonghong Song BTFType.Size = roundupToBytes(STy->getSizeInBits());
2827b410ac3SYonghong Song BTFType.Info = (HasBitField << 31) | (Kind << 24) | Vlen;
2837b410ac3SYonghong Song }
2847b410ac3SYonghong Song
completeType(BTFDebug & BDebug)2857b410ac3SYonghong Song void BTFTypeStruct::completeType(BTFDebug &BDebug) {
286d3d88d08SYonghong Song if (IsCompleted)
287d3d88d08SYonghong Song return;
288d3d88d08SYonghong Song IsCompleted = true;
289d3d88d08SYonghong Song
2907b410ac3SYonghong Song BTFType.NameOff = BDebug.addString(STy->getName());
2917b410ac3SYonghong Song
2927b410ac3SYonghong Song // Add struct/union members.
2937b410ac3SYonghong Song const DINodeArray Elements = STy->getElements();
2947b410ac3SYonghong Song for (const auto *Element : Elements) {
2957b410ac3SYonghong Song struct BTF::BTFMember BTFMember;
2967b410ac3SYonghong Song const auto *DDTy = cast<DIDerivedType>(Element);
2977b410ac3SYonghong Song
2987b410ac3SYonghong Song BTFMember.NameOff = BDebug.addString(DDTy->getName());
2997b410ac3SYonghong Song if (HasBitField) {
3007b410ac3SYonghong Song uint8_t BitFieldSize = DDTy->isBitField() ? DDTy->getSizeInBits() : 0;
3017b410ac3SYonghong Song BTFMember.Offset = BitFieldSize << 24 | DDTy->getOffsetInBits();
3027b410ac3SYonghong Song } else {
3037b410ac3SYonghong Song BTFMember.Offset = DDTy->getOffsetInBits();
3047b410ac3SYonghong Song }
305329abf29SYonghong Song const auto *BaseTy = DDTy->getBaseType();
306329abf29SYonghong Song BTFMember.Type = BDebug.getTypeId(BaseTy);
3077b410ac3SYonghong Song Members.push_back(BTFMember);
3087b410ac3SYonghong Song }
3097b410ac3SYonghong Song }
3107b410ac3SYonghong Song
emitType(MCStreamer & OS)3117b410ac3SYonghong Song void BTFTypeStruct::emitType(MCStreamer &OS) {
3127b410ac3SYonghong Song BTFTypeBase::emitType(OS);
3137b410ac3SYonghong Song for (const auto &Member : Members) {
314692e0c96SFangrui Song OS.emitInt32(Member.NameOff);
315692e0c96SFangrui Song OS.emitInt32(Member.Type);
3167b410ac3SYonghong Song OS.AddComment("0x" + Twine::utohexstr(Member.Offset));
317692e0c96SFangrui Song OS.emitInt32(Member.Offset);
3187b410ac3SYonghong Song }
3197b410ac3SYonghong Song }
3207b410ac3SYonghong Song
getName()321adcd0268SBenjamin Kramer std::string BTFTypeStruct::getName() { return std::string(STy->getName()); }
322d3d88d08SYonghong Song
3237b410ac3SYonghong Song /// The Func kind represents both subprogram and pointee of function
3247b410ac3SYonghong Song /// pointers. If the FuncName is empty, it represents a pointee of function
3257b410ac3SYonghong Song /// pointer. Otherwise, it represents a subprogram. The func arg names
3267b410ac3SYonghong Song /// are empty for pointee of function pointer case, and are valid names
3277b410ac3SYonghong Song /// for subprogram.
BTFTypeFuncProto(const DISubroutineType * STy,uint32_t VLen,const std::unordered_map<uint32_t,StringRef> & FuncArgNames)3287b410ac3SYonghong Song BTFTypeFuncProto::BTFTypeFuncProto(
3297b410ac3SYonghong Song const DISubroutineType *STy, uint32_t VLen,
3307b410ac3SYonghong Song const std::unordered_map<uint32_t, StringRef> &FuncArgNames)
3317b410ac3SYonghong Song : STy(STy), FuncArgNames(FuncArgNames) {
3327b410ac3SYonghong Song Kind = BTF::BTF_KIND_FUNC_PROTO;
3337b410ac3SYonghong Song BTFType.Info = (Kind << 24) | VLen;
3347b410ac3SYonghong Song }
3357b410ac3SYonghong Song
completeType(BTFDebug & BDebug)3367b410ac3SYonghong Song void BTFTypeFuncProto::completeType(BTFDebug &BDebug) {
337d3d88d08SYonghong Song if (IsCompleted)
338d3d88d08SYonghong Song return;
339d3d88d08SYonghong Song IsCompleted = true;
340d3d88d08SYonghong Song
3417b410ac3SYonghong Song DITypeRefArray Elements = STy->getTypeArray();
342da82ce99SFangrui Song auto RetType = Elements[0];
3437b410ac3SYonghong Song BTFType.Type = RetType ? BDebug.getTypeId(RetType) : 0;
3447b410ac3SYonghong Song BTFType.NameOff = 0;
3457b410ac3SYonghong Song
3467b410ac3SYonghong Song // For null parameter which is typically the last one
3477b410ac3SYonghong Song // to represent the vararg, encode the NameOff/Type to be 0.
3487b410ac3SYonghong Song for (unsigned I = 1, N = Elements.size(); I < N; ++I) {
3497b410ac3SYonghong Song struct BTF::BTFParam Param;
350da82ce99SFangrui Song auto Element = Elements[I];
3517b410ac3SYonghong Song if (Element) {
3527b410ac3SYonghong Song Param.NameOff = BDebug.addString(FuncArgNames[I]);
3537b410ac3SYonghong Song Param.Type = BDebug.getTypeId(Element);
3547b410ac3SYonghong Song } else {
3557b410ac3SYonghong Song Param.NameOff = 0;
3567b410ac3SYonghong Song Param.Type = 0;
3577b410ac3SYonghong Song }
3587b410ac3SYonghong Song Parameters.push_back(Param);
3597b410ac3SYonghong Song }
3607b410ac3SYonghong Song }
3617b410ac3SYonghong Song
emitType(MCStreamer & OS)3627b410ac3SYonghong Song void BTFTypeFuncProto::emitType(MCStreamer &OS) {
3637b410ac3SYonghong Song BTFTypeBase::emitType(OS);
3647b410ac3SYonghong Song for (const auto &Param : Parameters) {
365692e0c96SFangrui Song OS.emitInt32(Param.NameOff);
366692e0c96SFangrui Song OS.emitInt32(Param.Type);
3677b410ac3SYonghong Song }
3687b410ac3SYonghong Song }
3697b410ac3SYonghong Song
BTFTypeFunc(StringRef FuncName,uint32_t ProtoTypeId,uint32_t Scope)370fbb64aa6SYonghong Song BTFTypeFunc::BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId,
371fbb64aa6SYonghong Song uint32_t Scope)
3727b410ac3SYonghong Song : Name(FuncName) {
3737b410ac3SYonghong Song Kind = BTF::BTF_KIND_FUNC;
374fbb64aa6SYonghong Song BTFType.Info = (Kind << 24) | Scope;
3757b410ac3SYonghong Song BTFType.Type = ProtoTypeId;
3767b410ac3SYonghong Song }
3777b410ac3SYonghong Song
completeType(BTFDebug & BDebug)3787b410ac3SYonghong Song void BTFTypeFunc::completeType(BTFDebug &BDebug) {
379d3d88d08SYonghong Song if (IsCompleted)
380d3d88d08SYonghong Song return;
381d3d88d08SYonghong Song IsCompleted = true;
382d3d88d08SYonghong Song
3837b410ac3SYonghong Song BTFType.NameOff = BDebug.addString(Name);
3847b410ac3SYonghong Song }
3857b410ac3SYonghong Song
emitType(MCStreamer & OS)3867b410ac3SYonghong Song void BTFTypeFunc::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); }
3877b410ac3SYonghong Song
BTFKindVar(StringRef VarName,uint32_t TypeId,uint32_t VarInfo)3886db6b56aSYonghong Song BTFKindVar::BTFKindVar(StringRef VarName, uint32_t TypeId, uint32_t VarInfo)
3896db6b56aSYonghong Song : Name(VarName) {
3906db6b56aSYonghong Song Kind = BTF::BTF_KIND_VAR;
3916db6b56aSYonghong Song BTFType.Info = Kind << 24;
3926db6b56aSYonghong Song BTFType.Type = TypeId;
3936db6b56aSYonghong Song Info = VarInfo;
3946db6b56aSYonghong Song }
3956db6b56aSYonghong Song
completeType(BTFDebug & BDebug)3966db6b56aSYonghong Song void BTFKindVar::completeType(BTFDebug &BDebug) {
3976db6b56aSYonghong Song BTFType.NameOff = BDebug.addString(Name);
3986db6b56aSYonghong Song }
3996db6b56aSYonghong Song
emitType(MCStreamer & OS)4006db6b56aSYonghong Song void BTFKindVar::emitType(MCStreamer &OS) {
4016db6b56aSYonghong Song BTFTypeBase::emitType(OS);
402692e0c96SFangrui Song OS.emitInt32(Info);
4036db6b56aSYonghong Song }
4046db6b56aSYonghong Song
BTFKindDataSec(AsmPrinter * AsmPrt,std::string SecName)4056db6b56aSYonghong Song BTFKindDataSec::BTFKindDataSec(AsmPrinter *AsmPrt, std::string SecName)
4066db6b56aSYonghong Song : Asm(AsmPrt), Name(SecName) {
4076db6b56aSYonghong Song Kind = BTF::BTF_KIND_DATASEC;
4086db6b56aSYonghong Song BTFType.Info = Kind << 24;
4096db6b56aSYonghong Song BTFType.Size = 0;
4106db6b56aSYonghong Song }
4116db6b56aSYonghong Song
completeType(BTFDebug & BDebug)4126db6b56aSYonghong Song void BTFKindDataSec::completeType(BTFDebug &BDebug) {
4136db6b56aSYonghong Song BTFType.NameOff = BDebug.addString(Name);
4146db6b56aSYonghong Song BTFType.Info |= Vars.size();
4156db6b56aSYonghong Song }
4166db6b56aSYonghong Song
emitType(MCStreamer & OS)4176db6b56aSYonghong Song void BTFKindDataSec::emitType(MCStreamer &OS) {
4186db6b56aSYonghong Song BTFTypeBase::emitType(OS);
4196db6b56aSYonghong Song
4206db6b56aSYonghong Song for (const auto &V : Vars) {
421692e0c96SFangrui Song OS.emitInt32(std::get<0>(V));
4220bc77a0fSFangrui Song Asm->emitLabelReference(std::get<1>(V), 4);
423692e0c96SFangrui Song OS.emitInt32(std::get<2>(V));
4246db6b56aSYonghong Song }
4256db6b56aSYonghong Song }
4266db6b56aSYonghong Song
BTFTypeFloat(uint32_t SizeInBits,StringRef TypeName)427a7137b23SIlya Leoshkevich BTFTypeFloat::BTFTypeFloat(uint32_t SizeInBits, StringRef TypeName)
428a7137b23SIlya Leoshkevich : Name(TypeName) {
429a7137b23SIlya Leoshkevich Kind = BTF::BTF_KIND_FLOAT;
430a7137b23SIlya Leoshkevich BTFType.Info = Kind << 24;
431a7137b23SIlya Leoshkevich BTFType.Size = roundupToBytes(SizeInBits);
432a7137b23SIlya Leoshkevich }
433a7137b23SIlya Leoshkevich
completeType(BTFDebug & BDebug)434a7137b23SIlya Leoshkevich void BTFTypeFloat::completeType(BTFDebug &BDebug) {
435a7137b23SIlya Leoshkevich if (IsCompleted)
436a7137b23SIlya Leoshkevich return;
437a7137b23SIlya Leoshkevich IsCompleted = true;
438a7137b23SIlya Leoshkevich
439a7137b23SIlya Leoshkevich BTFType.NameOff = BDebug.addString(Name);
440a7137b23SIlya Leoshkevich }
441a7137b23SIlya Leoshkevich
BTFTypeDeclTag(uint32_t BaseTypeId,int ComponentIdx,StringRef Tag)4421321e472SYonghong Song BTFTypeDeclTag::BTFTypeDeclTag(uint32_t BaseTypeId, int ComponentIdx,
4431321e472SYonghong Song StringRef Tag)
44449489270SYonghong Song : Tag(Tag) {
4451321e472SYonghong Song Kind = BTF::BTF_KIND_DECL_TAG;
446e52617c3SYonghong Song BTFType.Info = Kind << 24;
44749489270SYonghong Song BTFType.Type = BaseTypeId;
448e52617c3SYonghong Song Info = ComponentIdx;
44949489270SYonghong Song }
45049489270SYonghong Song
completeType(BTFDebug & BDebug)4511321e472SYonghong Song void BTFTypeDeclTag::completeType(BTFDebug &BDebug) {
45249489270SYonghong Song if (IsCompleted)
45349489270SYonghong Song return;
45449489270SYonghong Song IsCompleted = true;
45549489270SYonghong Song
45649489270SYonghong Song BTFType.NameOff = BDebug.addString(Tag);
45749489270SYonghong Song }
45849489270SYonghong Song
emitType(MCStreamer & OS)4591321e472SYonghong Song void BTFTypeDeclTag::emitType(MCStreamer &OS) {
46049489270SYonghong Song BTFTypeBase::emitType(OS);
46149489270SYonghong Song OS.emitInt32(Info);
46249489270SYonghong Song }
46349489270SYonghong Song
BTFTypeTypeTag(uint32_t NextTypeId,StringRef Tag)4648d499bd5SYonghong Song BTFTypeTypeTag::BTFTypeTypeTag(uint32_t NextTypeId, StringRef Tag)
4658d499bd5SYonghong Song : DTy(nullptr), Tag(Tag) {
46641860e60SYonghong Song Kind = BTF::BTF_KIND_TYPE_TAG;
46741860e60SYonghong Song BTFType.Info = Kind << 24;
4688d499bd5SYonghong Song BTFType.Type = NextTypeId;
4698d499bd5SYonghong Song }
4708d499bd5SYonghong Song
BTFTypeTypeTag(const DIDerivedType * DTy,StringRef Tag)4718d499bd5SYonghong Song BTFTypeTypeTag::BTFTypeTypeTag(const DIDerivedType *DTy, StringRef Tag)
4728d499bd5SYonghong Song : DTy(DTy), Tag(Tag) {
4738d499bd5SYonghong Song Kind = BTF::BTF_KIND_TYPE_TAG;
4748d499bd5SYonghong Song BTFType.Info = Kind << 24;
47541860e60SYonghong Song }
47641860e60SYonghong Song
completeType(BTFDebug & BDebug)47741860e60SYonghong Song void BTFTypeTypeTag::completeType(BTFDebug &BDebug) {
47841860e60SYonghong Song if (IsCompleted)
47941860e60SYonghong Song return;
48041860e60SYonghong Song IsCompleted = true;
48141860e60SYonghong Song BTFType.NameOff = BDebug.addString(Tag);
4828d499bd5SYonghong Song if (DTy) {
4838d499bd5SYonghong Song const DIType *ResolvedType = DTy->getBaseType();
4848d499bd5SYonghong Song if (!ResolvedType)
4858d499bd5SYonghong Song BTFType.Type = 0;
4868d499bd5SYonghong Song else
4878d499bd5SYonghong Song BTFType.Type = BDebug.getTypeId(ResolvedType);
4888d499bd5SYonghong Song }
48941860e60SYonghong Song }
49041860e60SYonghong Song
addString(StringRef S)4917b410ac3SYonghong Song uint32_t BTFStringTable::addString(StringRef S) {
4927b410ac3SYonghong Song // Check whether the string already exists.
4937b410ac3SYonghong Song for (auto &OffsetM : OffsetToIdMap) {
4947b410ac3SYonghong Song if (Table[OffsetM.second] == S)
4957b410ac3SYonghong Song return OffsetM.first;
4967b410ac3SYonghong Song }
4977b410ac3SYonghong Song // Not find, add to the string table.
4987b410ac3SYonghong Song uint32_t Offset = Size;
4997b410ac3SYonghong Song OffsetToIdMap[Offset] = Table.size();
500adcd0268SBenjamin Kramer Table.push_back(std::string(S));
5017b410ac3SYonghong Song Size += S.size() + 1;
5027b410ac3SYonghong Song return Offset;
5037b410ac3SYonghong Song }
5047b410ac3SYonghong Song
BTFDebug(AsmPrinter * AP)5057b410ac3SYonghong Song BTFDebug::BTFDebug(AsmPrinter *AP)
5067b410ac3SYonghong Song : DebugHandlerBase(AP), OS(*Asm->OutStreamer), SkipInstruction(false),
507d3d88d08SYonghong Song LineInfoGenerated(false), SecNameOff(0), ArrayIndexTypeId(0),
508d3d88d08SYonghong Song MapDefNotCollected(true) {
5097b410ac3SYonghong Song addString("\0");
5107b410ac3SYonghong Song }
5117b410ac3SYonghong Song
addType(std::unique_ptr<BTFTypeBase> TypeEntry,const DIType * Ty)5126db6b56aSYonghong Song uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry,
5137b410ac3SYonghong Song const DIType *Ty) {
5147b410ac3SYonghong Song TypeEntry->setId(TypeEntries.size() + 1);
5156db6b56aSYonghong Song uint32_t Id = TypeEntry->getId();
5166db6b56aSYonghong Song DIToIdMap[Ty] = Id;
5177b410ac3SYonghong Song TypeEntries.push_back(std::move(TypeEntry));
5186db6b56aSYonghong Song return Id;
5197b410ac3SYonghong Song }
5207b410ac3SYonghong Song
addType(std::unique_ptr<BTFTypeBase> TypeEntry)5217b410ac3SYonghong Song uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry) {
5227b410ac3SYonghong Song TypeEntry->setId(TypeEntries.size() + 1);
5237b410ac3SYonghong Song uint32_t Id = TypeEntry->getId();
5247b410ac3SYonghong Song TypeEntries.push_back(std::move(TypeEntry));
5257b410ac3SYonghong Song return Id;
5267b410ac3SYonghong Song }
5277b410ac3SYonghong Song
visitBasicType(const DIBasicType * BTy,uint32_t & TypeId)5286db6b56aSYonghong Song void BTFDebug::visitBasicType(const DIBasicType *BTy, uint32_t &TypeId) {
529a7137b23SIlya Leoshkevich // Only int and binary floating point types are supported in BTF.
5307b410ac3SYonghong Song uint32_t Encoding = BTy->getEncoding();
531a7137b23SIlya Leoshkevich std::unique_ptr<BTFTypeBase> TypeEntry;
532a7137b23SIlya Leoshkevich switch (Encoding) {
533a7137b23SIlya Leoshkevich case dwarf::DW_ATE_boolean:
534a7137b23SIlya Leoshkevich case dwarf::DW_ATE_signed:
535a7137b23SIlya Leoshkevich case dwarf::DW_ATE_signed_char:
536a7137b23SIlya Leoshkevich case dwarf::DW_ATE_unsigned:
537a7137b23SIlya Leoshkevich case dwarf::DW_ATE_unsigned_char:
5387b410ac3SYonghong Song // Create a BTF type instance for this DIBasicType and put it into
5397b410ac3SYonghong Song // DIToIdMap for cross-type reference check.
540a7137b23SIlya Leoshkevich TypeEntry = std::make_unique<BTFTypeInt>(
5417b410ac3SYonghong Song Encoding, BTy->getSizeInBits(), BTy->getOffsetInBits(), BTy->getName());
542a7137b23SIlya Leoshkevich break;
543a7137b23SIlya Leoshkevich case dwarf::DW_ATE_float:
544a7137b23SIlya Leoshkevich TypeEntry =
545a7137b23SIlya Leoshkevich std::make_unique<BTFTypeFloat>(BTy->getSizeInBits(), BTy->getName());
546a7137b23SIlya Leoshkevich break;
547a7137b23SIlya Leoshkevich default:
548a7137b23SIlya Leoshkevich return;
549a7137b23SIlya Leoshkevich }
550a7137b23SIlya Leoshkevich
5516db6b56aSYonghong Song TypeId = addType(std::move(TypeEntry), BTy);
5527b410ac3SYonghong Song }
5537b410ac3SYonghong Song
5547b410ac3SYonghong Song /// Handle subprogram or subroutine types.
visitSubroutineType(const DISubroutineType * STy,bool ForSubprog,const std::unordered_map<uint32_t,StringRef> & FuncArgNames,uint32_t & TypeId)5557b410ac3SYonghong Song void BTFDebug::visitSubroutineType(
5567b410ac3SYonghong Song const DISubroutineType *STy, bool ForSubprog,
5577b410ac3SYonghong Song const std::unordered_map<uint32_t, StringRef> &FuncArgNames,
5587b410ac3SYonghong Song uint32_t &TypeId) {
5597b410ac3SYonghong Song DITypeRefArray Elements = STy->getTypeArray();
5607b410ac3SYonghong Song uint32_t VLen = Elements.size() - 1;
5617b410ac3SYonghong Song if (VLen > BTF::MAX_VLEN)
5627b410ac3SYonghong Song return;
5637b410ac3SYonghong Song
5647b410ac3SYonghong Song // Subprogram has a valid non-zero-length name, and the pointee of
5657b410ac3SYonghong Song // a function pointer has an empty name. The subprogram type will
5667b410ac3SYonghong Song // not be added to DIToIdMap as it should not be referenced by
5677b410ac3SYonghong Song // any other types.
5680eaee545SJonas Devlieghere auto TypeEntry = std::make_unique<BTFTypeFuncProto>(STy, VLen, FuncArgNames);
5697b410ac3SYonghong Song if (ForSubprog)
5707b410ac3SYonghong Song TypeId = addType(std::move(TypeEntry)); // For subprogram
5717b410ac3SYonghong Song else
5726db6b56aSYonghong Song TypeId = addType(std::move(TypeEntry), STy); // For func ptr
5737b410ac3SYonghong Song
5747b410ac3SYonghong Song // Visit return type and func arg types.
5757b410ac3SYonghong Song for (const auto Element : Elements) {
576da82ce99SFangrui Song visitTypeEntry(Element);
5777b410ac3SYonghong Song }
5787b410ac3SYonghong Song }
5797b410ac3SYonghong Song
processDeclAnnotations(DINodeArray Annotations,uint32_t BaseTypeId,int ComponentIdx)580f4a8526cSYonghong Song void BTFDebug::processDeclAnnotations(DINodeArray Annotations,
581f4a8526cSYonghong Song uint32_t BaseTypeId,
582e52617c3SYonghong Song int ComponentIdx) {
58349489270SYonghong Song if (!Annotations)
58449489270SYonghong Song return;
58549489270SYonghong Song
58649489270SYonghong Song for (const Metadata *Annotation : Annotations->operands()) {
58749489270SYonghong Song const MDNode *MD = cast<MDNode>(Annotation);
58849489270SYonghong Song const MDString *Name = cast<MDString>(MD->getOperand(0));
5891321e472SYonghong Song if (!Name->getString().equals("btf_decl_tag"))
59049489270SYonghong Song continue;
59149489270SYonghong Song
59249489270SYonghong Song const MDString *Value = cast<MDString>(MD->getOperand(1));
5931321e472SYonghong Song auto TypeEntry = std::make_unique<BTFTypeDeclTag>(BaseTypeId, ComponentIdx,
59449489270SYonghong Song Value->getString());
59549489270SYonghong Song addType(std::move(TypeEntry));
59649489270SYonghong Song }
59749489270SYonghong Song }
59849489270SYonghong Song
599f419029fSYonghong Song /// Generate btf_type_tag chains.
genBTFTypeTags(const DIDerivedType * DTy,int BaseTypeId)600f419029fSYonghong Song int BTFDebug::genBTFTypeTags(const DIDerivedType *DTy, int BaseTypeId) {
601f419029fSYonghong Song SmallVector<const MDString *, 4> MDStrs;
602f419029fSYonghong Song DINodeArray Annots = DTy->getAnnotations();
603f419029fSYonghong Song if (Annots) {
604f419029fSYonghong Song // For type with "int __tag1 __tag2 *p", the MDStrs will have
605f419029fSYonghong Song // content: [__tag1, __tag2].
606f419029fSYonghong Song for (const Metadata *Annotations : Annots->operands()) {
607f419029fSYonghong Song const MDNode *MD = cast<MDNode>(Annotations);
608f419029fSYonghong Song const MDString *Name = cast<MDString>(MD->getOperand(0));
609f419029fSYonghong Song if (!Name->getString().equals("btf_type_tag"))
610f419029fSYonghong Song continue;
611f419029fSYonghong Song MDStrs.push_back(cast<MDString>(MD->getOperand(1)));
612f419029fSYonghong Song }
613f419029fSYonghong Song }
614f419029fSYonghong Song
615f419029fSYonghong Song if (MDStrs.size() == 0)
616f419029fSYonghong Song return -1;
617f419029fSYonghong Song
618f419029fSYonghong Song // With MDStrs [__tag1, __tag2], the output type chain looks like
619f419029fSYonghong Song // PTR -> __tag2 -> __tag1 -> BaseType
620f419029fSYonghong Song // In the below, we construct BTF types with the order of __tag1, __tag2
621f419029fSYonghong Song // and PTR.
622f419029fSYonghong Song unsigned TmpTypeId;
623f419029fSYonghong Song std::unique_ptr<BTFTypeTypeTag> TypeEntry;
624f419029fSYonghong Song if (BaseTypeId >= 0)
625f419029fSYonghong Song TypeEntry =
626f419029fSYonghong Song std::make_unique<BTFTypeTypeTag>(BaseTypeId, MDStrs[0]->getString());
627f419029fSYonghong Song else
628f419029fSYonghong Song TypeEntry = std::make_unique<BTFTypeTypeTag>(DTy, MDStrs[0]->getString());
629f419029fSYonghong Song TmpTypeId = addType(std::move(TypeEntry));
630f419029fSYonghong Song
631f419029fSYonghong Song for (unsigned I = 1; I < MDStrs.size(); I++) {
632f419029fSYonghong Song const MDString *Value = MDStrs[I];
633f419029fSYonghong Song TypeEntry = std::make_unique<BTFTypeTypeTag>(TmpTypeId, Value->getString());
634f419029fSYonghong Song TmpTypeId = addType(std::move(TypeEntry));
635f419029fSYonghong Song }
636f419029fSYonghong Song return TmpTypeId;
637f419029fSYonghong Song }
638f419029fSYonghong Song
6397b410ac3SYonghong Song /// Handle structure/union types.
visitStructType(const DICompositeType * CTy,bool IsStruct,uint32_t & TypeId)6406db6b56aSYonghong Song void BTFDebug::visitStructType(const DICompositeType *CTy, bool IsStruct,
6416db6b56aSYonghong Song uint32_t &TypeId) {
6427b410ac3SYonghong Song const DINodeArray Elements = CTy->getElements();
6437b410ac3SYonghong Song uint32_t VLen = Elements.size();
6447b410ac3SYonghong Song if (VLen > BTF::MAX_VLEN)
6457b410ac3SYonghong Song return;
6467b410ac3SYonghong Song
6477b410ac3SYonghong Song // Check whether we have any bitfield members or not
6487b410ac3SYonghong Song bool HasBitField = false;
6497b410ac3SYonghong Song for (const auto *Element : Elements) {
6507b410ac3SYonghong Song auto E = cast<DIDerivedType>(Element);
6517b410ac3SYonghong Song if (E->isBitField()) {
6527b410ac3SYonghong Song HasBitField = true;
6537b410ac3SYonghong Song break;
6547b410ac3SYonghong Song }
6557b410ac3SYonghong Song }
6567b410ac3SYonghong Song
6577b410ac3SYonghong Song auto TypeEntry =
6580eaee545SJonas Devlieghere std::make_unique<BTFTypeStruct>(CTy, IsStruct, HasBitField, VLen);
659d3d88d08SYonghong Song StructTypes.push_back(TypeEntry.get());
6606db6b56aSYonghong Song TypeId = addType(std::move(TypeEntry), CTy);
6617b410ac3SYonghong Song
66249489270SYonghong Song // Check struct/union annotations
663f4a8526cSYonghong Song processDeclAnnotations(CTy->getAnnotations(), TypeId, -1);
66449489270SYonghong Song
6657b410ac3SYonghong Song // Visit all struct members.
66649489270SYonghong Song int FieldNo = 0;
66749489270SYonghong Song for (const auto *Element : Elements) {
66849489270SYonghong Song const auto Elem = cast<DIDerivedType>(Element);
66949489270SYonghong Song visitTypeEntry(Elem);
670f4a8526cSYonghong Song processDeclAnnotations(Elem->getAnnotations(), TypeId, FieldNo);
67149489270SYonghong Song FieldNo++;
67249489270SYonghong Song }
6737b410ac3SYonghong Song }
6747b410ac3SYonghong Song
visitArrayType(const DICompositeType * CTy,uint32_t & TypeId)6756db6b56aSYonghong Song void BTFDebug::visitArrayType(const DICompositeType *CTy, uint32_t &TypeId) {
676360a4e2cSYonghong Song // Visit array element type.
6771487bf6cSYonghong Song uint32_t ElemTypeId;
678d3d88d08SYonghong Song const DIType *ElemType = CTy->getBaseType();
679d3d88d08SYonghong Song visitTypeEntry(ElemType, ElemTypeId, false, false);
680329abf29SYonghong Song
681360a4e2cSYonghong Song // Visit array dimensions.
682360a4e2cSYonghong Song DINodeArray Elements = CTy->getElements();
683360a4e2cSYonghong Song for (int I = Elements.size() - 1; I >= 0; --I) {
684360a4e2cSYonghong Song if (auto *Element = dyn_cast_or_null<DINode>(Elements[I]))
685360a4e2cSYonghong Song if (Element->getTag() == dwarf::DW_TAG_subrange_type) {
686360a4e2cSYonghong Song const DISubrange *SR = cast<DISubrange>(Element);
687360a4e2cSYonghong Song auto *CI = SR->getCount().dyn_cast<ConstantInt *>();
688360a4e2cSYonghong Song int64_t Count = CI->getSExtValue();
689360a4e2cSYonghong Song
6901487bf6cSYonghong Song // For struct s { int b; char c[]; }, the c[] will be represented
6911487bf6cSYonghong Song // as an array with Count = -1.
692d3d88d08SYonghong Song auto TypeEntry =
6931487bf6cSYonghong Song std::make_unique<BTFTypeArray>(ElemTypeId,
6941487bf6cSYonghong Song Count >= 0 ? Count : 0);
695360a4e2cSYonghong Song if (I == 0)
696360a4e2cSYonghong Song ElemTypeId = addType(std::move(TypeEntry), CTy);
697360a4e2cSYonghong Song else
698360a4e2cSYonghong Song ElemTypeId = addType(std::move(TypeEntry));
699360a4e2cSYonghong Song }
700360a4e2cSYonghong Song }
701360a4e2cSYonghong Song
702360a4e2cSYonghong Song // The array TypeId is the type id of the outermost dimension.
703360a4e2cSYonghong Song TypeId = ElemTypeId;
7047b410ac3SYonghong Song
7057b410ac3SYonghong Song // The IR does not have a type for array index while BTF wants one.
7067b410ac3SYonghong Song // So create an array index type if there is none.
7077b410ac3SYonghong Song if (!ArrayIndexTypeId) {
7080eaee545SJonas Devlieghere auto TypeEntry = std::make_unique<BTFTypeInt>(dwarf::DW_ATE_unsigned, 32,
7097b410ac3SYonghong Song 0, "__ARRAY_SIZE_TYPE__");
7107b410ac3SYonghong Song ArrayIndexTypeId = addType(std::move(TypeEntry));
7117b410ac3SYonghong Song }
7127b410ac3SYonghong Song }
7137b410ac3SYonghong Song
visitEnumType(const DICompositeType * CTy,uint32_t & TypeId)7146db6b56aSYonghong Song void BTFDebug::visitEnumType(const DICompositeType *CTy, uint32_t &TypeId) {
7157b410ac3SYonghong Song DINodeArray Elements = CTy->getElements();
7167b410ac3SYonghong Song uint32_t VLen = Elements.size();
7177b410ac3SYonghong Song if (VLen > BTF::MAX_VLEN)
7187b410ac3SYonghong Song return;
7197b410ac3SYonghong Song
720dc1c43d7SYonghong Song bool IsSigned = false;
721dc1c43d7SYonghong Song unsigned NumBits = 32;
722dc1c43d7SYonghong Song // No BaseType implies forward declaration in which case a
723dc1c43d7SYonghong Song // BTFTypeEnum with Vlen = 0 is emitted.
724dc1c43d7SYonghong Song if (CTy->getBaseType() != nullptr) {
725dc1c43d7SYonghong Song const auto *BTy = cast<DIBasicType>(CTy->getBaseType());
726dc1c43d7SYonghong Song IsSigned = BTy->getEncoding() == dwarf::DW_ATE_signed ||
727dc1c43d7SYonghong Song BTy->getEncoding() == dwarf::DW_ATE_signed_char;
728dc1c43d7SYonghong Song NumBits = BTy->getSizeInBits();
729dc1c43d7SYonghong Song }
730dc1c43d7SYonghong Song
731dc1c43d7SYonghong Song if (NumBits <= 32) {
732dc1c43d7SYonghong Song auto TypeEntry = std::make_unique<BTFTypeEnum>(CTy, VLen, IsSigned);
7336db6b56aSYonghong Song TypeId = addType(std::move(TypeEntry), CTy);
734dc1c43d7SYonghong Song } else {
735dc1c43d7SYonghong Song assert(NumBits == 64);
736dc1c43d7SYonghong Song auto TypeEntry = std::make_unique<BTFTypeEnum64>(CTy, VLen, IsSigned);
737dc1c43d7SYonghong Song TypeId = addType(std::move(TypeEntry), CTy);
738dc1c43d7SYonghong Song }
7397b410ac3SYonghong Song // No need to visit base type as BTF does not encode it.
7407b410ac3SYonghong Song }
7417b410ac3SYonghong Song
7427b410ac3SYonghong Song /// Handle structure/union forward declarations.
visitFwdDeclType(const DICompositeType * CTy,bool IsUnion,uint32_t & TypeId)7436db6b56aSYonghong Song void BTFDebug::visitFwdDeclType(const DICompositeType *CTy, bool IsUnion,
7446db6b56aSYonghong Song uint32_t &TypeId) {
7450eaee545SJonas Devlieghere auto TypeEntry = std::make_unique<BTFTypeFwd>(CTy->getName(), IsUnion);
7466db6b56aSYonghong Song TypeId = addType(std::move(TypeEntry), CTy);
7477b410ac3SYonghong Song }
7487b410ac3SYonghong Song
7497b410ac3SYonghong Song /// Handle structure, union, array and enumeration types.
visitCompositeType(const DICompositeType * CTy,uint32_t & TypeId)7506db6b56aSYonghong Song void BTFDebug::visitCompositeType(const DICompositeType *CTy,
7516db6b56aSYonghong Song uint32_t &TypeId) {
7527b410ac3SYonghong Song auto Tag = CTy->getTag();
7537b410ac3SYonghong Song if (Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) {
7547b410ac3SYonghong Song // Handle forward declaration differently as it does not have members.
7557b410ac3SYonghong Song if (CTy->isForwardDecl())
7566db6b56aSYonghong Song visitFwdDeclType(CTy, Tag == dwarf::DW_TAG_union_type, TypeId);
7577b410ac3SYonghong Song else
7586db6b56aSYonghong Song visitStructType(CTy, Tag == dwarf::DW_TAG_structure_type, TypeId);
7597b410ac3SYonghong Song } else if (Tag == dwarf::DW_TAG_array_type)
7606db6b56aSYonghong Song visitArrayType(CTy, TypeId);
7617b410ac3SYonghong Song else if (Tag == dwarf::DW_TAG_enumeration_type)
7626db6b56aSYonghong Song visitEnumType(CTy, TypeId);
7637b410ac3SYonghong Song }
7647b410ac3SYonghong Song
7657b410ac3SYonghong Song /// Handle pointer, typedef, const, volatile, restrict and member types.
visitDerivedType(const DIDerivedType * DTy,uint32_t & TypeId,bool CheckPointer,bool SeenPointer)766d3d88d08SYonghong Song void BTFDebug::visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId,
767d3d88d08SYonghong Song bool CheckPointer, bool SeenPointer) {
7687b410ac3SYonghong Song unsigned Tag = DTy->getTag();
7697b410ac3SYonghong Song
770d3d88d08SYonghong Song /// Try to avoid chasing pointees, esp. structure pointees which may
771d3d88d08SYonghong Song /// unnecessary bring in a lot of types.
772d3d88d08SYonghong Song if (CheckPointer && !SeenPointer) {
773d3d88d08SYonghong Song SeenPointer = Tag == dwarf::DW_TAG_pointer_type;
774d3d88d08SYonghong Song }
775d3d88d08SYonghong Song
776d3d88d08SYonghong Song if (CheckPointer && SeenPointer) {
777d3d88d08SYonghong Song const DIType *Base = DTy->getBaseType();
778d3d88d08SYonghong Song if (Base) {
779d3d88d08SYonghong Song if (const auto *CTy = dyn_cast<DICompositeType>(Base)) {
780d3d88d08SYonghong Song auto CTag = CTy->getTag();
781d3d88d08SYonghong Song if ((CTag == dwarf::DW_TAG_structure_type ||
782d3d88d08SYonghong Song CTag == dwarf::DW_TAG_union_type) &&
7833eacfdc7SYonghong Song !CTy->getName().empty() && !CTy->isForwardDecl()) {
784d3d88d08SYonghong Song /// Find a candidate, generate a fixup. Later on the struct/union
785d3d88d08SYonghong Song /// pointee type will be replaced with either a real type or
786d3d88d08SYonghong Song /// a forward declaration.
7870eaee545SJonas Devlieghere auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy, Tag, true);
788f419029fSYonghong Song auto &Fixup = FixupDerivedTypes[CTy];
789f419029fSYonghong Song Fixup.push_back(std::make_pair(DTy, TypeEntry.get()));
790d3d88d08SYonghong Song TypeId = addType(std::move(TypeEntry), DTy);
791d3d88d08SYonghong Song return;
792d3d88d08SYonghong Song }
793d3d88d08SYonghong Song }
794d3d88d08SYonghong Song }
795d3d88d08SYonghong Song }
796d3d88d08SYonghong Song
79741860e60SYonghong Song if (Tag == dwarf::DW_TAG_pointer_type) {
798f419029fSYonghong Song int TmpTypeId = genBTFTypeTags(DTy, -1);
799f419029fSYonghong Song if (TmpTypeId >= 0) {
8008d499bd5SYonghong Song auto TypeDEntry =
8018d499bd5SYonghong Song std::make_unique<BTFTypeDerived>(TmpTypeId, Tag, DTy->getName());
8028d499bd5SYonghong Song TypeId = addType(std::move(TypeDEntry), DTy);
80341860e60SYonghong Song } else {
80441860e60SYonghong Song auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy, Tag, false);
80541860e60SYonghong Song TypeId = addType(std::move(TypeEntry), DTy);
80641860e60SYonghong Song }
80741860e60SYonghong Song } else if (Tag == dwarf::DW_TAG_typedef || Tag == dwarf::DW_TAG_const_type ||
80841860e60SYonghong Song Tag == dwarf::DW_TAG_volatile_type ||
8097b410ac3SYonghong Song Tag == dwarf::DW_TAG_restrict_type) {
8100eaee545SJonas Devlieghere auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy, Tag, false);
8116db6b56aSYonghong Song TypeId = addType(std::move(TypeEntry), DTy);
8120472e83fSYonghong Song if (Tag == dwarf::DW_TAG_typedef)
8130472e83fSYonghong Song processDeclAnnotations(DTy->getAnnotations(), TypeId, -1);
8147b410ac3SYonghong Song } else if (Tag != dwarf::DW_TAG_member) {
8157b410ac3SYonghong Song return;
8167b410ac3SYonghong Song }
8177b410ac3SYonghong Song
8187b410ac3SYonghong Song // Visit base type of pointer, typedef, const, volatile, restrict or
8197b410ac3SYonghong Song // struct/union member.
820ded9a440SYonghong Song uint32_t TempTypeId = 0;
821d3d88d08SYonghong Song if (Tag == dwarf::DW_TAG_member)
822d3d88d08SYonghong Song visitTypeEntry(DTy->getBaseType(), TempTypeId, true, false);
823d3d88d08SYonghong Song else
824d3d88d08SYonghong Song visitTypeEntry(DTy->getBaseType(), TempTypeId, CheckPointer, SeenPointer);
8257b410ac3SYonghong Song }
8267b410ac3SYonghong Song
visitTypeEntry(const DIType * Ty,uint32_t & TypeId,bool CheckPointer,bool SeenPointer)827d3d88d08SYonghong Song void BTFDebug::visitTypeEntry(const DIType *Ty, uint32_t &TypeId,
828d3d88d08SYonghong Song bool CheckPointer, bool SeenPointer) {
8296db6b56aSYonghong Song if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {
8306db6b56aSYonghong Song TypeId = DIToIdMap[Ty];
83189648eb1SYonghong Song
83289648eb1SYonghong Song // To handle the case like the following:
83389648eb1SYonghong Song // struct t;
83489648eb1SYonghong Song // typedef struct t _t;
83589648eb1SYonghong Song // struct s1 { _t *c; };
83689648eb1SYonghong Song // int test1(struct s1 *arg) { ... }
83789648eb1SYonghong Song //
83889648eb1SYonghong Song // struct t { int a; int b; };
83989648eb1SYonghong Song // struct s2 { _t c; }
84089648eb1SYonghong Song // int test2(struct s2 *arg) { ... }
84189648eb1SYonghong Song //
84289648eb1SYonghong Song // During traversing test1() argument, "_t" is recorded
84389648eb1SYonghong Song // in DIToIdMap and a forward declaration fixup is created
84489648eb1SYonghong Song // for "struct t" to avoid pointee type traversal.
84589648eb1SYonghong Song //
84689648eb1SYonghong Song // During traversing test2() argument, even if we see "_t" is
84789648eb1SYonghong Song // already defined, we should keep moving to eventually
84889648eb1SYonghong Song // bring in types for "struct t". Otherwise, the "struct s2"
84989648eb1SYonghong Song // definition won't be correct.
8503671bdbcSYonghong Song //
8513671bdbcSYonghong Song // In the above, we have following debuginfo:
8523671bdbcSYonghong Song // {ptr, struct_member} -> typedef -> struct
8533671bdbcSYonghong Song // and BTF type for 'typedef' is generated while 'struct' may
8543671bdbcSYonghong Song // be in FixUp. But let us generalize the above to handle
8553671bdbcSYonghong Song // {different types} -> [various derived types]+ -> another type.
8563671bdbcSYonghong Song // For example,
8573671bdbcSYonghong Song // {func_param, struct_member} -> const -> ptr -> volatile -> struct
8583671bdbcSYonghong Song // We will traverse const/ptr/volatile which already have corresponding
8593671bdbcSYonghong Song // BTF types and generate type for 'struct' which might be in Fixup
8603671bdbcSYonghong Song // state.
86189648eb1SYonghong Song if (Ty && (!CheckPointer || !SeenPointer)) {
86289648eb1SYonghong Song if (const auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
8633671bdbcSYonghong Song while (DTy) {
8643671bdbcSYonghong Song const DIType *BaseTy = DTy->getBaseType();
8653671bdbcSYonghong Song if (!BaseTy)
8663671bdbcSYonghong Song break;
8673671bdbcSYonghong Song
8683671bdbcSYonghong Song if (DIToIdMap.find(BaseTy) != DIToIdMap.end()) {
8693671bdbcSYonghong Song DTy = dyn_cast<DIDerivedType>(BaseTy);
8703671bdbcSYonghong Song } else {
87189648eb1SYonghong Song uint32_t TmpTypeId;
8723671bdbcSYonghong Song visitTypeEntry(BaseTy, TmpTypeId, CheckPointer, SeenPointer);
8733671bdbcSYonghong Song break;
8743671bdbcSYonghong Song }
87589648eb1SYonghong Song }
87689648eb1SYonghong Song }
87789648eb1SYonghong Song }
87889648eb1SYonghong Song
8797b410ac3SYonghong Song return;
8806db6b56aSYonghong Song }
8817b410ac3SYonghong Song
8827b410ac3SYonghong Song if (const auto *BTy = dyn_cast<DIBasicType>(Ty))
8836db6b56aSYonghong Song visitBasicType(BTy, TypeId);
8847b410ac3SYonghong Song else if (const auto *STy = dyn_cast<DISubroutineType>(Ty))
8857b410ac3SYonghong Song visitSubroutineType(STy, false, std::unordered_map<uint32_t, StringRef>(),
8867b410ac3SYonghong Song TypeId);
8877b410ac3SYonghong Song else if (const auto *CTy = dyn_cast<DICompositeType>(Ty))
8886db6b56aSYonghong Song visitCompositeType(CTy, TypeId);
8897b410ac3SYonghong Song else if (const auto *DTy = dyn_cast<DIDerivedType>(Ty))
890d3d88d08SYonghong Song visitDerivedType(DTy, TypeId, CheckPointer, SeenPointer);
8917b410ac3SYonghong Song else
8927b410ac3SYonghong Song llvm_unreachable("Unknown DIType");
8937b410ac3SYonghong Song }
8947b410ac3SYonghong Song
visitTypeEntry(const DIType * Ty)8956db6b56aSYonghong Song void BTFDebug::visitTypeEntry(const DIType *Ty) {
8966db6b56aSYonghong Song uint32_t TypeId;
897d3d88d08SYonghong Song visitTypeEntry(Ty, TypeId, false, false);
898d3d88d08SYonghong Song }
899d3d88d08SYonghong Song
visitMapDefType(const DIType * Ty,uint32_t & TypeId)900d3d88d08SYonghong Song void BTFDebug::visitMapDefType(const DIType *Ty, uint32_t &TypeId) {
901d3d88d08SYonghong Song if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {
902d3d88d08SYonghong Song TypeId = DIToIdMap[Ty];
903d3d88d08SYonghong Song return;
904d3d88d08SYonghong Song }
905d3d88d08SYonghong Song
906152a9fefSYonghong Song // MapDef type may be a struct type or a non-pointer derived type
907152a9fefSYonghong Song const DIType *OrigTy = Ty;
908152a9fefSYonghong Song while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
909152a9fefSYonghong Song auto Tag = DTy->getTag();
910152a9fefSYonghong Song if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type &&
911152a9fefSYonghong Song Tag != dwarf::DW_TAG_volatile_type &&
912152a9fefSYonghong Song Tag != dwarf::DW_TAG_restrict_type)
913152a9fefSYonghong Song break;
914152a9fefSYonghong Song Ty = DTy->getBaseType();
915152a9fefSYonghong Song }
916152a9fefSYonghong Song
917d3d88d08SYonghong Song const auto *CTy = dyn_cast<DICompositeType>(Ty);
918d3d88d08SYonghong Song if (!CTy)
919d3d88d08SYonghong Song return;
920d3d88d08SYonghong Song
921d3d88d08SYonghong Song auto Tag = CTy->getTag();
922d3d88d08SYonghong Song if (Tag != dwarf::DW_TAG_structure_type || CTy->isForwardDecl())
923d3d88d08SYonghong Song return;
924d3d88d08SYonghong Song
925152a9fefSYonghong Song // Visit all struct members to ensure pointee type is visited
926d3d88d08SYonghong Song const DINodeArray Elements = CTy->getElements();
927d3d88d08SYonghong Song for (const auto *Element : Elements) {
928d3d88d08SYonghong Song const auto *MemberType = cast<DIDerivedType>(Element);
929d3d88d08SYonghong Song visitTypeEntry(MemberType->getBaseType());
930d3d88d08SYonghong Song }
931152a9fefSYonghong Song
932152a9fefSYonghong Song // Visit this type, struct or a const/typedef/volatile/restrict type
933152a9fefSYonghong Song visitTypeEntry(OrigTy, TypeId, false, false);
9346db6b56aSYonghong Song }
9356db6b56aSYonghong Song
9367b410ac3SYonghong Song /// Read file contents from the actual file or from the source
populateFileContent(const DISubprogram * SP)9377b410ac3SYonghong Song std::string BTFDebug::populateFileContent(const DISubprogram *SP) {
9387b410ac3SYonghong Song auto File = SP->getFile();
9397b410ac3SYonghong Song std::string FileName;
9407b410ac3SYonghong Song
941fa365400SYonghong Song if (!File->getFilename().startswith("/") && File->getDirectory().size())
9427b410ac3SYonghong Song FileName = File->getDirectory().str() + "/" + File->getFilename().str();
9437b410ac3SYonghong Song else
944adcd0268SBenjamin Kramer FileName = std::string(File->getFilename());
9457b410ac3SYonghong Song
9467b410ac3SYonghong Song // No need to populate the contends if it has been populated!
9477b410ac3SYonghong Song if (FileContent.find(FileName) != FileContent.end())
9487b410ac3SYonghong Song return FileName;
9497b410ac3SYonghong Song
9507b410ac3SYonghong Song std::vector<std::string> Content;
9517b410ac3SYonghong Song std::string Line;
9527b410ac3SYonghong Song Content.push_back(Line); // Line 0 for empty string
9537b410ac3SYonghong Song
95483db8871SFangrui Song std::unique_ptr<MemoryBuffer> Buf;
9557b410ac3SYonghong Song auto Source = File->getSource();
95683db8871SFangrui Song if (Source)
95783db8871SFangrui Song Buf = MemoryBuffer::getMemBufferCopy(*Source);
95883db8871SFangrui Song else if (ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
95983db8871SFangrui Song MemoryBuffer::getFile(FileName))
96083db8871SFangrui Song Buf = std::move(*BufOrErr);
96183db8871SFangrui Song if (Buf)
96283db8871SFangrui Song for (line_iterator I(*Buf, false), E; I != E; ++I)
963adcd0268SBenjamin Kramer Content.push_back(std::string(*I));
9647b410ac3SYonghong Song
9657b410ac3SYonghong Song FileContent[FileName] = Content;
9667b410ac3SYonghong Song return FileName;
9677b410ac3SYonghong Song }
9687b410ac3SYonghong Song
constructLineInfo(const DISubprogram * SP,MCSymbol * Label,uint32_t Line,uint32_t Column)9697b410ac3SYonghong Song void BTFDebug::constructLineInfo(const DISubprogram *SP, MCSymbol *Label,
9707b410ac3SYonghong Song uint32_t Line, uint32_t Column) {
9717b410ac3SYonghong Song std::string FileName = populateFileContent(SP);
9727b410ac3SYonghong Song BTFLineInfo LineInfo;
9737b410ac3SYonghong Song
9747b410ac3SYonghong Song LineInfo.Label = Label;
9757b410ac3SYonghong Song LineInfo.FileNameOff = addString(FileName);
9767b410ac3SYonghong Song // If file content is not available, let LineOff = 0.
9777b410ac3SYonghong Song if (Line < FileContent[FileName].size())
9787b410ac3SYonghong Song LineInfo.LineOff = addString(FileContent[FileName][Line]);
9797b410ac3SYonghong Song else
9807b410ac3SYonghong Song LineInfo.LineOff = 0;
9817b410ac3SYonghong Song LineInfo.LineNum = Line;
9827b410ac3SYonghong Song LineInfo.ColumnNum = Column;
9837b410ac3SYonghong Song LineInfoTable[SecNameOff].push_back(LineInfo);
9847b410ac3SYonghong Song }
9857b410ac3SYonghong Song
emitCommonHeader()9867b410ac3SYonghong Song void BTFDebug::emitCommonHeader() {
9877b410ac3SYonghong Song OS.AddComment("0x" + Twine::utohexstr(BTF::MAGIC));
98877497103SFangrui Song OS.emitIntValue(BTF::MAGIC, 2);
989692e0c96SFangrui Song OS.emitInt8(BTF::VERSION);
990692e0c96SFangrui Song OS.emitInt8(0);
9917b410ac3SYonghong Song }
9927b410ac3SYonghong Song
emitBTFSection()9937b410ac3SYonghong Song void BTFDebug::emitBTFSection() {
994d82247cbSYonghong Song // Do not emit section if no types and only "" string.
995d82247cbSYonghong Song if (!TypeEntries.size() && StringTable.getSize() == 1)
996d82247cbSYonghong Song return;
997d82247cbSYonghong Song
9987b410ac3SYonghong Song MCContext &Ctx = OS.getContext();
999cd40b5a7SYonghong Song MCSectionELF *Sec = Ctx.getELFSection(".BTF", ELF::SHT_PROGBITS, 0);
1000cd40b5a7SYonghong Song Sec->setAlignment(Align(4));
1001adf4142fSFangrui Song OS.switchSection(Sec);
10027b410ac3SYonghong Song
10037b410ac3SYonghong Song // Emit header.
10047b410ac3SYonghong Song emitCommonHeader();
1005692e0c96SFangrui Song OS.emitInt32(BTF::HeaderSize);
10067b410ac3SYonghong Song
10077b410ac3SYonghong Song uint32_t TypeLen = 0, StrLen;
10087b410ac3SYonghong Song for (const auto &TypeEntry : TypeEntries)
10097b410ac3SYonghong Song TypeLen += TypeEntry->getSize();
10107b410ac3SYonghong Song StrLen = StringTable.getSize();
10117b410ac3SYonghong Song
1012692e0c96SFangrui Song OS.emitInt32(0);
1013692e0c96SFangrui Song OS.emitInt32(TypeLen);
1014692e0c96SFangrui Song OS.emitInt32(TypeLen);
1015692e0c96SFangrui Song OS.emitInt32(StrLen);
10167b410ac3SYonghong Song
10177b410ac3SYonghong Song // Emit type table.
10187b410ac3SYonghong Song for (const auto &TypeEntry : TypeEntries)
10197b410ac3SYonghong Song TypeEntry->emitType(OS);
10207b410ac3SYonghong Song
10217b410ac3SYonghong Song // Emit string table.
10227b410ac3SYonghong Song uint32_t StringOffset = 0;
10237b410ac3SYonghong Song for (const auto &S : StringTable.getTable()) {
10247b410ac3SYonghong Song OS.AddComment("string offset=" + std::to_string(StringOffset));
1025a55daa14SFangrui Song OS.emitBytes(S);
1026a55daa14SFangrui Song OS.emitBytes(StringRef("\0", 1));
10277b410ac3SYonghong Song StringOffset += S.size() + 1;
10287b410ac3SYonghong Song }
10297b410ac3SYonghong Song }
10307b410ac3SYonghong Song
emitBTFExtSection()10317b410ac3SYonghong Song void BTFDebug::emitBTFExtSection() {
1032d46a6a9eSYonghong Song // Do not emit section if empty FuncInfoTable and LineInfoTable
1033d46a6a9eSYonghong Song // and FieldRelocTable.
1034d3d88d08SYonghong Song if (!FuncInfoTable.size() && !LineInfoTable.size() &&
1035d46a6a9eSYonghong Song !FieldRelocTable.size())
1036d82247cbSYonghong Song return;
1037d82247cbSYonghong Song
10387b410ac3SYonghong Song MCContext &Ctx = OS.getContext();
1039cd40b5a7SYonghong Song MCSectionELF *Sec = Ctx.getELFSection(".BTF.ext", ELF::SHT_PROGBITS, 0);
1040cd40b5a7SYonghong Song Sec->setAlignment(Align(4));
1041adf4142fSFangrui Song OS.switchSection(Sec);
10427b410ac3SYonghong Song
10437b410ac3SYonghong Song // Emit header.
10447b410ac3SYonghong Song emitCommonHeader();
1045692e0c96SFangrui Song OS.emitInt32(BTF::ExtHeaderSize);
10467b410ac3SYonghong Song
10477b410ac3SYonghong Song // Account for FuncInfo/LineInfo record size as well.
10487b410ac3SYonghong Song uint32_t FuncLen = 4, LineLen = 4;
1049d46a6a9eSYonghong Song // Do not account for optional FieldReloc.
1050d46a6a9eSYonghong Song uint32_t FieldRelocLen = 0;
10517b410ac3SYonghong Song for (const auto &FuncSec : FuncInfoTable) {
10527b410ac3SYonghong Song FuncLen += BTF::SecFuncInfoSize;
10537b410ac3SYonghong Song FuncLen += FuncSec.second.size() * BTF::BPFFuncInfoSize;
10547b410ac3SYonghong Song }
10557b410ac3SYonghong Song for (const auto &LineSec : LineInfoTable) {
10567b410ac3SYonghong Song LineLen += BTF::SecLineInfoSize;
10577b410ac3SYonghong Song LineLen += LineSec.second.size() * BTF::BPFLineInfoSize;
10587b410ac3SYonghong Song }
105905e46979SYonghong Song for (const auto &FieldRelocSec : FieldRelocTable) {
106005e46979SYonghong Song FieldRelocLen += BTF::SecFieldRelocSize;
106105e46979SYonghong Song FieldRelocLen += FieldRelocSec.second.size() * BTF::BPFFieldRelocSize;
1062d3d88d08SYonghong Song }
1063d3d88d08SYonghong Song
106405e46979SYonghong Song if (FieldRelocLen)
106505e46979SYonghong Song FieldRelocLen += 4;
10667b410ac3SYonghong Song
1067692e0c96SFangrui Song OS.emitInt32(0);
1068692e0c96SFangrui Song OS.emitInt32(FuncLen);
1069692e0c96SFangrui Song OS.emitInt32(FuncLen);
1070692e0c96SFangrui Song OS.emitInt32(LineLen);
1071692e0c96SFangrui Song OS.emitInt32(FuncLen + LineLen);
1072692e0c96SFangrui Song OS.emitInt32(FieldRelocLen);
10737b410ac3SYonghong Song
10747b410ac3SYonghong Song // Emit func_info table.
10757b410ac3SYonghong Song OS.AddComment("FuncInfo");
1076692e0c96SFangrui Song OS.emitInt32(BTF::BPFFuncInfoSize);
10777b410ac3SYonghong Song for (const auto &FuncSec : FuncInfoTable) {
10787b410ac3SYonghong Song OS.AddComment("FuncInfo section string offset=" +
10797b410ac3SYonghong Song std::to_string(FuncSec.first));
1080692e0c96SFangrui Song OS.emitInt32(FuncSec.first);
1081692e0c96SFangrui Song OS.emitInt32(FuncSec.second.size());
10827b410ac3SYonghong Song for (const auto &FuncInfo : FuncSec.second) {
10830bc77a0fSFangrui Song Asm->emitLabelReference(FuncInfo.Label, 4);
1084692e0c96SFangrui Song OS.emitInt32(FuncInfo.TypeId);
10857b410ac3SYonghong Song }
10867b410ac3SYonghong Song }
10877b410ac3SYonghong Song
10887b410ac3SYonghong Song // Emit line_info table.
10897b410ac3SYonghong Song OS.AddComment("LineInfo");
1090692e0c96SFangrui Song OS.emitInt32(BTF::BPFLineInfoSize);
10917b410ac3SYonghong Song for (const auto &LineSec : LineInfoTable) {
10927b410ac3SYonghong Song OS.AddComment("LineInfo section string offset=" +
10937b410ac3SYonghong Song std::to_string(LineSec.first));
1094692e0c96SFangrui Song OS.emitInt32(LineSec.first);
1095692e0c96SFangrui Song OS.emitInt32(LineSec.second.size());
10967b410ac3SYonghong Song for (const auto &LineInfo : LineSec.second) {
10970bc77a0fSFangrui Song Asm->emitLabelReference(LineInfo.Label, 4);
1098692e0c96SFangrui Song OS.emitInt32(LineInfo.FileNameOff);
1099692e0c96SFangrui Song OS.emitInt32(LineInfo.LineOff);
11007b410ac3SYonghong Song OS.AddComment("Line " + std::to_string(LineInfo.LineNum) + " Col " +
11017b410ac3SYonghong Song std::to_string(LineInfo.ColumnNum));
1102692e0c96SFangrui Song OS.emitInt32(LineInfo.LineNum << 10 | LineInfo.ColumnNum);
11037b410ac3SYonghong Song }
11047b410ac3SYonghong Song }
1105d3d88d08SYonghong Song
110605e46979SYonghong Song // Emit field reloc table.
110705e46979SYonghong Song if (FieldRelocLen) {
110805e46979SYonghong Song OS.AddComment("FieldReloc");
1109692e0c96SFangrui Song OS.emitInt32(BTF::BPFFieldRelocSize);
111005e46979SYonghong Song for (const auto &FieldRelocSec : FieldRelocTable) {
111105e46979SYonghong Song OS.AddComment("Field reloc section string offset=" +
111205e46979SYonghong Song std::to_string(FieldRelocSec.first));
1113692e0c96SFangrui Song OS.emitInt32(FieldRelocSec.first);
1114692e0c96SFangrui Song OS.emitInt32(FieldRelocSec.second.size());
111505e46979SYonghong Song for (const auto &FieldRelocInfo : FieldRelocSec.second) {
11160bc77a0fSFangrui Song Asm->emitLabelReference(FieldRelocInfo.Label, 4);
1117692e0c96SFangrui Song OS.emitInt32(FieldRelocInfo.TypeID);
1118692e0c96SFangrui Song OS.emitInt32(FieldRelocInfo.OffsetNameOff);
1119692e0c96SFangrui Song OS.emitInt32(FieldRelocInfo.RelocKind);
1120d3d88d08SYonghong Song }
1121d3d88d08SYonghong Song }
1122d3d88d08SYonghong Song }
11237b410ac3SYonghong Song }
11247b410ac3SYonghong Song
beginFunctionImpl(const MachineFunction * MF)11257b410ac3SYonghong Song void BTFDebug::beginFunctionImpl(const MachineFunction *MF) {
11267b410ac3SYonghong Song auto *SP = MF->getFunction().getSubprogram();
11277b410ac3SYonghong Song auto *Unit = SP->getUnit();
11287b410ac3SYonghong Song
11297b410ac3SYonghong Song if (Unit->getEmissionKind() == DICompileUnit::NoDebug) {
11307b410ac3SYonghong Song SkipInstruction = true;
11317b410ac3SYonghong Song return;
11327b410ac3SYonghong Song }
11337b410ac3SYonghong Song SkipInstruction = false;
11347b410ac3SYonghong Song
1135d3d88d08SYonghong Song // Collect MapDef types. Map definition needs to collect
1136d3d88d08SYonghong Song // pointee types. Do it first. Otherwise, for the following
1137d3d88d08SYonghong Song // case:
1138d3d88d08SYonghong Song // struct m { ...};
1139d3d88d08SYonghong Song // struct t {
1140d3d88d08SYonghong Song // struct m *key;
1141d3d88d08SYonghong Song // };
1142d3d88d08SYonghong Song // foo(struct t *arg);
1143d3d88d08SYonghong Song //
1144d3d88d08SYonghong Song // struct mapdef {
1145d3d88d08SYonghong Song // ...
1146d3d88d08SYonghong Song // struct m *key;
1147d3d88d08SYonghong Song // ...
1148d3d88d08SYonghong Song // } __attribute__((section(".maps"))) hash_map;
1149d3d88d08SYonghong Song //
1150d3d88d08SYonghong Song // If subroutine foo is traversed first, a type chain
1151d3d88d08SYonghong Song // "ptr->struct m(fwd)" will be created and later on
1152d3d88d08SYonghong Song // when traversing mapdef, since "ptr->struct m" exists,
1153d3d88d08SYonghong Song // the traversal of "struct m" will be omitted.
1154d3d88d08SYonghong Song if (MapDefNotCollected) {
1155d3d88d08SYonghong Song processGlobals(true);
1156d3d88d08SYonghong Song MapDefNotCollected = false;
1157d3d88d08SYonghong Song }
1158d3d88d08SYonghong Song
11597b410ac3SYonghong Song // Collect all types locally referenced in this function.
11607b410ac3SYonghong Song // Use RetainedNodes so we can collect all argument names
11617b410ac3SYonghong Song // even if the argument is not used.
11627b410ac3SYonghong Song std::unordered_map<uint32_t, StringRef> FuncArgNames;
11637b410ac3SYonghong Song for (const DINode *DN : SP->getRetainedNodes()) {
11647b410ac3SYonghong Song if (const auto *DV = dyn_cast<DILocalVariable>(DN)) {
11657b410ac3SYonghong Song // Collect function arguments for subprogram func type.
11667b410ac3SYonghong Song uint32_t Arg = DV->getArg();
1167cacac05aSYonghong Song if (Arg) {
1168da82ce99SFangrui Song visitTypeEntry(DV->getType());
11697b410ac3SYonghong Song FuncArgNames[Arg] = DV->getName();
11707b410ac3SYonghong Song }
11717b410ac3SYonghong Song }
1172cacac05aSYonghong Song }
11737b410ac3SYonghong Song
11747b410ac3SYonghong Song // Construct subprogram func proto type.
11757b410ac3SYonghong Song uint32_t ProtoTypeId;
11767b410ac3SYonghong Song visitSubroutineType(SP->getType(), true, FuncArgNames, ProtoTypeId);
11777b410ac3SYonghong Song
11787b410ac3SYonghong Song // Construct subprogram func type
1179fbb64aa6SYonghong Song uint8_t Scope = SP->isLocalToUnit() ? BTF::FUNC_STATIC : BTF::FUNC_GLOBAL;
11807b410ac3SYonghong Song auto FuncTypeEntry =
1181fbb64aa6SYonghong Song std::make_unique<BTFTypeFunc>(SP->getName(), ProtoTypeId, Scope);
11827b410ac3SYonghong Song uint32_t FuncTypeId = addType(std::move(FuncTypeEntry));
11837b410ac3SYonghong Song
118449489270SYonghong Song // Process argument annotations.
118549489270SYonghong Song for (const DINode *DN : SP->getRetainedNodes()) {
118649489270SYonghong Song if (const auto *DV = dyn_cast<DILocalVariable>(DN)) {
118749489270SYonghong Song uint32_t Arg = DV->getArg();
118849489270SYonghong Song if (Arg)
1189f4a8526cSYonghong Song processDeclAnnotations(DV->getAnnotations(), FuncTypeId, Arg - 1);
119049489270SYonghong Song }
119149489270SYonghong Song }
119249489270SYonghong Song
1193f4a8526cSYonghong Song processDeclAnnotations(SP->getAnnotations(), FuncTypeId, -1);
119449489270SYonghong Song
1195d3d88d08SYonghong Song for (const auto &TypeEntry : TypeEntries)
1196d3d88d08SYonghong Song TypeEntry->completeType(*this);
1197d3d88d08SYonghong Song
11987b410ac3SYonghong Song // Construct funcinfo and the first lineinfo for the function.
11997b410ac3SYonghong Song MCSymbol *FuncLabel = Asm->getFunctionBegin();
12007b410ac3SYonghong Song BTFFuncInfo FuncInfo;
12017b410ac3SYonghong Song FuncInfo.Label = FuncLabel;
12027b410ac3SYonghong Song FuncInfo.TypeId = FuncTypeId;
12037b410ac3SYonghong Song if (FuncLabel->isInSection()) {
12047b410ac3SYonghong Song MCSection &Section = FuncLabel->getSection();
12057b410ac3SYonghong Song const MCSectionELF *SectionELF = dyn_cast<MCSectionELF>(&Section);
12067b410ac3SYonghong Song assert(SectionELF && "Null section for Function Label");
12077d1ff446SFangrui Song SecNameOff = addString(SectionELF->getName());
12087b410ac3SYonghong Song } else {
12097b410ac3SYonghong Song SecNameOff = addString(".text");
12107b410ac3SYonghong Song }
12117b410ac3SYonghong Song FuncInfoTable[SecNameOff].push_back(FuncInfo);
12127b410ac3SYonghong Song }
12137b410ac3SYonghong Song
endFunctionImpl(const MachineFunction * MF)12147b410ac3SYonghong Song void BTFDebug::endFunctionImpl(const MachineFunction *MF) {
12157b410ac3SYonghong Song SkipInstruction = false;
12167b410ac3SYonghong Song LineInfoGenerated = false;
12177b410ac3SYonghong Song SecNameOff = 0;
12187b410ac3SYonghong Song }
12197b410ac3SYonghong Song
12206b01b465SYonghong Song /// On-demand populate types as requested from abstract member
12216b01b465SYonghong Song /// accessing or preserve debuginfo type.
populateType(const DIType * Ty)12226b01b465SYonghong Song unsigned BTFDebug::populateType(const DIType *Ty) {
1223d3d88d08SYonghong Song unsigned Id;
1224d3d88d08SYonghong Song visitTypeEntry(Ty, Id, false, false);
1225d3d88d08SYonghong Song for (const auto &TypeEntry : TypeEntries)
1226d3d88d08SYonghong Song TypeEntry->completeType(*this);
1227d3d88d08SYonghong Song return Id;
1228d3d88d08SYonghong Song }
1229d3d88d08SYonghong Song
123005e46979SYonghong Song /// Generate a struct member field relocation.
generatePatchImmReloc(const MCSymbol * ORSym,uint32_t RootId,const GlobalVariable * GVar,bool IsAma)12316b01b465SYonghong Song void BTFDebug::generatePatchImmReloc(const MCSymbol *ORSym, uint32_t RootId,
12326b01b465SYonghong Song const GlobalVariable *GVar, bool IsAma) {
12336b01b465SYonghong Song BTFFieldReloc FieldReloc;
12346b01b465SYonghong Song FieldReloc.Label = ORSym;
12356b01b465SYonghong Song FieldReloc.TypeID = RootId;
12366b01b465SYonghong Song
12376b01b465SYonghong Song StringRef AccessPattern = GVar->getName();
123837d24a69SYonghong Song size_t FirstDollar = AccessPattern.find_first_of('$');
12396b01b465SYonghong Song if (IsAma) {
124037d24a69SYonghong Song size_t FirstColon = AccessPattern.find_first_of(':');
124105e46979SYonghong Song size_t SecondColon = AccessPattern.find_first_of(':', FirstColon + 1);
124237d24a69SYonghong Song StringRef IndexPattern = AccessPattern.substr(FirstDollar + 1);
124305e46979SYonghong Song StringRef RelocKindStr = AccessPattern.substr(FirstColon + 1,
124405e46979SYonghong Song SecondColon - FirstColon);
124505e46979SYonghong Song StringRef PatchImmStr = AccessPattern.substr(SecondColon + 1,
124605e46979SYonghong Song FirstDollar - SecondColon);
1247d3d88d08SYonghong Song
124805e46979SYonghong Song FieldReloc.OffsetNameOff = addString(IndexPattern);
1249adcd0268SBenjamin Kramer FieldReloc.RelocKind = std::stoull(std::string(RelocKindStr));
12506d218b4aSYonghong Song PatchImms[GVar] = std::make_pair(std::stoll(std::string(PatchImmStr)),
12516d218b4aSYonghong Song FieldReloc.RelocKind);
12526b01b465SYonghong Song } else {
12536b01b465SYonghong Song StringRef RelocStr = AccessPattern.substr(FirstDollar + 1);
12546b01b465SYonghong Song FieldReloc.OffsetNameOff = addString("0");
12556b01b465SYonghong Song FieldReloc.RelocKind = std::stoull(std::string(RelocStr));
12566d218b4aSYonghong Song PatchImms[GVar] = std::make_pair(RootId, FieldReloc.RelocKind);
12576b01b465SYonghong Song }
125805e46979SYonghong Song FieldRelocTable[SecNameOff].push_back(FieldReloc);
1259d3d88d08SYonghong Song }
1260d3d88d08SYonghong Song
processGlobalValue(const MachineOperand & MO)1261bba7338bSYonghong Song void BTFDebug::processGlobalValue(const MachineOperand &MO) {
1262d3d88d08SYonghong Song // check whether this is a candidate or not
1263d3d88d08SYonghong Song if (MO.isGlobal()) {
1264d3d88d08SYonghong Song const GlobalValue *GVal = MO.getGlobal();
1265d3d88d08SYonghong Song auto *GVar = dyn_cast<GlobalVariable>(GVal);
1266bba7338bSYonghong Song if (!GVar) {
1267bba7338bSYonghong Song // Not a global variable. Maybe an extern function reference.
1268bba7338bSYonghong Song processFuncPrototypes(dyn_cast<Function>(GVal));
12696b01b465SYonghong Song return;
1270bba7338bSYonghong Song }
12716b01b465SYonghong Song
12726b01b465SYonghong Song if (!GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr) &&
12736b01b465SYonghong Song !GVar->hasAttribute(BPFCoreSharedInfo::TypeIdAttr))
12746b01b465SYonghong Song return;
12756b01b465SYonghong Song
1276d3d88d08SYonghong Song MCSymbol *ORSym = OS.getContext().createTempSymbol();
12776d2d589bSFangrui Song OS.emitLabel(ORSym);
1278d3d88d08SYonghong Song
1279d3d88d08SYonghong Song MDNode *MDN = GVar->getMetadata(LLVMContext::MD_preserve_access_index);
12806b01b465SYonghong Song uint32_t RootId = populateType(dyn_cast<DIType>(MDN));
12816b01b465SYonghong Song generatePatchImmReloc(ORSym, RootId, GVar,
12826b01b465SYonghong Song GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr));
1283d3d88d08SYonghong Song }
1284d3d88d08SYonghong Song }
1285d3d88d08SYonghong Song
beginInstruction(const MachineInstr * MI)12867b410ac3SYonghong Song void BTFDebug::beginInstruction(const MachineInstr *MI) {
12877b410ac3SYonghong Song DebugHandlerBase::beginInstruction(MI);
12887b410ac3SYonghong Song
12897b410ac3SYonghong Song if (SkipInstruction || MI->isMetaInstruction() ||
12907b410ac3SYonghong Song MI->getFlag(MachineInstr::FrameSetup))
12917b410ac3SYonghong Song return;
12927b410ac3SYonghong Song
12937b410ac3SYonghong Song if (MI->isInlineAsm()) {
12947b410ac3SYonghong Song // Count the number of register definitions to find the asm string.
12957b410ac3SYonghong Song unsigned NumDefs = 0;
12967b410ac3SYonghong Song for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef();
12977b410ac3SYonghong Song ++NumDefs)
12987b410ac3SYonghong Song ;
12997b410ac3SYonghong Song
13007b410ac3SYonghong Song // Skip this inline asm instruction if the asmstr is empty.
13017b410ac3SYonghong Song const char *AsmStr = MI->getOperand(NumDefs).getSymbolName();
13027b410ac3SYonghong Song if (AsmStr[0] == 0)
13037b410ac3SYonghong Song return;
13047b410ac3SYonghong Song }
13057b410ac3SYonghong Song
1306ffd57408SYonghong Song if (MI->getOpcode() == BPF::LD_imm64) {
1307ffd57408SYonghong Song // If the insn is "r2 = LD_imm64 @<an AmaAttr global>",
1308ffd57408SYonghong Song // add this insn into the .BTF.ext FieldReloc subsection.
1309ffd57408SYonghong Song // Relocation looks like:
1310ffd57408SYonghong Song // . SecName:
1311ffd57408SYonghong Song // . InstOffset
1312ffd57408SYonghong Song // . TypeID
1313ffd57408SYonghong Song // . OffSetNameOff
1314ffd57408SYonghong Song // . RelocType
1315ffd57408SYonghong Song // Later, the insn is replaced with "r2 = <offset>"
1316ffd57408SYonghong Song // where "<offset>" equals to the offset based on current
1317ffd57408SYonghong Song // type definitions.
13186b01b465SYonghong Song //
13196b01b465SYonghong Song // If the insn is "r2 = LD_imm64 @<an TypeIdAttr global>",
13206b01b465SYonghong Song // The LD_imm64 result will be replaced with a btf type id.
1321bba7338bSYonghong Song processGlobalValue(MI->getOperand(1));
1322ffd57408SYonghong Song } else if (MI->getOpcode() == BPF::CORE_MEM ||
1323ffd57408SYonghong Song MI->getOpcode() == BPF::CORE_ALU32_MEM ||
1324ffd57408SYonghong Song MI->getOpcode() == BPF::CORE_SHIFT) {
1325ffd57408SYonghong Song // relocation insn is a load, store or shift insn.
1326bba7338bSYonghong Song processGlobalValue(MI->getOperand(3));
1327fbb64aa6SYonghong Song } else if (MI->getOpcode() == BPF::JAL) {
1328fbb64aa6SYonghong Song // check extern function references
1329fbb64aa6SYonghong Song const MachineOperand &MO = MI->getOperand(0);
1330fbb64aa6SYonghong Song if (MO.isGlobal()) {
1331fbb64aa6SYonghong Song processFuncPrototypes(dyn_cast<Function>(MO.getGlobal()));
1332fbb64aa6SYonghong Song }
1333ffd57408SYonghong Song }
1334d3d88d08SYonghong Song
1335a0ad066cSJameson Nash if (!CurMI) // no debug info
1336a0ad066cSJameson Nash return;
1337a0ad066cSJameson Nash
13387b410ac3SYonghong Song // Skip this instruction if no DebugLoc or the DebugLoc
13397b410ac3SYonghong Song // is the same as the previous instruction.
13407b410ac3SYonghong Song const DebugLoc &DL = MI->getDebugLoc();
13417b410ac3SYonghong Song if (!DL || PrevInstLoc == DL) {
13427b410ac3SYonghong Song // This instruction will be skipped, no LineInfo has
13437b410ac3SYonghong Song // been generated, construct one based on function signature.
13447b410ac3SYonghong Song if (LineInfoGenerated == false) {
13457b410ac3SYonghong Song auto *S = MI->getMF()->getFunction().getSubprogram();
13467b410ac3SYonghong Song MCSymbol *FuncLabel = Asm->getFunctionBegin();
13477b410ac3SYonghong Song constructLineInfo(S, FuncLabel, S->getLine(), 0);
13487b410ac3SYonghong Song LineInfoGenerated = true;
13497b410ac3SYonghong Song }
13507b410ac3SYonghong Song
13517b410ac3SYonghong Song return;
13527b410ac3SYonghong Song }
13537b410ac3SYonghong Song
13547b410ac3SYonghong Song // Create a temporary label to remember the insn for lineinfo.
13557b410ac3SYonghong Song MCSymbol *LineSym = OS.getContext().createTempSymbol();
13566d2d589bSFangrui Song OS.emitLabel(LineSym);
13577b410ac3SYonghong Song
13587b410ac3SYonghong Song // Construct the lineinfo.
13597b410ac3SYonghong Song auto SP = DL.get()->getScope()->getSubprogram();
13607b410ac3SYonghong Song constructLineInfo(SP, LineSym, DL.getLine(), DL.getCol());
13617b410ac3SYonghong Song
13627b410ac3SYonghong Song LineInfoGenerated = true;
13637b410ac3SYonghong Song PrevInstLoc = DL;
13647b410ac3SYonghong Song }
13657b410ac3SYonghong Song
processGlobals(bool ProcessingMapDef)1366d3d88d08SYonghong Song void BTFDebug::processGlobals(bool ProcessingMapDef) {
13677b410ac3SYonghong Song // Collect all types referenced by globals.
13687b410ac3SYonghong Song const Module *M = MMI->getModule();
1369cacac05aSYonghong Song for (const GlobalVariable &Global : M->globals()) {
1370d3d88d08SYonghong Song // Decide the section name.
1371d3d88d08SYonghong Song StringRef SecName;
1372d3d88d08SYonghong Song if (Global.hasSection()) {
1373d3d88d08SYonghong Song SecName = Global.getSection();
137444481250SYonghong Song } else if (Global.hasInitializer()) {
1375d3d88d08SYonghong Song // data, bss, or readonly sections
1376d3d88d08SYonghong Song if (Global.isConstant())
1377d3d88d08SYonghong Song SecName = ".rodata";
1378d3d88d08SYonghong Song else
1379d3d88d08SYonghong Song SecName = Global.getInitializer()->isZeroValue() ? ".bss" : ".data";
1380d3d88d08SYonghong Song }
1381d3d88d08SYonghong Song
1382d3d88d08SYonghong Song if (ProcessingMapDef != SecName.startswith(".maps"))
1383d3d88d08SYonghong Song continue;
1384d3d88d08SYonghong Song
13850e347c0fSYonghong Song // Create a .rodata datasec if the global variable is an initialized
13860e347c0fSYonghong Song // constant with private linkage and if it won't be in .rodata.str<#>
13870e347c0fSYonghong Song // and .rodata.cst<#> sections.
13880e347c0fSYonghong Song if (SecName == ".rodata" && Global.hasPrivateLinkage() &&
13890e347c0fSYonghong Song DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {
13900e347c0fSYonghong Song SectionKind GVKind =
13910e347c0fSYonghong Song TargetLoweringObjectFile::getKindForGlobal(&Global, Asm->TM);
13920e347c0fSYonghong Song // skip .rodata.str<#> and .rodata.cst<#> sections
13930e347c0fSYonghong Song if (!GVKind.isMergeableCString() && !GVKind.isMergeableConst()) {
13940e347c0fSYonghong Song DataSecEntries[std::string(SecName)] =
13950e347c0fSYonghong Song std::make_unique<BTFKindDataSec>(Asm, std::string(SecName));
13960e347c0fSYonghong Song }
13970e347c0fSYonghong Song }
13980e347c0fSYonghong Song
1399cacac05aSYonghong Song SmallVector<DIGlobalVariableExpression *, 1> GVs;
1400cacac05aSYonghong Song Global.getDebugInfo(GVs);
1401166cdc02SYonghong Song
1402166cdc02SYonghong Song // No type information, mostly internal, skip it.
1403166cdc02SYonghong Song if (GVs.size() == 0)
1404166cdc02SYonghong Song continue;
1405166cdc02SYonghong Song
14066db6b56aSYonghong Song uint32_t GVTypeId = 0;
140749489270SYonghong Song DIGlobalVariable *DIGlobal = nullptr;
1408cacac05aSYonghong Song for (auto *GVE : GVs) {
140949489270SYonghong Song DIGlobal = GVE->getVariable();
1410d3d88d08SYonghong Song if (SecName.startswith(".maps"))
141149489270SYonghong Song visitMapDefType(DIGlobal->getType(), GVTypeId);
1412d3d88d08SYonghong Song else
141349489270SYonghong Song visitTypeEntry(DIGlobal->getType(), GVTypeId, false, false);
14146db6b56aSYonghong Song break;
14157b410ac3SYonghong Song }
14166db6b56aSYonghong Song
14176db6b56aSYonghong Song // Only support the following globals:
14186db6b56aSYonghong Song // . static variables
14195ea611daSYonghong Song // . non-static weak or non-weak global variables
142044481250SYonghong Song // . weak or non-weak extern global variables
142144481250SYonghong Song // Whether DataSec is readonly or not can be found from corresponding ELF
142244481250SYonghong Song // section flags. Whether a BTF_KIND_VAR is a weak symbol or not
142344481250SYonghong Song // can be found from the corresponding ELF symbol table.
14246db6b56aSYonghong Song auto Linkage = Global.getLinkage();
14256db6b56aSYonghong Song if (Linkage != GlobalValue::InternalLinkage &&
14265ea611daSYonghong Song Linkage != GlobalValue::ExternalLinkage &&
142744481250SYonghong Song Linkage != GlobalValue::WeakAnyLinkage &&
1428968292cbSYonghong Song Linkage != GlobalValue::WeakODRLinkage &&
142944481250SYonghong Song Linkage != GlobalValue::ExternalWeakLinkage)
14306db6b56aSYonghong Song continue;
14316db6b56aSYonghong Song
143244481250SYonghong Song uint32_t GVarInfo;
143344481250SYonghong Song if (Linkage == GlobalValue::InternalLinkage) {
143444481250SYonghong Song GVarInfo = BTF::VAR_STATIC;
143544481250SYonghong Song } else if (Global.hasInitializer()) {
143644481250SYonghong Song GVarInfo = BTF::VAR_GLOBAL_ALLOCATED;
143744481250SYonghong Song } else {
143844481250SYonghong Song GVarInfo = BTF::VAR_GLOBAL_EXTERNAL;
143944481250SYonghong Song }
144044481250SYonghong Song
14416db6b56aSYonghong Song auto VarEntry =
14420eaee545SJonas Devlieghere std::make_unique<BTFKindVar>(Global.getName(), GVTypeId, GVarInfo);
14436db6b56aSYonghong Song uint32_t VarId = addType(std::move(VarEntry));
14446db6b56aSYonghong Song
1445f4a8526cSYonghong Song processDeclAnnotations(DIGlobal->getAnnotations(), VarId, -1);
144649489270SYonghong Song
1447a285bdb5SYonghong Song // An empty SecName means an extern variable without section attribute.
1448a285bdb5SYonghong Song if (SecName.empty())
1449a285bdb5SYonghong Song continue;
145044481250SYonghong Song
14516db6b56aSYonghong Song // Find or create a DataSec
1452adcd0268SBenjamin Kramer if (DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {
1453adcd0268SBenjamin Kramer DataSecEntries[std::string(SecName)] =
1454adcd0268SBenjamin Kramer std::make_unique<BTFKindDataSec>(Asm, std::string(SecName));
14556db6b56aSYonghong Song }
14566db6b56aSYonghong Song
14576db6b56aSYonghong Song // Calculate symbol size
14586db6b56aSYonghong Song const DataLayout &DL = Global.getParent()->getDataLayout();
1459fc72f3a1SNikita Popov uint32_t Size = DL.getTypeAllocSize(Global.getValueType());
14606db6b56aSYonghong Song
1461886f9ff5SYonghong Song DataSecEntries[std::string(SecName)]->addDataSecEntry(VarId,
1462886f9ff5SYonghong Song Asm->getSymbol(&Global), Size);
14636db6b56aSYonghong Song }
1464d3d88d08SYonghong Song }
14656db6b56aSYonghong Song
1466d3d88d08SYonghong Song /// Emit proper patchable instructions.
InstLower(const MachineInstr * MI,MCInst & OutMI)1467d3d88d08SYonghong Song bool BTFDebug::InstLower(const MachineInstr *MI, MCInst &OutMI) {
1468d3d88d08SYonghong Song if (MI->getOpcode() == BPF::LD_imm64) {
1469d3d88d08SYonghong Song const MachineOperand &MO = MI->getOperand(1);
1470d3d88d08SYonghong Song if (MO.isGlobal()) {
1471d3d88d08SYonghong Song const GlobalValue *GVal = MO.getGlobal();
1472d3d88d08SYonghong Song auto *GVar = dyn_cast<GlobalVariable>(GVal);
14736b01b465SYonghong Song if (GVar) {
14746b01b465SYonghong Song // Emit "mov ri, <imm>"
14756d218b4aSYonghong Song int64_t Imm;
14766d218b4aSYonghong Song uint32_t Reloc;
14776b01b465SYonghong Song if (GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr) ||
14786d218b4aSYonghong Song GVar->hasAttribute(BPFCoreSharedInfo::TypeIdAttr)) {
14796d218b4aSYonghong Song Imm = PatchImms[GVar].first;
14806d218b4aSYonghong Song Reloc = PatchImms[GVar].second;
14816d218b4aSYonghong Song } else {
14826b01b465SYonghong Song return false;
14836d218b4aSYonghong Song }
14846b01b465SYonghong Song
14856d218b4aSYonghong Song if (Reloc == BPFCoreSharedInfo::ENUM_VALUE_EXISTENCE ||
14864369223eSYonghong Song Reloc == BPFCoreSharedInfo::ENUM_VALUE ||
14874369223eSYonghong Song Reloc == BPFCoreSharedInfo::BTF_TYPE_ID_LOCAL ||
14884369223eSYonghong Song Reloc == BPFCoreSharedInfo::BTF_TYPE_ID_REMOTE)
14896d218b4aSYonghong Song OutMI.setOpcode(BPF::LD_imm64);
14906d218b4aSYonghong Song else
1491d3d88d08SYonghong Song OutMI.setOpcode(BPF::MOV_ri);
1492d3d88d08SYonghong Song OutMI.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
1493d3d88d08SYonghong Song OutMI.addOperand(MCOperand::createImm(Imm));
1494d3d88d08SYonghong Song return true;
1495d3d88d08SYonghong Song }
1496d3d88d08SYonghong Song }
1497ffd57408SYonghong Song } else if (MI->getOpcode() == BPF::CORE_MEM ||
1498ffd57408SYonghong Song MI->getOpcode() == BPF::CORE_ALU32_MEM ||
1499ffd57408SYonghong Song MI->getOpcode() == BPF::CORE_SHIFT) {
1500ffd57408SYonghong Song const MachineOperand &MO = MI->getOperand(3);
1501ffd57408SYonghong Song if (MO.isGlobal()) {
1502ffd57408SYonghong Song const GlobalValue *GVal = MO.getGlobal();
1503ffd57408SYonghong Song auto *GVar = dyn_cast<GlobalVariable>(GVal);
1504ffd57408SYonghong Song if (GVar && GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) {
15056d218b4aSYonghong Song uint32_t Imm = PatchImms[GVar].first;
1506ffd57408SYonghong Song OutMI.setOpcode(MI->getOperand(1).getImm());
1507ffd57408SYonghong Song if (MI->getOperand(0).isImm())
1508ffd57408SYonghong Song OutMI.addOperand(MCOperand::createImm(MI->getOperand(0).getImm()));
1509ffd57408SYonghong Song else
1510ffd57408SYonghong Song OutMI.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
1511ffd57408SYonghong Song OutMI.addOperand(MCOperand::createReg(MI->getOperand(2).getReg()));
1512ffd57408SYonghong Song OutMI.addOperand(MCOperand::createImm(Imm));
1513ffd57408SYonghong Song return true;
1514ffd57408SYonghong Song }
1515ffd57408SYonghong Song }
1516d3d88d08SYonghong Song }
1517d3d88d08SYonghong Song return false;
15186db6b56aSYonghong Song }
15196db6b56aSYonghong Song
processFuncPrototypes(const Function * F)1520fbb64aa6SYonghong Song void BTFDebug::processFuncPrototypes(const Function *F) {
1521fbb64aa6SYonghong Song if (!F)
1522fbb64aa6SYonghong Song return;
1523fbb64aa6SYonghong Song
1524fbb64aa6SYonghong Song const DISubprogram *SP = F->getSubprogram();
152544481250SYonghong Song if (!SP || SP->isDefinition())
1526fbb64aa6SYonghong Song return;
1527fbb64aa6SYonghong Song
1528fbb64aa6SYonghong Song // Do not emit again if already emitted.
1529*437f9600SKazu Hirata if (!ProtoFunctions.insert(F).second)
1530fbb64aa6SYonghong Song return;
153144481250SYonghong Song
153244481250SYonghong Song uint32_t ProtoTypeId;
153344481250SYonghong Song const std::unordered_map<uint32_t, StringRef> FuncArgNames;
153444481250SYonghong Song visitSubroutineType(SP->getType(), false, FuncArgNames, ProtoTypeId);
153544481250SYonghong Song
1536fbb64aa6SYonghong Song uint8_t Scope = BTF::FUNC_EXTERN;
1537fbb64aa6SYonghong Song auto FuncTypeEntry =
1538fbb64aa6SYonghong Song std::make_unique<BTFTypeFunc>(SP->getName(), ProtoTypeId, Scope);
1539886f9ff5SYonghong Song uint32_t FuncId = addType(std::move(FuncTypeEntry));
154049489270SYonghong Song
1541f4a8526cSYonghong Song processDeclAnnotations(SP->getAnnotations(), FuncId, -1);
154249489270SYonghong Song
1543886f9ff5SYonghong Song if (F->hasSection()) {
1544886f9ff5SYonghong Song StringRef SecName = F->getSection();
1545886f9ff5SYonghong Song
1546886f9ff5SYonghong Song if (DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {
1547886f9ff5SYonghong Song DataSecEntries[std::string(SecName)] =
1548886f9ff5SYonghong Song std::make_unique<BTFKindDataSec>(Asm, std::string(SecName));
1549886f9ff5SYonghong Song }
1550886f9ff5SYonghong Song
1551886f9ff5SYonghong Song // We really don't know func size, set it to 0.
1552886f9ff5SYonghong Song DataSecEntries[std::string(SecName)]->addDataSecEntry(FuncId,
1553886f9ff5SYonghong Song Asm->getSymbol(F), 0);
1554886f9ff5SYonghong Song }
155544481250SYonghong Song }
155644481250SYonghong Song
endModule()15576db6b56aSYonghong Song void BTFDebug::endModule() {
1558d3d88d08SYonghong Song // Collect MapDef globals if not collected yet.
1559d3d88d08SYonghong Song if (MapDefNotCollected) {
1560d3d88d08SYonghong Song processGlobals(true);
1561d3d88d08SYonghong Song MapDefNotCollected = false;
1562d3d88d08SYonghong Song }
1563d3d88d08SYonghong Song
1564d3d88d08SYonghong Song // Collect global types/variables except MapDef globals.
1565d3d88d08SYonghong Song processGlobals(false);
156644481250SYonghong Song
1567d3d88d08SYonghong Song for (auto &DataSec : DataSecEntries)
1568d3d88d08SYonghong Song addType(std::move(DataSec.second));
1569d3d88d08SYonghong Song
1570d3d88d08SYonghong Song // Fixups
1571d3d88d08SYonghong Song for (auto &Fixup : FixupDerivedTypes) {
1572f419029fSYonghong Song const DICompositeType *CTy = Fixup.first;
1573f419029fSYonghong Song StringRef TypeName = CTy->getName();
1574f419029fSYonghong Song bool IsUnion = CTy->getTag() == dwarf::DW_TAG_union_type;
1575d3d88d08SYonghong Song
1576d3d88d08SYonghong Song // Search through struct types
1577d3d88d08SYonghong Song uint32_t StructTypeId = 0;
1578d3d88d08SYonghong Song for (const auto &StructType : StructTypes) {
1579d3d88d08SYonghong Song if (StructType->getName() == TypeName) {
1580d3d88d08SYonghong Song StructTypeId = StructType->getId();
1581d3d88d08SYonghong Song break;
1582d3d88d08SYonghong Song }
1583d3d88d08SYonghong Song }
1584d3d88d08SYonghong Song
1585d3d88d08SYonghong Song if (StructTypeId == 0) {
15860eaee545SJonas Devlieghere auto FwdTypeEntry = std::make_unique<BTFTypeFwd>(TypeName, IsUnion);
1587d3d88d08SYonghong Song StructTypeId = addType(std::move(FwdTypeEntry));
1588d3d88d08SYonghong Song }
1589d3d88d08SYonghong Song
1590f419029fSYonghong Song for (auto &TypeInfo : Fixup.second) {
1591f419029fSYonghong Song const DIDerivedType *DTy = TypeInfo.first;
1592f419029fSYonghong Song BTFTypeDerived *BDType = TypeInfo.second;
1593f419029fSYonghong Song
1594f419029fSYonghong Song int TmpTypeId = genBTFTypeTags(DTy, StructTypeId);
1595f419029fSYonghong Song if (TmpTypeId >= 0)
1596f419029fSYonghong Song BDType->setPointeeType(TmpTypeId);
1597f419029fSYonghong Song else
1598f419029fSYonghong Song BDType->setPointeeType(StructTypeId);
1599d3d88d08SYonghong Song }
1600d3d88d08SYonghong Song }
16016db6b56aSYonghong Song
16027b410ac3SYonghong Song // Complete BTF type cross refereences.
16037b410ac3SYonghong Song for (const auto &TypeEntry : TypeEntries)
16047b410ac3SYonghong Song TypeEntry->completeType(*this);
16057b410ac3SYonghong Song
16067b410ac3SYonghong Song // Emit BTF sections.
16077b410ac3SYonghong Song emitBTFSection();
16087b410ac3SYonghong Song emitBTFExtSection();
16097b410ac3SYonghong Song }
1610