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