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/MathExtras.h" |
24 | #include "llvm/Support/RISCVAttributeParser.h" |
25 | #include "llvm/Support/RISCVAttributes.h" |
26 | #include "llvm/Support/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 | Expected<SubtargetFeatures> ELFObjectFileBase::getRISCVFeatures() const { |
291 | SubtargetFeatures Features; |
292 | unsigned PlatformFlags = getPlatformFlags(); |
293 | |
294 | if (PlatformFlags & ELF::EF_RISCV_RVC) { |
295 | Features.AddFeature(String: "zca" ); |
296 | } |
297 | |
298 | RISCVAttributeParser Attributes; |
299 | if (Error E = getBuildAttributes(Attributes)) { |
300 | return std::move(E); |
301 | } |
302 | |
303 | std::optional<StringRef> Attr = |
304 | Attributes.getAttributeString(tag: RISCVAttrs::ARCH); |
305 | if (Attr) { |
306 | auto ParseResult = RISCVISAInfo::parseNormalizedArchString(Arch: *Attr); |
307 | if (!ParseResult) |
308 | return ParseResult.takeError(); |
309 | auto &ISAInfo = *ParseResult; |
310 | |
311 | if (ISAInfo->getXLen() == 32) |
312 | Features.AddFeature(String: "64bit" , Enable: false); |
313 | else if (ISAInfo->getXLen() == 64) |
314 | Features.AddFeature(String: "64bit" ); |
315 | else |
316 | llvm_unreachable("XLEN should be 32 or 64." ); |
317 | |
318 | Features.addFeaturesVector(OtherFeatures: ISAInfo->toFeatures()); |
319 | } |
320 | |
321 | return Features; |
322 | } |
323 | |
324 | SubtargetFeatures ELFObjectFileBase::getLoongArchFeatures() const { |
325 | SubtargetFeatures Features; |
326 | |
327 | switch (getPlatformFlags() & ELF::EF_LOONGARCH_ABI_MODIFIER_MASK) { |
328 | case ELF::EF_LOONGARCH_ABI_SOFT_FLOAT: |
329 | break; |
330 | case ELF::EF_LOONGARCH_ABI_DOUBLE_FLOAT: |
331 | Features.AddFeature(String: "d" ); |
332 | // D implies F according to LoongArch ISA spec. |
333 | [[fallthrough]]; |
334 | case ELF::EF_LOONGARCH_ABI_SINGLE_FLOAT: |
335 | Features.AddFeature(String: "f" ); |
336 | break; |
337 | } |
338 | |
339 | return Features; |
340 | } |
341 | |
342 | Expected<SubtargetFeatures> ELFObjectFileBase::getFeatures() const { |
343 | switch (getEMachine()) { |
344 | case ELF::EM_MIPS: |
345 | return getMIPSFeatures(); |
346 | case ELF::EM_ARM: |
347 | return getARMFeatures(); |
348 | case ELF::EM_RISCV: |
349 | return getRISCVFeatures(); |
350 | case ELF::EM_LOONGARCH: |
351 | return getLoongArchFeatures(); |
352 | default: |
353 | return SubtargetFeatures(); |
354 | } |
355 | } |
356 | |
357 | std::optional<StringRef> ELFObjectFileBase::tryGetCPUName() const { |
358 | switch (getEMachine()) { |
359 | case ELF::EM_AMDGPU: |
360 | return getAMDGPUCPUName(); |
361 | case ELF::EM_CUDA: |
362 | return getNVPTXCPUName(); |
363 | case ELF::EM_PPC: |
364 | case ELF::EM_PPC64: |
365 | return StringRef("future" ); |
366 | default: |
367 | return std::nullopt; |
368 | } |
369 | } |
370 | |
371 | StringRef ELFObjectFileBase::getAMDGPUCPUName() const { |
372 | assert(getEMachine() == ELF::EM_AMDGPU); |
373 | unsigned CPU = getPlatformFlags() & ELF::EF_AMDGPU_MACH; |
374 | |
375 | switch (CPU) { |
376 | // Radeon HD 2000/3000 Series (R600). |
377 | case ELF::EF_AMDGPU_MACH_R600_R600: |
378 | return "r600" ; |
379 | case ELF::EF_AMDGPU_MACH_R600_R630: |
380 | return "r630" ; |
381 | case ELF::EF_AMDGPU_MACH_R600_RS880: |
382 | return "rs880" ; |
383 | case ELF::EF_AMDGPU_MACH_R600_RV670: |
384 | return "rv670" ; |
385 | |
386 | // Radeon HD 4000 Series (R700). |
387 | case ELF::EF_AMDGPU_MACH_R600_RV710: |
388 | return "rv710" ; |
389 | case ELF::EF_AMDGPU_MACH_R600_RV730: |
390 | return "rv730" ; |
391 | case ELF::EF_AMDGPU_MACH_R600_RV770: |
392 | return "rv770" ; |
393 | |
394 | // Radeon HD 5000 Series (Evergreen). |
395 | case ELF::EF_AMDGPU_MACH_R600_CEDAR: |
396 | return "cedar" ; |
397 | case ELF::EF_AMDGPU_MACH_R600_CYPRESS: |
398 | return "cypress" ; |
399 | case ELF::EF_AMDGPU_MACH_R600_JUNIPER: |
400 | return "juniper" ; |
401 | case ELF::EF_AMDGPU_MACH_R600_REDWOOD: |
402 | return "redwood" ; |
403 | case ELF::EF_AMDGPU_MACH_R600_SUMO: |
404 | return "sumo" ; |
405 | |
406 | // Radeon HD 6000 Series (Northern Islands). |
407 | case ELF::EF_AMDGPU_MACH_R600_BARTS: |
408 | return "barts" ; |
409 | case ELF::EF_AMDGPU_MACH_R600_CAICOS: |
410 | return "caicos" ; |
411 | case ELF::EF_AMDGPU_MACH_R600_CAYMAN: |
412 | return "cayman" ; |
413 | case ELF::EF_AMDGPU_MACH_R600_TURKS: |
414 | return "turks" ; |
415 | |
416 | // AMDGCN GFX6. |
417 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX600: |
418 | return "gfx600" ; |
419 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX601: |
420 | return "gfx601" ; |
421 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX602: |
422 | return "gfx602" ; |
423 | |
424 | // AMDGCN GFX7. |
425 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX700: |
426 | return "gfx700" ; |
427 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX701: |
428 | return "gfx701" ; |
429 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX702: |
430 | return "gfx702" ; |
431 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX703: |
432 | return "gfx703" ; |
433 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX704: |
434 | return "gfx704" ; |
435 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX705: |
436 | return "gfx705" ; |
437 | |
438 | // AMDGCN GFX8. |
439 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX801: |
440 | return "gfx801" ; |
441 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX802: |
442 | return "gfx802" ; |
443 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX803: |
444 | return "gfx803" ; |
445 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX805: |
446 | return "gfx805" ; |
447 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX810: |
448 | return "gfx810" ; |
449 | |
450 | // AMDGCN GFX9. |
451 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX900: |
452 | return "gfx900" ; |
453 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX902: |
454 | return "gfx902" ; |
455 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX904: |
456 | return "gfx904" ; |
457 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX906: |
458 | return "gfx906" ; |
459 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX908: |
460 | return "gfx908" ; |
461 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX909: |
462 | return "gfx909" ; |
463 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX90A: |
464 | return "gfx90a" ; |
465 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX90C: |
466 | return "gfx90c" ; |
467 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX940: |
468 | return "gfx940" ; |
469 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX941: |
470 | return "gfx941" ; |
471 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX942: |
472 | return "gfx942" ; |
473 | |
474 | // AMDGCN GFX10. |
475 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1010: |
476 | return "gfx1010" ; |
477 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1011: |
478 | return "gfx1011" ; |
479 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1012: |
480 | return "gfx1012" ; |
481 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1013: |
482 | return "gfx1013" ; |
483 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1030: |
484 | return "gfx1030" ; |
485 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1031: |
486 | return "gfx1031" ; |
487 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1032: |
488 | return "gfx1032" ; |
489 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1033: |
490 | return "gfx1033" ; |
491 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1034: |
492 | return "gfx1034" ; |
493 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1035: |
494 | return "gfx1035" ; |
495 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1036: |
496 | return "gfx1036" ; |
497 | |
498 | // AMDGCN GFX11. |
499 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1100: |
500 | return "gfx1100" ; |
501 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1101: |
502 | return "gfx1101" ; |
503 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1102: |
504 | return "gfx1102" ; |
505 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1103: |
506 | return "gfx1103" ; |
507 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1150: |
508 | return "gfx1150" ; |
509 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1151: |
510 | return "gfx1151" ; |
511 | |
512 | // AMDGCN GFX12. |
513 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1200: |
514 | return "gfx1200" ; |
515 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1201: |
516 | return "gfx1201" ; |
517 | |
518 | // Generic AMDGCN targets |
519 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX9_GENERIC: |
520 | return "gfx9-generic" ; |
521 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX10_1_GENERIC: |
522 | return "gfx10-1-generic" ; |
523 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX10_3_GENERIC: |
524 | return "gfx10-3-generic" ; |
525 | case ELF::EF_AMDGPU_MACH_AMDGCN_GFX11_GENERIC: |
526 | return "gfx11-generic" ; |
527 | default: |
528 | llvm_unreachable("Unknown EF_AMDGPU_MACH value" ); |
529 | } |
530 | } |
531 | |
532 | StringRef ELFObjectFileBase::getNVPTXCPUName() const { |
533 | assert(getEMachine() == ELF::EM_CUDA); |
534 | unsigned SM = getPlatformFlags() & ELF::EF_CUDA_SM; |
535 | |
536 | switch (SM) { |
537 | // Fermi architecture. |
538 | case ELF::EF_CUDA_SM20: |
539 | return "sm_20" ; |
540 | case ELF::EF_CUDA_SM21: |
541 | return "sm_21" ; |
542 | |
543 | // Kepler architecture. |
544 | case ELF::EF_CUDA_SM30: |
545 | return "sm_30" ; |
546 | case ELF::EF_CUDA_SM32: |
547 | return "sm_32" ; |
548 | case ELF::EF_CUDA_SM35: |
549 | return "sm_35" ; |
550 | case ELF::EF_CUDA_SM37: |
551 | return "sm_37" ; |
552 | |
553 | // Maxwell architecture. |
554 | case ELF::EF_CUDA_SM50: |
555 | return "sm_50" ; |
556 | case ELF::EF_CUDA_SM52: |
557 | return "sm_52" ; |
558 | case ELF::EF_CUDA_SM53: |
559 | return "sm_53" ; |
560 | |
561 | // Pascal architecture. |
562 | case ELF::EF_CUDA_SM60: |
563 | return "sm_60" ; |
564 | case ELF::EF_CUDA_SM61: |
565 | return "sm_61" ; |
566 | case ELF::EF_CUDA_SM62: |
567 | return "sm_62" ; |
568 | |
569 | // Volta architecture. |
570 | case ELF::EF_CUDA_SM70: |
571 | return "sm_70" ; |
572 | case ELF::EF_CUDA_SM72: |
573 | return "sm_72" ; |
574 | |
575 | // Turing architecture. |
576 | case ELF::EF_CUDA_SM75: |
577 | return "sm_75" ; |
578 | |
579 | // Ampere architecture. |
580 | case ELF::EF_CUDA_SM80: |
581 | return "sm_80" ; |
582 | case ELF::EF_CUDA_SM86: |
583 | return "sm_86" ; |
584 | case ELF::EF_CUDA_SM87: |
585 | return "sm_87" ; |
586 | |
587 | // Ada architecture. |
588 | case ELF::EF_CUDA_SM89: |
589 | return "sm_89" ; |
590 | |
591 | // Hopper architecture. |
592 | case ELF::EF_CUDA_SM90: |
593 | return getPlatformFlags() & ELF::EF_CUDA_ACCELERATORS ? "sm_90a" : "sm_90" ; |
594 | default: |
595 | llvm_unreachable("Unknown EF_CUDA_SM value" ); |
596 | } |
597 | } |
598 | |
599 | // FIXME Encode from a tablegen description or target parser. |
600 | void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { |
601 | if (TheTriple.getSubArch() != Triple::NoSubArch) |
602 | return; |
603 | |
604 | ARMAttributeParser Attributes; |
605 | if (Error E = getBuildAttributes(Attributes)) { |
606 | // TODO Propagate Error. |
607 | consumeError(Err: std::move(E)); |
608 | return; |
609 | } |
610 | |
611 | std::string Triple; |
612 | // Default to ARM, but use the triple if it's been set. |
613 | if (TheTriple.isThumb()) |
614 | Triple = "thumb" ; |
615 | else |
616 | Triple = "arm" ; |
617 | |
618 | std::optional<unsigned> Attr = |
619 | Attributes.getAttributeValue(tag: ARMBuildAttrs::CPU_arch); |
620 | if (Attr) { |
621 | switch (*Attr) { |
622 | case ARMBuildAttrs::v4: |
623 | Triple += "v4" ; |
624 | break; |
625 | case ARMBuildAttrs::v4T: |
626 | Triple += "v4t" ; |
627 | break; |
628 | case ARMBuildAttrs::v5T: |
629 | Triple += "v5t" ; |
630 | break; |
631 | case ARMBuildAttrs::v5TE: |
632 | Triple += "v5te" ; |
633 | break; |
634 | case ARMBuildAttrs::v5TEJ: |
635 | Triple += "v5tej" ; |
636 | break; |
637 | case ARMBuildAttrs::v6: |
638 | Triple += "v6" ; |
639 | break; |
640 | case ARMBuildAttrs::v6KZ: |
641 | Triple += "v6kz" ; |
642 | break; |
643 | case ARMBuildAttrs::v6T2: |
644 | Triple += "v6t2" ; |
645 | break; |
646 | case ARMBuildAttrs::v6K: |
647 | Triple += "v6k" ; |
648 | break; |
649 | case ARMBuildAttrs::v7: { |
650 | std::optional<unsigned> ArchProfileAttr = |
651 | Attributes.getAttributeValue(tag: ARMBuildAttrs::CPU_arch_profile); |
652 | if (ArchProfileAttr && |
653 | *ArchProfileAttr == ARMBuildAttrs::MicroControllerProfile) |
654 | Triple += "v7m" ; |
655 | else |
656 | Triple += "v7" ; |
657 | break; |
658 | } |
659 | case ARMBuildAttrs::v6_M: |
660 | Triple += "v6m" ; |
661 | break; |
662 | case ARMBuildAttrs::v6S_M: |
663 | Triple += "v6sm" ; |
664 | break; |
665 | case ARMBuildAttrs::v7E_M: |
666 | Triple += "v7em" ; |
667 | break; |
668 | case ARMBuildAttrs::v8_A: |
669 | Triple += "v8a" ; |
670 | break; |
671 | case ARMBuildAttrs::v8_R: |
672 | Triple += "v8r" ; |
673 | break; |
674 | case ARMBuildAttrs::v8_M_Base: |
675 | Triple += "v8m.base" ; |
676 | break; |
677 | case ARMBuildAttrs::v8_M_Main: |
678 | Triple += "v8m.main" ; |
679 | break; |
680 | case ARMBuildAttrs::v8_1_M_Main: |
681 | Triple += "v8.1m.main" ; |
682 | break; |
683 | case ARMBuildAttrs::v9_A: |
684 | Triple += "v9a" ; |
685 | break; |
686 | } |
687 | } |
688 | if (!isLittleEndian()) |
689 | Triple += "eb" ; |
690 | |
691 | TheTriple.setArchName(Triple); |
692 | } |
693 | |
694 | std::vector<ELFPltEntry> ELFObjectFileBase::getPltEntries() const { |
695 | std::string Err; |
696 | const auto Triple = makeTriple(); |
697 | const auto *T = TargetRegistry::lookupTarget(Triple: Triple.str(), Error&: Err); |
698 | if (!T) |
699 | return {}; |
700 | uint32_t JumpSlotReloc = 0, GlobDatReloc = 0; |
701 | switch (Triple.getArch()) { |
702 | case Triple::x86: |
703 | JumpSlotReloc = ELF::R_386_JUMP_SLOT; |
704 | GlobDatReloc = ELF::R_386_GLOB_DAT; |
705 | break; |
706 | case Triple::x86_64: |
707 | JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT; |
708 | GlobDatReloc = ELF::R_X86_64_GLOB_DAT; |
709 | break; |
710 | case Triple::aarch64: |
711 | case Triple::aarch64_be: |
712 | JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT; |
713 | break; |
714 | default: |
715 | return {}; |
716 | } |
717 | std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo()); |
718 | std::unique_ptr<const MCInstrAnalysis> MIA( |
719 | T->createMCInstrAnalysis(Info: MII.get())); |
720 | if (!MIA) |
721 | return {}; |
722 | std::vector<std::pair<uint64_t, uint64_t>> PltEntries; |
723 | std::optional<SectionRef> RelaPlt, RelaDyn; |
724 | uint64_t GotBaseVA = 0; |
725 | for (const SectionRef &Section : sections()) { |
726 | Expected<StringRef> NameOrErr = Section.getName(); |
727 | if (!NameOrErr) { |
728 | consumeError(Err: NameOrErr.takeError()); |
729 | continue; |
730 | } |
731 | StringRef Name = *NameOrErr; |
732 | |
733 | if (Name == ".rela.plt" || Name == ".rel.plt" ) { |
734 | RelaPlt = Section; |
735 | } else if (Name == ".rela.dyn" || Name == ".rel.dyn" ) { |
736 | RelaDyn = Section; |
737 | } else if (Name == ".got.plt" ) { |
738 | GotBaseVA = Section.getAddress(); |
739 | } else if (Name == ".plt" || Name == ".plt.got" ) { |
740 | Expected<StringRef> PltContents = Section.getContents(); |
741 | if (!PltContents) { |
742 | consumeError(Err: PltContents.takeError()); |
743 | return {}; |
744 | } |
745 | llvm::append_range( |
746 | C&: PltEntries, |
747 | R: MIA->findPltEntries(PltSectionVA: Section.getAddress(), |
748 | PltContents: arrayRefFromStringRef(Input: *PltContents), TargetTriple: Triple)); |
749 | } |
750 | } |
751 | |
752 | // Build a map from GOT entry virtual address to PLT entry virtual address. |
753 | DenseMap<uint64_t, uint64_t> GotToPlt; |
754 | for (auto [Plt, GotPlt] : PltEntries) { |
755 | uint64_t GotPltEntry = GotPlt; |
756 | // An x86-32 PIC PLT uses jmp DWORD PTR [ebx-offset]. Add |
757 | // _GLOBAL_OFFSET_TABLE_ (EBX) to get the .got.plt (or .got) entry address. |
758 | // See X86MCTargetDesc.cpp:findPltEntries for the 1 << 32 bit. |
759 | if (GotPltEntry & (uint64_t(1) << 32) && getEMachine() == ELF::EM_386) |
760 | GotPltEntry = static_cast<int32_t>(GotPltEntry) + GotBaseVA; |
761 | GotToPlt.insert(KV: std::make_pair(x&: GotPltEntry, y&: Plt)); |
762 | } |
763 | |
764 | // Find the relocations in the dynamic relocation table that point to |
765 | // locations in the GOT for which we know the corresponding PLT entry. |
766 | std::vector<ELFPltEntry> Result; |
767 | auto handleRels = [&](iterator_range<relocation_iterator> Rels, |
768 | uint32_t RelType, StringRef PltSec) { |
769 | for (const auto &R : Rels) { |
770 | if (R.getType() != RelType) |
771 | continue; |
772 | auto PltEntryIter = GotToPlt.find(Val: R.getOffset()); |
773 | if (PltEntryIter != GotToPlt.end()) { |
774 | symbol_iterator Sym = R.getSymbol(); |
775 | if (Sym == symbol_end()) |
776 | Result.push_back( |
777 | x: ELFPltEntry{.Section: PltSec, .Symbol: std::nullopt, .Address: PltEntryIter->second}); |
778 | else |
779 | Result.push_back(x: ELFPltEntry{.Section: PltSec, .Symbol: Sym->getRawDataRefImpl(), |
780 | .Address: PltEntryIter->second}); |
781 | } |
782 | } |
783 | }; |
784 | |
785 | if (RelaPlt) |
786 | handleRels(RelaPlt->relocations(), JumpSlotReloc, ".plt" ); |
787 | |
788 | // If a symbol needing a PLT entry also needs a GLOB_DAT relocation, GNU ld's |
789 | // x86 port places the PLT entry in the .plt.got section. |
790 | if (RelaDyn) |
791 | handleRels(RelaDyn->relocations(), GlobDatReloc, ".plt.got" ); |
792 | |
793 | return Result; |
794 | } |
795 | |
796 | template <class ELFT> |
797 | Expected<std::vector<BBAddrMap>> static readBBAddrMapImpl( |
798 | const ELFFile<ELFT> &EF, std::optional<unsigned> TextSectionIndex, |
799 | std::vector<PGOAnalysisMap> *PGOAnalyses) { |
800 | using Elf_Shdr = typename ELFT::Shdr; |
801 | bool IsRelocatable = EF.getHeader().e_type == ELF::ET_REL; |
802 | std::vector<BBAddrMap> BBAddrMaps; |
803 | if (PGOAnalyses) |
804 | PGOAnalyses->clear(); |
805 | |
806 | const auto &Sections = cantFail(EF.sections()); |
807 | auto IsMatch = [&](const Elf_Shdr &Sec) -> Expected<bool> { |
808 | if (Sec.sh_type != ELF::SHT_LLVM_BB_ADDR_MAP && |
809 | Sec.sh_type != ELF::SHT_LLVM_BB_ADDR_MAP_V0) |
810 | return false; |
811 | if (!TextSectionIndex) |
812 | return true; |
813 | Expected<const Elf_Shdr *> TextSecOrErr = EF.getSection(Sec.sh_link); |
814 | if (!TextSecOrErr) |
815 | return createError("unable to get the linked-to section for " + |
816 | describe(EF, Sec) + ": " + |
817 | toString(TextSecOrErr.takeError())); |
818 | assert(*TextSecOrErr >= Sections.begin() && |
819 | "Text section pointer outside of bounds" ); |
820 | if (*TextSectionIndex != |
821 | (unsigned)std::distance(Sections.begin(), *TextSecOrErr)) |
822 | return false; |
823 | return true; |
824 | }; |
825 | |
826 | Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SectionRelocMapOrErr = |
827 | EF.getSectionAndRelocations(IsMatch); |
828 | if (!SectionRelocMapOrErr) |
829 | return SectionRelocMapOrErr.takeError(); |
830 | |
831 | for (auto const &[Sec, RelocSec] : *SectionRelocMapOrErr) { |
832 | if (IsRelocatable && !RelocSec) |
833 | return createError("unable to get relocation section for " + |
834 | describe(EF, *Sec)); |
835 | Expected<std::vector<BBAddrMap>> BBAddrMapOrErr = |
836 | EF.decodeBBAddrMap(*Sec, RelocSec, PGOAnalyses); |
837 | if (!BBAddrMapOrErr) { |
838 | if (PGOAnalyses) |
839 | PGOAnalyses->clear(); |
840 | return createError("unable to read " + describe(EF, *Sec) + ": " + |
841 | toString(E: BBAddrMapOrErr.takeError())); |
842 | } |
843 | std::move(first: BBAddrMapOrErr->begin(), last: BBAddrMapOrErr->end(), |
844 | result: std::back_inserter(x&: BBAddrMaps)); |
845 | } |
846 | if (PGOAnalyses) |
847 | assert(PGOAnalyses->size() == BBAddrMaps.size() && |
848 | "The same number of BBAddrMaps and PGOAnalysisMaps should be " |
849 | "returned when PGO information is requested" ); |
850 | return BBAddrMaps; |
851 | } |
852 | |
853 | template <class ELFT> |
854 | static Expected<std::vector<VersionEntry>> |
855 | readDynsymVersionsImpl(const ELFFile<ELFT> &EF, |
856 | ELFObjectFileBase::elf_symbol_iterator_range Symbols) { |
857 | using Elf_Shdr = typename ELFT::Shdr; |
858 | const Elf_Shdr *VerSec = nullptr; |
859 | const Elf_Shdr *VerNeedSec = nullptr; |
860 | const Elf_Shdr *VerDefSec = nullptr; |
861 | // The user should ensure sections() can't fail here. |
862 | for (const Elf_Shdr &Sec : cantFail(EF.sections())) { |
863 | if (Sec.sh_type == ELF::SHT_GNU_versym) |
864 | VerSec = &Sec; |
865 | else if (Sec.sh_type == ELF::SHT_GNU_verdef) |
866 | VerDefSec = &Sec; |
867 | else if (Sec.sh_type == ELF::SHT_GNU_verneed) |
868 | VerNeedSec = &Sec; |
869 | } |
870 | if (!VerSec) |
871 | return std::vector<VersionEntry>(); |
872 | |
873 | Expected<SmallVector<std::optional<VersionEntry>, 0>> MapOrErr = |
874 | EF.loadVersionMap(VerNeedSec, VerDefSec); |
875 | if (!MapOrErr) |
876 | return MapOrErr.takeError(); |
877 | |
878 | std::vector<VersionEntry> Ret; |
879 | size_t I = 0; |
880 | for (const ELFSymbolRef &Sym : Symbols) { |
881 | ++I; |
882 | Expected<const typename ELFT::Versym *> VerEntryOrErr = |
883 | EF.template getEntry<typename ELFT::Versym>(*VerSec, I); |
884 | if (!VerEntryOrErr) |
885 | return createError("unable to read an entry with index " + Twine(I) + |
886 | " from " + describe(EF, *VerSec) + ": " + |
887 | toString(VerEntryOrErr.takeError())); |
888 | |
889 | Expected<uint32_t> FlagsOrErr = Sym.getFlags(); |
890 | if (!FlagsOrErr) |
891 | return createError(Err: "unable to read flags for symbol with index " + |
892 | Twine(I) + ": " + toString(E: FlagsOrErr.takeError())); |
893 | |
894 | bool IsDefault; |
895 | Expected<StringRef> VerOrErr = EF.getSymbolVersionByIndex( |
896 | (*VerEntryOrErr)->vs_index, IsDefault, *MapOrErr, |
897 | (*FlagsOrErr) & SymbolRef::SF_Undefined); |
898 | if (!VerOrErr) |
899 | return createError("unable to get a version for entry " + Twine(I) + |
900 | " of " + describe(EF, *VerSec) + ": " + |
901 | toString(E: VerOrErr.takeError())); |
902 | |
903 | Ret.push_back(x: {.Name: (*VerOrErr).str(), .IsVerDef: IsDefault}); |
904 | } |
905 | |
906 | return Ret; |
907 | } |
908 | |
909 | Expected<std::vector<VersionEntry>> |
910 | ELFObjectFileBase::readDynsymVersions() const { |
911 | elf_symbol_iterator_range Symbols = getDynamicSymbolIterators(); |
912 | if (const auto *Obj = dyn_cast<ELF32LEObjectFile>(Val: this)) |
913 | return readDynsymVersionsImpl(EF: Obj->getELFFile(), Symbols); |
914 | if (const auto *Obj = dyn_cast<ELF32BEObjectFile>(Val: this)) |
915 | return readDynsymVersionsImpl(EF: Obj->getELFFile(), Symbols); |
916 | if (const auto *Obj = dyn_cast<ELF64LEObjectFile>(Val: this)) |
917 | return readDynsymVersionsImpl(EF: Obj->getELFFile(), Symbols); |
918 | return readDynsymVersionsImpl(EF: cast<ELF64BEObjectFile>(Val: this)->getELFFile(), |
919 | Symbols); |
920 | } |
921 | |
922 | Expected<std::vector<BBAddrMap>> ELFObjectFileBase::readBBAddrMap( |
923 | std::optional<unsigned> TextSectionIndex, |
924 | std::vector<PGOAnalysisMap> *PGOAnalyses) const { |
925 | if (const auto *Obj = dyn_cast<ELF32LEObjectFile>(Val: this)) |
926 | return readBBAddrMapImpl(EF: Obj->getELFFile(), TextSectionIndex, PGOAnalyses); |
927 | if (const auto *Obj = dyn_cast<ELF64LEObjectFile>(Val: this)) |
928 | return readBBAddrMapImpl(EF: Obj->getELFFile(), TextSectionIndex, PGOAnalyses); |
929 | if (const auto *Obj = dyn_cast<ELF32BEObjectFile>(Val: this)) |
930 | return readBBAddrMapImpl(EF: Obj->getELFFile(), TextSectionIndex, PGOAnalyses); |
931 | return readBBAddrMapImpl(EF: cast<ELF64BEObjectFile>(Val: this)->getELFFile(), |
932 | TextSectionIndex, PGOAnalyses); |
933 | } |
934 | |