1*1df42facSEugene Zelenko //===- ELFObjectFile.cpp - ELF object file implementation -----------------===// 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 14*1df42facSEugene Zelenko #include "llvm/ADT/Triple.h" 15*1df42facSEugene Zelenko #include "llvm/MC/SubtargetFeature.h" 16*1df42facSEugene Zelenko #include "llvm/Object/ELF.h" 17126973baSMichael J. Spencer #include "llvm/Object/ELFObjectFile.h" 18*1df42facSEugene Zelenko #include "llvm/Object/ELFTypes.h" 19*1df42facSEugene Zelenko #include "llvm/Object/Error.h" 20b0de00d5SSam Parker #include "llvm/Support/ARMBuildAttributes.h" 21b0de00d5SSam Parker #include "llvm/Support/ARMAttributeParser.h" 22*1df42facSEugene Zelenko #include "llvm/Support/ELF.h" 23*1df42facSEugene Zelenko #include "llvm/Support/Endian.h" 24*1df42facSEugene Zelenko #include "llvm/Support/ErrorHandling.h" 25bae14cefSMichael J. Spencer #include "llvm/Support/MathExtras.h" 26*1df42facSEugene Zelenko #include <algorithm> 27*1df42facSEugene Zelenko #include <cstddef> 28*1df42facSEugene Zelenko #include <cstdint> 29*1df42facSEugene Zelenko #include <memory> 30*1df42facSEugene Zelenko #include <string> 31*1df42facSEugene Zelenko #include <system_error> 32*1df42facSEugene Zelenko #include <utility> 33b60a18deSMichael J. Spencer 34*1df42facSEugene Zelenko using namespace llvm; 35b60a18deSMichael J. Spencer using namespace object; 36b60a18deSMichael J. Spencer 3748af1c2aSRafael Espindola ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source) 3848af1c2aSRafael Espindola : ObjectFile(Type, Source) {} 39ab73774cSRafael Espindola 40437b0d58SRafael Espindola ErrorOr<std::unique_ptr<ObjectFile>> 4148af1c2aSRafael Espindola ObjectFile::createELFObjectFile(MemoryBufferRef Obj) { 42d5a8efe7SRafael Espindola std::pair<unsigned char, unsigned char> Ident = 4348af1c2aSRafael Espindola getElfArchType(Obj.getBuffer()); 44bae14cefSMichael J. Spencer std::size_t MaxAlignment = 4548af1c2aSRafael Espindola 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart())); 46bae14cefSMichael J. Spencer 47ac729b46SRafael Espindola if (MaxAlignment < 2) 48ac729b46SRafael Espindola return object_error::parse_failed; 49ac729b46SRafael Espindola 50db4ed0bdSRafael Espindola std::error_code EC; 5156440fd8SAhmed Charles std::unique_ptr<ObjectFile> R; 52ac729b46SRafael Espindola if (Ident.first == ELF::ELFCLASS32) { 53ac729b46SRafael Espindola if (Ident.second == ELF::ELFDATA2LSB) 54ac729b46SRafael Espindola R.reset(new ELFObjectFile<ELFType<support::little, false>>(Obj, EC)); 55ac729b46SRafael Espindola else if (Ident.second == ELF::ELFDATA2MSB) 56ac729b46SRafael Espindola R.reset(new ELFObjectFile<ELFType<support::big, false>>(Obj, EC)); 57692410efSRafael Espindola else 5818ad2e54SAlexey Samsonov return object_error::parse_failed; 5949179ddbSAlexey Samsonov } else if (Ident.first == ELF::ELFCLASS64) { 60ac729b46SRafael Espindola if (Ident.second == ELF::ELFDATA2LSB) 61ac729b46SRafael Espindola R.reset(new ELFObjectFile<ELFType<support::little, true>>(Obj, EC)); 62ac729b46SRafael Espindola else if (Ident.second == ELF::ELFDATA2MSB) 63ac729b46SRafael Espindola R.reset(new ELFObjectFile<ELFType<support::big, true>>(Obj, EC)); 64ac729b46SRafael Espindola else 6518ad2e54SAlexey Samsonov return object_error::parse_failed; 6649179ddbSAlexey Samsonov } else { 6749179ddbSAlexey Samsonov return object_error::parse_failed; 68ac729b46SRafael Espindola } 69692410efSRafael Espindola 70692410efSRafael Espindola if (EC) 71692410efSRafael Espindola return EC; 72437b0d58SRafael Espindola return std::move(R); 73b60a18deSMichael J. Spencer } 74b60a18deSMichael J. Spencer 75b0de00d5SSam Parker SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const { 761d14864bSDaniel Sanders SubtargetFeatures Features; 771d14864bSDaniel Sanders unsigned PlatformFlags; 781d14864bSDaniel Sanders getPlatformFlags(PlatformFlags); 791d14864bSDaniel Sanders 801d14864bSDaniel Sanders switch (PlatformFlags & ELF::EF_MIPS_ARCH) { 811d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_1: 821d14864bSDaniel Sanders break; 831d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_2: 841d14864bSDaniel Sanders Features.AddFeature("mips2"); 851d14864bSDaniel Sanders break; 861d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_3: 871d14864bSDaniel Sanders Features.AddFeature("mips3"); 881d14864bSDaniel Sanders break; 891d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_4: 901d14864bSDaniel Sanders Features.AddFeature("mips4"); 911d14864bSDaniel Sanders break; 921d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_5: 931d14864bSDaniel Sanders Features.AddFeature("mips5"); 941d14864bSDaniel Sanders break; 951d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_32: 961d14864bSDaniel Sanders Features.AddFeature("mips32"); 971d14864bSDaniel Sanders break; 981d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_64: 991d14864bSDaniel Sanders Features.AddFeature("mips64"); 1001d14864bSDaniel Sanders break; 1011d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_32R2: 1021d14864bSDaniel Sanders Features.AddFeature("mips32r2"); 1031d14864bSDaniel Sanders break; 1041d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_64R2: 1051d14864bSDaniel Sanders Features.AddFeature("mips64r2"); 1061d14864bSDaniel Sanders break; 1071d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_32R6: 1081d14864bSDaniel Sanders Features.AddFeature("mips32r6"); 1091d14864bSDaniel Sanders break; 1101d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_64R6: 1111d14864bSDaniel Sanders Features.AddFeature("mips64r6"); 1121d14864bSDaniel Sanders break; 1131d14864bSDaniel Sanders default: 1141d14864bSDaniel Sanders llvm_unreachable("Unknown EF_MIPS_ARCH value"); 1151d14864bSDaniel Sanders } 1161d14864bSDaniel Sanders 1171d14864bSDaniel Sanders switch (PlatformFlags & ELF::EF_MIPS_MACH) { 1181d14864bSDaniel Sanders case ELF::EF_MIPS_MACH_NONE: 1191d14864bSDaniel Sanders // No feature associated with this value. 1201d14864bSDaniel Sanders break; 1211d14864bSDaniel Sanders case ELF::EF_MIPS_MACH_OCTEON: 1221d14864bSDaniel Sanders Features.AddFeature("cnmips"); 1231d14864bSDaniel Sanders break; 1241d14864bSDaniel Sanders default: 1251d14864bSDaniel Sanders llvm_unreachable("Unknown EF_MIPS_ARCH value"); 1261d14864bSDaniel Sanders } 1271d14864bSDaniel Sanders 1281d14864bSDaniel Sanders if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16) 1291d14864bSDaniel Sanders Features.AddFeature("mips16"); 1301d14864bSDaniel Sanders if (PlatformFlags & ELF::EF_MIPS_MICROMIPS) 1311d14864bSDaniel Sanders Features.AddFeature("micromips"); 1321d14864bSDaniel Sanders 1331d14864bSDaniel Sanders return Features; 1341d14864bSDaniel Sanders } 135b0de00d5SSam Parker 136b0de00d5SSam Parker SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { 137b0de00d5SSam Parker SubtargetFeatures Features; 138b0de00d5SSam Parker ARMAttributeParser Attributes; 139b0de00d5SSam Parker std::error_code EC = getBuildAttributes(Attributes); 140b0de00d5SSam Parker if (EC) 141b0de00d5SSam Parker return SubtargetFeatures(); 142b0de00d5SSam Parker 143b0de00d5SSam Parker // both ARMv7-M and R have to support thumb hardware div 144b0de00d5SSam Parker bool isV7 = false; 145b0de00d5SSam Parker if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) 146b0de00d5SSam Parker isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch) 147b0de00d5SSam Parker == ARMBuildAttrs::v7; 148b0de00d5SSam Parker 149b0de00d5SSam Parker if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) { 150b0de00d5SSam Parker switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) { 151b0de00d5SSam Parker case ARMBuildAttrs::ApplicationProfile: 152b0de00d5SSam Parker Features.AddFeature("aclass"); 153b0de00d5SSam Parker break; 154b0de00d5SSam Parker case ARMBuildAttrs::RealTimeProfile: 155b0de00d5SSam Parker Features.AddFeature("rclass"); 156b0de00d5SSam Parker if (isV7) 157b0de00d5SSam Parker Features.AddFeature("hwdiv"); 158b0de00d5SSam Parker break; 159b0de00d5SSam Parker case ARMBuildAttrs::MicroControllerProfile: 160b0de00d5SSam Parker Features.AddFeature("mclass"); 161b0de00d5SSam Parker if (isV7) 162b0de00d5SSam Parker Features.AddFeature("hwdiv"); 163b0de00d5SSam Parker break; 164b0de00d5SSam Parker } 165b0de00d5SSam Parker } 166b0de00d5SSam Parker 167b0de00d5SSam Parker if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) { 168b0de00d5SSam Parker switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) { 169b0de00d5SSam Parker default: 170b0de00d5SSam Parker break; 171b0de00d5SSam Parker case ARMBuildAttrs::Not_Allowed: 172b0de00d5SSam Parker Features.AddFeature("thumb", false); 173b0de00d5SSam Parker Features.AddFeature("thumb2", false); 174b0de00d5SSam Parker break; 175b0de00d5SSam Parker case ARMBuildAttrs::AllowThumb32: 176b0de00d5SSam Parker Features.AddFeature("thumb2"); 177b0de00d5SSam Parker break; 178b0de00d5SSam Parker } 179b0de00d5SSam Parker } 180b0de00d5SSam Parker 181b0de00d5SSam Parker if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) { 182b0de00d5SSam Parker switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) { 183b0de00d5SSam Parker default: 184b0de00d5SSam Parker break; 185b0de00d5SSam Parker case ARMBuildAttrs::Not_Allowed: 186b0de00d5SSam Parker Features.AddFeature("vfp2", false); 187b0de00d5SSam Parker Features.AddFeature("vfp3", false); 188b0de00d5SSam Parker Features.AddFeature("vfp4", false); 189b0de00d5SSam Parker break; 190b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv2: 191b0de00d5SSam Parker Features.AddFeature("vfp2"); 192b0de00d5SSam Parker break; 193b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv3A: 194b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv3B: 195b0de00d5SSam Parker Features.AddFeature("vfp3"); 196b0de00d5SSam Parker break; 197b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv4A: 198b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv4B: 199b0de00d5SSam Parker Features.AddFeature("vfp4"); 200b0de00d5SSam Parker break; 201b0de00d5SSam Parker } 202b0de00d5SSam Parker } 203b0de00d5SSam Parker 204b0de00d5SSam Parker if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) { 205b0de00d5SSam Parker switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) { 206b0de00d5SSam Parker default: 207b0de00d5SSam Parker break; 208b0de00d5SSam Parker case ARMBuildAttrs::Not_Allowed: 209b0de00d5SSam Parker Features.AddFeature("neon", false); 210b0de00d5SSam Parker Features.AddFeature("fp16", false); 211b0de00d5SSam Parker break; 212b0de00d5SSam Parker case ARMBuildAttrs::AllowNeon: 213b0de00d5SSam Parker Features.AddFeature("neon"); 214b0de00d5SSam Parker break; 215b0de00d5SSam Parker case ARMBuildAttrs::AllowNeon2: 216b0de00d5SSam Parker Features.AddFeature("neon"); 217b0de00d5SSam Parker Features.AddFeature("fp16"); 218b0de00d5SSam Parker break; 219b0de00d5SSam Parker } 220b0de00d5SSam Parker } 221b0de00d5SSam Parker 222b0de00d5SSam Parker if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) { 223b0de00d5SSam Parker switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) { 224b0de00d5SSam Parker default: 225b0de00d5SSam Parker break; 226b0de00d5SSam Parker case ARMBuildAttrs::DisallowDIV: 227b0de00d5SSam Parker Features.AddFeature("hwdiv", false); 228b0de00d5SSam Parker Features.AddFeature("hwdiv-arm", false); 229b0de00d5SSam Parker break; 230b0de00d5SSam Parker case ARMBuildAttrs::AllowDIVExt: 231b0de00d5SSam Parker Features.AddFeature("hwdiv"); 232b0de00d5SSam Parker Features.AddFeature("hwdiv-arm"); 233b0de00d5SSam Parker break; 234b0de00d5SSam Parker } 235b0de00d5SSam Parker } 236b0de00d5SSam Parker 237b0de00d5SSam Parker return Features; 238b0de00d5SSam Parker } 239b0de00d5SSam Parker 240b0de00d5SSam Parker SubtargetFeatures ELFObjectFileBase::getFeatures() const { 241b0de00d5SSam Parker switch (getEMachine()) { 242b0de00d5SSam Parker case ELF::EM_MIPS: 243b0de00d5SSam Parker return getMIPSFeatures(); 244b0de00d5SSam Parker case ELF::EM_ARM: 245b0de00d5SSam Parker return getARMFeatures(); 2461d14864bSDaniel Sanders default: 2471d14864bSDaniel Sanders return SubtargetFeatures(); 2481d14864bSDaniel Sanders } 2491d14864bSDaniel Sanders } 2501d14864bSDaniel Sanders 251df7c6ef9SSam Parker // FIXME Encode from a tablegen description or target parser. 252df7c6ef9SSam Parker void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { 253df7c6ef9SSam Parker if (TheTriple.getSubArch() != Triple::NoSubArch) 254df7c6ef9SSam Parker return; 255df7c6ef9SSam Parker 256df7c6ef9SSam Parker ARMAttributeParser Attributes; 257df7c6ef9SSam Parker std::error_code EC = getBuildAttributes(Attributes); 258df7c6ef9SSam Parker if (EC) 259df7c6ef9SSam Parker return; 260df7c6ef9SSam Parker 261df7c6ef9SSam Parker std::string Triple; 262df7c6ef9SSam Parker // Default to ARM, but use the triple if it's been set. 263df7c6ef9SSam Parker if (TheTriple.getArch() == Triple::thumb || 264df7c6ef9SSam Parker TheTriple.getArch() == Triple::thumbeb) 265df7c6ef9SSam Parker Triple = "thumb"; 266df7c6ef9SSam Parker else 267df7c6ef9SSam Parker Triple = "arm"; 268df7c6ef9SSam Parker 269df7c6ef9SSam Parker if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) { 270df7c6ef9SSam Parker switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) { 271df7c6ef9SSam Parker case ARMBuildAttrs::v4: 272df7c6ef9SSam Parker Triple += "v4"; 273df7c6ef9SSam Parker break; 274df7c6ef9SSam Parker case ARMBuildAttrs::v4T: 275df7c6ef9SSam Parker Triple += "v4t"; 276df7c6ef9SSam Parker break; 277df7c6ef9SSam Parker case ARMBuildAttrs::v5T: 278df7c6ef9SSam Parker Triple += "v5t"; 279df7c6ef9SSam Parker break; 280df7c6ef9SSam Parker case ARMBuildAttrs::v5TE: 281df7c6ef9SSam Parker Triple += "v5te"; 282df7c6ef9SSam Parker break; 283df7c6ef9SSam Parker case ARMBuildAttrs::v5TEJ: 284df7c6ef9SSam Parker Triple += "v5tej"; 285df7c6ef9SSam Parker break; 286df7c6ef9SSam Parker case ARMBuildAttrs::v6: 287df7c6ef9SSam Parker Triple += "v6"; 288df7c6ef9SSam Parker break; 289df7c6ef9SSam Parker case ARMBuildAttrs::v6KZ: 290df7c6ef9SSam Parker Triple += "v6kz"; 291df7c6ef9SSam Parker break; 292df7c6ef9SSam Parker case ARMBuildAttrs::v6T2: 293df7c6ef9SSam Parker Triple += "v6t2"; 294df7c6ef9SSam Parker break; 295df7c6ef9SSam Parker case ARMBuildAttrs::v6K: 296df7c6ef9SSam Parker Triple += "v6k"; 297df7c6ef9SSam Parker break; 298df7c6ef9SSam Parker case ARMBuildAttrs::v7: 299df7c6ef9SSam Parker Triple += "v7"; 300df7c6ef9SSam Parker break; 301df7c6ef9SSam Parker case ARMBuildAttrs::v6_M: 302df7c6ef9SSam Parker Triple += "v6m"; 303df7c6ef9SSam Parker break; 304df7c6ef9SSam Parker case ARMBuildAttrs::v6S_M: 305df7c6ef9SSam Parker Triple += "v6sm"; 306df7c6ef9SSam Parker break; 307df7c6ef9SSam Parker case ARMBuildAttrs::v7E_M: 308df7c6ef9SSam Parker Triple += "v7em"; 309df7c6ef9SSam Parker break; 310df7c6ef9SSam Parker } 311df7c6ef9SSam Parker } 312df7c6ef9SSam Parker if (!isLittleEndian()) 313df7c6ef9SSam Parker Triple += "eb"; 314df7c6ef9SSam Parker 315df7c6ef9SSam Parker TheTriple.setArchName(Triple); 316df7c6ef9SSam Parker } 317