Recommit r368812 "[llvm/Object] - Convert SectionRef::getName() to return Expected<>"
[llvm-complete.git] / lib / Object / ELFObjectFile.cpp
blobf3b0347088a4fbfcd80c827c624231861429227b
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 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) {}
60 template <class ELFT>
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())
65 return std::move(E);
66 return 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()));
76 if (MaxAlignment < 2)
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);
84 else
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);
91 else
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:
103 break;
104 case ELF::EF_MIPS_ARCH_2:
105 Features.AddFeature("mips2");
106 break;
107 case ELF::EF_MIPS_ARCH_3:
108 Features.AddFeature("mips3");
109 break;
110 case ELF::EF_MIPS_ARCH_4:
111 Features.AddFeature("mips4");
112 break;
113 case ELF::EF_MIPS_ARCH_5:
114 Features.AddFeature("mips5");
115 break;
116 case ELF::EF_MIPS_ARCH_32:
117 Features.AddFeature("mips32");
118 break;
119 case ELF::EF_MIPS_ARCH_64:
120 Features.AddFeature("mips64");
121 break;
122 case ELF::EF_MIPS_ARCH_32R2:
123 Features.AddFeature("mips32r2");
124 break;
125 case ELF::EF_MIPS_ARCH_64R2:
126 Features.AddFeature("mips64r2");
127 break;
128 case ELF::EF_MIPS_ARCH_32R6:
129 Features.AddFeature("mips32r6");
130 break;
131 case ELF::EF_MIPS_ARCH_64R6:
132 Features.AddFeature("mips64r6");
133 break;
134 default:
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.
141 break;
142 case ELF::EF_MIPS_MACH_OCTEON:
143 Features.AddFeature("cnmips");
144 break;
145 default:
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");
154 return Features;
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
164 bool isV7 = false;
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");
173 break;
174 case ARMBuildAttrs::RealTimeProfile:
175 Features.AddFeature("rclass");
176 if (isV7)
177 Features.AddFeature("hwdiv");
178 break;
179 case ARMBuildAttrs::MicroControllerProfile:
180 Features.AddFeature("mclass");
181 if (isV7)
182 Features.AddFeature("hwdiv");
183 break;
187 if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) {
188 switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) {
189 default:
190 break;
191 case ARMBuildAttrs::Not_Allowed:
192 Features.AddFeature("thumb", false);
193 Features.AddFeature("thumb2", false);
194 break;
195 case ARMBuildAttrs::AllowThumb32:
196 Features.AddFeature("thumb2");
197 break;
201 if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) {
202 switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) {
203 default:
204 break;
205 case ARMBuildAttrs::Not_Allowed:
206 Features.AddFeature("vfp2d16sp", false);
207 Features.AddFeature("vfp3d16sp", false);
208 Features.AddFeature("vfp4d16sp", false);
209 break;
210 case ARMBuildAttrs::AllowFPv2:
211 Features.AddFeature("vfp2");
212 break;
213 case ARMBuildAttrs::AllowFPv3A:
214 case ARMBuildAttrs::AllowFPv3B:
215 Features.AddFeature("vfp3");
216 break;
217 case ARMBuildAttrs::AllowFPv4A:
218 case ARMBuildAttrs::AllowFPv4B:
219 Features.AddFeature("vfp4");
220 break;
224 if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) {
225 switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) {
226 default:
227 break;
228 case ARMBuildAttrs::Not_Allowed:
229 Features.AddFeature("neon", false);
230 Features.AddFeature("fp16", false);
231 break;
232 case ARMBuildAttrs::AllowNeon:
233 Features.AddFeature("neon");
234 break;
235 case ARMBuildAttrs::AllowNeon2:
236 Features.AddFeature("neon");
237 Features.AddFeature("fp16");
238 break;
242 if (Attributes.hasAttribute(ARMBuildAttrs::MVE_arch)) {
243 switch(Attributes.getAttributeValue(ARMBuildAttrs::MVE_arch)) {
244 default:
245 break;
246 case ARMBuildAttrs::Not_Allowed:
247 Features.AddFeature("mve", false);
248 Features.AddFeature("mve.fp", false);
249 break;
250 case ARMBuildAttrs::AllowMVEInteger:
251 Features.AddFeature("mve.fp", false);
252 Features.AddFeature("mve");
253 break;
254 case ARMBuildAttrs::AllowMVEIntegerAndFloat:
255 Features.AddFeature("mve.fp");
256 break;
260 if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) {
261 switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) {
262 default:
263 break;
264 case ARMBuildAttrs::DisallowDIV:
265 Features.AddFeature("hwdiv", false);
266 Features.AddFeature("hwdiv-arm", false);
267 break;
268 case ARMBuildAttrs::AllowDIVExt:
269 Features.AddFeature("hwdiv");
270 Features.AddFeature("hwdiv-arm");
271 break;
275 return Features;
278 SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const {
279 SubtargetFeatures Features;
280 unsigned PlatformFlags = getPlatformFlags();
282 if (PlatformFlags & ELF::EF_RISCV_RVC) {
283 Features.AddFeature("c");
286 return Features;
289 SubtargetFeatures ELFObjectFileBase::getFeatures() const {
290 switch (getEMachine()) {
291 case ELF::EM_MIPS:
292 return getMIPSFeatures();
293 case ELF::EM_ARM:
294 return getARMFeatures();
295 case ELF::EM_RISCV:
296 return getRISCVFeatures();
297 default:
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)
305 return;
307 ARMAttributeParser Attributes;
308 if (Error E = getBuildAttributes(Attributes))
309 return;
311 std::string Triple;
312 // Default to ARM, but use the triple if it's been set.
313 if (TheTriple.isThumb())
314 Triple = "thumb";
315 else
316 Triple = "arm";
318 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
319 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
320 case ARMBuildAttrs::v4:
321 Triple += "v4";
322 break;
323 case ARMBuildAttrs::v4T:
324 Triple += "v4t";
325 break;
326 case ARMBuildAttrs::v5T:
327 Triple += "v5t";
328 break;
329 case ARMBuildAttrs::v5TE:
330 Triple += "v5te";
331 break;
332 case ARMBuildAttrs::v5TEJ:
333 Triple += "v5tej";
334 break;
335 case ARMBuildAttrs::v6:
336 Triple += "v6";
337 break;
338 case ARMBuildAttrs::v6KZ:
339 Triple += "v6kz";
340 break;
341 case ARMBuildAttrs::v6T2:
342 Triple += "v6t2";
343 break;
344 case ARMBuildAttrs::v6K:
345 Triple += "v6k";
346 break;
347 case ARMBuildAttrs::v7:
348 Triple += "v7";
349 break;
350 case ARMBuildAttrs::v6_M:
351 Triple += "v6m";
352 break;
353 case ARMBuildAttrs::v6S_M:
354 Triple += "v6sm";
355 break;
356 case ARMBuildAttrs::v7E_M:
357 Triple += "v7em";
358 break;
361 if (!isLittleEndian())
362 Triple += "eb";
364 TheTriple.setArchName(Triple);
367 std::vector<std::pair<DataRefImpl, uint64_t>>
368 ELFObjectFileBase::getPltAddresses() const {
369 std::string Err;
370 const auto Triple = makeTriple();
371 const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err);
372 if (!T)
373 return {};
374 uint64_t JumpSlotReloc = 0;
375 switch (Triple.getArch()) {
376 case Triple::x86:
377 JumpSlotReloc = ELF::R_386_JUMP_SLOT;
378 break;
379 case Triple::x86_64:
380 JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT;
381 break;
382 case Triple::aarch64:
383 JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT;
384 break;
385 default:
386 return {};
388 std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo());
389 std::unique_ptr<const MCInstrAnalysis> MIA(
390 T->createMCInstrAnalysis(MII.get()));
391 if (!MIA)
392 return {};
393 Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None;
394 for (const SectionRef &Section : sections()) {
395 Expected<StringRef> NameOrErr = Section.getName();
396 if (!NameOrErr) {
397 consumeError(NameOrErr.takeError());
398 continue;
400 StringRef Name = *NameOrErr;
402 if (Name == ".plt")
403 Plt = Section;
404 else if (Name == ".rela.plt" || Name == ".rel.plt")
405 RelaPlt = Section;
406 else if (Name == ".got.plt")
407 GotPlt = Section;
409 if (!Plt || !RelaPlt || !GotPlt)
410 return {};
411 Expected<StringRef> PltContents = Plt->getContents();
412 if (!PltContents) {
413 consumeError(PltContents.takeError());
414 return {};
416 auto PltEntries = MIA->findPltEntries(Plt->getAddress(),
417 arrayRefFromStringRef(*PltContents),
418 GotPlt->getAddress(), Triple);
419 // Build a map from GOT entry virtual address to PLT entry virtual address.
420 DenseMap<uint64_t, uint64_t> GotToPlt;
421 for (const auto &Entry : PltEntries)
422 GotToPlt.insert(std::make_pair(Entry.second, Entry.first));
423 // Find the relocations in the dynamic relocation table that point to
424 // locations in the GOT for which we know the corresponding PLT entry.
425 std::vector<std::pair<DataRefImpl, uint64_t>> Result;
426 for (const auto &Relocation : RelaPlt->relocations()) {
427 if (Relocation.getType() != JumpSlotReloc)
428 continue;
429 auto PltEntryIter = GotToPlt.find(Relocation.getOffset());
430 if (PltEntryIter != GotToPlt.end())
431 Result.push_back(std::make_pair(
432 Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second));
434 return Result;