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