Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / lib / Object / ELFObjectFile.cpp
blob15e09f8116b0896a2f0199ca3925a4aa891015ab
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 ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
39 : ObjectFile(Type, Source) {}
41 template <class ELFT>
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())
46 return std::move(E);
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()));
57 if (MaxAlignment < 2)
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);
65 else
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);
72 else
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:
84 break;
85 case ELF::EF_MIPS_ARCH_2:
86 Features.AddFeature("mips2");
87 break;
88 case ELF::EF_MIPS_ARCH_3:
89 Features.AddFeature("mips3");
90 break;
91 case ELF::EF_MIPS_ARCH_4:
92 Features.AddFeature("mips4");
93 break;
94 case ELF::EF_MIPS_ARCH_5:
95 Features.AddFeature("mips5");
96 break;
97 case ELF::EF_MIPS_ARCH_32:
98 Features.AddFeature("mips32");
99 break;
100 case ELF::EF_MIPS_ARCH_64:
101 Features.AddFeature("mips64");
102 break;
103 case ELF::EF_MIPS_ARCH_32R2:
104 Features.AddFeature("mips32r2");
105 break;
106 case ELF::EF_MIPS_ARCH_64R2:
107 Features.AddFeature("mips64r2");
108 break;
109 case ELF::EF_MIPS_ARCH_32R6:
110 Features.AddFeature("mips32r6");
111 break;
112 case ELF::EF_MIPS_ARCH_64R6:
113 Features.AddFeature("mips64r6");
114 break;
115 default:
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.
122 break;
123 case ELF::EF_MIPS_MACH_OCTEON:
124 Features.AddFeature("cnmips");
125 break;
126 default:
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");
135 return Features;
138 SubtargetFeatures ELFObjectFileBase::getARMFeatures() const {
139 SubtargetFeatures Features;
140 ARMAttributeParser Attributes;
141 std::error_code EC = getBuildAttributes(Attributes);
142 if (EC)
143 return SubtargetFeatures();
145 // both ARMv7-M and R have to support thumb hardware div
146 bool isV7 = false;
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");
155 break;
156 case ARMBuildAttrs::RealTimeProfile:
157 Features.AddFeature("rclass");
158 if (isV7)
159 Features.AddFeature("hwdiv");
160 break;
161 case ARMBuildAttrs::MicroControllerProfile:
162 Features.AddFeature("mclass");
163 if (isV7)
164 Features.AddFeature("hwdiv");
165 break;
169 if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) {
170 switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) {
171 default:
172 break;
173 case ARMBuildAttrs::Not_Allowed:
174 Features.AddFeature("thumb", false);
175 Features.AddFeature("thumb2", false);
176 break;
177 case ARMBuildAttrs::AllowThumb32:
178 Features.AddFeature("thumb2");
179 break;
183 if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) {
184 switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) {
185 default:
186 break;
187 case ARMBuildAttrs::Not_Allowed:
188 Features.AddFeature("vfp2", false);
189 Features.AddFeature("vfp3", false);
190 Features.AddFeature("vfp4", false);
191 break;
192 case ARMBuildAttrs::AllowFPv2:
193 Features.AddFeature("vfp2");
194 break;
195 case ARMBuildAttrs::AllowFPv3A:
196 case ARMBuildAttrs::AllowFPv3B:
197 Features.AddFeature("vfp3");
198 break;
199 case ARMBuildAttrs::AllowFPv4A:
200 case ARMBuildAttrs::AllowFPv4B:
201 Features.AddFeature("vfp4");
202 break;
206 if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) {
207 switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) {
208 default:
209 break;
210 case ARMBuildAttrs::Not_Allowed:
211 Features.AddFeature("neon", false);
212 Features.AddFeature("fp16", false);
213 break;
214 case ARMBuildAttrs::AllowNeon:
215 Features.AddFeature("neon");
216 break;
217 case ARMBuildAttrs::AllowNeon2:
218 Features.AddFeature("neon");
219 Features.AddFeature("fp16");
220 break;
224 if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) {
225 switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) {
226 default:
227 break;
228 case ARMBuildAttrs::DisallowDIV:
229 Features.AddFeature("hwdiv", false);
230 Features.AddFeature("hwdiv-arm", false);
231 break;
232 case ARMBuildAttrs::AllowDIVExt:
233 Features.AddFeature("hwdiv");
234 Features.AddFeature("hwdiv-arm");
235 break;
239 return Features;
242 SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const {
243 SubtargetFeatures Features;
244 unsigned PlatformFlags = getPlatformFlags();
246 if (PlatformFlags & ELF::EF_RISCV_RVC) {
247 Features.AddFeature("c");
250 return Features;
253 SubtargetFeatures ELFObjectFileBase::getFeatures() const {
254 switch (getEMachine()) {
255 case ELF::EM_MIPS:
256 return getMIPSFeatures();
257 case ELF::EM_ARM:
258 return getARMFeatures();
259 case ELF::EM_RISCV:
260 return getRISCVFeatures();
261 default:
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)
269 return;
271 ARMAttributeParser Attributes;
272 std::error_code EC = getBuildAttributes(Attributes);
273 if (EC)
274 return;
276 std::string Triple;
277 // Default to ARM, but use the triple if it's been set.
278 if (TheTriple.isThumb())
279 Triple = "thumb";
280 else
281 Triple = "arm";
283 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
284 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
285 case ARMBuildAttrs::v4:
286 Triple += "v4";
287 break;
288 case ARMBuildAttrs::v4T:
289 Triple += "v4t";
290 break;
291 case ARMBuildAttrs::v5T:
292 Triple += "v5t";
293 break;
294 case ARMBuildAttrs::v5TE:
295 Triple += "v5te";
296 break;
297 case ARMBuildAttrs::v5TEJ:
298 Triple += "v5tej";
299 break;
300 case ARMBuildAttrs::v6:
301 Triple += "v6";
302 break;
303 case ARMBuildAttrs::v6KZ:
304 Triple += "v6kz";
305 break;
306 case ARMBuildAttrs::v6T2:
307 Triple += "v6t2";
308 break;
309 case ARMBuildAttrs::v6K:
310 Triple += "v6k";
311 break;
312 case ARMBuildAttrs::v7:
313 Triple += "v7";
314 break;
315 case ARMBuildAttrs::v6_M:
316 Triple += "v6m";
317 break;
318 case ARMBuildAttrs::v6S_M:
319 Triple += "v6sm";
320 break;
321 case ARMBuildAttrs::v7E_M:
322 Triple += "v7em";
323 break;
326 if (!isLittleEndian())
327 Triple += "eb";
329 TheTriple.setArchName(Triple);
332 std::vector<std::pair<DataRefImpl, uint64_t>>
333 ELFObjectFileBase::getPltAddresses() const {
334 std::string Err;
335 const auto Triple = makeTriple();
336 const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err);
337 if (!T)
338 return {};
339 uint64_t JumpSlotReloc = 0;
340 switch (Triple.getArch()) {
341 case Triple::x86:
342 JumpSlotReloc = ELF::R_386_JUMP_SLOT;
343 break;
344 case Triple::x86_64:
345 JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT;
346 break;
347 case Triple::aarch64:
348 JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT;
349 break;
350 default:
351 return {};
353 std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo());
354 std::unique_ptr<const MCInstrAnalysis> MIA(
355 T->createMCInstrAnalysis(MII.get()));
356 if (!MIA)
357 return {};
358 Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None;
359 for (const SectionRef &Section : sections()) {
360 StringRef Name;
361 if (Section.getName(Name))
362 continue;
363 if (Name == ".plt")
364 Plt = Section;
365 else if (Name == ".rela.plt" || Name == ".rel.plt")
366 RelaPlt = Section;
367 else if (Name == ".got.plt")
368 GotPlt = Section;
370 if (!Plt || !RelaPlt || !GotPlt)
371 return {};
372 StringRef PltContents;
373 if (Plt->getContents(PltContents))
374 return {};
375 ArrayRef<uint8_t> PltBytes((const uint8_t *)PltContents.data(),
376 Plt->getSize());
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)
388 continue;
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));
394 return Result;