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