File: | build/source/llvm/lib/Target/BPF/BTFDebug.cpp |
Warning: | line 1563, column 21 2nd function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- BTFDebug.cpp - BTF Generator ---------------------------------------===// | |||
2 | // | |||
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 | |||
6 | // | |||
7 | //===----------------------------------------------------------------------===// | |||
8 | // | |||
9 | // This file contains support for writing BTF debug info. | |||
10 | // | |||
11 | //===----------------------------------------------------------------------===// | |||
12 | ||||
13 | #include "BTFDebug.h" | |||
14 | #include "BPF.h" | |||
15 | #include "BPFCORE.h" | |||
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" | |||
25 | #include "llvm/Support/MemoryBuffer.h" | |||
26 | #include "llvm/Target/TargetLoweringObjectFile.h" | |||
27 | #include <optional> | |||
28 | ||||
29 | using namespace llvm; | |||
30 | ||||
31 | static const char *BTFKindStr[] = { | |||
32 | #define HANDLE_BTF_KIND(ID, NAME) "BTF_KIND_" #NAME, | |||
33 | #include "BTF.def" | |||
34 | }; | |||
35 | ||||
36 | /// Emit a BTF common type. | |||
37 | void BTFTypeBase::emitType(MCStreamer &OS) { | |||
38 | OS.AddComment(std::string(BTFKindStr[Kind]) + "(id = " + std::to_string(Id) + | |||
39 | ")"); | |||
40 | OS.emitInt32(BTFType.NameOff); | |||
41 | OS.AddComment("0x" + Twine::utohexstr(BTFType.Info)); | |||
42 | OS.emitInt32(BTFType.Info); | |||
43 | OS.emitInt32(BTFType.Size); | |||
44 | } | |||
45 | ||||
46 | BTFTypeDerived::BTFTypeDerived(const DIDerivedType *DTy, unsigned Tag, | |||
47 | bool NeedsFixup) | |||
48 | : DTy(DTy), NeedsFixup(NeedsFixup), Name(DTy->getName()) { | |||
49 | switch (Tag) { | |||
50 | case dwarf::DW_TAG_pointer_type: | |||
51 | Kind = BTF::BTF_KIND_PTR; | |||
52 | break; | |||
53 | case dwarf::DW_TAG_const_type: | |||
54 | Kind = BTF::BTF_KIND_CONST; | |||
55 | break; | |||
56 | case dwarf::DW_TAG_volatile_type: | |||
57 | Kind = BTF::BTF_KIND_VOLATILE; | |||
58 | break; | |||
59 | case dwarf::DW_TAG_typedef: | |||
60 | Kind = BTF::BTF_KIND_TYPEDEF; | |||
61 | break; | |||
62 | case dwarf::DW_TAG_restrict_type: | |||
63 | Kind = BTF::BTF_KIND_RESTRICT; | |||
64 | break; | |||
65 | default: | |||
66 | llvm_unreachable("Unknown DIDerivedType Tag")::llvm::llvm_unreachable_internal("Unknown DIDerivedType Tag" , "llvm/lib/Target/BPF/BTFDebug.cpp", 66); | |||
67 | } | |||
68 | BTFType.Info = Kind << 24; | |||
69 | } | |||
70 | ||||
71 | /// Used by DW_TAG_pointer_type only. | |||
72 | BTFTypeDerived::BTFTypeDerived(unsigned NextTypeId, unsigned Tag, | |||
73 | StringRef Name) | |||
74 | : DTy(nullptr), NeedsFixup(false), Name(Name) { | |||
75 | Kind = BTF::BTF_KIND_PTR; | |||
76 | BTFType.Info = Kind << 24; | |||
77 | BTFType.Type = NextTypeId; | |||
78 | } | |||
79 | ||||
80 | void BTFTypeDerived::completeType(BTFDebug &BDebug) { | |||
81 | if (IsCompleted) | |||
82 | return; | |||
83 | IsCompleted = true; | |||
84 | ||||
85 | BTFType.NameOff = BDebug.addString(Name); | |||
86 | ||||
87 | if (NeedsFixup || !DTy) | |||
88 | return; | |||
89 | ||||
90 | // The base type for PTR/CONST/VOLATILE could be void. | |||
91 | const DIType *ResolvedType = DTy->getBaseType(); | |||
92 | if (!ResolvedType) { | |||
93 | assert((Kind == BTF::BTF_KIND_PTR || Kind == BTF::BTF_KIND_CONST ||(static_cast <bool> ((Kind == BTF::BTF_KIND_PTR || Kind == BTF::BTF_KIND_CONST || Kind == BTF::BTF_KIND_VOLATILE) && "Invalid null basetype") ? void (0) : __assert_fail ("(Kind == BTF::BTF_KIND_PTR || Kind == BTF::BTF_KIND_CONST || Kind == BTF::BTF_KIND_VOLATILE) && \"Invalid null basetype\"" , "llvm/lib/Target/BPF/BTFDebug.cpp", 95, __extension__ __PRETTY_FUNCTION__ )) | |||
94 | Kind == BTF::BTF_KIND_VOLATILE) &&(static_cast <bool> ((Kind == BTF::BTF_KIND_PTR || Kind == BTF::BTF_KIND_CONST || Kind == BTF::BTF_KIND_VOLATILE) && "Invalid null basetype") ? void (0) : __assert_fail ("(Kind == BTF::BTF_KIND_PTR || Kind == BTF::BTF_KIND_CONST || Kind == BTF::BTF_KIND_VOLATILE) && \"Invalid null basetype\"" , "llvm/lib/Target/BPF/BTFDebug.cpp", 95, __extension__ __PRETTY_FUNCTION__ )) | |||
95 | "Invalid null basetype")(static_cast <bool> ((Kind == BTF::BTF_KIND_PTR || Kind == BTF::BTF_KIND_CONST || Kind == BTF::BTF_KIND_VOLATILE) && "Invalid null basetype") ? void (0) : __assert_fail ("(Kind == BTF::BTF_KIND_PTR || Kind == BTF::BTF_KIND_CONST || Kind == BTF::BTF_KIND_VOLATILE) && \"Invalid null basetype\"" , "llvm/lib/Target/BPF/BTFDebug.cpp", 95, __extension__ __PRETTY_FUNCTION__ )); | |||
96 | BTFType.Type = 0; | |||
97 | } else { | |||
98 | BTFType.Type = BDebug.getTypeId(ResolvedType); | |||
99 | } | |||
100 | } | |||
101 | ||||
102 | void BTFTypeDerived::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); } | |||
103 | ||||
104 | void BTFTypeDerived::setPointeeType(uint32_t PointeeType) { | |||
105 | BTFType.Type = PointeeType; | |||
106 | } | |||
107 | ||||
108 | /// Represent a struct/union forward declaration. | |||
109 | BTFTypeFwd::BTFTypeFwd(StringRef Name, bool IsUnion) : Name(Name) { | |||
110 | Kind = BTF::BTF_KIND_FWD; | |||
111 | BTFType.Info = IsUnion << 31 | Kind << 24; | |||
112 | BTFType.Type = 0; | |||
113 | } | |||
114 | ||||
115 | void BTFTypeFwd::completeType(BTFDebug &BDebug) { | |||
116 | if (IsCompleted) | |||
117 | return; | |||
118 | IsCompleted = true; | |||
119 | ||||
120 | BTFType.NameOff = BDebug.addString(Name); | |||
121 | } | |||
122 | ||||
123 | void BTFTypeFwd::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); } | |||
124 | ||||
125 | BTFTypeInt::BTFTypeInt(uint32_t Encoding, uint32_t SizeInBits, | |||
126 | uint32_t OffsetInBits, StringRef TypeName) | |||
127 | : Name(TypeName) { | |||
128 | // Translate IR int encoding to BTF int encoding. | |||
129 | uint8_t BTFEncoding; | |||
130 | switch (Encoding) { | |||
131 | case dwarf::DW_ATE_boolean: | |||
132 | BTFEncoding = BTF::INT_BOOL; | |||
133 | break; | |||
134 | case dwarf::DW_ATE_signed: | |||
135 | case dwarf::DW_ATE_signed_char: | |||
136 | BTFEncoding = BTF::INT_SIGNED; | |||
137 | break; | |||
138 | case dwarf::DW_ATE_unsigned: | |||
139 | case dwarf::DW_ATE_unsigned_char: | |||
140 | BTFEncoding = 0; | |||
141 | break; | |||
142 | default: | |||
143 | llvm_unreachable("Unknown BTFTypeInt Encoding")::llvm::llvm_unreachable_internal("Unknown BTFTypeInt Encoding" , "llvm/lib/Target/BPF/BTFDebug.cpp", 143); | |||
144 | } | |||
145 | ||||
146 | Kind = BTF::BTF_KIND_INT; | |||
147 | BTFType.Info = Kind << 24; | |||
148 | BTFType.Size = roundupToBytes(SizeInBits); | |||
149 | IntVal = (BTFEncoding << 24) | OffsetInBits << 16 | SizeInBits; | |||
150 | } | |||
151 | ||||
152 | void BTFTypeInt::completeType(BTFDebug &BDebug) { | |||
153 | if (IsCompleted) | |||
154 | return; | |||
155 | IsCompleted = true; | |||
156 | ||||
157 | BTFType.NameOff = BDebug.addString(Name); | |||
158 | } | |||
159 | ||||
160 | void BTFTypeInt::emitType(MCStreamer &OS) { | |||
161 | BTFTypeBase::emitType(OS); | |||
162 | OS.AddComment("0x" + Twine::utohexstr(IntVal)); | |||
163 | OS.emitInt32(IntVal); | |||
164 | } | |||
165 | ||||
166 | BTFTypeEnum::BTFTypeEnum(const DICompositeType *ETy, uint32_t VLen, | |||
167 | bool IsSigned) : ETy(ETy) { | |||
168 | Kind = BTF::BTF_KIND_ENUM; | |||
169 | BTFType.Info = IsSigned << 31 | Kind << 24 | VLen; | |||
170 | BTFType.Size = roundupToBytes(ETy->getSizeInBits()); | |||
171 | } | |||
172 | ||||
173 | void BTFTypeEnum::completeType(BTFDebug &BDebug) { | |||
174 | if (IsCompleted) | |||
175 | return; | |||
176 | IsCompleted = true; | |||
177 | ||||
178 | BTFType.NameOff = BDebug.addString(ETy->getName()); | |||
179 | ||||
180 | DINodeArray Elements = ETy->getElements(); | |||
181 | for (const auto Element : Elements) { | |||
182 | const auto *Enum = cast<DIEnumerator>(Element); | |||
183 | ||||
184 | struct BTF::BTFEnum BTFEnum; | |||
185 | BTFEnum.NameOff = BDebug.addString(Enum->getName()); | |||
186 | // BTF enum value is 32bit, enforce it. | |||
187 | uint32_t Value; | |||
188 | if (Enum->isUnsigned()) | |||
189 | Value = static_cast<uint32_t>(Enum->getValue().getZExtValue()); | |||
190 | else | |||
191 | Value = static_cast<uint32_t>(Enum->getValue().getSExtValue()); | |||
192 | BTFEnum.Val = Value; | |||
193 | EnumValues.push_back(BTFEnum); | |||
194 | } | |||
195 | } | |||
196 | ||||
197 | void BTFTypeEnum::emitType(MCStreamer &OS) { | |||
198 | BTFTypeBase::emitType(OS); | |||
199 | for (const auto &Enum : EnumValues) { | |||
200 | OS.emitInt32(Enum.NameOff); | |||
201 | OS.emitInt32(Enum.Val); | |||
202 | } | |||
203 | } | |||
204 | ||||
205 | BTFTypeEnum64::BTFTypeEnum64(const DICompositeType *ETy, uint32_t VLen, | |||
206 | bool IsSigned) : ETy(ETy) { | |||
207 | Kind = BTF::BTF_KIND_ENUM64; | |||
208 | BTFType.Info = IsSigned << 31 | Kind << 24 | VLen; | |||
209 | BTFType.Size = roundupToBytes(ETy->getSizeInBits()); | |||
210 | } | |||
211 | ||||
212 | void BTFTypeEnum64::completeType(BTFDebug &BDebug) { | |||
213 | if (IsCompleted) | |||
214 | return; | |||
215 | IsCompleted = true; | |||
216 | ||||
217 | BTFType.NameOff = BDebug.addString(ETy->getName()); | |||
218 | ||||
219 | DINodeArray Elements = ETy->getElements(); | |||
220 | for (const auto Element : Elements) { | |||
221 | const auto *Enum = cast<DIEnumerator>(Element); | |||
222 | ||||
223 | struct BTF::BTFEnum64 BTFEnum; | |||
224 | BTFEnum.NameOff = BDebug.addString(Enum->getName()); | |||
225 | uint64_t Value; | |||
226 | if (Enum->isUnsigned()) | |||
227 | Value = static_cast<uint64_t>(Enum->getValue().getZExtValue()); | |||
228 | else | |||
229 | Value = static_cast<uint64_t>(Enum->getValue().getSExtValue()); | |||
230 | BTFEnum.Val_Lo32 = Value; | |||
231 | BTFEnum.Val_Hi32 = Value >> 32; | |||
232 | EnumValues.push_back(BTFEnum); | |||
233 | } | |||
234 | } | |||
235 | ||||
236 | void BTFTypeEnum64::emitType(MCStreamer &OS) { | |||
237 | BTFTypeBase::emitType(OS); | |||
238 | for (const auto &Enum : EnumValues) { | |||
239 | OS.emitInt32(Enum.NameOff); | |||
240 | OS.AddComment("0x" + Twine::utohexstr(Enum.Val_Lo32)); | |||
241 | OS.emitInt32(Enum.Val_Lo32); | |||
242 | OS.AddComment("0x" + Twine::utohexstr(Enum.Val_Hi32)); | |||
243 | OS.emitInt32(Enum.Val_Hi32); | |||
244 | } | |||
245 | } | |||
246 | ||||
247 | BTFTypeArray::BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems) { | |||
248 | Kind = BTF::BTF_KIND_ARRAY; | |||
249 | BTFType.NameOff = 0; | |||
250 | BTFType.Info = Kind << 24; | |||
251 | BTFType.Size = 0; | |||
252 | ||||
253 | ArrayInfo.ElemType = ElemTypeId; | |||
254 | ArrayInfo.Nelems = NumElems; | |||
255 | } | |||
256 | ||||
257 | /// Represent a BTF array. | |||
258 | void BTFTypeArray::completeType(BTFDebug &BDebug) { | |||
259 | if (IsCompleted) | |||
260 | return; | |||
261 | IsCompleted = true; | |||
262 | ||||
263 | // The IR does not really have a type for the index. | |||
264 | // A special type for array index should have been | |||
265 | // created during initial type traversal. Just | |||
266 | // retrieve that type id. | |||
267 | ArrayInfo.IndexType = BDebug.getArrayIndexTypeId(); | |||
268 | } | |||
269 | ||||
270 | void BTFTypeArray::emitType(MCStreamer &OS) { | |||
271 | BTFTypeBase::emitType(OS); | |||
272 | OS.emitInt32(ArrayInfo.ElemType); | |||
273 | OS.emitInt32(ArrayInfo.IndexType); | |||
274 | OS.emitInt32(ArrayInfo.Nelems); | |||
275 | } | |||
276 | ||||
277 | /// Represent either a struct or a union. | |||
278 | BTFTypeStruct::BTFTypeStruct(const DICompositeType *STy, bool IsStruct, | |||
279 | bool HasBitField, uint32_t Vlen) | |||
280 | : STy(STy), HasBitField(HasBitField) { | |||
281 | Kind = IsStruct ? BTF::BTF_KIND_STRUCT : BTF::BTF_KIND_UNION; | |||
282 | BTFType.Size = roundupToBytes(STy->getSizeInBits()); | |||
283 | BTFType.Info = (HasBitField << 31) | (Kind << 24) | Vlen; | |||
284 | } | |||
285 | ||||
286 | void BTFTypeStruct::completeType(BTFDebug &BDebug) { | |||
287 | if (IsCompleted) | |||
288 | return; | |||
289 | IsCompleted = true; | |||
290 | ||||
291 | BTFType.NameOff = BDebug.addString(STy->getName()); | |||
292 | ||||
293 | // Add struct/union members. | |||
294 | const DINodeArray Elements = STy->getElements(); | |||
295 | for (const auto *Element : Elements) { | |||
296 | struct BTF::BTFMember BTFMember; | |||
297 | const auto *DDTy = cast<DIDerivedType>(Element); | |||
298 | ||||
299 | BTFMember.NameOff = BDebug.addString(DDTy->getName()); | |||
300 | if (HasBitField) { | |||
301 | uint8_t BitFieldSize = DDTy->isBitField() ? DDTy->getSizeInBits() : 0; | |||
302 | BTFMember.Offset = BitFieldSize << 24 | DDTy->getOffsetInBits(); | |||
303 | } else { | |||
304 | BTFMember.Offset = DDTy->getOffsetInBits(); | |||
305 | } | |||
306 | const auto *BaseTy = DDTy->getBaseType(); | |||
307 | BTFMember.Type = BDebug.getTypeId(BaseTy); | |||
308 | Members.push_back(BTFMember); | |||
309 | } | |||
310 | } | |||
311 | ||||
312 | void BTFTypeStruct::emitType(MCStreamer &OS) { | |||
313 | BTFTypeBase::emitType(OS); | |||
314 | for (const auto &Member : Members) { | |||
315 | OS.emitInt32(Member.NameOff); | |||
316 | OS.emitInt32(Member.Type); | |||
317 | OS.AddComment("0x" + Twine::utohexstr(Member.Offset)); | |||
318 | OS.emitInt32(Member.Offset); | |||
319 | } | |||
320 | } | |||
321 | ||||
322 | std::string BTFTypeStruct::getName() { return std::string(STy->getName()); } | |||
323 | ||||
324 | /// The Func kind represents both subprogram and pointee of function | |||
325 | /// pointers. If the FuncName is empty, it represents a pointee of function | |||
326 | /// pointer. Otherwise, it represents a subprogram. The func arg names | |||
327 | /// are empty for pointee of function pointer case, and are valid names | |||
328 | /// for subprogram. | |||
329 | BTFTypeFuncProto::BTFTypeFuncProto( | |||
330 | const DISubroutineType *STy, uint32_t VLen, | |||
331 | const std::unordered_map<uint32_t, StringRef> &FuncArgNames) | |||
332 | : STy(STy), FuncArgNames(FuncArgNames) { | |||
333 | Kind = BTF::BTF_KIND_FUNC_PROTO; | |||
334 | BTFType.Info = (Kind << 24) | VLen; | |||
335 | } | |||
336 | ||||
337 | void BTFTypeFuncProto::completeType(BTFDebug &BDebug) { | |||
338 | if (IsCompleted) | |||
339 | return; | |||
340 | IsCompleted = true; | |||
341 | ||||
342 | DITypeRefArray Elements = STy->getTypeArray(); | |||
343 | auto RetType = Elements[0]; | |||
344 | BTFType.Type = RetType ? BDebug.getTypeId(RetType) : 0; | |||
345 | BTFType.NameOff = 0; | |||
346 | ||||
347 | // For null parameter which is typically the last one | |||
348 | // to represent the vararg, encode the NameOff/Type to be 0. | |||
349 | for (unsigned I = 1, N = Elements.size(); I < N; ++I) { | |||
350 | struct BTF::BTFParam Param; | |||
351 | auto Element = Elements[I]; | |||
352 | if (Element) { | |||
353 | Param.NameOff = BDebug.addString(FuncArgNames[I]); | |||
354 | Param.Type = BDebug.getTypeId(Element); | |||
355 | } else { | |||
356 | Param.NameOff = 0; | |||
357 | Param.Type = 0; | |||
358 | } | |||
359 | Parameters.push_back(Param); | |||
360 | } | |||
361 | } | |||
362 | ||||
363 | void BTFTypeFuncProto::emitType(MCStreamer &OS) { | |||
364 | BTFTypeBase::emitType(OS); | |||
365 | for (const auto &Param : Parameters) { | |||
366 | OS.emitInt32(Param.NameOff); | |||
367 | OS.emitInt32(Param.Type); | |||
368 | } | |||
369 | } | |||
370 | ||||
371 | BTFTypeFunc::BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId, | |||
372 | uint32_t Scope) | |||
373 | : Name(FuncName) { | |||
374 | Kind = BTF::BTF_KIND_FUNC; | |||
375 | BTFType.Info = (Kind << 24) | Scope; | |||
376 | BTFType.Type = ProtoTypeId; | |||
377 | } | |||
378 | ||||
379 | void BTFTypeFunc::completeType(BTFDebug &BDebug) { | |||
380 | if (IsCompleted) | |||
381 | return; | |||
382 | IsCompleted = true; | |||
383 | ||||
384 | BTFType.NameOff = BDebug.addString(Name); | |||
385 | } | |||
386 | ||||
387 | void BTFTypeFunc::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); } | |||
388 | ||||
389 | BTFKindVar::BTFKindVar(StringRef VarName, uint32_t TypeId, uint32_t VarInfo) | |||
390 | : Name(VarName) { | |||
391 | Kind = BTF::BTF_KIND_VAR; | |||
392 | BTFType.Info = Kind << 24; | |||
393 | BTFType.Type = TypeId; | |||
394 | Info = VarInfo; | |||
395 | } | |||
396 | ||||
397 | void BTFKindVar::completeType(BTFDebug &BDebug) { | |||
398 | BTFType.NameOff = BDebug.addString(Name); | |||
399 | } | |||
400 | ||||
401 | void BTFKindVar::emitType(MCStreamer &OS) { | |||
402 | BTFTypeBase::emitType(OS); | |||
403 | OS.emitInt32(Info); | |||
404 | } | |||
405 | ||||
406 | BTFKindDataSec::BTFKindDataSec(AsmPrinter *AsmPrt, std::string SecName) | |||
407 | : Asm(AsmPrt), Name(SecName) { | |||
408 | Kind = BTF::BTF_KIND_DATASEC; | |||
409 | BTFType.Info = Kind << 24; | |||
410 | BTFType.Size = 0; | |||
411 | } | |||
412 | ||||
413 | void BTFKindDataSec::completeType(BTFDebug &BDebug) { | |||
414 | BTFType.NameOff = BDebug.addString(Name); | |||
415 | BTFType.Info |= Vars.size(); | |||
416 | } | |||
417 | ||||
418 | void BTFKindDataSec::emitType(MCStreamer &OS) { | |||
419 | BTFTypeBase::emitType(OS); | |||
420 | ||||
421 | for (const auto &V : Vars) { | |||
422 | OS.emitInt32(std::get<0>(V)); | |||
423 | Asm->emitLabelReference(std::get<1>(V), 4); | |||
424 | OS.emitInt32(std::get<2>(V)); | |||
425 | } | |||
426 | } | |||
427 | ||||
428 | BTFTypeFloat::BTFTypeFloat(uint32_t SizeInBits, StringRef TypeName) | |||
429 | : Name(TypeName) { | |||
430 | Kind = BTF::BTF_KIND_FLOAT; | |||
431 | BTFType.Info = Kind << 24; | |||
432 | BTFType.Size = roundupToBytes(SizeInBits); | |||
433 | } | |||
434 | ||||
435 | void BTFTypeFloat::completeType(BTFDebug &BDebug) { | |||
436 | if (IsCompleted) | |||
437 | return; | |||
438 | IsCompleted = true; | |||
439 | ||||
440 | BTFType.NameOff = BDebug.addString(Name); | |||
441 | } | |||
442 | ||||
443 | BTFTypeDeclTag::BTFTypeDeclTag(uint32_t BaseTypeId, int ComponentIdx, | |||
444 | StringRef Tag) | |||
445 | : Tag(Tag) { | |||
446 | Kind = BTF::BTF_KIND_DECL_TAG; | |||
447 | BTFType.Info = Kind << 24; | |||
448 | BTFType.Type = BaseTypeId; | |||
449 | Info = ComponentIdx; | |||
450 | } | |||
451 | ||||
452 | void BTFTypeDeclTag::completeType(BTFDebug &BDebug) { | |||
453 | if (IsCompleted) | |||
454 | return; | |||
455 | IsCompleted = true; | |||
456 | ||||
457 | BTFType.NameOff = BDebug.addString(Tag); | |||
458 | } | |||
459 | ||||
460 | void BTFTypeDeclTag::emitType(MCStreamer &OS) { | |||
461 | BTFTypeBase::emitType(OS); | |||
462 | OS.emitInt32(Info); | |||
463 | } | |||
464 | ||||
465 | BTFTypeTypeTag::BTFTypeTypeTag(uint32_t NextTypeId, StringRef Tag) | |||
466 | : DTy(nullptr), Tag(Tag) { | |||
467 | Kind = BTF::BTF_KIND_TYPE_TAG; | |||
468 | BTFType.Info = Kind << 24; | |||
469 | BTFType.Type = NextTypeId; | |||
470 | } | |||
471 | ||||
472 | BTFTypeTypeTag::BTFTypeTypeTag(const DIDerivedType *DTy, StringRef Tag) | |||
473 | : DTy(DTy), Tag(Tag) { | |||
474 | Kind = BTF::BTF_KIND_TYPE_TAG; | |||
475 | BTFType.Info = Kind << 24; | |||
476 | } | |||
477 | ||||
478 | void BTFTypeTypeTag::completeType(BTFDebug &BDebug) { | |||
479 | if (IsCompleted) | |||
480 | return; | |||
481 | IsCompleted = true; | |||
482 | BTFType.NameOff = BDebug.addString(Tag); | |||
483 | if (DTy) { | |||
484 | const DIType *ResolvedType = DTy->getBaseType(); | |||
485 | if (!ResolvedType) | |||
486 | BTFType.Type = 0; | |||
487 | else | |||
488 | BTFType.Type = BDebug.getTypeId(ResolvedType); | |||
489 | } | |||
490 | } | |||
491 | ||||
492 | uint32_t BTFStringTable::addString(StringRef S) { | |||
493 | // Check whether the string already exists. | |||
494 | for (auto &OffsetM : OffsetToIdMap) { | |||
495 | if (Table[OffsetM.second] == S) | |||
496 | return OffsetM.first; | |||
497 | } | |||
498 | // Not find, add to the string table. | |||
499 | uint32_t Offset = Size; | |||
500 | OffsetToIdMap[Offset] = Table.size(); | |||
501 | Table.push_back(std::string(S)); | |||
502 | Size += S.size() + 1; | |||
503 | return Offset; | |||
504 | } | |||
505 | ||||
506 | BTFDebug::BTFDebug(AsmPrinter *AP) | |||
507 | : DebugHandlerBase(AP), OS(*Asm->OutStreamer), SkipInstruction(false), | |||
508 | LineInfoGenerated(false), SecNameOff(0), ArrayIndexTypeId(0), | |||
509 | MapDefNotCollected(true) { | |||
510 | addString("\0"); | |||
511 | } | |||
512 | ||||
513 | uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry, | |||
514 | const DIType *Ty) { | |||
515 | TypeEntry->setId(TypeEntries.size() + 1); | |||
516 | uint32_t Id = TypeEntry->getId(); | |||
517 | DIToIdMap[Ty] = Id; | |||
518 | TypeEntries.push_back(std::move(TypeEntry)); | |||
519 | return Id; | |||
520 | } | |||
521 | ||||
522 | uint32_t BTFDebug::addType(std::unique_ptr<BTFTypeBase> TypeEntry) { | |||
523 | TypeEntry->setId(TypeEntries.size() + 1); | |||
524 | uint32_t Id = TypeEntry->getId(); | |||
525 | TypeEntries.push_back(std::move(TypeEntry)); | |||
526 | return Id; | |||
527 | } | |||
528 | ||||
529 | void BTFDebug::visitBasicType(const DIBasicType *BTy, uint32_t &TypeId) { | |||
530 | // Only int and binary floating point types are supported in BTF. | |||
531 | uint32_t Encoding = BTy->getEncoding(); | |||
532 | std::unique_ptr<BTFTypeBase> TypeEntry; | |||
533 | switch (Encoding) { | |||
534 | case dwarf::DW_ATE_boolean: | |||
535 | case dwarf::DW_ATE_signed: | |||
536 | case dwarf::DW_ATE_signed_char: | |||
537 | case dwarf::DW_ATE_unsigned: | |||
538 | case dwarf::DW_ATE_unsigned_char: | |||
539 | // Create a BTF type instance for this DIBasicType and put it into | |||
540 | // DIToIdMap for cross-type reference check. | |||
541 | TypeEntry = std::make_unique<BTFTypeInt>( | |||
542 | Encoding, BTy->getSizeInBits(), BTy->getOffsetInBits(), BTy->getName()); | |||
543 | break; | |||
544 | case dwarf::DW_ATE_float: | |||
545 | TypeEntry = | |||
546 | std::make_unique<BTFTypeFloat>(BTy->getSizeInBits(), BTy->getName()); | |||
547 | break; | |||
548 | default: | |||
549 | return; | |||
550 | } | |||
551 | ||||
552 | TypeId = addType(std::move(TypeEntry), BTy); | |||
553 | } | |||
554 | ||||
555 | /// Handle subprogram or subroutine types. | |||
556 | void BTFDebug::visitSubroutineType( | |||
557 | const DISubroutineType *STy, bool ForSubprog, | |||
558 | const std::unordered_map<uint32_t, StringRef> &FuncArgNames, | |||
559 | uint32_t &TypeId) { | |||
560 | DITypeRefArray Elements = STy->getTypeArray(); | |||
561 | uint32_t VLen = Elements.size() - 1; | |||
562 | if (VLen > BTF::MAX_VLEN) | |||
563 | return; | |||
564 | ||||
565 | // Subprogram has a valid non-zero-length name, and the pointee of | |||
566 | // a function pointer has an empty name. The subprogram type will | |||
567 | // not be added to DIToIdMap as it should not be referenced by | |||
568 | // any other types. | |||
569 | auto TypeEntry = std::make_unique<BTFTypeFuncProto>(STy, VLen, FuncArgNames); | |||
570 | if (ForSubprog) | |||
571 | TypeId = addType(std::move(TypeEntry)); // For subprogram | |||
572 | else | |||
573 | TypeId = addType(std::move(TypeEntry), STy); // For func ptr | |||
574 | ||||
575 | // Visit return type and func arg types. | |||
576 | for (const auto Element : Elements) { | |||
577 | visitTypeEntry(Element); | |||
578 | } | |||
579 | } | |||
580 | ||||
581 | void BTFDebug::processDeclAnnotations(DINodeArray Annotations, | |||
582 | uint32_t BaseTypeId, | |||
583 | int ComponentIdx) { | |||
584 | if (!Annotations) | |||
585 | return; | |||
586 | ||||
587 | for (const Metadata *Annotation : Annotations->operands()) { | |||
588 | const MDNode *MD = cast<MDNode>(Annotation); | |||
589 | const MDString *Name = cast<MDString>(MD->getOperand(0)); | |||
590 | if (!Name->getString().equals("btf_decl_tag")) | |||
591 | continue; | |||
592 | ||||
593 | const MDString *Value = cast<MDString>(MD->getOperand(1)); | |||
594 | auto TypeEntry = std::make_unique<BTFTypeDeclTag>(BaseTypeId, ComponentIdx, | |||
595 | Value->getString()); | |||
596 | addType(std::move(TypeEntry)); | |||
597 | } | |||
598 | } | |||
599 | ||||
600 | uint32_t BTFDebug::processDISubprogram(const DISubprogram *SP, | |||
601 | uint32_t ProtoTypeId, uint8_t Scope) { | |||
602 | auto FuncTypeEntry = | |||
603 | std::make_unique<BTFTypeFunc>(SP->getName(), ProtoTypeId, Scope); | |||
604 | uint32_t FuncId = addType(std::move(FuncTypeEntry)); | |||
605 | ||||
606 | // Process argument annotations. | |||
607 | for (const DINode *DN : SP->getRetainedNodes()) { | |||
608 | if (const auto *DV = dyn_cast<DILocalVariable>(DN)) { | |||
609 | uint32_t Arg = DV->getArg(); | |||
610 | if (Arg) | |||
611 | processDeclAnnotations(DV->getAnnotations(), FuncId, Arg - 1); | |||
612 | } | |||
613 | } | |||
614 | processDeclAnnotations(SP->getAnnotations(), FuncId, -1); | |||
615 | ||||
616 | return FuncId; | |||
617 | } | |||
618 | ||||
619 | /// Generate btf_type_tag chains. | |||
620 | int BTFDebug::genBTFTypeTags(const DIDerivedType *DTy, int BaseTypeId) { | |||
621 | SmallVector<const MDString *, 4> MDStrs; | |||
622 | DINodeArray Annots = DTy->getAnnotations(); | |||
623 | if (Annots) { | |||
624 | // For type with "int __tag1 __tag2 *p", the MDStrs will have | |||
625 | // content: [__tag1, __tag2]. | |||
626 | for (const Metadata *Annotations : Annots->operands()) { | |||
627 | const MDNode *MD = cast<MDNode>(Annotations); | |||
628 | const MDString *Name = cast<MDString>(MD->getOperand(0)); | |||
629 | if (!Name->getString().equals("btf_type_tag")) | |||
630 | continue; | |||
631 | MDStrs.push_back(cast<MDString>(MD->getOperand(1))); | |||
632 | } | |||
633 | } | |||
634 | ||||
635 | if (MDStrs.size() == 0) | |||
636 | return -1; | |||
637 | ||||
638 | // With MDStrs [__tag1, __tag2], the output type chain looks like | |||
639 | // PTR -> __tag2 -> __tag1 -> BaseType | |||
640 | // In the below, we construct BTF types with the order of __tag1, __tag2 | |||
641 | // and PTR. | |||
642 | unsigned TmpTypeId; | |||
643 | std::unique_ptr<BTFTypeTypeTag> TypeEntry; | |||
644 | if (BaseTypeId >= 0) | |||
645 | TypeEntry = | |||
646 | std::make_unique<BTFTypeTypeTag>(BaseTypeId, MDStrs[0]->getString()); | |||
647 | else | |||
648 | TypeEntry = std::make_unique<BTFTypeTypeTag>(DTy, MDStrs[0]->getString()); | |||
649 | TmpTypeId = addType(std::move(TypeEntry)); | |||
650 | ||||
651 | for (unsigned I = 1; I < MDStrs.size(); I++) { | |||
652 | const MDString *Value = MDStrs[I]; | |||
653 | TypeEntry = std::make_unique<BTFTypeTypeTag>(TmpTypeId, Value->getString()); | |||
654 | TmpTypeId = addType(std::move(TypeEntry)); | |||
655 | } | |||
656 | return TmpTypeId; | |||
657 | } | |||
658 | ||||
659 | /// Handle structure/union types. | |||
660 | void BTFDebug::visitStructType(const DICompositeType *CTy, bool IsStruct, | |||
661 | uint32_t &TypeId) { | |||
662 | const DINodeArray Elements = CTy->getElements(); | |||
663 | uint32_t VLen = Elements.size(); | |||
664 | if (VLen > BTF::MAX_VLEN) | |||
665 | return; | |||
666 | ||||
667 | // Check whether we have any bitfield members or not | |||
668 | bool HasBitField = false; | |||
669 | for (const auto *Element : Elements) { | |||
670 | auto E = cast<DIDerivedType>(Element); | |||
671 | if (E->isBitField()) { | |||
672 | HasBitField = true; | |||
673 | break; | |||
674 | } | |||
675 | } | |||
676 | ||||
677 | auto TypeEntry = | |||
678 | std::make_unique<BTFTypeStruct>(CTy, IsStruct, HasBitField, VLen); | |||
679 | StructTypes.push_back(TypeEntry.get()); | |||
680 | TypeId = addType(std::move(TypeEntry), CTy); | |||
681 | ||||
682 | // Check struct/union annotations | |||
683 | processDeclAnnotations(CTy->getAnnotations(), TypeId, -1); | |||
684 | ||||
685 | // Visit all struct members. | |||
686 | int FieldNo = 0; | |||
687 | for (const auto *Element : Elements) { | |||
688 | const auto Elem = cast<DIDerivedType>(Element); | |||
689 | visitTypeEntry(Elem); | |||
690 | processDeclAnnotations(Elem->getAnnotations(), TypeId, FieldNo); | |||
691 | FieldNo++; | |||
692 | } | |||
693 | } | |||
694 | ||||
695 | void BTFDebug::visitArrayType(const DICompositeType *CTy, uint32_t &TypeId) { | |||
696 | // Visit array element type. | |||
697 | uint32_t ElemTypeId; | |||
698 | const DIType *ElemType = CTy->getBaseType(); | |||
699 | visitTypeEntry(ElemType, ElemTypeId, false, false); | |||
700 | ||||
701 | // Visit array dimensions. | |||
702 | DINodeArray Elements = CTy->getElements(); | |||
703 | for (int I = Elements.size() - 1; I >= 0; --I) { | |||
704 | if (auto *Element = dyn_cast_or_null<DINode>(Elements[I])) | |||
705 | if (Element->getTag() == dwarf::DW_TAG_subrange_type) { | |||
706 | const DISubrange *SR = cast<DISubrange>(Element); | |||
707 | auto *CI = SR->getCount().dyn_cast<ConstantInt *>(); | |||
708 | int64_t Count = CI->getSExtValue(); | |||
709 | ||||
710 | // For struct s { int b; char c[]; }, the c[] will be represented | |||
711 | // as an array with Count = -1. | |||
712 | auto TypeEntry = | |||
713 | std::make_unique<BTFTypeArray>(ElemTypeId, | |||
714 | Count >= 0 ? Count : 0); | |||
715 | if (I == 0) | |||
716 | ElemTypeId = addType(std::move(TypeEntry), CTy); | |||
717 | else | |||
718 | ElemTypeId = addType(std::move(TypeEntry)); | |||
719 | } | |||
720 | } | |||
721 | ||||
722 | // The array TypeId is the type id of the outermost dimension. | |||
723 | TypeId = ElemTypeId; | |||
724 | ||||
725 | // The IR does not have a type for array index while BTF wants one. | |||
726 | // So create an array index type if there is none. | |||
727 | if (!ArrayIndexTypeId) { | |||
728 | auto TypeEntry = std::make_unique<BTFTypeInt>(dwarf::DW_ATE_unsigned, 32, | |||
729 | 0, "__ARRAY_SIZE_TYPE__"); | |||
730 | ArrayIndexTypeId = addType(std::move(TypeEntry)); | |||
731 | } | |||
732 | } | |||
733 | ||||
734 | void BTFDebug::visitEnumType(const DICompositeType *CTy, uint32_t &TypeId) { | |||
735 | DINodeArray Elements = CTy->getElements(); | |||
736 | uint32_t VLen = Elements.size(); | |||
737 | if (VLen > BTF::MAX_VLEN) | |||
738 | return; | |||
739 | ||||
740 | bool IsSigned = false; | |||
741 | unsigned NumBits = 32; | |||
742 | // No BaseType implies forward declaration in which case a | |||
743 | // BTFTypeEnum with Vlen = 0 is emitted. | |||
744 | if (CTy->getBaseType() != nullptr) { | |||
745 | const auto *BTy = cast<DIBasicType>(CTy->getBaseType()); | |||
746 | IsSigned = BTy->getEncoding() == dwarf::DW_ATE_signed || | |||
747 | BTy->getEncoding() == dwarf::DW_ATE_signed_char; | |||
748 | NumBits = BTy->getSizeInBits(); | |||
749 | } | |||
750 | ||||
751 | if (NumBits <= 32) { | |||
752 | auto TypeEntry = std::make_unique<BTFTypeEnum>(CTy, VLen, IsSigned); | |||
753 | TypeId = addType(std::move(TypeEntry), CTy); | |||
754 | } else { | |||
755 | assert(NumBits == 64)(static_cast <bool> (NumBits == 64) ? void (0) : __assert_fail ("NumBits == 64", "llvm/lib/Target/BPF/BTFDebug.cpp", 755, __extension__ __PRETTY_FUNCTION__)); | |||
756 | auto TypeEntry = std::make_unique<BTFTypeEnum64>(CTy, VLen, IsSigned); | |||
757 | TypeId = addType(std::move(TypeEntry), CTy); | |||
758 | } | |||
759 | // No need to visit base type as BTF does not encode it. | |||
760 | } | |||
761 | ||||
762 | /// Handle structure/union forward declarations. | |||
763 | void BTFDebug::visitFwdDeclType(const DICompositeType *CTy, bool IsUnion, | |||
764 | uint32_t &TypeId) { | |||
765 | auto TypeEntry = std::make_unique<BTFTypeFwd>(CTy->getName(), IsUnion); | |||
766 | TypeId = addType(std::move(TypeEntry), CTy); | |||
767 | } | |||
768 | ||||
769 | /// Handle structure, union, array and enumeration types. | |||
770 | void BTFDebug::visitCompositeType(const DICompositeType *CTy, | |||
771 | uint32_t &TypeId) { | |||
772 | auto Tag = CTy->getTag(); | |||
773 | if (Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) { | |||
774 | // Handle forward declaration differently as it does not have members. | |||
775 | if (CTy->isForwardDecl()) | |||
776 | visitFwdDeclType(CTy, Tag == dwarf::DW_TAG_union_type, TypeId); | |||
777 | else | |||
778 | visitStructType(CTy, Tag == dwarf::DW_TAG_structure_type, TypeId); | |||
779 | } else if (Tag == dwarf::DW_TAG_array_type) | |||
780 | visitArrayType(CTy, TypeId); | |||
781 | else if (Tag == dwarf::DW_TAG_enumeration_type) | |||
782 | visitEnumType(CTy, TypeId); | |||
783 | } | |||
784 | ||||
785 | bool BTFDebug::IsForwardDeclCandidate(const DIType *Base) { | |||
786 | if (const auto *CTy = dyn_cast<DICompositeType>(Base)) { | |||
787 | auto CTag = CTy->getTag(); | |||
788 | if ((CTag == dwarf::DW_TAG_structure_type || | |||
789 | CTag == dwarf::DW_TAG_union_type) && | |||
790 | !CTy->getName().empty() && !CTy->isForwardDecl()) | |||
791 | return true; | |||
792 | } | |||
793 | return false; | |||
794 | } | |||
795 | ||||
796 | /// Handle pointer, typedef, const, volatile, restrict and member types. | |||
797 | void BTFDebug::visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId, | |||
798 | bool CheckPointer, bool SeenPointer) { | |||
799 | unsigned Tag = DTy->getTag(); | |||
800 | ||||
801 | /// Try to avoid chasing pointees, esp. structure pointees which may | |||
802 | /// unnecessary bring in a lot of types. | |||
803 | if (CheckPointer && !SeenPointer) { | |||
804 | SeenPointer = Tag == dwarf::DW_TAG_pointer_type; | |||
805 | } | |||
806 | ||||
807 | if (CheckPointer && SeenPointer) { | |||
808 | const DIType *Base = DTy->getBaseType(); | |||
809 | if (Base) { | |||
810 | if (IsForwardDeclCandidate(Base)) { | |||
811 | /// Find a candidate, generate a fixup. Later on the struct/union | |||
812 | /// pointee type will be replaced with either a real type or | |||
813 | /// a forward declaration. | |||
814 | auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy, Tag, true); | |||
815 | auto &Fixup = FixupDerivedTypes[cast<DICompositeType>(Base)]; | |||
816 | Fixup.push_back(std::make_pair(DTy, TypeEntry.get())); | |||
817 | TypeId = addType(std::move(TypeEntry), DTy); | |||
818 | return; | |||
819 | } | |||
820 | } | |||
821 | } | |||
822 | ||||
823 | if (Tag == dwarf::DW_TAG_pointer_type) { | |||
824 | int TmpTypeId = genBTFTypeTags(DTy, -1); | |||
825 | if (TmpTypeId >= 0) { | |||
826 | auto TypeDEntry = | |||
827 | std::make_unique<BTFTypeDerived>(TmpTypeId, Tag, DTy->getName()); | |||
828 | TypeId = addType(std::move(TypeDEntry), DTy); | |||
829 | } else { | |||
830 | auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy, Tag, false); | |||
831 | TypeId = addType(std::move(TypeEntry), DTy); | |||
832 | } | |||
833 | } else if (Tag == dwarf::DW_TAG_typedef || Tag == dwarf::DW_TAG_const_type || | |||
834 | Tag == dwarf::DW_TAG_volatile_type || | |||
835 | Tag == dwarf::DW_TAG_restrict_type) { | |||
836 | auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy, Tag, false); | |||
837 | TypeId = addType(std::move(TypeEntry), DTy); | |||
838 | if (Tag == dwarf::DW_TAG_typedef) | |||
839 | processDeclAnnotations(DTy->getAnnotations(), TypeId, -1); | |||
840 | } else if (Tag != dwarf::DW_TAG_member) { | |||
841 | return; | |||
842 | } | |||
843 | ||||
844 | // Visit base type of pointer, typedef, const, volatile, restrict or | |||
845 | // struct/union member. | |||
846 | uint32_t TempTypeId = 0; | |||
847 | if (Tag == dwarf::DW_TAG_member) | |||
848 | visitTypeEntry(DTy->getBaseType(), TempTypeId, true, false); | |||
849 | else | |||
850 | visitTypeEntry(DTy->getBaseType(), TempTypeId, CheckPointer, SeenPointer); | |||
851 | } | |||
852 | ||||
853 | /// Visit a type entry. CheckPointer is true if the type has | |||
854 | /// one of its predecessors as one struct/union member. SeenPointer | |||
855 | /// is true if CheckPointer is true and one of its predecessors | |||
856 | /// is a pointer. The goal of CheckPointer and SeenPointer is to | |||
857 | /// do pruning for struct/union types so some of these types | |||
858 | /// will not be emitted in BTF and rather forward declarations | |||
859 | /// will be generated. | |||
860 | void BTFDebug::visitTypeEntry(const DIType *Ty, uint32_t &TypeId, | |||
861 | bool CheckPointer, bool SeenPointer) { | |||
862 | if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) { | |||
863 | TypeId = DIToIdMap[Ty]; | |||
864 | ||||
865 | // To handle the case like the following: | |||
866 | // struct t; | |||
867 | // typedef struct t _t; | |||
868 | // struct s1 { _t *c; }; | |||
869 | // int test1(struct s1 *arg) { ... } | |||
870 | // | |||
871 | // struct t { int a; int b; }; | |||
872 | // struct s2 { _t c; } | |||
873 | // int test2(struct s2 *arg) { ... } | |||
874 | // | |||
875 | // During traversing test1() argument, "_t" is recorded | |||
876 | // in DIToIdMap and a forward declaration fixup is created | |||
877 | // for "struct t" to avoid pointee type traversal. | |||
878 | // | |||
879 | // During traversing test2() argument, even if we see "_t" is | |||
880 | // already defined, we should keep moving to eventually | |||
881 | // bring in types for "struct t". Otherwise, the "struct s2" | |||
882 | // definition won't be correct. | |||
883 | // | |||
884 | // In the above, we have following debuginfo: | |||
885 | // {ptr, struct_member} -> typedef -> struct | |||
886 | // and BTF type for 'typedef' is generated while 'struct' may | |||
887 | // be in FixUp. But let us generalize the above to handle | |||
888 | // {different types} -> [various derived types]+ -> another type. | |||
889 | // For example, | |||
890 | // {func_param, struct_member} -> const -> ptr -> volatile -> struct | |||
891 | // We will traverse const/ptr/volatile which already have corresponding | |||
892 | // BTF types and generate type for 'struct' which might be in Fixup | |||
893 | // state. | |||
894 | if (Ty && (!CheckPointer || !SeenPointer)) { | |||
895 | if (const auto *DTy = dyn_cast<DIDerivedType>(Ty)) { | |||
896 | while (DTy) { | |||
897 | const DIType *BaseTy = DTy->getBaseType(); | |||
898 | if (!BaseTy) | |||
899 | break; | |||
900 | ||||
901 | if (DIToIdMap.find(BaseTy) != DIToIdMap.end()) { | |||
902 | DTy = dyn_cast<DIDerivedType>(BaseTy); | |||
903 | } else { | |||
904 | if (CheckPointer && DTy->getTag() == dwarf::DW_TAG_pointer_type) { | |||
905 | SeenPointer = true; | |||
906 | if (IsForwardDeclCandidate(BaseTy)) | |||
907 | break; | |||
908 | } | |||
909 | uint32_t TmpTypeId; | |||
910 | visitTypeEntry(BaseTy, TmpTypeId, CheckPointer, SeenPointer); | |||
911 | break; | |||
912 | } | |||
913 | } | |||
914 | } | |||
915 | } | |||
916 | ||||
917 | return; | |||
918 | } | |||
919 | ||||
920 | if (const auto *BTy = dyn_cast<DIBasicType>(Ty)) | |||
921 | visitBasicType(BTy, TypeId); | |||
922 | else if (const auto *STy = dyn_cast<DISubroutineType>(Ty)) | |||
923 | visitSubroutineType(STy, false, std::unordered_map<uint32_t, StringRef>(), | |||
924 | TypeId); | |||
925 | else if (const auto *CTy = dyn_cast<DICompositeType>(Ty)) | |||
926 | visitCompositeType(CTy, TypeId); | |||
927 | else if (const auto *DTy = dyn_cast<DIDerivedType>(Ty)) | |||
928 | visitDerivedType(DTy, TypeId, CheckPointer, SeenPointer); | |||
929 | else | |||
930 | llvm_unreachable("Unknown DIType")::llvm::llvm_unreachable_internal("Unknown DIType", "llvm/lib/Target/BPF/BTFDebug.cpp" , 930); | |||
931 | } | |||
932 | ||||
933 | void BTFDebug::visitTypeEntry(const DIType *Ty) { | |||
934 | uint32_t TypeId; | |||
935 | visitTypeEntry(Ty, TypeId, false, false); | |||
936 | } | |||
937 | ||||
938 | void BTFDebug::visitMapDefType(const DIType *Ty, uint32_t &TypeId) { | |||
939 | if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) { | |||
940 | TypeId = DIToIdMap[Ty]; | |||
941 | return; | |||
942 | } | |||
943 | ||||
944 | // MapDef type may be a struct type or a non-pointer derived type | |||
945 | const DIType *OrigTy = Ty; | |||
946 | while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) { | |||
947 | auto Tag = DTy->getTag(); | |||
948 | if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type && | |||
949 | Tag != dwarf::DW_TAG_volatile_type && | |||
950 | Tag != dwarf::DW_TAG_restrict_type) | |||
951 | break; | |||
952 | Ty = DTy->getBaseType(); | |||
953 | } | |||
954 | ||||
955 | const auto *CTy = dyn_cast<DICompositeType>(Ty); | |||
956 | if (!CTy) | |||
957 | return; | |||
958 | ||||
959 | auto Tag = CTy->getTag(); | |||
960 | if (Tag != dwarf::DW_TAG_structure_type || CTy->isForwardDecl()) | |||
961 | return; | |||
962 | ||||
963 | // Visit all struct members to ensure pointee type is visited | |||
964 | const DINodeArray Elements = CTy->getElements(); | |||
965 | for (const auto *Element : Elements) { | |||
966 | const auto *MemberType = cast<DIDerivedType>(Element); | |||
967 | visitTypeEntry(MemberType->getBaseType()); | |||
968 | } | |||
969 | ||||
970 | // Visit this type, struct or a const/typedef/volatile/restrict type | |||
971 | visitTypeEntry(OrigTy, TypeId, false, false); | |||
972 | } | |||
973 | ||||
974 | /// Read file contents from the actual file or from the source | |||
975 | std::string BTFDebug::populateFileContent(const DISubprogram *SP) { | |||
976 | auto File = SP->getFile(); | |||
977 | std::string FileName; | |||
978 | ||||
979 | if (!File->getFilename().startswith("/") && File->getDirectory().size()) | |||
980 | FileName = File->getDirectory().str() + "/" + File->getFilename().str(); | |||
981 | else | |||
982 | FileName = std::string(File->getFilename()); | |||
983 | ||||
984 | // No need to populate the contends if it has been populated! | |||
985 | if (FileContent.contains(FileName)) | |||
986 | return FileName; | |||
987 | ||||
988 | std::vector<std::string> Content; | |||
989 | std::string Line; | |||
990 | Content.push_back(Line); // Line 0 for empty string | |||
991 | ||||
992 | std::unique_ptr<MemoryBuffer> Buf; | |||
993 | auto Source = File->getSource(); | |||
994 | if (Source) | |||
995 | Buf = MemoryBuffer::getMemBufferCopy(*Source); | |||
996 | else if (ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = | |||
997 | MemoryBuffer::getFile(FileName)) | |||
998 | Buf = std::move(*BufOrErr); | |||
999 | if (Buf) | |||
1000 | for (line_iterator I(*Buf, false), E; I != E; ++I) | |||
1001 | Content.push_back(std::string(*I)); | |||
1002 | ||||
1003 | FileContent[FileName] = Content; | |||
1004 | return FileName; | |||
1005 | } | |||
1006 | ||||
1007 | void BTFDebug::constructLineInfo(const DISubprogram *SP, MCSymbol *Label, | |||
1008 | uint32_t Line, uint32_t Column) { | |||
1009 | std::string FileName = populateFileContent(SP); | |||
1010 | BTFLineInfo LineInfo; | |||
1011 | ||||
1012 | LineInfo.Label = Label; | |||
1013 | LineInfo.FileNameOff = addString(FileName); | |||
1014 | // If file content is not available, let LineOff = 0. | |||
1015 | if (Line < FileContent[FileName].size()) | |||
1016 | LineInfo.LineOff = addString(FileContent[FileName][Line]); | |||
1017 | else | |||
1018 | LineInfo.LineOff = 0; | |||
1019 | LineInfo.LineNum = Line; | |||
1020 | LineInfo.ColumnNum = Column; | |||
1021 | LineInfoTable[SecNameOff].push_back(LineInfo); | |||
1022 | } | |||
1023 | ||||
1024 | void BTFDebug::emitCommonHeader() { | |||
1025 | OS.AddComment("0x" + Twine::utohexstr(BTF::MAGIC)); | |||
1026 | OS.emitIntValue(BTF::MAGIC, 2); | |||
1027 | OS.emitInt8(BTF::VERSION); | |||
1028 | OS.emitInt8(0); | |||
1029 | } | |||
1030 | ||||
1031 | void BTFDebug::emitBTFSection() { | |||
1032 | // Do not emit section if no types and only "" string. | |||
1033 | if (!TypeEntries.size() && StringTable.getSize() == 1) | |||
1034 | return; | |||
1035 | ||||
1036 | MCContext &Ctx = OS.getContext(); | |||
1037 | MCSectionELF *Sec = Ctx.getELFSection(".BTF", ELF::SHT_PROGBITS, 0); | |||
1038 | Sec->setAlignment(Align(4)); | |||
1039 | OS.switchSection(Sec); | |||
1040 | ||||
1041 | // Emit header. | |||
1042 | emitCommonHeader(); | |||
1043 | OS.emitInt32(BTF::HeaderSize); | |||
1044 | ||||
1045 | uint32_t TypeLen = 0, StrLen; | |||
1046 | for (const auto &TypeEntry : TypeEntries) | |||
1047 | TypeLen += TypeEntry->getSize(); | |||
1048 | StrLen = StringTable.getSize(); | |||
1049 | ||||
1050 | OS.emitInt32(0); | |||
1051 | OS.emitInt32(TypeLen); | |||
1052 | OS.emitInt32(TypeLen); | |||
1053 | OS.emitInt32(StrLen); | |||
1054 | ||||
1055 | // Emit type table. | |||
1056 | for (const auto &TypeEntry : TypeEntries) | |||
1057 | TypeEntry->emitType(OS); | |||
1058 | ||||
1059 | // Emit string table. | |||
1060 | uint32_t StringOffset = 0; | |||
1061 | for (const auto &S : StringTable.getTable()) { | |||
1062 | OS.AddComment("string offset=" + std::to_string(StringOffset)); | |||
1063 | OS.emitBytes(S); | |||
1064 | OS.emitBytes(StringRef("\0", 1)); | |||
1065 | StringOffset += S.size() + 1; | |||
1066 | } | |||
1067 | } | |||
1068 | ||||
1069 | void BTFDebug::emitBTFExtSection() { | |||
1070 | // Do not emit section if empty FuncInfoTable and LineInfoTable | |||
1071 | // and FieldRelocTable. | |||
1072 | if (!FuncInfoTable.size() && !LineInfoTable.size() && | |||
1073 | !FieldRelocTable.size()) | |||
1074 | return; | |||
1075 | ||||
1076 | MCContext &Ctx = OS.getContext(); | |||
1077 | MCSectionELF *Sec = Ctx.getELFSection(".BTF.ext", ELF::SHT_PROGBITS, 0); | |||
1078 | Sec->setAlignment(Align(4)); | |||
1079 | OS.switchSection(Sec); | |||
1080 | ||||
1081 | // Emit header. | |||
1082 | emitCommonHeader(); | |||
1083 | OS.emitInt32(BTF::ExtHeaderSize); | |||
1084 | ||||
1085 | // Account for FuncInfo/LineInfo record size as well. | |||
1086 | uint32_t FuncLen = 4, LineLen = 4; | |||
1087 | // Do not account for optional FieldReloc. | |||
1088 | uint32_t FieldRelocLen = 0; | |||
1089 | for (const auto &FuncSec : FuncInfoTable) { | |||
1090 | FuncLen += BTF::SecFuncInfoSize; | |||
1091 | FuncLen += FuncSec.second.size() * BTF::BPFFuncInfoSize; | |||
1092 | } | |||
1093 | for (const auto &LineSec : LineInfoTable) { | |||
1094 | LineLen += BTF::SecLineInfoSize; | |||
1095 | LineLen += LineSec.second.size() * BTF::BPFLineInfoSize; | |||
1096 | } | |||
1097 | for (const auto &FieldRelocSec : FieldRelocTable) { | |||
1098 | FieldRelocLen += BTF::SecFieldRelocSize; | |||
1099 | FieldRelocLen += FieldRelocSec.second.size() * BTF::BPFFieldRelocSize; | |||
1100 | } | |||
1101 | ||||
1102 | if (FieldRelocLen) | |||
1103 | FieldRelocLen += 4; | |||
1104 | ||||
1105 | OS.emitInt32(0); | |||
1106 | OS.emitInt32(FuncLen); | |||
1107 | OS.emitInt32(FuncLen); | |||
1108 | OS.emitInt32(LineLen); | |||
1109 | OS.emitInt32(FuncLen + LineLen); | |||
1110 | OS.emitInt32(FieldRelocLen); | |||
1111 | ||||
1112 | // Emit func_info table. | |||
1113 | OS.AddComment("FuncInfo"); | |||
1114 | OS.emitInt32(BTF::BPFFuncInfoSize); | |||
1115 | for (const auto &FuncSec : FuncInfoTable) { | |||
1116 | OS.AddComment("FuncInfo section string offset=" + | |||
1117 | std::to_string(FuncSec.first)); | |||
1118 | OS.emitInt32(FuncSec.first); | |||
1119 | OS.emitInt32(FuncSec.second.size()); | |||
1120 | for (const auto &FuncInfo : FuncSec.second) { | |||
1121 | Asm->emitLabelReference(FuncInfo.Label, 4); | |||
1122 | OS.emitInt32(FuncInfo.TypeId); | |||
1123 | } | |||
1124 | } | |||
1125 | ||||
1126 | // Emit line_info table. | |||
1127 | OS.AddComment("LineInfo"); | |||
1128 | OS.emitInt32(BTF::BPFLineInfoSize); | |||
1129 | for (const auto &LineSec : LineInfoTable) { | |||
1130 | OS.AddComment("LineInfo section string offset=" + | |||
1131 | std::to_string(LineSec.first)); | |||
1132 | OS.emitInt32(LineSec.first); | |||
1133 | OS.emitInt32(LineSec.second.size()); | |||
1134 | for (const auto &LineInfo : LineSec.second) { | |||
1135 | Asm->emitLabelReference(LineInfo.Label, 4); | |||
1136 | OS.emitInt32(LineInfo.FileNameOff); | |||
1137 | OS.emitInt32(LineInfo.LineOff); | |||
1138 | OS.AddComment("Line " + std::to_string(LineInfo.LineNum) + " Col " + | |||
1139 | std::to_string(LineInfo.ColumnNum)); | |||
1140 | OS.emitInt32(LineInfo.LineNum << 10 | LineInfo.ColumnNum); | |||
1141 | } | |||
1142 | } | |||
1143 | ||||
1144 | // Emit field reloc table. | |||
1145 | if (FieldRelocLen) { | |||
1146 | OS.AddComment("FieldReloc"); | |||
1147 | OS.emitInt32(BTF::BPFFieldRelocSize); | |||
1148 | for (const auto &FieldRelocSec : FieldRelocTable) { | |||
1149 | OS.AddComment("Field reloc section string offset=" + | |||
1150 | std::to_string(FieldRelocSec.first)); | |||
1151 | OS.emitInt32(FieldRelocSec.first); | |||
1152 | OS.emitInt32(FieldRelocSec.second.size()); | |||
1153 | for (const auto &FieldRelocInfo : FieldRelocSec.second) { | |||
1154 | Asm->emitLabelReference(FieldRelocInfo.Label, 4); | |||
1155 | OS.emitInt32(FieldRelocInfo.TypeID); | |||
1156 | OS.emitInt32(FieldRelocInfo.OffsetNameOff); | |||
1157 | OS.emitInt32(FieldRelocInfo.RelocKind); | |||
1158 | } | |||
1159 | } | |||
1160 | } | |||
1161 | } | |||
1162 | ||||
1163 | void BTFDebug::beginFunctionImpl(const MachineFunction *MF) { | |||
1164 | auto *SP = MF->getFunction().getSubprogram(); | |||
1165 | auto *Unit = SP->getUnit(); | |||
1166 | ||||
1167 | if (Unit->getEmissionKind() == DICompileUnit::NoDebug) { | |||
1168 | SkipInstruction = true; | |||
1169 | return; | |||
1170 | } | |||
1171 | SkipInstruction = false; | |||
1172 | ||||
1173 | // Collect MapDef types. Map definition needs to collect | |||
1174 | // pointee types. Do it first. Otherwise, for the following | |||
1175 | // case: | |||
1176 | // struct m { ...}; | |||
1177 | // struct t { | |||
1178 | // struct m *key; | |||
1179 | // }; | |||
1180 | // foo(struct t *arg); | |||
1181 | // | |||
1182 | // struct mapdef { | |||
1183 | // ... | |||
1184 | // struct m *key; | |||
1185 | // ... | |||
1186 | // } __attribute__((section(".maps"))) hash_map; | |||
1187 | // | |||
1188 | // If subroutine foo is traversed first, a type chain | |||
1189 | // "ptr->struct m(fwd)" will be created and later on | |||
1190 | // when traversing mapdef, since "ptr->struct m" exists, | |||
1191 | // the traversal of "struct m" will be omitted. | |||
1192 | if (MapDefNotCollected) { | |||
1193 | processGlobals(true); | |||
1194 | MapDefNotCollected = false; | |||
1195 | } | |||
1196 | ||||
1197 | // Collect all types locally referenced in this function. | |||
1198 | // Use RetainedNodes so we can collect all argument names | |||
1199 | // even if the argument is not used. | |||
1200 | std::unordered_map<uint32_t, StringRef> FuncArgNames; | |||
1201 | for (const DINode *DN : SP->getRetainedNodes()) { | |||
1202 | if (const auto *DV = dyn_cast<DILocalVariable>(DN)) { | |||
1203 | // Collect function arguments for subprogram func type. | |||
1204 | uint32_t Arg = DV->getArg(); | |||
1205 | if (Arg) { | |||
1206 | visitTypeEntry(DV->getType()); | |||
1207 | FuncArgNames[Arg] = DV->getName(); | |||
1208 | } | |||
1209 | } | |||
1210 | } | |||
1211 | ||||
1212 | // Construct subprogram func proto type. | |||
1213 | uint32_t ProtoTypeId; | |||
1214 | visitSubroutineType(SP->getType(), true, FuncArgNames, ProtoTypeId); | |||
1215 | ||||
1216 | // Construct subprogram func type | |||
1217 | uint8_t Scope = SP->isLocalToUnit() ? BTF::FUNC_STATIC : BTF::FUNC_GLOBAL; | |||
1218 | uint32_t FuncTypeId = processDISubprogram(SP, ProtoTypeId, Scope); | |||
1219 | ||||
1220 | for (const auto &TypeEntry : TypeEntries) | |||
1221 | TypeEntry->completeType(*this); | |||
1222 | ||||
1223 | // Construct funcinfo and the first lineinfo for the function. | |||
1224 | MCSymbol *FuncLabel = Asm->getFunctionBegin(); | |||
1225 | BTFFuncInfo FuncInfo; | |||
1226 | FuncInfo.Label = FuncLabel; | |||
1227 | FuncInfo.TypeId = FuncTypeId; | |||
1228 | if (FuncLabel->isInSection()) { | |||
1229 | MCSection &Section = FuncLabel->getSection(); | |||
1230 | const MCSectionELF *SectionELF = dyn_cast<MCSectionELF>(&Section); | |||
1231 | assert(SectionELF && "Null section for Function Label")(static_cast <bool> (SectionELF && "Null section for Function Label" ) ? void (0) : __assert_fail ("SectionELF && \"Null section for Function Label\"" , "llvm/lib/Target/BPF/BTFDebug.cpp", 1231, __extension__ __PRETTY_FUNCTION__ )); | |||
1232 | SecNameOff = addString(SectionELF->getName()); | |||
1233 | } else { | |||
1234 | SecNameOff = addString(".text"); | |||
1235 | } | |||
1236 | FuncInfoTable[SecNameOff].push_back(FuncInfo); | |||
1237 | } | |||
1238 | ||||
1239 | void BTFDebug::endFunctionImpl(const MachineFunction *MF) { | |||
1240 | SkipInstruction = false; | |||
1241 | LineInfoGenerated = false; | |||
1242 | SecNameOff = 0; | |||
1243 | } | |||
1244 | ||||
1245 | /// On-demand populate types as requested from abstract member | |||
1246 | /// accessing or preserve debuginfo type. | |||
1247 | unsigned BTFDebug::populateType(const DIType *Ty) { | |||
1248 | unsigned Id; | |||
1249 | visitTypeEntry(Ty, Id, false, false); | |||
1250 | for (const auto &TypeEntry : TypeEntries) | |||
1251 | TypeEntry->completeType(*this); | |||
1252 | return Id; | |||
1253 | } | |||
1254 | ||||
1255 | /// Generate a struct member field relocation. | |||
1256 | void BTFDebug::generatePatchImmReloc(const MCSymbol *ORSym, uint32_t RootId, | |||
1257 | const GlobalVariable *GVar, bool IsAma) { | |||
1258 | BTFFieldReloc FieldReloc; | |||
1259 | FieldReloc.Label = ORSym; | |||
1260 | FieldReloc.TypeID = RootId; | |||
1261 | ||||
1262 | StringRef AccessPattern = GVar->getName(); | |||
1263 | size_t FirstDollar = AccessPattern.find_first_of('$'); | |||
1264 | if (IsAma) { | |||
1265 | size_t FirstColon = AccessPattern.find_first_of(':'); | |||
1266 | size_t SecondColon = AccessPattern.find_first_of(':', FirstColon + 1); | |||
1267 | StringRef IndexPattern = AccessPattern.substr(FirstDollar + 1); | |||
1268 | StringRef RelocKindStr = AccessPattern.substr(FirstColon + 1, | |||
1269 | SecondColon - FirstColon); | |||
1270 | StringRef PatchImmStr = AccessPattern.substr(SecondColon + 1, | |||
1271 | FirstDollar - SecondColon); | |||
1272 | ||||
1273 | FieldReloc.OffsetNameOff = addString(IndexPattern); | |||
1274 | FieldReloc.RelocKind = std::stoull(std::string(RelocKindStr)); | |||
1275 | PatchImms[GVar] = std::make_pair(std::stoll(std::string(PatchImmStr)), | |||
1276 | FieldReloc.RelocKind); | |||
1277 | } else { | |||
1278 | StringRef RelocStr = AccessPattern.substr(FirstDollar + 1); | |||
1279 | FieldReloc.OffsetNameOff = addString("0"); | |||
1280 | FieldReloc.RelocKind = std::stoull(std::string(RelocStr)); | |||
1281 | PatchImms[GVar] = std::make_pair(RootId, FieldReloc.RelocKind); | |||
1282 | } | |||
1283 | FieldRelocTable[SecNameOff].push_back(FieldReloc); | |||
1284 | } | |||
1285 | ||||
1286 | void BTFDebug::processGlobalValue(const MachineOperand &MO) { | |||
1287 | // check whether this is a candidate or not | |||
1288 | if (MO.isGlobal()) { | |||
1289 | const GlobalValue *GVal = MO.getGlobal(); | |||
1290 | auto *GVar = dyn_cast<GlobalVariable>(GVal); | |||
1291 | if (!GVar
| |||
1292 | // Not a global variable. Maybe an extern function reference. | |||
1293 | processFuncPrototypes(dyn_cast<Function>(GVal)); | |||
1294 | return; | |||
1295 | } | |||
1296 | ||||
1297 | if (!GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr) && | |||
1298 | !GVar->hasAttribute(BPFCoreSharedInfo::TypeIdAttr)) | |||
1299 | return; | |||
1300 | ||||
1301 | MCSymbol *ORSym = OS.getContext().createTempSymbol(); | |||
1302 | OS.emitLabel(ORSym); | |||
1303 | ||||
1304 | MDNode *MDN = GVar->getMetadata(LLVMContext::MD_preserve_access_index); | |||
1305 | uint32_t RootId = populateType(dyn_cast<DIType>(MDN)); | |||
1306 | generatePatchImmReloc(ORSym, RootId, GVar, | |||
1307 | GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)); | |||
1308 | } | |||
1309 | } | |||
1310 | ||||
1311 | void BTFDebug::beginInstruction(const MachineInstr *MI) { | |||
1312 | DebugHandlerBase::beginInstruction(MI); | |||
1313 | ||||
1314 | if (SkipInstruction || MI->isMetaInstruction() || | |||
| ||||
1315 | MI->getFlag(MachineInstr::FrameSetup)) | |||
1316 | return; | |||
1317 | ||||
1318 | if (MI->isInlineAsm()) { | |||
1319 | // Count the number of register definitions to find the asm string. | |||
1320 | unsigned NumDefs = 0; | |||
1321 | for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef(); | |||
1322 | ++NumDefs) | |||
1323 | ; | |||
1324 | ||||
1325 | // Skip this inline asm instruction if the asmstr is empty. | |||
1326 | const char *AsmStr = MI->getOperand(NumDefs).getSymbolName(); | |||
1327 | if (AsmStr[0] == 0) | |||
1328 | return; | |||
1329 | } | |||
1330 | ||||
1331 | if (MI->getOpcode() == BPF::LD_imm64) { | |||
1332 | // If the insn is "r2 = LD_imm64 @<an AmaAttr global>", | |||
1333 | // add this insn into the .BTF.ext FieldReloc subsection. | |||
1334 | // Relocation looks like: | |||
1335 | // . SecName: | |||
1336 | // . InstOffset | |||
1337 | // . TypeID | |||
1338 | // . OffSetNameOff | |||
1339 | // . RelocType | |||
1340 | // Later, the insn is replaced with "r2 = <offset>" | |||
1341 | // where "<offset>" equals to the offset based on current | |||
1342 | // type definitions. | |||
1343 | // | |||
1344 | // If the insn is "r2 = LD_imm64 @<an TypeIdAttr global>", | |||
1345 | // The LD_imm64 result will be replaced with a btf type id. | |||
1346 | processGlobalValue(MI->getOperand(1)); | |||
1347 | } else if (MI->getOpcode() == BPF::CORE_MEM || | |||
1348 | MI->getOpcode() == BPF::CORE_ALU32_MEM || | |||
1349 | MI->getOpcode() == BPF::CORE_SHIFT) { | |||
1350 | // relocation insn is a load, store or shift insn. | |||
1351 | processGlobalValue(MI->getOperand(3)); | |||
1352 | } else if (MI->getOpcode() == BPF::JAL) { | |||
1353 | // check extern function references | |||
1354 | const MachineOperand &MO = MI->getOperand(0); | |||
1355 | if (MO.isGlobal()) { | |||
1356 | processFuncPrototypes(dyn_cast<Function>(MO.getGlobal())); | |||
1357 | } | |||
1358 | } | |||
1359 | ||||
1360 | if (!CurMI) // no debug info | |||
1361 | return; | |||
1362 | ||||
1363 | // Skip this instruction if no DebugLoc or the DebugLoc | |||
1364 | // is the same as the previous instruction. | |||
1365 | const DebugLoc &DL = MI->getDebugLoc(); | |||
1366 | if (!DL || PrevInstLoc == DL) { | |||
1367 | // This instruction will be skipped, no LineInfo has | |||
1368 | // been generated, construct one based on function signature. | |||
1369 | if (LineInfoGenerated == false) { | |||
1370 | auto *S = MI->getMF()->getFunction().getSubprogram(); | |||
1371 | MCSymbol *FuncLabel = Asm->getFunctionBegin(); | |||
1372 | constructLineInfo(S, FuncLabel, S->getLine(), 0); | |||
1373 | LineInfoGenerated = true; | |||
1374 | } | |||
1375 | ||||
1376 | return; | |||
1377 | } | |||
1378 | ||||
1379 | // Create a temporary label to remember the insn for lineinfo. | |||
1380 | MCSymbol *LineSym = OS.getContext().createTempSymbol(); | |||
1381 | OS.emitLabel(LineSym); | |||
1382 | ||||
1383 | // Construct the lineinfo. | |||
1384 | auto SP = DL->getScope()->getSubprogram(); | |||
1385 | constructLineInfo(SP, LineSym, DL.getLine(), DL.getCol()); | |||
1386 | ||||
1387 | LineInfoGenerated = true; | |||
1388 | PrevInstLoc = DL; | |||
1389 | } | |||
1390 | ||||
1391 | void BTFDebug::processGlobals(bool ProcessingMapDef) { | |||
1392 | // Collect all types referenced by globals. | |||
1393 | const Module *M = MMI->getModule(); | |||
1394 | for (const GlobalVariable &Global : M->globals()) { | |||
1395 | // Decide the section name. | |||
1396 | StringRef SecName; | |||
1397 | std::optional<SectionKind> GVKind; | |||
1398 | ||||
1399 | if (!Global.isDeclarationForLinker()) | |||
1400 | GVKind = TargetLoweringObjectFile::getKindForGlobal(&Global, Asm->TM); | |||
1401 | ||||
1402 | if (Global.isDeclarationForLinker()) | |||
1403 | SecName = Global.hasSection() ? Global.getSection() : ""; | |||
1404 | else if (GVKind->isCommon()) | |||
1405 | SecName = ".bss"; | |||
1406 | else { | |||
1407 | TargetLoweringObjectFile *TLOF = Asm->TM.getObjFileLowering(); | |||
1408 | MCSection *Sec = TLOF->SectionForGlobal(&Global, Asm->TM); | |||
1409 | SecName = Sec->getName(); | |||
1410 | } | |||
1411 | ||||
1412 | if (ProcessingMapDef != SecName.startswith(".maps")) | |||
1413 | continue; | |||
1414 | ||||
1415 | // Create a .rodata datasec if the global variable is an initialized | |||
1416 | // constant with private linkage and if it won't be in .rodata.str<#> | |||
1417 | // and .rodata.cst<#> sections. | |||
1418 | if (SecName == ".rodata" && Global.hasPrivateLinkage() && | |||
1419 | DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) { | |||
1420 | // skip .rodata.str<#> and .rodata.cst<#> sections | |||
1421 | if (!GVKind->isMergeableCString() && !GVKind->isMergeableConst()) { | |||
1422 | DataSecEntries[std::string(SecName)] = | |||
1423 | std::make_unique<BTFKindDataSec>(Asm, std::string(SecName)); | |||
1424 | } | |||
1425 | } | |||
1426 | ||||
1427 | SmallVector<DIGlobalVariableExpression *, 1> GVs; | |||
1428 | Global.getDebugInfo(GVs); | |||
1429 | ||||
1430 | // No type information, mostly internal, skip it. | |||
1431 | if (GVs.size() == 0) | |||
1432 | continue; | |||
1433 | ||||
1434 | uint32_t GVTypeId = 0; | |||
1435 | DIGlobalVariable *DIGlobal = nullptr; | |||
1436 | for (auto *GVE : GVs) { | |||
1437 | DIGlobal = GVE->getVariable(); | |||
1438 | if (SecName.startswith(".maps")) | |||
1439 | visitMapDefType(DIGlobal->getType(), GVTypeId); | |||
1440 | else | |||
1441 | visitTypeEntry(DIGlobal->getType(), GVTypeId, false, false); | |||
1442 | break; | |||
1443 | } | |||
1444 | ||||
1445 | // Only support the following globals: | |||
1446 | // . static variables | |||
1447 | // . non-static weak or non-weak global variables | |||
1448 | // . weak or non-weak extern global variables | |||
1449 | // Whether DataSec is readonly or not can be found from corresponding ELF | |||
1450 | // section flags. Whether a BTF_KIND_VAR is a weak symbol or not | |||
1451 | // can be found from the corresponding ELF symbol table. | |||
1452 | auto Linkage = Global.getLinkage(); | |||
1453 | if (Linkage != GlobalValue::InternalLinkage && | |||
1454 | Linkage != GlobalValue::ExternalLinkage && | |||
1455 | Linkage != GlobalValue::WeakAnyLinkage && | |||
1456 | Linkage != GlobalValue::WeakODRLinkage && | |||
1457 | Linkage != GlobalValue::ExternalWeakLinkage) | |||
1458 | continue; | |||
1459 | ||||
1460 | uint32_t GVarInfo; | |||
1461 | if (Linkage == GlobalValue::InternalLinkage) { | |||
1462 | GVarInfo = BTF::VAR_STATIC; | |||
1463 | } else if (Global.hasInitializer()) { | |||
1464 | GVarInfo = BTF::VAR_GLOBAL_ALLOCATED; | |||
1465 | } else { | |||
1466 | GVarInfo = BTF::VAR_GLOBAL_EXTERNAL; | |||
1467 | } | |||
1468 | ||||
1469 | auto VarEntry = | |||
1470 | std::make_unique<BTFKindVar>(Global.getName(), GVTypeId, GVarInfo); | |||
1471 | uint32_t VarId = addType(std::move(VarEntry)); | |||
1472 | ||||
1473 | processDeclAnnotations(DIGlobal->getAnnotations(), VarId, -1); | |||
1474 | ||||
1475 | // An empty SecName means an extern variable without section attribute. | |||
1476 | if (SecName.empty()) | |||
1477 | continue; | |||
1478 | ||||
1479 | // Find or create a DataSec | |||
1480 | if (DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) { | |||
1481 | DataSecEntries[std::string(SecName)] = | |||
1482 | std::make_unique<BTFKindDataSec>(Asm, std::string(SecName)); | |||
1483 | } | |||
1484 | ||||
1485 | // Calculate symbol size | |||
1486 | const DataLayout &DL = Global.getParent()->getDataLayout(); | |||
1487 | uint32_t Size = DL.getTypeAllocSize(Global.getValueType()); | |||
1488 | ||||
1489 | DataSecEntries[std::string(SecName)]->addDataSecEntry(VarId, | |||
1490 | Asm->getSymbol(&Global), Size); | |||
1491 | } | |||
1492 | } | |||
1493 | ||||
1494 | /// Emit proper patchable instructions. | |||
1495 | bool BTFDebug::InstLower(const MachineInstr *MI, MCInst &OutMI) { | |||
1496 | if (MI->getOpcode() == BPF::LD_imm64) { | |||
1497 | const MachineOperand &MO = MI->getOperand(1); | |||
1498 | if (MO.isGlobal()) { | |||
1499 | const GlobalValue *GVal = MO.getGlobal(); | |||
1500 | auto *GVar = dyn_cast<GlobalVariable>(GVal); | |||
1501 | if (GVar) { | |||
1502 | // Emit "mov ri, <imm>" | |||
1503 | int64_t Imm; | |||
1504 | uint32_t Reloc; | |||
1505 | if (GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr) || | |||
1506 | GVar->hasAttribute(BPFCoreSharedInfo::TypeIdAttr)) { | |||
1507 | Imm = PatchImms[GVar].first; | |||
1508 | Reloc = PatchImms[GVar].second; | |||
1509 | } else { | |||
1510 | return false; | |||
1511 | } | |||
1512 | ||||
1513 | if (Reloc == BPFCoreSharedInfo::ENUM_VALUE_EXISTENCE || | |||
1514 | Reloc == BPFCoreSharedInfo::ENUM_VALUE || | |||
1515 | Reloc == BPFCoreSharedInfo::BTF_TYPE_ID_LOCAL || | |||
1516 | Reloc == BPFCoreSharedInfo::BTF_TYPE_ID_REMOTE) | |||
1517 | OutMI.setOpcode(BPF::LD_imm64); | |||
1518 | else | |||
1519 | OutMI.setOpcode(BPF::MOV_ri); | |||
1520 | OutMI.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); | |||
1521 | OutMI.addOperand(MCOperand::createImm(Imm)); | |||
1522 | return true; | |||
1523 | } | |||
1524 | } | |||
1525 | } else if (MI->getOpcode() == BPF::CORE_MEM || | |||
1526 | MI->getOpcode() == BPF::CORE_ALU32_MEM || | |||
1527 | MI->getOpcode() == BPF::CORE_SHIFT) { | |||
1528 | const MachineOperand &MO = MI->getOperand(3); | |||
1529 | if (MO.isGlobal()) { | |||
1530 | const GlobalValue *GVal = MO.getGlobal(); | |||
1531 | auto *GVar = dyn_cast<GlobalVariable>(GVal); | |||
1532 | if (GVar && GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) { | |||
1533 | uint32_t Imm = PatchImms[GVar].first; | |||
1534 | OutMI.setOpcode(MI->getOperand(1).getImm()); | |||
1535 | if (MI->getOperand(0).isImm()) | |||
1536 | OutMI.addOperand(MCOperand::createImm(MI->getOperand(0).getImm())); | |||
1537 | else | |||
1538 | OutMI.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); | |||
1539 | OutMI.addOperand(MCOperand::createReg(MI->getOperand(2).getReg())); | |||
1540 | OutMI.addOperand(MCOperand::createImm(Imm)); | |||
1541 | return true; | |||
1542 | } | |||
1543 | } | |||
1544 | } | |||
1545 | return false; | |||
1546 | } | |||
1547 | ||||
1548 | void BTFDebug::processFuncPrototypes(const Function *F) { | |||
1549 | if (!F
| |||
1550 | return; | |||
1551 | ||||
1552 | const DISubprogram *SP = F->getSubprogram(); | |||
1553 | if (!SP || SP->isDefinition()) | |||
1554 | return; | |||
1555 | ||||
1556 | // Do not emit again if already emitted. | |||
1557 | if (!ProtoFunctions.insert(F).second) | |||
1558 | return; | |||
1559 | ||||
1560 | uint32_t ProtoTypeId; | |||
1561 | const std::unordered_map<uint32_t, StringRef> FuncArgNames; | |||
1562 | visitSubroutineType(SP->getType(), false, FuncArgNames, ProtoTypeId); | |||
1563 | uint32_t FuncId = processDISubprogram(SP, ProtoTypeId, BTF::FUNC_EXTERN); | |||
| ||||
1564 | ||||
1565 | if (F->hasSection()) { | |||
1566 | StringRef SecName = F->getSection(); | |||
1567 | ||||
1568 | if (DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) { | |||
1569 | DataSecEntries[std::string(SecName)] = | |||
1570 | std::make_unique<BTFKindDataSec>(Asm, std::string(SecName)); | |||
1571 | } | |||
1572 | ||||
1573 | // We really don't know func size, set it to 0. | |||
1574 | DataSecEntries[std::string(SecName)]->addDataSecEntry(FuncId, | |||
1575 | Asm->getSymbol(F), 0); | |||
1576 | } | |||
1577 | } | |||
1578 | ||||
1579 | void BTFDebug::endModule() { | |||
1580 | // Collect MapDef globals if not collected yet. | |||
1581 | if (MapDefNotCollected) { | |||
1582 | processGlobals(true); | |||
1583 | MapDefNotCollected = false; | |||
1584 | } | |||
1585 | ||||
1586 | // Collect global types/variables except MapDef globals. | |||
1587 | processGlobals(false); | |||
1588 | ||||
1589 | for (auto &DataSec : DataSecEntries) | |||
1590 | addType(std::move(DataSec.second)); | |||
1591 | ||||
1592 | // Fixups | |||
1593 | for (auto &Fixup : FixupDerivedTypes) { | |||
1594 | const DICompositeType *CTy = Fixup.first; | |||
1595 | StringRef TypeName = CTy->getName(); | |||
1596 | bool IsUnion = CTy->getTag() == dwarf::DW_TAG_union_type; | |||
1597 | ||||
1598 | // Search through struct types | |||
1599 | uint32_t StructTypeId = 0; | |||
1600 | for (const auto &StructType : StructTypes) { | |||
1601 | if (StructType->getName() == TypeName) { | |||
1602 | StructTypeId = StructType->getId(); | |||
1603 | break; | |||
1604 | } | |||
1605 | } | |||
1606 | ||||
1607 | if (StructTypeId == 0) { | |||
1608 | auto FwdTypeEntry = std::make_unique<BTFTypeFwd>(TypeName, IsUnion); | |||
1609 | StructTypeId = addType(std::move(FwdTypeEntry)); | |||
1610 | } | |||
1611 | ||||
1612 | for (auto &TypeInfo : Fixup.second) { | |||
1613 | const DIDerivedType *DTy = TypeInfo.first; | |||
1614 | BTFTypeDerived *BDType = TypeInfo.second; | |||
1615 | ||||
1616 | int TmpTypeId = genBTFTypeTags(DTy, StructTypeId); | |||
1617 | if (TmpTypeId >= 0) | |||
1618 | BDType->setPointeeType(TmpTypeId); | |||
1619 | else | |||
1620 | BDType->setPointeeType(StructTypeId); | |||
1621 | } | |||
1622 | } | |||
1623 | ||||
1624 | // Complete BTF type cross refereences. | |||
1625 | for (const auto &TypeEntry : TypeEntries) | |||
1626 | TypeEntry->completeType(*this); | |||
1627 | ||||
1628 | // Emit BTF sections. | |||
1629 | emitBTFSection(); | |||
1630 | emitBTFExtSection(); | |||
1631 | } |