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 
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>>>
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>>
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 
77 SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const {
78   SubtargetFeatures Features;
79   unsigned PlatformFlags;
80   getPlatformFlags(PlatformFlags);
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::getFeatures() const {
243   switch (getEMachine()) {
244   case ELF::EM_MIPS:
245     return getMIPSFeatures();
246   case ELF::EM_ARM:
247     return getARMFeatures();
248   default:
249     return SubtargetFeatures();
250   }
251 }
252 
253 // FIXME Encode from a tablegen description or target parser.
254 void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
255   if (TheTriple.getSubArch() != Triple::NoSubArch)
256     return;
257 
258   ARMAttributeParser Attributes;
259   std::error_code EC = getBuildAttributes(Attributes);
260   if (EC)
261     return;
262 
263   std::string Triple;
264   // Default to ARM, but use the triple if it's been set.
265   if (TheTriple.isThumb())
266     Triple = "thumb";
267   else
268     Triple = "arm";
269 
270   if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
271     switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
272     case ARMBuildAttrs::v4:
273       Triple += "v4";
274       break;
275     case ARMBuildAttrs::v4T:
276       Triple += "v4t";
277       break;
278     case ARMBuildAttrs::v5T:
279       Triple += "v5t";
280       break;
281     case ARMBuildAttrs::v5TE:
282       Triple += "v5te";
283       break;
284     case ARMBuildAttrs::v5TEJ:
285       Triple += "v5tej";
286       break;
287     case ARMBuildAttrs::v6:
288       Triple += "v6";
289       break;
290     case ARMBuildAttrs::v6KZ:
291       Triple += "v6kz";
292       break;
293     case ARMBuildAttrs::v6T2:
294       Triple += "v6t2";
295       break;
296     case ARMBuildAttrs::v6K:
297       Triple += "v6k";
298       break;
299     case ARMBuildAttrs::v7:
300       Triple += "v7";
301       break;
302     case ARMBuildAttrs::v6_M:
303       Triple += "v6m";
304       break;
305     case ARMBuildAttrs::v6S_M:
306       Triple += "v6sm";
307       break;
308     case ARMBuildAttrs::v7E_M:
309       Triple += "v7em";
310       break;
311     }
312   }
313   if (!isLittleEndian())
314     Triple += "eb";
315 
316   TheTriple.setArchName(Triple);
317 }
318