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 402cab237bSDimitry Andric template <class ELFT> 412cab237bSDimitry Andric static Expected<std::unique_ptr<ELFObjectFile<ELFT>>> 422cab237bSDimitry Andric createPtr(MemoryBufferRef Object) { 432cab237bSDimitry Andric auto Ret = ELFObjectFile<ELFT>::create(Object); 442cab237bSDimitry Andric if (Error E = Ret.takeError()) 452cab237bSDimitry Andric return std::move(E); 462cab237bSDimitry Andric return make_unique<ELFObjectFile<ELFT>>(std::move(*Ret)); 472cab237bSDimitry Andric } 482cab237bSDimitry Andric 492cab237bSDimitry Andric Expected<std::unique_ptr<ObjectFile>> 5039d628a0SDimitry Andric ObjectFile::createELFObjectFile(MemoryBufferRef Obj) { 5191bc56edSDimitry Andric std::pair<unsigned char, unsigned char> Ident = 5239d628a0SDimitry Andric getElfArchType(Obj.getBuffer()); 53139f7f9bSDimitry Andric std::size_t MaxAlignment = 5439d628a0SDimitry Andric 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart())); 55139f7f9bSDimitry Andric 5697bc6c73SDimitry Andric if (MaxAlignment < 2) 572cab237bSDimitry Andric return createError("Insufficient alignment"); 5897bc6c73SDimitry Andric 5997bc6c73SDimitry Andric if (Ident.first == ELF::ELFCLASS32) { 6097bc6c73SDimitry Andric if (Ident.second == ELF::ELFDATA2LSB) 612cab237bSDimitry Andric return createPtr<ELF32LE>(Obj); 6297bc6c73SDimitry Andric else if (Ident.second == ELF::ELFDATA2MSB) 632cab237bSDimitry Andric return createPtr<ELF32BE>(Obj); 64139f7f9bSDimitry Andric else 652cab237bSDimitry Andric return createError("Invalid ELF data"); 6697bc6c73SDimitry Andric } else if (Ident.first == ELF::ELFCLASS64) { 6797bc6c73SDimitry Andric if (Ident.second == ELF::ELFDATA2LSB) 682cab237bSDimitry Andric return createPtr<ELF64LE>(Obj); 6997bc6c73SDimitry Andric else if (Ident.second == ELF::ELFDATA2MSB) 702cab237bSDimitry Andric return createPtr<ELF64BE>(Obj); 71139f7f9bSDimitry Andric else 722cab237bSDimitry Andric return createError("Invalid ELF data"); 73dff0c46cSDimitry Andric } 742cab237bSDimitry Andric return createError("Invalid ELF class"); 752754fe60SDimitry Andric } 762754fe60SDimitry Andric 777a7e6055SDimitry Andric SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const { 783ca95b02SDimitry Andric SubtargetFeatures Features; 793ca95b02SDimitry Andric unsigned PlatformFlags; 803ca95b02SDimitry Andric getPlatformFlags(PlatformFlags); 813ca95b02SDimitry Andric 823ca95b02SDimitry Andric switch (PlatformFlags & ELF::EF_MIPS_ARCH) { 833ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_1: 843ca95b02SDimitry Andric break; 853ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_2: 863ca95b02SDimitry Andric Features.AddFeature("mips2"); 873ca95b02SDimitry Andric break; 883ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_3: 893ca95b02SDimitry Andric Features.AddFeature("mips3"); 903ca95b02SDimitry Andric break; 913ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_4: 923ca95b02SDimitry Andric Features.AddFeature("mips4"); 933ca95b02SDimitry Andric break; 943ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_5: 953ca95b02SDimitry Andric Features.AddFeature("mips5"); 963ca95b02SDimitry Andric break; 973ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_32: 983ca95b02SDimitry Andric Features.AddFeature("mips32"); 993ca95b02SDimitry Andric break; 1003ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_64: 1013ca95b02SDimitry Andric Features.AddFeature("mips64"); 1023ca95b02SDimitry Andric break; 1033ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_32R2: 1043ca95b02SDimitry Andric Features.AddFeature("mips32r2"); 1053ca95b02SDimitry Andric break; 1063ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_64R2: 1073ca95b02SDimitry Andric Features.AddFeature("mips64r2"); 1083ca95b02SDimitry Andric break; 1093ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_32R6: 1103ca95b02SDimitry Andric Features.AddFeature("mips32r6"); 1113ca95b02SDimitry Andric break; 1123ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_64R6: 1133ca95b02SDimitry Andric Features.AddFeature("mips64r6"); 1143ca95b02SDimitry Andric break; 1153ca95b02SDimitry Andric default: 1163ca95b02SDimitry Andric llvm_unreachable("Unknown EF_MIPS_ARCH value"); 1173ca95b02SDimitry Andric } 1183ca95b02SDimitry Andric 1193ca95b02SDimitry Andric switch (PlatformFlags & ELF::EF_MIPS_MACH) { 1203ca95b02SDimitry Andric case ELF::EF_MIPS_MACH_NONE: 1213ca95b02SDimitry Andric // No feature associated with this value. 1223ca95b02SDimitry Andric break; 1233ca95b02SDimitry Andric case ELF::EF_MIPS_MACH_OCTEON: 1243ca95b02SDimitry Andric Features.AddFeature("cnmips"); 1253ca95b02SDimitry Andric break; 1263ca95b02SDimitry Andric default: 1273ca95b02SDimitry Andric llvm_unreachable("Unknown EF_MIPS_ARCH value"); 1283ca95b02SDimitry Andric } 1293ca95b02SDimitry Andric 1303ca95b02SDimitry Andric if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16) 1313ca95b02SDimitry Andric Features.AddFeature("mips16"); 1323ca95b02SDimitry Andric if (PlatformFlags & ELF::EF_MIPS_MICROMIPS) 1333ca95b02SDimitry Andric Features.AddFeature("micromips"); 1343ca95b02SDimitry Andric 1353ca95b02SDimitry Andric return Features; 1363ca95b02SDimitry Andric } 1377a7e6055SDimitry Andric 1387a7e6055SDimitry Andric SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { 1397a7e6055SDimitry Andric SubtargetFeatures Features; 1407a7e6055SDimitry Andric ARMAttributeParser Attributes; 1417a7e6055SDimitry Andric std::error_code EC = getBuildAttributes(Attributes); 1427a7e6055SDimitry Andric if (EC) 1437a7e6055SDimitry Andric return SubtargetFeatures(); 1447a7e6055SDimitry Andric 1457a7e6055SDimitry Andric // both ARMv7-M and R have to support thumb hardware div 1467a7e6055SDimitry Andric bool isV7 = false; 1477a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) 1487a7e6055SDimitry Andric isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch) 1497a7e6055SDimitry Andric == ARMBuildAttrs::v7; 1507a7e6055SDimitry Andric 1517a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) { 1527a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) { 1537a7e6055SDimitry Andric case ARMBuildAttrs::ApplicationProfile: 1547a7e6055SDimitry Andric Features.AddFeature("aclass"); 1557a7e6055SDimitry Andric break; 1567a7e6055SDimitry Andric case ARMBuildAttrs::RealTimeProfile: 1577a7e6055SDimitry Andric Features.AddFeature("rclass"); 1587a7e6055SDimitry Andric if (isV7) 1597a7e6055SDimitry Andric Features.AddFeature("hwdiv"); 1607a7e6055SDimitry Andric break; 1617a7e6055SDimitry Andric case ARMBuildAttrs::MicroControllerProfile: 1627a7e6055SDimitry Andric Features.AddFeature("mclass"); 1637a7e6055SDimitry Andric if (isV7) 1647a7e6055SDimitry Andric Features.AddFeature("hwdiv"); 1657a7e6055SDimitry Andric break; 1667a7e6055SDimitry Andric } 1677a7e6055SDimitry Andric } 1687a7e6055SDimitry Andric 1697a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) { 1707a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) { 1717a7e6055SDimitry Andric default: 1727a7e6055SDimitry Andric break; 1737a7e6055SDimitry Andric case ARMBuildAttrs::Not_Allowed: 1747a7e6055SDimitry Andric Features.AddFeature("thumb", false); 1757a7e6055SDimitry Andric Features.AddFeature("thumb2", false); 1767a7e6055SDimitry Andric break; 1777a7e6055SDimitry Andric case ARMBuildAttrs::AllowThumb32: 1787a7e6055SDimitry Andric Features.AddFeature("thumb2"); 1797a7e6055SDimitry Andric break; 1807a7e6055SDimitry Andric } 1817a7e6055SDimitry Andric } 1827a7e6055SDimitry Andric 1837a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) { 1847a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) { 1857a7e6055SDimitry Andric default: 1867a7e6055SDimitry Andric break; 1877a7e6055SDimitry Andric case ARMBuildAttrs::Not_Allowed: 1887a7e6055SDimitry Andric Features.AddFeature("vfp2", false); 1897a7e6055SDimitry Andric Features.AddFeature("vfp3", false); 1907a7e6055SDimitry Andric Features.AddFeature("vfp4", false); 1917a7e6055SDimitry Andric break; 1927a7e6055SDimitry Andric case ARMBuildAttrs::AllowFPv2: 1937a7e6055SDimitry Andric Features.AddFeature("vfp2"); 1947a7e6055SDimitry Andric break; 1957a7e6055SDimitry Andric case ARMBuildAttrs::AllowFPv3A: 1967a7e6055SDimitry Andric case ARMBuildAttrs::AllowFPv3B: 1977a7e6055SDimitry Andric Features.AddFeature("vfp3"); 1987a7e6055SDimitry Andric break; 1997a7e6055SDimitry Andric case ARMBuildAttrs::AllowFPv4A: 2007a7e6055SDimitry Andric case ARMBuildAttrs::AllowFPv4B: 2017a7e6055SDimitry Andric Features.AddFeature("vfp4"); 2027a7e6055SDimitry Andric break; 2037a7e6055SDimitry Andric } 2047a7e6055SDimitry Andric } 2057a7e6055SDimitry Andric 2067a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) { 2077a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) { 2087a7e6055SDimitry Andric default: 2097a7e6055SDimitry Andric break; 2107a7e6055SDimitry Andric case ARMBuildAttrs::Not_Allowed: 2117a7e6055SDimitry Andric Features.AddFeature("neon", false); 2127a7e6055SDimitry Andric Features.AddFeature("fp16", false); 2137a7e6055SDimitry Andric break; 2147a7e6055SDimitry Andric case ARMBuildAttrs::AllowNeon: 2157a7e6055SDimitry Andric Features.AddFeature("neon"); 2167a7e6055SDimitry Andric break; 2177a7e6055SDimitry Andric case ARMBuildAttrs::AllowNeon2: 2187a7e6055SDimitry Andric Features.AddFeature("neon"); 2197a7e6055SDimitry Andric Features.AddFeature("fp16"); 2207a7e6055SDimitry Andric break; 2217a7e6055SDimitry Andric } 2227a7e6055SDimitry Andric } 2237a7e6055SDimitry Andric 2247a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) { 2257a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) { 2267a7e6055SDimitry Andric default: 2277a7e6055SDimitry Andric break; 2287a7e6055SDimitry Andric case ARMBuildAttrs::DisallowDIV: 2297a7e6055SDimitry Andric Features.AddFeature("hwdiv", false); 2307a7e6055SDimitry Andric Features.AddFeature("hwdiv-arm", false); 2317a7e6055SDimitry Andric break; 2327a7e6055SDimitry Andric case ARMBuildAttrs::AllowDIVExt: 2337a7e6055SDimitry Andric Features.AddFeature("hwdiv"); 2347a7e6055SDimitry Andric Features.AddFeature("hwdiv-arm"); 2357a7e6055SDimitry Andric break; 2367a7e6055SDimitry Andric } 2377a7e6055SDimitry Andric } 2387a7e6055SDimitry Andric 2397a7e6055SDimitry Andric return Features; 2407a7e6055SDimitry Andric } 2417a7e6055SDimitry Andric 2427a7e6055SDimitry Andric SubtargetFeatures ELFObjectFileBase::getFeatures() const { 2437a7e6055SDimitry Andric switch (getEMachine()) { 2447a7e6055SDimitry Andric case ELF::EM_MIPS: 2457a7e6055SDimitry Andric return getMIPSFeatures(); 2467a7e6055SDimitry Andric case ELF::EM_ARM: 2477a7e6055SDimitry Andric return getARMFeatures(); 2483ca95b02SDimitry Andric default: 2493ca95b02SDimitry Andric return SubtargetFeatures(); 2503ca95b02SDimitry Andric } 2513ca95b02SDimitry Andric } 2523ca95b02SDimitry Andric 2537a7e6055SDimitry Andric // FIXME Encode from a tablegen description or target parser. 2547a7e6055SDimitry Andric void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { 2557a7e6055SDimitry Andric if (TheTriple.getSubArch() != Triple::NoSubArch) 2567a7e6055SDimitry Andric return; 2577a7e6055SDimitry Andric 2587a7e6055SDimitry Andric ARMAttributeParser Attributes; 2597a7e6055SDimitry Andric std::error_code EC = getBuildAttributes(Attributes); 2607a7e6055SDimitry Andric if (EC) 2617a7e6055SDimitry Andric return; 2627a7e6055SDimitry Andric 2637a7e6055SDimitry Andric std::string Triple; 2647a7e6055SDimitry Andric // Default to ARM, but use the triple if it's been set. 2652cab237bSDimitry Andric if (TheTriple.isThumb()) 2667a7e6055SDimitry Andric Triple = "thumb"; 2677a7e6055SDimitry Andric else 2687a7e6055SDimitry Andric Triple = "arm"; 2697a7e6055SDimitry Andric 2707a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) { 2717a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) { 2727a7e6055SDimitry Andric case ARMBuildAttrs::v4: 2737a7e6055SDimitry Andric Triple += "v4"; 2747a7e6055SDimitry Andric break; 2757a7e6055SDimitry Andric case ARMBuildAttrs::v4T: 2767a7e6055SDimitry Andric Triple += "v4t"; 2777a7e6055SDimitry Andric break; 2787a7e6055SDimitry Andric case ARMBuildAttrs::v5T: 2797a7e6055SDimitry Andric Triple += "v5t"; 2807a7e6055SDimitry Andric break; 2817a7e6055SDimitry Andric case ARMBuildAttrs::v5TE: 2827a7e6055SDimitry Andric Triple += "v5te"; 2837a7e6055SDimitry Andric break; 2847a7e6055SDimitry Andric case ARMBuildAttrs::v5TEJ: 2857a7e6055SDimitry Andric Triple += "v5tej"; 2867a7e6055SDimitry Andric break; 2877a7e6055SDimitry Andric case ARMBuildAttrs::v6: 2887a7e6055SDimitry Andric Triple += "v6"; 2897a7e6055SDimitry Andric break; 2907a7e6055SDimitry Andric case ARMBuildAttrs::v6KZ: 2917a7e6055SDimitry Andric Triple += "v6kz"; 2927a7e6055SDimitry Andric break; 2937a7e6055SDimitry Andric case ARMBuildAttrs::v6T2: 2947a7e6055SDimitry Andric Triple += "v6t2"; 2957a7e6055SDimitry Andric break; 2967a7e6055SDimitry Andric case ARMBuildAttrs::v6K: 2977a7e6055SDimitry Andric Triple += "v6k"; 2987a7e6055SDimitry Andric break; 2997a7e6055SDimitry Andric case ARMBuildAttrs::v7: 3007a7e6055SDimitry Andric Triple += "v7"; 3017a7e6055SDimitry Andric break; 3027a7e6055SDimitry Andric case ARMBuildAttrs::v6_M: 3037a7e6055SDimitry Andric Triple += "v6m"; 3047a7e6055SDimitry Andric break; 3057a7e6055SDimitry Andric case ARMBuildAttrs::v6S_M: 3067a7e6055SDimitry Andric Triple += "v6sm"; 3077a7e6055SDimitry Andric break; 3087a7e6055SDimitry Andric case ARMBuildAttrs::v7E_M: 3097a7e6055SDimitry Andric Triple += "v7em"; 3107a7e6055SDimitry Andric break; 3117a7e6055SDimitry Andric } 3127a7e6055SDimitry Andric } 3137a7e6055SDimitry Andric if (!isLittleEndian()) 3147a7e6055SDimitry Andric Triple += "eb"; 3157a7e6055SDimitry Andric 3167a7e6055SDimitry Andric TheTriple.setArchName(Triple); 3177a7e6055SDimitry Andric } 318