xref: /llvm-project/llvm/lib/Object/ELFObjectFile.cpp (revision d36fb48a274bd6c53ce289e968be4c53c189e0a7)
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 
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>>>
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>>
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 
79 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 
139 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 
243 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 
254 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.
268 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>>
334 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   const auto *MIA = T->createMCInstrAnalysis(T->createMCInstrInfo());
355   if (!MIA)
356     return {};
357   Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None;
358   for (const SectionRef &Section : sections()) {
359     StringRef Name;
360     if (Section.getName(Name))
361       continue;
362     if (Name == ".plt")
363       Plt = Section;
364     else if (Name == ".rela.plt" || Name == ".rel.plt")
365       RelaPlt = Section;
366     else if (Name == ".got.plt")
367       GotPlt = Section;
368   }
369   if (!Plt || !RelaPlt || !GotPlt)
370     return {};
371   StringRef PltContents;
372   if (Plt->getContents(PltContents))
373     return {};
374   ArrayRef<uint8_t> PltBytes((const uint8_t *)PltContents.data(),
375                              Plt->getSize());
376   auto PltEntries = MIA->findPltEntries(Plt->getAddress(), PltBytes,
377                                         GotPlt->getAddress(), Triple);
378   // Build a map from GOT entry virtual address to PLT entry virtual address.
379   DenseMap<uint64_t, uint64_t> GotToPlt;
380   for (const auto &Entry : PltEntries)
381     GotToPlt.insert(std::make_pair(Entry.second, Entry.first));
382   // Find the relocations in the dynamic relocation table that point to
383   // locations in the GOT for which we know the corresponding PLT entry.
384   std::vector<std::pair<DataRefImpl, uint64_t>> Result;
385   for (const auto &Relocation : RelaPlt->relocations()) {
386     if (Relocation.getType() != JumpSlotReloc)
387       continue;
388     auto PltEntryIter = GotToPlt.find(Relocation.getOffset());
389     if (PltEntryIter != GotToPlt.end())
390       Result.push_back(std::make_pair(
391           Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second));
392   }
393   return Result;
394 }
395