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("vfp2d16sp", 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
));