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