34#define HANDLE_BTF_KIND(ID, NAME) "BTF_KIND_" #NAME,
35#include "llvm/DebugInfo/BTF/BTF.def"
50 : DTy(DTy), NeedsFixup(NeedsFixup),
Name(DTy->
getName()) {
52 case dwarf::DW_TAG_pointer_type:
53 Kind = BTF::BTF_KIND_PTR;
55 case dwarf::DW_TAG_const_type:
56 Kind = BTF::BTF_KIND_CONST;
58 case dwarf::DW_TAG_volatile_type:
59 Kind = BTF::BTF_KIND_VOLATILE;
61 case dwarf::DW_TAG_typedef:
62 Kind = BTF::BTF_KIND_TYPEDEF;
64 case dwarf::DW_TAG_restrict_type:
65 Kind = BTF::BTF_KIND_RESTRICT;
77 Kind = BTF::BTF_KIND_PTR;
89 if (NeedsFixup || !DTy)
93 const DIType *ResolvedType = DTy->getBaseType();
95 assert((
Kind == BTF::BTF_KIND_PTR ||
Kind == BTF::BTF_KIND_CONST ||
96 Kind == BTF::BTF_KIND_VOLATILE) &&
97 "Invalid null basetype");
112 Kind = BTF::BTF_KIND_FWD;
133 case dwarf::DW_ATE_boolean:
136 case dwarf::DW_ATE_signed:
137 case dwarf::DW_ATE_signed_char:
140 case dwarf::DW_ATE_unsigned:
141 case dwarf::DW_ATE_unsigned_char:
148 Kind = BTF::BTF_KIND_INT;
151 IntVal = (BTFEncoding << 24) | OffsetInBits << 16 | SizeInBits;
165 OS.emitInt32(IntVal);
169 bool IsSigned) : ETy(ETy) {
170 Kind = BTF::BTF_KIND_ENUM;
183 for (
const auto Element : Elements) {
184 const auto *Enum = cast<DIEnumerator>(Element);
190 if (Enum->isUnsigned())
191 Value =
static_cast<uint32_t>(Enum->getValue().getZExtValue());
193 Value =
static_cast<uint32_t>(Enum->getValue().getSExtValue());
195 EnumValues.push_back(BTFEnum);
201 for (
const auto &Enum : EnumValues) {
202 OS.emitInt32(Enum.NameOff);
203 OS.emitInt32(Enum.Val);
208 bool IsSigned) : ETy(ETy) {
209 Kind = BTF::BTF_KIND_ENUM64;
222 for (
const auto Element : Elements) {
223 const auto *Enum = cast<DIEnumerator>(Element);
228 if (Enum->isUnsigned())
229 Value =
static_cast<uint64_t>(Enum->getValue().getZExtValue());
231 Value =
static_cast<uint64_t>(Enum->getValue().getSExtValue());
234 EnumValues.push_back(BTFEnum);
240 for (
const auto &Enum : EnumValues) {
241 OS.emitInt32(Enum.NameOff);
243 OS.emitInt32(Enum.Val_Lo32);
245 OS.emitInt32(Enum.Val_Hi32);
250 Kind = BTF::BTF_KIND_ARRAY;
256 ArrayInfo.
Nelems = NumElems;
282 : STy(STy), HasBitField(HasBitField) {
283 Kind = IsStruct ? BTF::BTF_KIND_STRUCT : BTF::BTF_KIND_UNION;
297 for (
const auto *Element : Elements) {
299 const auto *DDTy = cast<DIDerivedType>(Element);
303 uint8_t BitFieldSize = DDTy->isBitField() ? DDTy->getSizeInBits() : 0;
304 BTFMember.
Offset = BitFieldSize << 24 | DDTy->getOffsetInBits();
306 BTFMember.
Offset = DDTy->getOffsetInBits();
308 const auto *
BaseTy = DDTy->getBaseType();
310 Members.push_back(BTFMember);
316 for (
const auto &Member : Members) {
317 OS.emitInt32(Member.NameOff);
318 OS.emitInt32(Member.Type);
320 OS.emitInt32(Member.Offset);
333 const std::unordered_map<uint32_t, StringRef> &FuncArgNames)
334 : STy(STy), FuncArgNames(FuncArgNames) {
335 Kind = BTF::BTF_KIND_FUNC_PROTO;
345 auto RetType = Elements[0];
351 for (
unsigned I = 1,
N = Elements.size();
I <
N; ++
I) {
353 auto Element = Elements[
I];
355 Param.NameOff = BDebug.
addString(FuncArgNames[
I]);
361 Parameters.push_back(Param);
367 for (
const auto &Param : Parameters) {
368 OS.emitInt32(Param.NameOff);
369 OS.emitInt32(Param.Type);
376 Kind = BTF::BTF_KIND_FUNC;
393 Kind = BTF::BTF_KIND_VAR;
409 : Asm(AsmPrt),
Name(SecName) {
410 Kind = BTF::BTF_KIND_DATASEC;
423 for (
const auto &V : Vars) {
424 OS.emitInt32(std::get<0>(V));
426 OS.emitInt32(std::get<2>(V));
432 Kind = BTF::BTF_KIND_FLOAT;
448 Kind = BTF::BTF_KIND_DECL_TAG;
468 : DTy(nullptr),
Tag(
Tag) {
469 Kind = BTF::BTF_KIND_TYPE_TAG;
476 Kind = BTF::BTF_KIND_TYPE_TAG;
486 const DIType *ResolvedType = DTy->getBaseType();
496 for (
auto &OffsetM : OffsetToIdMap) {
497 if (Table[OffsetM.second] == S)
498 return OffsetM.first;
502 OffsetToIdMap[
Offset] = Table.size();
503 Table.push_back(std::string(S));
510 LineInfoGenerated(
false), SecNameOff(0), ArrayIndexTypeId(0),
511 MapDefNotCollected(
true) {
515uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry,
517 TypeEntry->setId(TypeEntries.size() + 1);
520 TypeEntries.push_back(std::move(TypeEntry));
524uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry) {
525 TypeEntry->setId(TypeEntries.size() + 1);
527 TypeEntries.push_back(std::move(TypeEntry));
536 case dwarf::DW_ATE_boolean:
537 case dwarf::DW_ATE_signed:
538 case dwarf::DW_ATE_signed_char:
539 case dwarf::DW_ATE_unsigned:
540 case dwarf::DW_ATE_unsigned_char:
543 TypeEntry = std::make_unique<BTFTypeInt>(
546 case dwarf::DW_ATE_float:
554 TypeId = addType(std::move(TypeEntry), BTy);
558void BTFDebug::visitSubroutineType(
560 const std::unordered_map<uint32_t, StringRef> &FuncArgNames,
571 auto TypeEntry = std::make_unique<BTFTypeFuncProto>(STy, VLen, FuncArgNames);
573 TypeId = addType(std::move(TypeEntry));
575 TypeId = addType(std::move(TypeEntry), STy);
578 for (
const auto Element : Elements) {
579 visitTypeEntry(Element);
583void BTFDebug::processDeclAnnotations(DINodeArray
Annotations,
590 const MDNode *MD = cast<MDNode>(Annotation);
592 if (
Name->getString() !=
"btf_decl_tag")
596 auto TypeEntry = std::make_unique<BTFTypeDeclTag>(BaseTypeId, ComponentIdx,
598 addType(std::move(TypeEntry));
603 uint32_t ProtoTypeId, uint8_t Scope) {
605 std::make_unique<BTFTypeFunc>(SP->
getName(), ProtoTypeId, Scope);
609 for (
const DINode *DN : SP->getRetainedNodes()) {
610 if (
const auto *DV = dyn_cast<DILocalVariable>(DN)) {
613 processDeclAnnotations(DV->getAnnotations(),
FuncId, Arg - 1);
616 processDeclAnnotations(SP->getAnnotations(),
FuncId, -1);
622int BTFDebug::genBTFTypeTags(
const DIDerivedType *DTy,
int BaseTypeId) {
631 if (
Name->getString() !=
"btf_type_tag")
637 if (MDStrs.
size() == 0)
645 std::unique_ptr<BTFTypeTypeTag>
TypeEntry;
648 std::make_unique<BTFTypeTypeTag>(BaseTypeId, MDStrs[0]->getString());
650 TypeEntry = std::make_unique<BTFTypeTypeTag>(DTy, MDStrs[0]->getString());
651 TmpTypeId = addType(std::move(TypeEntry));
653 for (
unsigned I = 1;
I < MDStrs.
size();
I++) {
655 TypeEntry = std::make_unique<BTFTypeTypeTag>(TmpTypeId,
Value->getString());
656 TmpTypeId = addType(std::move(TypeEntry));
662void BTFDebug::visitStructType(
const DICompositeType *CTy,
bool IsStruct,
670 bool HasBitField =
false;
671 for (
const auto *Element : Elements) {
672 auto E = cast<DIDerivedType>(Element);
673 if (
E->isBitField()) {
680 std::make_unique<BTFTypeStruct>(CTy, IsStruct, HasBitField, VLen);
682 TypeId = addType(std::move(TypeEntry), CTy);
689 for (
const auto *Element : Elements) {
690 const auto Elem = cast<DIDerivedType>(Element);
691 visitTypeEntry(Elem);
692 processDeclAnnotations(Elem->getAnnotations(), TypeId, FieldNo);
701 visitTypeEntry(ElemType, ElemTypeId,
false,
false);
706 if (
auto *Element = dyn_cast_or_null<DINode>(Elements[
I]))
707 if (Element->getTag() == dwarf::DW_TAG_subrange_type) {
708 const DISubrange *SR = cast<DISubrange>(Element);
715 std::make_unique<BTFTypeArray>(ElemTypeId,
716 Count >= 0 ? Count : 0);
718 ElemTypeId = addType(std::move(TypeEntry), CTy);
720 ElemTypeId = addType(std::move(TypeEntry));
729 if (!ArrayIndexTypeId) {
730 auto TypeEntry = std::make_unique<BTFTypeInt>(dwarf::DW_ATE_unsigned, 32,
731 0,
"__ARRAY_SIZE_TYPE__");
732 ArrayIndexTypeId = addType(std::move(TypeEntry));
742 bool IsSigned =
false;
743 unsigned NumBits = 32;
747 const auto *BTy = cast<DIBasicType>(CTy->
getBaseType());
748 IsSigned = BTy->
getEncoding() == dwarf::DW_ATE_signed ||
754 auto TypeEntry = std::make_unique<BTFTypeEnum>(CTy, VLen, IsSigned);
755 TypeId = addType(std::move(TypeEntry), CTy);
758 auto TypeEntry = std::make_unique<BTFTypeEnum64>(CTy, VLen, IsSigned);
759 TypeId = addType(std::move(TypeEntry), CTy);
765void BTFDebug::visitFwdDeclType(
const DICompositeType *CTy,
bool IsUnion,
768 TypeId = addType(std::move(TypeEntry), CTy);
775 if (
Tag == dwarf::DW_TAG_structure_type ||
Tag == dwarf::DW_TAG_union_type) {
778 visitFwdDeclType(CTy,
Tag == dwarf::DW_TAG_union_type, TypeId);
780 visitStructType(CTy,
Tag == dwarf::DW_TAG_structure_type, TypeId);
781 }
else if (
Tag == dwarf::DW_TAG_array_type)
782 visitArrayType(CTy, TypeId);
783 else if (
Tag == dwarf::DW_TAG_enumeration_type)
784 visitEnumType(CTy, TypeId);
787bool BTFDebug::IsForwardDeclCandidate(
const DIType *
Base) {
788 if (
const auto *CTy = dyn_cast<DICompositeType>(
Base)) {
789 auto CTag = CTy->
getTag();
790 if ((CTag == dwarf::DW_TAG_structure_type ||
791 CTag == dwarf::DW_TAG_union_type) &&
800 bool CheckPointer,
bool SeenPointer) {
805 if (CheckPointer && !SeenPointer) {
806 SeenPointer =
Tag == dwarf::DW_TAG_pointer_type;
809 if (CheckPointer && SeenPointer) {
812 if (IsForwardDeclCandidate(
Base)) {
816 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
true);
817 auto &
Fixup = FixupDerivedTypes[cast<DICompositeType>(
Base)];
819 TypeId = addType(std::move(TypeEntry), DTy);
825 if (
Tag == dwarf::DW_TAG_pointer_type) {
826 int TmpTypeId = genBTFTypeTags(DTy, -1);
827 if (TmpTypeId >= 0) {
829 std::make_unique<BTFTypeDerived>(TmpTypeId,
Tag, DTy->
getName());
830 TypeId = addType(std::move(TypeDEntry), DTy);
832 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
false);
833 TypeId = addType(std::move(TypeEntry), DTy);
835 }
else if (
Tag == dwarf::DW_TAG_typedef ||
Tag == dwarf::DW_TAG_const_type ||
836 Tag == dwarf::DW_TAG_volatile_type ||
837 Tag == dwarf::DW_TAG_restrict_type) {
838 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
false);
839 TypeId = addType(std::move(TypeEntry), DTy);
840 if (
Tag == dwarf::DW_TAG_typedef)
842 }
else if (
Tag != dwarf::DW_TAG_member) {
849 if (
Tag == dwarf::DW_TAG_member)
850 visitTypeEntry(DTy->getBaseType(), TempTypeId,
true,
false);
852 visitTypeEntry(DTy->getBaseType(), TempTypeId, CheckPointer, SeenPointer);
863 bool CheckPointer,
bool SeenPointer) {
864 if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {
865 TypeId = DIToIdMap[Ty];
896 if (Ty && (!CheckPointer || !SeenPointer)) {
897 if (
const auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
903 if (DIToIdMap.find(
BaseTy) != DIToIdMap.end()) {
904 DTy = dyn_cast<DIDerivedType>(
BaseTy);
906 if (CheckPointer && DTy->
getTag() == dwarf::DW_TAG_pointer_type) {
908 if (IsForwardDeclCandidate(
BaseTy))
912 visitTypeEntry(
BaseTy, TmpTypeId, CheckPointer, SeenPointer);
922 if (
const auto *BTy = dyn_cast<DIBasicType>(Ty))
923 visitBasicType(BTy, TypeId);
924 else if (
const auto *STy = dyn_cast<DISubroutineType>(Ty))
925 visitSubroutineType(STy,
false, std::unordered_map<uint32_t, StringRef>(),
927 else if (
const auto *CTy = dyn_cast<DICompositeType>(Ty))
928 visitCompositeType(CTy, TypeId);
929 else if (
const auto *DTy = dyn_cast<DIDerivedType>(Ty))
930 visitDerivedType(DTy, TypeId, CheckPointer, SeenPointer);
935void BTFDebug::visitTypeEntry(
const DIType *Ty) {
937 visitTypeEntry(Ty, TypeId,
false,
false);
940void BTFDebug::visitMapDefType(
const DIType *Ty,
uint32_t &TypeId) {
941 if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {
942 TypeId = DIToIdMap[Ty];
947 const DIType *OrigTy = Ty;
948 while (
auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
950 if (
Tag != dwarf::DW_TAG_typedef &&
Tag != dwarf::DW_TAG_const_type &&
951 Tag != dwarf::DW_TAG_volatile_type &&
952 Tag != dwarf::DW_TAG_restrict_type)
954 Ty = DTy->getBaseType();
957 const auto *CTy = dyn_cast<DICompositeType>(Ty);
967 for (
const auto *Element : Elements) {
968 const auto *MemberType = cast<DIDerivedType>(Element);
969 visitTypeEntry(MemberType->getBaseType());
973 visitTypeEntry(OrigTy, TypeId,
false,
false);
977std::string BTFDebug::populateFileContent(
const DIFile *File) {
978 std::string FileName;
980 if (!
File->getFilename().starts_with(
"/") &&
File->getDirectory().size())
981 FileName =
File->getDirectory().str() +
"/" +
File->getFilename().str();
983 FileName = std::string(
File->getFilename());
989 std::vector<std::string>
Content;
993 std::unique_ptr<MemoryBuffer> Buf;
997 else if (
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
999 Buf = std::move(*BufOrErr);
1002 Content.push_back(std::string(*
I));
1004 FileContent[FileName] =
Content;
1008void BTFDebug::constructLineInfo(
MCSymbol *Label,
const DIFile *File,
1010 std::string FileName = populateFileContent(File);
1016 if (Line < FileContent[FileName].
size())
1022 LineInfoTable[SecNameOff].push_back(LineInfo);
1025void BTFDebug::emitCommonHeader() {
1032void BTFDebug::emitBTFSection() {
1034 if (!TypeEntries.size() && StringTable.
getSize() == 1)
1040 OS.switchSection(Sec);
1047 for (
const auto &TypeEntry : TypeEntries)
1049 StrLen = StringTable.
getSize();
1052 OS.emitInt32(TypeLen);
1053 OS.emitInt32(TypeLen);
1054 OS.emitInt32(StrLen);
1057 for (
const auto &TypeEntry : TypeEntries)
1062 for (
const auto &S : StringTable.
getTable()) {
1063 OS.AddComment(
"string offset=" + std::to_string(StringOffset));
1066 StringOffset += S.size() + 1;
1070void BTFDebug::emitBTFExtSection() {
1073 if (!FuncInfoTable.size() && !LineInfoTable.size() &&
1074 !FieldRelocTable.size())
1080 OS.switchSection(Sec);
1090 for (
const auto &FuncSec : FuncInfoTable) {
1094 for (
const auto &LineSec : LineInfoTable) {
1098 for (
const auto &FieldRelocSec : FieldRelocTable) {
1107 OS.emitInt32(FuncLen);
1108 OS.emitInt32(FuncLen);
1109 OS.emitInt32(LineLen);
1110 OS.emitInt32(FuncLen + LineLen);
1111 OS.emitInt32(FieldRelocLen);
1114 OS.AddComment(
"FuncInfo");
1116 for (
const auto &FuncSec : FuncInfoTable) {
1117 OS.AddComment(
"FuncInfo section string offset=" +
1118 std::to_string(FuncSec.first));
1119 OS.emitInt32(FuncSec.first);
1120 OS.emitInt32(FuncSec.second.size());
1121 for (
const auto &FuncInfo : FuncSec.second) {
1123 OS.emitInt32(FuncInfo.TypeId);
1128 OS.AddComment(
"LineInfo");
1130 for (
const auto &LineSec : LineInfoTable) {
1131 OS.AddComment(
"LineInfo section string offset=" +
1132 std::to_string(LineSec.first));
1133 OS.emitInt32(LineSec.first);
1134 OS.emitInt32(LineSec.second.size());
1135 for (
const auto &LineInfo : LineSec.second) {
1139 OS.AddComment(
"Line " + std::to_string(LineInfo.
LineNum) +
" Col " +
1146 if (FieldRelocLen) {
1147 OS.AddComment(
"FieldReloc");
1149 for (
const auto &FieldRelocSec : FieldRelocTable) {
1150 OS.AddComment(
"Field reloc section string offset=" +
1151 std::to_string(FieldRelocSec.first));
1152 OS.emitInt32(FieldRelocSec.first);
1153 OS.emitInt32(FieldRelocSec.second.size());
1154 for (
const auto &FieldRelocInfo : FieldRelocSec.second) {
1156 OS.emitInt32(FieldRelocInfo.TypeID);
1157 OS.emitInt32(FieldRelocInfo.OffsetNameOff);
1158 OS.emitInt32(FieldRelocInfo.RelocKind);
1166 auto *Unit = SP->getUnit();
1169 SkipInstruction =
true;
1172 SkipInstruction =
false;
1193 if (MapDefNotCollected) {
1194 processGlobals(
true);
1195 MapDefNotCollected =
false;
1201 std::unordered_map<uint32_t, StringRef> FuncArgNames;
1202 for (
const DINode *DN : SP->getRetainedNodes()) {
1203 if (
const auto *DV = dyn_cast<DILocalVariable>(DN)) {
1207 visitTypeEntry(DV->getType());
1208 FuncArgNames[Arg] = DV->getName();
1215 visitSubroutineType(SP->getType(),
true, FuncArgNames, ProtoTypeId);
1219 uint32_t FuncTypeId = processDISubprogram(SP, ProtoTypeId, Scope);
1221 for (
const auto &TypeEntry : TypeEntries)
1222 TypeEntry->completeType(*
this);
1227 FuncInfo.
Label = FuncLabel;
1228 FuncInfo.
TypeId = FuncTypeId;
1231 const MCSectionELF *SectionELF = dyn_cast<MCSectionELF>(&Section);
1232 assert(SectionELF &&
"Null section for Function Label");
1237 FuncInfoTable[SecNameOff].push_back(FuncInfo);
1241 SkipInstruction =
false;
1242 LineInfoGenerated =
false;
1248unsigned BTFDebug::populateType(
const DIType *Ty) {
1250 visitTypeEntry(Ty, Id,
false,
false);
1251 for (
const auto &TypeEntry : TypeEntries)
1252 TypeEntry->completeType(*
this);
1257void BTFDebug::generatePatchImmReloc(
const MCSymbol *ORSym,
uint32_t RootId,
1260 FieldReloc.
Label = ORSym;
1261 FieldReloc.
TypeID = RootId;
1267 size_t SecondColon = AccessPattern.
find_first_of(
':', FirstColon + 1);
1270 SecondColon - FirstColon);
1272 FirstDollar - SecondColon);
1275 FieldReloc.
RelocKind = std::stoull(std::string(RelocKindStr));
1276 PatchImms[GVar] = std::make_pair(std::stoll(std::string(PatchImmStr)),
1281 FieldReloc.
RelocKind = std::stoull(std::string(RelocStr));
1282 PatchImms[GVar] = std::make_pair(RootId, FieldReloc.
RelocKind);
1284 FieldRelocTable[SecNameOff].push_back(FieldReloc);
1291 auto *GVar = dyn_cast<GlobalVariable>(GVal);
1294 processFuncPrototypes(dyn_cast<Function>(GVal));
1302 MCSymbol *ORSym =
OS.getContext().createTempSymbol();
1303 OS.emitLabel(ORSym);
1306 uint32_t RootId = populateType(dyn_cast<DIType>(MDN));
1307 generatePatchImmReloc(ORSym, RootId, GVar,
1315 if (SkipInstruction ||
MI->isMetaInstruction() ||
1319 if (
MI->isInlineAsm()) {
1321 unsigned NumDefs = 0;
1336 if (
MI->getOpcode() == BPF::LD_imm64) {
1351 processGlobalValue(
MI->getOperand(1));
1352 }
else if (
MI->getOpcode() == BPF::CORE_LD64 ||
1353 MI->getOpcode() == BPF::CORE_LD32 ||
1354 MI->getOpcode() == BPF::CORE_ST ||
1355 MI->getOpcode() == BPF::CORE_SHIFT) {
1357 processGlobalValue(
MI->getOperand(3));
1358 }
else if (
MI->getOpcode() == BPF::JAL) {
1362 processFuncPrototypes(dyn_cast<Function>(MO.
getGlobal()));
1375 if (LineInfoGenerated ==
false) {
1376 auto *S =
MI->getMF()->getFunction().getSubprogram();
1380 constructLineInfo(FuncLabel, S->getFile(), S->getLine(), 0);
1381 LineInfoGenerated =
true;
1388 MCSymbol *LineSym =
OS.getContext().createTempSymbol();
1389 OS.emitLabel(LineSym);
1392 constructLineInfo(LineSym,
DL->getFile(),
DL.getLine(),
DL.getCol());
1394 LineInfoGenerated =
true;
1398void BTFDebug::processGlobals(
bool ProcessingMapDef) {
1404 std::optional<SectionKind> GVKind;
1406 if (!
Global.isDeclarationForLinker())
1409 if (
Global.isDeclarationForLinker())
1410 SecName =
Global.hasSection() ?
Global.getSection() :
"";
1411 else if (GVKind->isCommon())
1419 if (ProcessingMapDef != SecName.
starts_with(
".maps"))
1425 if (SecName ==
".rodata" &&
Global.hasPrivateLinkage() &&
1426 DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {
1428 if (!GVKind->isMergeableCString() && !GVKind->isMergeableConst()) {
1429 DataSecEntries[std::string(SecName)] =
1430 std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1435 Global.getDebugInfo(GVs);
1438 if (GVs.
size() == 0)
1443 for (
auto *GVE : GVs) {
1446 visitMapDefType(
DIGlobal->getType(), GVTypeId);
1448 visitTypeEntry(
DIGlobal->getType(), GVTypeId,
false,
false);
1470 }
else if (
Global.hasInitializer()) {
1477 std::make_unique<BTFKindVar>(
Global.getName(), GVTypeId, GVarInfo);
1478 uint32_t VarId = addType(std::move(VarEntry));
1480 processDeclAnnotations(
DIGlobal->getAnnotations(), VarId, -1);
1483 if (SecName.
empty())
1487 if (DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {
1488 DataSecEntries[std::string(SecName)] =
1489 std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1496 DataSecEntries[std::string(SecName)]->addDataSecEntry(VarId,
1499 if (
Global.hasInitializer())
1500 processGlobalInitializer(
Global.getInitializer());
1515void BTFDebug::processGlobalInitializer(
const Constant *
C) {
1516 if (
auto *Fn = dyn_cast<Function>(
C))
1517 processFuncPrototypes(Fn);
1518 if (
auto *CA = dyn_cast<ConstantAggregate>(
C)) {
1519 for (
unsigned I = 0,
N = CA->getNumOperands();
I <
N; ++
I)
1520 processGlobalInitializer(CA->getOperand(
I));
1526 if (
MI->getOpcode() == BPF::LD_imm64) {
1530 auto *GVar = dyn_cast<GlobalVariable>(GVal);
1537 Imm = PatchImms[GVar].first;
1538 Reloc = PatchImms[GVar].second;
1553 }
else if (
MI->getOpcode() == BPF::CORE_LD64 ||
1554 MI->getOpcode() == BPF::CORE_LD32 ||
1555 MI->getOpcode() == BPF::CORE_ST ||
1556 MI->getOpcode() == BPF::CORE_SHIFT) {
1560 auto *GVar = dyn_cast<GlobalVariable>(GVal);
1562 uint32_t Imm = PatchImms[GVar].first;
1564 if (
MI->getOperand(0).isImm())
1577void BTFDebug::processFuncPrototypes(
const Function *
F) {
1582 if (!SP || SP->isDefinition())
1586 if (!ProtoFunctions.insert(
F).second)
1590 const std::unordered_map<uint32_t, StringRef> FuncArgNames;
1591 visitSubroutineType(SP->getType(),
false, FuncArgNames, ProtoTypeId);
1594 if (
F->hasSection()) {
1597 if (DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {
1598 DataSecEntries[std::string(SecName)] =
1599 std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1603 DataSecEntries[std::string(SecName)]->addDataSecEntry(
FuncId,
1610 if (MapDefNotCollected) {
1611 processGlobals(
true);
1612 MapDefNotCollected =
false;
1616 processGlobals(
false);
1618 for (
auto &DataSec : DataSecEntries)
1619 addType(std::move(DataSec.second));
1622 for (
auto &
Fixup : FixupDerivedTypes) {
1625 bool IsUnion = CTy->
getTag() == dwarf::DW_TAG_union_type;
1636 if (StructTypeId == 0) {
1637 auto FwdTypeEntry = std::make_unique<BTFTypeFwd>(TypeName, IsUnion);
1638 StructTypeId = addType(std::move(FwdTypeEntry));
1641 for (
auto &TypeInfo :
Fixup.second) {
1645 int TmpTypeId = genBTFTypeTags(DTy, StructTypeId);
1654 for (
const auto &TypeEntry : TypeEntries)
1655 TypeEntry->completeType(*
this);
1659 emitBTFExtSection();
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const char * BTFKindStr[]
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.
std::vector< std::string > & getTable()
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 the shared class of boolean and integer constants.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
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(unsigned 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.
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.
@ VAR_GLOBAL_ALLOCATED
Linkage: ExternalLinkage.
@ VAR_STATIC
Linkage: InternalLinkage.
@ VAR_GLOBAL_EXTERNAL
Linkage: ExternalLinkage.
@ MAX_VLEN
Max # of struct/union/enum members or func args.
@ 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.