LCOV - code coverage report
Current view: top level - lib/Object - ELFObjectFile.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 92 125 73.6 %
Date: 2018-06-17 00:07:59 Functions: 10 11 90.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- ELFObjectFile.cpp - ELF object file implementation -----------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // Part of the ELFObjectFile class implementation.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #include "llvm/Object/ELFObjectFile.h"
      15             : #include "llvm/ADT/Triple.h"
      16             : #include "llvm/BinaryFormat/ELF.h"
      17             : #include "llvm/MC/SubtargetFeature.h"
      18             : #include "llvm/Object/ELF.h"
      19             : #include "llvm/Object/ELFTypes.h"
      20             : #include "llvm/Object/Error.h"
      21             : #include "llvm/Support/ARMAttributeParser.h"
      22             : #include "llvm/Support/ARMBuildAttributes.h"
      23             : #include "llvm/Support/Endian.h"
      24             : #include "llvm/Support/ErrorHandling.h"
      25             : #include "llvm/Support/MathExtras.h"
      26             : #include <algorithm>
      27             : #include <cstddef>
      28             : #include <cstdint>
      29             : #include <memory>
      30             : #include <string>
      31             : #include <system_error>
      32             : #include <utility>
      33             : 
      34             : using namespace llvm;
      35             : using namespace object;
      36             : 
      37       17103 : ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
      38       17103 :     : ObjectFile(Type, Source) {}
      39             : 
      40             : template <class ELFT>
      41             : static Expected<std::unique_ptr<ELFObjectFile<ELFT>>>
      42        5556 : createPtr(MemoryBufferRef Object) {
      43       11112 :   auto Ret = ELFObjectFile<ELFT>::create(Object);
      44        5556 :   if (Error E = Ret.takeError())
      45             :     return std::move(E);
      46             :   return make_unique<ELFObjectFile<ELFT>>(std::move(*Ret));
      47             : }
      48             : 
      49             : Expected<std::unique_ptr<ObjectFile>>
      50        5559 : ObjectFile::createELFObjectFile(MemoryBufferRef Obj) {
      51             :   std::pair<unsigned char, unsigned char> Ident =
      52             :       getElfArchType(Obj.getBuffer());
      53             :   std::size_t MaxAlignment =
      54       11118 :       1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart()));
      55             : 
      56        5559 :   if (MaxAlignment < 2)
      57             :     return createError("Insufficient alignment");
      58             : 
      59        5558 :   if (Ident.first == ELF::ELFCLASS32) {
      60        1349 :     if (Ident.second == ELF::ELFDATA2LSB)
      61        2148 :       return createPtr<ELF32LE>(Obj);
      62         275 :     else if (Ident.second == ELF::ELFDATA2MSB)
      63         550 :       return createPtr<ELF32BE>(Obj);
      64             :     else
      65             :       return createError("Invalid ELF data");
      66        4209 :   } else if (Ident.first == ELF::ELFCLASS64) {
      67        4208 :     if (Ident.second == ELF::ELFDATA2LSB)
      68        7998 :       return createPtr<ELF64LE>(Obj);
      69         209 :     else if (Ident.second == ELF::ELFDATA2MSB)
      70         416 :       return createPtr<ELF64BE>(Obj);
      71             :     else
      72             :       return createError("Invalid ELF data");
      73             :   }
      74             :   return createError("Invalid ELF class");
      75             : }
      76             : 
      77         114 : SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const {
      78         114 :   SubtargetFeatures Features;
      79         114 :   unsigned PlatformFlags = getPlatformFlags();
      80             : 
      81         114 :   switch (PlatformFlags & ELF::EF_MIPS_ARCH) {
      82             :   case ELF::EF_MIPS_ARCH_1:
      83             :     break;
      84             :   case ELF::EF_MIPS_ARCH_2:
      85           0 :     Features.AddFeature("mips2");
      86           0 :     break;
      87             :   case ELF::EF_MIPS_ARCH_3:
      88           0 :     Features.AddFeature("mips3");
      89           0 :     break;
      90             :   case ELF::EF_MIPS_ARCH_4:
      91           0 :     Features.AddFeature("mips4");
      92           0 :     break;
      93             :   case ELF::EF_MIPS_ARCH_5:
      94           0 :     Features.AddFeature("mips5");
      95           0 :     break;
      96             :   case ELF::EF_MIPS_ARCH_32:
      97          55 :     Features.AddFeature("mips32");
      98          55 :     break;
      99             :   case ELF::EF_MIPS_ARCH_64:
     100          22 :     Features.AddFeature("mips64");
     101          22 :     break;
     102             :   case ELF::EF_MIPS_ARCH_32R2:
     103          10 :     Features.AddFeature("mips32r2");
     104          10 :     break;
     105             :   case ELF::EF_MIPS_ARCH_64R2:
     106           9 :     Features.AddFeature("mips64r2");
     107           9 :     break;
     108             :   case ELF::EF_MIPS_ARCH_32R6:
     109          14 :     Features.AddFeature("mips32r6");
     110          14 :     break;
     111             :   case ELF::EF_MIPS_ARCH_64R6:
     112           3 :     Features.AddFeature("mips64r6");
     113           3 :     break;
     114           0 :   default:
     115           0 :     llvm_unreachable("Unknown EF_MIPS_ARCH value");
     116             :   }
     117             : 
     118         114 :   switch (PlatformFlags & ELF::EF_MIPS_MACH) {
     119             :   case ELF::EF_MIPS_MACH_NONE:
     120             :     // No feature associated with this value.
     121             :     break;
     122             :   case ELF::EF_MIPS_MACH_OCTEON:
     123           0 :     Features.AddFeature("cnmips");
     124           0 :     break;
     125           0 :   default:
     126           0 :     llvm_unreachable("Unknown EF_MIPS_ARCH value");
     127             :   }
     128             : 
     129         114 :   if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16)
     130           0 :     Features.AddFeature("mips16");
     131         114 :   if (PlatformFlags & ELF::EF_MIPS_MICROMIPS)
     132          25 :     Features.AddFeature("micromips");
     133             : 
     134         114 :   return Features;
     135             : }
     136             : 
     137         172 : SubtargetFeatures ELFObjectFileBase::getARMFeatures() const {
     138         172 :   SubtargetFeatures Features;
     139             :   ARMAttributeParser Attributes;
     140         172 :   std::error_code EC = getBuildAttributes(Attributes);
     141         172 :   if (EC)
     142           0 :     return SubtargetFeatures();
     143             : 
     144             :   // both ARMv7-M and R have to support thumb hardware div
     145             :   bool isV7 = false;
     146             :   if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch))
     147          35 :     isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)
     148             :       == ARMBuildAttrs::v7;
     149             : 
     150             :   if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) {
     151          24 :     switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) {
     152             :     case ARMBuildAttrs::ApplicationProfile:
     153          19 :       Features.AddFeature("aclass");
     154          19 :       break;
     155             :     case ARMBuildAttrs::RealTimeProfile:
     156           2 :       Features.AddFeature("rclass");
     157           2 :       if (isV7)
     158           2 :         Features.AddFeature("hwdiv");
     159             :       break;
     160             :     case ARMBuildAttrs::MicroControllerProfile:
     161           3 :       Features.AddFeature("mclass");
     162           3 :       if (isV7)
     163           2 :         Features.AddFeature("hwdiv");
     164             :       break;
     165             :     }
     166             :   }
     167             : 
     168             :   if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) {
     169          30 :     switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) {
     170             :     default:
     171             :       break;
     172             :     case ARMBuildAttrs::Not_Allowed:
     173           0 :       Features.AddFeature("thumb", false);
     174           0 :       Features.AddFeature("thumb2", false);
     175           0 :       break;
     176             :     case ARMBuildAttrs::AllowThumb32:
     177          21 :       Features.AddFeature("thumb2");
     178          21 :       break;
     179             :     }
     180             :   }
     181             : 
     182             :   if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) {
     183          24 :     switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) {
     184             :     default:
     185             :       break;
     186             :     case ARMBuildAttrs::Not_Allowed:
     187           3 :       Features.AddFeature("vfp2", false);
     188           3 :       Features.AddFeature("vfp3", false);
     189           3 :       Features.AddFeature("vfp4", false);
     190           3 :       break;
     191             :     case ARMBuildAttrs::AllowFPv2:
     192           1 :       Features.AddFeature("vfp2");
     193           1 :       break;
     194             :     case ARMBuildAttrs::AllowFPv3A:
     195             :     case ARMBuildAttrs::AllowFPv3B:
     196          16 :       Features.AddFeature("vfp3");
     197          16 :       break;
     198             :     case ARMBuildAttrs::AllowFPv4A:
     199             :     case ARMBuildAttrs::AllowFPv4B:
     200           3 :       Features.AddFeature("vfp4");
     201           3 :       break;
     202             :     }
     203             :   }
     204             : 
     205             :   if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) {
     206          17 :     switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) {
     207             :     default:
     208             :       break;
     209             :     case ARMBuildAttrs::Not_Allowed:
     210           0 :       Features.AddFeature("neon", false);
     211           0 :       Features.AddFeature("fp16", false);
     212           0 :       break;
     213             :     case ARMBuildAttrs::AllowNeon:
     214          14 :       Features.AddFeature("neon");
     215          14 :       break;
     216             :     case ARMBuildAttrs::AllowNeon2:
     217           3 :       Features.AddFeature("neon");
     218           3 :       Features.AddFeature("fp16");
     219           3 :       break;
     220             :     }
     221             :   }
     222             : 
     223             :   if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) {
     224           3 :     switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) {
     225             :     default:
     226             :       break;
     227             :     case ARMBuildAttrs::DisallowDIV:
     228           0 :       Features.AddFeature("hwdiv", false);
     229           0 :       Features.AddFeature("hwdiv-arm", false);
     230           0 :       break;
     231             :     case ARMBuildAttrs::AllowDIVExt:
     232           3 :       Features.AddFeature("hwdiv");
     233           3 :       Features.AddFeature("hwdiv-arm");
     234           3 :       break;
     235             :     }
     236             :   }
     237             : 
     238             :   return Features;
     239             : }
     240             : 
     241           0 : SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const {
     242           0 :   SubtargetFeatures Features;
     243           0 :   unsigned PlatformFlags = getPlatformFlags();
     244             : 
     245           0 :   if (PlatformFlags & ELF::EF_RISCV_RVC) {
     246           0 :     Features.AddFeature("c");
     247             :   }
     248             : 
     249           0 :   return Features;
     250             : }
     251             : 
     252         927 : SubtargetFeatures ELFObjectFileBase::getFeatures() const {
     253         927 :   switch (getEMachine()) {
     254         114 :   case ELF::EM_MIPS:
     255         114 :     return getMIPSFeatures();
     256         172 :   case ELF::EM_ARM:
     257         172 :     return getARMFeatures();
     258           0 :   case ELF::EM_RISCV:
     259           0 :     return getRISCVFeatures();
     260             :   default:
     261         641 :     return SubtargetFeatures();
     262             :   }
     263             : }
     264             : 
     265             : // FIXME Encode from a tablegen description or target parser.
     266         172 : void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
     267         172 :   if (TheTriple.getSubArch() != Triple::NoSubArch)
     268         142 :     return;
     269             : 
     270             :   ARMAttributeParser Attributes;
     271          30 :   std::error_code EC = getBuildAttributes(Attributes);
     272          30 :   if (EC)
     273             :     return;
     274             : 
     275             :   std::string Triple;
     276             :   // Default to ARM, but use the triple if it's been set.
     277             :   if (TheTriple.isThumb())
     278             :     Triple = "thumb";
     279             :   else
     280             :     Triple = "arm";
     281             : 
     282             :   if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
     283          14 :     switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
     284             :     case ARMBuildAttrs::v4:
     285             :       Triple += "v4";
     286             :       break;
     287             :     case ARMBuildAttrs::v4T:
     288             :       Triple += "v4t";
     289             :       break;
     290             :     case ARMBuildAttrs::v5T:
     291             :       Triple += "v5t";
     292             :       break;
     293             :     case ARMBuildAttrs::v5TE:
     294             :       Triple += "v5te";
     295             :       break;
     296             :     case ARMBuildAttrs::v5TEJ:
     297             :       Triple += "v5tej";
     298             :       break;
     299             :     case ARMBuildAttrs::v6:
     300             :       Triple += "v6";
     301             :       break;
     302             :     case ARMBuildAttrs::v6KZ:
     303             :       Triple += "v6kz";
     304             :       break;
     305             :     case ARMBuildAttrs::v6T2:
     306             :       Triple += "v6t2";
     307             :       break;
     308             :     case ARMBuildAttrs::v6K:
     309             :       Triple += "v6k";
     310             :       break;
     311             :     case ARMBuildAttrs::v7:
     312             :       Triple += "v7";
     313             :       break;
     314             :     case ARMBuildAttrs::v6_M:
     315             :       Triple += "v6m";
     316             :       break;
     317             :     case ARMBuildAttrs::v6S_M:
     318             :       Triple += "v6sm";
     319             :       break;
     320             :     case ARMBuildAttrs::v7E_M:
     321             :       Triple += "v7em";
     322             :       break;
     323             :     }
     324             :   }
     325          30 :   if (!isLittleEndian())
     326             :     Triple += "eb";
     327             : 
     328          30 :   TheTriple.setArchName(Triple);
     329             : }

Generated by: LCOV version 1.13