32#define HANDLE_BTF_KIND(ID, NAME) "BTF_KIND_" #NAME,
48 : DTy(DTy), NeedsFixup(NeedsFixup),
Name(DTy->
getName()) {
50 case dwarf::DW_TAG_pointer_type:
51 Kind = BTF::BTF_KIND_PTR;
53 case dwarf::DW_TAG_const_type:
54 Kind = BTF::BTF_KIND_CONST;
56 case dwarf::DW_TAG_volatile_type:
57 Kind = BTF::BTF_KIND_VOLATILE;
59 case dwarf::DW_TAG_typedef:
60 Kind = BTF::BTF_KIND_TYPEDEF;
62 case dwarf::DW_TAG_restrict_type:
63 Kind = BTF::BTF_KIND_RESTRICT;
75 Kind = BTF::BTF_KIND_PTR;
87 if (NeedsFixup || !DTy)
91 const DIType *ResolvedType = DTy->getBaseType();
93 assert((
Kind == BTF::BTF_KIND_PTR ||
Kind == BTF::BTF_KIND_CONST ||
94 Kind == BTF::BTF_KIND_VOLATILE) &&
95 "Invalid null basetype");
110 Kind = BTF::BTF_KIND_FWD;
131 case dwarf::DW_ATE_boolean:
134 case dwarf::DW_ATE_signed:
135 case dwarf::DW_ATE_signed_char:
138 case dwarf::DW_ATE_unsigned:
139 case dwarf::DW_ATE_unsigned_char:
146 Kind = BTF::BTF_KIND_INT;
149 IntVal = (BTFEncoding << 24) | OffsetInBits << 16 | SizeInBits;
163 OS.emitInt32(IntVal);
167 bool IsSigned) : ETy(ETy) {
168 Kind = BTF::BTF_KIND_ENUM;
181 for (
const auto Element : Elements) {
182 const auto *Enum = cast<DIEnumerator>(Element);
188 if (Enum->isUnsigned())
189 Value =
static_cast<uint32_t>(Enum->getValue().getZExtValue());
191 Value =
static_cast<uint32_t>(Enum->getValue().getSExtValue());
193 EnumValues.push_back(BTFEnum);
199 for (
const auto &Enum : EnumValues) {
200 OS.emitInt32(Enum.NameOff);
201 OS.emitInt32(Enum.Val);
206 bool IsSigned) : ETy(ETy) {
207 Kind = BTF::BTF_KIND_ENUM64;
220 for (
const auto Element : Elements) {
221 const auto *Enum = cast<DIEnumerator>(Element);
226 if (Enum->isUnsigned())
227 Value =
static_cast<uint64_t>(Enum->getValue().getZExtValue());
229 Value =
static_cast<uint64_t>(Enum->getValue().getSExtValue());
232 EnumValues.push_back(BTFEnum);
238 for (
const auto &Enum : EnumValues) {
239 OS.emitInt32(Enum.NameOff);
241 OS.emitInt32(Enum.Val_Lo32);
243 OS.emitInt32(Enum.Val_Hi32);
248 Kind = BTF::BTF_KIND_ARRAY;
254 ArrayInfo.
Nelems = NumElems;
280 : STy(STy), HasBitField(HasBitField) {
281 Kind = IsStruct ? BTF::BTF_KIND_STRUCT : BTF::BTF_KIND_UNION;
295 for (
const auto *Element : Elements) {
297 const auto *DDTy = cast<DIDerivedType>(Element);
301 uint8_t BitFieldSize = DDTy->isBitField() ? DDTy->getSizeInBits() : 0;
302 BTFMember.
Offset = BitFieldSize << 24 | DDTy->getOffsetInBits();
304 BTFMember.
Offset = DDTy->getOffsetInBits();
306 const auto *
BaseTy = DDTy->getBaseType();
308 Members.push_back(BTFMember);
314 for (
const auto &Member : Members) {
315 OS.emitInt32(Member.NameOff);
316 OS.emitInt32(Member.Type);
318 OS.emitInt32(Member.Offset);
331 const std::unordered_map<uint32_t, StringRef> &FuncArgNames)
332 : STy(STy), FuncArgNames(FuncArgNames) {
333 Kind = BTF::BTF_KIND_FUNC_PROTO;
343 auto RetType = Elements[0];
349 for (
unsigned I = 1,
N = Elements.size();
I <
N; ++
I) {
351 auto Element = Elements[
I];
353 Param.NameOff = BDebug.
addString(FuncArgNames[
I]);
359 Parameters.push_back(Param);
365 for (
const auto &Param : Parameters) {
366 OS.emitInt32(Param.NameOff);
367 OS.emitInt32(Param.Type);
374 Kind = BTF::BTF_KIND_FUNC;
391 Kind = BTF::BTF_KIND_VAR;
407 : Asm(AsmPrt),
Name(SecName) {
408 Kind = BTF::BTF_KIND_DATASEC;
421 for (
const auto &V : Vars) {
422 OS.emitInt32(std::get<0>(V));
424 OS.emitInt32(std::get<2>(V));
430 Kind = BTF::BTF_KIND_FLOAT;
446 Kind = BTF::BTF_KIND_DECL_TAG;
466 : DTy(nullptr),
Tag(
Tag) {
467 Kind = BTF::BTF_KIND_TYPE_TAG;
474 Kind = BTF::BTF_KIND_TYPE_TAG;
484 const DIType *ResolvedType = DTy->getBaseType();
494 for (
auto &OffsetM : OffsetToIdMap) {
495 if (Table[OffsetM.second] == S)
496 return OffsetM.first;
500 OffsetToIdMap[
Offset] = Table.size();
501 Table.push_back(std::string(S));
508 LineInfoGenerated(
false), SecNameOff(0), ArrayIndexTypeId(0),
509 MapDefNotCollected(
true) {
513uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry,
515 TypeEntry->setId(TypeEntries.size() + 1);
518 TypeEntries.push_back(std::move(TypeEntry));
522uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry) {
523 TypeEntry->setId(TypeEntries.size() + 1);
525 TypeEntries.push_back(std::move(TypeEntry));
532 std::unique_ptr<BTFTypeBase> TypeEntry;
534 case dwarf::DW_ATE_boolean:
535 case dwarf::DW_ATE_signed:
536 case dwarf::DW_ATE_signed_char:
537 case dwarf::DW_ATE_unsigned:
538 case dwarf::DW_ATE_unsigned_char:
541 TypeEntry = std::make_unique<BTFTypeInt>(
544 case dwarf::DW_ATE_float:
552 TypeId = addType(std::move(TypeEntry), BTy);
556void BTFDebug::visitSubroutineType(
558 const std::unordered_map<uint32_t, StringRef> &FuncArgNames,
569 auto TypeEntry = std::make_unique<BTFTypeFuncProto>(STy, VLen, FuncArgNames);
571 TypeId = addType(std::move(TypeEntry));
573 TypeId = addType(std::move(TypeEntry), STy);
576 for (
const auto Element : Elements) {
577 visitTypeEntry(Element);
581void BTFDebug::processDeclAnnotations(DINodeArray
Annotations,
588 const MDNode *MD = cast<MDNode>(Annotation);
590 if (!
Name->getString().equals(
"btf_decl_tag"))
594 auto TypeEntry = std::make_unique<BTFTypeDeclTag>(BaseTypeId, ComponentIdx,
596 addType(std::move(TypeEntry));
601 uint32_t ProtoTypeId, uint8_t Scope) {
603 std::make_unique<BTFTypeFunc>(SP->
getName(), ProtoTypeId, Scope);
607 for (
const DINode *DN : SP->getRetainedNodes()) {
608 if (
const auto *DV = dyn_cast<DILocalVariable>(DN)) {
611 processDeclAnnotations(DV->getAnnotations(),
FuncId,
Arg - 1);
614 processDeclAnnotations(SP->getAnnotations(),
FuncId, -1);
620int BTFDebug::genBTFTypeTags(
const DIDerivedType *DTy,
int BaseTypeId) {
622 DINodeArray Annots = DTy->getAnnotations();
629 if (!
Name->getString().equals(
"btf_type_tag"))
635 if (MDStrs.
size() == 0)
643 std::unique_ptr<BTFTypeTypeTag> TypeEntry;
646 std::make_unique<BTFTypeTypeTag>(BaseTypeId, MDStrs[0]->getString());
648 TypeEntry = std::make_unique<BTFTypeTypeTag>(DTy, MDStrs[0]->getString());
649 TmpTypeId = addType(std::move(TypeEntry));
651 for (
unsigned I = 1;
I < MDStrs.
size();
I++) {
653 TypeEntry = std::make_unique<BTFTypeTypeTag>(TmpTypeId,
Value->getString());
654 TmpTypeId = addType(std::move(TypeEntry));
660void BTFDebug::visitStructType(
const DICompositeType *CTy,
bool IsStruct,
668 bool HasBitField =
false;
669 for (
const auto *Element : Elements) {
670 auto E = cast<DIDerivedType>(Element);
671 if (
E->isBitField()) {
678 std::make_unique<BTFTypeStruct>(CTy, IsStruct, HasBitField, VLen);
679 StructTypes.push_back(TypeEntry.get());
680 TypeId = addType(std::move(TypeEntry), CTy);
687 for (
const auto *Element : Elements) {
688 const auto Elem = cast<DIDerivedType>(Element);
689 visitTypeEntry(Elem);
690 processDeclAnnotations(Elem->getAnnotations(), TypeId, FieldNo);
699 visitTypeEntry(ElemType, ElemTypeId,
false,
false);
704 if (
auto *Element = dyn_cast_or_null<DINode>(Elements[
I]))
705 if (Element->getTag() == dwarf::DW_TAG_subrange_type) {
706 const DISubrange *SR = cast<DISubrange>(Element);
713 std::make_unique<BTFTypeArray>(ElemTypeId,
714 Count >= 0 ? Count : 0);
716 ElemTypeId = addType(std::move(TypeEntry), CTy);
718 ElemTypeId = addType(std::move(TypeEntry));
727 if (!ArrayIndexTypeId) {
728 auto TypeEntry = std::make_unique<BTFTypeInt>(dwarf::DW_ATE_unsigned, 32,
729 0,
"__ARRAY_SIZE_TYPE__");
730 ArrayIndexTypeId = addType(std::move(TypeEntry));
740 bool IsSigned =
false;
741 unsigned NumBits = 32;
745 const auto *BTy = cast<DIBasicType>(CTy->
getBaseType());
746 IsSigned = BTy->
getEncoding() == dwarf::DW_ATE_signed ||
752 auto TypeEntry = std::make_unique<BTFTypeEnum>(CTy, VLen, IsSigned);
753 TypeId = addType(std::move(TypeEntry), CTy);
756 auto TypeEntry = std::make_unique<BTFTypeEnum64>(CTy, VLen, IsSigned);
757 TypeId = addType(std::move(TypeEntry), CTy);
763void BTFDebug::visitFwdDeclType(
const DICompositeType *CTy,
bool IsUnion,
765 auto TypeEntry = std::make_unique<BTFTypeFwd>(CTy->
getName(), IsUnion);
766 TypeId = addType(std::move(TypeEntry), CTy);
773 if (
Tag == dwarf::DW_TAG_structure_type ||
Tag == dwarf::DW_TAG_union_type) {
776 visitFwdDeclType(CTy,
Tag == dwarf::DW_TAG_union_type, TypeId);
778 visitStructType(CTy,
Tag == dwarf::DW_TAG_structure_type, TypeId);
779 }
else if (
Tag == dwarf::DW_TAG_array_type)
780 visitArrayType(CTy, TypeId);
781 else if (
Tag == dwarf::DW_TAG_enumeration_type)
782 visitEnumType(CTy, TypeId);
785bool BTFDebug::IsForwardDeclCandidate(
const DIType *
Base) {
786 if (
const auto *CTy = dyn_cast<DICompositeType>(
Base)) {
787 auto CTag = CTy->
getTag();
788 if ((CTag == dwarf::DW_TAG_structure_type ||
789 CTag == dwarf::DW_TAG_union_type) &&
798 bool CheckPointer,
bool SeenPointer) {
803 if (CheckPointer && !SeenPointer) {
804 SeenPointer =
Tag == dwarf::DW_TAG_pointer_type;
807 if (CheckPointer && SeenPointer) {
810 if (IsForwardDeclCandidate(
Base)) {
814 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
true);
815 auto &
Fixup = FixupDerivedTypes[cast<DICompositeType>(
Base)];
816 Fixup.push_back(std::make_pair(DTy, TypeEntry.get()));
817 TypeId = addType(std::move(TypeEntry), DTy);
823 if (
Tag == dwarf::DW_TAG_pointer_type) {
824 int TmpTypeId = genBTFTypeTags(DTy, -1);
825 if (TmpTypeId >= 0) {
827 std::make_unique<BTFTypeDerived>(TmpTypeId,
Tag, DTy->
getName());
828 TypeId = addType(std::move(TypeDEntry), DTy);
830 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
false);
831 TypeId = addType(std::move(TypeEntry), DTy);
833 }
else if (
Tag == dwarf::DW_TAG_typedef ||
Tag == dwarf::DW_TAG_const_type ||
834 Tag == dwarf::DW_TAG_volatile_type ||
835 Tag == dwarf::DW_TAG_restrict_type) {
836 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
false);
837 TypeId = addType(std::move(TypeEntry), DTy);
838 if (
Tag == dwarf::DW_TAG_typedef)
839 processDeclAnnotations(DTy->getAnnotations(), TypeId, -1);
840 }
else if (
Tag != dwarf::DW_TAG_member) {
847 if (
Tag == dwarf::DW_TAG_member)
848 visitTypeEntry(DTy->getBaseType(), TempTypeId,
true,
false);
850 visitTypeEntry(DTy->getBaseType(), TempTypeId, CheckPointer, SeenPointer);
861 bool CheckPointer,
bool SeenPointer) {
862 if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {
863 TypeId = DIToIdMap[Ty];
894 if (Ty && (!CheckPointer || !SeenPointer)) {
895 if (
const auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
901 if (DIToIdMap.find(
BaseTy) != DIToIdMap.end()) {
902 DTy = dyn_cast<DIDerivedType>(
BaseTy);
904 if (CheckPointer && DTy->
getTag() == dwarf::DW_TAG_pointer_type) {
906 if (IsForwardDeclCandidate(
BaseTy))
910 visitTypeEntry(
BaseTy, TmpTypeId, CheckPointer, SeenPointer);
920 if (
const auto *BTy = dyn_cast<DIBasicType>(Ty))
921 visitBasicType(BTy, TypeId);
922 else if (
const auto *STy = dyn_cast<DISubroutineType>(Ty))
923 visitSubroutineType(STy,
false, std::unordered_map<uint32_t, StringRef>(),
925 else if (
const auto *CTy = dyn_cast<DICompositeType>(Ty))
926 visitCompositeType(CTy, TypeId);
927 else if (
const auto *DTy = dyn_cast<DIDerivedType>(Ty))
928 visitDerivedType(DTy, TypeId, CheckPointer, SeenPointer);
933void BTFDebug::visitTypeEntry(
const DIType *Ty) {
935 visitTypeEntry(Ty, TypeId,
false,
false);
938void BTFDebug::visitMapDefType(
const DIType *Ty,
uint32_t &TypeId) {
939 if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {
940 TypeId = DIToIdMap[Ty];
945 const DIType *OrigTy = Ty;
946 while (
auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
948 if (
Tag != dwarf::DW_TAG_typedef &&
Tag != dwarf::DW_TAG_const_type &&
949 Tag != dwarf::DW_TAG_volatile_type &&
950 Tag != dwarf::DW_TAG_restrict_type)
952 Ty = DTy->getBaseType();
955 const auto *CTy = dyn_cast<DICompositeType>(Ty);
965 for (
const auto *Element : Elements) {
966 const auto *MemberType = cast<DIDerivedType>(Element);
967 visitTypeEntry(MemberType->getBaseType());
971 visitTypeEntry(OrigTy, TypeId,
false,
false);
975std::string BTFDebug::populateFileContent(
const DISubprogram *SP) {
977 std::string FileName;
979 if (!
File->getFilename().startswith(
"/") &&
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;
1009 std::string FileName = populateFileContent(SP);
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)
1047 TypeLen += TypeEntry->getSize();
1048 StrLen = StringTable.
getSize();
1051 OS.emitInt32(TypeLen);
1052 OS.emitInt32(TypeLen);
1053 OS.emitInt32(StrLen);
1056 for (
const auto &TypeEntry : TypeEntries)
1057 TypeEntry->emitType(
OS);
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) {
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);
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;
1321 for (;
MI->getOperand(NumDefs).
isReg() &&
MI->getOperand(NumDefs).isDef();
1326 const char *AsmStr =
MI->getOperand(NumDefs).getSymbolName();
1331 if (
MI->getOpcode() == BPF::LD_imm64) {
1346 processGlobalValue(
MI->getOperand(1));
1347 }
else if (
MI->getOpcode() == BPF::CORE_MEM ||
1348 MI->getOpcode() == BPF::CORE_ALU32_MEM ||
1349 MI->getOpcode() == BPF::CORE_SHIFT) {
1351 processGlobalValue(
MI->getOperand(3));
1352 }
else if (
MI->getOpcode() == BPF::JAL) {
1356 processFuncPrototypes(dyn_cast<Function>(MO.
getGlobal()));
1369 if (LineInfoGenerated ==
false) {
1370 auto *S =
MI->getMF()->getFunction().getSubprogram();
1372 constructLineInfo(S, FuncLabel, S->getLine(), 0);
1373 LineInfoGenerated =
true;
1380 MCSymbol *LineSym =
OS.getContext().createTempSymbol();
1381 OS.emitLabel(LineSym);
1384 auto SP =
DL->getScope()->getSubprogram();
1385 constructLineInfo(SP, LineSym,
DL.getLine(),
DL.getCol());
1387 LineInfoGenerated =
true;
1391void BTFDebug::processGlobals(
bool ProcessingMapDef) {
1397 std::optional<SectionKind> GVKind;
1399 if (!
Global.isDeclarationForLinker())
1402 if (
Global.isDeclarationForLinker())
1403 SecName =
Global.hasSection() ?
Global.getSection() :
"";
1404 else if (GVKind->isCommon())
1412 if (ProcessingMapDef != SecName.
startswith(
".maps"))
1418 if (SecName ==
".rodata" &&
Global.hasPrivateLinkage() &&
1419 DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {
1421 if (!GVKind->isMergeableCString() && !GVKind->isMergeableConst()) {
1422 DataSecEntries[std::string(SecName)] =
1423 std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1428 Global.getDebugInfo(GVs);
1431 if (GVs.
size() == 0)
1436 for (
auto *GVE : GVs) {
1439 visitMapDefType(
DIGlobal->getType(), GVTypeId);
1441 visitTypeEntry(
DIGlobal->getType(), GVTypeId,
false,
false);
1463 }
else if (
Global.hasInitializer()) {
1470 std::make_unique<BTFKindVar>(
Global.getName(), GVTypeId, GVarInfo);
1471 uint32_t VarId = addType(std::move(VarEntry));
1473 processDeclAnnotations(
DIGlobal->getAnnotations(), VarId, -1);
1476 if (SecName.
empty())
1480 if (DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {
1481 DataSecEntries[std::string(SecName)] =
1482 std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1489 DataSecEntries[std::string(SecName)]->addDataSecEntry(VarId,
1496 if (
MI->getOpcode() == BPF::LD_imm64) {
1500 auto *GVar = dyn_cast<GlobalVariable>(GVal);
1507 Imm = PatchImms[GVar].first;
1508 Reloc = PatchImms[GVar].second;
1525 }
else if (
MI->getOpcode() == BPF::CORE_MEM ||
1526 MI->getOpcode() == BPF::CORE_ALU32_MEM ||
1527 MI->getOpcode() == BPF::CORE_SHIFT) {
1531 auto *GVar = dyn_cast<GlobalVariable>(GVal);
1533 uint32_t Imm = PatchImms[GVar].first;
1535 if (
MI->getOperand(0).isImm())
1548void BTFDebug::processFuncPrototypes(
const Function *
F) {
1553 if (!SP || SP->isDefinition())
1557 if (!ProtoFunctions.insert(
F).second)
1561 const std::unordered_map<uint32_t, StringRef> FuncArgNames;
1562 visitSubroutineType(SP->getType(),
false, FuncArgNames, ProtoTypeId);
1565 if (
F->hasSection()) {
1568 if (DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) {
1569 DataSecEntries[std::string(SecName)] =
1570 std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1574 DataSecEntries[std::string(SecName)]->addDataSecEntry(
FuncId,
1581 if (MapDefNotCollected) {
1582 processGlobals(
true);
1583 MapDefNotCollected =
false;
1587 processGlobals(
false);
1589 for (
auto &DataSec : DataSecEntries)
1590 addType(std::move(DataSec.second));
1593 for (
auto &
Fixup : FixupDerivedTypes) {
1596 bool IsUnion = CTy->
getTag() == dwarf::DW_TAG_union_type;
1607 if (StructTypeId == 0) {
1608 auto FwdTypeEntry = std::make_unique<BTFTypeFwd>(TypeName, IsUnion);
1609 StructTypeId = addType(std::move(FwdTypeEntry));
1612 for (
auto &TypeInfo :
Fixup.second) {
1616 int TmpTypeId = genBTFTypeTags(DTy, StructTypeId);
1625 for (
const auto &TypeEntry : TypeEntries)
1626 TypeEntry->completeType(*
this);
1630 emitBTFExtSection();
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
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
typename CallsiteContextGraph< DerivedCCG, FuncTy, CallTy >::FuncInfo FuncInfo
static bool isReg(const MCInst &MI, unsigned OpNo)
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
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 isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
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).
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
bool startswith(StringRef Prefix) const
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.
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 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.