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.
476 uint32_t ElemTypeId
, ElemSize
;
477 const DIType
*ElemType
= CTy
->getBaseType();
478 visitTypeEntry(ElemType
, ElemTypeId
, false, false);
480 // Strip qualifiers from element type to get accurate element size.
481 ElemSize
= ElemType
->getSizeInBits() >> 3;
483 if (!CTy
->getSizeInBits()) {
484 auto TypeEntry
= std::make_unique
<BTFTypeArray
>(ElemTypeId
, 0);
485 ElemTypeId
= addType(std::move(TypeEntry
), CTy
);
487 // Visit array dimensions.
488 DINodeArray Elements
= CTy
->getElements();
489 for (int I
= Elements
.size() - 1; I
>= 0; --I
) {
490 if (auto *Element
= dyn_cast_or_null
<DINode
>(Elements
[I
]))
491 if (Element
->getTag() == dwarf::DW_TAG_subrange_type
) {
492 const DISubrange
*SR
= cast
<DISubrange
>(Element
);
493 auto *CI
= SR
->getCount().dyn_cast
<ConstantInt
*>();
494 int64_t Count
= CI
->getSExtValue();
497 std::make_unique
<BTFTypeArray
>(ElemTypeId
, Count
);
499 ElemTypeId
= addType(std::move(TypeEntry
), CTy
);
501 ElemTypeId
= addType(std::move(TypeEntry
));
502 ElemSize
= ElemSize
* Count
;
507 // The array TypeId is the type id of the outermost dimension.
510 // The IR does not have a type for array index while BTF wants one.
511 // So create an array index type if there is none.
512 if (!ArrayIndexTypeId
) {
513 auto TypeEntry
= std::make_unique
<BTFTypeInt
>(dwarf::DW_ATE_unsigned
, 32,
514 0, "__ARRAY_SIZE_TYPE__");
515 ArrayIndexTypeId
= addType(std::move(TypeEntry
));
519 void BTFDebug::visitEnumType(const DICompositeType
*CTy
, uint32_t &TypeId
) {
520 DINodeArray Elements
= CTy
->getElements();
521 uint32_t VLen
= Elements
.size();
522 if (VLen
> BTF::MAX_VLEN
)
525 auto TypeEntry
= std::make_unique
<BTFTypeEnum
>(CTy
, VLen
);
526 TypeId
= addType(std::move(TypeEntry
), CTy
);
527 // No need to visit base type as BTF does not encode it.
530 /// Handle structure/union forward declarations.
531 void BTFDebug::visitFwdDeclType(const DICompositeType
*CTy
, bool IsUnion
,
533 auto TypeEntry
= std::make_unique
<BTFTypeFwd
>(CTy
->getName(), IsUnion
);
534 TypeId
= addType(std::move(TypeEntry
), CTy
);
537 /// Handle structure, union, array and enumeration types.
538 void BTFDebug::visitCompositeType(const DICompositeType
*CTy
,
540 auto Tag
= CTy
->getTag();
541 if (Tag
== dwarf::DW_TAG_structure_type
|| Tag
== dwarf::DW_TAG_union_type
) {
542 // Handle forward declaration differently as it does not have members.
543 if (CTy
->isForwardDecl())
544 visitFwdDeclType(CTy
, Tag
== dwarf::DW_TAG_union_type
, TypeId
);
546 visitStructType(CTy
, Tag
== dwarf::DW_TAG_structure_type
, TypeId
);
547 } else if (Tag
== dwarf::DW_TAG_array_type
)
548 visitArrayType(CTy
, TypeId
);
549 else if (Tag
== dwarf::DW_TAG_enumeration_type
)
550 visitEnumType(CTy
, TypeId
);
553 /// Handle pointer, typedef, const, volatile, restrict and member types.
554 void BTFDebug::visitDerivedType(const DIDerivedType
*DTy
, uint32_t &TypeId
,
555 bool CheckPointer
, bool SeenPointer
) {
556 unsigned Tag
= DTy
->getTag();
558 /// Try to avoid chasing pointees, esp. structure pointees which may
559 /// unnecessary bring in a lot of types.
560 if (CheckPointer
&& !SeenPointer
) {
561 SeenPointer
= Tag
== dwarf::DW_TAG_pointer_type
;
564 if (CheckPointer
&& SeenPointer
) {
565 const DIType
*Base
= DTy
->getBaseType();
567 if (const auto *CTy
= dyn_cast
<DICompositeType
>(Base
)) {
568 auto CTag
= CTy
->getTag();
569 if ((CTag
== dwarf::DW_TAG_structure_type
||
570 CTag
== dwarf::DW_TAG_union_type
) &&
571 !CTy
->isForwardDecl()) {
572 /// Find a candidate, generate a fixup. Later on the struct/union
573 /// pointee type will be replaced with either a real type or
574 /// a forward declaration.
575 auto TypeEntry
= std::make_unique
<BTFTypeDerived
>(DTy
, Tag
, true);
576 auto &Fixup
= FixupDerivedTypes
[CTy
->getName()];
577 Fixup
.first
= CTag
== dwarf::DW_TAG_union_type
;
578 Fixup
.second
.push_back(TypeEntry
.get());
579 TypeId
= addType(std::move(TypeEntry
), DTy
);
586 if (Tag
== dwarf::DW_TAG_pointer_type
|| Tag
== dwarf::DW_TAG_typedef
||
587 Tag
== dwarf::DW_TAG_const_type
|| Tag
== dwarf::DW_TAG_volatile_type
||
588 Tag
== dwarf::DW_TAG_restrict_type
) {
589 auto TypeEntry
= std::make_unique
<BTFTypeDerived
>(DTy
, Tag
, false);
590 TypeId
= addType(std::move(TypeEntry
), DTy
);
591 } else if (Tag
!= dwarf::DW_TAG_member
) {
595 // Visit base type of pointer, typedef, const, volatile, restrict or
596 // struct/union member.
597 uint32_t TempTypeId
= 0;
598 if (Tag
== dwarf::DW_TAG_member
)
599 visitTypeEntry(DTy
->getBaseType(), TempTypeId
, true, false);
601 visitTypeEntry(DTy
->getBaseType(), TempTypeId
, CheckPointer
, SeenPointer
);
604 void BTFDebug::visitTypeEntry(const DIType
*Ty
, uint32_t &TypeId
,
605 bool CheckPointer
, bool SeenPointer
) {
606 if (!Ty
|| DIToIdMap
.find(Ty
) != DIToIdMap
.end()) {
607 TypeId
= DIToIdMap
[Ty
];
611 if (const auto *BTy
= dyn_cast
<DIBasicType
>(Ty
))
612 visitBasicType(BTy
, TypeId
);
613 else if (const auto *STy
= dyn_cast
<DISubroutineType
>(Ty
))
614 visitSubroutineType(STy
, false, std::unordered_map
<uint32_t, StringRef
>(),
616 else if (const auto *CTy
= dyn_cast
<DICompositeType
>(Ty
))
617 visitCompositeType(CTy
, TypeId
);
618 else if (const auto *DTy
= dyn_cast
<DIDerivedType
>(Ty
))
619 visitDerivedType(DTy
, TypeId
, CheckPointer
, SeenPointer
);
621 llvm_unreachable("Unknown DIType");
624 void BTFDebug::visitTypeEntry(const DIType
*Ty
) {
626 visitTypeEntry(Ty
, TypeId
, false, false);
629 void BTFDebug::visitMapDefType(const DIType
*Ty
, uint32_t &TypeId
) {
630 if (!Ty
|| DIToIdMap
.find(Ty
) != DIToIdMap
.end()) {
631 TypeId
= DIToIdMap
[Ty
];
635 // MapDef type is a struct type
636 const auto *CTy
= dyn_cast
<DICompositeType
>(Ty
);
640 auto Tag
= CTy
->getTag();
641 if (Tag
!= dwarf::DW_TAG_structure_type
|| CTy
->isForwardDecl())
645 const DINodeArray Elements
= CTy
->getElements();
646 bool HasBitField
= false;
647 for (const auto *Element
: Elements
) {
648 auto E
= cast
<DIDerivedType
>(Element
);
649 if (E
->isBitField()) {
656 std::make_unique
<BTFTypeStruct
>(CTy
, true, HasBitField
, Elements
.size());
657 StructTypes
.push_back(TypeEntry
.get());
658 TypeId
= addType(std::move(TypeEntry
), CTy
);
660 // Visit all struct members
661 for (const auto *Element
: Elements
) {
662 const auto *MemberType
= cast
<DIDerivedType
>(Element
);
663 visitTypeEntry(MemberType
->getBaseType());
667 /// Read file contents from the actual file or from the source
668 std::string
BTFDebug::populateFileContent(const DISubprogram
*SP
) {
669 auto File
= SP
->getFile();
670 std::string FileName
;
672 if (!File
->getFilename().startswith("/") && File
->getDirectory().size())
673 FileName
= File
->getDirectory().str() + "/" + File
->getFilename().str();
675 FileName
= File
->getFilename();
677 // No need to populate the contends if it has been populated!
678 if (FileContent
.find(FileName
) != FileContent
.end())
681 std::vector
<std::string
> Content
;
683 Content
.push_back(Line
); // Line 0 for empty string
685 std::unique_ptr
<MemoryBuffer
> Buf
;
686 auto Source
= File
->getSource();
688 Buf
= MemoryBuffer::getMemBufferCopy(*Source
);
689 else if (ErrorOr
<std::unique_ptr
<MemoryBuffer
>> BufOrErr
=
690 MemoryBuffer::getFile(FileName
))
691 Buf
= std::move(*BufOrErr
);
693 for (line_iterator
I(*Buf
, false), E
; I
!= E
; ++I
)
694 Content
.push_back(*I
);
696 FileContent
[FileName
] = Content
;
700 void BTFDebug::constructLineInfo(const DISubprogram
*SP
, MCSymbol
*Label
,
701 uint32_t Line
, uint32_t Column
) {
702 std::string FileName
= populateFileContent(SP
);
703 BTFLineInfo LineInfo
;
705 LineInfo
.Label
= Label
;
706 LineInfo
.FileNameOff
= addString(FileName
);
707 // If file content is not available, let LineOff = 0.
708 if (Line
< FileContent
[FileName
].size())
709 LineInfo
.LineOff
= addString(FileContent
[FileName
][Line
]);
711 LineInfo
.LineOff
= 0;
712 LineInfo
.LineNum
= Line
;
713 LineInfo
.ColumnNum
= Column
;
714 LineInfoTable
[SecNameOff
].push_back(LineInfo
);
717 void BTFDebug::emitCommonHeader() {
718 OS
.AddComment("0x" + Twine::utohexstr(BTF::MAGIC
));
719 OS
.EmitIntValue(BTF::MAGIC
, 2);
720 OS
.EmitIntValue(BTF::VERSION
, 1);
721 OS
.EmitIntValue(0, 1);
724 void BTFDebug::emitBTFSection() {
725 // Do not emit section if no types and only "" string.
726 if (!TypeEntries
.size() && StringTable
.getSize() == 1)
729 MCContext
&Ctx
= OS
.getContext();
730 OS
.SwitchSection(Ctx
.getELFSection(".BTF", ELF::SHT_PROGBITS
, 0));
734 OS
.EmitIntValue(BTF::HeaderSize
, 4);
736 uint32_t TypeLen
= 0, StrLen
;
737 for (const auto &TypeEntry
: TypeEntries
)
738 TypeLen
+= TypeEntry
->getSize();
739 StrLen
= StringTable
.getSize();
741 OS
.EmitIntValue(0, 4);
742 OS
.EmitIntValue(TypeLen
, 4);
743 OS
.EmitIntValue(TypeLen
, 4);
744 OS
.EmitIntValue(StrLen
, 4);
747 for (const auto &TypeEntry
: TypeEntries
)
748 TypeEntry
->emitType(OS
);
750 // Emit string table.
751 uint32_t StringOffset
= 0;
752 for (const auto &S
: StringTable
.getTable()) {
753 OS
.AddComment("string offset=" + std::to_string(StringOffset
));
755 OS
.EmitBytes(StringRef("\0", 1));
756 StringOffset
+= S
.size() + 1;
760 void BTFDebug::emitBTFExtSection() {
761 // Do not emit section if empty FuncInfoTable and LineInfoTable.
762 if (!FuncInfoTable
.size() && !LineInfoTable
.size() &&
763 !OffsetRelocTable
.size() && !ExternRelocTable
.size())
766 MCContext
&Ctx
= OS
.getContext();
767 OS
.SwitchSection(Ctx
.getELFSection(".BTF.ext", ELF::SHT_PROGBITS
, 0));
771 OS
.EmitIntValue(BTF::ExtHeaderSize
, 4);
773 // Account for FuncInfo/LineInfo record size as well.
774 uint32_t FuncLen
= 4, LineLen
= 4;
775 // Do not account for optional OffsetReloc/ExternReloc.
776 uint32_t OffsetRelocLen
= 0, ExternRelocLen
= 0;
777 for (const auto &FuncSec
: FuncInfoTable
) {
778 FuncLen
+= BTF::SecFuncInfoSize
;
779 FuncLen
+= FuncSec
.second
.size() * BTF::BPFFuncInfoSize
;
781 for (const auto &LineSec
: LineInfoTable
) {
782 LineLen
+= BTF::SecLineInfoSize
;
783 LineLen
+= LineSec
.second
.size() * BTF::BPFLineInfoSize
;
785 for (const auto &OffsetRelocSec
: OffsetRelocTable
) {
786 OffsetRelocLen
+= BTF::SecOffsetRelocSize
;
787 OffsetRelocLen
+= OffsetRelocSec
.second
.size() * BTF::BPFOffsetRelocSize
;
789 for (const auto &ExternRelocSec
: ExternRelocTable
) {
790 ExternRelocLen
+= BTF::SecExternRelocSize
;
791 ExternRelocLen
+= ExternRelocSec
.second
.size() * BTF::BPFExternRelocSize
;
799 OS
.EmitIntValue(0, 4);
800 OS
.EmitIntValue(FuncLen
, 4);
801 OS
.EmitIntValue(FuncLen
, 4);
802 OS
.EmitIntValue(LineLen
, 4);
803 OS
.EmitIntValue(FuncLen
+ LineLen
, 4);
804 OS
.EmitIntValue(OffsetRelocLen
, 4);
805 OS
.EmitIntValue(FuncLen
+ LineLen
+ OffsetRelocLen
, 4);
806 OS
.EmitIntValue(ExternRelocLen
, 4);
808 // Emit func_info table.
809 OS
.AddComment("FuncInfo");
810 OS
.EmitIntValue(BTF::BPFFuncInfoSize
, 4);
811 for (const auto &FuncSec
: FuncInfoTable
) {
812 OS
.AddComment("FuncInfo section string offset=" +
813 std::to_string(FuncSec
.first
));
814 OS
.EmitIntValue(FuncSec
.first
, 4);
815 OS
.EmitIntValue(FuncSec
.second
.size(), 4);
816 for (const auto &FuncInfo
: FuncSec
.second
) {
817 Asm
->EmitLabelReference(FuncInfo
.Label
, 4);
818 OS
.EmitIntValue(FuncInfo
.TypeId
, 4);
822 // Emit line_info table.
823 OS
.AddComment("LineInfo");
824 OS
.EmitIntValue(BTF::BPFLineInfoSize
, 4);
825 for (const auto &LineSec
: LineInfoTable
) {
826 OS
.AddComment("LineInfo section string offset=" +
827 std::to_string(LineSec
.first
));
828 OS
.EmitIntValue(LineSec
.first
, 4);
829 OS
.EmitIntValue(LineSec
.second
.size(), 4);
830 for (const auto &LineInfo
: LineSec
.second
) {
831 Asm
->EmitLabelReference(LineInfo
.Label
, 4);
832 OS
.EmitIntValue(LineInfo
.FileNameOff
, 4);
833 OS
.EmitIntValue(LineInfo
.LineOff
, 4);
834 OS
.AddComment("Line " + std::to_string(LineInfo
.LineNum
) + " Col " +
835 std::to_string(LineInfo
.ColumnNum
));
836 OS
.EmitIntValue(LineInfo
.LineNum
<< 10 | LineInfo
.ColumnNum
, 4);
840 // Emit offset reloc table.
841 if (OffsetRelocLen
) {
842 OS
.AddComment("OffsetReloc");
843 OS
.EmitIntValue(BTF::BPFOffsetRelocSize
, 4);
844 for (const auto &OffsetRelocSec
: OffsetRelocTable
) {
845 OS
.AddComment("Offset reloc section string offset=" +
846 std::to_string(OffsetRelocSec
.first
));
847 OS
.EmitIntValue(OffsetRelocSec
.first
, 4);
848 OS
.EmitIntValue(OffsetRelocSec
.second
.size(), 4);
849 for (const auto &OffsetRelocInfo
: OffsetRelocSec
.second
) {
850 Asm
->EmitLabelReference(OffsetRelocInfo
.Label
, 4);
851 OS
.EmitIntValue(OffsetRelocInfo
.TypeID
, 4);
852 OS
.EmitIntValue(OffsetRelocInfo
.OffsetNameOff
, 4);
857 // Emit extern reloc table.
858 if (ExternRelocLen
) {
859 OS
.AddComment("ExternReloc");
860 OS
.EmitIntValue(BTF::BPFExternRelocSize
, 4);
861 for (const auto &ExternRelocSec
: ExternRelocTable
) {
862 OS
.AddComment("Extern reloc section string offset=" +
863 std::to_string(ExternRelocSec
.first
));
864 OS
.EmitIntValue(ExternRelocSec
.first
, 4);
865 OS
.EmitIntValue(ExternRelocSec
.second
.size(), 4);
866 for (const auto &ExternRelocInfo
: ExternRelocSec
.second
) {
867 Asm
->EmitLabelReference(ExternRelocInfo
.Label
, 4);
868 OS
.EmitIntValue(ExternRelocInfo
.ExternNameOff
, 4);
874 void BTFDebug::beginFunctionImpl(const MachineFunction
*MF
) {
875 auto *SP
= MF
->getFunction().getSubprogram();
876 auto *Unit
= SP
->getUnit();
878 if (Unit
->getEmissionKind() == DICompileUnit::NoDebug
) {
879 SkipInstruction
= true;
882 SkipInstruction
= false;
884 // Collect MapDef types. Map definition needs to collect
885 // pointee types. Do it first. Otherwise, for the following
891 // foo(struct t *arg);
897 // } __attribute__((section(".maps"))) hash_map;
899 // If subroutine foo is traversed first, a type chain
900 // "ptr->struct m(fwd)" will be created and later on
901 // when traversing mapdef, since "ptr->struct m" exists,
902 // the traversal of "struct m" will be omitted.
903 if (MapDefNotCollected
) {
904 processGlobals(true);
905 MapDefNotCollected
= false;
908 // Collect all types locally referenced in this function.
909 // Use RetainedNodes so we can collect all argument names
910 // even if the argument is not used.
911 std::unordered_map
<uint32_t, StringRef
> FuncArgNames
;
912 for (const DINode
*DN
: SP
->getRetainedNodes()) {
913 if (const auto *DV
= dyn_cast
<DILocalVariable
>(DN
)) {
914 // Collect function arguments for subprogram func type.
915 uint32_t Arg
= DV
->getArg();
917 visitTypeEntry(DV
->getType());
918 FuncArgNames
[Arg
] = DV
->getName();
923 // Construct subprogram func proto type.
924 uint32_t ProtoTypeId
;
925 visitSubroutineType(SP
->getType(), true, FuncArgNames
, ProtoTypeId
);
927 // Construct subprogram func type
929 std::make_unique
<BTFTypeFunc
>(SP
->getName(), ProtoTypeId
);
930 uint32_t FuncTypeId
= addType(std::move(FuncTypeEntry
));
932 for (const auto &TypeEntry
: TypeEntries
)
933 TypeEntry
->completeType(*this);
935 // Construct funcinfo and the first lineinfo for the function.
936 MCSymbol
*FuncLabel
= Asm
->getFunctionBegin();
937 BTFFuncInfo FuncInfo
;
938 FuncInfo
.Label
= FuncLabel
;
939 FuncInfo
.TypeId
= FuncTypeId
;
940 if (FuncLabel
->isInSection()) {
941 MCSection
&Section
= FuncLabel
->getSection();
942 const MCSectionELF
*SectionELF
= dyn_cast
<MCSectionELF
>(&Section
);
943 assert(SectionELF
&& "Null section for Function Label");
944 SecNameOff
= addString(SectionELF
->getSectionName());
946 SecNameOff
= addString(".text");
948 FuncInfoTable
[SecNameOff
].push_back(FuncInfo
);
951 void BTFDebug::endFunctionImpl(const MachineFunction
*MF
) {
952 SkipInstruction
= false;
953 LineInfoGenerated
= false;
957 /// On-demand populate struct types as requested from abstract member
959 unsigned BTFDebug::populateStructType(const DIType
*Ty
) {
961 visitTypeEntry(Ty
, Id
, false, false);
962 for (const auto &TypeEntry
: TypeEntries
)
963 TypeEntry
->completeType(*this);
967 /// Generate a struct member offset relocation.
968 void BTFDebug::generateOffsetReloc(const MachineInstr
*MI
,
969 const MCSymbol
*ORSym
, DIType
*RootTy
,
970 StringRef AccessPattern
) {
971 unsigned RootId
= populateStructType(RootTy
);
972 size_t FirstDollar
= AccessPattern
.find_first_of('$');
973 size_t FirstColon
= AccessPattern
.find_first_of(':');
974 StringRef IndexPattern
= AccessPattern
.substr(FirstDollar
+ 1);
975 StringRef OffsetStr
= AccessPattern
.substr(FirstColon
+ 1,
976 FirstDollar
- FirstColon
);
978 BTFOffsetReloc OffsetReloc
;
979 OffsetReloc
.Label
= ORSym
;
980 OffsetReloc
.OffsetNameOff
= addString(IndexPattern
);
981 OffsetReloc
.TypeID
= RootId
;
982 AccessOffsets
[AccessPattern
.str()] = std::stoi(OffsetStr
);
983 OffsetRelocTable
[SecNameOff
].push_back(OffsetReloc
);
986 void BTFDebug::processLDimm64(const MachineInstr
*MI
) {
987 // If the insn is an LD_imm64, the following two cases
988 // will generate an .BTF.ext record.
990 // If the insn is "r2 = LD_imm64 @__BTF_...",
991 // add this insn into the .BTF.ext OffsetReloc subsection.
992 // Relocation looks like:
997 // Later, the insn is replaced with "r2 = <offset>"
998 // where "<offset>" equals to the offset based on current
1001 // If the insn is "r2 = LD_imm64 @VAR" and VAR is
1002 // a patchable external global, add this insn into the .BTF.ext
1003 // ExternReloc subsection.
1004 // Relocation looks like:
1008 // Later, the insn is replaced with "r2 = <value>" or
1009 // "LD_imm64 r2, <value>" where "<value>" = 0.
1011 // check whether this is a candidate or not
1012 const MachineOperand
&MO
= MI
->getOperand(1);
1013 if (MO
.isGlobal()) {
1014 const GlobalValue
*GVal
= MO
.getGlobal();
1015 auto *GVar
= dyn_cast
<GlobalVariable
>(GVal
);
1016 if (GVar
&& GVar
->hasAttribute(BPFCoreSharedInfo::AmaAttr
)) {
1017 MCSymbol
*ORSym
= OS
.getContext().createTempSymbol();
1018 OS
.EmitLabel(ORSym
);
1020 MDNode
*MDN
= GVar
->getMetadata(LLVMContext::MD_preserve_access_index
);
1021 DIType
*Ty
= dyn_cast
<DIType
>(MDN
);
1022 generateOffsetReloc(MI
, ORSym
, Ty
, GVar
->getName());
1023 } else if (GVar
&& !GVar
->hasInitializer() && GVar
->hasExternalLinkage() &&
1024 GVar
->getSection() == BPFCoreSharedInfo::PatchableExtSecName
) {
1025 MCSymbol
*ORSym
= OS
.getContext().createTempSymbol();
1026 OS
.EmitLabel(ORSym
);
1028 BTFExternReloc ExternReloc
;
1029 ExternReloc
.Label
= ORSym
;
1030 ExternReloc
.ExternNameOff
= addString(GVar
->getName());
1031 ExternRelocTable
[SecNameOff
].push_back(ExternReloc
);
1036 void BTFDebug::beginInstruction(const MachineInstr
*MI
) {
1037 DebugHandlerBase::beginInstruction(MI
);
1039 if (SkipInstruction
|| MI
->isMetaInstruction() ||
1040 MI
->getFlag(MachineInstr::FrameSetup
))
1043 if (MI
->isInlineAsm()) {
1044 // Count the number of register definitions to find the asm string.
1045 unsigned NumDefs
= 0;
1046 for (; MI
->getOperand(NumDefs
).isReg() && MI
->getOperand(NumDefs
).isDef();
1050 // Skip this inline asm instruction if the asmstr is empty.
1051 const char *AsmStr
= MI
->getOperand(NumDefs
).getSymbolName();
1056 if (MI
->getOpcode() == BPF::LD_imm64
)
1059 // Skip this instruction if no DebugLoc or the DebugLoc
1060 // is the same as the previous instruction.
1061 const DebugLoc
&DL
= MI
->getDebugLoc();
1062 if (!DL
|| PrevInstLoc
== DL
) {
1063 // This instruction will be skipped, no LineInfo has
1064 // been generated, construct one based on function signature.
1065 if (LineInfoGenerated
== false) {
1066 auto *S
= MI
->getMF()->getFunction().getSubprogram();
1067 MCSymbol
*FuncLabel
= Asm
->getFunctionBegin();
1068 constructLineInfo(S
, FuncLabel
, S
->getLine(), 0);
1069 LineInfoGenerated
= true;
1075 // Create a temporary label to remember the insn for lineinfo.
1076 MCSymbol
*LineSym
= OS
.getContext().createTempSymbol();
1077 OS
.EmitLabel(LineSym
);
1079 // Construct the lineinfo.
1080 auto SP
= DL
.get()->getScope()->getSubprogram();
1081 constructLineInfo(SP
, LineSym
, DL
.getLine(), DL
.getCol());
1083 LineInfoGenerated
= true;
1087 void BTFDebug::processGlobals(bool ProcessingMapDef
) {
1088 // Collect all types referenced by globals.
1089 const Module
*M
= MMI
->getModule();
1090 for (const GlobalVariable
&Global
: M
->globals()) {
1091 // Ignore external globals for now.
1092 if (!Global
.hasInitializer() && Global
.hasExternalLinkage())
1095 // Decide the section name.
1097 if (Global
.hasSection()) {
1098 SecName
= Global
.getSection();
1100 // data, bss, or readonly sections
1101 if (Global
.isConstant())
1102 SecName
= ".rodata";
1104 SecName
= Global
.getInitializer()->isZeroValue() ? ".bss" : ".data";
1107 if (ProcessingMapDef
!= SecName
.startswith(".maps"))
1110 SmallVector
<DIGlobalVariableExpression
*, 1> GVs
;
1111 Global
.getDebugInfo(GVs
);
1112 uint32_t GVTypeId
= 0;
1113 for (auto *GVE
: GVs
) {
1114 if (SecName
.startswith(".maps"))
1115 visitMapDefType(GVE
->getVariable()->getType(), GVTypeId
);
1117 visitTypeEntry(GVE
->getVariable()->getType(), GVTypeId
, false, false);
1121 // Only support the following globals:
1122 // . static variables
1123 // . non-static global variables with section attributes
1124 // Essentially means:
1125 // . .bcc/.data/.rodata DataSec entities only contain static data
1126 // . Other DataSec entities contain static or initialized global data.
1127 // Initialized global data are mostly used for finding map key/value type
1128 // id's. Whether DataSec is readonly or not can be found from
1129 // corresponding ELF section flags.
1130 auto Linkage
= Global
.getLinkage();
1131 if (Linkage
!= GlobalValue::InternalLinkage
&&
1132 (Linkage
!= GlobalValue::ExternalLinkage
|| !Global
.hasSection()))
1135 uint32_t GVarInfo
= Linkage
== GlobalValue::ExternalLinkage
1136 ? BTF::VAR_GLOBAL_ALLOCATED
1139 std::make_unique
<BTFKindVar
>(Global
.getName(), GVTypeId
, GVarInfo
);
1140 uint32_t VarId
= addType(std::move(VarEntry
));
1142 // Find or create a DataSec
1143 if (DataSecEntries
.find(SecName
) == DataSecEntries
.end()) {
1144 DataSecEntries
[SecName
] = std::make_unique
<BTFKindDataSec
>(Asm
, SecName
);
1147 // Calculate symbol size
1148 const DataLayout
&DL
= Global
.getParent()->getDataLayout();
1149 uint32_t Size
= DL
.getTypeAllocSize(Global
.getType()->getElementType());
1151 DataSecEntries
[SecName
]->addVar(VarId
, Asm
->getSymbol(&Global
), Size
);
1155 /// Emit proper patchable instructions.
1156 bool BTFDebug::InstLower(const MachineInstr
*MI
, MCInst
&OutMI
) {
1157 if (MI
->getOpcode() == BPF::LD_imm64
) {
1158 const MachineOperand
&MO
= MI
->getOperand(1);
1159 if (MO
.isGlobal()) {
1160 const GlobalValue
*GVal
= MO
.getGlobal();
1161 auto *GVar
= dyn_cast
<GlobalVariable
>(GVal
);
1162 if (GVar
&& GVar
->hasAttribute(BPFCoreSharedInfo::AmaAttr
)) {
1163 MDNode
*MDN
= GVar
->getMetadata(LLVMContext::MD_preserve_access_index
);
1164 DIType
*Ty
= dyn_cast
<DIType
>(MDN
);
1165 std::string TypeName
= Ty
->getName();
1166 int64_t Imm
= AccessOffsets
[GVar
->getName().str()];
1168 // Emit "mov ri, <imm>" for abstract member accesses.
1169 OutMI
.setOpcode(BPF::MOV_ri
);
1170 OutMI
.addOperand(MCOperand::createReg(MI
->getOperand(0).getReg()));
1171 OutMI
.addOperand(MCOperand::createImm(Imm
));
1173 } else if (GVar
&& !GVar
->hasInitializer() &&
1174 GVar
->hasExternalLinkage() &&
1175 GVar
->getSection() == BPFCoreSharedInfo::PatchableExtSecName
) {
1176 const IntegerType
*IntTy
= dyn_cast
<IntegerType
>(GVar
->getValueType());
1178 // For patchable externals, emit "LD_imm64, ri, 0" if the external
1179 // variable is 64bit width, emit "mov ri, 0" otherwise.
1180 if (IntTy
->getBitWidth() == 64)
1181 OutMI
.setOpcode(BPF::LD_imm64
);
1183 OutMI
.setOpcode(BPF::MOV_ri
);
1184 OutMI
.addOperand(MCOperand::createReg(MI
->getOperand(0).getReg()));
1185 OutMI
.addOperand(MCOperand::createImm(0));
1193 void BTFDebug::endModule() {
1194 // Collect MapDef globals if not collected yet.
1195 if (MapDefNotCollected
) {
1196 processGlobals(true);
1197 MapDefNotCollected
= false;
1200 // Collect global types/variables except MapDef globals.
1201 processGlobals(false);
1202 for (auto &DataSec
: DataSecEntries
)
1203 addType(std::move(DataSec
.second
));
1206 for (auto &Fixup
: FixupDerivedTypes
) {
1207 StringRef TypeName
= Fixup
.first
;
1208 bool IsUnion
= Fixup
.second
.first
;
1210 // Search through struct types
1211 uint32_t StructTypeId
= 0;
1212 for (const auto &StructType
: StructTypes
) {
1213 if (StructType
->getName() == TypeName
) {
1214 StructTypeId
= StructType
->getId();
1219 if (StructTypeId
== 0) {
1220 auto FwdTypeEntry
= std::make_unique
<BTFTypeFwd
>(TypeName
, IsUnion
);
1221 StructTypeId
= addType(std::move(FwdTypeEntry
));
1224 for (auto &DType
: Fixup
.second
.second
) {
1225 DType
->setPointeeType(StructTypeId
);
1229 // Complete BTF type cross refereences.
1230 for (const auto &TypeEntry
: TypeEntries
)
1231 TypeEntry
->completeType(*this);
1233 // Emit BTF sections.
1235 emitBTFExtSection();