1b60a18deSMichael J. Spencer //===- ELFObjectFile.cpp - ELF object file implementation -------*- C++ -*-===//
2b60a18deSMichael J. Spencer //
3b60a18deSMichael J. Spencer //                     The LLVM Compiler Infrastructure
4b60a18deSMichael J. Spencer //
5b60a18deSMichael J. Spencer // This file is distributed under the University of Illinois Open Source
6b60a18deSMichael J. Spencer // License. See LICENSE.TXT for details.
7b60a18deSMichael J. Spencer //
8b60a18deSMichael J. Spencer //===----------------------------------------------------------------------===//
9b60a18deSMichael J. Spencer //
10c7d23ddbSEli Bendersky // Part of the ELFObjectFile class implementation.
11b60a18deSMichael J. Spencer //
12b60a18deSMichael J. Spencer //===----------------------------------------------------------------------===//
13b60a18deSMichael J. Spencer 
14126973baSMichael J. Spencer #include "llvm/Object/ELFObjectFile.h"
15*b0de00d5SSam Parker #include "llvm/Support/ARMBuildAttributes.h"
16*b0de00d5SSam Parker #include "llvm/Support/ARMAttributeParser.h"
17bae14cefSMichael J. Spencer #include "llvm/Support/MathExtras.h"
18b60a18deSMichael J. Spencer 
19c7d23ddbSEli Bendersky namespace llvm {
20b60a18deSMichael J. Spencer using namespace object;
21b60a18deSMichael J. Spencer 
2248af1c2aSRafael Espindola ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
2348af1c2aSRafael Espindola     : ObjectFile(Type, Source) {}
24ab73774cSRafael Espindola 
25437b0d58SRafael Espindola ErrorOr<std::unique_ptr<ObjectFile>>
2648af1c2aSRafael Espindola ObjectFile::createELFObjectFile(MemoryBufferRef Obj) {
27d5a8efe7SRafael Espindola   std::pair<unsigned char, unsigned char> Ident =
2848af1c2aSRafael Espindola       getElfArchType(Obj.getBuffer());
29bae14cefSMichael J. Spencer   std::size_t MaxAlignment =
3048af1c2aSRafael Espindola       1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart()));
31bae14cefSMichael J. Spencer 
32ac729b46SRafael Espindola   if (MaxAlignment < 2)
33ac729b46SRafael Espindola     return object_error::parse_failed;
34ac729b46SRafael Espindola 
35db4ed0bdSRafael Espindola   std::error_code EC;
3656440fd8SAhmed Charles   std::unique_ptr<ObjectFile> R;
37ac729b46SRafael Espindola   if (Ident.first == ELF::ELFCLASS32) {
38ac729b46SRafael Espindola     if (Ident.second == ELF::ELFDATA2LSB)
39ac729b46SRafael Espindola       R.reset(new ELFObjectFile<ELFType<support::little, false>>(Obj, EC));
40ac729b46SRafael Espindola     else if (Ident.second == ELF::ELFDATA2MSB)
41ac729b46SRafael Espindola       R.reset(new ELFObjectFile<ELFType<support::big, false>>(Obj, EC));
42692410efSRafael Espindola     else
4318ad2e54SAlexey Samsonov       return object_error::parse_failed;
4449179ddbSAlexey Samsonov   } else if (Ident.first == ELF::ELFCLASS64) {
45ac729b46SRafael Espindola     if (Ident.second == ELF::ELFDATA2LSB)
46ac729b46SRafael Espindola       R.reset(new ELFObjectFile<ELFType<support::little, true>>(Obj, EC));
47ac729b46SRafael Espindola     else if (Ident.second == ELF::ELFDATA2MSB)
48ac729b46SRafael Espindola       R.reset(new ELFObjectFile<ELFType<support::big, true>>(Obj, EC));
49ac729b46SRafael Espindola     else
5018ad2e54SAlexey Samsonov       return object_error::parse_failed;
5149179ddbSAlexey Samsonov   } else {
5249179ddbSAlexey Samsonov     return object_error::parse_failed;
53ac729b46SRafael Espindola   }
54692410efSRafael Espindola 
55692410efSRafael Espindola   if (EC)
56692410efSRafael Espindola     return EC;
57437b0d58SRafael Espindola   return std::move(R);
58b60a18deSMichael J. Spencer }
59b60a18deSMichael J. Spencer 
60*b0de00d5SSam Parker SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const {
611d14864bSDaniel Sanders   SubtargetFeatures Features;
621d14864bSDaniel Sanders   unsigned PlatformFlags;
631d14864bSDaniel Sanders   getPlatformFlags(PlatformFlags);
641d14864bSDaniel Sanders 
651d14864bSDaniel Sanders   switch (PlatformFlags & ELF::EF_MIPS_ARCH) {
661d14864bSDaniel Sanders   case ELF::EF_MIPS_ARCH_1:
671d14864bSDaniel Sanders     break;
681d14864bSDaniel Sanders   case ELF::EF_MIPS_ARCH_2:
691d14864bSDaniel Sanders     Features.AddFeature("mips2");
701d14864bSDaniel Sanders     break;
711d14864bSDaniel Sanders   case ELF::EF_MIPS_ARCH_3:
721d14864bSDaniel Sanders     Features.AddFeature("mips3");
731d14864bSDaniel Sanders     break;
741d14864bSDaniel Sanders   case ELF::EF_MIPS_ARCH_4:
751d14864bSDaniel Sanders     Features.AddFeature("mips4");
761d14864bSDaniel Sanders     break;
771d14864bSDaniel Sanders   case ELF::EF_MIPS_ARCH_5:
781d14864bSDaniel Sanders     Features.AddFeature("mips5");
791d14864bSDaniel Sanders     break;
801d14864bSDaniel Sanders   case ELF::EF_MIPS_ARCH_32:
811d14864bSDaniel Sanders     Features.AddFeature("mips32");
821d14864bSDaniel Sanders     break;
831d14864bSDaniel Sanders   case ELF::EF_MIPS_ARCH_64:
841d14864bSDaniel Sanders     Features.AddFeature("mips64");
851d14864bSDaniel Sanders     break;
861d14864bSDaniel Sanders   case ELF::EF_MIPS_ARCH_32R2:
871d14864bSDaniel Sanders     Features.AddFeature("mips32r2");
881d14864bSDaniel Sanders     break;
891d14864bSDaniel Sanders   case ELF::EF_MIPS_ARCH_64R2:
901d14864bSDaniel Sanders     Features.AddFeature("mips64r2");
911d14864bSDaniel Sanders     break;
921d14864bSDaniel Sanders   case ELF::EF_MIPS_ARCH_32R6:
931d14864bSDaniel Sanders     Features.AddFeature("mips32r6");
941d14864bSDaniel Sanders     break;
951d14864bSDaniel Sanders   case ELF::EF_MIPS_ARCH_64R6:
961d14864bSDaniel Sanders     Features.AddFeature("mips64r6");
971d14864bSDaniel Sanders     break;
981d14864bSDaniel Sanders   default:
991d14864bSDaniel Sanders     llvm_unreachable("Unknown EF_MIPS_ARCH value");
1001d14864bSDaniel Sanders   }
1011d14864bSDaniel Sanders 
1021d14864bSDaniel Sanders   switch (PlatformFlags & ELF::EF_MIPS_MACH) {
1031d14864bSDaniel Sanders   case ELF::EF_MIPS_MACH_NONE:
1041d14864bSDaniel Sanders     // No feature associated with this value.
1051d14864bSDaniel Sanders     break;
1061d14864bSDaniel Sanders   case ELF::EF_MIPS_MACH_OCTEON:
1071d14864bSDaniel Sanders     Features.AddFeature("cnmips");
1081d14864bSDaniel Sanders     break;
1091d14864bSDaniel Sanders   default:
1101d14864bSDaniel Sanders     llvm_unreachable("Unknown EF_MIPS_ARCH value");
1111d14864bSDaniel Sanders   }
1121d14864bSDaniel Sanders 
1131d14864bSDaniel Sanders   if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16)
1141d14864bSDaniel Sanders     Features.AddFeature("mips16");
1151d14864bSDaniel Sanders   if (PlatformFlags & ELF::EF_MIPS_MICROMIPS)
1161d14864bSDaniel Sanders     Features.AddFeature("micromips");
1171d14864bSDaniel Sanders 
1181d14864bSDaniel Sanders   return Features;
1191d14864bSDaniel Sanders }
120*b0de00d5SSam Parker 
121*b0de00d5SSam Parker SubtargetFeatures ELFObjectFileBase::getARMFeatures() const {
122*b0de00d5SSam Parker   SubtargetFeatures Features;
123*b0de00d5SSam Parker   ARMAttributeParser Attributes;
124*b0de00d5SSam Parker   std::error_code EC = getBuildAttributes(Attributes);
125*b0de00d5SSam Parker   if (EC)
126*b0de00d5SSam Parker     return SubtargetFeatures();
127*b0de00d5SSam Parker 
128*b0de00d5SSam Parker   // both ARMv7-M and R have to support thumb hardware div
129*b0de00d5SSam Parker   bool isV7 = false;
130*b0de00d5SSam Parker   if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch))
131*b0de00d5SSam Parker     isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)
132*b0de00d5SSam Parker       == ARMBuildAttrs::v7;
133*b0de00d5SSam Parker 
134*b0de00d5SSam Parker   if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) {
135*b0de00d5SSam Parker     switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) {
136*b0de00d5SSam Parker     case ARMBuildAttrs::ApplicationProfile:
137*b0de00d5SSam Parker       Features.AddFeature("aclass");
138*b0de00d5SSam Parker       break;
139*b0de00d5SSam Parker     case ARMBuildAttrs::RealTimeProfile:
140*b0de00d5SSam Parker       Features.AddFeature("rclass");
141*b0de00d5SSam Parker       if (isV7)
142*b0de00d5SSam Parker         Features.AddFeature("hwdiv");
143*b0de00d5SSam Parker       break;
144*b0de00d5SSam Parker     case ARMBuildAttrs::MicroControllerProfile:
145*b0de00d5SSam Parker       Features.AddFeature("mclass");
146*b0de00d5SSam Parker       if (isV7)
147*b0de00d5SSam Parker         Features.AddFeature("hwdiv");
148*b0de00d5SSam Parker       break;
149*b0de00d5SSam Parker     }
150*b0de00d5SSam Parker   }
151*b0de00d5SSam Parker 
152*b0de00d5SSam Parker   if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) {
153*b0de00d5SSam Parker     switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) {
154*b0de00d5SSam Parker     default:
155*b0de00d5SSam Parker       break;
156*b0de00d5SSam Parker     case ARMBuildAttrs::Not_Allowed:
157*b0de00d5SSam Parker       Features.AddFeature("thumb", false);
158*b0de00d5SSam Parker       Features.AddFeature("thumb2", false);
159*b0de00d5SSam Parker       break;
160*b0de00d5SSam Parker     case ARMBuildAttrs::AllowThumb32:
161*b0de00d5SSam Parker       Features.AddFeature("thumb2");
162*b0de00d5SSam Parker       break;
163*b0de00d5SSam Parker     }
164*b0de00d5SSam Parker   }
165*b0de00d5SSam Parker 
166*b0de00d5SSam Parker   if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) {
167*b0de00d5SSam Parker     switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) {
168*b0de00d5SSam Parker     default:
169*b0de00d5SSam Parker       break;
170*b0de00d5SSam Parker     case ARMBuildAttrs::Not_Allowed:
171*b0de00d5SSam Parker       Features.AddFeature("vfp2", false);
172*b0de00d5SSam Parker       Features.AddFeature("vfp3", false);
173*b0de00d5SSam Parker       Features.AddFeature("vfp4", false);
174*b0de00d5SSam Parker       break;
175*b0de00d5SSam Parker     case ARMBuildAttrs::AllowFPv2:
176*b0de00d5SSam Parker       Features.AddFeature("vfp2");
177*b0de00d5SSam Parker       break;
178*b0de00d5SSam Parker     case ARMBuildAttrs::AllowFPv3A:
179*b0de00d5SSam Parker     case ARMBuildAttrs::AllowFPv3B:
180*b0de00d5SSam Parker       Features.AddFeature("vfp3");
181*b0de00d5SSam Parker       break;
182*b0de00d5SSam Parker     case ARMBuildAttrs::AllowFPv4A:
183*b0de00d5SSam Parker     case ARMBuildAttrs::AllowFPv4B:
184*b0de00d5SSam Parker       Features.AddFeature("vfp4");
185*b0de00d5SSam Parker       break;
186*b0de00d5SSam Parker     }
187*b0de00d5SSam Parker   }
188*b0de00d5SSam Parker 
189*b0de00d5SSam Parker   if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) {
190*b0de00d5SSam Parker     switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) {
191*b0de00d5SSam Parker     default:
192*b0de00d5SSam Parker       break;
193*b0de00d5SSam Parker     case ARMBuildAttrs::Not_Allowed:
194*b0de00d5SSam Parker       Features.AddFeature("neon", false);
195*b0de00d5SSam Parker       Features.AddFeature("fp16", false);
196*b0de00d5SSam Parker       break;
197*b0de00d5SSam Parker     case ARMBuildAttrs::AllowNeon:
198*b0de00d5SSam Parker       Features.AddFeature("neon");
199*b0de00d5SSam Parker       break;
200*b0de00d5SSam Parker     case ARMBuildAttrs::AllowNeon2:
201*b0de00d5SSam Parker       Features.AddFeature("neon");
202*b0de00d5SSam Parker       Features.AddFeature("fp16");
203*b0de00d5SSam Parker       break;
204*b0de00d5SSam Parker     }
205*b0de00d5SSam Parker   }
206*b0de00d5SSam Parker 
207*b0de00d5SSam Parker   if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) {
208*b0de00d5SSam Parker     switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) {
209*b0de00d5SSam Parker     default:
210*b0de00d5SSam Parker       break;
211*b0de00d5SSam Parker     case ARMBuildAttrs::DisallowDIV:
212*b0de00d5SSam Parker       Features.AddFeature("hwdiv", false);
213*b0de00d5SSam Parker       Features.AddFeature("hwdiv-arm", false);
214*b0de00d5SSam Parker       break;
215*b0de00d5SSam Parker     case ARMBuildAttrs::AllowDIVExt:
216*b0de00d5SSam Parker       Features.AddFeature("hwdiv");
217*b0de00d5SSam Parker       Features.AddFeature("hwdiv-arm");
218*b0de00d5SSam Parker       break;
219*b0de00d5SSam Parker     }
220*b0de00d5SSam Parker   }
221*b0de00d5SSam Parker 
222*b0de00d5SSam Parker   return Features;
223*b0de00d5SSam Parker }
224*b0de00d5SSam Parker 
225*b0de00d5SSam Parker SubtargetFeatures ELFObjectFileBase::getFeatures() const {
226*b0de00d5SSam Parker   switch (getEMachine()) {
227*b0de00d5SSam Parker   case ELF::EM_MIPS:
228*b0de00d5SSam Parker     return getMIPSFeatures();
229*b0de00d5SSam Parker   case ELF::EM_ARM:
230*b0de00d5SSam Parker     return getARMFeatures();
2311d14864bSDaniel Sanders   default:
2321d14864bSDaniel Sanders     return SubtargetFeatures();
2331d14864bSDaniel Sanders   }
2341d14864bSDaniel Sanders }
2351d14864bSDaniel Sanders 
236df7c6ef9SSam Parker // FIXME Encode from a tablegen description or target parser.
237df7c6ef9SSam Parker void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
238df7c6ef9SSam Parker   if (TheTriple.getSubArch() != Triple::NoSubArch)
239df7c6ef9SSam Parker     return;
240df7c6ef9SSam Parker 
241df7c6ef9SSam Parker   ARMAttributeParser Attributes;
242df7c6ef9SSam Parker   std::error_code EC = getBuildAttributes(Attributes);
243df7c6ef9SSam Parker   if (EC)
244df7c6ef9SSam Parker     return;
245df7c6ef9SSam Parker 
246df7c6ef9SSam Parker   std::string Triple;
247df7c6ef9SSam Parker   // Default to ARM, but use the triple if it's been set.
248df7c6ef9SSam Parker   if (TheTriple.getArch() == Triple::thumb ||
249df7c6ef9SSam Parker       TheTriple.getArch() == Triple::thumbeb)
250df7c6ef9SSam Parker     Triple = "thumb";
251df7c6ef9SSam Parker   else
252df7c6ef9SSam Parker     Triple = "arm";
253df7c6ef9SSam Parker 
254df7c6ef9SSam Parker   if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
255df7c6ef9SSam Parker     switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
256df7c6ef9SSam Parker     case ARMBuildAttrs::v4:
257df7c6ef9SSam Parker       Triple += "v4";
258df7c6ef9SSam Parker       break;
259df7c6ef9SSam Parker     case ARMBuildAttrs::v4T:
260df7c6ef9SSam Parker       Triple += "v4t";
261df7c6ef9SSam Parker       break;
262df7c6ef9SSam Parker     case ARMBuildAttrs::v5T:
263df7c6ef9SSam Parker       Triple += "v5t";
264df7c6ef9SSam Parker       break;
265df7c6ef9SSam Parker     case ARMBuildAttrs::v5TE:
266df7c6ef9SSam Parker       Triple += "v5te";
267df7c6ef9SSam Parker       break;
268df7c6ef9SSam Parker     case ARMBuildAttrs::v5TEJ:
269df7c6ef9SSam Parker       Triple += "v5tej";
270df7c6ef9SSam Parker       break;
271df7c6ef9SSam Parker     case ARMBuildAttrs::v6:
272df7c6ef9SSam Parker       Triple += "v6";
273df7c6ef9SSam Parker       break;
274df7c6ef9SSam Parker     case ARMBuildAttrs::v6KZ:
275df7c6ef9SSam Parker       Triple += "v6kz";
276df7c6ef9SSam Parker       break;
277df7c6ef9SSam Parker     case ARMBuildAttrs::v6T2:
278df7c6ef9SSam Parker       Triple += "v6t2";
279df7c6ef9SSam Parker       break;
280df7c6ef9SSam Parker     case ARMBuildAttrs::v6K:
281df7c6ef9SSam Parker       Triple += "v6k";
282df7c6ef9SSam Parker       break;
283df7c6ef9SSam Parker     case ARMBuildAttrs::v7:
284df7c6ef9SSam Parker       Triple += "v7";
285df7c6ef9SSam Parker       break;
286df7c6ef9SSam Parker     case ARMBuildAttrs::v6_M:
287df7c6ef9SSam Parker       Triple += "v6m";
288df7c6ef9SSam Parker       break;
289df7c6ef9SSam Parker     case ARMBuildAttrs::v6S_M:
290df7c6ef9SSam Parker       Triple += "v6sm";
291df7c6ef9SSam Parker       break;
292df7c6ef9SSam Parker     case ARMBuildAttrs::v7E_M:
293df7c6ef9SSam Parker       Triple += "v7em";
294df7c6ef9SSam Parker       break;
295df7c6ef9SSam Parker     }
296df7c6ef9SSam Parker   }
297df7c6ef9SSam Parker   if (!isLittleEndian())
298df7c6ef9SSam Parker     Triple += "eb";
299df7c6ef9SSam Parker 
300df7c6ef9SSam Parker   TheTriple.setArchName(Triple);
301df7c6ef9SSam Parker }
302df7c6ef9SSam Parker 
303b60a18deSMichael J. Spencer } // end namespace llvm
304