37#define HANDLE_BTF_KIND(ID, NAME) "BTF_KIND_" #NAME,
38#include "llvm/DebugInfo/BTF/BTF.def"
45 if (DerivedTy && DerivedTy->getTag() == dwarf::DW_TAG_atomic_type)
46 return DerivedTy->getBaseType();
62 : DTy(DTy), NeedsFixup(NeedsFixup), Name(DTy->
getName()) {
64 case dwarf::DW_TAG_pointer_type:
65 Kind = BTF::BTF_KIND_PTR;
67 case dwarf::DW_TAG_const_type:
68 Kind = BTF::BTF_KIND_CONST;
70 case dwarf::DW_TAG_volatile_type:
71 Kind = BTF::BTF_KIND_VOLATILE;
73 case dwarf::DW_TAG_typedef:
74 Kind = BTF::BTF_KIND_TYPEDEF;
76 case dwarf::DW_TAG_restrict_type:
77 Kind = BTF::BTF_KIND_RESTRICT;
88 : DTy(nullptr), NeedsFixup(
false), Name(Name) {
89 Kind = BTF::BTF_KIND_PTR;
100 case BTF::BTF_KIND_PTR:
101 case BTF::BTF_KIND_CONST:
102 case BTF::BTF_KIND_VOLATILE:
103 case BTF::BTF_KIND_RESTRICT:
118 if (NeedsFixup || !DTy)
124 assert((
Kind == BTF::BTF_KIND_PTR ||
Kind == BTF::BTF_KIND_CONST ||
125 Kind == BTF::BTF_KIND_VOLATILE) &&
126 "Invalid null basetype");
141 Kind = BTF::BTF_KIND_FWD;
162 case dwarf::DW_ATE_boolean:
165 case dwarf::DW_ATE_signed:
166 case dwarf::DW_ATE_signed_char:
169 case dwarf::DW_ATE_unsigned:
170 case dwarf::DW_ATE_unsigned_char:
171 case dwarf::DW_ATE_UTF:
178 Kind = BTF::BTF_KIND_INT;
181 IntVal = (BTFEncoding << 24) | OffsetInBits << 16 | SizeInBits;
199 bool IsSigned) : ETy(ETy) {
200 Kind = BTF::BTF_KIND_ENUM;
212 DINodeArray Elements = ETy->getElements();
213 for (
const auto Element : Elements) {
220 if (Enum->isUnsigned())
221 Value =
static_cast<uint32_t>(Enum->getValue().getZExtValue());
223 Value =
static_cast<uint32_t>(Enum->getValue().getSExtValue());
225 EnumValues.push_back(BTFEnum);
231 for (
const auto &Enum : EnumValues) {
238 bool IsSigned) : ETy(ETy) {
239 Kind = BTF::BTF_KIND_ENUM64;
251 DINodeArray Elements = ETy->getElements();
252 for (
const auto Element : Elements) {
258 if (Enum->isUnsigned())
259 Value = Enum->getValue().getZExtValue();
261 Value =
static_cast<uint64_t>(Enum->getValue().getSExtValue());
264 EnumValues.push_back(BTFEnum);
270 for (
const auto &Enum : EnumValues) {
280 Kind = BTF::BTF_KIND_ARRAY;
285 ArrayInfo.ElemType = ElemTypeId;
286 ArrayInfo.Nelems = NumElems;
312 : STy(STy), HasBitField(HasBitField) {
313 Kind = IsStruct ? BTF::BTF_KIND_STRUCT : BTF::BTF_KIND_UNION;
315 BTFType.Info = (HasBitField << 31) | (
Kind << 24) | Vlen;
325 if (STy->getTag() == dwarf::DW_TAG_variant_part) {
334 const auto *DTy = STy->getDiscriminator();
338 Discriminator.NameOff = BDebug.
addString(DTy->getName());
339 Discriminator.Offset = DTy->getOffsetInBits();
340 const auto *BaseTy = DTy->getBaseType();
341 Discriminator.Type = BDebug.
getTypeId(BaseTy);
343 Members.push_back(Discriminator);
348 const DINodeArray Elements = STy->getElements();
349 for (
const auto *Element : Elements) {
352 switch (Element->getTag()) {
353 case dwarf::DW_TAG_member: {
358 uint8_t BitFieldSize = DDTy->isBitField() ? DDTy->getSizeInBits() : 0;
359 BTFMember.
Offset = BitFieldSize << 24 | DDTy->getOffsetInBits();
361 BTFMember.
Offset = DDTy->getOffsetInBits();
367 case dwarf::DW_TAG_variant_part: {
371 BTFMember.
Offset = DCTy->getOffsetInBits();
378 Members.push_back(BTFMember);
384 for (
const auto &Member : Members) {
401 const std::unordered_map<uint32_t, StringRef> &FuncArgNames)
402 : STy(STy), FuncArgNames(FuncArgNames) {
403 Kind = BTF::BTF_KIND_FUNC_PROTO;
412 DITypeArray Elements = STy->getTypeArray();
419 for (
unsigned I = 1,
N = Elements.size();
I <
N; ++
I) {
423 Param.NameOff = BDebug.
addString(FuncArgNames[
I]);
429 Parameters.push_back(Param);
435 for (
const auto &Param : Parameters) {
444 Kind = BTF::BTF_KIND_FUNC;
461 Kind = BTF::BTF_KIND_VAR;
477 : Asm(AsmPrt), Name(SecName) {
478 Kind = BTF::BTF_KIND_DATASEC;
491 for (
const auto &V : Vars) {
493 Asm->emitLabelReference(std::get<1>(V), 4);
500 Kind = BTF::BTF_KIND_FLOAT;
516 Kind = BTF::BTF_KIND_DECL_TAG;
536 : DTy(nullptr), Tag(Tag) {
537 Kind = BTF::BTF_KIND_TYPE_TAG;
543 : DTy(DTy), Tag(Tag) {
544 Kind = BTF::BTF_KIND_TYPE_TAG;
564 for (
auto &OffsetM : OffsetToIdMap) {
565 if (Table[OffsetM.second] == S)
566 return OffsetM.first;
570 OffsetToIdMap[
Offset] = Table.size();
571 Table.push_back(std::string(S));
572 Size += S.
size() + 1;
578 LineInfoGenerated(
false), SecNameOff(0), ArrayIndexTypeId(0),
579 MapDefNotCollected(
true) {
583uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry,
585 TypeEntry->setId(TypeEntries.size() + 1);
588 TypeEntries.push_back(std::move(TypeEntry));
592uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry) {
593 TypeEntry->setId(TypeEntries.size() + 1);
595 TypeEntries.push_back(std::move(TypeEntry));
599void BTFDebug::visitBasicType(
const DIBasicType *BTy, uint32_t &TypeId) {
604 case dwarf::DW_ATE_boolean:
605 case dwarf::DW_ATE_signed:
606 case dwarf::DW_ATE_signed_char:
607 case dwarf::DW_ATE_unsigned:
608 case dwarf::DW_ATE_unsigned_char:
609 case dwarf::DW_ATE_UTF:
612 TypeEntry = std::make_unique<BTFTypeInt>(
615 case dwarf::DW_ATE_float:
623 TypeId = addType(std::move(TypeEntry), BTy);
627void BTFDebug::visitSubroutineType(
629 const std::unordered_map<uint32_t, StringRef> &FuncArgNames,
632 uint32_t VLen =
Elements.size() - 1;
640 auto TypeEntry = std::make_unique<BTFTypeFuncProto>(STy, VLen, FuncArgNames);
642 TypeId = addType(std::move(TypeEntry));
644 TypeId = addType(std::move(TypeEntry), STy);
647 for (
const auto Element : Elements) {
648 visitTypeEntry(Element);
652void BTFDebug::processDeclAnnotations(DINodeArray
Annotations,
658 for (
const Metadata *Annotation : Annotations->operands()) {
661 if (
Name->getString() !=
"btf_decl_tag")
665 auto TypeEntry = std::make_unique<BTFTypeDeclTag>(BaseTypeId, ComponentIdx,
667 addType(std::move(TypeEntry));
671uint32_t BTFDebug::processDISubprogram(
const DISubprogram *SP,
672 uint32_t ProtoTypeId, uint8_t Scope) {
674 std::make_unique<BTFTypeFunc>(
SP->getName(), ProtoTypeId, Scope);
675 uint32_t FuncId = addType(std::move(FuncTypeEntry));
678 for (
const DINode *DN :
SP->getRetainedNodes()) {
680 uint32_t Arg = DV->getArg();
682 processDeclAnnotations(DV->getAnnotations(), FuncId, Arg - 1);
685 processDeclAnnotations(
SP->getAnnotations(), FuncId, -1);
691int BTFDebug::genBTFTypeTags(
const DIDerivedType *DTy,
int BaseTypeId) {
697 for (
const Metadata *Annotations : Annots->operands()) {
700 if (
Name->getString() !=
"btf_type_tag")
706 if (MDStrs.
size() == 0)
714 std::unique_ptr<BTFTypeTypeTag>
TypeEntry;
717 std::make_unique<BTFTypeTypeTag>(BaseTypeId, MDStrs[0]->getString());
719 TypeEntry = std::make_unique<BTFTypeTypeTag>(DTy, MDStrs[0]->getString());
720 TmpTypeId = addType(std::move(TypeEntry));
722 for (
unsigned I = 1;
I < MDStrs.
size();
I++) {
723 const MDString *
Value = MDStrs[
I];
724 TypeEntry = std::make_unique<BTFTypeTypeTag>(TmpTypeId,
Value->getString());
725 TmpTypeId = addType(std::move(TypeEntry));
731void BTFDebug::visitStructType(
const DICompositeType *CTy,
bool IsStruct,
738 if (CTy->
getTag() == dwarf::DW_TAG_variant_part) {
749 bool HasBitField =
false;
750 for (
const auto *Element : Elements) {
751 if (Element->getTag() == dwarf::DW_TAG_member) {
753 if (
E->isBitField()) {
761 std::make_unique<BTFTypeStruct>(CTy, IsStruct, HasBitField, VLen);
763 TypeId = addType(std::move(TypeEntry), CTy);
770 for (
const auto *Element : Elements) {
771 switch (Element->getTag()) {
772 case dwarf::DW_TAG_member: {
774 visitTypeEntry(Elem);
775 processDeclAnnotations(Elem->getAnnotations(), TypeId, FieldNo);
778 case dwarf::DW_TAG_variant_part: {
780 visitTypeEntry(Elem);
781 processDeclAnnotations(Elem->getAnnotations(), TypeId, FieldNo);
791void BTFDebug::visitArrayType(
const DICompositeType *CTy, uint32_t &TypeId) {
795 visitTypeEntry(ElemType, ElemTypeId,
false,
false);
802 auto TypeEntry = std::make_unique<BTFTypeArray>(ElemTypeId, 0);
803 ElemTypeId = addType(std::move(TypeEntry), CTy);
807 if (Element->getTag() == dwarf::DW_TAG_subrange_type) {
810 int64_t
Count = CI->getSExtValue();
815 std::make_unique<BTFTypeArray>(ElemTypeId,
818 ElemTypeId = addType(std::move(TypeEntry), CTy);
820 ElemTypeId = addType(std::move(TypeEntry));
829 if (!ArrayIndexTypeId) {
830 auto TypeEntry = std::make_unique<BTFTypeInt>(dwarf::DW_ATE_unsigned, 32,
831 0,
"__ARRAY_SIZE_TYPE__");
832 ArrayIndexTypeId = addType(std::move(TypeEntry));
836void BTFDebug::visitEnumType(
const DICompositeType *CTy, uint32_t &TypeId) {
842 bool IsSigned =
false;
843 unsigned NumBits = 32;
848 IsSigned = BTy->
getEncoding() == dwarf::DW_ATE_signed ||
854 auto TypeEntry = std::make_unique<BTFTypeEnum>(CTy, VLen, IsSigned);
855 TypeId = addType(std::move(TypeEntry), CTy);
858 auto TypeEntry = std::make_unique<BTFTypeEnum64>(CTy, VLen, IsSigned);
859 TypeId = addType(std::move(TypeEntry), CTy);
865void BTFDebug::visitFwdDeclType(
const DICompositeType *CTy,
bool IsUnion,
868 TypeId = addType(std::move(TypeEntry), CTy);
876 case dwarf::DW_TAG_structure_type:
877 case dwarf::DW_TAG_union_type:
878 case dwarf::DW_TAG_variant_part:
881 visitFwdDeclType(CTy,
Tag == dwarf::DW_TAG_union_type, TypeId);
883 visitStructType(CTy,
Tag == dwarf::DW_TAG_structure_type, TypeId);
885 case dwarf::DW_TAG_array_type:
886 visitArrayType(CTy, TypeId);
888 case dwarf::DW_TAG_enumeration_type:
889 visitEnumType(CTy, TypeId);
896bool BTFDebug::IsForwardDeclCandidate(
const DIType *
Base) {
898 auto CTag = CTy->
getTag();
899 if ((CTag == dwarf::DW_TAG_structure_type ||
900 CTag == dwarf::DW_TAG_union_type) &&
908void BTFDebug::visitDerivedType(
const DIDerivedType *DTy, uint32_t &TypeId,
909 bool CheckPointer,
bool SeenPointer) {
912 if (
Tag == dwarf::DW_TAG_atomic_type)
913 return visitTypeEntry(DTy->getBaseType(), TypeId, CheckPointer,
918 if (CheckPointer && !SeenPointer) {
922 if (CheckPointer && SeenPointer) {
923 const DIType *
Base = DTy->getBaseType();
925 if (IsForwardDeclCandidate(
Base)) {
929 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
true);
932 TypeId = addType(std::move(TypeEntry), DTy);
938 if (
Tag == dwarf::DW_TAG_pointer_type) {
939 int TmpTypeId = genBTFTypeTags(DTy, -1);
940 if (TmpTypeId >= 0) {
942 std::make_unique<BTFTypeDerived>(TmpTypeId,
Tag, DTy->
getName());
943 TypeId = addType(std::move(TypeDEntry), DTy);
945 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
false);
946 TypeId = addType(std::move(TypeEntry), DTy);
948 }
else 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) {
951 auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy,
Tag,
false);
952 TypeId = addType(std::move(TypeEntry), DTy);
953 if (
Tag == dwarf::DW_TAG_typedef)
955 }
else if (
Tag != dwarf::DW_TAG_member) {
961 uint32_t TempTypeId = 0;
962 if (
Tag == dwarf::DW_TAG_member)
963 visitTypeEntry(DTy->getBaseType(), TempTypeId,
true,
false);
965 visitTypeEntry(DTy->getBaseType(), TempTypeId, CheckPointer, SeenPointer);
975void BTFDebug::visitTypeEntry(
const DIType *Ty, uint32_t &TypeId,
976 bool CheckPointer,
bool SeenPointer) {
977 if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {
978 TypeId = DIToIdMap[Ty];
1009 if (Ty && (!CheckPointer || !SeenPointer)) {
1012 const DIType *BaseTy = DTy->getBaseType();
1016 if (DIToIdMap.find(BaseTy) != DIToIdMap.end()) {
1019 if (CheckPointer && DTy->
getTag() == dwarf::DW_TAG_pointer_type &&
1022 if (IsForwardDeclCandidate(BaseTy))
1026 visitTypeEntry(BaseTy, TmpTypeId, CheckPointer, SeenPointer);
1037 visitBasicType(BTy, TypeId);
1039 visitSubroutineType(STy,
false, std::unordered_map<uint32_t, StringRef>(),
1042 visitCompositeType(CTy, TypeId);
1044 visitDerivedType(DTy, TypeId, CheckPointer, SeenPointer);
1049void BTFDebug::visitTypeEntry(
const DIType *Ty) {
1051 visitTypeEntry(Ty, TypeId,
false,
false);
1054void BTFDebug::visitMapDefType(
const DIType *Ty, uint32_t &TypeId) {
1055 if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {
1056 TypeId = DIToIdMap[Ty];
1062 case dwarf::DW_TAG_typedef:
1063 case dwarf::DW_TAG_const_type:
1064 case dwarf::DW_TAG_volatile_type:
1065 case dwarf::DW_TAG_restrict_type:
1066 case dwarf::DW_TAG_pointer_type:
1069 case dwarf::DW_TAG_array_type:
1073 case dwarf::DW_TAG_structure_type: {
1077 for (
const auto *Element : Elements) {
1079 const DIType *MemberBaseType = MemberType->getBaseType();
1088 visitMapDefType(MemberBaseType, TmpId);
1090 visitTypeEntry(MemberBaseType);
1100 visitTypeEntry(Ty, TypeId,
false,
false);
1104std::string BTFDebug::populateFileContent(
const DIFile *File) {
1105 std::string FileName;
1107 if (!
File->getFilename().starts_with(
"/") &&
File->getDirectory().size())
1108 FileName =
File->getDirectory().str() +
"/" +
File->getFilename().str();
1110 FileName = std::string(
File->getFilename());
1113 if (FileContent.contains(FileName))
1116 std::vector<std::string> Content;
1118 Content.push_back(Line);
1120 auto LoadFile = [](StringRef FileName) {
1126 std::unique_ptr<MemoryBuffer> Buf;
1130 else if (ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = LoadFile(FileName))
1131 Buf = std::move(*BufOrErr);
1133 for (line_iterator
I(*Buf,
false),
E;
I !=
E; ++
I)
1134 Content.push_back(std::string(*
I));
1136 FileContent[FileName] = std::move(Content);
1140void BTFDebug::constructLineInfo(
MCSymbol *Label,
const DIFile *File,
1141 uint32_t Line, uint32_t Column) {
1142 std::string FileName = populateFileContent(File);
1143 BTFLineInfo LineInfo;
1148 const auto &Content = FileContent[FileName];
1149 if (Line < Content.size())
1155 LineInfoTable[SecNameOff].push_back(LineInfo);
1158void BTFDebug::emitCommonHeader() {
1165void BTFDebug::emitBTFSection() {
1167 if (!TypeEntries.size() && StringTable.getSize() == 1)
1170 MCContext &Ctx = OS.getContext();
1173 OS.switchSection(Sec);
1179 uint32_t TypeLen = 0, StrLen;
1180 for (
const auto &TypeEntry : TypeEntries)
1182 StrLen = StringTable.getSize();
1185 OS.emitInt32(TypeLen);
1186 OS.emitInt32(TypeLen);
1187 OS.emitInt32(StrLen);
1190 for (
const auto &TypeEntry : TypeEntries)
1194 uint32_t StringOffset = 0;
1195 for (
const auto &S : StringTable.getTable()) {
1196 OS.AddComment(
"string offset=" + std::to_string(StringOffset));
1198 OS.emitBytes(StringRef(
"\0", 1));
1199 StringOffset += S.size() + 1;
1203void BTFDebug::emitBTFExtSection() {
1206 if (!FuncInfoTable.size() && !LineInfoTable.size() &&
1207 !FieldRelocTable.size())
1210 MCContext &Ctx = OS.getContext();
1213 OS.switchSection(Sec);
1220 uint32_t FuncLen = 4, LineLen = 4;
1222 uint32_t FieldRelocLen = 0;
1223 for (
const auto &FuncSec : FuncInfoTable) {
1227 for (
const auto &LineSec : LineInfoTable) {
1231 for (
const auto &FieldRelocSec : FieldRelocTable) {
1240 OS.emitInt32(FuncLen);
1241 OS.emitInt32(FuncLen);
1242 OS.emitInt32(LineLen);
1243 OS.emitInt32(FuncLen + LineLen);
1244 OS.emitInt32(FieldRelocLen);
1247 OS.AddComment(
"FuncInfo");
1249 for (
const auto &FuncSec : FuncInfoTable) {
1250 OS.AddComment(
"FuncInfo section string offset=" +
1251 std::to_string(FuncSec.first));
1252 OS.emitInt32(FuncSec.first);
1253 OS.emitInt32(FuncSec.second.size());
1254 for (
const auto &FuncInfo : FuncSec.second) {
1255 Asm->emitLabelReference(FuncInfo.Label, 4);
1256 OS.emitInt32(FuncInfo.TypeId);
1261 OS.AddComment(
"LineInfo");
1263 for (
const auto &LineSec : LineInfoTable) {
1264 OS.AddComment(
"LineInfo section string offset=" +
1265 std::to_string(LineSec.first));
1266 OS.emitInt32(LineSec.first);
1267 OS.emitInt32(LineSec.second.size());
1268 for (
const auto &LineInfo : LineSec.second) {
1269 Asm->emitLabelReference(LineInfo.
Label, 4);
1271 OS.emitInt32(LineInfo.
LineOff);
1272 OS.AddComment(
"Line " + std::to_string(LineInfo.
LineNum) +
" Col " +
1279 if (FieldRelocLen) {
1280 OS.AddComment(
"FieldReloc");
1282 for (
const auto &FieldRelocSec : FieldRelocTable) {
1283 OS.AddComment(
"Field reloc section string offset=" +
1284 std::to_string(FieldRelocSec.first));
1285 OS.emitInt32(FieldRelocSec.first);
1286 OS.emitInt32(FieldRelocSec.second.size());
1287 for (
const auto &FieldRelocInfo : FieldRelocSec.second) {
1288 Asm->emitLabelReference(FieldRelocInfo.Label, 4);
1289 OS.emitInt32(FieldRelocInfo.TypeID);
1290 OS.emitInt32(FieldRelocInfo.OffsetNameOff);
1291 OS.emitInt32(FieldRelocInfo.RelocKind);
1299 auto *Unit = SP->getUnit();
1302 SkipInstruction =
true;
1305 SkipInstruction =
false;
1326 if (MapDefNotCollected) {
1327 processGlobals(
true);
1328 MapDefNotCollected =
false;
1334 std::unordered_map<uint32_t, StringRef> FuncArgNames;
1335 for (
const DINode *DN : SP->getRetainedNodes()) {
1340 visitTypeEntry(DV->getType());
1341 FuncArgNames[Arg] = DV->getName();
1348 visitSubroutineType(SP->getType(),
true, FuncArgNames, ProtoTypeId);
1352 uint32_t FuncTypeId = processDISubprogram(SP, ProtoTypeId, Scope);
1354 for (
const auto &TypeEntry : TypeEntries)
1355 TypeEntry->completeType(*
this);
1360 FuncInfo.
Label = FuncLabel;
1361 FuncInfo.
TypeId = FuncTypeId;
1368 FuncInfoTable[SecNameOff].push_back(FuncInfo);
1372 SkipInstruction =
false;
1373 LineInfoGenerated =
false;
1379unsigned BTFDebug::populateType(
const DIType *Ty) {
1381 visitTypeEntry(Ty, Id,
false,
false);
1382 for (
const auto &TypeEntry : TypeEntries)
1383 TypeEntry->completeType(*
this);
1388void BTFDebug::generatePatchImmReloc(
const MCSymbol *ORSym,
uint32_t RootId,
1391 FieldReloc.
Label = ORSym;
1392 FieldReloc.
TypeID = RootId;
1398 size_t SecondColon = AccessPattern.
find_first_of(
':', FirstColon + 1);
1401 SecondColon - FirstColon);
1403 FirstDollar - SecondColon);
1406 FieldReloc.
RelocKind = std::stoull(std::string(RelocKindStr));
1407 PatchImms[GVar] = std::make_pair(std::stoll(std::string(PatchImmStr)),
1410 StringRef RelocStr = AccessPattern.
substr(FirstDollar + 1);
1412 FieldReloc.
RelocKind = std::stoull(std::string(RelocStr));
1413 PatchImms[GVar] = std::make_pair(RootId, FieldReloc.
RelocKind);
1415 FieldRelocTable[SecNameOff].push_back(FieldReloc);
1421 const GlobalValue *GVal = MO.
getGlobal();
1433 MCSymbol *ORSym = OS.getContext().createTempSymbol();
1434 OS.emitLabel(ORSym);
1436 MDNode *MDN = GVar->
getMetadata(LLVMContext::MD_preserve_access_index);
1438 generatePatchImmReloc(ORSym, RootId, GVar,
1446 if (SkipInstruction ||
MI->isMetaInstruction() ||
1450 if (
MI->isInlineAsm()) {
1452 unsigned NumDefs = 0;
1467 if (
MI->getOpcode() == BPF::LD_imm64) {
1482 processGlobalValue(
MI->getOperand(1));
1483 }
else if (
MI->getOpcode() == BPF::CORE_LD64 ||
1484 MI->getOpcode() == BPF::CORE_LD32 ||
1485 MI->getOpcode() == BPF::CORE_ST ||
1486 MI->getOpcode() == BPF::CORE_SHIFT) {
1488 processGlobalValue(
MI->getOperand(3));
1489 }
else if (
MI->getOpcode() == BPF::JAL) {
1506 if (LineInfoGenerated ==
false) {
1507 auto *S =
MI->getMF()->getFunction().getSubprogram();
1511 constructLineInfo(FuncLabel, S->getFile(), S->getLine(), 0);
1512 LineInfoGenerated =
true;
1519 MCSymbol *LineSym = OS.getContext().createTempSymbol();
1520 OS.emitLabel(LineSym);
1523 constructLineInfo(LineSym,
DL->getFile(),
DL.getLine(),
DL.getCol());
1525 LineInfoGenerated =
true;
1529void BTFDebug::processGlobals(
bool ProcessingMapDef) {
1535 std::optional<SectionKind> GVKind;
1537 if (!
Global.isDeclarationForLinker())
1540 if (
Global.isDeclarationForLinker())
1541 SecName =
Global.hasSection() ?
Global.getSection() :
"";
1542 else if (GVKind->isCommon())
1550 if (ProcessingMapDef != SecName.
starts_with(
".maps"))
1556 if (SecName ==
".rodata" &&
Global.hasPrivateLinkage() &&
1557 DataSecEntries.find(SecName) == DataSecEntries.end()) {
1559 if (!GVKind->isMergeableCString() && !GVKind->isMergeableConst()) {
1560 DataSecEntries[std::string(SecName)] =
1561 std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1566 Global.getDebugInfo(GVs);
1569 if (GVs.
size() == 0)
1572 uint32_t GVTypeId = 0;
1573 DIGlobalVariable *DIGlobal =
nullptr;
1574 for (
auto *GVE : GVs) {
1575 DIGlobal = GVE->getVariable();
1577 visitMapDefType(DIGlobal->
getType(), GVTypeId);
1580 visitTypeEntry(Ty, GVTypeId,
false,
false);
1603 }
else if (
Global.hasInitializer()) {
1610 std::make_unique<BTFKindVar>(
Global.getName(), GVTypeId, GVarInfo);
1611 uint32_t VarId = addType(std::move(VarEntry));
1616 if (SecName.
empty())
1620 auto [It,
Inserted] = DataSecEntries.try_emplace(std::string(SecName));
1622 It->second = std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1625 const DataLayout &
DL =
Global.getDataLayout();
1628 It->second->addDataSecEntry(VarId,
Asm->getSymbol(&
Global),
Size);
1630 if (
Global.hasInitializer())
1631 processGlobalInitializer(
Global.getInitializer());
1646void BTFDebug::processGlobalInitializer(
const Constant *
C) {
1648 processFuncPrototypes(Fn);
1650 for (
unsigned I = 0,
N = CA->getNumOperands();
I <
N; ++
I)
1651 processGlobalInitializer(CA->getOperand(
I));
1657 if (
MI->getOpcode() == BPF::LD_imm64) {
1668 auto [Imm,
Reloc] = PatchImms[GVar];
1679 }
else if (
MI->getOpcode() == BPF::CORE_LD64 ||
1680 MI->getOpcode() == BPF::CORE_LD32 ||
1681 MI->getOpcode() == BPF::CORE_ST ||
1682 MI->getOpcode() == BPF::CORE_SHIFT) {
1688 uint32_t Imm = PatchImms[GVar].first;
1690 if (
MI->getOperand(0).isImm())
1703void BTFDebug::processFuncPrototypes(
const Function *
F) {
1708 if (!SP || SP->isDefinition())
1712 if (!ProtoFunctions.insert(
F).second)
1716 const std::unordered_map<uint32_t, StringRef> FuncArgNames;
1717 visitSubroutineType(SP->getType(),
false, FuncArgNames, ProtoTypeId);
1720 if (
F->hasSection()) {
1723 auto [It, Inserted] = DataSecEntries.try_emplace(std::string(SecName));
1725 It->second = std::make_unique<BTFKindDataSec>(
Asm, std::string(SecName));
1734 if (MapDefNotCollected) {
1735 processGlobals(
true);
1736 MapDefNotCollected =
false;
1740 processGlobals(
false);
1746 processFuncPrototypes(&
F);
1749 for (
auto &DataSec : DataSecEntries)
1750 addType(std::move(DataSec.second));
1753 for (
auto &
Fixup : FixupDerivedTypes) {
1756 bool IsUnion = CTy->
getTag() == dwarf::DW_TAG_union_type;
1767 if (StructTypeId == 0) {
1768 auto FwdTypeEntry = std::make_unique<BTFTypeFwd>(TypeName, IsUnion);
1769 StructTypeId = addType(std::move(FwdTypeEntry));
1772 for (
auto &TypeInfo :
Fixup.second) {
1776 int TmpTypeId = genBTFTypeTags(DTy, StructTypeId);
1785 for (
const auto &TypeEntry : TypeEntries)
1786 TypeEntry->completeType(*
this);
1790 emitBTFExtSection();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const char * BTFKindStr[]
static const DIType * tryRemoveAtomicType(const DIType *Ty)
This file contains support for writing BTF debug info.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains constants used for implementing Dwarf debug support.
Module.h This file contains the declarations for the Module class.
PowerPC TLS Dynamic Call Fixup
static StringRef getName(Value *V)
static enum BaseType getBaseType(const Value *Val)
Return the baseType for Val which states whether Val is exclusively derived from constant/null,...
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.
static constexpr StringRef TypeIdAttr
The attribute attached to globals representing a type id.
static constexpr StringRef AmaAttr
The attribute attached to globals representing a field access.
Collect and emit BTF information.
void endFunctionImpl(const MachineFunction *MF) override
Post process after all instructions in this function are processed.
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
bool InstLower(const MachineInstr *MI, MCInst &OutMI)
Emit proper patchable instructions.
size_t addString(StringRef S)
Add string to the string table.
uint32_t getArrayIndexTypeId()
Get the special array index type id.
uint32_t getTypeId(const DIType *Ty)
Get the type id for a particular DIType.
void endModule() override
Complete all the types and emit the BTF sections.
void beginFunctionImpl(const MachineFunction *MF) override
Gather pre-function debug information.
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
BTFKindDataSec(AsmPrinter *AsmPrt, std::string SecName)
BTFKindVar(StringRef VarName, uint32_t TypeId, uint32_t VarInfo)
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
uint32_t addString(StringRef S)
Add a string to the string table and returns its offset in the table.
BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems)
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void completeType(BTFDebug &BDebug) override
Represent a BTF array.
struct BTF::CommonType BTFType
virtual void emitType(MCStreamer &OS)
Emit types for this BTF type entry.
uint32_t roundupToBytes(uint32_t NumBits)
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
BTFTypeDeclTag(uint32_t BaseTypeId, int ComponentId, StringRef Tag)
Handle several derived types include pointer, const, volatile, typedef and restrict.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void setPointeeType(uint32_t PointeeType)
BTFTypeDerived(const DIDerivedType *Ty, unsigned Tag, bool NeedsFixup)
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
BTFTypeEnum64(const DICompositeType *ETy, uint32_t NumValues, bool IsSigned)
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
BTFTypeEnum(const DICompositeType *ETy, uint32_t NumValues, bool IsSigned)
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
BTFTypeFloat(uint32_t SizeInBits, StringRef TypeName)
BTFTypeFuncProto(const DISubroutineType *STy, uint32_t NumParams, const std::unordered_map< uint32_t, StringRef > &FuncArgNames)
The Func kind represents both subprogram and pointee of function pointers.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId, uint32_t Scope)
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
BTFTypeFwd(StringRef Name, bool IsUnion)
Represent a struct/union forward declaration.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
BTFTypeInt(uint32_t Encoding, uint32_t SizeInBits, uint32_t OffsetInBits, StringRef TypeName)
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void emitType(MCStreamer &OS) override
Emit types for this BTF type entry.
BTFTypeStruct(const DICompositeType *STy, bool IsStruct, bool HasBitField, uint32_t NumMembers)
Represent either a struct or a union.
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
void completeType(BTFDebug &BDebug) override
Complete BTF type generation after all related DebugInfo types have been visited so their BTF type id...
BTFTypeTypeTag(uint32_t NextTypeId, StringRef Tag)
This is an important base class in LLVM.
Basic type, like 'int' or 'float'.
unsigned getEncoding() const
DIDerivedType * getDiscriminator() const
DINodeArray getElements() const
DINodeArray getAnnotations() const
DIType * getBaseType() const
DINodeArray getAnnotations() const
Get annotations associated with this derived type.
DINodeArray getAnnotations() const
Tagged DWARF-like metadata node.
LLVM_ABI dwarf::Tag getTag() const
Subprogram description. Uses SubclassData1.
LLVM_ABI BoundType getCount() const
Type array for a subprogram.
DITypeArray getTypeArray() const
uint64_t getOffsetInBits() const
StringRef getName() const
bool isForwardDecl() const
uint64_t getSizeInBits() const
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.
DebugHandlerBase(AsmPrinter *A)
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
DISubprogram * getSubprogram() const
Get the attached subprogram.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this GlobalObject.
@ 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.
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
Instances of this class represent a single low-level machine instruction.
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
This represents a section on linux, lots of unix variants and some bare metal systems.
Instances of this class represent a uniqued identifier for a section in the current translation unit.
void setAlignment(Align Value)
StringRef getName() const
Streaming machine code generation interface.
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
void emitInt32(uint64_t Value)
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)
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.
LLVM_ABI 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(uint64_t Val)
LLVM Value Representation.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ 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
ScopedSetting scopedDisable()
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto dyn_cast_or_null(const Y &Val)
FunctionAddr VTableAddr Count
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ Global
Append to llvm.global_dtors.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
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
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".