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