1 | //===- ELFObjectFile.cpp - ELF object file implementation -----------------===// |
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 | // Part of the ELFObjectFile class implementation. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/Object/ELFObjectFile.h" |
14 | #include "llvm/BinaryFormat/ELF.h" |
15 | #include "llvm/MC/MCInstrAnalysis.h" |
16 | #include "llvm/MC/TargetRegistry.h" |
17 | #include "llvm/Object/ELF.h" |
18 | #include "llvm/Object/ELFTypes.h" |
19 | #include "llvm/Object/Error.h" |
20 | #include "llvm/Support/ARMAttributeParser.h" |
21 | #include "llvm/Support/ARMBuildAttributes.h" |
22 | #include "llvm/Support/ErrorHandling.h" |
23 | #include "llvm/Support/HexagonAttributeParser.h" |
24 | #include "llvm/Support/RISCVAttributeParser.h" |
25 | #include "llvm/Support/RISCVAttributes.h" |
26 | #include "llvm/TargetParser/RISCVISAInfo.h" |
27 | #include "llvm/TargetParser/SubtargetFeature.h" |
28 | #include "llvm/TargetParser/Triple.h" |
29 | #include <algorithm> |
30 | #include <cstddef> |
31 | #include <cstdint> |
32 | #include <memory> |
33 | #include <optional> |
34 | #include <string> |
35 | #include <utility> |
36 | |
37 | using namespace llvm; |
38 | using namespace object; |
39 | |
40 | const EnumEntry<unsigned> llvm::object::ElfSymbolTypes[NumElfSymbolTypes] = { |
41 | {"None" , "NOTYPE" , ELF::STT_NOTYPE}, |
42 | {"Object" , "OBJECT" , ELF::STT_OBJECT}, |
43 | {"Function" , "FUNC" , ELF::STT_FUNC}, |
44 | {"Section" , "SECTION" , ELF::STT_SECTION}, |
45 | {"File" , "FILE" , ELF::STT_FILE}, |
46 | {"Common" , "COMMON" , ELF::STT_COMMON}, |
47 | {"TLS" , "TLS" , ELF::STT_TLS}, |
48 | {"Unknown" , "<unknown>: 7" , 7}, |
49 | {"Unknown" , "<unknown>: 8" , 8}, |
50 | {"Unknown" , "<unknown>: 9" , 9}, |
51 | {"GNU_IFunc" , "IFUNC" , ELF::STT_GNU_IFUNC}, |
52 | {"OS Specific" , "<OS specific>: 11" , 11}, |
53 | {"OS Specific" , "<OS specific>: 12" , 12}, |
54 | {"Proc Specific" , "<processor specific>: 13" , 13}, |
55 | {"Proc Specific" , "<processor specific>: 14" , 14}, |
56 | {"Proc Specific" , "<processor specific>: 15" , 15} |
57 | }; |
58 | |
59 | ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source) |
60 | : ObjectFile(Type, Source) {} |
61 | |
62 | template <class ELFT> |
63 | static Expected<std::unique_ptr<ELFObjectFile<ELFT>>> |
64 | createPtr(MemoryBufferRef Object, bool InitContent) { |
65 | auto Ret = ELFObjectFile<ELFT>::create(Object, InitContent); |
66 | if (Error E = Ret.takeError()) |
67 | return std::move(E); |
68 | return std::make_unique<ELFObjectFile<ELFT>>(std::move(*Ret)); |
69 | } |
70 | |
71 | Expected<std::unique_ptr<ObjectFile>> |
72 | ObjectFile::createELFObjectFile(MemoryBufferRef Obj, bool InitContent) { |
73 | std::pair<unsigned char, unsigned char> Ident = |
74 | getElfArchType(Object: Obj.getBuffer()); |
75 | std::size_t MaxAlignment = |
76 | 1ULL << llvm::countr_zero( |
77 | Val: reinterpret_cast<uintptr_t>(Obj.getBufferStart())); |
78 | |
79 | if (MaxAlignment < 2) |
80 | return createError(Err: "Insufficient alignment" ); |
81 | |
82 | if (Ident.first == ELF::ELFCLASS32) { |
83 | if (Ident.second == ELF::ELFDATA2LSB) |
84 | return createPtr<ELF32LE>(Object: Obj, InitContent); |
85 | else if (Ident.second == ELF::ELFDATA2MSB) |
86 | return createPtr<ELF32BE>(Object: Obj, InitContent); |
87 | else |
88 | return createError(Err: "Invalid ELF data" ); |
89 | } else if (Ident.first == ELF::ELFCLASS64) { |
90 | if (Ident.second == ELF::ELFDATA2LSB) |
91 | return createPtr<ELF64LE>(Object: Obj, InitContent); |
92 | else if (Ident.second == ELF::ELFDATA2MSB) |
93 | return createPtr<ELF64BE>(Object: Obj, InitContent); |
94 | else |
95 | return createError(Err: "Invalid ELF data" ); |
96 | } |
97 | return createError(Err: "Invalid ELF class" ); |
98 | } |
99 | |
100 | SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const { |
101 | SubtargetFeatures Features; |
102 | unsigned PlatformFlags = getPlatformFlags(); |
103 | |
104 | switch (PlatformFlags & ELF::EF_MIPS_ARCH) { |
105 | case ELF::EF_MIPS_ARCH_1: |
106 | break; |
107 | case ELF::EF_MIPS_ARCH_2: |
108 | Features.AddFeature(String: "mips2" ); |
109 | break; |
110 | case ELF::EF_MIPS_ARCH_3: |
111 | Features.AddFeature(String: "mips3" ); |
112 | break; |
113 | case ELF::EF_MIPS_ARCH_4: |
114 | Features.AddFeature(String: "mips4" ); |
115 | break; |
116 | case ELF::EF_MIPS_ARCH_5: |
117 | Features.AddFeature(String: "mips5" ); |
118 | break; |
119 | case ELF::EF_MIPS_ARCH_32: |
120 | Features.AddFeature(String: "mips32" ); |
121 | break; |
122 | case ELF::EF_MIPS_ARCH_64: |
123 | Features.AddFeature(String: "mips64" ); |
124 | break; |
125 | case ELF::EF_MIPS_ARCH_32R2: |
126 | Features.AddFeature(String: "mips32r2" ); |
127 | break; |
128 | case ELF::EF_MIPS_ARCH_64R2: |
129 | Features.AddFeature(String: "mips64r2" ); |
130 | break; |
131 | case ELF::EF_MIPS_ARCH_32R6: |
132 | Features.AddFeature(String: "mips32r6" ); |
133 | break; |
134 | case ELF::EF_MIPS_ARCH_64R6: |
135 | Features.AddFeature(String: "mips64r6" ); |
136 | break; |
137 | default: |
138 | llvm_unreachable("Unknown EF_MIPS_ARCH value" ); |
139 | } |
140 | |
141 | switch (PlatformFlags & ELF::EF_MIPS_MACH) { |
142 | case ELF::EF_MIPS_MACH_NONE: |
143 | // No feature associated with this value. |
144 | break; |
145 | case ELF::EF_MIPS_MACH_OCTEON: |
146 | Features.AddFeature(String: "cnmips" ); |
147 | break; |
148 | default: |
149 | llvm_unreachable("Unknown EF_MIPS_ARCH value" ); |
150 | } |
151 | |
152 | if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16) |
153 | Features.AddFeature(String: "mips16" ); |
154 | if (PlatformFlags & ELF::EF_MIPS_MICROMIPS) |
155 | Features.AddFeature(String: "micromips" ); |
156 | |
157 | return Features; |
158 | } |
159 | |
160 | SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { |
161 | SubtargetFeatures Features; |
162 | ARMAttributeParser Attributes; |
163 | if (Error E = getBuildAttributes(Attributes)) { |
164 | consumeError(Err: std::move(E)); |
165 | return SubtargetFeatures(); |
166 | } |
167 | |
168 | // both ARMv7-M and R have to support thumb hardware div |
169 | bool isV7 = false; |
170 | std::optional<unsigned> Attr = |
171 | Attributes.getAttributeValue(tag: ARMBuildAttrs::CPU_arch); |
172 | if (Attr) |
173 | isV7 = *Attr == ARMBuildAttrs::v7; |
174 | |
175 | Attr = Attributes.getAttributeValue(tag: ARMBuildAttrs::CPU_arch_profile); |
176 | if (Attr) { |
177 | switch (*Attr) { |
178 | case ARMBuildAttrs::ApplicationProfile: |
179 | Features.AddFeature(String: "aclass" ); |
180 | break; |
181 | case ARMBuildAttrs::RealTimeProfile: |
182 | Features.AddFeature(String: "rclass" ); |
183 | if (isV7) |
184 | Features.AddFeature(String: "hwdiv" ); |
185 | break; |
186 | case ARMBuildAttrs::MicroControllerProfile: |
187 | Features.AddFeature(String: "mclass" ); |
188 | if (isV7) |
189 | Features.AddFeature(String: "hwdiv" ); |
190 | break; |
191 | } |
192 | } |
193 | |
194 | Attr = Attributes.getAttributeValue(tag: ARMBuildAttrs::THUMB_ISA_use); |
195 | if (Attr) { |
196 | switch (*Attr) { |
197 | default: |
198 | break; |
199 | case ARMBuildAttrs::Not_Allowed: |
200 | Features.AddFeature(String: "thumb" , Enable: false); |
201 | Features.AddFeature(String: "thumb2" , Enable: false); |
202 | break; |
203 | case ARMBuildAttrs::AllowThumb32: |
204 | Features.AddFeature(String: "thumb2" ); |
205 | break; |
206 | } |
207 | } |
208 | |
209 | Attr = Attributes.getAttributeValue(tag: ARMBuildAttrs::FP_arch); |
210 | if (Attr) { |
211 | switch (*Attr) { |
212 | default: |
213 | break; |
214 | case ARMBuildAttrs::Not_Allowed: |
215 | Features.AddFeature(String: "vfp2sp" , Enable: false); |
216 | Features.AddFeature(String: "vfp3d16sp" , Enable: false); |
217 | Features.AddFeature(String: "vfp4d16sp" , Enable: false); |
218 | break; |
219 | case ARMBuildAttrs::AllowFPv2: |
220 | Features.AddFeature(String: "vfp2" ); |
221 | break; |
222 | case ARMBuildAttrs::AllowFPv3A: |
223 | case ARMBuildAttrs::AllowFPv3B: |
224 | Features.AddFeature(String: "vfp3" ); |
225 | break; |
226 | case ARMBuildAttrs::AllowFPv4A: |
227 | case ARMBuildAttrs::AllowFPv4B: |
228 | Features.AddFeature(String: "vfp4" ); |
229 | break; |
230 | } |
231 | } |
232 | |
233 | Attr = Attributes.getAttributeValue(tag: ARMBuildAttrs::Advanced_SIMD_arch); |
234 | if (Attr) { |
235 | switch (*Attr) { |
236 | default: |
237 | break; |
238 | case ARMBuildAttrs::Not_Allowed: |
239 | Features.AddFeature(String: "neon" , Enable: false); |
240 | Features.AddFeature(String: "fp16" , Enable: false); |
241 | break; |
242 | case ARMBuildAttrs::AllowNeon: |
243 | Features.AddFeature(String: "neon" ); |
244 | break; |
245 | case ARMBuildAttrs::AllowNeon2: |
246 | Features.AddFeature(String: "neon" ); |
247 | Features.AddFeature(String: "fp16" ); |
248 | break; |
249 | } |
250 | } |
251 | |
252 | Attr = Attributes.getAttributeValue(tag: ARMBuildAttrs::MVE_arch); |
253 | if (Attr) { |
254 | switch (*Attr) { |
255 | default: |
256 | break; |
257 | case ARMBuildAttrs::Not_Allowed: |
258 | Features.AddFeature(String: "mve" , Enable: false); |
259 | Features.AddFeature(String: "mve.fp" , Enable: false); |
260 | break; |
261 | case ARMBuildAttrs::AllowMVEInteger: |
262 | Features.AddFeature(String: "mve.fp" , Enable: false); |
263 | Features.AddFeature(String: "mve" ); |
264 | break; |
265 | case ARMBuildAttrs::AllowMVEIntegerAndFloat: |
266 | Features.AddFeature(String: "mve.fp" ); |
267 | break; |
268 | } |
269 | } |
270 | |
271 | Attr = Attributes.getAttributeValue(tag: ARMBuildAttrs::DIV_use); |
272 | if (Attr) { |
273 | switch (*Attr) { |
274 | default: |
275 | break; |
276 | case ARMBuildAttrs::DisallowDIV: |
277 | Features.AddFeature(String: "hwdiv" , Enable: false); |
278 | Features.AddFeature(String: "hwdiv-arm" , Enable: false); |
279 | break; |
280 | case ARMBuildAttrs::AllowDIVExt: |
281 | Features.AddFeature(String: "hwdiv" ); |
282 | Features.AddFeature(String: "hwdiv-arm" ); |
283 | break; |
284 | } |
285 | } |
286 | |
287 | return Features; |
288 | } |
289 | |
290 | static std::optional<std::string> hexagonAttrToFeatureString(unsigned Attr) { |
291 | switch (Attr) { |
292 | case 5: |
293 | return "v5" ; |
294 | case 55: |
295 | return "v55" ; |
296 | case 60: |
297 | return "v60" ; |
298 | case 62: |
299 | return "v62" ; |
300 | case 65: |
301 | return "v65" ; |
302 | case 67: |
303 | return "v67" ; |
304 | case 68: |
305 | return "v68" ; |
306 | case 69: |
307 | return "v69" ; |
308 | case 71: |
309 | return "v71" ; |
310 | case 73: |
311 | return "v73" ; |
312 | case 75: |
313 | return "v75" ; |
314 | default: |
315 | return {}; |
316 | } |
317 | } |
318 | |
319 | SubtargetFeatures ELFObjectFileBase::getHexagonFeatures() const { |
320 | SubtargetFeatures Features; |
321 | HexagonAttributeParser Parser; |
322 | if (Error E = getBuildAttributes(Attributes&: Parser)) { |
323 | // Return no attributes if none can be read. |
324 | // This behavior is important for backwards compatibility. |
325 | consumeError(Err: std::move(E)); |
326 | return Features; |
327 | } |
328 | std::optional<unsigned> Attr; |
329 | |
330 | if ((Attr = Parser.getAttributeValue(tag: HexagonAttrs::ARCH))) { |
331 | if (std::optional<std::string> FeatureString = |
332 | hexagonAttrToFeatureString(Attr: *Attr)) |
333 | Features.AddFeature(String: *FeatureString); |
334 | } |
335 | |
336 | if ((Attr = Parser.getAttributeValue(tag: HexagonAttrs::HVXARCH))) { |
337 | std::optional<std::string> FeatureString = |
338 | hexagonAttrToFeatureString(Attr: *Attr); |
339 | // There is no corresponding hvx arch for v5 and v55. |
340 | if (FeatureString && *Attr >= 60) |
341 | Features.AddFeature(String: "hvx" + *FeatureString); |
342 | } |
343 | |
344 | if ((Attr = Parser.getAttributeValue(tag: HexagonAttrs::HVXIEEEFP))) |
345 | if (*Attr) |
346 | Features.AddFeature(String: "hvx-ieee-fp" ); |
347 | |
348 | if ((Attr = Parser.getAttributeValue(tag: HexagonAttrs::HVXQFLOAT))) |
349 | if (*Attr) |
350 | Features.AddFeature(String: "hvx-qfloat" ); |
351 | |
352 | if ((Attr = Parser.getAttributeValue(tag: HexagonAttrs::ZREG))) |
353 | if (*Attr) |
354 | Features.AddFeature(String: "zreg" ); |
355 | |
356 | if ((Attr = Parser.getAttributeValue(tag: HexagonAttrs::AUDIO))) |
357 | if (*Attr) |
358 | Features.AddFeature(String: "audio" ); |
359 | |
360 | if ((Attr = Parser.getAttributeValue(tag: HexagonAttrs::CABAC))) |
361 | if (*Attr) |
362 | Features.AddFeature(String: "cabac" ); |
363 | |
364 | return Features; |
365 | } |
366 | |
367 | Expected<SubtargetFeatures> ELFObjectFileBase::getRISCVFeatures() const { |
368 | SubtargetFeatures Features; |
369 | unsigned PlatformFlags = getPlatformFlags(); |
370 | |
371 | if (PlatformFlags & ELF::EF_RISCV_RVC) { |
372 | Features.AddFeature(String: "zca" ); |
373 | } |
374 | |
375 | RISCVAttributeParser Attributes; |
376 | if (Error E = getBuildAttributes(Attributes)) { |
377 | return std::move(E); |
378 | } |
379 | |
380 | std::optional<StringRef> Attr = |
381 | Attributes.getAttributeString(tag: RISCVAttrs::ARCH); |
382 | if (Attr) { |
383 | auto ParseResult = RISCVISAInfo::parseNormalizedArchString(Arch: *Attr); |
384 | if (!ParseResult) |
385 | return ParseResult.takeError(); |
386 | auto &ISAInfo = *ParseResult; |
387 | |
388 | if (ISAInfo->getXLen() == 32) |
389 | Features.AddFeature(String: "64bit" , Enable: false); |
390 | else if (ISAInfo->getXLen() == 64) |
391 | Features.AddFeature(String: "64bit" ); |
392 | else |
393 | llvm_unreachable("XLEN should be 32 or 64." ); |
394 | |
395 | Features.addFeaturesVector(OtherFeatures: ISAInfo->toFeatures()); |
396 | } |
397 | |
398 | return Features; |
399 | } |
400 | |
401 | SubtargetFeatures ELFObjectFileBase::getLoongArchFeatures() const { |
402 | SubtargetFeatures Features; |
403 | |
404 | switch (getPlatformFlags() & ELF::EF_LOONGARCH_ABI_MODIFIER_MASK) { |
405 | case ELF::EF_LOONGARCH_ABI_SOFT_FLOAT: |
406 | break; |
407 | case ELF::EF_LOONGARCH_ABI_DOUBLE_FLOAT: |
408 | Features.AddFeature(String: "d" ); |
409 | // D implies F according to LoongArch ISA spec. |
410 | [[fallthrough]]; |
411 | case ELF::EF_LOONGARCH_ABI_SINGLE_FLOAT: |
412 | Features.AddFeature(String: "f" ); |
413 | break; |
414 | } |
415 | |
416 | return Features; |
417 | } |
418 | |
419 | Expected<SubtargetFeatures> ELFObjectFileBase::getFeatures() const { |
420 | switch (getEMachine()) { |
421 | case ELF::EM_MIPS: |
422 | return getMIPSFeatures(); |
423 | case ELF::EM_ARM: |
424 | return getARMFeatures(); |
425 | case ELF::EM_RISCV: |
426 | return getRISCVFeatures(); |
427 | case ELF::EM_LOONGARCH: |
428 | return getLoongArchFeatures(); |
429 | case ELF::EM_HEXAGON: |
430 | return getHexagonFeatures(); |
431 | default: |
432 | return SubtargetFeatures(); |
433 | } |
434 | } |
435 | |
436 | std::optional<StringRef> ELFObjectFileBase::tryGetCPUName() const { |
437 | switch (getEMachine()) { |
438 | case ELF::EM_AMDGPU: |
439 | return getAMDGPUCPUName(); |
440 | case ELF::EM_CUDA: |
441 | return getNVPTXCPUName(); |
442 | case ELF::EM_PPC: |
443 | case ELF::EM_PPC64: |
444 | return StringRef("future" ); |
445 | case ELF::EM_BPF: |
446 | return StringRef("v4" ); |
447 | default: |
448 | return std::nullopt; |
449 | } |
450 | } |
451 | |
452 | StringRef ELFObjectFileBase::getAMDGPUCPUName() const { |
453 | assert(getEMachine() == ELF::EM_AMDGPU); |
454 | unsigned CPU = getPlatformFlags() & ELF::EF_AMDGPU_MACH; |
455 | |
456 | switch (CPU) { |
457 | // Radeon HD 2000/3000 Series (R600). |
458 | case ELF::EF_AMDGPU_MACH_R600_R600: |
459 | return "r600" ; |
460 | case ELF::EF_AMDGPU_MACH_R600_R630: |
461 | return "r630" ; |
462 | case ELF::EF_AMDGPU_MACH_R600_RS880: |
463 | return "rs880" ; |
464 | case ELF::EF_AMDGPU_MACH_R600_RV670: |
465 | return "rv670" ; |
466 | |
467 | // Radeon HD 4000 Series (R700). |
468 | case ELF::EF_AMDGPU_MACH_R600_RV710: |
469 | return "rv710" ; |
470 | case ELF::EF_AMDGPU_MACH_R600_RV730: |
471 | return "rv730" ; |
472 | case ELF::EF_AMDGPU_MACH_R600_RV770: |
473 | return "rv770" ; |
474 | |
475 | // Radeon HD 5000 Series (Evergreen). |
476 | case ELF::EF_AMDGPU_MACH_R600_CEDAR: |
477 | return "cedar" ; |
478 | case ELF::EF_AMDGPU_MACH_R600_CYPRESS: |
479 | return "cypress" ; |
480 | case ELF::EF_AMDGPU_MACH_R600_JUNIPER: |
481 | return "juniper" ; |
482 | case ELF::EF_AMDGPU_MACH_R600_REDWOOD: |
483 | return "redwood" ; |
484 | case ELF::EF_AMDGPU_MACH_R600_SUMO: |
485 | return "sumo" ; |
486 | |
487 | // Radeon HD 6000 Series (Northern Islands). |
488 | case ELF::EF_AMDGPU_MACH_R600_BARTS: |
489 | return "barts" ; |
490 | case ELF::EF_AMDGPU_MACH_R600_CAICOS: |
491 | return "caicos" ; |
492 | case ELF::EF_AMDGPU_MACH_R600_CAYMAN: |
493 | return "cayman" ; |
494 | case ELF::EF_AMDGPU_MACH_R600_TURKS: |
495 | return "turks" ; |
496 | |
497 | // AMDGCN GFX6. |
498 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX600: |
499 | return "gfx600" ; |
500 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX601: |
501 | return "gfx601" ; |
502 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX602: |
503 | return "gfx602" ; |
504 | |
505 | // AMDGCN GFX7. |
506 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX700: |
507 | return "gfx700" ; |
508 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX701: |
509 | return "gfx701" ; |
510 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX702: |
511 | return "gfx702" ; |
512 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX703: |
513 | return "gfx703" ; |
514 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX704: |
515 | return "gfx704" ; |
516 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX705: |
517 | return "gfx705" ; |
518 | |
519 | // AMDGCN GFX8. |
520 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX801: |
521 | return "gfx801" ; |
522 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX802: |
523 | return "gfx802" ; |
524 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX803: |
525 | return "gfx803" ; |
526 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX805: |
527 | return "gfx805" ; |
528 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX810: |
529 | return "gfx810" ; |
530 | |
531 | // AMDGCN GFX9. |
532 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX900: |
533 | return "gfx900" ; |
534 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX902: |
535 | return "gfx902" ; |
536 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX904: |
537 | return "gfx904" ; |
538 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX906: |
539 | return "gfx906" ; |
540 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX908: |
541 | return "gfx908" ; |
542 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX909: |
543 | return "gfx909" ; |
544 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX90A: |
545 | return "gfx90a" ; |
546 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX90C: |
547 | return "gfx90c" ; |
548 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX942: |
549 | return "gfx942" ; |
550 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX950: |
551 | return "gfx950" ; |
552 | |
553 | // AMDGCN GFX10. |
554 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1010: |
555 | return "gfx1010" ; |
556 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1011: |
557 | return "gfx1011" ; |
558 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1012: |
559 | return "gfx1012" ; |
560 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1013: |
561 | return "gfx1013" ; |
562 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1030: |
563 | return "gfx1030" ; |
564 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1031: |
565 | return "gfx1031" ; |
566 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1032: |
567 | return "gfx1032" ; |
568 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1033: |
569 | return "gfx1033" ; |
570 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1034: |
571 | return "gfx1034" ; |
572 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1035: |
573 | return "gfx1035" ; |
574 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1036: |
575 | return "gfx1036" ; |
576 | |
577 | // AMDGCN GFX11. |
578 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1100: |
579 | return "gfx1100" ; |
580 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1101: |
581 | return "gfx1101" ; |
582 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1102: |
583 | return "gfx1102" ; |
584 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1103: |
585 | return "gfx1103" ; |
586 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1150: |
587 | return "gfx1150" ; |
588 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1151: |
589 | return "gfx1151" ; |
590 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1152: |
591 | return "gfx1152" ; |
592 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1153: |
593 | return "gfx1153" ; |
594 | |
595 | // AMDGCN GFX12. |
596 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1200: |
597 | return "gfx1200" ; |
598 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1201: |
599 | return "gfx1201" ; |
600 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1250: |
601 | return "gfx1250" ; |
602 | |
603 | // Generic AMDGCN targets |
604 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX9_GENERIC: |
605 | return "gfx9-generic" ; |
606 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX9_4_GENERIC: |
607 | return "gfx9-4-generic" ; |
608 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX10_1_GENERIC: |
609 | return "gfx10-1-generic" ; |
610 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX10_3_GENERIC: |
611 | return "gfx10-3-generic" ; |
612 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX11_GENERIC: |
613 | return "gfx11-generic" ; |
614 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX12_GENERIC: |
615 | return "gfx12-generic" ; |
616 | default: |
617 | llvm_unreachable("Unknown EF_AMDGPU_MACH value" ); |
618 | } |
619 | } |
620 | |
621 | StringRef ELFObjectFileBase::getNVPTXCPUName() const { |
622 | assert(getEMachine() == ELF::EM_CUDA); |
623 | unsigned SM = getPlatformFlags() & ELF::EF_CUDA_SM; |
624 | |
625 | switch (SM) { |
626 | // Fermi architecture. |
627 | case ELF::EF_CUDA_SM20: |
628 | return "sm_20" ; |
629 | case ELF::EF_CUDA_SM21: |
630 | return "sm_21" ; |
631 | |
632 | // Kepler architecture. |
633 | case ELF::EF_CUDA_SM30: |
634 | return "sm_30" ; |
635 | case ELF::EF_CUDA_SM32: |
636 | return "sm_32" ; |
637 | case ELF::EF_CUDA_SM35: |
638 | return "sm_35" ; |
639 | case ELF::EF_CUDA_SM37: |
640 | return "sm_37" ; |
641 | |
642 | // Maxwell architecture. |
643 | case ELF::EF_CUDA_SM50: |
644 | return "sm_50" ; |
645 | case ELF::EF_CUDA_SM52: |
646 | return "sm_52" ; |
647 | case ELF::EF_CUDA_SM53: |
648 | return "sm_53" ; |
649 | |
650 | // Pascal architecture. |
651 | case ELF::EF_CUDA_SM60: |
652 | return "sm_60" ; |
653 | case ELF::EF_CUDA_SM61: |
654 | return "sm_61" ; |
655 | case ELF::EF_CUDA_SM62: |
656 | return "sm_62" ; |
657 | |
658 | // Volta architecture. |
659 | case ELF::EF_CUDA_SM70: |
660 | return "sm_70" ; |
661 | case ELF::EF_CUDA_SM72: |
662 | return "sm_72" ; |
663 | |
664 | // Turing architecture. |
665 | case ELF::EF_CUDA_SM75: |
666 | return "sm_75" ; |
667 | |
668 | // Ampere architecture. |
669 | case ELF::EF_CUDA_SM80: |
670 | return "sm_80" ; |
671 | case ELF::EF_CUDA_SM86: |
672 | return "sm_86" ; |
673 | case ELF::EF_CUDA_SM87: |
674 | return "sm_87" ; |
675 | |
676 | // Ada architecture. |
677 | case ELF::EF_CUDA_SM89: |
678 | return "sm_89" ; |
679 | |
680 | // Hopper architecture. |
681 | case ELF::EF_CUDA_SM90: |
682 | return getPlatformFlags() & ELF::EF_CUDA_ACCELERATORS ? "sm_90a" : "sm_90" ; |
683 | default: |
684 | llvm_unreachable("Unknown EF_CUDA_SM value" ); |
685 | } |
686 | } |
687 | |
688 | // FIXME Encode from a tablegen description or target parser. |
689 | void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { |
690 | if (TheTriple.getSubArch() != Triple::NoSubArch) |
691 | return; |
692 | |
693 | ARMAttributeParser Attributes; |
694 | if (Error E = getBuildAttributes(Attributes)) { |
695 | // TODO Propagate Error. |
696 | consumeError(Err: std::move(E)); |
697 | return; |
698 | } |
699 | |
700 | std::string Triple; |
701 | // Default to ARM, but use the triple if it's been set. |
702 | if (TheTriple.isThumb()) |
703 | Triple = "thumb" ; |
704 | else |
705 | Triple = "arm" ; |
706 | |
707 | std::optional<unsigned> Attr = |
708 | Attributes.getAttributeValue(tag: ARMBuildAttrs::CPU_arch); |
709 | if (Attr) { |
710 | switch (*Attr) { |
711 | case ARMBuildAttrs::v4: |
712 | Triple += "v4" ; |
713 | break; |
714 | case ARMBuildAttrs::v4T: |
715 | Triple += "v4t" ; |
716 | break; |
717 | case ARMBuildAttrs::v5T: |
718 | Triple += "v5t" ; |
719 | break; |
720 | case ARMBuildAttrs::v5TE: |
721 | Triple += "v5te" ; |
722 | break; |
723 | case ARMBuildAttrs::v5TEJ: |
724 | Triple += "v5tej" ; |
725 | break; |
726 | case ARMBuildAttrs::v6: |
727 | Triple += "v6" ; |
728 | break; |
729 | case ARMBuildAttrs::v6KZ: |
730 | Triple += "v6kz" ; |
731 | break; |
732 | case ARMBuildAttrs::v6T2: |
733 | Triple += "v6t2" ; |
734 | break; |
735 | case ARMBuildAttrs::v6K: |
736 | Triple += "v6k" ; |
737 | break; |
738 | case ARMBuildAttrs::v7: { |
739 | std::optional<unsigned> ArchProfileAttr = |
740 | Attributes.getAttributeValue(tag: ARMBuildAttrs::CPU_arch_profile); |
741 | if (ArchProfileAttr == ARMBuildAttrs::MicroControllerProfile) |
742 | Triple += "v7m" ; |
743 | else |
744 | Triple += "v7" ; |
745 | break; |
746 | } |
747 | case ARMBuildAttrs::v6_M: |
748 | Triple += "v6m" ; |
749 | break; |
750 | case ARMBuildAttrs::v6S_M: |
751 | Triple += "v6sm" ; |
752 | break; |
753 | case ARMBuildAttrs::v7E_M: |
754 | Triple += "v7em" ; |
755 | break; |
756 | case ARMBuildAttrs::v8_A: |
757 | Triple += "v8a" ; |
758 | break; |
759 | case ARMBuildAttrs::v8_R: |
760 | Triple += "v8r" ; |
761 | break; |
762 | case ARMBuildAttrs::v8_M_Base: |
763 | Triple += "v8m.base" ; |
764 | break; |
765 | case ARMBuildAttrs::v8_M_Main: |
766 | Triple += "v8m.main" ; |
767 | break; |
768 | case ARMBuildAttrs::v8_1_M_Main: |
769 | Triple += "v8.1m.main" ; |
770 | break; |
771 | case ARMBuildAttrs::v9_A: |
772 | Triple += "v9a" ; |
773 | break; |
774 | } |
775 | } |
776 | if (!isLittleEndian()) |
777 | Triple += "eb" ; |
778 | |
779 | TheTriple.setArchName(Triple); |
780 | } |
781 | |
782 | std::vector<ELFPltEntry> |
783 | ELFObjectFileBase::getPltEntries(const MCSubtargetInfo &STI) const { |
784 | std::string Err; |
785 | const auto Triple = makeTriple(); |
786 | const auto *T = TargetRegistry::lookupTarget(TheTriple: Triple, Error&: Err); |
787 | if (!T) |
788 | return {}; |
789 | uint32_t JumpSlotReloc = 0, GlobDatReloc = 0; |
790 | switch (Triple.getArch()) { |
791 | case Triple::x86: |
792 | JumpSlotReloc = ELF::R_386_JUMP_SLOT; |
793 | GlobDatReloc = ELF::R_386_GLOB_DAT; |
794 | break; |
795 | case Triple::x86_64: |
796 | JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT; |
797 | GlobDatReloc = ELF::R_X86_64_GLOB_DAT; |
798 | break; |
799 | case Triple::aarch64: |
800 | case Triple::aarch64_be: |
801 | JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT; |
802 | break; |
803 | case Triple::arm: |
804 | case Triple::armeb: |
805 | case Triple::thumb: |
806 | case Triple::thumbeb: |
807 | JumpSlotReloc = ELF::R_ARM_JUMP_SLOT; |
808 | break; |
809 | case Triple::hexagon: |
810 | JumpSlotReloc = ELF::R_HEX_JMP_SLOT; |
811 | GlobDatReloc = ELF::R_HEX_GLOB_DAT; |
812 | break; |
813 | default: |
814 | return {}; |
815 | } |
816 | std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo()); |
817 | std::unique_ptr<const MCInstrAnalysis> MIA( |
818 | T->createMCInstrAnalysis(Info: MII.get())); |
819 | if (!MIA) |
820 | return {}; |
821 | std::vector<std::pair<uint64_t, uint64_t>> PltEntries; |
822 | std::optional<SectionRef> RelaPlt, RelaDyn; |
823 | uint64_t GotBaseVA = 0; |
824 | for (const SectionRef &Section : sections()) { |
825 | Expected<StringRef> NameOrErr = Section.getName(); |
826 | if (!NameOrErr) { |
827 | consumeError(Err: NameOrErr.takeError()); |
828 | continue; |
829 | } |
830 | StringRef Name = *NameOrErr; |
831 | |
832 | if (Name == ".rela.plt" || Name == ".rel.plt" ) { |
833 | RelaPlt = Section; |
834 | } else if (Name == ".rela.dyn" || Name == ".rel.dyn" ) { |
835 | RelaDyn = Section; |
836 | } else if (Name == ".got.plt" ) { |
837 | GotBaseVA = Section.getAddress(); |
838 | } else if (Name == ".plt" || Name == ".plt.got" ) { |
839 | Expected<StringRef> PltContents = Section.getContents(); |
840 | if (!PltContents) { |
841 | consumeError(Err: PltContents.takeError()); |
842 | return {}; |
843 | } |
844 | llvm::append_range( |
845 | C&: PltEntries, |
846 | R: MIA->findPltEntries(PltSectionVA: Section.getAddress(), |
847 | PltContents: arrayRefFromStringRef(Input: *PltContents), STI)); |
848 | } |
849 | } |
850 | |
851 | // Build a map from GOT entry virtual address to PLT entry virtual address. |
852 | DenseMap<uint64_t, uint64_t> GotToPlt; |
853 | for (auto [Plt, GotPlt] : PltEntries) { |
854 | uint64_t GotPltEntry = GotPlt; |
855 | // An x86-32 PIC PLT uses jmp DWORD PTR [ebx-offset]. Add |
856 | // _GLOBAL_OFFSET_TABLE_ (EBX) to get the .got.plt (or .got) entry address. |
857 | // See X86MCTargetDesc.cpp:findPltEntries for the 1 << 32 bit. |
858 | if (GotPltEntry & (uint64_t(1) << 32) && getEMachine() == ELF::EM_386) |
859 | GotPltEntry = static_cast<int32_t>(GotPltEntry) + GotBaseVA; |
860 | GotToPlt.insert(KV: std::make_pair(x&: GotPltEntry, y&: Plt)); |
861 | } |
862 | |
863 | // Find the relocations in the dynamic relocation table that point to |
864 | // locations in the GOT for which we know the corresponding PLT entry. |
865 | std::vector<ELFPltEntry> Result; |
866 | auto handleRels = [&](iterator_range<relocation_iterator> Rels, |
867 | uint32_t RelType, StringRef PltSec) { |
868 | for (const auto &R : Rels) { |
869 | if (R.getType() != RelType) |
870 | continue; |
871 | auto PltEntryIter = GotToPlt.find(Val: R.getOffset()); |
872 | if (PltEntryIter != GotToPlt.end()) { |
873 | symbol_iterator Sym = R.getSymbol(); |
874 | if (Sym == symbol_end()) |
875 | Result.push_back( |
876 | x: ELFPltEntry{.Section: PltSec, .Symbol: std::nullopt, .Address: PltEntryIter->second}); |
877 | else |
878 | Result.push_back(x: ELFPltEntry{.Section: PltSec, .Symbol: Sym->getRawDataRefImpl(), |
879 | .Address: PltEntryIter->second}); |
880 | } |
881 | } |
882 | }; |
883 | |
884 | if (RelaPlt) |
885 | handleRels(RelaPlt->relocations(), JumpSlotReloc, ".plt" ); |
886 | |
887 | // If a symbol needing a PLT entry also needs a GLOB_DAT relocation, GNU ld's |
888 | // x86 port places the PLT entry in the .plt.got section. |
889 | if (RelaDyn) |
890 | handleRels(RelaDyn->relocations(), GlobDatReloc, ".plt.got" ); |
891 | |
892 | return Result; |
893 | } |
894 | |
895 | template <class ELFT> |
896 | Expected<std::vector<BBAddrMap>> static readBBAddrMapImpl( |
897 | const ELFFile<ELFT> &EF, std::optional<unsigned> TextSectionIndex, |
898 | std::vector<PGOAnalysisMap> *PGOAnalyses) { |
899 | using Elf_Shdr = typename ELFT::Shdr; |
900 | bool IsRelocatable = EF.getHeader().e_type == ELF::ET_REL; |
901 | std::vector<BBAddrMap> BBAddrMaps; |
902 | if (PGOAnalyses) |
903 | PGOAnalyses->clear(); |
904 | |
905 | const auto &Sections = cantFail(EF.sections()); |
906 | auto IsMatch = [&](const Elf_Shdr &Sec) -> Expected<bool> { |
907 | if (Sec.sh_type != ELF::SHT_LLVM_BB_ADDR_MAP) |
908 | return false; |
909 | if (!TextSectionIndex) |
910 | return true; |
911 | Expected<const Elf_Shdr *> TextSecOrErr = EF.getSection(Sec.sh_link); |
912 | if (!TextSecOrErr) |
913 | return createError("unable to get the linked-to section for " + |
914 | describe(EF, Sec) + ": " + |
915 | toString(TextSecOrErr.takeError())); |
916 | assert(*TextSecOrErr >= Sections.begin() && |
917 | "Text section pointer outside of bounds" ); |
918 | if (*TextSectionIndex != |
919 | (unsigned)std::distance(Sections.begin(), *TextSecOrErr)) |
920 | return false; |
921 | return true; |
922 | }; |
923 | |
924 | Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SectionRelocMapOrErr = |
925 | EF.getSectionAndRelocations(IsMatch); |
926 | if (!SectionRelocMapOrErr) |
927 | return SectionRelocMapOrErr.takeError(); |
928 | |
929 | for (auto const &[Sec, RelocSec] : *SectionRelocMapOrErr) { |
930 | if (IsRelocatable && !RelocSec) |
931 | return createError("unable to get relocation section for " + |
932 | describe(EF, *Sec)); |
933 | Expected<std::vector<BBAddrMap>> BBAddrMapOrErr = |
934 | EF.decodeBBAddrMap(*Sec, RelocSec, PGOAnalyses); |
935 | if (!BBAddrMapOrErr) { |
936 | if (PGOAnalyses) |
937 | PGOAnalyses->clear(); |
938 | return createError("unable to read " + describe(EF, *Sec) + ": " + |
939 | toString(E: BBAddrMapOrErr.takeError())); |
940 | } |
941 | std::move(first: BBAddrMapOrErr->begin(), last: BBAddrMapOrErr->end(), |
942 | result: std::back_inserter(x&: BBAddrMaps)); |
943 | } |
944 | if (PGOAnalyses) |
945 | assert(PGOAnalyses->size() == BBAddrMaps.size() && |
946 | "The same number of BBAddrMaps and PGOAnalysisMaps should be " |
947 | "returned when PGO information is requested" ); |
948 | return BBAddrMaps; |
949 | } |
950 | |
951 | template <class ELFT> |
952 | static Expected<std::vector<VersionEntry>> |
953 | readDynsymVersionsImpl(const ELFFile<ELFT> &EF, |
954 | ELFObjectFileBase::elf_symbol_iterator_range Symbols) { |
955 | using Elf_Shdr = typename ELFT::Shdr; |
956 | const Elf_Shdr *VerSec = nullptr; |
957 | const Elf_Shdr *VerNeedSec = nullptr; |
958 | const Elf_Shdr *VerDefSec = nullptr; |
959 | // The user should ensure sections() can't fail here. |
960 | for (const Elf_Shdr &Sec : cantFail(EF.sections())) { |
961 | if (Sec.sh_type == ELF::SHT_GNU_versym) |
962 | VerSec = &Sec; |
963 | else if (Sec.sh_type == ELF::SHT_GNU_verdef) |
964 | VerDefSec = &Sec; |
965 | else if (Sec.sh_type == ELF::SHT_GNU_verneed) |
966 | VerNeedSec = &Sec; |
967 | } |
968 | if (!VerSec) |
969 | return std::vector<VersionEntry>(); |
970 | |
971 | Expected<SmallVector<std::optional<VersionEntry>, 0>> MapOrErr = |
972 | EF.loadVersionMap(VerNeedSec, VerDefSec); |
973 | if (!MapOrErr) |
974 | return MapOrErr.takeError(); |
975 | |
976 | std::vector<VersionEntry> Ret; |
977 | size_t I = 0; |
978 | for (const ELFSymbolRef &Sym : Symbols) { |
979 | ++I; |
980 | Expected<const typename ELFT::Versym *> VerEntryOrErr = |
981 | EF.template getEntry<typename ELFT::Versym>(*VerSec, I); |
982 | if (!VerEntryOrErr) |
983 | return createError("unable to read an entry with index " + Twine(I) + |
984 | " from " + describe(EF, *VerSec) + ": " + |
985 | toString(VerEntryOrErr.takeError())); |
986 | |
987 | Expected<uint32_t> FlagsOrErr = Sym.getFlags(); |
988 | if (!FlagsOrErr) |
989 | return createError(Err: "unable to read flags for symbol with index " + |
990 | Twine(I) + ": " + toString(E: FlagsOrErr.takeError())); |
991 | |
992 | bool IsDefault; |
993 | Expected<StringRef> VerOrErr = EF.getSymbolVersionByIndex( |
994 | (*VerEntryOrErr)->vs_index, IsDefault, *MapOrErr, |
995 | (*FlagsOrErr) & SymbolRef::SF_Undefined); |
996 | if (!VerOrErr) |
997 | return createError("unable to get a version for entry " + Twine(I) + |
998 | " of " + describe(EF, *VerSec) + ": " + |
999 | toString(E: VerOrErr.takeError())); |
1000 | |
1001 | Ret.push_back(x: {.Name: (*VerOrErr).str(), .IsVerDef: IsDefault}); |
1002 | } |
1003 | |
1004 | return Ret; |
1005 | } |
1006 | |
1007 | Expected<std::vector<VersionEntry>> |
1008 | ELFObjectFileBase::readDynsymVersions() const { |
1009 | elf_symbol_iterator_range Symbols = getDynamicSymbolIterators(); |
1010 | if (const auto *Obj = dyn_cast<ELF32LEObjectFile>(Val: this)) |
1011 | return readDynsymVersionsImpl(EF: Obj->getELFFile(), Symbols); |
1012 | if (const auto *Obj = dyn_cast<ELF32BEObjectFile>(Val: this)) |
1013 | return readDynsymVersionsImpl(EF: Obj->getELFFile(), Symbols); |
1014 | if (const auto *Obj = dyn_cast<ELF64LEObjectFile>(Val: this)) |
1015 | return readDynsymVersionsImpl(EF: Obj->getELFFile(), Symbols); |
1016 | return readDynsymVersionsImpl(EF: cast<ELF64BEObjectFile>(Val: this)->getELFFile(), |
1017 | Symbols); |
1018 | } |
1019 | |
1020 | Expected<std::vector<BBAddrMap>> ELFObjectFileBase::readBBAddrMap( |
1021 | std::optional<unsigned> TextSectionIndex, |
1022 | std::vector<PGOAnalysisMap> *PGOAnalyses) const { |
1023 | if (const auto *Obj = dyn_cast<ELF32LEObjectFile>(Val: this)) |
1024 | return readBBAddrMapImpl(EF: Obj->getELFFile(), TextSectionIndex, PGOAnalyses); |
1025 | if (const auto *Obj = dyn_cast<ELF64LEObjectFile>(Val: this)) |
1026 | return readBBAddrMapImpl(EF: Obj->getELFFile(), TextSectionIndex, PGOAnalyses); |
1027 | if (const auto *Obj = dyn_cast<ELF32BEObjectFile>(Val: this)) |
1028 | return readBBAddrMapImpl(EF: Obj->getELFFile(), TextSectionIndex, PGOAnalyses); |
1029 | return readBBAddrMapImpl(EF: cast<ELF64BEObjectFile>(Val: this)->getELFFile(), |
1030 | TextSectionIndex, PGOAnalyses); |
1031 | } |
1032 | |
1033 | StringRef ELFObjectFileBase::getCrelDecodeProblem(SectionRef Sec) const { |
1034 | auto Data = Sec.getRawDataRefImpl(); |
1035 | if (const auto *Obj = dyn_cast<ELF32LEObjectFile>(Val: this)) |
1036 | return Obj->getCrelDecodeProblem(Sec: Data); |
1037 | if (const auto *Obj = dyn_cast<ELF32BEObjectFile>(Val: this)) |
1038 | return Obj->getCrelDecodeProblem(Sec: Data); |
1039 | if (const auto *Obj = dyn_cast<ELF64LEObjectFile>(Val: this)) |
1040 | return Obj->getCrelDecodeProblem(Sec: Data); |
1041 | return cast<ELF64BEObjectFile>(Val: this)->getCrelDecodeProblem(Sec: Data); |
1042 | } |
1043 | |