151690af2SDimitry Andric //===- ELFObjectFile.cpp - ELF object file implementation -----------------===// 22754fe60SDimitry Andric // 32754fe60SDimitry Andric // The LLVM Compiler Infrastructure 42754fe60SDimitry Andric // 52754fe60SDimitry Andric // This file is distributed under the University of Illinois Open Source 62754fe60SDimitry Andric // License. See LICENSE.TXT for details. 72754fe60SDimitry Andric // 82754fe60SDimitry Andric //===----------------------------------------------------------------------===// 92754fe60SDimitry Andric // 10dff0c46cSDimitry Andric // Part of the ELFObjectFile class implementation. 112754fe60SDimitry Andric // 122754fe60SDimitry Andric //===----------------------------------------------------------------------===// 132754fe60SDimitry Andric 14db17bf38SDimitry Andric #include "llvm/Object/ELFObjectFile.h" 1551690af2SDimitry Andric #include "llvm/ADT/Triple.h" 16db17bf38SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 1751690af2SDimitry Andric #include "llvm/MC/SubtargetFeature.h" 1851690af2SDimitry Andric #include "llvm/Object/ELF.h" 1951690af2SDimitry Andric #include "llvm/Object/ELFTypes.h" 2051690af2SDimitry Andric #include "llvm/Object/Error.h" 217a7e6055SDimitry Andric #include "llvm/Support/ARMAttributeParser.h" 22db17bf38SDimitry Andric #include "llvm/Support/ARMBuildAttributes.h" 2351690af2SDimitry Andric #include "llvm/Support/Endian.h" 2451690af2SDimitry Andric #include "llvm/Support/ErrorHandling.h" 25139f7f9bSDimitry Andric #include "llvm/Support/MathExtras.h" 2651690af2SDimitry Andric #include <algorithm> 2751690af2SDimitry Andric #include <cstddef> 2851690af2SDimitry Andric #include <cstdint> 2951690af2SDimitry Andric #include <memory> 3051690af2SDimitry Andric #include <string> 3151690af2SDimitry Andric #include <system_error> 3251690af2SDimitry Andric #include <utility> 332754fe60SDimitry Andric 3451690af2SDimitry Andric using namespace llvm; 352754fe60SDimitry Andric using namespace object; 362754fe60SDimitry Andric 3739d628a0SDimitry Andric ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source) 3839d628a0SDimitry Andric : ObjectFile(Type, Source) {} 3939d628a0SDimitry Andric 4039d628a0SDimitry Andric ErrorOr<std::unique_ptr<ObjectFile>> 4139d628a0SDimitry Andric ObjectFile::createELFObjectFile(MemoryBufferRef Obj) { 4291bc56edSDimitry Andric std::pair<unsigned char, unsigned char> Ident = 4339d628a0SDimitry Andric getElfArchType(Obj.getBuffer()); 44139f7f9bSDimitry Andric std::size_t MaxAlignment = 4539d628a0SDimitry Andric 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart())); 46139f7f9bSDimitry Andric 4797bc6c73SDimitry Andric if (MaxAlignment < 2) 4897bc6c73SDimitry Andric return object_error::parse_failed; 4997bc6c73SDimitry Andric 5091bc56edSDimitry Andric std::error_code EC; 5191bc56edSDimitry Andric std::unique_ptr<ObjectFile> R; 5297bc6c73SDimitry Andric if (Ident.first == ELF::ELFCLASS32) { 5397bc6c73SDimitry Andric if (Ident.second == ELF::ELFDATA2LSB) 5497bc6c73SDimitry Andric R.reset(new ELFObjectFile<ELFType<support::little, false>>(Obj, EC)); 5597bc6c73SDimitry Andric else if (Ident.second == ELF::ELFDATA2MSB) 5697bc6c73SDimitry Andric R.reset(new ELFObjectFile<ELFType<support::big, false>>(Obj, EC)); 57139f7f9bSDimitry Andric else 5891bc56edSDimitry Andric return object_error::parse_failed; 5997bc6c73SDimitry Andric } else if (Ident.first == ELF::ELFCLASS64) { 6097bc6c73SDimitry Andric if (Ident.second == ELF::ELFDATA2LSB) 6197bc6c73SDimitry Andric R.reset(new ELFObjectFile<ELFType<support::little, true>>(Obj, EC)); 6297bc6c73SDimitry Andric else if (Ident.second == ELF::ELFDATA2MSB) 6397bc6c73SDimitry Andric R.reset(new ELFObjectFile<ELFType<support::big, true>>(Obj, EC)); 64139f7f9bSDimitry Andric else 6591bc56edSDimitry Andric return object_error::parse_failed; 6697bc6c73SDimitry Andric } else { 6791bc56edSDimitry Andric return object_error::parse_failed; 68dff0c46cSDimitry Andric } 69dff0c46cSDimitry Andric 7091bc56edSDimitry Andric if (EC) 7191bc56edSDimitry Andric return EC; 7239d628a0SDimitry Andric return std::move(R); 732754fe60SDimitry Andric } 742754fe60SDimitry Andric 757a7e6055SDimitry Andric SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const { 763ca95b02SDimitry Andric SubtargetFeatures Features; 773ca95b02SDimitry Andric unsigned PlatformFlags; 783ca95b02SDimitry Andric getPlatformFlags(PlatformFlags); 793ca95b02SDimitry Andric 803ca95b02SDimitry Andric switch (PlatformFlags & ELF::EF_MIPS_ARCH) { 813ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_1: 823ca95b02SDimitry Andric break; 833ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_2: 843ca95b02SDimitry Andric Features.AddFeature("mips2"); 853ca95b02SDimitry Andric break; 863ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_3: 873ca95b02SDimitry Andric Features.AddFeature("mips3"); 883ca95b02SDimitry Andric break; 893ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_4: 903ca95b02SDimitry Andric Features.AddFeature("mips4"); 913ca95b02SDimitry Andric break; 923ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_5: 933ca95b02SDimitry Andric Features.AddFeature("mips5"); 943ca95b02SDimitry Andric break; 953ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_32: 963ca95b02SDimitry Andric Features.AddFeature("mips32"); 973ca95b02SDimitry Andric break; 983ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_64: 993ca95b02SDimitry Andric Features.AddFeature("mips64"); 1003ca95b02SDimitry Andric break; 1013ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_32R2: 1023ca95b02SDimitry Andric Features.AddFeature("mips32r2"); 1033ca95b02SDimitry Andric break; 1043ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_64R2: 1053ca95b02SDimitry Andric Features.AddFeature("mips64r2"); 1063ca95b02SDimitry Andric break; 1073ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_32R6: 1083ca95b02SDimitry Andric Features.AddFeature("mips32r6"); 1093ca95b02SDimitry Andric break; 1103ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_64R6: 1113ca95b02SDimitry Andric Features.AddFeature("mips64r6"); 1123ca95b02SDimitry Andric break; 1133ca95b02SDimitry Andric default: 1143ca95b02SDimitry Andric llvm_unreachable("Unknown EF_MIPS_ARCH value"); 1153ca95b02SDimitry Andric } 1163ca95b02SDimitry Andric 1173ca95b02SDimitry Andric switch (PlatformFlags & ELF::EF_MIPS_MACH) { 1183ca95b02SDimitry Andric case ELF::EF_MIPS_MACH_NONE: 1193ca95b02SDimitry Andric // No feature associated with this value. 1203ca95b02SDimitry Andric break; 1213ca95b02SDimitry Andric case ELF::EF_MIPS_MACH_OCTEON: 1223ca95b02SDimitry Andric Features.AddFeature("cnmips"); 1233ca95b02SDimitry Andric break; 1243ca95b02SDimitry Andric default: 1253ca95b02SDimitry Andric llvm_unreachable("Unknown EF_MIPS_ARCH value"); 1263ca95b02SDimitry Andric } 1273ca95b02SDimitry Andric 1283ca95b02SDimitry Andric if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16) 1293ca95b02SDimitry Andric Features.AddFeature("mips16"); 1303ca95b02SDimitry Andric if (PlatformFlags & ELF::EF_MIPS_MICROMIPS) 1313ca95b02SDimitry Andric Features.AddFeature("micromips"); 1323ca95b02SDimitry Andric 1333ca95b02SDimitry Andric return Features; 1343ca95b02SDimitry Andric } 1357a7e6055SDimitry Andric 1367a7e6055SDimitry Andric SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { 1377a7e6055SDimitry Andric SubtargetFeatures Features; 1387a7e6055SDimitry Andric ARMAttributeParser Attributes; 1397a7e6055SDimitry Andric std::error_code EC = getBuildAttributes(Attributes); 1407a7e6055SDimitry Andric if (EC) 1417a7e6055SDimitry Andric return SubtargetFeatures(); 1427a7e6055SDimitry Andric 1437a7e6055SDimitry Andric // both ARMv7-M and R have to support thumb hardware div 1447a7e6055SDimitry Andric bool isV7 = false; 1457a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) 1467a7e6055SDimitry Andric isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch) 1477a7e6055SDimitry Andric == ARMBuildAttrs::v7; 1487a7e6055SDimitry Andric 1497a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) { 1507a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) { 1517a7e6055SDimitry Andric case ARMBuildAttrs::ApplicationProfile: 1527a7e6055SDimitry Andric Features.AddFeature("aclass"); 1537a7e6055SDimitry Andric break; 1547a7e6055SDimitry Andric case ARMBuildAttrs::RealTimeProfile: 1557a7e6055SDimitry Andric Features.AddFeature("rclass"); 1567a7e6055SDimitry Andric if (isV7) 1577a7e6055SDimitry Andric Features.AddFeature("hwdiv"); 1587a7e6055SDimitry Andric break; 1597a7e6055SDimitry Andric case ARMBuildAttrs::MicroControllerProfile: 1607a7e6055SDimitry Andric Features.AddFeature("mclass"); 1617a7e6055SDimitry Andric if (isV7) 1627a7e6055SDimitry Andric Features.AddFeature("hwdiv"); 1637a7e6055SDimitry Andric break; 1647a7e6055SDimitry Andric } 1657a7e6055SDimitry Andric } 1667a7e6055SDimitry Andric 1677a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) { 1687a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) { 1697a7e6055SDimitry Andric default: 1707a7e6055SDimitry Andric break; 1717a7e6055SDimitry Andric case ARMBuildAttrs::Not_Allowed: 1727a7e6055SDimitry Andric Features.AddFeature("thumb", false); 1737a7e6055SDimitry Andric Features.AddFeature("thumb2", false); 1747a7e6055SDimitry Andric break; 1757a7e6055SDimitry Andric case ARMBuildAttrs::AllowThumb32: 1767a7e6055SDimitry Andric Features.AddFeature("thumb2"); 1777a7e6055SDimitry Andric break; 1787a7e6055SDimitry Andric } 1797a7e6055SDimitry Andric } 1807a7e6055SDimitry Andric 1817a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) { 1827a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) { 1837a7e6055SDimitry Andric default: 1847a7e6055SDimitry Andric break; 1857a7e6055SDimitry Andric case ARMBuildAttrs::Not_Allowed: 1867a7e6055SDimitry Andric Features.AddFeature("vfp2", false); 1877a7e6055SDimitry Andric Features.AddFeature("vfp3", false); 1887a7e6055SDimitry Andric Features.AddFeature("vfp4", false); 1897a7e6055SDimitry Andric break; 1907a7e6055SDimitry Andric case ARMBuildAttrs::AllowFPv2: 1917a7e6055SDimitry Andric Features.AddFeature("vfp2"); 1927a7e6055SDimitry Andric break; 1937a7e6055SDimitry Andric case ARMBuildAttrs::AllowFPv3A: 1947a7e6055SDimitry Andric case ARMBuildAttrs::AllowFPv3B: 1957a7e6055SDimitry Andric Features.AddFeature("vfp3"); 1967a7e6055SDimitry Andric break; 1977a7e6055SDimitry Andric case ARMBuildAttrs::AllowFPv4A: 1987a7e6055SDimitry Andric case ARMBuildAttrs::AllowFPv4B: 1997a7e6055SDimitry Andric Features.AddFeature("vfp4"); 2007a7e6055SDimitry Andric break; 2017a7e6055SDimitry Andric } 2027a7e6055SDimitry Andric } 2037a7e6055SDimitry Andric 2047a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) { 2057a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) { 2067a7e6055SDimitry Andric default: 2077a7e6055SDimitry Andric break; 2087a7e6055SDimitry Andric case ARMBuildAttrs::Not_Allowed: 2097a7e6055SDimitry Andric Features.AddFeature("neon", false); 2107a7e6055SDimitry Andric Features.AddFeature("fp16", false); 2117a7e6055SDimitry Andric break; 2127a7e6055SDimitry Andric case ARMBuildAttrs::AllowNeon: 2137a7e6055SDimitry Andric Features.AddFeature("neon"); 2147a7e6055SDimitry Andric break; 2157a7e6055SDimitry Andric case ARMBuildAttrs::AllowNeon2: 2167a7e6055SDimitry Andric Features.AddFeature("neon"); 2177a7e6055SDimitry Andric Features.AddFeature("fp16"); 2187a7e6055SDimitry Andric break; 2197a7e6055SDimitry Andric } 2207a7e6055SDimitry Andric } 2217a7e6055SDimitry Andric 2227a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) { 2237a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) { 2247a7e6055SDimitry Andric default: 2257a7e6055SDimitry Andric break; 2267a7e6055SDimitry Andric case ARMBuildAttrs::DisallowDIV: 2277a7e6055SDimitry Andric Features.AddFeature("hwdiv", false); 2287a7e6055SDimitry Andric Features.AddFeature("hwdiv-arm", false); 2297a7e6055SDimitry Andric break; 2307a7e6055SDimitry Andric case ARMBuildAttrs::AllowDIVExt: 2317a7e6055SDimitry Andric Features.AddFeature("hwdiv"); 2327a7e6055SDimitry Andric Features.AddFeature("hwdiv-arm"); 2337a7e6055SDimitry Andric break; 2347a7e6055SDimitry Andric } 2357a7e6055SDimitry Andric } 2367a7e6055SDimitry Andric 2377a7e6055SDimitry Andric return Features; 2387a7e6055SDimitry Andric } 2397a7e6055SDimitry Andric 2407a7e6055SDimitry Andric SubtargetFeatures ELFObjectFileBase::getFeatures() const { 2417a7e6055SDimitry Andric switch (getEMachine()) { 2427a7e6055SDimitry Andric case ELF::EM_MIPS: 2437a7e6055SDimitry Andric return getMIPSFeatures(); 2447a7e6055SDimitry Andric case ELF::EM_ARM: 2457a7e6055SDimitry Andric return getARMFeatures(); 2463ca95b02SDimitry Andric default: 2473ca95b02SDimitry Andric return SubtargetFeatures(); 2483ca95b02SDimitry Andric } 2493ca95b02SDimitry Andric } 2503ca95b02SDimitry Andric 2517a7e6055SDimitry Andric // FIXME Encode from a tablegen description or target parser. 2527a7e6055SDimitry Andric void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { 2537a7e6055SDimitry Andric if (TheTriple.getSubArch() != Triple::NoSubArch) 2547a7e6055SDimitry Andric return; 2557a7e6055SDimitry Andric 2567a7e6055SDimitry Andric ARMAttributeParser Attributes; 2577a7e6055SDimitry Andric std::error_code EC = getBuildAttributes(Attributes); 2587a7e6055SDimitry Andric if (EC) 2597a7e6055SDimitry Andric return; 2607a7e6055SDimitry Andric 2617a7e6055SDimitry Andric std::string Triple; 2627a7e6055SDimitry Andric // Default to ARM, but use the triple if it's been set. 2637a7e6055SDimitry Andric if (TheTriple.getArch() == Triple::thumb || 2647a7e6055SDimitry Andric TheTriple.getArch() == Triple::thumbeb) 2657a7e6055SDimitry Andric Triple = "thumb"; 2667a7e6055SDimitry Andric else 2677a7e6055SDimitry Andric Triple = "arm"; 2687a7e6055SDimitry Andric 2697a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) { 2707a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) { 2717a7e6055SDimitry Andric case ARMBuildAttrs::v4: 2727a7e6055SDimitry Andric Triple += "v4"; 2737a7e6055SDimitry Andric break; 2747a7e6055SDimitry Andric case ARMBuildAttrs::v4T: 2757a7e6055SDimitry Andric Triple += "v4t"; 2767a7e6055SDimitry Andric break; 2777a7e6055SDimitry Andric case ARMBuildAttrs::v5T: 2787a7e6055SDimitry Andric Triple += "v5t"; 2797a7e6055SDimitry Andric break; 2807a7e6055SDimitry Andric case ARMBuildAttrs::v5TE: 2817a7e6055SDimitry Andric Triple += "v5te"; 2827a7e6055SDimitry Andric break; 2837a7e6055SDimitry Andric case ARMBuildAttrs::v5TEJ: 2847a7e6055SDimitry Andric Triple += "v5tej"; 2857a7e6055SDimitry Andric break; 2867a7e6055SDimitry Andric case ARMBuildAttrs::v6: 2877a7e6055SDimitry Andric Triple += "v6"; 2887a7e6055SDimitry Andric break; 2897a7e6055SDimitry Andric case ARMBuildAttrs::v6KZ: 2907a7e6055SDimitry Andric Triple += "v6kz"; 2917a7e6055SDimitry Andric break; 2927a7e6055SDimitry Andric case ARMBuildAttrs::v6T2: 2937a7e6055SDimitry Andric Triple += "v6t2"; 2947a7e6055SDimitry Andric break; 2957a7e6055SDimitry Andric case ARMBuildAttrs::v6K: 2967a7e6055SDimitry Andric Triple += "v6k"; 2977a7e6055SDimitry Andric break; 2987a7e6055SDimitry Andric case ARMBuildAttrs::v7: 2997a7e6055SDimitry Andric Triple += "v7"; 3007a7e6055SDimitry Andric break; 3017a7e6055SDimitry Andric case ARMBuildAttrs::v6_M: 3027a7e6055SDimitry Andric Triple += "v6m"; 3037a7e6055SDimitry Andric break; 3047a7e6055SDimitry Andric case ARMBuildAttrs::v6S_M: 3057a7e6055SDimitry Andric Triple += "v6sm"; 3067a7e6055SDimitry Andric break; 3077a7e6055SDimitry Andric case ARMBuildAttrs::v7E_M: 3087a7e6055SDimitry Andric Triple += "v7em"; 3097a7e6055SDimitry Andric break; 3107a7e6055SDimitry Andric } 3117a7e6055SDimitry Andric } 3127a7e6055SDimitry Andric if (!isLittleEndian()) 3137a7e6055SDimitry Andric Triple += "eb"; 3147a7e6055SDimitry Andric 3157a7e6055SDimitry Andric TheTriple.setArchName(Triple); 3167a7e6055SDimitry Andric } 317