1 //===-- X86ELFRelocationInfo.cpp ----------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
20 using namespace object;
24 class X86_64ELFRelocationInfo : public MCRelocationInfo {
26 X86_64ELFRelocationInfo(MCContext &Ctx) : MCRelocationInfo(Ctx) {}
28 const MCExpr *createExprForRelocation(RelocationRef Rel) override {
29 uint64_t RelType = Rel.getType();
30 elf_symbol_iterator SymI = Rel.getSymbol();
32 ErrorOr<StringRef> SymNameOrErr = SymI->getName();
33 if (std::error_code EC = SymNameOrErr.getError())
34 report_fatal_error(EC.message());
35 StringRef SymName = *SymNameOrErr;
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();
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));
48 const MCExpr *Expr = nullptr;
49 // If hasAddend is true, then we need to add Addend (r_addend) to Expr.
50 bool hasAddend = false;
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.
78 // S + A (We don't care about the result not fitting in 32 bits.)
83 // S + A - P (P/pcrel is implicit)
85 Expr = MCSymbolRefExpr::create(Sym, Ctx);
89 case R_X86_64_GOTPC32:
90 case R_X86_64_GOTPC64:
91 case R_X86_64_GOTPLT64:
94 Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOT, Ctx);
97 // L + A - P -> S@PLT + A
99 Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_PLT, Ctx);
101 case R_X86_64_GLOB_DAT:
102 case R_X86_64_JUMP_SLOT:
104 Expr = MCSymbolRefExpr::create(Sym, Ctx);
106 case R_X86_64_GOTPCREL:
107 case R_X86_64_GOTPCREL64:
108 // G + GOT + A - P -> S@GOTPCREL + A
110 Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOTPCREL, Ctx);
112 case R_X86_64_GOTOFF64:
114 Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOTOFF, Ctx);
116 case R_X86_64_PLTOFF64:
119 case R_X86_64_SIZE32:
120 case R_X86_64_SIZE64:
122 Expr = MCConstantExpr::create(SymSize, Ctx);
125 Expr = MCSymbolRefExpr::create(Sym, Ctx);
128 if (Expr && hasAddend && Addend != 0)
129 Expr = MCBinaryExpr::createAdd(Expr,
130 MCConstantExpr::create(Addend, Ctx),
135 } // End unnamed namespace
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);