[ARM] MVE integer min and max
[llvm-complete.git] / lib / Object / ELFObjectFile.cpp
blobc7b715793048c28cbc12cb384ff48af33eb096e5
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.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/Object/ELFObjectFile.h"
14 #include "llvm/ADT/Triple.h"
15 #include "llvm/BinaryFormat/ELF.h"
16 #include "llvm/MC/MCInstrAnalysis.h"
17 #include "llvm/MC/SubtargetFeature.h"
18 #include "llvm/Object/ELF.h"
19 #include "llvm/Object/ELFTypes.h"
20 #include "llvm/Object/Error.h"
21 #include "llvm/Support/ARMAttributeParser.h"
22 #include "llvm/Support/ARMBuildAttributes.h"
23 #include "llvm/Support/Endian.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include "llvm/Support/MathExtras.h"
26 #include "llvm/Support/TargetRegistry.h"
27 #include <algorithm>
28 #include <cstddef>
29 #include <cstdint>
30 #include <memory>
31 #include <string>
32 #include <system_error>
33 #include <utility>
35 using namespace llvm;
36 using namespace object;
38 const EnumEntry<unsigned> llvm::object::ElfSymbolTypes[NumElfSymbolTypes] = {
39 {"None", "NOTYPE", ELF::STT_NOTYPE},
40 {"Object", "OBJECT", ELF::STT_OBJECT},
41 {"Function", "FUNC", ELF::STT_FUNC},
42 {"Section", "SECTION", ELF::STT_SECTION},
43 {"File", "FILE", ELF::STT_FILE},
44 {"Common", "COMMON", ELF::STT_COMMON},
45 {"TLS", "TLS", ELF::STT_TLS},
46 {"GNU_IFunc", "IFUNC", ELF::STT_GNU_IFUNC}};
48 ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
49 : ObjectFile(Type, Source) {}
51 template <class ELFT>
52 static Expected<std::unique_ptr<ELFObjectFile<ELFT>>>
53 createPtr(MemoryBufferRef Object) {
54 auto Ret = ELFObjectFile<ELFT>::create(Object);
55 if (Error E = Ret.takeError())
56 return std::move(E);
57 return make_unique<ELFObjectFile<ELFT>>(std::move(*Ret));
60 Expected<std::unique_ptr<ObjectFile>>
61 ObjectFile::createELFObjectFile(MemoryBufferRef Obj) {
62 std::pair<unsigned char, unsigned char> Ident =
63 getElfArchType(Obj.getBuffer());
64 std::size_t MaxAlignment =
65 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart()));
67 if (MaxAlignment < 2)
68 return createError("Insufficient alignment");
70 if (Ident.first == ELF::ELFCLASS32) {
71 if (Ident.second == ELF::ELFDATA2LSB)
72 return createPtr<ELF32LE>(Obj);
73 else if (Ident.second == ELF::ELFDATA2MSB)
74 return createPtr<ELF32BE>(Obj);
75 else
76 return createError("Invalid ELF data");
77 } else if (Ident.first == ELF::ELFCLASS64) {
78 if (Ident.second == ELF::ELFDATA2LSB)
79 return createPtr<ELF64LE>(Obj);
80 else if (Ident.second == ELF::ELFDATA2MSB)
81 return createPtr<ELF64BE>(Obj);
82 else
83 return createError("Invalid ELF data");
85 return createError("Invalid ELF class");
88 SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const {
89 SubtargetFeatures Features;
90 unsigned PlatformFlags = getPlatformFlags();
92 switch (PlatformFlags & ELF::EF_MIPS_ARCH) {
93 case ELF::EF_MIPS_ARCH_1:
94 break;
95 case ELF::EF_MIPS_ARCH_2:
96 Features.AddFeature("mips2");
97 break;
98 case ELF::EF_MIPS_ARCH_3:
99 Features.AddFeature("mips3");
100 break;
101 case ELF::EF_MIPS_ARCH_4:
102 Features.AddFeature("mips4");
103 break;
104 case ELF::EF_MIPS_ARCH_5:
105 Features.AddFeature("mips5");
106 break;
107 case ELF::EF_MIPS_ARCH_32:
108 Features.AddFeature("mips32");
109 break;
110 case ELF::EF_MIPS_ARCH_64:
111 Features.AddFeature("mips64");
112 break;
113 case ELF::EF_MIPS_ARCH_32R2:
114 Features.AddFeature("mips32r2");
115 break;
116 case ELF::EF_MIPS_ARCH_64R2:
117 Features.AddFeature("mips64r2");
118 break;
119 case ELF::EF_MIPS_ARCH_32R6:
120 Features.AddFeature("mips32r6");
121 break;
122 case ELF::EF_MIPS_ARCH_64R6:
123 Features.AddFeature("mips64r6");
124 break;
125 default:
126 llvm_unreachable("Unknown EF_MIPS_ARCH value");
129 switch (PlatformFlags & ELF::EF_MIPS_MACH) {
130 case ELF::EF_MIPS_MACH_NONE:
131 // No feature associated with this value.
132 break;
133 case ELF::EF_MIPS_MACH_OCTEON:
134 Features.AddFeature("cnmips");
135 break;
136 default:
137 llvm_unreachable("Unknown EF_MIPS_ARCH value");
140 if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16)
141 Features.AddFeature("mips16");
142 if (PlatformFlags & ELF::EF_MIPS_MICROMIPS)
143 Features.AddFeature("micromips");
145 return Features;
148 SubtargetFeatures ELFObjectFileBase::getARMFeatures() const {
149 SubtargetFeatures Features;
150 ARMAttributeParser Attributes;
151 if (Error E = getBuildAttributes(Attributes))
152 return SubtargetFeatures();
154 // both ARMv7-M and R have to support thumb hardware div
155 bool isV7 = false;
156 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch))
157 isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)
158 == ARMBuildAttrs::v7;
160 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) {
161 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) {
162 case ARMBuildAttrs::ApplicationProfile:
163 Features.AddFeature("aclass");
164 break;
165 case ARMBuildAttrs::RealTimeProfile:
166 Features.AddFeature("rclass");
167 if (isV7)
168 Features.AddFeature("hwdiv");
169 break;
170 case ARMBuildAttrs::MicroControllerProfile:
171 Features.AddFeature("mclass");
172 if (isV7)
173 Features.AddFeature("hwdiv");
174 break;
178 if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) {
179 switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) {
180 default:
181 break;
182 case ARMBuildAttrs::Not_Allowed:
183 Features.AddFeature("thumb", false);
184 Features.AddFeature("thumb2", false);
185 break;
186 case ARMBuildAttrs::AllowThumb32:
187 Features.AddFeature("thumb2");
188 break;
192 if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) {
193 switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) {
194 default:
195 break;
196 case ARMBuildAttrs::Not_Allowed:
197 Features.AddFeature("vfp2d16sp", false);
198 Features.AddFeature("vfp3d16sp", false);
199 Features.AddFeature("vfp4d16sp", false);
200 break;
201 case ARMBuildAttrs::AllowFPv2:
202 Features.AddFeature("vfp2");
203 break;
204 case ARMBuildAttrs::AllowFPv3A:
205 case ARMBuildAttrs::AllowFPv3B:
206 Features.AddFeature("vfp3");
207 break;
208 case ARMBuildAttrs::AllowFPv4A:
209 case ARMBuildAttrs::AllowFPv4B:
210 Features.AddFeature("vfp4");
211 break;
215 if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) {
216 switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) {
217 default:
218 break;
219 case ARMBuildAttrs::Not_Allowed:
220 Features.AddFeature("neon", false);
221 Features.AddFeature("fp16", false);
222 break;
223 case ARMBuildAttrs::AllowNeon:
224 Features.AddFeature("neon");
225 break;
226 case ARMBuildAttrs::AllowNeon2:
227 Features.AddFeature("neon");
228 Features.AddFeature("fp16");
229 break;
233 if (Attributes.hasAttribute(ARMBuildAttrs::MVE_arch)) {
234 switch(Attributes.getAttributeValue(ARMBuildAttrs::MVE_arch)) {
235 default:
236 break;
237 case ARMBuildAttrs::Not_Allowed:
238 Features.AddFeature("mve", false);
239 Features.AddFeature("mve.fp", false);
240 break;
241 case ARMBuildAttrs::AllowMVEInteger:
242 Features.AddFeature("mve.fp", false);
243 Features.AddFeature("mve");
244 break;
245 case ARMBuildAttrs::AllowMVEIntegerAndFloat:
246 Features.AddFeature("mve.fp");
247 break;
251 if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) {
252 switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) {
253 default:
254 break;
255 case ARMBuildAttrs::DisallowDIV:
256 Features.AddFeature("hwdiv", false);
257 Features.AddFeature("hwdiv-arm", false);
258 break;
259 case ARMBuildAttrs::AllowDIVExt:
260 Features.AddFeature("hwdiv");
261 Features.AddFeature("hwdiv-arm");
262 break;
266 return Features;
269 SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const {
270 SubtargetFeatures Features;
271 unsigned PlatformFlags = getPlatformFlags();
273 if (PlatformFlags & ELF::EF_RISCV_RVC) {
274 Features.AddFeature("c");
277 return Features;
280 SubtargetFeatures ELFObjectFileBase::getFeatures() const {
281 switch (getEMachine()) {
282 case ELF::EM_MIPS:
283 return getMIPSFeatures();
284 case ELF::EM_ARM:
285 return getARMFeatures();
286 case ELF::EM_RISCV:
287 return getRISCVFeatures();
288 default:
289 return SubtargetFeatures();
293 // FIXME Encode from a tablegen description or target parser.
294 void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
295 if (TheTriple.getSubArch() != Triple::NoSubArch)
296 return;
298 ARMAttributeParser Attributes;
299 if (Error E = getBuildAttributes(Attributes))
300 return;
302 std::string Triple;
303 // Default to ARM, but use the triple if it's been set.
304 if (TheTriple.isThumb())
305 Triple = "thumb";
306 else
307 Triple = "arm";
309 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
310 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
311 case ARMBuildAttrs::v4:
312 Triple += "v4";
313 break;
314 case ARMBuildAttrs::v4T:
315 Triple += "v4t";
316 break;
317 case ARMBuildAttrs::v5T:
318 Triple += "v5t";
319 break;
320 case ARMBuildAttrs::v5TE:
321 Triple += "v5te";
322 break;
323 case ARMBuildAttrs::v5TEJ:
324 Triple += "v5tej";
325 break;
326 case ARMBuildAttrs::v6:
327 Triple += "v6";
328 break;
329 case ARMBuildAttrs::v6KZ:
330 Triple += "v6kz";
331 break;
332 case ARMBuildAttrs::v6T2:
333 Triple += "v6t2";
334 break;
335 case ARMBuildAttrs::v6K:
336 Triple += "v6k";
337 break;
338 case ARMBuildAttrs::v7:
339 Triple += "v7";
340 break;
341 case ARMBuildAttrs::v6_M:
342 Triple += "v6m";
343 break;
344 case ARMBuildAttrs::v6S_M:
345 Triple += "v6sm";
346 break;
347 case ARMBuildAttrs::v7E_M:
348 Triple += "v7em";
349 break;
352 if (!isLittleEndian())
353 Triple += "eb";
355 TheTriple.setArchName(Triple);
358 std::vector<std::pair<DataRefImpl, uint64_t>>
359 ELFObjectFileBase::getPltAddresses() const {
360 std::string Err;
361 const auto Triple = makeTriple();
362 const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err);
363 if (!T)
364 return {};
365 uint64_t JumpSlotReloc = 0;
366 switch (Triple.getArch()) {
367 case Triple::x86:
368 JumpSlotReloc = ELF::R_386_JUMP_SLOT;
369 break;
370 case Triple::x86_64:
371 JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT;
372 break;
373 case Triple::aarch64:
374 JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT;
375 break;
376 default:
377 return {};
379 std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo());
380 std::unique_ptr<const MCInstrAnalysis> MIA(
381 T->createMCInstrAnalysis(MII.get()));
382 if (!MIA)
383 return {};
384 Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None;
385 for (const SectionRef &Section : sections()) {
386 StringRef Name;
387 if (Section.getName(Name))
388 continue;
389 if (Name == ".plt")
390 Plt = Section;
391 else if (Name == ".rela.plt" || Name == ".rel.plt")
392 RelaPlt = Section;
393 else if (Name == ".got.plt")
394 GotPlt = Section;
396 if (!Plt || !RelaPlt || !GotPlt)
397 return {};
398 Expected<StringRef> PltContents = Plt->getContents();
399 if (!PltContents) {
400 consumeError(PltContents.takeError());
401 return {};
403 auto PltEntries = MIA->findPltEntries(Plt->getAddress(),
404 arrayRefFromStringRef(*PltContents),
405 GotPlt->getAddress(), Triple);
406 // Build a map from GOT entry virtual address to PLT entry virtual address.
407 DenseMap<uint64_t, uint64_t> GotToPlt;
408 for (const auto &Entry : PltEntries)
409 GotToPlt.insert(std::make_pair(Entry.second, Entry.first));
410 // Find the relocations in the dynamic relocation table that point to
411 // locations in the GOT for which we know the corresponding PLT entry.
412 std::vector<std::pair<DataRefImpl, uint64_t>> Result;
413 for (const auto &Relocation : RelaPlt->relocations()) {
414 if (Relocation.getType() != JumpSlotReloc)
415 continue;
416 auto PltEntryIter = GotToPlt.find(Relocation.getOffset());
417 if (PltEntryIter != GotToPlt.end())
418 Result.push_back(std::make_pair(
419 Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second));
421 return Result;