1 //===- ELFObjectFile.cpp - ELF object file implementation -----------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // 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"
32 #include <system_error>
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 {"Unknown", "<unknown>: 7", 7},
47 {"Unknown", "<unknown>: 8", 8},
48 {"Unknown", "<unknown>: 9", 9},
49 {"GNU_IFunc", "IFUNC", ELF::STT_GNU_IFUNC},
50 {"OS Specific", "<OS specific>: 11", 11},
51 {"OS Specific", "<OS specific>: 12", 12},
52 {"Proc Specific", "<processor specific>: 13", 13},
53 {"Proc Specific", "<processor specific>: 14", 14},
54 {"Proc Specific", "<processor specific>: 15", 15}
57 ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
58 : ObjectFile(Type, Source) {}
61 static Expected<std::unique_ptr<ELFObjectFile<ELFT>>>
62 createPtr(MemoryBufferRef Object) {
63 auto Ret = ELFObjectFile<ELFT>::create(Object);
64 if (Error E = Ret.takeError())
66 return std::make_unique<ELFObjectFile<ELFT>>(std::move(*Ret));
69 Expected<std::unique_ptr<ObjectFile>>
70 ObjectFile::createELFObjectFile(MemoryBufferRef Obj) {
71 std::pair<unsigned char, unsigned char> Ident =
72 getElfArchType(Obj.getBuffer());
73 std::size_t MaxAlignment =
74 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart()));
77 return createError("Insufficient alignment");
79 if (Ident.first == ELF::ELFCLASS32) {
80 if (Ident.second == ELF::ELFDATA2LSB)
81 return createPtr<ELF32LE>(Obj);
82 else if (Ident.second == ELF::ELFDATA2MSB)
83 return createPtr<ELF32BE>(Obj);
85 return createError("Invalid ELF data");
86 } else if (Ident.first == ELF::ELFCLASS64) {
87 if (Ident.second == ELF::ELFDATA2LSB)
88 return createPtr<ELF64LE>(Obj);
89 else if (Ident.second == ELF::ELFDATA2MSB)
90 return createPtr<ELF64BE>(Obj);
92 return createError("Invalid ELF data");
94 return createError("Invalid ELF class");
97 SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const {
98 SubtargetFeatures Features;
99 unsigned PlatformFlags = getPlatformFlags();
101 switch (PlatformFlags & ELF::EF_MIPS_ARCH) {
102 case ELF::EF_MIPS_ARCH_1:
104 case ELF::EF_MIPS_ARCH_2:
105 Features.AddFeature("mips2");
107 case ELF::EF_MIPS_ARCH_3:
108 Features.AddFeature("mips3");
110 case ELF::EF_MIPS_ARCH_4:
111 Features.AddFeature("mips4");
113 case ELF::EF_MIPS_ARCH_5:
114 Features.AddFeature("mips5");
116 case ELF::EF_MIPS_ARCH_32:
117 Features.AddFeature("mips32");
119 case ELF::EF_MIPS_ARCH_64:
120 Features.AddFeature("mips64");
122 case ELF::EF_MIPS_ARCH_32R2:
123 Features.AddFeature("mips32r2");
125 case ELF::EF_MIPS_ARCH_64R2:
126 Features.AddFeature("mips64r2");
128 case ELF::EF_MIPS_ARCH_32R6:
129 Features.AddFeature("mips32r6");
131 case ELF::EF_MIPS_ARCH_64R6:
132 Features.AddFeature("mips64r6");
135 llvm_unreachable("Unknown EF_MIPS_ARCH value");
138 switch (PlatformFlags & ELF::EF_MIPS_MACH) {
139 case ELF::EF_MIPS_MACH_NONE:
140 // No feature associated with this value.
142 case ELF::EF_MIPS_MACH_OCTEON:
143 Features.AddFeature("cnmips");
146 llvm_unreachable("Unknown EF_MIPS_ARCH value");
149 if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16)
150 Features.AddFeature("mips16");
151 if (PlatformFlags & ELF::EF_MIPS_MICROMIPS)
152 Features.AddFeature("micromips");
157 SubtargetFeatures ELFObjectFileBase::getARMFeatures() const {
158 SubtargetFeatures Features;
159 ARMAttributeParser Attributes;
160 if (Error E = getBuildAttributes(Attributes))
161 return SubtargetFeatures();
163 // both ARMv7-M and R have to support thumb hardware div
165 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch))
166 isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)
167 == ARMBuildAttrs::v7;
169 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) {
170 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) {
171 case ARMBuildAttrs::ApplicationProfile:
172 Features.AddFeature("aclass");
174 case ARMBuildAttrs::RealTimeProfile:
175 Features.AddFeature("rclass");
177 Features.AddFeature("hwdiv");
179 case ARMBuildAttrs::MicroControllerProfile:
180 Features.AddFeature("mclass");
182 Features.AddFeature("hwdiv");
187 if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) {
188 switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) {
191 case ARMBuildAttrs::Not_Allowed:
192 Features.AddFeature("thumb", false);
193 Features.AddFeature("thumb2", false);
195 case ARMBuildAttrs::AllowThumb32:
196 Features.AddFeature("thumb2");
201 if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) {
202 switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) {
205 case ARMBuildAttrs::Not_Allowed:
206 Features.AddFeature("vfp2sp", false);
207 Features.AddFeature("vfp3d16sp", false);
208 Features.AddFeature("vfp4d16sp", false);
210 case ARMBuildAttrs::AllowFPv2:
211 Features.AddFeature("vfp2");
213 case ARMBuildAttrs::AllowFPv3A:
214 case ARMBuildAttrs::AllowFPv3B:
215 Features.AddFeature("vfp3");
217 case ARMBuildAttrs::AllowFPv4A:
218 case ARMBuildAttrs::AllowFPv4B:
219 Features.AddFeature("vfp4");
224 if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) {
225 switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) {
228 case ARMBuildAttrs::Not_Allowed:
229 Features.AddFeature("neon", false);
230 Features.AddFeature("fp16", false);
232 case ARMBuildAttrs::AllowNeon:
233 Features.AddFeature("neon");
235 case ARMBuildAttrs::AllowNeon2:
236 Features.AddFeature("neon");
237 Features.AddFeature("fp16");
242 if (Attributes.hasAttribute(ARMBuildAttrs::MVE_arch)) {
243 switch(Attributes.getAttributeValue(ARMBuildAttrs::MVE_arch)) {
246 case ARMBuildAttrs::Not_Allowed:
247 Features.AddFeature("mve", false);
248 Features.AddFeature("mve.fp", false);
250 case ARMBuildAttrs::AllowMVEInteger:
251 Features.AddFeature("mve.fp", false);
252 Features.AddFeature("mve");
254 case ARMBuildAttrs::AllowMVEIntegerAndFloat:
255 Features.AddFeature("mve.fp");
260 if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) {
261 switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) {
264 case ARMBuildAttrs::DisallowDIV:
265 Features.AddFeature("hwdiv", false);
266 Features.AddFeature("hwdiv-arm", false);
268 case ARMBuildAttrs::AllowDIVExt:
269 Features.AddFeature("hwdiv");
270 Features.AddFeature("hwdiv-arm");
278 SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const {
279 SubtargetFeatures Features;
280 unsigned PlatformFlags = getPlatformFlags();
282 if (PlatformFlags & ELF::EF_RISCV_RVC) {
283 Features.AddFeature("c");
289 SubtargetFeatures ELFObjectFileBase::getFeatures() const {
290 switch (getEMachine()) {
292 return getMIPSFeatures();
294 return getARMFeatures();
296 return getRISCVFeatures();
298 return SubtargetFeatures();
302 // FIXME Encode from a tablegen description or target parser.
303 void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
304 if (TheTriple.getSubArch() != Triple::NoSubArch)
307 ARMAttributeParser Attributes;
308 if (Error E = getBuildAttributes(Attributes))
312 // Default to ARM, but use the triple if it's been set.
313 if (TheTriple.isThumb())
318 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
319 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
320 case ARMBuildAttrs::v4:
323 case ARMBuildAttrs::v4T:
326 case ARMBuildAttrs::v5T:
329 case ARMBuildAttrs::v5TE:
332 case ARMBuildAttrs::v5TEJ:
335 case ARMBuildAttrs::v6:
338 case ARMBuildAttrs::v6KZ:
341 case ARMBuildAttrs::v6T2:
344 case ARMBuildAttrs::v6K:
347 case ARMBuildAttrs::v7:
350 case ARMBuildAttrs::v6_M:
353 case ARMBuildAttrs::v6S_M:
356 case ARMBuildAttrs::v7E_M:
359 case ARMBuildAttrs::v8_A:
362 case ARMBuildAttrs::v8_R:
365 case ARMBuildAttrs::v8_M_Base:
366 Triple += "v8m.base";
368 case ARMBuildAttrs::v8_M_Main:
369 Triple += "v8m.main";
371 case ARMBuildAttrs::v8_1_M_Main:
372 Triple += "v8.1m.main";
376 if (!isLittleEndian())
379 TheTriple.setArchName(Triple);
382 std::vector<std::pair<DataRefImpl, uint64_t>>
383 ELFObjectFileBase::getPltAddresses() const {
385 const auto Triple = makeTriple();
386 const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err);
389 uint64_t JumpSlotReloc = 0;
390 switch (Triple.getArch()) {
392 JumpSlotReloc = ELF::R_386_JUMP_SLOT;
395 JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT;
397 case Triple::aarch64:
398 JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT;
403 std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo());
404 std::unique_ptr<const MCInstrAnalysis> MIA(
405 T->createMCInstrAnalysis(MII.get()));
408 Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None;
409 for (const SectionRef &Section : sections()) {
410 Expected<StringRef> NameOrErr = Section.getName();
412 consumeError(NameOrErr.takeError());
415 StringRef Name = *NameOrErr;
419 else if (Name == ".rela.plt" || Name == ".rel.plt")
421 else if (Name == ".got.plt")
424 if (!Plt || !RelaPlt || !GotPlt)
426 Expected<StringRef> PltContents = Plt->getContents();
428 consumeError(PltContents.takeError());
431 auto PltEntries = MIA->findPltEntries(Plt->getAddress(),
432 arrayRefFromStringRef(*PltContents),
433 GotPlt->getAddress(), Triple);
434 // Build a map from GOT entry virtual address to PLT entry virtual address.
435 DenseMap<uint64_t, uint64_t> GotToPlt;
436 for (const auto &Entry : PltEntries)
437 GotToPlt.insert(std::make_pair(Entry.second, Entry.first));
438 // Find the relocations in the dynamic relocation table that point to
439 // locations in the GOT for which we know the corresponding PLT entry.
440 std::vector<std::pair<DataRefImpl, uint64_t>> Result;
441 for (const auto &Relocation : RelaPlt->relocations()) {
442 if (Relocation.getType() != JumpSlotReloc)
444 auto PltEntryIter = GotToPlt.find(Relocation.getOffset());
445 if (PltEntryIter != GotToPlt.end())
446 Result.push_back(std::make_pair(
447 Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second));