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