xref: /llvm-project/llvm/lib/Object/ELFObjectFile.cpp (revision c6d54ae9daad8fbcf26bbff2be6844bf05c19f6e)
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.
10 //
11 //===----------------------------------------------------------------------===//
12 
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>
34 
35 using namespace llvm;
36 using namespace object;
37 
38 ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
39     : ObjectFile(Type, Source) {}
40 
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));
48 }
49 
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()));
56 
57   if (MaxAlignment < 2)
58     return createError("Insufficient alignment");
59 
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");
74   }
75   return createError("Invalid ELF class");
76 }
77 
78 SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const {
79   SubtargetFeatures Features;
80   unsigned PlatformFlags = getPlatformFlags();
81 
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");
117   }
118 
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");
128   }
129 
130   if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16)
131     Features.AddFeature("mips16");
132   if (PlatformFlags & ELF::EF_MIPS_MICROMIPS)
133     Features.AddFeature("micromips");
134 
135   return Features;
136 }
137 
138 SubtargetFeatures ELFObjectFileBase::getARMFeatures() const {
139   SubtargetFeatures Features;
140   ARMAttributeParser Attributes;
141   std::error_code EC = getBuildAttributes(Attributes);
142   if (EC)
143     return SubtargetFeatures();
144 
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;
150 
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;
166     }
167   }
168 
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;
180     }
181   }
182 
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;
203     }
204   }
205 
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;
221     }
222   }
223 
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;
236     }
237   }
238 
239   return Features;
240 }
241 
242 SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const {
243   SubtargetFeatures Features;
244   unsigned PlatformFlags = getPlatformFlags();
245 
246   if (PlatformFlags & ELF::EF_RISCV_RVC) {
247     Features.AddFeature("c");
248   }
249 
250   return Features;
251 }
252 
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();
263   }
264 }
265 
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;
270 
271   ARMAttributeParser Attributes;
272   std::error_code EC = getBuildAttributes(Attributes);
273   if (EC)
274     return;
275 
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";
282 
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;
324     }
325   }
326   if (!isLittleEndian())
327     Triple += "eb";
328 
329   TheTriple.setArchName(Triple);
330 }
331 
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 {};
352   }
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;
369   }
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));
393   }
394   return Result;
395 }
396