Home | History | Annotate | Download | only in Object
      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   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   uint64_t visit(uint32_t Rel, RelocationRef R, uint64_t Value = 0) {
     44     if (isa<ELFObjectFileBase>(ObjToVisit))
     45       return visitELF(Rel, R, Value);
     46     if (isa<COFFObjectFile>(ObjToVisit))
     47       return visitCOFF(Rel, R, Value);
     48     if (isa<MachOObjectFile>(ObjToVisit))
     49       return visitMachO(Rel, R, Value);
     50 
     51     HasError = true;
     52     return 0;
     53   }
     54 
     55   bool error() { return HasError; }
     56 
     57 private:
     58   const ObjectFile &ObjToVisit;
     59   bool HasError = false;
     60 
     61   uint64_t visitELF(uint32_t Rel, RelocationRef R, uint64_t Value) {
     62     if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
     63       switch (ObjToVisit.getArch()) {
     64       case Triple::x86_64:
     65         return visitX86_64(Rel, R, Value);
     66       case Triple::aarch64:
     67       case Triple::aarch64_be:
     68         return visitAarch64(Rel, R, Value);
     69       case Triple::bpfel:
     70       case Triple::bpfeb:
     71         return visitBpf(Rel, R, Value);
     72       case Triple::mips64el:
     73       case Triple::mips64:
     74         return visitMips64(Rel, R, Value);
     75       case Triple::ppc64le:
     76       case Triple::ppc64:
     77         return visitPPC64(Rel, R, Value);
     78       case Triple::systemz:
     79         return visitSystemz(Rel, R, Value);
     80       case Triple::sparcv9:
     81         return visitSparc64(Rel, R, Value);
     82       case Triple::amdgcn:
     83         return visitAmdgpu(Rel, R, Value);
     84       default:
     85         HasError = true;
     86         return 0;
     87       }
     88     }
     89 
     90     // 32-bit object file
     91     assert(ObjToVisit.getBytesInAddress() == 4 &&
     92            "Invalid word size in object file");
     93 
     94     switch (ObjToVisit.getArch()) {
     95     case Triple::x86:
     96       return visitX86(Rel, R, Value);
     97     case Triple::ppc:
     98       return visitPPC32(Rel, R, Value);
     99     case Triple::arm:
    100     case Triple::armeb:
    101       return visitARM(Rel, R, Value);
    102     case Triple::lanai:
    103       return visitLanai(Rel, R, Value);
    104     case Triple::mipsel:
    105     case Triple::mips:
    106       return visitMips32(Rel, R, Value);
    107     case Triple::sparc:
    108       return visitSparc32(Rel, R, Value);
    109     case Triple::hexagon:
    110       return visitHexagon(Rel, R, Value);
    111     default:
    112       HasError = true;
    113       return 0;
    114     }
    115   }
    116 
    117   int64_t getELFAddend(RelocationRef R) {
    118     ErrorOr<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
    119     if (std::error_code EC = AddendOrErr.getError())
    120       report_fatal_error(EC.message());
    121     return *AddendOrErr;
    122   }
    123 
    124   uint64_t visitX86_64(uint32_t Rel, RelocationRef R, uint64_t Value) {
    125     switch (Rel) {
    126     case ELF::R_X86_64_NONE:
    127       return 0;
    128     case ELF::R_X86_64_64:
    129       return Value + getELFAddend(R);
    130     case ELF::R_X86_64_PC32:
    131       return Value + getELFAddend(R) - R.getOffset();
    132     case ELF::R_X86_64_32:
    133     case ELF::R_X86_64_32S:
    134       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
    135     }
    136     HasError = true;
    137     return 0;
    138   }
    139 
    140   uint64_t visitAarch64(uint32_t Rel, RelocationRef R, uint64_t Value) {
    141     switch (Rel) {
    142     case ELF::R_AARCH64_ABS32: {
    143       int64_t Res = Value + getELFAddend(R);
    144       if (Res < INT32_MIN || Res > UINT32_MAX)
    145         HasError = true;
    146       return static_cast<uint32_t>(Res);
    147     }
    148     case ELF::R_AARCH64_ABS64:
    149       return Value + getELFAddend(R);
    150     }
    151     HasError = true;
    152     return 0;
    153   }
    154 
    155   uint64_t visitBpf(uint32_t Rel, RelocationRef R, uint64_t Value) {
    156     switch (Rel) {
    157     case ELF::R_BPF_64_32:
    158       return Value & 0xFFFFFFFF;
    159     case ELF::R_BPF_64_64:
    160       return Value;
    161     }
    162     HasError = true;
    163     return 0;
    164   }
    165 
    166   uint64_t visitMips64(uint32_t Rel, RelocationRef R, uint64_t Value) {
    167     switch (Rel) {
    168     case ELF::R_MIPS_32:
    169       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
    170     case ELF::R_MIPS_64:
    171       return Value + getELFAddend(R);
    172     }
    173     HasError = true;
    174     return 0;
    175   }
    176 
    177   uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) {
    178     switch (Rel) {
    179     case ELF::R_PPC64_ADDR32:
    180       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
    181     case ELF::R_PPC64_ADDR64:
    182       return Value + getELFAddend(R);
    183     }
    184     HasError = true;
    185     return 0;
    186   }
    187 
    188   uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) {
    189     switch (Rel) {
    190     case ELF::R_390_32: {
    191       int64_t Res = Value + getELFAddend(R);
    192       if (Res < INT32_MIN || Res > UINT32_MAX)
    193         HasError = true;
    194       return static_cast<uint32_t>(Res);
    195     }
    196     case ELF::R_390_64:
    197       return Value + getELFAddend(R);
    198     }
    199     HasError = true;
    200     return 0;
    201   }
    202 
    203   uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) {
    204     switch (Rel) {
    205     case ELF::R_SPARC_32:
    206     case ELF::R_SPARC_64:
    207     case ELF::R_SPARC_UA32:
    208     case ELF::R_SPARC_UA64:
    209       return Value + getELFAddend(R);
    210     }
    211     HasError = true;
    212     return 0;
    213   }
    214 
    215   uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) {
    216     switch (Rel) {
    217     case ELF::R_AMDGPU_ABS32:
    218     case ELF::R_AMDGPU_ABS64:
    219       return Value + getELFAddend(R);
    220     }
    221     HasError = true;
    222     return 0;
    223   }
    224 
    225   uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) {
    226     switch (Rel) {
    227     case ELF::R_386_NONE:
    228       return 0;
    229     case ELF::R_386_32:
    230       return Value;
    231     case ELF::R_386_PC32:
    232       return Value - R.getOffset();
    233     }
    234     HasError = true;
    235     return 0;
    236   }
    237 
    238   uint64_t visitPPC32(uint32_t Rel, RelocationRef R, uint64_t Value) {
    239     if (Rel == ELF::R_PPC_ADDR32)
    240       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
    241     HasError = true;
    242     return 0;
    243   }
    244 
    245   uint64_t visitARM(uint32_t Rel, RelocationRef R, uint64_t Value) {
    246     if (Rel == ELF::R_ARM_ABS32) {
    247       if ((int64_t)Value < INT32_MIN || (int64_t)Value > UINT32_MAX)
    248         HasError = true;
    249       return static_cast<uint32_t>(Value);
    250     }
    251     HasError = true;
    252     return 0;
    253   }
    254 
    255   uint64_t visitLanai(uint32_t Rel, RelocationRef R, uint64_t Value) {
    256     if (Rel == ELF::R_LANAI_32)
    257       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
    258     HasError = true;
    259     return 0;
    260   }
    261 
    262   uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) {
    263     if (Rel == ELF::R_MIPS_32)
    264       return Value & 0xFFFFFFFF;
    265     HasError = true;
    266     return 0;
    267   }
    268 
    269   uint64_t visitSparc32(uint32_t Rel, RelocationRef R, uint64_t Value) {
    270     if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
    271       return Value + getELFAddend(R);
    272     HasError = true;
    273     return 0;
    274   }
    275 
    276   uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) {
    277     if (Rel == ELF::R_HEX_32)
    278       return Value + getELFAddend(R);
    279     HasError = true;
    280     return 0;
    281   }
    282 
    283   uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) {
    284     switch (ObjToVisit.getArch()) {
    285     case Triple::x86:
    286       switch (Rel) {
    287       case COFF::IMAGE_REL_I386_SECREL:
    288       case COFF::IMAGE_REL_I386_DIR32:
    289         return static_cast<uint32_t>(Value);
    290       }
    291       break;
    292     case Triple::x86_64:
    293       switch (Rel) {
    294       case COFF::IMAGE_REL_AMD64_SECREL:
    295         return static_cast<uint32_t>(Value);
    296       case COFF::IMAGE_REL_AMD64_ADDR64:
    297         return Value;
    298       }
    299       break;
    300     }
    301     HasError = true;
    302     return 0;
    303   }
    304 
    305   uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) {
    306     if (ObjToVisit.getArch() == Triple::x86_64 &&
    307         Rel == MachO::X86_64_RELOC_UNSIGNED)
    308       return Value;
    309     HasError = true;
    310     return 0;
    311   }
    312 };
    313 
    314 } // end namespace object
    315 } // end namespace llvm
    316 
    317 #endif // LLVM_OBJECT_RELOCVISITOR_H
    318