LCOV - code coverage report
Current view: top level - include/llvm/Object - RelocVisitor.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 99 145 68.3 %
Date: 2018-02-21 17:27:13 Functions: 10 12 83.3 %
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 <cstdint>
      29             : #include <system_error>
      30             : 
      31             : namespace llvm {
      32             : namespace object {
      33             : 
      34             : /// @brief Base class for object file relocation visitors.
      35             : class RelocVisitor {
      36             : public:
      37        5694 :   explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {}
      38             : 
      39             :   // TODO: Should handle multiple applied relocations via either passing in the
      40             :   // previously computed value or just count paired relocations as a single
      41             :   // visit.
      42        5694 :   uint64_t visit(uint32_t Rel, RelocationRef R, uint64_t Value = 0) {
      43       11388 :     if (isa<ELFObjectFileBase>(ObjToVisit))
      44        5533 :       return visitELF(Rel, R, Value);
      45         161 :     if (isa<COFFObjectFile>(ObjToVisit))
      46         148 :       return visitCOFF(Rel, R, Value);
      47          13 :     if (isa<MachOObjectFile>(ObjToVisit))
      48             :       return visitMachO(Rel, R, Value);
      49             : 
      50           0 :     HasError = true;
      51           0 :     return 0;
      52             :   }
      53             : 
      54             :   bool error() { return HasError; }
      55             : 
      56             : private:
      57             :   const ObjectFile &ObjToVisit;
      58             :   bool HasError = false;
      59             : 
      60        5533 :   uint64_t visitELF(uint32_t Rel, RelocationRef R, uint64_t Value) {
      61        5533 :     if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
      62        5035 :       switch (ObjToVisit.getArch()) {
      63        4756 :       case Triple::x86_64:
      64        4756 :         return visitX86_64(Rel, R, Value);
      65          73 :       case Triple::aarch64:
      66             :       case Triple::aarch64_be:
      67          73 :         return visitAarch64(Rel, R, Value);
      68          32 :       case Triple::bpfel:
      69             :       case Triple::bpfeb:
      70             :         return visitBpf(Rel, R, Value);
      71          18 :       case Triple::mips64el:
      72             :       case Triple::mips64:
      73          18 :         return visitMips64(Rel, R, Value);
      74           0 :       case Triple::ppc64le:
      75             :       case Triple::ppc64:
      76           0 :         return visitPPC64(Rel, R, Value);
      77          31 :       case Triple::systemz:
      78          31 :         return visitSystemz(Rel, R, Value);
      79          22 :       case Triple::sparcv9:
      80          22 :         return visitSparc64(Rel, R, Value);
      81         103 :       case Triple::amdgcn:
      82             :         return visitAmdgpu(Rel, R, Value);
      83           0 :       default:
      84           0 :         HasError = true;
      85           0 :         return 0;
      86             :       }
      87             :     }
      88             : 
      89             :     // 32-bit object file
      90             :     assert(ObjToVisit.getBytesInAddress() == 4 &&
      91             :            "Invalid word size in object file");
      92             : 
      93         498 :     switch (ObjToVisit.getArch()) {
      94         216 :     case Triple::x86:
      95             :       return visitX86(Rel, R, Value);
      96           0 :     case Triple::ppc:
      97             :       return visitPPC32(Rel, R, Value);
      98         151 :     case Triple::arm:
      99             :     case Triple::armeb:
     100             :       return visitARM(Rel, R, Value);
     101           0 :     case Triple::lanai:
     102             :       return visitLanai(Rel, R, Value);
     103          82 :     case Triple::mipsel:
     104             :     case Triple::mips:
     105             :       return visitMips32(Rel, R, Value);
     106          10 :     case Triple::sparc:
     107             :       return visitSparc32(Rel, R, Value);
     108          30 :     case Triple::hexagon:
     109             :       return visitHexagon(Rel, R, Value);
     110           9 :     default:
     111           9 :       HasError = true;
     112           9 :       return 0;
     113             :     }
     114             :   }
     115             : 
     116        5038 :   int64_t getELFAddend(RelocationRef R) {
     117        5038 :     Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
     118       10076 :     handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
     119           1 :       report_fatal_error(EI.message());
     120           0 :     });
     121       10074 :     return *AddendOrErr;
     122             :   }
     123             : 
     124        4756 :   uint64_t visitX86_64(uint32_t Rel, RelocationRef R, uint64_t Value) {
     125        4756 :     switch (Rel) {
     126             :     case ELF::R_X86_64_NONE:
     127             :       return 0;
     128        1288 :     case ELF::R_X86_64_64:
     129        1288 :       return Value + getELFAddend(R);
     130           0 :     case ELF::R_X86_64_PC32:
     131           0 :       return Value + getELFAddend(R) - R.getOffset();
     132        3463 :     case ELF::R_X86_64_32:
     133             :     case ELF::R_X86_64_32S:
     134        3463 :       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
     135             :     }
     136           5 :     HasError = true;
     137           5 :     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         216 :     switch (Rel) {
     229             :     case ELF::R_386_NONE:
     230             :       return 0;
     231         215 :     case ELF::R_386_32:
     232             :       return Value;
     233             :     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         151 :     if (Rel == ELF::R_ARM_ABS32) {
     249         151 :       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         148 :   uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) {
     289         148 :     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          90 :     case Triple::x86_64:
     298          90 :       switch (Rel) {
     299          73 :       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             :     default:
     306             :       break;
     307             :     }
     308           0 :     HasError = true;
     309             :     return 0;
     310             :   }
     311             : 
     312             :   uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) {
     313          13 :     if (ObjToVisit.getArch() == Triple::x86_64 &&
     314             :         Rel == MachO::X86_64_RELOC_UNSIGNED)
     315             :       return Value;
     316           0 :     HasError = true;
     317             :     return 0;
     318             :   }
     319             : };
     320             : 
     321             : } // end namespace object
     322             : } // end namespace llvm
     323             : 
     324             : #endif // LLVM_OBJECT_RELOCVISITOR_H

Generated by: LCOV version 1.13