33#define HANDLE_BTF_KIND(ID, NAME) "BTF_KIND_" #NAME,
34#include "llvm/DebugInfo/BTF/BTF.def"
49 : DTy(DTy), NeedsFixup(NeedsFixup),
Name(DTy->
getName()) {
51 case dwarf::DW_TAG_pointer_type:
52 Kind = BTF::BTF_KIND_PTR;
54 case dwarf::DW_TAG_const_type:
55 Kind = BTF::BTF_KIND_CONST;
57 case dwarf::DW_TAG_volatile_type:
58 Kind = BTF::BTF_KIND_VOLATILE;
60 case dwarf::DW_TAG_typedef:
61 Kind = BTF::BTF_KIND_TYPEDEF;
63 case dwarf::DW_TAG_restrict_type:
64 Kind = BTF::BTF_KIND_RESTRICT;
76 Kind = BTF::BTF_KIND_PTR;
88 if (NeedsFixup || !DTy)
92 const DIType *ResolvedType = DTy->getBaseType();
94 assert((
Kind == BTF::BTF_KIND_PTR ||
Kind == BTF::BTF_KIND_CONST ||
95 Kind == BTF::BTF_KIND_VOLATILE) &&
96 "Invalid null basetype");
111 Kind = BTF::BTF_KIND_FWD;
132 case dwarf::DW_ATE_boolean:
135 case dwarf::DW_ATE_signed:
136 case dwarf::DW_ATE_signed_char:
139 case dwarf::DW_ATE_unsigned:
140 case dwarf::DW_ATE_unsigned_char:
147 Kind = BTF::BTF_KIND_INT;
150 IntVal = (BTFEncoding << 24) | OffsetInBits << 16 | SizeInBits;
164 OS.emitInt32(IntVal);
168 bool IsSigned) : ETy(ETy) {
169 Kind = BTF::BTF_KIND_ENUM;
182 for (
const auto Element : Elements) {
183 const auto *Enum = cast<DIEnumerator>(Element);
189 if (Enum->isUnsigned())
190 Value =
static_cast<uint32_t>(Enum->getValue().getZExtValue());
192 Value =
static_cast<uint32_t>(Enum->getValue().getSExtValue());
194 EnumValues.push_back(BTFEnum);
200 for (
const auto &Enum : EnumValues) {
201 OS.emitInt32(Enum.NameOff);
202 OS.emitInt32(Enum.Val);
207 bool IsSigned) : ETy(ETy) {
208 Kind = BTF::BTF_KIND_ENUM64;
221 for (
const auto Element : Elements) {
222 const auto *Enum = cast<DIEnumerator>(Element);
227 if (Enum->isUnsigned())
228 Value =
static_cast<uint64_t>(Enum->getValue().getZExtValue());
230 Value =
static_cast<uint64_t>(Enum->getValue().getSExtValue());
233 EnumValues.push_back(BTFEnum);
239 for (
const auto &Enum : EnumValues) {
240 OS.emitInt32(Enum.NameOff);
242 OS.emitInt32(Enum.Val_Lo32);
244 OS.emitInt32(Enum.Val_Hi32);
249 Kind = BTF::BTF_KIND_ARRAY;
255 ArrayInfo.
Nelems = NumElems;
281 : STy(STy), HasBitField(HasBitField) {
282 Kind = IsStruct ? BTF::BTF_KIND_STRUCT : BTF::BTF_KIND_UNION;
296 for (
const auto *Element : Elements) {
298 const auto *DDTy = cast<DIDerivedType>(Element);
302 uint8_t BitFieldSize = DDTy->isBitField() ? DDTy->getSizeInBits() : 0;
303 BTFMember.
Offset = BitFieldSize << 24 | DDTy->getOffsetInBits();
305 BTFMember.
Offset = DDTy->getOffsetInBits();
307 const auto *
BaseTy = DDTy->getBaseType();
309 Members.push_back(BTFMember);
315 for (
const auto &Member : Members) {
316 OS.emitInt32(Member.NameOff);
317 OS.emitInt32(Member.Type);
319 OS.emitInt32(Member.Offset);
332 const std::unordered_map<uint32_t, StringRef> &FuncArgNames)
333 : STy(STy), FuncArgNames(FuncArgNames) {
334 Kind = BTF::BTF_KIND_FUNC_PROTO;
344 auto RetType = Elements[0];
350 for (
unsigned I = 1,
N = Elements.size();
I <
N; ++
I) {
352 auto Element = Elements[
I];
354 Param.NameOff = BDebug.
addString(FuncArgNames[
I]);
360 Parameters.push_back(Param);
366 for (
const auto &Param : Parameters) {
367 OS.emitInt32(Param.NameOff);
368 OS.emitInt32(Param.Type);
375 Kind = BTF::BTF_KIND_FUNC;
392 Kind = BTF::BTF_KIND_VAR;
408 : Asm(AsmPrt),
Name(SecName) {
409 Kind = BTF::BTF_KIND_DATASEC;
422 for (
const auto &V : Vars) {
423 OS.emitInt32(std::get<0>(V));
425 OS.emitInt32(std::get<2>(V));
431 Kind = BTF::BTF_KIND_FLOAT;
447 Kind = BTF::BTF_KIND_DECL_TAG;
467 : DTy(nullptr),
Tag(
Tag) {
468 Kind = BTF::BTF_KIND_TYPE_TAG;
475 Kind = BTF::BTF_KIND_TYPE_TAG;
485 const DIType *ResolvedType = DTy->getBaseType();
495 for (
auto &OffsetM : OffsetToIdMap) {
496 if (Table[OffsetM.second] == S)
497 return OffsetM.first;
501 OffsetToIdMap[
Offset] = Table.size();
502 Table.push_back(std::string(S));
509 LineInfoGenerated(
false), SecNameOff(0), ArrayIndexTypeId(0),
510 MapDefNotCollected(
true) {
514uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry,
516 TypeEntry->setId(TypeEntries.size() + 1);
519 TypeEntries.push_back(std::move(TypeEntry));
523uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry) {
524 TypeEntry->setId(TypeEntries.size() + 1);
526 TypeEntries.push_back(std::move(TypeEntry));
535 case dwarf::DW_ATE_boolean:
536 case dwarf::DW_ATE_signed:
537 case dwarf::DW_ATE_signed_char:
538 case dwarf::DW_ATE_unsigned:
539 case dwarf::DW_ATE_unsigned_char:
542 TypeEntry = std::make_unique<BTFTypeInt>(
545 case dwarf::DW_ATE_float:
553 TypeId = addType(std::move(TypeEntry), BTy);
557void BTFDebug::visitSubroutineType(
559 const std::unordered_map<uint32_t, StringRef> &FuncArgNames,
570 auto TypeEntry = std::make_unique<BTFTypeFuncProto>(STy, VLen, FuncArgNames);
572 TypeId = addType(std::move(TypeEntry));
574 TypeId = addType(std::move(TypeEntry), STy);
577 for (
const auto Element : Elements) {
578 visitTypeEntry(Element);
582void BTFDebug::processDeclAnnotations(DINodeArray
Annotations,
589 const MDNode *MD = cast<MDNode>(Annotation);
591 if (
Name->getString() !=
"btf_decl_tag")
595 auto TypeEntry = std::make_unique<BTFTypeDeclTag>(BaseTypeId, ComponentIdx,
597 addType(std::move(TypeEntry));
602 uint32_t ProtoTypeId, uint8_t Scope) {
604 std::make_unique<BTFTypeFunc>(SP->
getName(), ProtoTypeId, Scope);
608 for (
const DINode *DN : SP->getRetainedNodes()) {
609 if (
const auto *DV = dyn_cast<DILocalVariable>(DN)) {
612 processDeclAnnotations(DV->getAnnotations(),
FuncId, Arg - 1);
615 processDeclAnnotations(SP->getAnnotations(),
FuncId, -1);
621int BTFDebug::genBTFTypeTags(
const DIDerivedType *DTy,
int BaseTypeId) {
630 if (
Name->getString() !=
"btf_type_tag")
636 if (MDStrs.
size() == 0)
644 std::unique_ptr<BTFTypeTypeTag>
TypeEntry;
647 std::make_unique<BTFTypeTypeTag>(BaseTypeId, MDStrs[0]->getString());
649 TypeEntry = std::make_unique<BTFTypeTypeTag>(DTy, MDStrs[0]->getString());
650 TmpTypeId = addType(std::move(TypeEntry));
652 for (
unsigned I = 1;
I < MDStrs.
size();
I++) {
654 TypeEntry = std::make_unique<BTFTypeTypeTag>(TmpTypeId,
Value->getString());
655 TmpTypeId = addType(std::move(TypeEntry));
661void BTFDebug::visitStructType(
const DICompositeType *CTy,
bool IsStruct,
669 bool HasBitField =
false;
670 for (
const auto *Element : Elements) {
671 auto E = cast<DIDerivedType>(Element);
672 if (
E->isBitField()) {
679 std::make_unique<BTFTypeStruct>(CTy, IsStruct, HasBitField, VLen);
681 TypeId = addType(std::move(TypeEntry), CTy);
688 for (
const auto *Element : Elements) {
689 const auto Elem = cast<DIDerivedType>(Element);
690 visitTypeEntry(Elem);
691 processDeclAnnotations(Elem->getAnnotations(), TypeId, FieldNo);
700 visitTypeEntry(ElemType, ElemTypeId,
false,
false);
705 if (
auto *Element = dyn_cast_or_null<DINode>(Elements[
I]))
706 if (Element->getTag() == dwarf::DW_TAG_subrange_type) {
707 const DISubrange *SR = cast<DISubrange>(Element);
714 std::make_unique<BTFTypeArray>(ElemTypeId,
715 Count >= 0 ? Count : 0);
717 ElemTypeId = addType(std::move(TypeEntry), CTy);
719 ElemTypeId = addType(std::move(TypeEntry));
728 if (!ArrayIndexTypeId) {
729 auto TypeEntry = std::make_unique<BTFTypeInt>(dwarf::DW_ATE_unsigned, 32,
730 0,
"__ARRAY_SIZE_TYPE__");
731 ArrayIndexTypeId = addType(std::move(TypeEntry));
741 bool IsSigned =
false;
742 unsigned NumBits = 32;
746 const auto *BTy = cast<DIBasicType>(CTy->
getBaseType());
747 IsSigned = BTy->
getEncoding() == dwarf::DW_ATE_signed ||
753 auto TypeEntry = std::make_unique<BTFTypeEnum>(CTy, VLen, IsSigned);
754 TypeId = addType(std::move(TypeEntry), CTy);
757 auto TypeEntry = std::make_unique<BTFTypeEnum64>(CTy, VLen, IsSigned);
758 TypeId = addType(std::move(TypeEntry), CTy);
764void BTFDebug::visitFwdDeclType(
const DICompositeType *CTy,
bool IsUnion,
767 TypeId = addType(std::move(TypeEntry), CTy);
774 if (
Tag == dwarf::DW_TAG_structure_type ||
Tag == dwarf::DW_TAG_union_type) {
777 visitFwdDeclType(CTy,
Tag == dwarf::DW_TAG_union_type, TypeId);
779 visitStructType(CTy,
Tag == dwarf::DW_TAG_structure_type, TypeId);
780 }
else if (
Tag == dwarf::DW_TAG_array_type)
781 visitArrayType(CTy, TypeId);
782 else if (
Tag == dwarf::DW_TAG_enumeration_type)
783 visitEnumType(CTy, TypeId);
786bool BTFDebug::IsForwardDeclCandidate(
const DIType *
Base) {
787 if (
const auto *CTy = dyn_cast<DICompositeType>(
Base)) {
788 auto CTag = CTy->
getTag();
789 if ((CTag == dwarf::DW_TAG_structure_type ||
790 CTag == dwarf::DW_TAG_union_type) &&
799 bool CheckPointer,
bool SeenPointer) {
804 if (CheckPointer && !SeenPointer) {
805 SeenPointer =
Tag == dwarf::DW_TAG_pointer_type;
808 if (CheckPointer && SeenPointer) {
811 if (IsForwardDeclCandidate(
Base)) {
815 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
true);
816 auto &
Fixup = FixupDerivedTypes[cast<DICompositeType>(
Base)];
818 TypeId = addType(std::move(TypeEntry), DTy);
824 if (
Tag == dwarf::DW_TAG_pointer_type) {
825 int TmpTypeId = genBTFTypeTags(DTy, -1);
826 if (TmpTypeId >= 0) {
828 std::make_unique<BTFTypeDerived>(TmpTypeId,
Tag, DTy->
getName());
829 TypeId = addType(std::move(TypeDEntry), DTy);
831 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
false);
832 TypeId = addType(std::move(TypeEntry), DTy);
834 }
else if (
Tag == dwarf::DW_TAG_typedef ||
Tag == dwarf::DW_TAG_const_type ||
835 Tag == dwarf::DW_TAG_volatile_type ||
836 Tag == dwarf::DW_TAG_restrict_type) {
837 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
false);
838 TypeId = addType(std::move(TypeEntry), DTy);
839 if (
Tag == dwarf::DW_TAG_typedef)
841 }
else if (
Tag != dwarf::DW_TAG_member) {
848 if (
Tag == dwarf::DW_TAG_member)
849 visitTypeEntry(DTy->getBaseType(), TempTypeId,
true,
false);
851 visitTypeEntry(DTy->getBaseType(), TempTypeId, CheckPointer, SeenPointer);
862 bool CheckPointer,
bool SeenPointer) {
863 if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {
864 TypeId = DIToIdMap[Ty];
895 if (Ty && (!CheckPointer || !SeenPointer)) {
896 if (
const auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
902 if (DIToIdMap.find(
BaseTy) != DIToIdMap.end()) {
903 DTy = dyn_cast<DIDerivedType>(
BaseTy);
905 if (CheckPointer && DTy->
getTag() == dwarf::DW_TAG_pointer_type) {
907 if (IsForwardDeclCandidate(
BaseTy))
911 visitTypeEntry(
BaseTy, TmpTypeId, CheckPointer, SeenPointer);
921 if (
const auto *BTy = dyn_cast<DIBasicType>(Ty))
922 visitBasicType(BTy, TypeId);
923 else if (
const auto *STy = dyn_cast<DISubroutineType>(Ty))
924 visitSubroutineType(STy,
false, std::unordered_map<uint32_t, StringRef>(),
926 else if (
const auto *CTy = dyn_cast<DICompositeType>(Ty))
927 visitCompositeType(CTy, TypeId);
928 else if (
const auto *DTy = dyn_cast<DIDerivedType>(Ty))
929 visitDerivedType(DTy, TypeId, CheckPointer, SeenPointer);
934void BTFDebug::visitTypeEntry(
const DIType *Ty) {
936 visitTypeEntry(Ty, TypeId,
false,
false);
939void BTFDebug::visitMapDefType(
const DIType *Ty,
uint32_t &TypeId) {
940 if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {
941 TypeId = DIToIdMap[Ty];
946 const DIType *OrigTy = Ty;
947 while (
auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
949 if (
Tag != dwarf::DW_TAG_typedef &&
Tag != dwarf::DW_TAG_const_type &&
950 Tag != dwarf::DW_TAG_volatile_type &&
951 Tag != dwarf::DW_TAG_restrict_type)
953 Ty = DTy->getBaseType();
956 const auto *CTy = dyn_cast<DICompositeType>(Ty);
966 for (
const auto *Element : Elements) {
967 const auto *MemberType = cast<DIDerivedType>(Element);
968 visitTypeEntry(MemberType->getBaseType());
972 visitTypeEntry(OrigTy, TypeId,
false,
false);
976std::string BTFDebug::populateFileContent(
const DIFile *File) {
977 std::string FileName;
979 if (!
File->getFilename().starts_with(
"/") &&
File->getDirectory().size())
980 FileName =
File->getDirectory().str() +
"/" +
File->getFilename().str();
982 FileName = std::string(
File->getFilename());
988 std::vector<std::string>
Content;
992 std::unique_ptr<MemoryBuffer> Buf;
996 else if (
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
998 Buf = std::move(*BufOrErr);
1001 Content.push_back(std::string(*
I));
1003 FileContent[FileName] =
Content;
1007void BTFDebug::constructLineInfo(
MCSymbol *Label,
const DIFile *File,
1009 std::string FileName = populateFileContent(File);
1015 if (Line < FileContent[FileName].
size())
1021 LineInfoTable[SecNameOff].push_back(LineInfo);
1024void BTFDebug::emitCommonHeader() {
1031void BTFDebug::emitBTFSection() {
1033 if (!TypeEntries.size() && StringTable.
getSize() == 1)
1039 OS.switchSection(Sec);
1046 for (
const auto &TypeEntry : TypeEntries)
1048 StrLen = StringTable.
getSize();
1051 OS.emitInt32(TypeLen);
1052 OS.emitInt32(TypeLen);
1053 OS.emitInt32(StrLen);
1056 for (
const auto &TypeEntry : TypeEntries)
1061 for (
const auto &S : StringTable.
getTable()) {
1062 OS.AddComment(
"string offset=" + std::to_string(StringOffset));
1065 StringOffset += S.size() + 1;
1069void BTFDebug::emitBTFExtSection() {
1072 if (!FuncInfoTable.size() && !LineInfoTable.size() &&
1073 !FieldRelocTable.size())
1079 OS.switchSection(Sec);
1089 for (
const auto &FuncSec : FuncInfoTable) {
1093 for (
const auto &LineSec : LineInfoTable) {
1097 for (
const auto &FieldRelocSec : FieldRelocTable) {
1106 OS.emitInt32(FuncLen);
1107 OS.emitInt32(FuncLen);
1108 OS.emitInt32(LineLen);
1109 OS.emitInt32(FuncLen + LineLen);
1110 OS.emitInt32(FieldRelocLen);
1113 OS.AddComment(
"FuncInfo");
1115 for (
const auto &FuncSec : FuncInfoTable) {
1116 OS.AddComment(
"FuncInfo section string offset=" +
1117 std::to_string(FuncSec.first));
1118 OS.emitInt32(FuncSec.first);
1119 OS.emitInt32(FuncSec.second.size());
1120 for (
const auto &FuncInfo : FuncSec.second) {
1122 OS.emitInt32(FuncInfo.TypeId);
1127 OS.AddComment(
"LineInfo");
1129 for (
const auto &LineSec : LineInfoTable) {
1130 OS.AddComment(
"LineInfo section string offset=" +
1131 std::to_string(LineSec.first));
1132 OS.emitInt32(LineSec.first);
1133 OS.emitInt32(LineSec.second.size());
1134 for (
const auto &LineInfo : LineSec.second) {
1138 OS.AddComment(
"Line " + std::to_string(LineInfo.
LineNum) +
" Col " +
1145 if (FieldRelocLen) {
1146 OS.AddComment(
"FieldReloc");
1148 for (
const auto &FieldRelocSec : FieldRelocTable) {
1149 OS.AddComment(
"Field reloc section string offset=" +
1150 std::to_string(FieldRelocSec.first));
1151 OS.emitInt32(FieldRelocSec.first);
1152 OS.emitInt32(FieldRelocSec.second.size());
1153 for (
const auto &FieldRelocInfo : FieldRelocSec.second) {
1155 OS.emitInt32(FieldRelocInfo.TypeID);
1156 OS.emitInt32(FieldRelocInfo.OffsetNameOff);
1157 OS.emitInt32(FieldRelocInfo.RelocKind);
1165 auto *Unit = SP->getUnit();
1168 SkipInstruction =
true;
1171 SkipInstruction =
false;
1192 if (MapDefNotCollected) {
1193 processGlobals(
true);
1194 MapDefNotCollected =
false;
1200 std::unordered_map<uint32_t, StringRef> FuncArgNames;
1201 for (
const DINode *DN : SP->getRetainedNodes()) {
1202 if (
const auto *DV = dyn_cast<DILocalVariable>(DN)) {
1206 visitTypeEntry(DV->getType());
1207 FuncArgNames[Arg] = DV->getName();
1214 visitSubroutineType(SP->getType(),
true, FuncArgNames, ProtoTypeId);
1218 uint32_t FuncTypeId = processDISubprogram(SP, ProtoTypeId, Scope);
1220 for (
const auto &TypeEntry : TypeEntries)
1221 TypeEntry->completeType(*
this);
1226 FuncInfo.
Label = FuncLabel;
1227 FuncInfo.
TypeId = FuncTypeId;
1230 const MCSectionELF *SectionELF = dyn_cast<MCSectionELF>(&Section);
1231 assert(SectionELF &&
"Null section for Function Label");
1236 FuncInfoTable[SecNameOff].push_back(FuncInfo);
1240 SkipInstruction =
false;
1241 LineInfoGenerated =
false;
1247unsigned BTFDebug::populateType(
const DIType *Ty) {
1249 visitTypeEntry(Ty, Id,
false,
false);
1250 for (
const auto &TypeEntry : TypeEntries)
1251 TypeEntry->completeType(*
this);
1256void BTFDebug::generatePatchImmReloc(
const MCSymbol *ORSym,
uint32_t RootId,
1259 FieldReloc.
Label = ORSym;
1260 FieldReloc.
TypeID = RootId;
1266 size_t SecondColon = AccessPattern.
find_first_of(
':', FirstColon + 1);
1269 SecondColon - FirstColon);
1271 FirstDollar - SecondColon);
1274 FieldReloc.
RelocKind = std::stoull(std::string(RelocKindStr));
1275 PatchImms[GVar] = std::make_pair(std::stoll(std::string(PatchImmStr)),
1280 FieldReloc.
RelocKind = std::stoull(std::string(RelocStr));
1281 PatchImms[GVar] = std::make_pair(RootId, FieldReloc.
RelocKind);
1283 FieldRelocTable[SecNameOff].push_back(FieldReloc);
1290 auto *GVar = dyn_cast<GlobalVariable>(GVal);
1293 processFuncPrototypes(dyn_cast<Function>(GVal));
1301 MCSymbol *ORSym =
OS.getContext().createTempSymbol();
1302 OS.emitLabel(ORSym);
1305 uint32_t RootId = populateType(dyn_cast<DIType>(MDN));
1306 generatePatchImmReloc(ORSym, RootId, GVar,
1314 if (SkipInstruction ||
MI->isMetaInstruction() ||
1318 if (
MI->isInlineAsm()) {
1320 unsigned NumDefs = 0;
1335 if (
MI->getOpcode() == BPF::LD_imm64) {
1350 processGlobalValue(
MI->getOperand(1));
1351 }
else if (
MI->getOpcode() == BPF::CORE_LD64 ||
1352 MI->getOpcode() == BPF::CORE_LD32 ||
1353 MI->getOpcode() == BPF::CORE_ST ||
1354 MI->getOpcode() == BPF::CORE_SHIFT) {
1356 processGlobalValue(
MI->getOperand(3));
1357 }
else if (
MI->getOpcode() == BPF::JAL) {
1361 processFuncPrototypes(dyn_cast<Function>(MO.
getGlobal()));
1374 if (LineInfoGenerated ==
false) {
1375 auto *S =
MI->getMF()->getFunction().getSubprogram();
1379 constructLineInfo(FuncLabel, S->getFile(), S->getLine(), 0);
1380 LineInfoGenerated =
true;
1387 MCSymbol *LineSym =
OS.getContext().createTempSymbol();
1388 OS.emitLabel(LineSym);
1391 constructLineInfo(LineSym,
DL->getFile(),
DL.getLine(),
DL.getCol());
1393 LineInfoGenerated =
true;
1397void BTFDebug::processGlobals(
bool ProcessingMapDef) {
1403 std::optional<SectionKind> GVKind;
1405 if (!
Global.isDeclarationForLinker())
1408 if (
Global.isDeclarationForLinker())
1409 SecName =
Global.hasSection() ?
Global.getSection() :
"";
1410 else if (GVKind->isCommon())
1418 if (ProcessingMapDef != SecName.
starts_with(
".maps"))
1424 if (SecName ==
".rodata" &&
Global.hasPrivateLinkage() &&
1425 DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {
1427 if (!GVKind->isMergeableCString() && !GVKind->isMergeableConst()) {
1428 DataSecEntries[std::string(SecName)] =
1429 std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1434 Global.getDebugInfo(GVs);
1437 if (GVs.
size() == 0)
1442 for (
auto *GVE : GVs) {
1445 visitMapDefType(
DIGlobal->getType(), GVTypeId);
1447 visitTypeEntry(
DIGlobal->getType(), GVTypeId,
false,
false);
1469 }
else if (
Global.hasInitializer()) {
1476 std::make_unique<BTFKindVar>(
Global.getName(), GVTypeId, GVarInfo);
1477 uint32_t VarId = addType(std::move(VarEntry));
1479 processDeclAnnotations(
DIGlobal->getAnnotations(), VarId, -1);
1482 if (SecName.
empty())
1486 if (DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {
1487 DataSecEntries[std::string(SecName)] =
1488 std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1495 DataSecEntries[std::string(SecName)]->addDataSecEntry(VarId,
1502 if (
MI->getOpcode() == BPF::LD_imm64) {
1506 auto *GVar = dyn_cast<GlobalVariable>(GVal);
1513 Imm = PatchImms[GVar].first;
1514 Reloc = PatchImms[GVar].second;
1529 }
else if (
MI->getOpcode() == BPF::CORE_LD64 ||
1530 MI->getOpcode() == BPF::CORE_LD32 ||
1531 MI->getOpcode() == BPF::CORE_ST ||
1532 MI->getOpcode() == BPF::CORE_SHIFT) {
1536 auto *GVar = dyn_cast<GlobalVariable>(GVal);
1538 uint32_t Imm = PatchImms[GVar].first;
1540 if (
MI->getOperand(0).isImm())
1553void BTFDebug::processFuncPrototypes(
const Function *
F) {
1558 if (!SP || SP->isDefinition())
1562 if (!ProtoFunctions.insert(
F).second)
1566 const std::unordered_map<uint32_t, StringRef> FuncArgNames;
1567 visitSubroutineType(SP->getType(),
false, FuncArgNames, ProtoTypeId);
1570 if (
F->hasSection()) {
1573 if (DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {
1574 DataSecEntries[std::string(SecName)] =
1575 std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1579 DataSecEntries[std::string(SecName)]->addDataSecEntry(
FuncId,
1586 if (MapDefNotCollected) {
1587 processGlobals(
true);
1588 MapDefNotCollected =
false;
1592 processGlobals(
false);
1594 for (
auto &DataSec : DataSecEntries)
1595 addType(std::move(DataSec.second));
1598 for (
auto &
Fixup : FixupDerivedTypes) {
1601 bool IsUnion = CTy->
getTag() == dwarf::DW_TAG_union_type;
1612 if (StructTypeId == 0) {
1613 auto FwdTypeEntry = std::make_unique<BTFTypeFwd>(TypeName, IsUnion);
1614 StructTypeId = addType(std::move(FwdTypeEntry));
1617 for (
auto &TypeInfo :
Fixup.second) {
1621 int TmpTypeId = genBTFTypeTags(DTy, StructTypeId);
1630 for (
const auto &TypeEntry : TypeEntries)
1631 TypeEntry->completeType(*
this);
1635 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
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 ...
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.
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
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.
@ 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.
StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry
Linkage
Describes symbol linkage. This can be used to resolve definition clashes.
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.