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 {"GNU_IFunc", "IFUNC", ELF::STT_GNU_IFUNC}};
48 ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
49 : ObjectFile(Type, Source) {}
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())
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()));
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);
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);
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:
95 case ELF::EF_MIPS_ARCH_2:
96 Features.AddFeature("mips2");
98 case ELF::EF_MIPS_ARCH_3:
99 Features.AddFeature("mips3");
101 case ELF::EF_MIPS_ARCH_4:
102 Features.AddFeature("mips4");
104 case ELF::EF_MIPS_ARCH_5:
105 Features.AddFeature("mips5");
107 case ELF::EF_MIPS_ARCH_32:
108 Features.AddFeature("mips32");
110 case ELF::EF_MIPS_ARCH_64:
111 Features.AddFeature("mips64");
113 case ELF::EF_MIPS_ARCH_32R2:
114 Features.AddFeature("mips32r2");
116 case ELF::EF_MIPS_ARCH_64R2:
117 Features.AddFeature("mips64r2");
119 case ELF::EF_MIPS_ARCH_32R6:
120 Features.AddFeature("mips32r6");
122 case ELF::EF_MIPS_ARCH_64R6:
123 Features.AddFeature("mips64r6");
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.
133 case ELF::EF_MIPS_MACH_OCTEON:
134 Features.AddFeature("cnmips");
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");
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
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");
165 case ARMBuildAttrs::RealTimeProfile:
166 Features.AddFeature("rclass");
168 Features.AddFeature("hwdiv");
170 case ARMBuildAttrs::MicroControllerProfile:
171 Features.AddFeature("mclass");
173 Features.AddFeature("hwdiv");
178 if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) {
179 switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) {
182 case ARMBuildAttrs::Not_Allowed:
183 Features.AddFeature("thumb", false);
184 Features.AddFeature("thumb2", false);
186 case ARMBuildAttrs::AllowThumb32:
187 Features.AddFeature("thumb2");
192 if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) {
193 switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) {
196 case ARMBuildAttrs::Not_Allowed:
197 Features.AddFeature("vfp2sp", false);
198 Features.AddFeature("vfp3d16sp", false);
199 Features.AddFeature("vfp4d16sp", false);
201 case ARMBuildAttrs::AllowFPv2:
202 Features.AddFeature("vfp2");
204 case ARMBuildAttrs::AllowFPv3A:
205 case ARMBuildAttrs::AllowFPv3B:
206 Features.AddFeature("vfp3");
208 case ARMBuildAttrs::AllowFPv4A:
209 case ARMBuildAttrs::AllowFPv4B:
210 Features.AddFeature("vfp4");
215 if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) {
216 switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) {
219 case ARMBuildAttrs::Not_Allowed:
220 Features.AddFeature("neon", false);
221 Features.AddFeature("fp16", false);
223 case ARMBuildAttrs::AllowNeon:
224 Features.AddFeature("neon");
226 case ARMBuildAttrs::AllowNeon2:
227 Features.AddFeature("neon");
228 Features.AddFeature("fp16");
233 if (Attributes.hasAttribute(ARMBuildAttrs::MVE_arch)) {
234 switch(Attributes.getAttributeValue(ARMBuildAttrs::MVE_arch)) {
237 case ARMBuildAttrs::Not_Allowed:
238 Features.AddFeature("mve", false);
239 Features.AddFeature("mve.fp", false);
241 case ARMBuildAttrs::AllowMVEInteger:
242 Features.AddFeature("mve.fp", false);
243 Features.AddFeature("mve");
245 case ARMBuildAttrs::AllowMVEIntegerAndFloat:
246 Features.AddFeature("mve.fp");
251 if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) {
252 switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) {
255 case ARMBuildAttrs::DisallowDIV:
256 Features.AddFeature("hwdiv", false);
257 Features.AddFeature("hwdiv-arm", false);
259 case ARMBuildAttrs::AllowDIVExt:
260 Features.AddFeature("hwdiv");
261 Features.AddFeature("hwdiv-arm");
269 SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const {
270 SubtargetFeatures Features;
271 unsigned PlatformFlags = getPlatformFlags();
273 if (PlatformFlags & ELF::EF_RISCV_RVC) {
274 Features.AddFeature("c");
280 SubtargetFeatures ELFObjectFileBase::getFeatures() const {
281 switch (getEMachine()) {
283 return getMIPSFeatures();
285 return getARMFeatures();
287 return getRISCVFeatures();
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)
298 ARMAttributeParser Attributes;
299 if (Error E = getBuildAttributes(Attributes))
303 // Default to ARM, but use the triple if it's been set.
304 if (TheTriple.isThumb())
309 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
310 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
311 case ARMBuildAttrs::v4:
314 case ARMBuildAttrs::v4T:
317 case ARMBuildAttrs::v5T:
320 case ARMBuildAttrs::v5TE:
323 case ARMBuildAttrs::v5TEJ:
326 case ARMBuildAttrs::v6:
329 case ARMBuildAttrs::v6KZ:
332 case ARMBuildAttrs::v6T2:
335 case ARMBuildAttrs::v6K:
338 case ARMBuildAttrs::v7:
341 case ARMBuildAttrs::v6_M:
344 case ARMBuildAttrs::v6S_M:
347 case ARMBuildAttrs::v7E_M:
352 if (!isLittleEndian())
355 TheTriple.setArchName(Triple);
358 std::vector<std::pair<DataRefImpl, uint64_t>>
359 ELFObjectFileBase::getPltAddresses() const {
361 const auto Triple = makeTriple();
362 const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err);
365 uint64_t JumpSlotReloc = 0;
366 switch (Triple.getArch()) {
368 JumpSlotReloc = ELF::R_386_JUMP_SLOT;
371 JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT;
373 case Triple::aarch64:
374 JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT;
379 std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo());
380 std::unique_ptr<const MCInstrAnalysis> MIA(
381 T->createMCInstrAnalysis(MII.get()));
384 Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None;
385 for (const SectionRef &Section : sections()) {
387 if (Section.getName(Name))
391 else if (Name == ".rela.plt" || Name == ".rel.plt")
393 else if (Name == ".got.plt")
396 if (!Plt || !RelaPlt || !GotPlt)
398 Expected<StringRef> PltContents = Plt->getContents();
400 consumeError(PltContents.takeError());
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)
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));