34#define HANDLE_BTF_KIND(ID, NAME) "BTF_KIND_" #NAME,
35#include "llvm/DebugInfo/BTF/BTF.def"
41 auto DerivedTy = dyn_cast<DIDerivedType>(Ty);
42 if (DerivedTy && DerivedTy->getTag() == dwarf::DW_TAG_atomic_type)
43 return DerivedTy->getBaseType();
59 : DTy(DTy), NeedsFixup(NeedsFixup),
Name(DTy->
getName()) {
61 case dwarf::DW_TAG_pointer_type:
62 Kind = BTF::BTF_KIND_PTR;
64 case dwarf::DW_TAG_const_type:
65 Kind = BTF::BTF_KIND_CONST;
67 case dwarf::DW_TAG_volatile_type:
68 Kind = BTF::BTF_KIND_VOLATILE;
70 case dwarf::DW_TAG_typedef:
71 Kind = BTF::BTF_KIND_TYPEDEF;
73 case dwarf::DW_TAG_restrict_type:
74 Kind = BTF::BTF_KIND_RESTRICT;
86 Kind = BTF::BTF_KIND_PTR;
98 if (NeedsFixup || !DTy)
104 assert((
Kind == BTF::BTF_KIND_PTR ||
Kind == BTF::BTF_KIND_CONST ||
105 Kind == BTF::BTF_KIND_VOLATILE) &&
106 "Invalid null basetype");
121 Kind = BTF::BTF_KIND_FWD;
142 case dwarf::DW_ATE_boolean:
145 case dwarf::DW_ATE_signed:
146 case dwarf::DW_ATE_signed_char:
149 case dwarf::DW_ATE_unsigned:
150 case dwarf::DW_ATE_unsigned_char:
157 Kind = BTF::BTF_KIND_INT;
160 IntVal = (BTFEncoding << 24) | OffsetInBits << 16 | SizeInBits;
174 OS.emitInt32(IntVal);
178 bool IsSigned) : ETy(ETy) {
179 Kind = BTF::BTF_KIND_ENUM;
192 for (
const auto Element : Elements) {
193 const auto *Enum = cast<DIEnumerator>(Element);
199 if (Enum->isUnsigned())
200 Value =
static_cast<uint32_t>(Enum->getValue().getZExtValue());
202 Value =
static_cast<uint32_t>(Enum->getValue().getSExtValue());
204 EnumValues.push_back(BTFEnum);
210 for (
const auto &Enum : EnumValues) {
211 OS.emitInt32(Enum.NameOff);
212 OS.emitInt32(Enum.Val);
217 bool IsSigned) : ETy(ETy) {
218 Kind = BTF::BTF_KIND_ENUM64;
231 for (
const auto Element : Elements) {
232 const auto *Enum = cast<DIEnumerator>(Element);
237 if (Enum->isUnsigned())
238 Value =
static_cast<uint64_t>(Enum->getValue().getZExtValue());
240 Value =
static_cast<uint64_t>(Enum->getValue().getSExtValue());
243 EnumValues.push_back(BTFEnum);
249 for (
const auto &Enum : EnumValues) {
250 OS.emitInt32(Enum.NameOff);
252 OS.emitInt32(Enum.Val_Lo32);
254 OS.emitInt32(Enum.Val_Hi32);
259 Kind = BTF::BTF_KIND_ARRAY;
265 ArrayInfo.
Nelems = NumElems;
291 : STy(STy), HasBitField(HasBitField) {
292 Kind = IsStruct ? BTF::BTF_KIND_STRUCT : BTF::BTF_KIND_UNION;
306 for (
const auto *Element : Elements) {
308 const auto *DDTy = cast<DIDerivedType>(Element);
312 uint8_t BitFieldSize = DDTy->isBitField() ? DDTy->getSizeInBits() : 0;
313 BTFMember.
Offset = BitFieldSize << 24 | DDTy->getOffsetInBits();
315 BTFMember.
Offset = DDTy->getOffsetInBits();
319 Members.push_back(BTFMember);
325 for (
const auto &Member : Members) {
326 OS.emitInt32(Member.NameOff);
327 OS.emitInt32(Member.Type);
329 OS.emitInt32(Member.Offset);
342 const std::unordered_map<uint32_t, StringRef> &FuncArgNames)
343 : STy(STy), FuncArgNames(FuncArgNames) {
344 Kind = BTF::BTF_KIND_FUNC_PROTO;
360 for (
unsigned I = 1,
N = Elements.size();
I <
N; ++
I) {
364 Param.NameOff = BDebug.
addString(FuncArgNames[
I]);
370 Parameters.push_back(Param);
376 for (
const auto &Param : Parameters) {
377 OS.emitInt32(Param.NameOff);
378 OS.emitInt32(Param.Type);
385 Kind = BTF::BTF_KIND_FUNC;
402 Kind = BTF::BTF_KIND_VAR;
418 : Asm(AsmPrt),
Name(SecName) {
419 Kind = BTF::BTF_KIND_DATASEC;
432 for (
const auto &V : Vars) {
433 OS.emitInt32(std::get<0>(V));
435 OS.emitInt32(std::get<2>(V));
441 Kind = BTF::BTF_KIND_FLOAT;
457 Kind = BTF::BTF_KIND_DECL_TAG;
477 : DTy(nullptr),
Tag(
Tag) {
478 Kind = BTF::BTF_KIND_TYPE_TAG;
485 Kind = BTF::BTF_KIND_TYPE_TAG;
505 for (
auto &OffsetM : OffsetToIdMap) {
506 if (Table[OffsetM.second] == S)
507 return OffsetM.first;
511 OffsetToIdMap[
Offset] = Table.size();
512 Table.push_back(std::string(S));
519 LineInfoGenerated(
false), SecNameOff(0), ArrayIndexTypeId(0),
520 MapDefNotCollected(
true) {
524uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry,
526 TypeEntry->setId(TypeEntries.size() + 1);
529 TypeEntries.push_back(std::move(TypeEntry));
533uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry) {
534 TypeEntry->setId(TypeEntries.size() + 1);
536 TypeEntries.push_back(std::move(TypeEntry));
545 case dwarf::DW_ATE_boolean:
546 case dwarf::DW_ATE_signed:
547 case dwarf::DW_ATE_signed_char:
548 case dwarf::DW_ATE_unsigned:
549 case dwarf::DW_ATE_unsigned_char:
552 TypeEntry = std::make_unique<BTFTypeInt>(
555 case dwarf::DW_ATE_float:
563 TypeId = addType(std::move(TypeEntry), BTy);
567void BTFDebug::visitSubroutineType(
569 const std::unordered_map<uint32_t, StringRef> &FuncArgNames,
580 auto TypeEntry = std::make_unique<BTFTypeFuncProto>(STy, VLen, FuncArgNames);
582 TypeId = addType(std::move(TypeEntry));
584 TypeId = addType(std::move(TypeEntry), STy);
587 for (
const auto Element : Elements) {
588 visitTypeEntry(Element);
592void BTFDebug::processDeclAnnotations(DINodeArray
Annotations,
599 const MDNode *MD = cast<MDNode>(Annotation);
601 if (
Name->getString() !=
"btf_decl_tag")
605 auto TypeEntry = std::make_unique<BTFTypeDeclTag>(BaseTypeId, ComponentIdx,
607 addType(std::move(TypeEntry));
614 std::make_unique<BTFTypeFunc>(SP->
getName(), ProtoTypeId, Scope);
618 for (
const DINode *DN : SP->getRetainedNodes()) {
619 if (
const auto *DV = dyn_cast<DILocalVariable>(DN)) {
622 processDeclAnnotations(DV->getAnnotations(),
FuncId, Arg - 1);
625 processDeclAnnotations(SP->getAnnotations(),
FuncId, -1);
631int BTFDebug::genBTFTypeTags(
const DIDerivedType *DTy,
int BaseTypeId) {
640 if (
Name->getString() !=
"btf_type_tag")
646 if (MDStrs.
size() == 0)
654 std::unique_ptr<BTFTypeTypeTag>
TypeEntry;
657 std::make_unique<BTFTypeTypeTag>(BaseTypeId, MDStrs[0]->getString());
659 TypeEntry = std::make_unique<BTFTypeTypeTag>(DTy, MDStrs[0]->getString());
660 TmpTypeId = addType(std::move(TypeEntry));
662 for (
unsigned I = 1;
I < MDStrs.
size();
I++) {
664 TypeEntry = std::make_unique<BTFTypeTypeTag>(TmpTypeId,
Value->getString());
665 TmpTypeId = addType(std::move(TypeEntry));
671void BTFDebug::visitStructType(
const DICompositeType *CTy,
bool IsStruct,
679 bool HasBitField =
false;
680 for (
const auto *Element : Elements) {
681 auto E = cast<DIDerivedType>(Element);
682 if (
E->isBitField()) {
689 std::make_unique<BTFTypeStruct>(CTy, IsStruct, HasBitField, VLen);
691 TypeId = addType(std::move(TypeEntry), CTy);
698 for (
const auto *Element : Elements) {
699 const auto Elem = cast<DIDerivedType>(Element);
700 visitTypeEntry(Elem);
701 processDeclAnnotations(Elem->getAnnotations(), TypeId, FieldNo);
710 visitTypeEntry(ElemType, ElemTypeId,
false,
false);
715 if (
auto *Element = dyn_cast_or_null<DINode>(Elements[
I]))
716 if (Element->getTag() == dwarf::DW_TAG_subrange_type) {
717 const DISubrange *SR = cast<DISubrange>(Element);
718 auto *CI = dyn_cast<ConstantInt *>(SR->
getCount());
719 int64_t Count = CI->getSExtValue();
724 std::make_unique<BTFTypeArray>(ElemTypeId,
725 Count >= 0 ? Count : 0);
727 ElemTypeId = addType(std::move(TypeEntry), CTy);
729 ElemTypeId = addType(std::move(TypeEntry));
738 if (!ArrayIndexTypeId) {
739 auto TypeEntry = std::make_unique<BTFTypeInt>(dwarf::DW_ATE_unsigned, 32,
740 0,
"__ARRAY_SIZE_TYPE__");
741 ArrayIndexTypeId = addType(std::move(TypeEntry));
751 bool IsSigned =
false;
752 unsigned NumBits = 32;
756 const auto *BTy = cast<DIBasicType>(CTy->
getBaseType());
757 IsSigned = BTy->
getEncoding() == dwarf::DW_ATE_signed ||
763 auto TypeEntry = std::make_unique<BTFTypeEnum>(CTy, VLen, IsSigned);
764 TypeId = addType(std::move(TypeEntry), CTy);
767 auto TypeEntry = std::make_unique<BTFTypeEnum64>(CTy, VLen, IsSigned);
768 TypeId = addType(std::move(TypeEntry), CTy);
774void BTFDebug::visitFwdDeclType(
const DICompositeType *CTy,
bool IsUnion,
777 TypeId = addType(std::move(TypeEntry), CTy);
784 if (
Tag == dwarf::DW_TAG_structure_type ||
Tag == dwarf::DW_TAG_union_type) {
787 visitFwdDeclType(CTy,
Tag == dwarf::DW_TAG_union_type, TypeId);
789 visitStructType(CTy,
Tag == dwarf::DW_TAG_structure_type, TypeId);
790 }
else if (
Tag == dwarf::DW_TAG_array_type)
791 visitArrayType(CTy, TypeId);
792 else if (
Tag == dwarf::DW_TAG_enumeration_type)
793 visitEnumType(CTy, TypeId);
796bool BTFDebug::IsForwardDeclCandidate(
const DIType *
Base) {
797 if (
const auto *CTy = dyn_cast<DICompositeType>(
Base)) {
798 auto CTag = CTy->
getTag();
799 if ((CTag == dwarf::DW_TAG_structure_type ||
800 CTag == dwarf::DW_TAG_union_type) &&
809 bool CheckPointer,
bool SeenPointer) {
812 if (
Tag == dwarf::DW_TAG_atomic_type)
813 return visitTypeEntry(DTy->getBaseType(), TypeId, CheckPointer,
818 if (CheckPointer && !SeenPointer) {
819 SeenPointer =
Tag == dwarf::DW_TAG_pointer_type;
822 if (CheckPointer && SeenPointer) {
825 if (IsForwardDeclCandidate(
Base)) {
829 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
true);
830 auto &
Fixup = FixupDerivedTypes[cast<DICompositeType>(
Base)];
832 TypeId = addType(std::move(TypeEntry), DTy);
838 if (
Tag == dwarf::DW_TAG_pointer_type) {
839 int TmpTypeId = genBTFTypeTags(DTy, -1);
840 if (TmpTypeId >= 0) {
842 std::make_unique<BTFTypeDerived>(TmpTypeId,
Tag, DTy->
getName());
843 TypeId = addType(std::move(TypeDEntry), DTy);
845 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
false);
846 TypeId = addType(std::move(TypeEntry), DTy);
848 }
else if (
Tag == dwarf::DW_TAG_typedef ||
Tag == dwarf::DW_TAG_const_type ||
849 Tag == dwarf::DW_TAG_volatile_type ||
850 Tag == dwarf::DW_TAG_restrict_type) {
851 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
false);
852 TypeId = addType(std::move(TypeEntry), DTy);
853 if (
Tag == dwarf::DW_TAG_typedef)
855 }
else if (
Tag != dwarf::DW_TAG_member) {
862 if (
Tag == dwarf::DW_TAG_member)
863 visitTypeEntry(DTy->getBaseType(), TempTypeId,
true,
false);
865 visitTypeEntry(DTy->getBaseType(), TempTypeId, CheckPointer, SeenPointer);
876 bool CheckPointer,
bool SeenPointer) {
877 if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {
878 TypeId = DIToIdMap[Ty];
909 if (Ty && (!CheckPointer || !SeenPointer)) {
910 if (
const auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
916 if (DIToIdMap.find(
BaseTy) != DIToIdMap.end()) {
917 DTy = dyn_cast<DIDerivedType>(
BaseTy);
919 if (CheckPointer && DTy->
getTag() == dwarf::DW_TAG_pointer_type) {
921 if (IsForwardDeclCandidate(
BaseTy))
925 visitTypeEntry(
BaseTy, TmpTypeId, CheckPointer, SeenPointer);
935 if (
const auto *BTy = dyn_cast<DIBasicType>(Ty))
936 visitBasicType(BTy, TypeId);
937 else if (
const auto *STy = dyn_cast<DISubroutineType>(Ty))
938 visitSubroutineType(STy,
false, std::unordered_map<uint32_t, StringRef>(),
940 else if (
const auto *CTy = dyn_cast<DICompositeType>(Ty))
941 visitCompositeType(CTy, TypeId);
942 else if (
const auto *DTy = dyn_cast<DIDerivedType>(Ty))
943 visitDerivedType(DTy, TypeId, CheckPointer, SeenPointer);
948void BTFDebug::visitTypeEntry(
const DIType *Ty) {
950 visitTypeEntry(Ty, TypeId,
false,
false);
953void BTFDebug::visitMapDefType(
const DIType *Ty,
uint32_t &TypeId) {
954 if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {
955 TypeId = DIToIdMap[Ty];
960 const DIType *OrigTy = Ty;
961 while (
auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
963 if (
Tag != dwarf::DW_TAG_typedef &&
Tag != dwarf::DW_TAG_const_type &&
964 Tag != dwarf::DW_TAG_volatile_type &&
965 Tag != dwarf::DW_TAG_restrict_type)
967 Ty = DTy->getBaseType();
970 const auto *CTy = dyn_cast<DICompositeType>(Ty);
980 for (
const auto *Element : Elements) {
981 const auto *MemberType = cast<DIDerivedType>(Element);
982 visitTypeEntry(MemberType->getBaseType());
986 visitTypeEntry(OrigTy, TypeId,
false,
false);
990std::string BTFDebug::populateFileContent(
const DIFile *File) {
991 std::string FileName;
993 if (!
File->getFilename().starts_with(
"/") &&
File->getDirectory().size())
994 FileName =
File->getDirectory().str() +
"/" +
File->getFilename().str();
996 FileName = std::string(
File->getFilename());
1002 std::vector<std::string>
Content;
1006 std::unique_ptr<MemoryBuffer> Buf;
1010 else if (
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
1012 Buf = std::move(*BufOrErr);
1015 Content.push_back(std::string(*
I));
1017 FileContent[FileName] =
Content;
1021void BTFDebug::constructLineInfo(
MCSymbol *Label,
const DIFile *File,
1023 std::string FileName = populateFileContent(File);
1029 if (Line < FileContent[FileName].
size())
1035 LineInfoTable[SecNameOff].push_back(LineInfo);
1038void BTFDebug::emitCommonHeader() {
1045void BTFDebug::emitBTFSection() {
1047 if (!TypeEntries.size() &&
StringTable.getSize() == 1)
1053 OS.switchSection(Sec);
1060 for (
const auto &TypeEntry : TypeEntries)
1065 OS.emitInt32(TypeLen);
1066 OS.emitInt32(TypeLen);
1067 OS.emitInt32(StrLen);
1070 for (
const auto &TypeEntry : TypeEntries)
1076 OS.AddComment(
"string offset=" + std::to_string(StringOffset));
1079 StringOffset += S.size() + 1;
1083void BTFDebug::emitBTFExtSection() {
1086 if (!FuncInfoTable.size() && !LineInfoTable.size() &&
1087 !FieldRelocTable.size())
1093 OS.switchSection(Sec);
1103 for (
const auto &FuncSec : FuncInfoTable) {
1107 for (
const auto &LineSec : LineInfoTable) {
1111 for (
const auto &FieldRelocSec : FieldRelocTable) {
1120 OS.emitInt32(FuncLen);
1121 OS.emitInt32(FuncLen);
1122 OS.emitInt32(LineLen);
1123 OS.emitInt32(FuncLen + LineLen);
1124 OS.emitInt32(FieldRelocLen);
1127 OS.AddComment(
"FuncInfo");
1129 for (
const auto &FuncSec : FuncInfoTable) {
1130 OS.AddComment(
"FuncInfo section string offset=" +
1131 std::to_string(FuncSec.first));
1132 OS.emitInt32(FuncSec.first);
1133 OS.emitInt32(FuncSec.second.size());
1134 for (
const auto &FuncInfo : FuncSec.second) {
1136 OS.emitInt32(FuncInfo.TypeId);
1141 OS.AddComment(
"LineInfo");
1143 for (
const auto &LineSec : LineInfoTable) {
1144 OS.AddComment(
"LineInfo section string offset=" +
1145 std::to_string(LineSec.first));
1146 OS.emitInt32(LineSec.first);
1147 OS.emitInt32(LineSec.second.size());
1148 for (
const auto &LineInfo : LineSec.second) {
1152 OS.AddComment(
"Line " + std::to_string(LineInfo.
LineNum) +
" Col " +
1159 if (FieldRelocLen) {
1160 OS.AddComment(
"FieldReloc");
1162 for (
const auto &FieldRelocSec : FieldRelocTable) {
1163 OS.AddComment(
"Field reloc section string offset=" +
1164 std::to_string(FieldRelocSec.first));
1165 OS.emitInt32(FieldRelocSec.first);
1166 OS.emitInt32(FieldRelocSec.second.size());
1167 for (
const auto &FieldRelocInfo : FieldRelocSec.second) {
1169 OS.emitInt32(FieldRelocInfo.TypeID);
1170 OS.emitInt32(FieldRelocInfo.OffsetNameOff);
1171 OS.emitInt32(FieldRelocInfo.RelocKind);
1179 auto *Unit = SP->getUnit();
1182 SkipInstruction =
true;
1185 SkipInstruction =
false;
1206 if (MapDefNotCollected) {
1207 processGlobals(
true);
1208 MapDefNotCollected =
false;
1214 std::unordered_map<uint32_t, StringRef> FuncArgNames;
1215 for (
const DINode *DN : SP->getRetainedNodes()) {
1216 if (
const auto *DV = dyn_cast<DILocalVariable>(DN)) {
1220 visitTypeEntry(DV->getType());
1221 FuncArgNames[Arg] = DV->getName();
1228 visitSubroutineType(SP->getType(),
true, FuncArgNames, ProtoTypeId);
1232 uint32_t FuncTypeId = processDISubprogram(SP, ProtoTypeId, Scope);
1234 for (
const auto &TypeEntry : TypeEntries)
1235 TypeEntry->completeType(*
this);
1240 FuncInfo.
Label = FuncLabel;
1241 FuncInfo.
TypeId = FuncTypeId;
1244 const MCSectionELF *SectionELF = dyn_cast<MCSectionELF>(&Section);
1245 assert(SectionELF &&
"Null section for Function Label");
1250 FuncInfoTable[SecNameOff].push_back(FuncInfo);
1254 SkipInstruction =
false;
1255 LineInfoGenerated =
false;
1261unsigned BTFDebug::populateType(
const DIType *Ty) {
1263 visitTypeEntry(Ty, Id,
false,
false);
1264 for (
const auto &TypeEntry : TypeEntries)
1265 TypeEntry->completeType(*
this);
1270void BTFDebug::generatePatchImmReloc(
const MCSymbol *ORSym,
uint32_t RootId,
1273 FieldReloc.
Label = ORSym;
1274 FieldReloc.
TypeID = RootId;
1280 size_t SecondColon = AccessPattern.
find_first_of(
':', FirstColon + 1);
1283 SecondColon - FirstColon);
1285 FirstDollar - SecondColon);
1288 FieldReloc.
RelocKind = std::stoull(std::string(RelocKindStr));
1289 PatchImms[GVar] = std::make_pair(std::stoll(std::string(PatchImmStr)),
1294 FieldReloc.
RelocKind = std::stoull(std::string(RelocStr));
1295 PatchImms[GVar] = std::make_pair(RootId, FieldReloc.
RelocKind);
1297 FieldRelocTable[SecNameOff].push_back(FieldReloc);
1304 auto *GVar = dyn_cast<GlobalVariable>(GVal);
1307 processFuncPrototypes(dyn_cast<Function>(GVal));
1315 MCSymbol *ORSym =
OS.getContext().createTempSymbol();
1316 OS.emitLabel(ORSym);
1319 uint32_t RootId = populateType(dyn_cast<DIType>(MDN));
1320 generatePatchImmReloc(ORSym, RootId, GVar,
1328 if (SkipInstruction ||
MI->isMetaInstruction() ||
1332 if (
MI->isInlineAsm()) {
1334 unsigned NumDefs = 0;
1349 if (
MI->getOpcode() == BPF::LD_imm64) {
1364 processGlobalValue(
MI->getOperand(1));
1365 }
else if (
MI->getOpcode() == BPF::CORE_LD64 ||
1366 MI->getOpcode() == BPF::CORE_LD32 ||
1367 MI->getOpcode() == BPF::CORE_ST ||
1368 MI->getOpcode() == BPF::CORE_SHIFT) {
1370 processGlobalValue(
MI->getOperand(3));
1371 }
else if (
MI->getOpcode() == BPF::JAL) {
1375 processFuncPrototypes(dyn_cast<Function>(MO.
getGlobal()));
1388 if (LineInfoGenerated ==
false) {
1389 auto *S =
MI->getMF()->getFunction().getSubprogram();
1393 constructLineInfo(FuncLabel, S->getFile(), S->getLine(), 0);
1394 LineInfoGenerated =
true;
1401 MCSymbol *LineSym =
OS.getContext().createTempSymbol();
1402 OS.emitLabel(LineSym);
1405 constructLineInfo(LineSym,
DL->getFile(),
DL.getLine(),
DL.getCol());
1407 LineInfoGenerated =
true;
1411void BTFDebug::processGlobals(
bool ProcessingMapDef) {
1417 std::optional<SectionKind> GVKind;
1419 if (!
Global.isDeclarationForLinker())
1422 if (
Global.isDeclarationForLinker())
1423 SecName =
Global.hasSection() ?
Global.getSection() :
"";
1424 else if (GVKind->isCommon())
1432 if (ProcessingMapDef != SecName.
starts_with(
".maps"))
1438 if (SecName ==
".rodata" &&
Global.hasPrivateLinkage() &&
1439 DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {
1441 if (!GVKind->isMergeableCString() && !GVKind->isMergeableConst()) {
1442 DataSecEntries[std::string(SecName)] =
1443 std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1448 Global.getDebugInfo(GVs);
1451 if (GVs.
size() == 0)
1456 for (
auto *GVE : GVs) {
1459 visitMapDefType(
DIGlobal->getType(), GVTypeId);
1462 visitTypeEntry(Ty, GVTypeId,
false,
false);
1485 }
else if (
Global.hasInitializer()) {
1492 std::make_unique<BTFKindVar>(
Global.getName(), GVTypeId, GVarInfo);
1493 uint32_t VarId = addType(std::move(VarEntry));
1495 processDeclAnnotations(
DIGlobal->getAnnotations(), VarId, -1);
1498 if (SecName.
empty())
1502 auto [It,
Inserted] = DataSecEntries.try_emplace(std::string(SecName));
1504 It->second = std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1512 if (
Global.hasInitializer())
1513 processGlobalInitializer(
Global.getInitializer());
1528void BTFDebug::processGlobalInitializer(
const Constant *
C) {
1529 if (
auto *Fn = dyn_cast<Function>(
C))
1530 processFuncPrototypes(Fn);
1531 if (
auto *CA = dyn_cast<ConstantAggregate>(
C)) {
1532 for (
unsigned I = 0,
N = CA->getNumOperands();
I <
N; ++
I)
1533 processGlobalInitializer(CA->getOperand(
I));
1539 if (
MI->getOpcode() == BPF::LD_imm64) {
1543 auto *GVar = dyn_cast<GlobalVariable>(GVal);
1550 Imm = PatchImms[GVar].first;
1551 Reloc = PatchImms[GVar].second;
1566 }
else if (
MI->getOpcode() == BPF::CORE_LD64 ||
1567 MI->getOpcode() == BPF::CORE_LD32 ||
1568 MI->getOpcode() == BPF::CORE_ST ||
1569 MI->getOpcode() == BPF::CORE_SHIFT) {
1573 auto *GVar = dyn_cast<GlobalVariable>(GVal);
1575 uint32_t Imm = PatchImms[GVar].first;
1577 if (
MI->getOperand(0).isImm())
1590void BTFDebug::processFuncPrototypes(
const Function *
F) {
1595 if (!SP || SP->isDefinition())
1599 if (!ProtoFunctions.insert(
F).second)
1603 const std::unordered_map<uint32_t, StringRef> FuncArgNames;
1604 visitSubroutineType(SP->getType(),
false, FuncArgNames, ProtoTypeId);
1607 if (
F->hasSection()) {
1610 auto [It, Inserted] = DataSecEntries.try_emplace(std::string(SecName));
1612 It->second = std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1621 if (MapDefNotCollected) {
1622 processGlobals(
true);
1623 MapDefNotCollected =
false;
1627 processGlobals(
false);
1629 for (
auto &DataSec : DataSecEntries)
1630 addType(std::move(DataSec.second));
1633 for (
auto &
Fixup : FixupDerivedTypes) {
1636 bool IsUnion = CTy->
getTag() == dwarf::DW_TAG_union_type;
1647 if (StructTypeId == 0) {
1648 auto FwdTypeEntry = std::make_unique<BTFTypeFwd>(TypeName, IsUnion);
1649 StructTypeId = addType(std::move(FwdTypeEntry));
1652 for (
auto &TypeInfo :
Fixup.second) {
1656 int TmpTypeId = genBTFTypeTags(DTy, StructTypeId);
1665 for (
const auto &TypeEntry : TypeEntries)
1666 TypeEntry->completeType(*
this);
1670 emitBTFExtSection();
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const char * BTFKindStr[]
static const DIType * tryRemoveAtomicType(const DIType *Ty)
This file contains support for writing BTF debug info.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
Module.h This file contains the declarations for the Module class.
PowerPC TLS Dynamic Call Fixup
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Annotations lets you mark points and ranges inside source code, for tests:
This class is intended to be used as a driving class for all asm writers.
MCSymbol * getSymbol(const GlobalValue *GV) const
TargetMachine & TM
Target machine description.
MCSymbol * getFunctionBegin() const
void emitLabelReference(const MCSymbol *Label, unsigned Size, bool IsSectionRelative=false) const
Emit something like ".long Label" where the size in bytes of the directive is specified by Size and L...
static constexpr StringRef TypeIdAttr
The attribute attached to globals representing a type id.
static constexpr StringRef AmaAttr
The attribute attached to globals representing a field access.
Collect and emit BTF information.
void endFunctionImpl(const MachineFunction *MF) override
Post process after all instructions in this function are processed.
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
bool InstLower(const MachineInstr *MI, MCInst &OutMI)
Emit proper patchable instructions.
size_t addString(StringRef S)
Add string to the string table.
uint32_t getArrayIndexTypeId()
Get the special array index type id.
uint32_t getTypeId(const DIType *Ty)
Get the type id for a particular DIType.
void endModule() override
Complete all the types and emit the BTF sections.
void beginFunctionImpl(const MachineFunction *MF) override
Gather pre-function debug information.
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
BTFKindDataSec(AsmPrinter *AsmPrt, std::string SecName)
BTFKindVar(StringRef VarName, uint32_t TypeId, uint32_t VarInfo)
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
uint32_t addString(StringRef S)
Add a string to the string table and returns its offset in the table.
BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems)
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void completeType(BTFDebug &BDebug) override
Represent a BTF array.
struct BTF::CommonType BTFType
virtual void emitType(MCStreamer &OS)
Emit types for this BTF type entry.
uint32_t roundupToBytes(uint32_t NumBits)
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
BTFTypeDeclTag(uint32_t BaseTypeId, int ComponentId, StringRef Tag)
Handle several derived types include pointer, const, volatile, typedef and restrict.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void setPointeeType(uint32_t PointeeType)
BTFTypeDerived(const DIDerivedType *Ty, unsigned Tag, bool NeedsFixup)
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
BTFTypeEnum64(const DICompositeType *ETy, uint32_t NumValues, bool IsSigned)
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
BTFTypeEnum(const DICompositeType *ETy, uint32_t NumValues, bool IsSigned)
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
BTFTypeFloat(uint32_t SizeInBits, StringRef TypeName)
BTFTypeFuncProto(const DISubroutineType *STy, uint32_t NumParams, const std::unordered_map< uint32_t, StringRef > &FuncArgNames)
The Func kind represents both subprogram and pointee of function pointers.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId, uint32_t Scope)
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
BTFTypeFwd(StringRef Name, bool IsUnion)
Represent a struct/union forward declaration.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
BTFTypeInt(uint32_t Encoding, uint32_t SizeInBits, uint32_t OffsetInBits, StringRef TypeName)
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
BTFTypeStruct(const DICompositeType *STy, bool IsStruct, bool HasBitField, uint32_t NumMembers)
Represent either a struct or a union.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
BTFTypeTypeTag(uint32_t NextTypeId, StringRef Tag)
This is an important base class in LLVM.
Basic type, like 'int' or 'float'.
unsigned getEncoding() const
DINodeArray getElements() const
DINodeArray getAnnotations() const
DIType * getBaseType() const
DINodeArray getAnnotations() const
Get annotations associated with this derived type.
Tagged DWARF-like metadata node.
dwarf::Tag getTag() const
StringRef getName() const
BoundType getCount() const
Type array for a subprogram.
DITypeRefArray getTypeArray() const
uint64_t getOffsetInBits() const
StringRef getName() const
bool isForwardDecl() const
uint64_t getSizeInBits() const
A parsed version of the target data layout string in and methods for querying it.
Base class for debug information backends.
const MachineInstr * CurMI
If nonnull, stores the current machine instruction we're processing.
AsmPrinter * Asm
Target of debug info emission.
MachineModuleInfo * MMI
Collected machine module information.
DebugLoc PrevInstLoc
Previous instruction's location information.
virtual void beginInstruction(const MachineInstr *MI)
Represents either an error or a value T.
DISubprogram * getSubprogram() const
Get the attached subprogram.
MDNode * getMetadata(unsigned KindID) const
Get the current metadata attachments for the given kind, if any.
@ InternalLinkage
Rename collisions when linking (static functions).
@ WeakODRLinkage
Same, but only replaced by something equivalent.
@ ExternalLinkage
Externally visible function.
@ WeakAnyLinkage
Keep one copy of named function when linking (weak)
@ ExternalWeakLinkage
ExternalWeak linkage description.
bool hasAttribute(Attribute::AttrKind Kind) const
Return true if the attribute exists.
Context object for machine code objects.
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
Instances of this class represent a single low-level machine instruction.
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
This represents a section on linux, lots of unix variants and some bare metal systems.
Instances of this class represent a uniqued identifier for a section in the current translation unit.
void setAlignment(Align Value)
StringRef getName() const
Streaming machine code generation interface.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
bool isInSection() const
isInSection - Check if this symbol is defined in some section (i.e., it is defined but not absolute).
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
const MDOperand & getOperand(unsigned I) const
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
const Module * getModule() const
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
const char * getSymbolName() const
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
A Module instance is used to store all the information related to an LLVM module.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool contains(StringRef Key) const
contains - Return true if the element is in the map, false otherwise.
StringRef - Represent a constant reference to a string, i.e.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
A table of densely packed, null-terminated strings indexed by offset.
Class to represent struct types.
StringRef getName() const
Return the name for this struct type if it has an identity.
static SectionKind getKindForGlobal(const GlobalObject *GO, const TargetMachine &TM)
Classify the specified global variable into a set of target independent categories embodied in Sectio...
MCSection * SectionForGlobal(const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const
This method computes the appropriate section to emit the specified global variable or function defini...
virtual TargetLoweringObjectFile * getObjFileLowering() const
static Twine utohexstr(const uint64_t &Val)
LLVM Value Representation.
StringRef getName() const
Return a constant reference to the value's name.
A forward iterator which reads text lines from a buffer.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MAX_VLEN
Max # of struct/union/enum members or func args.
@ VAR_GLOBAL_ALLOCATED
Linkage: ExternalLinkage.
@ VAR_STATIC
Linkage: InternalLinkage.
@ VAR_GLOBAL_EXTERNAL
Linkage: ExternalLinkage.
@ C
The default llvm calling convention, compatible with C.
StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
@ Global
Append to llvm.global_dtors.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Represent one field relocation.
uint32_t RelocKind
What to patch the instruction.
const MCSymbol * Label
MCSymbol identifying insn for the reloc.
uint32_t OffsetNameOff
The string to traverse types.
Represent one func and its type id.
uint32_t TypeId
Type id referring to .BTF type section.
const MCSymbol * Label
Func MCSymbol.
uint32_t LineOff
line offset in the .BTF string table
MCSymbol * Label
MCSymbol identifying insn for the lineinfo.
uint32_t ColumnNum
the column number
uint32_t FileNameOff
file name offset in the .BTF string table
uint32_t LineNum
the line number
uint32_t Nelems
Number of elements for this array.
uint32_t IndexType
Index type.
uint32_t ElemType
Element type.
BTF_KIND_ENUM64 is followed by multiple "struct BTFEnum64".
uint32_t NameOff
Enum name offset in the string table.
uint32_t Val_Hi32
Enum member hi32 value.
uint32_t Val_Lo32
Enum member lo32 value.
BTF_KIND_ENUM is followed by multiple "struct BTFEnum".
int32_t Val
Enum member value.
uint32_t NameOff
Enum name offset in the string table.
BTF_KIND_STRUCT and BTF_KIND_UNION are followed by multiple "struct BTFMember".
uint32_t NameOff
Member name offset in the string table.
uint32_t Offset
BitOffset or BitFieldSize+BitOffset.
uint32_t Type
Member type.
BTF_KIND_FUNC_PROTO are followed by multiple "struct BTFParam".
uint32_t NameOff
Type name offset in the string table.
uint32_t Info
"Info" bits arrangement: Bits 0-15: vlen (e.g.
Container for description of a global variable.