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"
15bae14cefSMichael J. Spencer #include "llvm/Support/MathExtras.h"
16b60a18deSMichael J. Spencer 
17c7d23ddbSEli Bendersky namespace llvm {
18b60a18deSMichael J. Spencer using namespace object;
19b60a18deSMichael J. Spencer 
2048af1c2aSRafael Espindola ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
2148af1c2aSRafael Espindola     : ObjectFile(Type, Source) {}
22ab73774cSRafael Espindola 
23437b0d58SRafael Espindola ErrorOr<std::unique_ptr<ObjectFile>>
2448af1c2aSRafael Espindola ObjectFile::createELFObjectFile(MemoryBufferRef Obj) {
25d5a8efe7SRafael Espindola   std::pair<unsigned char, unsigned char> Ident =
2648af1c2aSRafael Espindola       getElfArchType(Obj.getBuffer());
27bae14cefSMichael J. Spencer   std::size_t MaxAlignment =
2848af1c2aSRafael Espindola       1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart()));
29bae14cefSMichael J. Spencer 
30ac729b46SRafael Espindola   if (MaxAlignment < 2)
31ac729b46SRafael Espindola     return object_error::parse_failed;
32ac729b46SRafael Espindola 
33db4ed0bdSRafael Espindola   std::error_code EC;
3456440fd8SAhmed Charles   std::unique_ptr<ObjectFile> R;
35ac729b46SRafael Espindola   if (Ident.first == ELF::ELFCLASS32) {
36ac729b46SRafael Espindola     if (Ident.second == ELF::ELFDATA2LSB)
37ac729b46SRafael Espindola       R.reset(new ELFObjectFile<ELFType<support::little, false>>(Obj, EC));
38ac729b46SRafael Espindola     else if (Ident.second == ELF::ELFDATA2MSB)
39ac729b46SRafael Espindola       R.reset(new ELFObjectFile<ELFType<support::big, false>>(Obj, EC));
40692410efSRafael Espindola     else
4118ad2e54SAlexey Samsonov       return object_error::parse_failed;
4249179ddbSAlexey Samsonov   } else if (Ident.first == ELF::ELFCLASS64) {
43ac729b46SRafael Espindola     if (Ident.second == ELF::ELFDATA2LSB)
44ac729b46SRafael Espindola       R.reset(new ELFObjectFile<ELFType<support::little, true>>(Obj, EC));
45ac729b46SRafael Espindola     else if (Ident.second == ELF::ELFDATA2MSB)
46ac729b46SRafael Espindola       R.reset(new ELFObjectFile<ELFType<support::big, true>>(Obj, EC));
47ac729b46SRafael Espindola     else
4818ad2e54SAlexey Samsonov       return object_error::parse_failed;
4949179ddbSAlexey Samsonov   } else {
5049179ddbSAlexey Samsonov     return object_error::parse_failed;
51ac729b46SRafael Espindola   }
52692410efSRafael Espindola 
53692410efSRafael Espindola   if (EC)
54692410efSRafael Espindola     return EC;
55437b0d58SRafael Espindola   return std::move(R);
56b60a18deSMichael J. Spencer }
57b60a18deSMichael J. Spencer 
581d14864bSDaniel Sanders SubtargetFeatures ELFObjectFileBase::getFeatures() const {
591d14864bSDaniel Sanders   switch (getEMachine()) {
601d14864bSDaniel Sanders   case ELF::EM_MIPS: {
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   }
1201d14864bSDaniel Sanders   default:
1211d14864bSDaniel Sanders     return SubtargetFeatures();
1221d14864bSDaniel Sanders   }
1231d14864bSDaniel Sanders }
1241d14864bSDaniel Sanders 
125*df7c6ef9SSam Parker // FIXME Encode from a tablegen description or target parser.
126*df7c6ef9SSam Parker void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
127*df7c6ef9SSam Parker   if (TheTriple.getSubArch() != Triple::NoSubArch)
128*df7c6ef9SSam Parker     return;
129*df7c6ef9SSam Parker 
130*df7c6ef9SSam Parker   ARMAttributeParser Attributes;
131*df7c6ef9SSam Parker   std::error_code EC = getBuildAttributes(Attributes);
132*df7c6ef9SSam Parker   if (EC)
133*df7c6ef9SSam Parker     return;
134*df7c6ef9SSam Parker 
135*df7c6ef9SSam Parker   std::string Triple;
136*df7c6ef9SSam Parker   // Default to ARM, but use the triple if it's been set.
137*df7c6ef9SSam Parker   if (TheTriple.getArch() == Triple::thumb ||
138*df7c6ef9SSam Parker       TheTriple.getArch() == Triple::thumbeb)
139*df7c6ef9SSam Parker     Triple = "thumb";
140*df7c6ef9SSam Parker   else
141*df7c6ef9SSam Parker     Triple = "arm";
142*df7c6ef9SSam Parker 
143*df7c6ef9SSam Parker   if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
144*df7c6ef9SSam Parker     switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
145*df7c6ef9SSam Parker     case ARMBuildAttrs::v4:
146*df7c6ef9SSam Parker       Triple += "v4";
147*df7c6ef9SSam Parker       break;
148*df7c6ef9SSam Parker     case ARMBuildAttrs::v4T:
149*df7c6ef9SSam Parker       Triple += "v4t";
150*df7c6ef9SSam Parker       break;
151*df7c6ef9SSam Parker     case ARMBuildAttrs::v5T:
152*df7c6ef9SSam Parker       Triple += "v5t";
153*df7c6ef9SSam Parker       break;
154*df7c6ef9SSam Parker     case ARMBuildAttrs::v5TE:
155*df7c6ef9SSam Parker       Triple += "v5te";
156*df7c6ef9SSam Parker       break;
157*df7c6ef9SSam Parker     case ARMBuildAttrs::v5TEJ:
158*df7c6ef9SSam Parker       Triple += "v5tej";
159*df7c6ef9SSam Parker       break;
160*df7c6ef9SSam Parker     case ARMBuildAttrs::v6:
161*df7c6ef9SSam Parker       Triple += "v6";
162*df7c6ef9SSam Parker       break;
163*df7c6ef9SSam Parker     case ARMBuildAttrs::v6KZ:
164*df7c6ef9SSam Parker       Triple += "v6kz";
165*df7c6ef9SSam Parker       break;
166*df7c6ef9SSam Parker     case ARMBuildAttrs::v6T2:
167*df7c6ef9SSam Parker       Triple += "v6t2";
168*df7c6ef9SSam Parker       break;
169*df7c6ef9SSam Parker     case ARMBuildAttrs::v6K:
170*df7c6ef9SSam Parker       Triple += "v6k";
171*df7c6ef9SSam Parker       break;
172*df7c6ef9SSam Parker     case ARMBuildAttrs::v7:
173*df7c6ef9SSam Parker       Triple += "v7";
174*df7c6ef9SSam Parker       break;
175*df7c6ef9SSam Parker     case ARMBuildAttrs::v6_M:
176*df7c6ef9SSam Parker       Triple += "v6m";
177*df7c6ef9SSam Parker       break;
178*df7c6ef9SSam Parker     case ARMBuildAttrs::v6S_M:
179*df7c6ef9SSam Parker       Triple += "v6sm";
180*df7c6ef9SSam Parker       break;
181*df7c6ef9SSam Parker     case ARMBuildAttrs::v7E_M:
182*df7c6ef9SSam Parker       Triple += "v7em";
183*df7c6ef9SSam Parker       break;
184*df7c6ef9SSam Parker     }
185*df7c6ef9SSam Parker   }
186*df7c6ef9SSam Parker   if (!isLittleEndian())
187*df7c6ef9SSam Parker     Triple += "eb";
188*df7c6ef9SSam Parker 
189*df7c6ef9SSam Parker   TheTriple.setArchName(Triple);
190*df7c6ef9SSam Parker }
191*df7c6ef9SSam Parker 
192b60a18deSMichael J. Spencer } // end namespace llvm
193