12c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha//===-- X86ELFRelocationInfo.cpp ----------------------------------------===// 22c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha// 32c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha// The LLVM Compiler Infrastructure 42c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha// 52c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha// This file is distributed under the University of Illinois Open Source 62c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha// License. See LICENSE.TXT for details. 72c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha// 82c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha//===----------------------------------------------------------------------===// 92c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha 102c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha#include "MCTargetDesc/X86MCTargetDesc.h" 112c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha#include "llvm/MC/MCContext.h" 122c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha#include "llvm/MC/MCExpr.h" 132c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha#include "llvm/MC/MCInst.h" 142c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha#include "llvm/MC/MCRelocationInfo.h" 1536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/MC/MCSymbol.h" 16081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer#include "llvm/Object/ELFObjectFile.h" 172c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha#include "llvm/Support/ELF.h" 182c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha 192c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougachausing namespace llvm; 202c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougachausing namespace object; 212c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougachausing namespace ELF; 222c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha 232c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougachanamespace { 242c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougachaclass X86_64ELFRelocationInfo : public MCRelocationInfo { 252c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougachapublic: 262c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha X86_64ELFRelocationInfo(MCContext &Ctx) : MCRelocationInfo(Ctx) {} 272c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha 2836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const MCExpr *createExprForRelocation(RelocationRef Rel) override { 292c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha uint64_t RelType; Rel.getType(RelType); 306c1202c459ffa6d693ad92fa84e43902bc780bcaRafael Espindola symbol_iterator SymI = Rel.getSymbol(); 312c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha 326c1202c459ffa6d693ad92fa84e43902bc780bcaRafael Espindola StringRef SymName; SymI->getName(SymName); 336c1202c459ffa6d693ad92fa84e43902bc780bcaRafael Espindola uint64_t SymAddr; SymI->getAddress(SymAddr); 346c1202c459ffa6d693ad92fa84e43902bc780bcaRafael Espindola uint64_t SymSize; SymI->getSize(SymSize); 352c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha int64_t Addend; getELFRelocationAddend(Rel, Addend); 362c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha 372c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha MCSymbol *Sym = Ctx.GetOrCreateSymbol(SymName); 382c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // FIXME: check that the value is actually the same. 392c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha if (Sym->isVariable() == false) 402c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha Sym->setVariableValue(MCConstantExpr::Create(SymAddr, Ctx)); 412c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha 42dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const MCExpr *Expr = nullptr; 432c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // If hasAddend is true, then we need to add Addend (r_addend) to Expr. 442c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha bool hasAddend = false; 452c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha 462c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // The AMD64 SysV ABI says: 472c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // A: the addend used to compute the value of the relocatable field. 482c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // B: the base address at which a shared object has been loaded into memory 492c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // during execution. Generally, a shared object is built with a 0 base 502c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // virtual address, but the execution address will be different. 512c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // G: the offset into the global offset table at which the relocation 522c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // entry's symbol will reside during execution. 532c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // GOT: the address of the global offset table. 542c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // L: the place (section offset or address) of the Procedure Linkage Table 552c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // entry for a symbol. 562c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // P: the place (section offset or address) of the storage unit being 572c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // relocated (computed using r_offset). 582c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // S: the value of the symbol whose index resides in the relocation entry. 592c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // Z: the size of the symbol whose index resides in the relocation entry. 602c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha 612c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha switch(RelType) { 622c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_NONE: 632c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_COPY: 642c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // none 652c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha break; 662c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_64: 672c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_16: 682c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_8: 692c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // S + A 702c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_32: 712c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_32S: 722c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // S + A (We don't care about the result not fitting in 32 bits.) 732c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_PC32: 742c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_PC16: 752c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_PC8: 762c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_PC64: 772c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // S + A - P (P/pcrel is implicit) 782c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha hasAddend = true; 792c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha Expr = MCSymbolRefExpr::Create(Sym, Ctx); 802c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha break; 812c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_GOT32: 822c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_GOT64: 832c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_GOTPC32: 842c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_GOTPC64: 852c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_GOTPLT64: 862c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // G + A 872c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha hasAddend = true; 882c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOT, Ctx); 892c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha break; 902c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_PLT32: 912c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // L + A - P -> S@PLT + A 922c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha hasAddend = true; 932c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_PLT, Ctx); 942c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha break; 952c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_GLOB_DAT: 962c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_JUMP_SLOT: 972c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // S 982c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha Expr = MCSymbolRefExpr::Create(Sym, Ctx); 992c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha break; 1002c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_GOTPCREL: 1012c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_GOTPCREL64: 1022c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // G + GOT + A - P -> S@GOTPCREL + A 1032c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha hasAddend = true; 1042c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOTPCREL, Ctx); 1052c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha break; 1062c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_GOTOFF64: 1072c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // S + A - GOT 1082c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOTOFF, Ctx); 1092c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha break; 1102c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_PLTOFF64: 1112c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // L + A - GOT 1122c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha break; 1132c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_SIZE32: 1142c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha case R_X86_64_SIZE64: 1152c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // Z + A 1162c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha Expr = MCConstantExpr::Create(SymSize, Ctx); 1172c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha break; 1182c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha default: 1192c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha Expr = MCSymbolRefExpr::Create(Sym, Ctx); 1202c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha break; 1212c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha } 1222c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha if (Expr && hasAddend && Addend != 0) 1232c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha Expr = MCBinaryExpr::CreateAdd(Expr, 1242c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha MCConstantExpr::Create(Addend, Ctx), 1252c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha Ctx); 1262c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha return Expr; 1272c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha } 1282c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha}; 1292c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha} // End unnamed namespace 1302c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha 1312c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha/// createX86ELFRelocationInfo - Construct an X86 Mach-O RelocationInfo. 1322c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed BougachaMCRelocationInfo *llvm::createX86_64ELFRelocationInfo(MCContext &Ctx) { 1332c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha // We only handle x86-64 for now. 1342c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha return new X86_64ELFRelocationInfo(Ctx); 1352c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha} 136