• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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 <algorithm>
27 #include <cstddef>
28 #include <cstdint>
29 #include <memory>
30 #include <string>
31 #include <system_error>
32 #include <utility>
33 
34 using namespace llvm;
35 using namespace object;
36 
ELFObjectFileBase(unsigned int Type,MemoryBufferRef Source)37 ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
38     : ObjectFile(Type, Source) {}
39 
40 template <class ELFT>
41 static Expected<std::unique_ptr<ELFObjectFile<ELFT>>>
createPtr(MemoryBufferRef Object)42 createPtr(MemoryBufferRef Object) {
43   auto Ret = ELFObjectFile<ELFT>::create(Object);
44   if (Error E = Ret.takeError())
45     return std::move(E);
46   return make_unique<ELFObjectFile<ELFT>>(std::move(*Ret));
47 }
48 
49 Expected<std::unique_ptr<ObjectFile>>
createELFObjectFile(MemoryBufferRef Obj)50 ObjectFile::createELFObjectFile(MemoryBufferRef Obj) {
51   std::pair<unsigned char, unsigned char> Ident =
52       getElfArchType(Obj.getBuffer());
53   std::size_t MaxAlignment =
54       1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart()));
55 
56   if (MaxAlignment < 2)
57     return createError("Insufficient alignment");
58 
59   if (Ident.first == ELF::ELFCLASS32) {
60     if (Ident.second == ELF::ELFDATA2LSB)
61       return createPtr<ELF32LE>(Obj);
62     else if (Ident.second == ELF::ELFDATA2MSB)
63       return createPtr<ELF32BE>(Obj);
64     else
65       return createError("Invalid ELF data");
66   } else if (Ident.first == ELF::ELFCLASS64) {
67     if (Ident.second == ELF::ELFDATA2LSB)
68       return createPtr<ELF64LE>(Obj);
69     else if (Ident.second == ELF::ELFDATA2MSB)
70       return createPtr<ELF64BE>(Obj);
71     else
72       return createError("Invalid ELF data");
73   }
74   return createError("Invalid ELF class");
75 }
76 
getMIPSFeatures() const77 SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const {
78   SubtargetFeatures Features;
79   unsigned PlatformFlags = getPlatformFlags();
80 
81   switch (PlatformFlags & ELF::EF_MIPS_ARCH) {
82   case ELF::EF_MIPS_ARCH_1:
83     break;
84   case ELF::EF_MIPS_ARCH_2:
85     Features.AddFeature("mips2");
86     break;
87   case ELF::EF_MIPS_ARCH_3:
88     Features.AddFeature("mips3");
89     break;
90   case ELF::EF_MIPS_ARCH_4:
91     Features.AddFeature("mips4");
92     break;
93   case ELF::EF_MIPS_ARCH_5:
94     Features.AddFeature("mips5");
95     break;
96   case ELF::EF_MIPS_ARCH_32:
97     Features.AddFeature("mips32");
98     break;
99   case ELF::EF_MIPS_ARCH_64:
100     Features.AddFeature("mips64");
101     break;
102   case ELF::EF_MIPS_ARCH_32R2:
103     Features.AddFeature("mips32r2");
104     break;
105   case ELF::EF_MIPS_ARCH_64R2:
106     Features.AddFeature("mips64r2");
107     break;
108   case ELF::EF_MIPS_ARCH_32R6:
109     Features.AddFeature("mips32r6");
110     break;
111   case ELF::EF_MIPS_ARCH_64R6:
112     Features.AddFeature("mips64r6");
113     break;
114   default:
115     llvm_unreachable("Unknown EF_MIPS_ARCH value");
116   }
117 
118   switch (PlatformFlags & ELF::EF_MIPS_MACH) {
119   case ELF::EF_MIPS_MACH_NONE:
120     // No feature associated with this value.
121     break;
122   case ELF::EF_MIPS_MACH_OCTEON:
123     Features.AddFeature("cnmips");
124     break;
125   default:
126     llvm_unreachable("Unknown EF_MIPS_ARCH value");
127   }
128 
129   if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16)
130     Features.AddFeature("mips16");
131   if (PlatformFlags & ELF::EF_MIPS_MICROMIPS)
132     Features.AddFeature("micromips");
133 
134   return Features;
135 }
136 
getARMFeatures() const137 SubtargetFeatures ELFObjectFileBase::getARMFeatures() const {
138   SubtargetFeatures Features;
139   ARMAttributeParser Attributes;
140   std::error_code EC = getBuildAttributes(Attributes);
141   if (EC)
142     return SubtargetFeatures();
143 
144   // both ARMv7-M and R have to support thumb hardware div
145   bool isV7 = false;
146   if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch))
147     isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)
148       == ARMBuildAttrs::v7;
149 
150   if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) {
151     switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) {
152     case ARMBuildAttrs::ApplicationProfile:
153       Features.AddFeature("aclass");
154       break;
155     case ARMBuildAttrs::RealTimeProfile:
156       Features.AddFeature("rclass");
157       if (isV7)
158         Features.AddFeature("hwdiv");
159       break;
160     case ARMBuildAttrs::MicroControllerProfile:
161       Features.AddFeature("mclass");
162       if (isV7)
163         Features.AddFeature("hwdiv");
164       break;
165     }
166   }
167 
168   if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) {
169     switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) {
170     default:
171       break;
172     case ARMBuildAttrs::Not_Allowed:
173       Features.AddFeature("thumb", false);
174       Features.AddFeature("thumb2", false);
175       break;
176     case ARMBuildAttrs::AllowThumb32:
177       Features.AddFeature("thumb2");
178       break;
179     }
180   }
181 
182   if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) {
183     switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) {
184     default:
185       break;
186     case ARMBuildAttrs::Not_Allowed:
187       Features.AddFeature("vfp2", false);
188       Features.AddFeature("vfp3", false);
189       Features.AddFeature("vfp4", false);
190       break;
191     case ARMBuildAttrs::AllowFPv2:
192       Features.AddFeature("vfp2");
193       break;
194     case ARMBuildAttrs::AllowFPv3A:
195     case ARMBuildAttrs::AllowFPv3B:
196       Features.AddFeature("vfp3");
197       break;
198     case ARMBuildAttrs::AllowFPv4A:
199     case ARMBuildAttrs::AllowFPv4B:
200       Features.AddFeature("vfp4");
201       break;
202     }
203   }
204 
205   if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) {
206     switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) {
207     default:
208       break;
209     case ARMBuildAttrs::Not_Allowed:
210       Features.AddFeature("neon", false);
211       Features.AddFeature("fp16", false);
212       break;
213     case ARMBuildAttrs::AllowNeon:
214       Features.AddFeature("neon");
215       break;
216     case ARMBuildAttrs::AllowNeon2:
217       Features.AddFeature("neon");
218       Features.AddFeature("fp16");
219       break;
220     }
221   }
222 
223   if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) {
224     switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) {
225     default:
226       break;
227     case ARMBuildAttrs::DisallowDIV:
228       Features.AddFeature("hwdiv", false);
229       Features.AddFeature("hwdiv-arm", false);
230       break;
231     case ARMBuildAttrs::AllowDIVExt:
232       Features.AddFeature("hwdiv");
233       Features.AddFeature("hwdiv-arm");
234       break;
235     }
236   }
237 
238   return Features;
239 }
240 
getRISCVFeatures() const241 SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const {
242   SubtargetFeatures Features;
243   unsigned PlatformFlags = getPlatformFlags();
244 
245   if (PlatformFlags & ELF::EF_RISCV_RVC) {
246     Features.AddFeature("c");
247   }
248 
249   return Features;
250 }
251 
getFeatures() const252 SubtargetFeatures ELFObjectFileBase::getFeatures() const {
253   switch (getEMachine()) {
254   case ELF::EM_MIPS:
255     return getMIPSFeatures();
256   case ELF::EM_ARM:
257     return getARMFeatures();
258   case ELF::EM_RISCV:
259     return getRISCVFeatures();
260   default:
261     return SubtargetFeatures();
262   }
263 }
264 
265 // FIXME Encode from a tablegen description or target parser.
setARMSubArch(Triple & TheTriple) const266 void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
267   if (TheTriple.getSubArch() != Triple::NoSubArch)
268     return;
269 
270   ARMAttributeParser Attributes;
271   std::error_code EC = getBuildAttributes(Attributes);
272   if (EC)
273     return;
274 
275   std::string Triple;
276   // Default to ARM, but use the triple if it's been set.
277   if (TheTriple.isThumb())
278     Triple = "thumb";
279   else
280     Triple = "arm";
281 
282   if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
283     switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
284     case ARMBuildAttrs::v4:
285       Triple += "v4";
286       break;
287     case ARMBuildAttrs::v4T:
288       Triple += "v4t";
289       break;
290     case ARMBuildAttrs::v5T:
291       Triple += "v5t";
292       break;
293     case ARMBuildAttrs::v5TE:
294       Triple += "v5te";
295       break;
296     case ARMBuildAttrs::v5TEJ:
297       Triple += "v5tej";
298       break;
299     case ARMBuildAttrs::v6:
300       Triple += "v6";
301       break;
302     case ARMBuildAttrs::v6KZ:
303       Triple += "v6kz";
304       break;
305     case ARMBuildAttrs::v6T2:
306       Triple += "v6t2";
307       break;
308     case ARMBuildAttrs::v6K:
309       Triple += "v6k";
310       break;
311     case ARMBuildAttrs::v7:
312       Triple += "v7";
313       break;
314     case ARMBuildAttrs::v6_M:
315       Triple += "v6m";
316       break;
317     case ARMBuildAttrs::v6S_M:
318       Triple += "v6sm";
319       break;
320     case ARMBuildAttrs::v7E_M:
321       Triple += "v7em";
322       break;
323     }
324   }
325   if (!isLittleEndian())
326     Triple += "eb";
327 
328   TheTriple.setArchName(Triple);
329 }
330