LCOV - code coverage report
Current view: top level - include/llvm/Object - RelocVisitor.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 105 173 60.7 %
Date: 2018-10-20 13:21:21 Functions: 9 17 52.9 %
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/Object/Wasm.h"
      27             : #include "llvm/Support/Casting.h"
      28             : #include "llvm/Support/ErrorHandling.h"
      29             : #include <cstdint>
      30             : #include <system_error>
      31             : 
      32             : namespace llvm {
      33             : namespace object {
      34             : 
      35             : /// Base class for object file relocation visitors.
      36             : class RelocVisitor {
      37             : public:
      38       12334 :   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       12334 :   uint64_t visit(uint32_t Rel, RelocationRef R, uint64_t Value = 0) {
      44       24668 :     if (isa<ELFObjectFileBase>(ObjToVisit))
      45       12159 :       return visitELF(Rel, R, Value);
      46         175 :     if (isa<COFFObjectFile>(ObjToVisit))
      47         148 :       return visitCOFF(Rel, R, Value);
      48          27 :     if (isa<MachOObjectFile>(ObjToVisit))
      49             :       return visitMachO(Rel, R, Value);
      50          14 :     if (isa<WasmObjectFile>(ObjToVisit))
      51             :       return visitWasm(Rel, R, Value);
      52             : 
      53           0 :     HasError = true;
      54           0 :     return 0;
      55             :   }
      56             : 
      57           0 :   bool error() { return HasError; }
      58             : 
      59             : private:
      60             :   const ObjectFile &ObjToVisit;
      61             :   bool HasError = false;
      62             : 
      63       12159 :   uint64_t visitELF(uint32_t Rel, RelocationRef R, uint64_t Value) {
      64       12159 :     if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
      65       11608 :       switch (ObjToVisit.getArch()) {
      66       11263 :       case Triple::x86_64:
      67       11263 :         return visitX86_64(Rel, R, Value);
      68         133 :       case Triple::aarch64:
      69             :       case Triple::aarch64_be:
      70         133 :         return visitAarch64(Rel, R, Value);
      71          32 :       case Triple::bpfel:
      72             :       case Triple::bpfeb:
      73             :         return visitBpf(Rel, R, Value);
      74          24 :       case Triple::mips64el:
      75             :       case Triple::mips64:
      76          24 :         return visitMips64(Rel, R, Value);
      77           0 :       case Triple::ppc64le:
      78             :       case Triple::ppc64:
      79           0 :         return visitPPC64(Rel, R, Value);
      80          31 :       case Triple::systemz:
      81          31 :         return visitSystemz(Rel, R, Value);
      82          22 :       case Triple::sparcv9:
      83          22 :         return visitSparc64(Rel, R, Value);
      84         103 :       case Triple::amdgcn:
      85         103 :         return visitAmdgpu(Rel, R, Value);
      86           0 :       default:
      87           0 :         HasError = true;
      88           0 :         return 0;
      89             :       }
      90             :     }
      91             : 
      92             :     // 32-bit object file
      93             :     assert(ObjToVisit.getBytesInAddress() == 4 &&
      94             :            "Invalid word size in object file");
      95             : 
      96         551 :     switch (ObjToVisit.getArch()) {
      97         251 :     case Triple::x86:
      98         251 :       return visitX86(Rel, R, Value);
      99           0 :     case Triple::ppc:
     100           0 :       return visitPPC32(Rel, R, Value);
     101         157 :     case Triple::arm:
     102             :     case Triple::armeb:
     103             :       return visitARM(Rel, R, Value);
     104           0 :     case Triple::lanai:
     105           0 :       return visitLanai(Rel, R, Value);
     106          94 :     case Triple::mipsel:
     107             :     case Triple::mips:
     108             :       return visitMips32(Rel, R, Value);
     109          10 :     case Triple::sparc:
     110          10 :       return visitSparc32(Rel, R, Value);
     111          30 :     case Triple::hexagon:
     112          30 :       return visitHexagon(Rel, R, Value);
     113           9 :     default:
     114           9 :       HasError = true;
     115           9 :       return 0;
     116             :     }
     117             :   }
     118             : 
     119       11611 :   int64_t getELFAddend(RelocationRef R) {
     120       11611 :     Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
     121       11611 :     handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
     122             :       report_fatal_error(EI.message());
     123             :     });
     124       11610 :     return *AddendOrErr;
     125             :   }
     126             : 
     127       11263 :   uint64_t visitX86_64(uint32_t Rel, RelocationRef R, uint64_t Value) {
     128       11263 :     switch (Rel) {
     129             :     case ELF::R_X86_64_NONE:
     130             :       return 0;
     131        2013 :     case ELF::R_X86_64_64:
     132        2013 :       return Value + getELFAddend(R);
     133           0 :     case ELF::R_X86_64_PC32:
     134           0 :       return Value + getELFAddend(R) - R.getOffset();
     135        9245 :     case ELF::R_X86_64_32:
     136             :     case ELF::R_X86_64_32S:
     137        9245 :       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
     138             :     }
     139           5 :     HasError = true;
     140           5 :     return 0;
     141             :   }
     142             : 
     143         133 :   uint64_t visitAarch64(uint32_t Rel, RelocationRef R, uint64_t Value) {
     144         133 :     switch (Rel) {
     145          95 :     case ELF::R_AARCH64_ABS32: {
     146          95 :       int64_t Res = Value + getELFAddend(R);
     147          95 :       if (Res < INT32_MIN || Res > UINT32_MAX)
     148           0 :         HasError = true;
     149          95 :       return static_cast<uint32_t>(Res);
     150             :     }
     151          38 :     case ELF::R_AARCH64_ABS64:
     152          38 :       return Value + getELFAddend(R);
     153             :     }
     154           0 :     HasError = true;
     155           0 :     return 0;
     156             :   }
     157             : 
     158           0 :   uint64_t visitBpf(uint32_t Rel, RelocationRef R, uint64_t Value) {
     159          32 :     switch (Rel) {
     160          24 :     case ELF::R_BPF_64_32:
     161          24 :       return Value & 0xFFFFFFFF;
     162             :     case ELF::R_BPF_64_64:
     163             :       return Value;
     164             :     }
     165           0 :     HasError = true;
     166           0 :     return 0;
     167             :   }
     168             : 
     169          24 :   uint64_t visitMips64(uint32_t Rel, RelocationRef R, uint64_t Value) {
     170          24 :     switch (Rel) {
     171          16 :     case ELF::R_MIPS_32:
     172          16 :       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
     173           7 :     case ELF::R_MIPS_64:
     174           7 :       return Value + getELFAddend(R);
     175           1 :     case ELF::R_MIPS_TLS_DTPREL64:
     176           1 :       return Value + getELFAddend(R) - 0x8000;
     177             :     }
     178           0 :     HasError = true;
     179           0 :     return 0;
     180             :   }
     181             : 
     182           0 :   uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) {
     183           0 :     switch (Rel) {
     184           0 :     case ELF::R_PPC64_ADDR32:
     185           0 :       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
     186           0 :     case ELF::R_PPC64_ADDR64:
     187           0 :       return Value + getELFAddend(R);
     188             :     }
     189           0 :     HasError = true;
     190           0 :     return 0;
     191             :   }
     192             : 
     193          31 :   uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) {
     194          31 :     switch (Rel) {
     195          22 :     case ELF::R_390_32: {
     196          22 :       int64_t Res = Value + getELFAddend(R);
     197          22 :       if (Res < INT32_MIN || Res > UINT32_MAX)
     198           0 :         HasError = true;
     199          22 :       return static_cast<uint32_t>(Res);
     200             :     }
     201           9 :     case ELF::R_390_64:
     202           9 :       return Value + getELFAddend(R);
     203             :     }
     204           0 :     HasError = true;
     205           0 :     return 0;
     206             :   }
     207             : 
     208          22 :   uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) {
     209             :     switch (Rel) {
     210          22 :     case ELF::R_SPARC_32:
     211             :     case ELF::R_SPARC_64:
     212             :     case ELF::R_SPARC_UA32:
     213             :     case ELF::R_SPARC_UA64:
     214          22 :       return Value + getELFAddend(R);
     215             :     }
     216           0 :     HasError = true;
     217           0 :     return 0;
     218             :   }
     219             : 
     220             :   uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) {
     221         103 :     switch (Rel) {
     222         103 :     case ELF::R_AMDGPU_ABS32:
     223             :     case ELF::R_AMDGPU_ABS64:
     224         103 :       return Value + getELFAddend(R);
     225             :     }
     226           0 :     HasError = true;
     227             :     return 0;
     228             :   }
     229             : 
     230           0 :   uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) {
     231         251 :     switch (Rel) {
     232             :     case ELF::R_386_NONE:
     233             :       return 0;
     234         250 :     case ELF::R_386_32:
     235           0 :       return Value;
     236           0 :     case ELF::R_386_PC32:
     237           0 :       return Value - R.getOffset();
     238             :     }
     239           1 :     HasError = true;
     240           0 :     return 0;
     241             :   }
     242             : 
     243             :   uint64_t visitPPC32(uint32_t Rel, RelocationRef R, uint64_t Value) {
     244           0 :     if (Rel == ELF::R_PPC_ADDR32)
     245           0 :       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
     246           0 :     HasError = true;
     247             :     return 0;
     248             :   }
     249             : 
     250           0 :   uint64_t visitARM(uint32_t Rel, RelocationRef R, uint64_t Value) {
     251         157 :     if (Rel == ELF::R_ARM_ABS32) {
     252         157 :       if ((int64_t)Value < INT32_MIN || (int64_t)Value > UINT32_MAX)
     253           0 :         HasError = true;
     254           0 :       return static_cast<uint32_t>(Value);
     255             :     }
     256           0 :     HasError = true;
     257           0 :     return 0;
     258             :   }
     259             : 
     260             :   uint64_t visitLanai(uint32_t Rel, RelocationRef R, uint64_t Value) {
     261           0 :     if (Rel == ELF::R_LANAI_32)
     262           0 :       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
     263           0 :     HasError = true;
     264             :     return 0;
     265             :   }
     266             : 
     267           0 :   uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) {
     268             :     // FIXME: Take in account implicit addends to get correct results.
     269          94 :     if (Rel == ELF::R_MIPS_32)
     270          93 :       return Value & 0xFFFFFFFF;
     271           1 :     if (Rel == ELF::R_MIPS_TLS_DTPREL32)
     272           1 :       return Value & 0xFFFFFFFF;
     273           0 :     HasError = true;
     274           0 :     return 0;
     275             :   }
     276             : 
     277             :   uint64_t visitSparc32(uint32_t Rel, RelocationRef R, uint64_t Value) {
     278          10 :     if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
     279          10 :       return Value + getELFAddend(R);
     280           0 :     HasError = true;
     281             :     return 0;
     282             :   }
     283             : 
     284             :   uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) {
     285          30 :     if (Rel == ELF::R_HEX_32)
     286          30 :       return Value + getELFAddend(R);
     287           0 :     HasError = true;
     288             :     return 0;
     289             :   }
     290             : 
     291         148 :   uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) {
     292         148 :     switch (ObjToVisit.getArch()) {
     293          58 :     case Triple::x86:
     294             :       switch (Rel) {
     295          58 :       case COFF::IMAGE_REL_I386_SECREL:
     296             :       case COFF::IMAGE_REL_I386_DIR32:
     297          58 :         return static_cast<uint32_t>(Value);
     298             :       }
     299             :       break;
     300          90 :     case Triple::x86_64:
     301             :       switch (Rel) {
     302          73 :       case COFF::IMAGE_REL_AMD64_SECREL:
     303          73 :         return static_cast<uint32_t>(Value);
     304             :       case COFF::IMAGE_REL_AMD64_ADDR64:
     305             :         return Value;
     306             :       }
     307             :       break;
     308             :     default:
     309             :       break;
     310             :     }
     311           0 :     HasError = true;
     312           0 :     return 0;
     313             :   }
     314             : 
     315           0 :   uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) {
     316          13 :     if (ObjToVisit.getArch() == Triple::x86_64 &&
     317             :         Rel == MachO::X86_64_RELOC_UNSIGNED)
     318           0 :       return Value;
     319           0 :     HasError = true;
     320           0 :     return 0;
     321             :   }
     322             : 
     323           0 :   uint64_t visitWasm(uint32_t Rel, RelocationRef R, uint64_t Value) {
     324          14 :     if (ObjToVisit.getArch() == Triple::wasm32) {
     325          14 :       switch (Rel) {
     326           0 :       case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
     327             :       case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
     328             :       case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
     329             :       case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
     330             :       case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
     331             :       case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
     332             :       case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
     333             :       case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
     334             :       case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
     335             :       case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
     336             :         // For wasm section, its offset at 0 -- ignoring Value
     337           0 :         return 0;
     338             :       }
     339             :     }
     340           0 :     HasError = true;
     341           0 :     return 0;
     342             :   }
     343             : };
     344             : 
     345             : } // end namespace object
     346             : } // end namespace llvm
     347             : 
     348             : #endif // LLVM_OBJECT_RELOCVISITOR_H

Generated by: LCOV version 1.13