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 ELFObjectFileBase::ELFObjectFileBase(unsigned int Type
, MemoryBufferRef Source
)
39 : ObjectFile(Type
, Source
) {}
42 static Expected
<std::unique_ptr
<ELFObjectFile
<ELFT
>>>
43 createPtr(MemoryBufferRef Object
) {
44 auto Ret
= ELFObjectFile
<ELFT
>::create(Object
);
45 if (Error E
= Ret
.takeError())
47 return make_unique
<ELFObjectFile
<ELFT
>>(std::move(*Ret
));
50 Expected
<std::unique_ptr
<ObjectFile
>>
51 ObjectFile::createELFObjectFile(MemoryBufferRef Obj
) {
52 std::pair
<unsigned char, unsigned char> Ident
=
53 getElfArchType(Obj
.getBuffer());
54 std::size_t MaxAlignment
=
55 1ULL << countTrailingZeros(uintptr_t(Obj
.getBufferStart()));
58 return createError("Insufficient alignment");
60 if (Ident
.first
== ELF::ELFCLASS32
) {
61 if (Ident
.second
== ELF::ELFDATA2LSB
)
62 return createPtr
<ELF32LE
>(Obj
);
63 else if (Ident
.second
== ELF::ELFDATA2MSB
)
64 return createPtr
<ELF32BE
>(Obj
);
66 return createError("Invalid ELF data");
67 } else if (Ident
.first
== ELF::ELFCLASS64
) {
68 if (Ident
.second
== ELF::ELFDATA2LSB
)
69 return createPtr
<ELF64LE
>(Obj
);
70 else if (Ident
.second
== ELF::ELFDATA2MSB
)
71 return createPtr
<ELF64BE
>(Obj
);
73 return createError("Invalid ELF data");
75 return createError("Invalid ELF class");
78 SubtargetFeatures
ELFObjectFileBase::getMIPSFeatures() const {
79 SubtargetFeatures Features
;
80 unsigned PlatformFlags
= getPlatformFlags();
82 switch (PlatformFlags
& ELF::EF_MIPS_ARCH
) {
83 case ELF::EF_MIPS_ARCH_1
:
85 case ELF::EF_MIPS_ARCH_2
:
86 Features
.AddFeature("mips2");
88 case ELF::EF_MIPS_ARCH_3
:
89 Features
.AddFeature("mips3");
91 case ELF::EF_MIPS_ARCH_4
:
92 Features
.AddFeature("mips4");
94 case ELF::EF_MIPS_ARCH_5
:
95 Features
.AddFeature("mips5");
97 case ELF::EF_MIPS_ARCH_32
:
98 Features
.AddFeature("mips32");
100 case ELF::EF_MIPS_ARCH_64
:
101 Features
.AddFeature("mips64");
103 case ELF::EF_MIPS_ARCH_32R2
:
104 Features
.AddFeature("mips32r2");
106 case ELF::EF_MIPS_ARCH_64R2
:
107 Features
.AddFeature("mips64r2");
109 case ELF::EF_MIPS_ARCH_32R6
:
110 Features
.AddFeature("mips32r6");
112 case ELF::EF_MIPS_ARCH_64R6
:
113 Features
.AddFeature("mips64r6");
116 llvm_unreachable("Unknown EF_MIPS_ARCH value");
119 switch (PlatformFlags
& ELF::EF_MIPS_MACH
) {
120 case ELF::EF_MIPS_MACH_NONE
:
121 // No feature associated with this value.
123 case ELF::EF_MIPS_MACH_OCTEON
:
124 Features
.AddFeature("cnmips");
127 llvm_unreachable("Unknown EF_MIPS_ARCH value");
130 if (PlatformFlags
& ELF::EF_MIPS_ARCH_ASE_M16
)
131 Features
.AddFeature("mips16");
132 if (PlatformFlags
& ELF::EF_MIPS_MICROMIPS
)
133 Features
.AddFeature("micromips");
138 SubtargetFeatures
ELFObjectFileBase::getARMFeatures() const {
139 SubtargetFeatures Features
;
140 ARMAttributeParser Attributes
;
141 std::error_code EC
= getBuildAttributes(Attributes
);
143 return SubtargetFeatures();
145 // both ARMv7-M and R have to support thumb hardware div
147 if (Attributes
.hasAttribute(ARMBuildAttrs::CPU_arch
))
148 isV7
= Attributes
.getAttributeValue(ARMBuildAttrs::CPU_arch
)
149 == ARMBuildAttrs::v7
;
151 if (Attributes
.hasAttribute(ARMBuildAttrs::CPU_arch_profile
)) {
152 switch(Attributes
.getAttributeValue(ARMBuildAttrs::CPU_arch_profile
)) {
153 case ARMBuildAttrs::ApplicationProfile
:
154 Features
.AddFeature("aclass");
156 case ARMBuildAttrs::RealTimeProfile
:
157 Features
.AddFeature("rclass");
159 Features
.AddFeature("hwdiv");
161 case ARMBuildAttrs::MicroControllerProfile
:
162 Features
.AddFeature("mclass");
164 Features
.AddFeature("hwdiv");
169 if (Attributes
.hasAttribute(ARMBuildAttrs::THUMB_ISA_use
)) {
170 switch(Attributes
.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use
)) {
173 case ARMBuildAttrs::Not_Allowed
:
174 Features
.AddFeature("thumb", false);
175 Features
.AddFeature("thumb2", false);
177 case ARMBuildAttrs::AllowThumb32
:
178 Features
.AddFeature("thumb2");
183 if (Attributes
.hasAttribute(ARMBuildAttrs::FP_arch
)) {
184 switch(Attributes
.getAttributeValue(ARMBuildAttrs::FP_arch
)) {
187 case ARMBuildAttrs::Not_Allowed
:
188 Features
.AddFeature("vfp2", false);
189 Features
.AddFeature("vfp3", false);
190 Features
.AddFeature("vfp4", false);
192 case ARMBuildAttrs::AllowFPv2
:
193 Features
.AddFeature("vfp2");
195 case ARMBuildAttrs::AllowFPv3A
:
196 case ARMBuildAttrs::AllowFPv3B
:
197 Features
.AddFeature("vfp3");
199 case ARMBuildAttrs::AllowFPv4A
:
200 case ARMBuildAttrs::AllowFPv4B
:
201 Features
.AddFeature("vfp4");
206 if (Attributes
.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch
)) {
207 switch(Attributes
.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch
)) {
210 case ARMBuildAttrs::Not_Allowed
:
211 Features
.AddFeature("neon", false);
212 Features
.AddFeature("fp16", false);
214 case ARMBuildAttrs::AllowNeon
:
215 Features
.AddFeature("neon");
217 case ARMBuildAttrs::AllowNeon2
:
218 Features
.AddFeature("neon");
219 Features
.AddFeature("fp16");
224 if (Attributes
.hasAttribute(ARMBuildAttrs::DIV_use
)) {
225 switch(Attributes
.getAttributeValue(ARMBuildAttrs::DIV_use
)) {
228 case ARMBuildAttrs::DisallowDIV
:
229 Features
.AddFeature("hwdiv", false);
230 Features
.AddFeature("hwdiv-arm", false);
232 case ARMBuildAttrs::AllowDIVExt
:
233 Features
.AddFeature("hwdiv");
234 Features
.AddFeature("hwdiv-arm");
242 SubtargetFeatures
ELFObjectFileBase::getRISCVFeatures() const {
243 SubtargetFeatures Features
;
244 unsigned PlatformFlags
= getPlatformFlags();
246 if (PlatformFlags
& ELF::EF_RISCV_RVC
) {
247 Features
.AddFeature("c");
253 SubtargetFeatures
ELFObjectFileBase::getFeatures() const {
254 switch (getEMachine()) {
256 return getMIPSFeatures();
258 return getARMFeatures();
260 return getRISCVFeatures();
262 return SubtargetFeatures();
266 // FIXME Encode from a tablegen description or target parser.
267 void ELFObjectFileBase::setARMSubArch(Triple
&TheTriple
) const {
268 if (TheTriple
.getSubArch() != Triple::NoSubArch
)
271 ARMAttributeParser Attributes
;
272 std::error_code EC
= getBuildAttributes(Attributes
);
277 // Default to ARM, but use the triple if it's been set.
278 if (TheTriple
.isThumb())
283 if (Attributes
.hasAttribute(ARMBuildAttrs::CPU_arch
)) {
284 switch(Attributes
.getAttributeValue(ARMBuildAttrs::CPU_arch
)) {
285 case ARMBuildAttrs::v4
:
288 case ARMBuildAttrs::v4T
:
291 case ARMBuildAttrs::v5T
:
294 case ARMBuildAttrs::v5TE
:
297 case ARMBuildAttrs::v5TEJ
:
300 case ARMBuildAttrs::v6
:
303 case ARMBuildAttrs::v6KZ
:
306 case ARMBuildAttrs::v6T2
:
309 case ARMBuildAttrs::v6K
:
312 case ARMBuildAttrs::v7
:
315 case ARMBuildAttrs::v6_M
:
318 case ARMBuildAttrs::v6S_M
:
321 case ARMBuildAttrs::v7E_M
:
326 if (!isLittleEndian())
329 TheTriple
.setArchName(Triple
);
332 std::vector
<std::pair
<DataRefImpl
, uint64_t>>
333 ELFObjectFileBase::getPltAddresses() const {
335 const auto Triple
= makeTriple();
336 const auto *T
= TargetRegistry::lookupTarget(Triple
.str(), Err
);
339 uint64_t JumpSlotReloc
= 0;
340 switch (Triple
.getArch()) {
342 JumpSlotReloc
= ELF::R_386_JUMP_SLOT
;
345 JumpSlotReloc
= ELF::R_X86_64_JUMP_SLOT
;
347 case Triple::aarch64
:
348 JumpSlotReloc
= ELF::R_AARCH64_JUMP_SLOT
;
353 std::unique_ptr
<const MCInstrInfo
> MII(T
->createMCInstrInfo());
354 std::unique_ptr
<const MCInstrAnalysis
> MIA(
355 T
->createMCInstrAnalysis(MII
.get()));
358 Optional
<SectionRef
> Plt
= None
, RelaPlt
= None
, GotPlt
= None
;
359 for (const SectionRef
&Section
: sections()) {
361 if (Section
.getName(Name
))
365 else if (Name
== ".rela.plt" || Name
== ".rel.plt")
367 else if (Name
== ".got.plt")
370 if (!Plt
|| !RelaPlt
|| !GotPlt
)
372 StringRef PltContents
;
373 if (Plt
->getContents(PltContents
))
375 ArrayRef
<uint8_t> PltBytes((const uint8_t *)PltContents
.data(),
377 auto PltEntries
= MIA
->findPltEntries(Plt
->getAddress(), PltBytes
,
378 GotPlt
->getAddress(), Triple
);
379 // Build a map from GOT entry virtual address to PLT entry virtual address.
380 DenseMap
<uint64_t, uint64_t> GotToPlt
;
381 for (const auto &Entry
: PltEntries
)
382 GotToPlt
.insert(std::make_pair(Entry
.second
, Entry
.first
));
383 // Find the relocations in the dynamic relocation table that point to
384 // locations in the GOT for which we know the corresponding PLT entry.
385 std::vector
<std::pair
<DataRefImpl
, uint64_t>> Result
;
386 for (const auto &Relocation
: RelaPlt
->relocations()) {
387 if (Relocation
.getType() != JumpSlotReloc
)
389 auto PltEntryIter
= GotToPlt
.find(Relocation
.getOffset());
390 if (PltEntryIter
!= GotToPlt
.end())
391 Result
.push_back(std::make_pair(
392 Relocation
.getSymbol()->getRawDataRefImpl(), PltEntryIter
->second
));