Home | History | Annotate | Download | only in MCTargetDesc
      1 //===-- X86ELFRelocationInfo.cpp ----------------------------------------===//
      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 #include "MCTargetDesc/X86MCTargetDesc.h"
     11 #include "llvm/MC/MCContext.h"
     12 #include "llvm/MC/MCExpr.h"
     13 #include "llvm/MC/MCInst.h"
     14 #include "llvm/MC/MCRelocationInfo.h"
     15 #include "llvm/MC/MCSymbol.h"
     16 #include "llvm/Object/ELFObjectFile.h"
     17 #include "llvm/Support/ELF.h"
     18 
     19 using namespace llvm;
     20 using namespace object;
     21 using namespace ELF;
     22 
     23 namespace {
     24 class X86_64ELFRelocationInfo : public MCRelocationInfo {
     25 public:
     26   X86_64ELFRelocationInfo(MCContext &Ctx) : MCRelocationInfo(Ctx) {}
     27 
     28   const MCExpr *createExprForRelocation(RelocationRef Rel) override {
     29     uint64_t RelType = Rel.getType();
     30     elf_symbol_iterator SymI = Rel.getSymbol();
     31 
     32     ErrorOr<StringRef> SymNameOrErr = SymI->getName();
     33     if (std::error_code EC = SymNameOrErr.getError())
     34       report_fatal_error(EC.message());
     35     StringRef SymName = *SymNameOrErr;
     36 
     37     ErrorOr<uint64_t> SymAddr = SymI->getAddress();
     38     if (std::error_code EC = SymAddr.getError())
     39       report_fatal_error(EC.message());
     40     uint64_t SymSize = SymI->getSize();
     41     int64_t Addend = *ELFRelocationRef(Rel).getAddend();
     42 
     43     MCSymbol *Sym = Ctx.getOrCreateSymbol(SymName);
     44     // FIXME: check that the value is actually the same.
     45     if (!Sym->isVariable())
     46       Sym->setVariableValue(MCConstantExpr::create(*SymAddr, Ctx));
     47 
     48     const MCExpr *Expr = nullptr;
     49     // If hasAddend is true, then we need to add Addend (r_addend) to Expr.
     50     bool hasAddend = false;
     51 
     52     // The AMD64 SysV ABI says:
     53     // A: the addend used to compute the value of the relocatable field.
     54     // B: the base address at which a shared object has been loaded into memory
     55     //    during execution. Generally, a shared object is built with a 0 base
     56     //    virtual address, but the execution address will be different.
     57     // G: the offset into the global offset table at which the relocation
     58     //    entry's symbol will reside during execution.
     59     // GOT: the address of the global offset table.
     60     // L: the place (section offset or address) of the Procedure Linkage Table
     61     //    entry for a symbol.
     62     // P: the place (section offset or address) of the storage unit being
     63     //    relocated (computed using r_offset).
     64     // S: the value of the symbol whose index resides in the relocation entry.
     65     // Z: the size of the symbol whose index resides in the relocation entry.
     66 
     67     switch(RelType) {
     68     case R_X86_64_NONE:
     69     case R_X86_64_COPY:
     70       // none
     71       break;
     72     case R_X86_64_64:
     73     case R_X86_64_16:
     74     case R_X86_64_8:
     75       // S + A
     76     case R_X86_64_32:
     77     case R_X86_64_32S:
     78       // S + A (We don't care about the result not fitting in 32 bits.)
     79     case R_X86_64_PC32:
     80     case R_X86_64_PC16:
     81     case R_X86_64_PC8:
     82     case R_X86_64_PC64:
     83       // S + A - P (P/pcrel is implicit)
     84       hasAddend = true;
     85       Expr = MCSymbolRefExpr::create(Sym, Ctx);
     86       break;
     87     case R_X86_64_GOT32:
     88     case R_X86_64_GOT64:
     89     case R_X86_64_GOTPC32:
     90     case R_X86_64_GOTPC64:
     91     case R_X86_64_GOTPLT64:
     92       // G + A
     93       hasAddend = true;
     94       Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOT, Ctx);
     95       break;
     96     case R_X86_64_PLT32:
     97       // L + A - P -> S@PLT + A
     98       hasAddend = true;
     99       Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_PLT, Ctx);
    100       break;
    101     case R_X86_64_GLOB_DAT:
    102     case R_X86_64_JUMP_SLOT:
    103       // S
    104       Expr = MCSymbolRefExpr::create(Sym, Ctx);
    105       break;
    106     case R_X86_64_GOTPCREL:
    107     case R_X86_64_GOTPCREL64:
    108       // G + GOT + A - P -> S@GOTPCREL + A
    109       hasAddend = true;
    110       Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOTPCREL, Ctx);
    111       break;
    112     case R_X86_64_GOTOFF64:
    113       // S + A - GOT
    114       Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOTOFF, Ctx);
    115       break;
    116     case R_X86_64_PLTOFF64:
    117       // L + A - GOT
    118       break;
    119     case R_X86_64_SIZE32:
    120     case R_X86_64_SIZE64:
    121       // Z + A
    122       Expr = MCConstantExpr::create(SymSize, Ctx);
    123       break;
    124     default:
    125       Expr = MCSymbolRefExpr::create(Sym, Ctx);
    126       break;
    127     }
    128     if (Expr && hasAddend && Addend != 0)
    129       Expr = MCBinaryExpr::createAdd(Expr,
    130                                      MCConstantExpr::create(Addend, Ctx),
    131                                      Ctx);
    132     return Expr;
    133   }
    134 };
    135 } // End unnamed namespace
    136 
    137 /// createX86ELFRelocationInfo - Construct an X86 Mach-O RelocationInfo.
    138 MCRelocationInfo *llvm::createX86_64ELFRelocationInfo(MCContext &Ctx) {
    139   // We only handle x86-64 for now.
    140   return new X86_64ELFRelocationInfo(Ctx);
    141 }
    142