LCOV - code coverage report
Current view: top level - lib/Object - ELFObjectFile.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 137 172 79.7 %
Date: 2018-10-20 13:21:21 Functions: 11 12 91.7 %
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/MCInstrAnalysis.h"
      18             : #include "llvm/MC/SubtargetFeature.h"
      19             : #include "llvm/Object/ELF.h"
      20             : #include "llvm/Object/ELFTypes.h"
      21             : #include "llvm/Object/Error.h"
      22             : #include "llvm/Support/ARMAttributeParser.h"
      23             : #include "llvm/Support/ARMBuildAttributes.h"
      24             : #include "llvm/Support/Endian.h"
      25             : #include "llvm/Support/ErrorHandling.h"
      26             : #include "llvm/Support/MathExtras.h"
      27             : #include "llvm/Support/TargetRegistry.h"
      28             : #include <algorithm>
      29             : #include <cstddef>
      30             : #include <cstdint>
      31             : #include <memory>
      32             : #include <string>
      33             : #include <system_error>
      34             : #include <utility>
      35             : 
      36             : using namespace llvm;
      37             : using namespace object;
      38             : 
      39       19359 : ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
      40       19359 :     : ObjectFile(Type, Source) {}
      41             : 
      42             : template <class ELFT>
      43             : static Expected<std::unique_ptr<ELFObjectFile<ELFT>>>
      44        6308 : createPtr(MemoryBufferRef Object) {
      45       12616 :   auto Ret = ELFObjectFile<ELFT>::create(Object);
      46        6308 :   if (Error E = Ret.takeError())
      47             :     return std::move(E);
      48             :   return make_unique<ELFObjectFile<ELFT>>(std::move(*Ret));
      49             : }
      50         237 : 
      51         474 : Expected<std::unique_ptr<ObjectFile>>
      52         237 : ObjectFile::createELFObjectFile(MemoryBufferRef Obj) {
      53             :   std::pair<unsigned char, unsigned char> Ident =
      54             :       getElfArchType(Obj.getBuffer());
      55             :   std::size_t MaxAlignment =
      56        4649 :       1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart()));
      57        9298 : 
      58        4649 :   if (MaxAlignment < 2)
      59             :     return createError("Insufficient alignment");
      60             : 
      61             :   if (Ident.first == ELF::ELFCLASS32) {
      62         284 :     if (Ident.second == ELF::ELFDATA2LSB)
      63         568 :       return createPtr<ELF32LE>(Obj);
      64         284 :     else if (Ident.second == ELF::ELFDATA2MSB)
      65             :       return createPtr<ELF32BE>(Obj);
      66             :     else
      67             :       return createError("Invalid ELF data");
      68        1138 :   } else if (Ident.first == ELF::ELFCLASS64) {
      69        2276 :     if (Ident.second == ELF::ELFDATA2LSB)
      70        1138 :       return createPtr<ELF64LE>(Obj);
      71             :     else if (Ident.second == ELF::ELFDATA2MSB)
      72             :       return createPtr<ELF64BE>(Obj);
      73             :     else
      74             :       return createError("Invalid ELF data");
      75             :   }
      76        6311 :   return createError("Invalid ELF class");
      77             : }
      78             : 
      79             : SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const {
      80        6311 :   SubtargetFeatures Features;
      81             :   unsigned PlatformFlags = getPlatformFlags();
      82        6311 : 
      83           1 :   switch (PlatformFlags & ELF::EF_MIPS_ARCH) {
      84             :   case ELF::EF_MIPS_ARCH_1:
      85        6310 :     break;
      86        1422 :   case ELF::EF_MIPS_ARCH_2:
      87        2276 :     Features.AddFeature("mips2");
      88         284 :     break;
      89         568 :   case ELF::EF_MIPS_ARCH_3:
      90             :     Features.AddFeature("mips3");
      91           0 :     break;
      92        4888 :   case ELF::EF_MIPS_ARCH_4:
      93        4887 :     Features.AddFeature("mips4");
      94        9298 :     break;
      95         238 :   case ELF::EF_MIPS_ARCH_5:
      96         474 :     Features.AddFeature("mips5");
      97             :     break;
      98           1 :   case ELF::EF_MIPS_ARCH_32:
      99             :     Features.AddFeature("mips32");
     100           1 :     break;
     101             :   case ELF::EF_MIPS_ARCH_64:
     102             :     Features.AddFeature("mips64");
     103         114 :     break;
     104         114 :   case ELF::EF_MIPS_ARCH_32R2:
     105         114 :     Features.AddFeature("mips32r2");
     106             :     break;
     107         114 :   case ELF::EF_MIPS_ARCH_64R2:
     108             :     Features.AddFeature("mips64r2");
     109             :     break;
     110             :   case ELF::EF_MIPS_ARCH_32R6:
     111           0 :     Features.AddFeature("mips32r6");
     112           0 :     break;
     113             :   case ELF::EF_MIPS_ARCH_64R6:
     114           0 :     Features.AddFeature("mips64r6");
     115           0 :     break;
     116             :   default:
     117           0 :     llvm_unreachable("Unknown EF_MIPS_ARCH value");
     118           0 :   }
     119             : 
     120           0 :   switch (PlatformFlags & ELF::EF_MIPS_MACH) {
     121           0 :   case ELF::EF_MIPS_MACH_NONE:
     122             :     // No feature associated with this value.
     123          56 :     break;
     124          56 :   case ELF::EF_MIPS_MACH_OCTEON:
     125             :     Features.AddFeature("cnmips");
     126          22 :     break;
     127          22 :   default:
     128             :     llvm_unreachable("Unknown EF_MIPS_ARCH value");
     129          10 :   }
     130          10 : 
     131             :   if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16)
     132           8 :     Features.AddFeature("mips16");
     133           8 :   if (PlatformFlags & ELF::EF_MIPS_MICROMIPS)
     134             :     Features.AddFeature("micromips");
     135          14 : 
     136          14 :   return Features;
     137             : }
     138           3 : 
     139           3 : SubtargetFeatures ELFObjectFileBase::getARMFeatures() const {
     140           0 :   SubtargetFeatures Features;
     141           0 :   ARMAttributeParser Attributes;
     142             :   std::error_code EC = getBuildAttributes(Attributes);
     143             :   if (EC)
     144         114 :     return SubtargetFeatures();
     145             : 
     146             :   // both ARMv7-M and R have to support thumb hardware div
     147             :   bool isV7 = false;
     148             :   if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch))
     149           0 :     isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)
     150           0 :       == ARMBuildAttrs::v7;
     151           0 : 
     152           0 :   if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) {
     153             :     switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) {
     154             :     case ARMBuildAttrs::ApplicationProfile:
     155         114 :       Features.AddFeature("aclass");
     156           0 :       break;
     157         114 :     case ARMBuildAttrs::RealTimeProfile:
     158          25 :       Features.AddFeature("rclass");
     159             :       if (isV7)
     160         114 :         Features.AddFeature("hwdiv");
     161             :       break;
     162             :     case ARMBuildAttrs::MicroControllerProfile:
     163         184 :       Features.AddFeature("mclass");
     164         184 :       if (isV7)
     165             :         Features.AddFeature("hwdiv");
     166         184 :       break;
     167         184 :     }
     168           0 :   }
     169             : 
     170             :   if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) {
     171             :     switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) {
     172             :     default:
     173         119 :       break;
     174             :     case ARMBuildAttrs::Not_Allowed:
     175             :       Features.AddFeature("thumb", false);
     176             :       Features.AddFeature("thumb2", false);
     177          98 :       break;
     178             :     case ARMBuildAttrs::AllowThumb32:
     179          93 :       Features.AddFeature("thumb2");
     180          93 :       break;
     181             :     }
     182           2 :   }
     183           2 : 
     184           2 :   if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) {
     185             :     switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) {
     186             :     default:
     187           3 :       break;
     188           3 :     case ARMBuildAttrs::Not_Allowed:
     189           2 :       Features.AddFeature("vfp2", false);
     190             :       Features.AddFeature("vfp3", false);
     191             :       Features.AddFeature("vfp4", false);
     192             :       break;
     193             :     case ARMBuildAttrs::AllowFPv2:
     194             :       Features.AddFeature("vfp2");
     195         114 :       break;
     196             :     case ARMBuildAttrs::AllowFPv3A:
     197             :     case ARMBuildAttrs::AllowFPv3B:
     198             :       Features.AddFeature("vfp3");
     199           0 :       break;
     200           0 :     case ARMBuildAttrs::AllowFPv4A:
     201           0 :     case ARMBuildAttrs::AllowFPv4B:
     202             :       Features.AddFeature("vfp4");
     203          95 :       break;
     204          95 :     }
     205             :   }
     206             : 
     207             :   if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) {
     208             :     switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) {
     209          98 :     default:
     210             :       break;
     211             :     case ARMBuildAttrs::Not_Allowed:
     212             :       Features.AddFeature("neon", false);
     213           3 :       Features.AddFeature("fp16", false);
     214           3 :       break;
     215           3 :     case ARMBuildAttrs::AllowNeon:
     216           3 :       Features.AddFeature("neon");
     217             :       break;
     218           1 :     case ARMBuildAttrs::AllowNeon2:
     219           1 :       Features.AddFeature("neon");
     220             :       Features.AddFeature("fp16");
     221             :       break;
     222          90 :     }
     223          90 :   }
     224             : 
     225             :   if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) {
     226           3 :     switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) {
     227           3 :     default:
     228             :       break;
     229             :     case ARMBuildAttrs::DisallowDIV:
     230             :       Features.AddFeature("hwdiv", false);
     231             :       Features.AddFeature("hwdiv-arm", false);
     232          91 :       break;
     233             :     case ARMBuildAttrs::AllowDIVExt:
     234             :       Features.AddFeature("hwdiv");
     235             :       Features.AddFeature("hwdiv-arm");
     236           0 :       break;
     237           0 :     }
     238           0 :   }
     239             : 
     240          88 :   return Features;
     241          88 : }
     242             : 
     243           3 : SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const {
     244           3 :   SubtargetFeatures Features;
     245           3 :   unsigned PlatformFlags = getPlatformFlags();
     246             : 
     247             :   if (PlatformFlags & ELF::EF_RISCV_RVC) {
     248             :     Features.AddFeature("c");
     249             :   }
     250           3 : 
     251             :   return Features;
     252             : }
     253             : 
     254           0 : SubtargetFeatures ELFObjectFileBase::getFeatures() const {
     255           0 :   switch (getEMachine()) {
     256           0 :   case ELF::EM_MIPS:
     257             :     return getMIPSFeatures();
     258           3 :   case ELF::EM_ARM:
     259           3 :     return getARMFeatures();
     260           3 :   case ELF::EM_RISCV:
     261             :     return getRISCVFeatures();
     262             :   default:
     263             :     return SubtargetFeatures();
     264             :   }
     265             : }
     266             : 
     267           0 : // FIXME Encode from a tablegen description or target parser.
     268           0 : void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
     269           0 :   if (TheTriple.getSubArch() != Triple::NoSubArch)
     270             :     return;
     271           0 : 
     272           0 :   ARMAttributeParser Attributes;
     273             :   std::error_code EC = getBuildAttributes(Attributes);
     274             :   if (EC)
     275           0 :     return;
     276             : 
     277             :   std::string Triple;
     278        1433 :   // Default to ARM, but use the triple if it's been set.
     279        1433 :   if (TheTriple.isThumb())
     280         114 :     Triple = "thumb";
     281         114 :   else
     282         184 :     Triple = "arm";
     283         184 : 
     284           0 :   if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
     285           0 :     switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
     286             :     case ARMBuildAttrs::v4:
     287        1135 :       Triple += "v4";
     288             :       break;
     289             :     case ARMBuildAttrs::v4T:
     290             :       Triple += "v4t";
     291             :       break;
     292         204 :     case ARMBuildAttrs::v5T:
     293         204 :       Triple += "v5t";
     294         154 :       break;
     295             :     case ARMBuildAttrs::v5TE:
     296             :       Triple += "v5te";
     297          50 :       break;
     298          50 :     case ARMBuildAttrs::v5TEJ:
     299             :       Triple += "v5tej";
     300             :       break;
     301             :     case ARMBuildAttrs::v6:
     302             :       Triple += "v6";
     303             :       break;
     304             :     case ARMBuildAttrs::v6KZ:
     305             :       Triple += "v6kz";
     306             :       break;
     307             :     case ARMBuildAttrs::v6T2:
     308             :       Triple += "v6t2";
     309          26 :       break;
     310             :     case ARMBuildAttrs::v6K:
     311             :       Triple += "v6k";
     312             :       break;
     313             :     case ARMBuildAttrs::v7:
     314             :       Triple += "v7";
     315             :       break;
     316             :     case ARMBuildAttrs::v6_M:
     317             :       Triple += "v6m";
     318             :       break;
     319             :     case ARMBuildAttrs::v6S_M:
     320             :       Triple += "v6sm";
     321             :       break;
     322             :     case ARMBuildAttrs::v7E_M:
     323             :       Triple += "v7em";
     324             :       break;
     325             :     }
     326             :   }
     327             :   if (!isLittleEndian())
     328             :     Triple += "eb";
     329             : 
     330             :   TheTriple.setArchName(Triple);
     331             : }
     332             : 
     333             : std::vector<std::pair<DataRefImpl, uint64_t>>
     334             : ELFObjectFileBase::getPltAddresses() const {
     335             :   std::string Err;
     336             :   const auto Triple = makeTriple();
     337             :   const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err);
     338             :   if (!T)
     339             :     return {};
     340             :   uint64_t JumpSlotReloc = 0;
     341             :   switch (Triple.getArch()) {
     342             :     case Triple::x86:
     343             :       JumpSlotReloc = ELF::R_386_JUMP_SLOT;
     344             :       break;
     345             :     case Triple::x86_64:
     346             :       JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT;
     347             :       break;
     348             :     case Triple::aarch64:
     349             :       JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT;
     350             :       break;
     351          50 :     default:
     352             :       return {};
     353             :   }
     354          50 :   std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo());
     355             :   std::unique_ptr<const MCInstrAnalysis> MIA(
     356             :       T->createMCInstrAnalysis(MII.get()));
     357             :   if (!MIA)
     358         103 :     return {};
     359             :   Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None;
     360         103 :   for (const SectionRef &Section : sections()) {
     361         103 :     StringRef Name;
     362         103 :     if (Section.getName(Name))
     363             :       continue;
     364             :     if (Name == ".plt")
     365         103 :       Plt = Section;
     366             :     else if (Name == ".rela.plt" || Name == ".rel.plt")
     367             :       RelaPlt = Section;
     368             :     else if (Name == ".got.plt")
     369             :       GotPlt = Section;
     370             :   }
     371             :   if (!Plt || !RelaPlt || !GotPlt)
     372          11 :     return {};
     373             :   StringRef PltContents;
     374          11 :   if (Plt->getContents(PltContents))
     375             :     return {};
     376             :   ArrayRef<uint8_t> PltBytes((const uint8_t *)PltContents.data(),
     377             :                              Plt->getSize());
     378          50 :   auto PltEntries = MIA->findPltEntries(Plt->getAddress(), PltBytes,
     379             :                                         GotPlt->getAddress(), Triple);
     380          50 :   // Build a map from GOT entry virtual address to PLT entry virtual address.
     381          50 :   DenseMap<uint64_t, uint64_t> GotToPlt;
     382             :   for (const auto &Entry : PltEntries)
     383             :     GotToPlt.insert(std::make_pair(Entry.second, Entry.first));
     384         875 :   // Find the relocations in the dynamic relocation table that point to
     385         825 :   // locations in the GOT for which we know the corresponding PLT entry.
     386         825 :   std::vector<std::pair<DataRefImpl, uint64_t>> Result;
     387           0 :   for (const auto &Relocation : RelaPlt->relocations()) {
     388             :     if (Relocation.getType() != JumpSlotReloc)
     389          41 :       continue;
     390             :     auto PltEntryIter = GotToPlt.find(Relocation.getOffset());
     391          41 :     if (PltEntryIter != GotToPlt.end())
     392             :       Result.push_back(std::make_pair(
     393          41 :           Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second));
     394             :   }
     395          50 :   return Result;
     396             : }

Generated by: LCOV version 1.13