1 //===- ELFObjectFile.cpp - ELF object file implementation -----------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Part of the ELFObjectFile class implementation.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Object/ELFObjectFile.h"
15 #include "llvm/ADT/Triple.h"
16 #include "llvm/BinaryFormat/ELF.h"
17 #include "llvm/MC/MCInstrAnalysis.h"
18 #include "llvm/MC/SubtargetFeature.h"
19 #include "llvm/Object/ELF.h"
20 #include "llvm/Object/ELFTypes.h"
21 #include "llvm/Object/Error.h"
22 #include "llvm/Support/ARMAttributeParser.h"
23 #include "llvm/Support/ARMBuildAttributes.h"
24 #include "llvm/Support/Endian.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/Support/MathExtras.h"
27 #include "llvm/Support/TargetRegistry.h"
28 #include <algorithm>
29 #include <cstddef>
30 #include <cstdint>
31 #include <memory>
32 #include <string>
33 #include <system_error>
34 #include <utility>
35
36 using namespace llvm;
37 using namespace object;
38
ELFObjectFileBase(unsigned int Type,MemoryBufferRef Source)39 ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
40 : ObjectFile(Type, Source) {}
41
42 template <class ELFT>
43 static Expected<std::unique_ptr<ELFObjectFile<ELFT>>>
createPtr(MemoryBufferRef Object)44 createPtr(MemoryBufferRef Object) {
45 auto Ret = ELFObjectFile<ELFT>::create(Object);
46 if (Error E = Ret.takeError())
47 return std::move(E);
48 return make_unique<ELFObjectFile<ELFT>>(std::move(*Ret));
49 }
50
51 Expected<std::unique_ptr<ObjectFile>>
createELFObjectFile(MemoryBufferRef Obj)52 ObjectFile::createELFObjectFile(MemoryBufferRef Obj) {
53 std::pair<unsigned char, unsigned char> Ident =
54 getElfArchType(Obj.getBuffer());
55 std::size_t MaxAlignment =
56 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart()));
57
58 if (MaxAlignment < 2)
59 return createError("Insufficient alignment");
60
61 if (Ident.first == ELF::ELFCLASS32) {
62 if (Ident.second == ELF::ELFDATA2LSB)
63 return createPtr<ELF32LE>(Obj);
64 else if (Ident.second == ELF::ELFDATA2MSB)
65 return createPtr<ELF32BE>(Obj);
66 else
67 return createError("Invalid ELF data");
68 } else if (Ident.first == ELF::ELFCLASS64) {
69 if (Ident.second == ELF::ELFDATA2LSB)
70 return createPtr<ELF64LE>(Obj);
71 else if (Ident.second == ELF::ELFDATA2MSB)
72 return createPtr<ELF64BE>(Obj);
73 else
74 return createError("Invalid ELF data");
75 }
76 return createError("Invalid ELF class");
77 }
78
getMIPSFeatures() const79 SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const {
80 SubtargetFeatures Features;
81 unsigned PlatformFlags = getPlatformFlags();
82
83 switch (PlatformFlags & ELF::EF_MIPS_ARCH) {
84 case ELF::EF_MIPS_ARCH_1:
85 break;
86 case ELF::EF_MIPS_ARCH_2:
87 Features.AddFeature("mips2");
88 break;
89 case ELF::EF_MIPS_ARCH_3:
90 Features.AddFeature("mips3");
91 break;
92 case ELF::EF_MIPS_ARCH_4:
93 Features.AddFeature("mips4");
94 break;
95 case ELF::EF_MIPS_ARCH_5:
96 Features.AddFeature("mips5");
97 break;
98 case ELF::EF_MIPS_ARCH_32:
99 Features.AddFeature("mips32");
100 break;
101 case ELF::EF_MIPS_ARCH_64:
102 Features.AddFeature("mips64");
103 break;
104 case ELF::EF_MIPS_ARCH_32R2:
105 Features.AddFeature("mips32r2");
106 break;
107 case ELF::EF_MIPS_ARCH_64R2:
108 Features.AddFeature("mips64r2");
109 break;
110 case ELF::EF_MIPS_ARCH_32R6:
111 Features.AddFeature("mips32r6");
112 break;
113 case ELF::EF_MIPS_ARCH_64R6:
114 Features.AddFeature("mips64r6");
115 break;
116 default:
117 llvm_unreachable("Unknown EF_MIPS_ARCH value");
118 }
119
120 switch (PlatformFlags & ELF::EF_MIPS_MACH) {
121 case ELF::EF_MIPS_MACH_NONE:
122 // No feature associated with this value.
123 break;
124 case ELF::EF_MIPS_MACH_OCTEON:
125 Features.AddFeature("cnmips");
126 break;
127 default:
128 llvm_unreachable("Unknown EF_MIPS_ARCH value");
129 }
130
131 if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16)
132 Features.AddFeature("mips16");
133 if (PlatformFlags & ELF::EF_MIPS_MICROMIPS)
134 Features.AddFeature("micromips");
135
136 return Features;
137 }
138
getARMFeatures() const139 SubtargetFeatures ELFObjectFileBase::getARMFeatures() const {
140 SubtargetFeatures Features;
141 ARMAttributeParser Attributes;
142 std::error_code EC = getBuildAttributes(Attributes);
143 if (EC)
144 return SubtargetFeatures();
145
146 // both ARMv7-M and R have to support thumb hardware div
147 bool isV7 = false;
148 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch))
149 isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)
150 == ARMBuildAttrs::v7;
151
152 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) {
153 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) {
154 case ARMBuildAttrs::ApplicationProfile:
155 Features.AddFeature("aclass");
156 break;
157 case ARMBuildAttrs::RealTimeProfile:
158 Features.AddFeature("rclass");
159 if (isV7)
160 Features.AddFeature("hwdiv");
161 break;
162 case ARMBuildAttrs::MicroControllerProfile:
163 Features.AddFeature("mclass");
164 if (isV7)
165 Features.AddFeature("hwdiv");
166 break;
167 }
168 }
169
170 if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) {
171 switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) {
172 default:
173 break;
174 case ARMBuildAttrs::Not_Allowed:
175 Features.AddFeature("thumb", false);
176 Features.AddFeature("thumb2", false);
177 break;
178 case ARMBuildAttrs::AllowThumb32:
179 Features.AddFeature("thumb2");
180 break;
181 }
182 }
183
184 if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) {
185 switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) {
186 default:
187 break;
188 case ARMBuildAttrs::Not_Allowed:
189 Features.AddFeature("vfp2", false);
190 Features.AddFeature("vfp3", false);
191 Features.AddFeature("vfp4", false);
192 break;
193 case ARMBuildAttrs::AllowFPv2:
194 Features.AddFeature("vfp2");
195 break;
196 case ARMBuildAttrs::AllowFPv3A:
197 case ARMBuildAttrs::AllowFPv3B:
198 Features.AddFeature("vfp3");
199 break;
200 case ARMBuildAttrs::AllowFPv4A:
201 case ARMBuildAttrs::AllowFPv4B:
202 Features.AddFeature("vfp4");
203 break;
204 }
205 }
206
207 if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) {
208 switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) {
209 default:
210 break;
211 case ARMBuildAttrs::Not_Allowed:
212 Features.AddFeature("neon", false);
213 Features.AddFeature("fp16", false);
214 break;
215 case ARMBuildAttrs::AllowNeon:
216 Features.AddFeature("neon");
217 break;
218 case ARMBuildAttrs::AllowNeon2:
219 Features.AddFeature("neon");
220 Features.AddFeature("fp16");
221 break;
222 }
223 }
224
225 if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) {
226 switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) {
227 default:
228 break;
229 case ARMBuildAttrs::DisallowDIV:
230 Features.AddFeature("hwdiv", false);
231 Features.AddFeature("hwdiv-arm", false);
232 break;
233 case ARMBuildAttrs::AllowDIVExt:
234 Features.AddFeature("hwdiv");
235 Features.AddFeature("hwdiv-arm");
236 break;
237 }
238 }
239
240 return Features;
241 }
242
getRISCVFeatures() const243 SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const {
244 SubtargetFeatures Features;
245 unsigned PlatformFlags = getPlatformFlags();
246
247 if (PlatformFlags & ELF::EF_RISCV_RVC) {
248 Features.AddFeature("c");
249 }
250
251 return Features;
252 }
253
getFeatures() const254 SubtargetFeatures ELFObjectFileBase::getFeatures() const {
255 switch (getEMachine()) {
256 case ELF::EM_MIPS:
257 return getMIPSFeatures();
258 case ELF::EM_ARM:
259 return getARMFeatures();
260 case ELF::EM_RISCV:
261 return getRISCVFeatures();
262 default:
263 return SubtargetFeatures();
264 }
265 }
266
267 // FIXME Encode from a tablegen description or target parser.
setARMSubArch(Triple & TheTriple) const268 void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
269 if (TheTriple.getSubArch() != Triple::NoSubArch)
270 return;
271
272 ARMAttributeParser Attributes;
273 std::error_code EC = getBuildAttributes(Attributes);
274 if (EC)
275 return;
276
277 std::string Triple;
278 // Default to ARM, but use the triple if it's been set.
279 if (TheTriple.isThumb())
280 Triple = "thumb";
281 else
282 Triple = "arm";
283
284 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
285 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
286 case ARMBuildAttrs::v4:
287 Triple += "v4";
288 break;
289 case ARMBuildAttrs::v4T:
290 Triple += "v4t";
291 break;
292 case ARMBuildAttrs::v5T:
293 Triple += "v5t";
294 break;
295 case ARMBuildAttrs::v5TE:
296 Triple += "v5te";
297 break;
298 case ARMBuildAttrs::v5TEJ:
299 Triple += "v5tej";
300 break;
301 case ARMBuildAttrs::v6:
302 Triple += "v6";
303 break;
304 case ARMBuildAttrs::v6KZ:
305 Triple += "v6kz";
306 break;
307 case ARMBuildAttrs::v6T2:
308 Triple += "v6t2";
309 break;
310 case ARMBuildAttrs::v6K:
311 Triple += "v6k";
312 break;
313 case ARMBuildAttrs::v7:
314 Triple += "v7";
315 break;
316 case ARMBuildAttrs::v6_M:
317 Triple += "v6m";
318 break;
319 case ARMBuildAttrs::v6S_M:
320 Triple += "v6sm";
321 break;
322 case ARMBuildAttrs::v7E_M:
323 Triple += "v7em";
324 break;
325 }
326 }
327 if (!isLittleEndian())
328 Triple += "eb";
329
330 TheTriple.setArchName(Triple);
331 }
332
333 std::vector<std::pair<DataRefImpl, uint64_t>>
getPltAddresses() const334 ELFObjectFileBase::getPltAddresses() const {
335 std::string Err;
336 const auto Triple = makeTriple();
337 const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err);
338 if (!T)
339 return {};
340 uint64_t JumpSlotReloc = 0;
341 switch (Triple.getArch()) {
342 case Triple::x86:
343 JumpSlotReloc = ELF::R_386_JUMP_SLOT;
344 break;
345 case Triple::x86_64:
346 JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT;
347 break;
348 case Triple::aarch64:
349 JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT;
350 break;
351 default:
352 return {};
353 }
354 std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo());
355 std::unique_ptr<const MCInstrAnalysis> MIA(
356 T->createMCInstrAnalysis(MII.get()));
357 if (!MIA)
358 return {};
359 Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None;
360 for (const SectionRef &Section : sections()) {
361 StringRef Name;
362 if (Section.getName(Name))
363 continue;
364 if (Name == ".plt")
365 Plt = Section;
366 else if (Name == ".rela.plt" || Name == ".rel.plt")
367 RelaPlt = Section;
368 else if (Name == ".got.plt")
369 GotPlt = Section;
370 }
371 if (!Plt || !RelaPlt || !GotPlt)
372 return {};
373 StringRef PltContents;
374 if (Plt->getContents(PltContents))
375 return {};
376 ArrayRef<uint8_t> PltBytes((const uint8_t *)PltContents.data(),
377 Plt->getSize());
378 auto PltEntries = MIA->findPltEntries(Plt->getAddress(), PltBytes,
379 GotPlt->getAddress(), Triple);
380 // Build a map from GOT entry virtual address to PLT entry virtual address.
381 DenseMap<uint64_t, uint64_t> GotToPlt;
382 for (const auto &Entry : PltEntries)
383 GotToPlt.insert(std::make_pair(Entry.second, Entry.first));
384 // Find the relocations in the dynamic relocation table that point to
385 // locations in the GOT for which we know the corresponding PLT entry.
386 std::vector<std::pair<DataRefImpl, uint64_t>> Result;
387 for (const auto &Relocation : RelaPlt->relocations()) {
388 if (Relocation.getType() != JumpSlotReloc)
389 continue;
390 auto PltEntryIter = GotToPlt.find(Relocation.getOffset());
391 if (PltEntryIter != GotToPlt.end())
392 Result.push_back(std::make_pair(
393 Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second));
394 }
395 return Result;
396 }
397