OSDN Git Service

Update aosp/master LLVM for rebase to r256229
[android-x86/external-llvm.git] / lib / Target / X86 / MCTargetDesc / X86ELFRelocationInfo.cpp
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 }