LCOV - code coverage report
Current view: top level - include/llvm/Object - RelocVisitor.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 102 150 68.0 %
Date: 2017-09-14 15:23:50 Functions: 9 10 90.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- RelocVisitor.h - Visitor for object file relocations -----*- C++ -*-===//
       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             : // This file provides a wrapper around all the different types of relocations
      11             : // in different file formats, such that a client can handle them in a unified
      12             : // manner by only implementing a minimal number of functions.
      13             : //
      14             : //===----------------------------------------------------------------------===//
      15             : 
      16             : #ifndef LLVM_OBJECT_RELOCVISITOR_H
      17             : #define LLVM_OBJECT_RELOCVISITOR_H
      18             : 
      19             : #include "llvm/ADT/Triple.h"
      20             : #include "llvm/BinaryFormat/ELF.h"
      21             : #include "llvm/BinaryFormat/MachO.h"
      22             : #include "llvm/Object/COFF.h"
      23             : #include "llvm/Object/ELFObjectFile.h"
      24             : #include "llvm/Object/MachO.h"
      25             : #include "llvm/Object/ObjectFile.h"
      26             : #include "llvm/Support/Casting.h"
      27             : #include "llvm/Support/ErrorHandling.h"
      28             : #include "llvm/Support/ErrorOr.h"
      29             : #include <cstdint>
      30             : #include <system_error>
      31             : 
      32             : namespace llvm {
      33             : namespace object {
      34             : 
      35             : /// @brief Base class for object file relocation visitors.
      36             : class RelocVisitor {
      37             : public:
      38        4560 :   explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {}
      39             : 
      40             :   // TODO: Should handle multiple applied relocations via either passing in the
      41             :   // previously computed value or just count paired relocations as a single
      42             :   // visit.
      43        4560 :   uint64_t visit(uint32_t Rel, RelocationRef R, uint64_t Value = 0) {
      44        9120 :     if (isa<ELFObjectFileBase>(ObjToVisit))
      45        4425 :       return visitELF(Rel, R, Value);
      46         270 :     if (isa<COFFObjectFile>(ObjToVisit))
      47         122 :       return visitCOFF(Rel, R, Value);
      48          26 :     if (isa<MachOObjectFile>(ObjToVisit))
      49          13 :       return visitMachO(Rel, R, Value);
      50             : 
      51           0 :     HasError = true;
      52           0 :     return 0;
      53             :   }
      54             : 
      55             :   bool error() { return HasError; }
      56             : 
      57             : private:
      58             :   const ObjectFile &ObjToVisit;
      59             :   bool HasError = false;
      60             : 
      61        4425 :   uint64_t visitELF(uint32_t Rel, RelocationRef R, uint64_t Value) {
      62        4425 :     if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
      63        3968 :       switch (ObjToVisit.getArch()) {
      64        3689 :       case Triple::x86_64:
      65        3689 :         return visitX86_64(Rel, R, Value);
      66          73 :       case Triple::aarch64:
      67             :       case Triple::aarch64_be:
      68          73 :         return visitAarch64(Rel, R, Value);
      69          32 :       case Triple::bpfel:
      70             :       case Triple::bpfeb:
      71          32 :         return visitBpf(Rel, R, Value);
      72          18 :       case Triple::mips64el:
      73             :       case Triple::mips64:
      74          18 :         return visitMips64(Rel, R, Value);
      75           0 :       case Triple::ppc64le:
      76             :       case Triple::ppc64:
      77           0 :         return visitPPC64(Rel, R, Value);
      78          31 :       case Triple::systemz:
      79          31 :         return visitSystemz(Rel, R, Value);
      80          22 :       case Triple::sparcv9:
      81          22 :         return visitSparc64(Rel, R, Value);
      82         103 :       case Triple::amdgcn:
      83             :         return visitAmdgpu(Rel, R, Value);
      84           0 :       default:
      85           0 :         HasError = true;
      86           0 :         return 0;
      87             :       }
      88             :     }
      89             : 
      90             :     // 32-bit object file
      91             :     assert(ObjToVisit.getBytesInAddress() == 4 &&
      92             :            "Invalid word size in object file");
      93             : 
      94         457 :     switch (ObjToVisit.getArch()) {
      95         203 :     case Triple::x86:
      96         203 :       return visitX86(Rel, R, Value);
      97           0 :     case Triple::ppc:
      98             :       return visitPPC32(Rel, R, Value);
      99         123 :     case Triple::arm:
     100             :     case Triple::armeb:
     101         123 :       return visitARM(Rel, R, Value);
     102           0 :     case Triple::lanai:
     103             :       return visitLanai(Rel, R, Value);
     104          82 :     case Triple::mipsel:
     105             :     case Triple::mips:
     106          82 :       return visitMips32(Rel, R, Value);
     107          10 :     case Triple::sparc:
     108             :       return visitSparc32(Rel, R, Value);
     109          30 :     case Triple::hexagon:
     110             :       return visitHexagon(Rel, R, Value);
     111           9 :     default:
     112           9 :       HasError = true;
     113           9 :       return 0;
     114             :     }
     115             :   }
     116             : 
     117        3976 :   int64_t getELFAddend(RelocationRef R) {
     118       11927 :     ErrorOr<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
     119        3976 :     if (std::error_code EC = AddendOrErr.getError())
     120           1 :       report_fatal_error(EC.message());
     121        7950 :     return *AddendOrErr;
     122             :   }
     123             : 
     124        3689 :   uint64_t visitX86_64(uint32_t Rel, RelocationRef R, uint64_t Value) {
     125        3689 :     switch (Rel) {
     126             :     case ELF::R_X86_64_NONE:
     127             :       return 0;
     128        1120 :     case ELF::R_X86_64_64:
     129        1120 :       return Value + getELFAddend(R);
     130           0 :     case ELF::R_X86_64_PC32:
     131           0 :       return Value + getELFAddend(R) - R.getOffset();
     132        2569 :     case ELF::R_X86_64_32:
     133             :     case ELF::R_X86_64_32S:
     134        2569 :       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
     135             :     }
     136           0 :     HasError = true;
     137           0 :     return 0;
     138             :   }
     139             : 
     140          73 :   uint64_t visitAarch64(uint32_t Rel, RelocationRef R, uint64_t Value) {
     141          73 :     switch (Rel) {
     142          55 :     case ELF::R_AARCH64_ABS32: {
     143          55 :       int64_t Res = Value + getELFAddend(R);
     144          55 :       if (Res < INT32_MIN || Res > UINT32_MAX)
     145           0 :         HasError = true;
     146          55 :       return static_cast<uint32_t>(Res);
     147             :     }
     148          18 :     case ELF::R_AARCH64_ABS64:
     149          18 :       return Value + getELFAddend(R);
     150             :     }
     151           0 :     HasError = true;
     152           0 :     return 0;
     153             :   }
     154             : 
     155             :   uint64_t visitBpf(uint32_t Rel, RelocationRef R, uint64_t Value) {
     156          32 :     switch (Rel) {
     157          24 :     case ELF::R_BPF_64_32:
     158          24 :       return Value & 0xFFFFFFFF;
     159             :     case ELF::R_BPF_64_64:
     160             :       return Value;
     161             :     }
     162           0 :     HasError = true;
     163             :     return 0;
     164             :   }
     165             : 
     166          18 :   uint64_t visitMips64(uint32_t Rel, RelocationRef R, uint64_t Value) {
     167          18 :     switch (Rel) {
     168          14 :     case ELF::R_MIPS_32:
     169          14 :       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
     170           3 :     case ELF::R_MIPS_64:
     171           3 :       return Value + getELFAddend(R);
     172           1 :     case ELF::R_MIPS_TLS_DTPREL64:
     173           1 :       return Value + getELFAddend(R) - 0x8000;
     174             :     }
     175           0 :     HasError = true;
     176           0 :     return 0;
     177             :   }
     178             : 
     179           0 :   uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) {
     180           0 :     switch (Rel) {
     181           0 :     case ELF::R_PPC64_ADDR32:
     182           0 :       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
     183           0 :     case ELF::R_PPC64_ADDR64:
     184           0 :       return Value + getELFAddend(R);
     185             :     }
     186           0 :     HasError = true;
     187           0 :     return 0;
     188             :   }
     189             : 
     190          31 :   uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) {
     191          31 :     switch (Rel) {
     192          22 :     case ELF::R_390_32: {
     193          22 :       int64_t Res = Value + getELFAddend(R);
     194          22 :       if (Res < INT32_MIN || Res > UINT32_MAX)
     195           0 :         HasError = true;
     196          22 :       return static_cast<uint32_t>(Res);
     197             :     }
     198           9 :     case ELF::R_390_64:
     199           9 :       return Value + getELFAddend(R);
     200             :     }
     201           0 :     HasError = true;
     202           0 :     return 0;
     203             :   }
     204             : 
     205          22 :   uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) {
     206             :     switch (Rel) {
     207          22 :     case ELF::R_SPARC_32:
     208             :     case ELF::R_SPARC_64:
     209             :     case ELF::R_SPARC_UA32:
     210             :     case ELF::R_SPARC_UA64:
     211          22 :       return Value + getELFAddend(R);
     212             :     }
     213           0 :     HasError = true;
     214           0 :     return 0;
     215             :   }
     216             : 
     217             :   uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) {
     218         103 :     switch (Rel) {
     219         103 :     case ELF::R_AMDGPU_ABS32:
     220             :     case ELF::R_AMDGPU_ABS64:
     221         103 :       return Value + getELFAddend(R);
     222             :     }
     223           0 :     HasError = true;
     224             :     return 0;
     225             :   }
     226             : 
     227             :   uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) {
     228         203 :     switch (Rel) {
     229             :     case ELF::R_386_NONE:
     230             :       return 0;
     231         202 :     case ELF::R_386_32:
     232             :       return Value;
     233           0 :     case ELF::R_386_PC32:
     234           0 :       return Value - R.getOffset();
     235             :     }
     236           1 :     HasError = true;
     237             :     return 0;
     238             :   }
     239             : 
     240             :   uint64_t visitPPC32(uint32_t Rel, RelocationRef R, uint64_t Value) {
     241           0 :     if (Rel == ELF::R_PPC_ADDR32)
     242           0 :       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
     243           0 :     HasError = true;
     244             :     return 0;
     245             :   }
     246             : 
     247             :   uint64_t visitARM(uint32_t Rel, RelocationRef R, uint64_t Value) {
     248         123 :     if (Rel == ELF::R_ARM_ABS32) {
     249         123 :       if ((int64_t)Value < INT32_MIN || (int64_t)Value > UINT32_MAX)
     250           0 :         HasError = true;
     251             :       return static_cast<uint32_t>(Value);
     252             :     }
     253           0 :     HasError = true;
     254             :     return 0;
     255             :   }
     256             : 
     257             :   uint64_t visitLanai(uint32_t Rel, RelocationRef R, uint64_t Value) {
     258           0 :     if (Rel == ELF::R_LANAI_32)
     259           0 :       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
     260           0 :     HasError = true;
     261             :     return 0;
     262             :   }
     263             : 
     264             :   uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) {
     265             :     // FIXME: Take in account implicit addends to get correct results.
     266          82 :     if (Rel == ELF::R_MIPS_32)
     267          81 :       return Value & 0xFFFFFFFF;
     268           1 :     if (Rel == ELF::R_MIPS_TLS_DTPREL32)
     269           1 :       return Value & 0xFFFFFFFF;
     270           0 :     HasError = true;
     271             :     return 0;
     272             :   }
     273             : 
     274             :   uint64_t visitSparc32(uint32_t Rel, RelocationRef R, uint64_t Value) {
     275          10 :     if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
     276          10 :       return Value + getELFAddend(R);
     277           0 :     HasError = true;
     278             :     return 0;
     279             :   }
     280             : 
     281             :   uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) {
     282          30 :     if (Rel == ELF::R_HEX_32)
     283          30 :       return Value + getELFAddend(R);
     284           0 :     HasError = true;
     285             :     return 0;
     286             :   }
     287             : 
     288         122 :   uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) {
     289         122 :     switch (ObjToVisit.getArch()) {
     290          58 :     case Triple::x86:
     291          58 :       switch (Rel) {
     292          58 :       case COFF::IMAGE_REL_I386_SECREL:
     293             :       case COFF::IMAGE_REL_I386_DIR32:
     294             :         return static_cast<uint32_t>(Value);
     295             :       }
     296             :       break;
     297          64 :     case Triple::x86_64:
     298          64 :       switch (Rel) {
     299          53 :       case COFF::IMAGE_REL_AMD64_SECREL:
     300             :         return static_cast<uint32_t>(Value);
     301             :       case COFF::IMAGE_REL_AMD64_ADDR64:
     302             :         return Value;
     303             :       }
     304             :       break;
     305             :     }
     306           0 :     HasError = true;
     307             :     return 0;
     308             :   }
     309             : 
     310             :   uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) {
     311          13 :     if (ObjToVisit.getArch() == Triple::x86_64 &&
     312             :         Rel == MachO::X86_64_RELOC_UNSIGNED)
     313             :       return Value;
     314           0 :     HasError = true;
     315             :     return 0;
     316             :   }
     317             : };
     318             : 
     319             : } // end namespace object
     320             : } // end namespace llvm
     321             : 
     322             : #endif // LLVM_OBJECT_RELOCVISITOR_H

Generated by: LCOV version 1.13