1 //===- BTFDebug.cpp - BTF Generator ---------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file contains support for writing BTF debug info.
11 //===----------------------------------------------------------------------===//
16 #include "MCTargetDesc/BPFMCTargetDesc.h"
17 #include "llvm/BinaryFormat/ELF.h"
18 #include "llvm/CodeGen/AsmPrinter.h"
19 #include "llvm/CodeGen/MachineModuleInfo.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCObjectFileInfo.h"
22 #include "llvm/MC/MCSectionELF.h"
23 #include "llvm/MC/MCStreamer.h"
24 #include "llvm/Support/LineIterator.h"
28 static const char *BTFKindStr
[] = {
29 #define HANDLE_BTF_KIND(ID, NAME) "BTF_KIND_" #NAME,
33 /// Emit a BTF common type.
34 void BTFTypeBase::emitType(MCStreamer
&OS
) {
35 OS
.AddComment(std::string(BTFKindStr
[Kind
]) + "(id = " + std::to_string(Id
) +
37 OS
.EmitIntValue(BTFType
.NameOff
, 4);
38 OS
.AddComment("0x" + Twine::utohexstr(BTFType
.Info
));
39 OS
.EmitIntValue(BTFType
.Info
, 4);
40 OS
.EmitIntValue(BTFType
.Size
, 4);
43 BTFTypeDerived::BTFTypeDerived(const DIDerivedType
*DTy
, unsigned Tag
,
45 : DTy(DTy
), NeedsFixup(NeedsFixup
) {
47 case dwarf::DW_TAG_pointer_type
:
48 Kind
= BTF::BTF_KIND_PTR
;
50 case dwarf::DW_TAG_const_type
:
51 Kind
= BTF::BTF_KIND_CONST
;
53 case dwarf::DW_TAG_volatile_type
:
54 Kind
= BTF::BTF_KIND_VOLATILE
;
56 case dwarf::DW_TAG_typedef
:
57 Kind
= BTF::BTF_KIND_TYPEDEF
;
59 case dwarf::DW_TAG_restrict_type
:
60 Kind
= BTF::BTF_KIND_RESTRICT
;
63 llvm_unreachable("Unknown DIDerivedType Tag");
65 BTFType
.Info
= Kind
<< 24;
68 void BTFTypeDerived::completeType(BTFDebug
&BDebug
) {
73 BTFType
.NameOff
= BDebug
.addString(DTy
->getName());
78 // The base type for PTR/CONST/VOLATILE could be void.
79 const DIType
*ResolvedType
= DTy
->getBaseType();
81 assert((Kind
== BTF::BTF_KIND_PTR
|| Kind
== BTF::BTF_KIND_CONST
||
82 Kind
== BTF::BTF_KIND_VOLATILE
) &&
83 "Invalid null basetype");
86 BTFType
.Type
= BDebug
.getTypeId(ResolvedType
);
90 void BTFTypeDerived::emitType(MCStreamer
&OS
) { BTFTypeBase::emitType(OS
); }
92 void BTFTypeDerived::setPointeeType(uint32_t PointeeType
) {
93 BTFType
.Type
= PointeeType
;
96 /// Represent a struct/union forward declaration.
97 BTFTypeFwd::BTFTypeFwd(StringRef Name
, bool IsUnion
) : Name(Name
) {
98 Kind
= BTF::BTF_KIND_FWD
;
99 BTFType
.Info
= IsUnion
<< 31 | Kind
<< 24;
103 void BTFTypeFwd::completeType(BTFDebug
&BDebug
) {
108 BTFType
.NameOff
= BDebug
.addString(Name
);
111 void BTFTypeFwd::emitType(MCStreamer
&OS
) { BTFTypeBase::emitType(OS
); }
113 BTFTypeInt::BTFTypeInt(uint32_t Encoding
, uint32_t SizeInBits
,
114 uint32_t OffsetInBits
, StringRef TypeName
)
116 // Translate IR int encoding to BTF int encoding.
119 case dwarf::DW_ATE_boolean
:
120 BTFEncoding
= BTF::INT_BOOL
;
122 case dwarf::DW_ATE_signed
:
123 case dwarf::DW_ATE_signed_char
:
124 BTFEncoding
= BTF::INT_SIGNED
;
126 case dwarf::DW_ATE_unsigned
:
127 case dwarf::DW_ATE_unsigned_char
:
131 llvm_unreachable("Unknown BTFTypeInt Encoding");
134 Kind
= BTF::BTF_KIND_INT
;
135 BTFType
.Info
= Kind
<< 24;
136 BTFType
.Size
= roundupToBytes(SizeInBits
);
137 IntVal
= (BTFEncoding
<< 24) | OffsetInBits
<< 16 | SizeInBits
;
140 void BTFTypeInt::completeType(BTFDebug
&BDebug
) {
145 BTFType
.NameOff
= BDebug
.addString(Name
);
148 void BTFTypeInt::emitType(MCStreamer
&OS
) {
149 BTFTypeBase::emitType(OS
);
150 OS
.AddComment("0x" + Twine::utohexstr(IntVal
));
151 OS
.EmitIntValue(IntVal
, 4);
154 BTFTypeEnum::BTFTypeEnum(const DICompositeType
*ETy
, uint32_t VLen
) : ETy(ETy
) {
155 Kind
= BTF::BTF_KIND_ENUM
;
156 BTFType
.Info
= Kind
<< 24 | VLen
;
157 BTFType
.Size
= roundupToBytes(ETy
->getSizeInBits());
160 void BTFTypeEnum::completeType(BTFDebug
&BDebug
) {
165 BTFType
.NameOff
= BDebug
.addString(ETy
->getName());
167 DINodeArray Elements
= ETy
->getElements();
168 for (const auto Element
: Elements
) {
169 const auto *Enum
= cast
<DIEnumerator
>(Element
);
171 struct BTF::BTFEnum BTFEnum
;
172 BTFEnum
.NameOff
= BDebug
.addString(Enum
->getName());
173 // BTF enum value is 32bit, enforce it.
174 BTFEnum
.Val
= static_cast<uint32_t>(Enum
->getValue());
175 EnumValues
.push_back(BTFEnum
);
179 void BTFTypeEnum::emitType(MCStreamer
&OS
) {
180 BTFTypeBase::emitType(OS
);
181 for (const auto &Enum
: EnumValues
) {
182 OS
.EmitIntValue(Enum
.NameOff
, 4);
183 OS
.EmitIntValue(Enum
.Val
, 4);
187 BTFTypeArray::BTFTypeArray(uint32_t ElemTypeId
, uint32_t NumElems
) {
188 Kind
= BTF::BTF_KIND_ARRAY
;
190 BTFType
.Info
= Kind
<< 24;
193 ArrayInfo
.ElemType
= ElemTypeId
;
194 ArrayInfo
.Nelems
= NumElems
;
197 /// Represent a BTF array.
198 void BTFTypeArray::completeType(BTFDebug
&BDebug
) {
203 // The IR does not really have a type for the index.
204 // A special type for array index should have been
205 // created during initial type traversal. Just
206 // retrieve that type id.
207 ArrayInfo
.IndexType
= BDebug
.getArrayIndexTypeId();
210 void BTFTypeArray::emitType(MCStreamer
&OS
) {
211 BTFTypeBase::emitType(OS
);
212 OS
.EmitIntValue(ArrayInfo
.ElemType
, 4);
213 OS
.EmitIntValue(ArrayInfo
.IndexType
, 4);
214 OS
.EmitIntValue(ArrayInfo
.Nelems
, 4);
217 /// Represent either a struct or a union.
218 BTFTypeStruct::BTFTypeStruct(const DICompositeType
*STy
, bool IsStruct
,
219 bool HasBitField
, uint32_t Vlen
)
220 : STy(STy
), HasBitField(HasBitField
) {
221 Kind
= IsStruct
? BTF::BTF_KIND_STRUCT
: BTF::BTF_KIND_UNION
;
222 BTFType
.Size
= roundupToBytes(STy
->getSizeInBits());
223 BTFType
.Info
= (HasBitField
<< 31) | (Kind
<< 24) | Vlen
;
226 void BTFTypeStruct::completeType(BTFDebug
&BDebug
) {
231 BTFType
.NameOff
= BDebug
.addString(STy
->getName());
233 // Add struct/union members.
234 const DINodeArray Elements
= STy
->getElements();
235 for (const auto *Element
: Elements
) {
236 struct BTF::BTFMember BTFMember
;
237 const auto *DDTy
= cast
<DIDerivedType
>(Element
);
239 BTFMember
.NameOff
= BDebug
.addString(DDTy
->getName());
241 uint8_t BitFieldSize
= DDTy
->isBitField() ? DDTy
->getSizeInBits() : 0;
242 BTFMember
.Offset
= BitFieldSize
<< 24 | DDTy
->getOffsetInBits();
244 BTFMember
.Offset
= DDTy
->getOffsetInBits();
246 const auto *BaseTy
= DDTy
->getBaseType();
247 BTFMember
.Type
= BDebug
.getTypeId(BaseTy
);
248 Members
.push_back(BTFMember
);
252 void BTFTypeStruct::emitType(MCStreamer
&OS
) {
253 BTFTypeBase::emitType(OS
);
254 for (const auto &Member
: Members
) {
255 OS
.EmitIntValue(Member
.NameOff
, 4);
256 OS
.EmitIntValue(Member
.Type
, 4);
257 OS
.AddComment("0x" + Twine::utohexstr(Member
.Offset
));
258 OS
.EmitIntValue(Member
.Offset
, 4);
262 std::string
BTFTypeStruct::getName() { return STy
->getName(); }
264 /// The Func kind represents both subprogram and pointee of function
265 /// pointers. If the FuncName is empty, it represents a pointee of function
266 /// pointer. Otherwise, it represents a subprogram. The func arg names
267 /// are empty for pointee of function pointer case, and are valid names
269 BTFTypeFuncProto::BTFTypeFuncProto(
270 const DISubroutineType
*STy
, uint32_t VLen
,
271 const std::unordered_map
<uint32_t, StringRef
> &FuncArgNames
)
272 : STy(STy
), FuncArgNames(FuncArgNames
) {
273 Kind
= BTF::BTF_KIND_FUNC_PROTO
;
274 BTFType
.Info
= (Kind
<< 24) | VLen
;
277 void BTFTypeFuncProto::completeType(BTFDebug
&BDebug
) {
282 DITypeRefArray Elements
= STy
->getTypeArray();
283 auto RetType
= Elements
[0];
284 BTFType
.Type
= RetType
? BDebug
.getTypeId(RetType
) : 0;
287 // For null parameter which is typically the last one
288 // to represent the vararg, encode the NameOff/Type to be 0.
289 for (unsigned I
= 1, N
= Elements
.size(); I
< N
; ++I
) {
290 struct BTF::BTFParam Param
;
291 auto Element
= Elements
[I
];
293 Param
.NameOff
= BDebug
.addString(FuncArgNames
[I
]);
294 Param
.Type
= BDebug
.getTypeId(Element
);
299 Parameters
.push_back(Param
);
303 void BTFTypeFuncProto::emitType(MCStreamer
&OS
) {
304 BTFTypeBase::emitType(OS
);
305 for (const auto &Param
: Parameters
) {
306 OS
.EmitIntValue(Param
.NameOff
, 4);
307 OS
.EmitIntValue(Param
.Type
, 4);
311 BTFTypeFunc::BTFTypeFunc(StringRef FuncName
, uint32_t ProtoTypeId
)
313 Kind
= BTF::BTF_KIND_FUNC
;
314 BTFType
.Info
= Kind
<< 24;
315 BTFType
.Type
= ProtoTypeId
;
318 void BTFTypeFunc::completeType(BTFDebug
&BDebug
) {
323 BTFType
.NameOff
= BDebug
.addString(Name
);
326 void BTFTypeFunc::emitType(MCStreamer
&OS
) { BTFTypeBase::emitType(OS
); }
328 BTFKindVar::BTFKindVar(StringRef VarName
, uint32_t TypeId
, uint32_t VarInfo
)
330 Kind
= BTF::BTF_KIND_VAR
;
331 BTFType
.Info
= Kind
<< 24;
332 BTFType
.Type
= TypeId
;
336 void BTFKindVar::completeType(BTFDebug
&BDebug
) {
337 BTFType
.NameOff
= BDebug
.addString(Name
);
340 void BTFKindVar::emitType(MCStreamer
&OS
) {
341 BTFTypeBase::emitType(OS
);
342 OS
.EmitIntValue(Info
, 4);
345 BTFKindDataSec::BTFKindDataSec(AsmPrinter
*AsmPrt
, std::string SecName
)
346 : Asm(AsmPrt
), Name(SecName
) {
347 Kind
= BTF::BTF_KIND_DATASEC
;
348 BTFType
.Info
= Kind
<< 24;
352 void BTFKindDataSec::completeType(BTFDebug
&BDebug
) {
353 BTFType
.NameOff
= BDebug
.addString(Name
);
354 BTFType
.Info
|= Vars
.size();
357 void BTFKindDataSec::emitType(MCStreamer
&OS
) {
358 BTFTypeBase::emitType(OS
);
360 for (const auto &V
: Vars
) {
361 OS
.EmitIntValue(std::get
<0>(V
), 4);
362 Asm
->EmitLabelReference(std::get
<1>(V
), 4);
363 OS
.EmitIntValue(std::get
<2>(V
), 4);
367 uint32_t BTFStringTable::addString(StringRef S
) {
368 // Check whether the string already exists.
369 for (auto &OffsetM
: OffsetToIdMap
) {
370 if (Table
[OffsetM
.second
] == S
)
371 return OffsetM
.first
;
373 // Not find, add to the string table.
374 uint32_t Offset
= Size
;
375 OffsetToIdMap
[Offset
] = Table
.size();
377 Size
+= S
.size() + 1;
381 BTFDebug::BTFDebug(AsmPrinter
*AP
)
382 : DebugHandlerBase(AP
), OS(*Asm
->OutStreamer
), SkipInstruction(false),
383 LineInfoGenerated(false), SecNameOff(0), ArrayIndexTypeId(0),
384 MapDefNotCollected(true) {
388 uint32_t BTFDebug::addType(std::unique_ptr
<BTFTypeBase
> TypeEntry
,
390 TypeEntry
->setId(TypeEntries
.size() + 1);
391 uint32_t Id
= TypeEntry
->getId();
393 TypeEntries
.push_back(std::move(TypeEntry
));
397 uint32_t BTFDebug::addType(std::unique_ptr
<BTFTypeBase
> TypeEntry
) {
398 TypeEntry
->setId(TypeEntries
.size() + 1);
399 uint32_t Id
= TypeEntry
->getId();
400 TypeEntries
.push_back(std::move(TypeEntry
));
404 void BTFDebug::visitBasicType(const DIBasicType
*BTy
, uint32_t &TypeId
) {
405 // Only int types are supported in BTF.
406 uint32_t Encoding
= BTy
->getEncoding();
407 if (Encoding
!= dwarf::DW_ATE_boolean
&& Encoding
!= dwarf::DW_ATE_signed
&&
408 Encoding
!= dwarf::DW_ATE_signed_char
&&
409 Encoding
!= dwarf::DW_ATE_unsigned
&&
410 Encoding
!= dwarf::DW_ATE_unsigned_char
)
413 // Create a BTF type instance for this DIBasicType and put it into
414 // DIToIdMap for cross-type reference check.
415 auto TypeEntry
= std::make_unique
<BTFTypeInt
>(
416 Encoding
, BTy
->getSizeInBits(), BTy
->getOffsetInBits(), BTy
->getName());
417 TypeId
= addType(std::move(TypeEntry
), BTy
);
420 /// Handle subprogram or subroutine types.
421 void BTFDebug::visitSubroutineType(
422 const DISubroutineType
*STy
, bool ForSubprog
,
423 const std::unordered_map
<uint32_t, StringRef
> &FuncArgNames
,
425 DITypeRefArray Elements
= STy
->getTypeArray();
426 uint32_t VLen
= Elements
.size() - 1;
427 if (VLen
> BTF::MAX_VLEN
)
430 // Subprogram has a valid non-zero-length name, and the pointee of
431 // a function pointer has an empty name. The subprogram type will
432 // not be added to DIToIdMap as it should not be referenced by
434 auto TypeEntry
= std::make_unique
<BTFTypeFuncProto
>(STy
, VLen
, FuncArgNames
);
436 TypeId
= addType(std::move(TypeEntry
)); // For subprogram
438 TypeId
= addType(std::move(TypeEntry
), STy
); // For func ptr
440 // Visit return type and func arg types.
441 for (const auto Element
: Elements
) {
442 visitTypeEntry(Element
);
446 /// Handle structure/union types.
447 void BTFDebug::visitStructType(const DICompositeType
*CTy
, bool IsStruct
,
449 const DINodeArray Elements
= CTy
->getElements();
450 uint32_t VLen
= Elements
.size();
451 if (VLen
> BTF::MAX_VLEN
)
454 // Check whether we have any bitfield members or not
455 bool HasBitField
= false;
456 for (const auto *Element
: Elements
) {
457 auto E
= cast
<DIDerivedType
>(Element
);
458 if (E
->isBitField()) {
465 std::make_unique
<BTFTypeStruct
>(CTy
, IsStruct
, HasBitField
, VLen
);
466 StructTypes
.push_back(TypeEntry
.get());
467 TypeId
= addType(std::move(TypeEntry
), CTy
);
469 // Visit all struct members.
470 for (const auto *Element
: Elements
)
471 visitTypeEntry(cast
<DIDerivedType
>(Element
));
474 void BTFDebug::visitArrayType(const DICompositeType
*CTy
, uint32_t &TypeId
) {
475 // Visit array element type.
477 const DIType
*ElemType
= CTy
->getBaseType();
478 visitTypeEntry(ElemType
, ElemTypeId
, false, false);
480 // Visit array dimensions.
481 DINodeArray Elements
= CTy
->getElements();
482 for (int I
= Elements
.size() - 1; I
>= 0; --I
) {
483 if (auto *Element
= dyn_cast_or_null
<DINode
>(Elements
[I
]))
484 if (Element
->getTag() == dwarf::DW_TAG_subrange_type
) {
485 const DISubrange
*SR
= cast
<DISubrange
>(Element
);
486 auto *CI
= SR
->getCount().dyn_cast
<ConstantInt
*>();
487 int64_t Count
= CI
->getSExtValue();
489 // For struct s { int b; char c[]; }, the c[] will be represented
490 // as an array with Count = -1.
492 std::make_unique
<BTFTypeArray
>(ElemTypeId
,
493 Count
>= 0 ? Count
: 0);
495 ElemTypeId
= addType(std::move(TypeEntry
), CTy
);
497 ElemTypeId
= addType(std::move(TypeEntry
));
501 // The array TypeId is the type id of the outermost dimension.
504 // The IR does not have a type for array index while BTF wants one.
505 // So create an array index type if there is none.
506 if (!ArrayIndexTypeId
) {
507 auto TypeEntry
= std::make_unique
<BTFTypeInt
>(dwarf::DW_ATE_unsigned
, 32,
508 0, "__ARRAY_SIZE_TYPE__");
509 ArrayIndexTypeId
= addType(std::move(TypeEntry
));
513 void BTFDebug::visitEnumType(const DICompositeType
*CTy
, uint32_t &TypeId
) {
514 DINodeArray Elements
= CTy
->getElements();
515 uint32_t VLen
= Elements
.size();
516 if (VLen
> BTF::MAX_VLEN
)
519 auto TypeEntry
= std::make_unique
<BTFTypeEnum
>(CTy
, VLen
);
520 TypeId
= addType(std::move(TypeEntry
), CTy
);
521 // No need to visit base type as BTF does not encode it.
524 /// Handle structure/union forward declarations.
525 void BTFDebug::visitFwdDeclType(const DICompositeType
*CTy
, bool IsUnion
,
527 auto TypeEntry
= std::make_unique
<BTFTypeFwd
>(CTy
->getName(), IsUnion
);
528 TypeId
= addType(std::move(TypeEntry
), CTy
);
531 /// Handle structure, union, array and enumeration types.
532 void BTFDebug::visitCompositeType(const DICompositeType
*CTy
,
534 auto Tag
= CTy
->getTag();
535 if (Tag
== dwarf::DW_TAG_structure_type
|| Tag
== dwarf::DW_TAG_union_type
) {
536 // Handle forward declaration differently as it does not have members.
537 if (CTy
->isForwardDecl())
538 visitFwdDeclType(CTy
, Tag
== dwarf::DW_TAG_union_type
, TypeId
);
540 visitStructType(CTy
, Tag
== dwarf::DW_TAG_structure_type
, TypeId
);
541 } else if (Tag
== dwarf::DW_TAG_array_type
)
542 visitArrayType(CTy
, TypeId
);
543 else if (Tag
== dwarf::DW_TAG_enumeration_type
)
544 visitEnumType(CTy
, TypeId
);
547 /// Handle pointer, typedef, const, volatile, restrict and member types.
548 void BTFDebug::visitDerivedType(const DIDerivedType
*DTy
, uint32_t &TypeId
,
549 bool CheckPointer
, bool SeenPointer
) {
550 unsigned Tag
= DTy
->getTag();
552 /// Try to avoid chasing pointees, esp. structure pointees which may
553 /// unnecessary bring in a lot of types.
554 if (CheckPointer
&& !SeenPointer
) {
555 SeenPointer
= Tag
== dwarf::DW_TAG_pointer_type
;
558 if (CheckPointer
&& SeenPointer
) {
559 const DIType
*Base
= DTy
->getBaseType();
561 if (const auto *CTy
= dyn_cast
<DICompositeType
>(Base
)) {
562 auto CTag
= CTy
->getTag();
563 if ((CTag
== dwarf::DW_TAG_structure_type
||
564 CTag
== dwarf::DW_TAG_union_type
) &&
565 !CTy
->isForwardDecl()) {
566 /// Find a candidate, generate a fixup. Later on the struct/union
567 /// pointee type will be replaced with either a real type or
568 /// a forward declaration.
569 auto TypeEntry
= std::make_unique
<BTFTypeDerived
>(DTy
, Tag
, true);
570 auto &Fixup
= FixupDerivedTypes
[CTy
->getName()];
571 Fixup
.first
= CTag
== dwarf::DW_TAG_union_type
;
572 Fixup
.second
.push_back(TypeEntry
.get());
573 TypeId
= addType(std::move(TypeEntry
), DTy
);
580 if (Tag
== dwarf::DW_TAG_pointer_type
|| Tag
== dwarf::DW_TAG_typedef
||
581 Tag
== dwarf::DW_TAG_const_type
|| Tag
== dwarf::DW_TAG_volatile_type
||
582 Tag
== dwarf::DW_TAG_restrict_type
) {
583 auto TypeEntry
= std::make_unique
<BTFTypeDerived
>(DTy
, Tag
, false);
584 TypeId
= addType(std::move(TypeEntry
), DTy
);
585 } else if (Tag
!= dwarf::DW_TAG_member
) {
589 // Visit base type of pointer, typedef, const, volatile, restrict or
590 // struct/union member.
591 uint32_t TempTypeId
= 0;
592 if (Tag
== dwarf::DW_TAG_member
)
593 visitTypeEntry(DTy
->getBaseType(), TempTypeId
, true, false);
595 visitTypeEntry(DTy
->getBaseType(), TempTypeId
, CheckPointer
, SeenPointer
);
598 void BTFDebug::visitTypeEntry(const DIType
*Ty
, uint32_t &TypeId
,
599 bool CheckPointer
, bool SeenPointer
) {
600 if (!Ty
|| DIToIdMap
.find(Ty
) != DIToIdMap
.end()) {
601 TypeId
= DIToIdMap
[Ty
];
605 if (const auto *BTy
= dyn_cast
<DIBasicType
>(Ty
))
606 visitBasicType(BTy
, TypeId
);
607 else if (const auto *STy
= dyn_cast
<DISubroutineType
>(Ty
))
608 visitSubroutineType(STy
, false, std::unordered_map
<uint32_t, StringRef
>(),
610 else if (const auto *CTy
= dyn_cast
<DICompositeType
>(Ty
))
611 visitCompositeType(CTy
, TypeId
);
612 else if (const auto *DTy
= dyn_cast
<DIDerivedType
>(Ty
))
613 visitDerivedType(DTy
, TypeId
, CheckPointer
, SeenPointer
);
615 llvm_unreachable("Unknown DIType");
618 void BTFDebug::visitTypeEntry(const DIType
*Ty
) {
620 visitTypeEntry(Ty
, TypeId
, false, false);
623 void BTFDebug::visitMapDefType(const DIType
*Ty
, uint32_t &TypeId
) {
624 if (!Ty
|| DIToIdMap
.find(Ty
) != DIToIdMap
.end()) {
625 TypeId
= DIToIdMap
[Ty
];
629 // MapDef type is a struct type
630 const auto *CTy
= dyn_cast
<DICompositeType
>(Ty
);
634 auto Tag
= CTy
->getTag();
635 if (Tag
!= dwarf::DW_TAG_structure_type
|| CTy
->isForwardDecl())
639 const DINodeArray Elements
= CTy
->getElements();
640 bool HasBitField
= false;
641 for (const auto *Element
: Elements
) {
642 auto E
= cast
<DIDerivedType
>(Element
);
643 if (E
->isBitField()) {
650 std::make_unique
<BTFTypeStruct
>(CTy
, true, HasBitField
, Elements
.size());
651 StructTypes
.push_back(TypeEntry
.get());
652 TypeId
= addType(std::move(TypeEntry
), CTy
);
654 // Visit all struct members
655 for (const auto *Element
: Elements
) {
656 const auto *MemberType
= cast
<DIDerivedType
>(Element
);
657 visitTypeEntry(MemberType
->getBaseType());
661 /// Read file contents from the actual file or from the source
662 std::string
BTFDebug::populateFileContent(const DISubprogram
*SP
) {
663 auto File
= SP
->getFile();
664 std::string FileName
;
666 if (!File
->getFilename().startswith("/") && File
->getDirectory().size())
667 FileName
= File
->getDirectory().str() + "/" + File
->getFilename().str();
669 FileName
= File
->getFilename();
671 // No need to populate the contends if it has been populated!
672 if (FileContent
.find(FileName
) != FileContent
.end())
675 std::vector
<std::string
> Content
;
677 Content
.push_back(Line
); // Line 0 for empty string
679 std::unique_ptr
<MemoryBuffer
> Buf
;
680 auto Source
= File
->getSource();
682 Buf
= MemoryBuffer::getMemBufferCopy(*Source
);
683 else if (ErrorOr
<std::unique_ptr
<MemoryBuffer
>> BufOrErr
=
684 MemoryBuffer::getFile(FileName
))
685 Buf
= std::move(*BufOrErr
);
687 for (line_iterator
I(*Buf
, false), E
; I
!= E
; ++I
)
688 Content
.push_back(*I
);
690 FileContent
[FileName
] = Content
;
694 void BTFDebug::constructLineInfo(const DISubprogram
*SP
, MCSymbol
*Label
,
695 uint32_t Line
, uint32_t Column
) {
696 std::string FileName
= populateFileContent(SP
);
697 BTFLineInfo LineInfo
;
699 LineInfo
.Label
= Label
;
700 LineInfo
.FileNameOff
= addString(FileName
);
701 // If file content is not available, let LineOff = 0.
702 if (Line
< FileContent
[FileName
].size())
703 LineInfo
.LineOff
= addString(FileContent
[FileName
][Line
]);
705 LineInfo
.LineOff
= 0;
706 LineInfo
.LineNum
= Line
;
707 LineInfo
.ColumnNum
= Column
;
708 LineInfoTable
[SecNameOff
].push_back(LineInfo
);
711 void BTFDebug::emitCommonHeader() {
712 OS
.AddComment("0x" + Twine::utohexstr(BTF::MAGIC
));
713 OS
.EmitIntValue(BTF::MAGIC
, 2);
714 OS
.EmitIntValue(BTF::VERSION
, 1);
715 OS
.EmitIntValue(0, 1);
718 void BTFDebug::emitBTFSection() {
719 // Do not emit section if no types and only "" string.
720 if (!TypeEntries
.size() && StringTable
.getSize() == 1)
723 MCContext
&Ctx
= OS
.getContext();
724 OS
.SwitchSection(Ctx
.getELFSection(".BTF", ELF::SHT_PROGBITS
, 0));
728 OS
.EmitIntValue(BTF::HeaderSize
, 4);
730 uint32_t TypeLen
= 0, StrLen
;
731 for (const auto &TypeEntry
: TypeEntries
)
732 TypeLen
+= TypeEntry
->getSize();
733 StrLen
= StringTable
.getSize();
735 OS
.EmitIntValue(0, 4);
736 OS
.EmitIntValue(TypeLen
, 4);
737 OS
.EmitIntValue(TypeLen
, 4);
738 OS
.EmitIntValue(StrLen
, 4);
741 for (const auto &TypeEntry
: TypeEntries
)
742 TypeEntry
->emitType(OS
);
744 // Emit string table.
745 uint32_t StringOffset
= 0;
746 for (const auto &S
: StringTable
.getTable()) {
747 OS
.AddComment("string offset=" + std::to_string(StringOffset
));
749 OS
.EmitBytes(StringRef("\0", 1));
750 StringOffset
+= S
.size() + 1;
754 void BTFDebug::emitBTFExtSection() {
755 // Do not emit section if empty FuncInfoTable and LineInfoTable.
756 if (!FuncInfoTable
.size() && !LineInfoTable
.size() &&
757 !FieldRelocTable
.size() && !ExternRelocTable
.size())
760 MCContext
&Ctx
= OS
.getContext();
761 OS
.SwitchSection(Ctx
.getELFSection(".BTF.ext", ELF::SHT_PROGBITS
, 0));
765 OS
.EmitIntValue(BTF::ExtHeaderSize
, 4);
767 // Account for FuncInfo/LineInfo record size as well.
768 uint32_t FuncLen
= 4, LineLen
= 4;
769 // Do not account for optional FieldReloc/ExternReloc.
770 uint32_t FieldRelocLen
= 0, ExternRelocLen
= 0;
771 for (const auto &FuncSec
: FuncInfoTable
) {
772 FuncLen
+= BTF::SecFuncInfoSize
;
773 FuncLen
+= FuncSec
.second
.size() * BTF::BPFFuncInfoSize
;
775 for (const auto &LineSec
: LineInfoTable
) {
776 LineLen
+= BTF::SecLineInfoSize
;
777 LineLen
+= LineSec
.second
.size() * BTF::BPFLineInfoSize
;
779 for (const auto &FieldRelocSec
: FieldRelocTable
) {
780 FieldRelocLen
+= BTF::SecFieldRelocSize
;
781 FieldRelocLen
+= FieldRelocSec
.second
.size() * BTF::BPFFieldRelocSize
;
783 for (const auto &ExternRelocSec
: ExternRelocTable
) {
784 ExternRelocLen
+= BTF::SecExternRelocSize
;
785 ExternRelocLen
+= ExternRelocSec
.second
.size() * BTF::BPFExternRelocSize
;
793 OS
.EmitIntValue(0, 4);
794 OS
.EmitIntValue(FuncLen
, 4);
795 OS
.EmitIntValue(FuncLen
, 4);
796 OS
.EmitIntValue(LineLen
, 4);
797 OS
.EmitIntValue(FuncLen
+ LineLen
, 4);
798 OS
.EmitIntValue(FieldRelocLen
, 4);
799 OS
.EmitIntValue(FuncLen
+ LineLen
+ FieldRelocLen
, 4);
800 OS
.EmitIntValue(ExternRelocLen
, 4);
802 // Emit func_info table.
803 OS
.AddComment("FuncInfo");
804 OS
.EmitIntValue(BTF::BPFFuncInfoSize
, 4);
805 for (const auto &FuncSec
: FuncInfoTable
) {
806 OS
.AddComment("FuncInfo section string offset=" +
807 std::to_string(FuncSec
.first
));
808 OS
.EmitIntValue(FuncSec
.first
, 4);
809 OS
.EmitIntValue(FuncSec
.second
.size(), 4);
810 for (const auto &FuncInfo
: FuncSec
.second
) {
811 Asm
->EmitLabelReference(FuncInfo
.Label
, 4);
812 OS
.EmitIntValue(FuncInfo
.TypeId
, 4);
816 // Emit line_info table.
817 OS
.AddComment("LineInfo");
818 OS
.EmitIntValue(BTF::BPFLineInfoSize
, 4);
819 for (const auto &LineSec
: LineInfoTable
) {
820 OS
.AddComment("LineInfo section string offset=" +
821 std::to_string(LineSec
.first
));
822 OS
.EmitIntValue(LineSec
.first
, 4);
823 OS
.EmitIntValue(LineSec
.second
.size(), 4);
824 for (const auto &LineInfo
: LineSec
.second
) {
825 Asm
->EmitLabelReference(LineInfo
.Label
, 4);
826 OS
.EmitIntValue(LineInfo
.FileNameOff
, 4);
827 OS
.EmitIntValue(LineInfo
.LineOff
, 4);
828 OS
.AddComment("Line " + std::to_string(LineInfo
.LineNum
) + " Col " +
829 std::to_string(LineInfo
.ColumnNum
));
830 OS
.EmitIntValue(LineInfo
.LineNum
<< 10 | LineInfo
.ColumnNum
, 4);
834 // Emit field reloc table.
836 OS
.AddComment("FieldReloc");
837 OS
.EmitIntValue(BTF::BPFFieldRelocSize
, 4);
838 for (const auto &FieldRelocSec
: FieldRelocTable
) {
839 OS
.AddComment("Field reloc section string offset=" +
840 std::to_string(FieldRelocSec
.first
));
841 OS
.EmitIntValue(FieldRelocSec
.first
, 4);
842 OS
.EmitIntValue(FieldRelocSec
.second
.size(), 4);
843 for (const auto &FieldRelocInfo
: FieldRelocSec
.second
) {
844 Asm
->EmitLabelReference(FieldRelocInfo
.Label
, 4);
845 OS
.EmitIntValue(FieldRelocInfo
.TypeID
, 4);
846 OS
.EmitIntValue(FieldRelocInfo
.OffsetNameOff
, 4);
847 OS
.EmitIntValue(FieldRelocInfo
.RelocKind
, 4);
852 // Emit extern reloc table.
853 if (ExternRelocLen
) {
854 OS
.AddComment("ExternReloc");
855 OS
.EmitIntValue(BTF::BPFExternRelocSize
, 4);
856 for (const auto &ExternRelocSec
: ExternRelocTable
) {
857 OS
.AddComment("Extern reloc section string offset=" +
858 std::to_string(ExternRelocSec
.first
));
859 OS
.EmitIntValue(ExternRelocSec
.first
, 4);
860 OS
.EmitIntValue(ExternRelocSec
.second
.size(), 4);
861 for (const auto &ExternRelocInfo
: ExternRelocSec
.second
) {
862 Asm
->EmitLabelReference(ExternRelocInfo
.Label
, 4);
863 OS
.EmitIntValue(ExternRelocInfo
.ExternNameOff
, 4);
869 void BTFDebug::beginFunctionImpl(const MachineFunction
*MF
) {
870 auto *SP
= MF
->getFunction().getSubprogram();
871 auto *Unit
= SP
->getUnit();
873 if (Unit
->getEmissionKind() == DICompileUnit::NoDebug
) {
874 SkipInstruction
= true;
877 SkipInstruction
= false;
879 // Collect MapDef types. Map definition needs to collect
880 // pointee types. Do it first. Otherwise, for the following
886 // foo(struct t *arg);
892 // } __attribute__((section(".maps"))) hash_map;
894 // If subroutine foo is traversed first, a type chain
895 // "ptr->struct m(fwd)" will be created and later on
896 // when traversing mapdef, since "ptr->struct m" exists,
897 // the traversal of "struct m" will be omitted.
898 if (MapDefNotCollected
) {
899 processGlobals(true);
900 MapDefNotCollected
= false;
903 // Collect all types locally referenced in this function.
904 // Use RetainedNodes so we can collect all argument names
905 // even if the argument is not used.
906 std::unordered_map
<uint32_t, StringRef
> FuncArgNames
;
907 for (const DINode
*DN
: SP
->getRetainedNodes()) {
908 if (const auto *DV
= dyn_cast
<DILocalVariable
>(DN
)) {
909 // Collect function arguments for subprogram func type.
910 uint32_t Arg
= DV
->getArg();
912 visitTypeEntry(DV
->getType());
913 FuncArgNames
[Arg
] = DV
->getName();
918 // Construct subprogram func proto type.
919 uint32_t ProtoTypeId
;
920 visitSubroutineType(SP
->getType(), true, FuncArgNames
, ProtoTypeId
);
922 // Construct subprogram func type
924 std::make_unique
<BTFTypeFunc
>(SP
->getName(), ProtoTypeId
);
925 uint32_t FuncTypeId
= addType(std::move(FuncTypeEntry
));
927 for (const auto &TypeEntry
: TypeEntries
)
928 TypeEntry
->completeType(*this);
930 // Construct funcinfo and the first lineinfo for the function.
931 MCSymbol
*FuncLabel
= Asm
->getFunctionBegin();
932 BTFFuncInfo FuncInfo
;
933 FuncInfo
.Label
= FuncLabel
;
934 FuncInfo
.TypeId
= FuncTypeId
;
935 if (FuncLabel
->isInSection()) {
936 MCSection
&Section
= FuncLabel
->getSection();
937 const MCSectionELF
*SectionELF
= dyn_cast
<MCSectionELF
>(&Section
);
938 assert(SectionELF
&& "Null section for Function Label");
939 SecNameOff
= addString(SectionELF
->getSectionName());
941 SecNameOff
= addString(".text");
943 FuncInfoTable
[SecNameOff
].push_back(FuncInfo
);
946 void BTFDebug::endFunctionImpl(const MachineFunction
*MF
) {
947 SkipInstruction
= false;
948 LineInfoGenerated
= false;
952 /// On-demand populate struct types as requested from abstract member
954 unsigned BTFDebug::populateStructType(const DIType
*Ty
) {
956 visitTypeEntry(Ty
, Id
, false, false);
957 for (const auto &TypeEntry
: TypeEntries
)
958 TypeEntry
->completeType(*this);
962 /// Generate a struct member field relocation.
963 void BTFDebug::generateFieldReloc(const MachineInstr
*MI
,
964 const MCSymbol
*ORSym
, DIType
*RootTy
,
965 StringRef AccessPattern
) {
966 unsigned RootId
= populateStructType(RootTy
);
967 size_t FirstDollar
= AccessPattern
.find_first_of('$');
968 size_t FirstColon
= AccessPattern
.find_first_of(':');
969 size_t SecondColon
= AccessPattern
.find_first_of(':', FirstColon
+ 1);
970 StringRef IndexPattern
= AccessPattern
.substr(FirstDollar
+ 1);
971 StringRef RelocKindStr
= AccessPattern
.substr(FirstColon
+ 1,
972 SecondColon
- FirstColon
);
973 StringRef PatchImmStr
= AccessPattern
.substr(SecondColon
+ 1,
974 FirstDollar
- SecondColon
);
976 BTFFieldReloc FieldReloc
;
977 FieldReloc
.Label
= ORSym
;
978 FieldReloc
.OffsetNameOff
= addString(IndexPattern
);
979 FieldReloc
.TypeID
= RootId
;
980 FieldReloc
.RelocKind
= std::stoull(RelocKindStr
);
981 PatchImms
[AccessPattern
.str()] = std::stoul(PatchImmStr
);
982 FieldRelocTable
[SecNameOff
].push_back(FieldReloc
);
985 void BTFDebug::processLDimm64(const MachineInstr
*MI
) {
986 // If the insn is an LD_imm64, the following two cases
987 // will generate an .BTF.ext record.
989 // If the insn is "r2 = LD_imm64 @__BTF_...",
990 // add this insn into the .BTF.ext FieldReloc subsection.
991 // Relocation looks like:
996 // Later, the insn is replaced with "r2 = <offset>"
997 // where "<offset>" equals to the offset based on current
1000 // If the insn is "r2 = LD_imm64 @VAR" and VAR is
1001 // a patchable external global, add this insn into the .BTF.ext
1002 // ExternReloc subsection.
1003 // Relocation looks like:
1007 // Later, the insn is replaced with "r2 = <value>" or
1008 // "LD_imm64 r2, <value>" where "<value>" = 0.
1010 // check whether this is a candidate or not
1011 const MachineOperand
&MO
= MI
->getOperand(1);
1012 if (MO
.isGlobal()) {
1013 const GlobalValue
*GVal
= MO
.getGlobal();
1014 auto *GVar
= dyn_cast
<GlobalVariable
>(GVal
);
1015 if (GVar
&& GVar
->hasAttribute(BPFCoreSharedInfo::AmaAttr
)) {
1016 MCSymbol
*ORSym
= OS
.getContext().createTempSymbol();
1017 OS
.EmitLabel(ORSym
);
1019 MDNode
*MDN
= GVar
->getMetadata(LLVMContext::MD_preserve_access_index
);
1020 DIType
*Ty
= dyn_cast
<DIType
>(MDN
);
1021 generateFieldReloc(MI
, ORSym
, Ty
, GVar
->getName());
1022 } else if (GVar
&& !GVar
->hasInitializer() && GVar
->hasExternalLinkage() &&
1023 GVar
->getSection() == BPFCoreSharedInfo::PatchableExtSecName
) {
1024 MCSymbol
*ORSym
= OS
.getContext().createTempSymbol();
1025 OS
.EmitLabel(ORSym
);
1027 BTFExternReloc ExternReloc
;
1028 ExternReloc
.Label
= ORSym
;
1029 ExternReloc
.ExternNameOff
= addString(GVar
->getName());
1030 ExternRelocTable
[SecNameOff
].push_back(ExternReloc
);
1035 void BTFDebug::beginInstruction(const MachineInstr
*MI
) {
1036 DebugHandlerBase::beginInstruction(MI
);
1038 if (SkipInstruction
|| MI
->isMetaInstruction() ||
1039 MI
->getFlag(MachineInstr::FrameSetup
))
1042 if (MI
->isInlineAsm()) {
1043 // Count the number of register definitions to find the asm string.
1044 unsigned NumDefs
= 0;
1045 for (; MI
->getOperand(NumDefs
).isReg() && MI
->getOperand(NumDefs
).isDef();
1049 // Skip this inline asm instruction if the asmstr is empty.
1050 const char *AsmStr
= MI
->getOperand(NumDefs
).getSymbolName();
1055 if (MI
->getOpcode() == BPF::LD_imm64
)
1058 // Skip this instruction if no DebugLoc or the DebugLoc
1059 // is the same as the previous instruction.
1060 const DebugLoc
&DL
= MI
->getDebugLoc();
1061 if (!DL
|| PrevInstLoc
== DL
) {
1062 // This instruction will be skipped, no LineInfo has
1063 // been generated, construct one based on function signature.
1064 if (LineInfoGenerated
== false) {
1065 auto *S
= MI
->getMF()->getFunction().getSubprogram();
1066 MCSymbol
*FuncLabel
= Asm
->getFunctionBegin();
1067 constructLineInfo(S
, FuncLabel
, S
->getLine(), 0);
1068 LineInfoGenerated
= true;
1074 // Create a temporary label to remember the insn for lineinfo.
1075 MCSymbol
*LineSym
= OS
.getContext().createTempSymbol();
1076 OS
.EmitLabel(LineSym
);
1078 // Construct the lineinfo.
1079 auto SP
= DL
.get()->getScope()->getSubprogram();
1080 constructLineInfo(SP
, LineSym
, DL
.getLine(), DL
.getCol());
1082 LineInfoGenerated
= true;
1086 void BTFDebug::processGlobals(bool ProcessingMapDef
) {
1087 // Collect all types referenced by globals.
1088 const Module
*M
= MMI
->getModule();
1089 for (const GlobalVariable
&Global
: M
->globals()) {
1090 // Ignore external globals for now.
1091 if (!Global
.hasInitializer() && Global
.hasExternalLinkage())
1094 // Decide the section name.
1096 if (Global
.hasSection()) {
1097 SecName
= Global
.getSection();
1099 // data, bss, or readonly sections
1100 if (Global
.isConstant())
1101 SecName
= ".rodata";
1103 SecName
= Global
.getInitializer()->isZeroValue() ? ".bss" : ".data";
1106 if (ProcessingMapDef
!= SecName
.startswith(".maps"))
1109 SmallVector
<DIGlobalVariableExpression
*, 1> GVs
;
1110 Global
.getDebugInfo(GVs
);
1111 uint32_t GVTypeId
= 0;
1112 for (auto *GVE
: GVs
) {
1113 if (SecName
.startswith(".maps"))
1114 visitMapDefType(GVE
->getVariable()->getType(), GVTypeId
);
1116 visitTypeEntry(GVE
->getVariable()->getType(), GVTypeId
, false, false);
1120 // Only support the following globals:
1121 // . static variables
1122 // . non-static global variables with section attributes
1123 // Essentially means:
1124 // . .bcc/.data/.rodata DataSec entities only contain static data
1125 // . Other DataSec entities contain static or initialized global data.
1126 // Initialized global data are mostly used for finding map key/value type
1127 // id's. Whether DataSec is readonly or not can be found from
1128 // corresponding ELF section flags.
1129 auto Linkage
= Global
.getLinkage();
1130 if (Linkage
!= GlobalValue::InternalLinkage
&&
1131 (Linkage
!= GlobalValue::ExternalLinkage
|| !Global
.hasSection()))
1134 uint32_t GVarInfo
= Linkage
== GlobalValue::ExternalLinkage
1135 ? BTF::VAR_GLOBAL_ALLOCATED
1138 std::make_unique
<BTFKindVar
>(Global
.getName(), GVTypeId
, GVarInfo
);
1139 uint32_t VarId
= addType(std::move(VarEntry
));
1141 // Find or create a DataSec
1142 if (DataSecEntries
.find(SecName
) == DataSecEntries
.end()) {
1143 DataSecEntries
[SecName
] = std::make_unique
<BTFKindDataSec
>(Asm
, SecName
);
1146 // Calculate symbol size
1147 const DataLayout
&DL
= Global
.getParent()->getDataLayout();
1148 uint32_t Size
= DL
.getTypeAllocSize(Global
.getType()->getElementType());
1150 DataSecEntries
[SecName
]->addVar(VarId
, Asm
->getSymbol(&Global
), Size
);
1154 /// Emit proper patchable instructions.
1155 bool BTFDebug::InstLower(const MachineInstr
*MI
, MCInst
&OutMI
) {
1156 if (MI
->getOpcode() == BPF::LD_imm64
) {
1157 const MachineOperand
&MO
= MI
->getOperand(1);
1158 if (MO
.isGlobal()) {
1159 const GlobalValue
*GVal
= MO
.getGlobal();
1160 auto *GVar
= dyn_cast
<GlobalVariable
>(GVal
);
1161 if (GVar
&& GVar
->hasAttribute(BPFCoreSharedInfo::AmaAttr
)) {
1162 // Emit "mov ri, <imm>" for patched immediate.
1163 uint32_t Imm
= PatchImms
[GVar
->getName().str()];
1164 OutMI
.setOpcode(BPF::MOV_ri
);
1165 OutMI
.addOperand(MCOperand::createReg(MI
->getOperand(0).getReg()));
1166 OutMI
.addOperand(MCOperand::createImm(Imm
));
1168 } else if (GVar
&& !GVar
->hasInitializer() &&
1169 GVar
->hasExternalLinkage() &&
1170 GVar
->getSection() == BPFCoreSharedInfo::PatchableExtSecName
) {
1171 const IntegerType
*IntTy
= dyn_cast
<IntegerType
>(GVar
->getValueType());
1173 // For patchable externals, emit "LD_imm64, ri, 0" if the external
1174 // variable is 64bit width, emit "mov ri, 0" otherwise.
1175 if (IntTy
->getBitWidth() == 64)
1176 OutMI
.setOpcode(BPF::LD_imm64
);
1178 OutMI
.setOpcode(BPF::MOV_ri
);
1179 OutMI
.addOperand(MCOperand::createReg(MI
->getOperand(0).getReg()));
1180 OutMI
.addOperand(MCOperand::createImm(0));
1188 void BTFDebug::endModule() {
1189 // Collect MapDef globals if not collected yet.
1190 if (MapDefNotCollected
) {
1191 processGlobals(true);
1192 MapDefNotCollected
= false;
1195 // Collect global types/variables except MapDef globals.
1196 processGlobals(false);
1197 for (auto &DataSec
: DataSecEntries
)
1198 addType(std::move(DataSec
.second
));
1201 for (auto &Fixup
: FixupDerivedTypes
) {
1202 StringRef TypeName
= Fixup
.first
;
1203 bool IsUnion
= Fixup
.second
.first
;
1205 // Search through struct types
1206 uint32_t StructTypeId
= 0;
1207 for (const auto &StructType
: StructTypes
) {
1208 if (StructType
->getName() == TypeName
) {
1209 StructTypeId
= StructType
->getId();
1214 if (StructTypeId
== 0) {
1215 auto FwdTypeEntry
= std::make_unique
<BTFTypeFwd
>(TypeName
, IsUnion
);
1216 StructTypeId
= addType(std::move(FwdTypeEntry
));
1219 for (auto &DType
: Fixup
.second
.second
) {
1220 DType
->setPointeeType(StructTypeId
);
1224 // Complete BTF type cross refereences.
1225 for (const auto &TypeEntry
: TypeEntries
)
1226 TypeEntry
->completeType(*this);
1228 // Emit BTF sections.
1230 emitBTFExtSection();