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