1 //===-- X86MachORelocationInfo.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/MachO.h"
17
18 using namespace llvm;
19 using namespace object;
20 using namespace MachO;
21
22 namespace {
23 class X86_64MachORelocationInfo : public MCRelocationInfo {
24 public:
X86_64MachORelocationInfo(MCContext & Ctx)25 X86_64MachORelocationInfo(MCContext &Ctx) : MCRelocationInfo(Ctx) {}
26
createExprForRelocation(RelocationRef Rel)27 const MCExpr *createExprForRelocation(RelocationRef Rel) override {
28 const MachOObjectFile *Obj = cast<MachOObjectFile>(Rel.getObjectFile());
29
30 uint64_t RelType; Rel.getType(RelType);
31 symbol_iterator SymI = Rel.getSymbol();
32
33 StringRef SymName; SymI->getName(SymName);
34 uint64_t SymAddr; SymI->getAddress(SymAddr);
35
36 any_relocation_info RE = Obj->getRelocation(Rel.getRawDataRefImpl());
37 bool isPCRel = Obj->getAnyRelocationPCRel(RE);
38
39 MCSymbol *Sym = Ctx.GetOrCreateSymbol(SymName);
40 // FIXME: check that the value is actually the same.
41 if (!Sym->isVariable())
42 Sym->setVariableValue(MCConstantExpr::Create(SymAddr, Ctx));
43 const MCExpr *Expr = nullptr;
44
45 switch(RelType) {
46 case X86_64_RELOC_TLV:
47 Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_TLVP, Ctx);
48 break;
49 case X86_64_RELOC_SIGNED_4:
50 Expr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Sym, Ctx),
51 MCConstantExpr::Create(4, Ctx),
52 Ctx);
53 break;
54 case X86_64_RELOC_SIGNED_2:
55 Expr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Sym, Ctx),
56 MCConstantExpr::Create(2, Ctx),
57 Ctx);
58 break;
59 case X86_64_RELOC_SIGNED_1:
60 Expr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Sym, Ctx),
61 MCConstantExpr::Create(1, Ctx),
62 Ctx);
63 break;
64 case X86_64_RELOC_GOT_LOAD:
65 Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOTPCREL, Ctx);
66 break;
67 case X86_64_RELOC_GOT:
68 Expr = MCSymbolRefExpr::Create(Sym, isPCRel ?
69 MCSymbolRefExpr::VK_GOTPCREL :
70 MCSymbolRefExpr::VK_GOT,
71 Ctx);
72 break;
73 case X86_64_RELOC_SUBTRACTOR:
74 {
75 Rel.moveNext();
76 any_relocation_info RENext =
77 Obj->getRelocation(Rel.getRawDataRefImpl());
78
79 // X86_64_SUBTRACTOR must be followed by a relocation of type
80 // X86_64_RELOC_UNSIGNED.
81 // NOTE: Scattered relocations don't exist on x86_64.
82 unsigned RType = Obj->getAnyRelocationType(RENext);
83 if (RType != X86_64_RELOC_UNSIGNED)
84 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
85 "X86_64_RELOC_SUBTRACTOR.");
86
87 const MCExpr *LHS = MCSymbolRefExpr::Create(Sym, Ctx);
88
89 symbol_iterator RSymI = Rel.getSymbol();
90 uint64_t RSymAddr;
91 RSymI->getAddress(RSymAddr);
92 StringRef RSymName;
93 RSymI->getName(RSymName);
94
95 MCSymbol *RSym = Ctx.GetOrCreateSymbol(RSymName);
96 if (!RSym->isVariable())
97 RSym->setVariableValue(MCConstantExpr::Create(RSymAddr, Ctx));
98
99 const MCExpr *RHS = MCSymbolRefExpr::Create(RSym, Ctx);
100
101 Expr = MCBinaryExpr::CreateSub(LHS, RHS, Ctx);
102 break;
103 }
104 default:
105 Expr = MCSymbolRefExpr::Create(Sym, Ctx);
106 break;
107 }
108 return Expr;
109 }
110 };
111 } // End unnamed namespace
112
113 /// createX86_64MachORelocationInfo - Construct an X86-64 Mach-O RelocationInfo.
createX86_64MachORelocationInfo(MCContext & Ctx)114 MCRelocationInfo *llvm::createX86_64MachORelocationInfo(MCContext &Ctx) {
115 return new X86_64MachORelocationInfo(Ctx);
116 }
117