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