LLVM API Documentation
00001 //===-- X86ELFRelocationInfo.cpp ----------------------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "MCTargetDesc/X86MCTargetDesc.h" 00011 #include "llvm/MC/MCContext.h" 00012 #include "llvm/MC/MCExpr.h" 00013 #include "llvm/MC/MCInst.h" 00014 #include "llvm/MC/MCRelocationInfo.h" 00015 #include "llvm/MC/MCSymbol.h" 00016 #include "llvm/Object/ELFObjectFile.h" 00017 #include "llvm/Support/ELF.h" 00018 00019 using namespace llvm; 00020 using namespace object; 00021 using namespace ELF; 00022 00023 namespace { 00024 class X86_64ELFRelocationInfo : public MCRelocationInfo { 00025 public: 00026 X86_64ELFRelocationInfo(MCContext &Ctx) : MCRelocationInfo(Ctx) {} 00027 00028 const MCExpr *createExprForRelocation(RelocationRef Rel) override { 00029 uint64_t RelType; Rel.getType(RelType); 00030 symbol_iterator SymI = Rel.getSymbol(); 00031 00032 StringRef SymName; SymI->getName(SymName); 00033 uint64_t SymAddr; SymI->getAddress(SymAddr); 00034 uint64_t SymSize; SymI->getSize(SymSize); 00035 int64_t Addend; getELFRelocationAddend(Rel, Addend); 00036 00037 MCSymbol *Sym = Ctx.GetOrCreateSymbol(SymName); 00038 // FIXME: check that the value is actually the same. 00039 if (Sym->isVariable() == false) 00040 Sym->setVariableValue(MCConstantExpr::Create(SymAddr, Ctx)); 00041 00042 const MCExpr *Expr = nullptr; 00043 // If hasAddend is true, then we need to add Addend (r_addend) to Expr. 00044 bool hasAddend = false; 00045 00046 // The AMD64 SysV ABI says: 00047 // A: the addend used to compute the value of the relocatable field. 00048 // B: the base address at which a shared object has been loaded into memory 00049 // during execution. Generally, a shared object is built with a 0 base 00050 // virtual address, but the execution address will be different. 00051 // G: the offset into the global offset table at which the relocation 00052 // entry's symbol will reside during execution. 00053 // GOT: the address of the global offset table. 00054 // L: the place (section offset or address) of the Procedure Linkage Table 00055 // entry for a symbol. 00056 // P: the place (section offset or address) of the storage unit being 00057 // relocated (computed using r_offset). 00058 // S: the value of the symbol whose index resides in the relocation entry. 00059 // Z: the size of the symbol whose index resides in the relocation entry. 00060 00061 switch(RelType) { 00062 case R_X86_64_NONE: 00063 case R_X86_64_COPY: 00064 // none 00065 break; 00066 case R_X86_64_64: 00067 case R_X86_64_16: 00068 case R_X86_64_8: 00069 // S + A 00070 case R_X86_64_32: 00071 case R_X86_64_32S: 00072 // S + A (We don't care about the result not fitting in 32 bits.) 00073 case R_X86_64_PC32: 00074 case R_X86_64_PC16: 00075 case R_X86_64_PC8: 00076 case R_X86_64_PC64: 00077 // S + A - P (P/pcrel is implicit) 00078 hasAddend = true; 00079 Expr = MCSymbolRefExpr::Create(Sym, Ctx); 00080 break; 00081 case R_X86_64_GOT32: 00082 case R_X86_64_GOT64: 00083 case R_X86_64_GOTPC32: 00084 case R_X86_64_GOTPC64: 00085 case R_X86_64_GOTPLT64: 00086 // G + A 00087 hasAddend = true; 00088 Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOT, Ctx); 00089 break; 00090 case R_X86_64_PLT32: 00091 // L + A - P -> S@PLT + A 00092 hasAddend = true; 00093 Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_PLT, Ctx); 00094 break; 00095 case R_X86_64_GLOB_DAT: 00096 case R_X86_64_JUMP_SLOT: 00097 // S 00098 Expr = MCSymbolRefExpr::Create(Sym, Ctx); 00099 break; 00100 case R_X86_64_GOTPCREL: 00101 case R_X86_64_GOTPCREL64: 00102 // G + GOT + A - P -> S@GOTPCREL + A 00103 hasAddend = true; 00104 Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOTPCREL, Ctx); 00105 break; 00106 case R_X86_64_GOTOFF64: 00107 // S + A - GOT 00108 Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOTOFF, Ctx); 00109 break; 00110 case R_X86_64_PLTOFF64: 00111 // L + A - GOT 00112 break; 00113 case R_X86_64_SIZE32: 00114 case R_X86_64_SIZE64: 00115 // Z + A 00116 Expr = MCConstantExpr::Create(SymSize, Ctx); 00117 break; 00118 default: 00119 Expr = MCSymbolRefExpr::Create(Sym, Ctx); 00120 break; 00121 } 00122 if (Expr && hasAddend && Addend != 0) 00123 Expr = MCBinaryExpr::CreateAdd(Expr, 00124 MCConstantExpr::Create(Addend, Ctx), 00125 Ctx); 00126 return Expr; 00127 } 00128 }; 00129 } // End unnamed namespace 00130 00131 /// createX86ELFRelocationInfo - Construct an X86 Mach-O RelocationInfo. 00132 MCRelocationInfo *llvm::createX86_64ELFRelocationInfo(MCContext &Ctx) { 00133 // We only handle x86-64 for now. 00134 return new X86_64ELFRelocationInfo(Ctx); 00135 }