1259698Sdim//===-- X86MachORelocationInfo.cpp ----------------------------------------===// 2259698Sdim// 3259698Sdim// The LLVM Compiler Infrastructure 4259698Sdim// 5259698Sdim// This file is distributed under the University of Illinois Open Source 6259698Sdim// License. See LICENSE.TXT for details. 7259698Sdim// 8259698Sdim//===----------------------------------------------------------------------===// 9259698Sdim 10259698Sdim#include "MCTargetDesc/X86MCTargetDesc.h" 11259698Sdim#include "llvm/MC/MCContext.h" 12259698Sdim#include "llvm/MC/MCExpr.h" 13259698Sdim#include "llvm/MC/MCInst.h" 14259698Sdim#include "llvm/MC/MCSymbol.h" 15259698Sdim#include "llvm/MC/MCRelocationInfo.h" 16259698Sdim#include "llvm/Object/MachO.h" 17259698Sdim 18259698Sdimusing namespace llvm; 19259698Sdimusing namespace object; 20259698Sdimusing namespace MachO; 21259698Sdim 22259698Sdimnamespace { 23259698Sdimclass X86_64MachORelocationInfo : public MCRelocationInfo { 24259698Sdimpublic: 25259698Sdim X86_64MachORelocationInfo(MCContext &Ctx) : MCRelocationInfo(Ctx) {} 26259698Sdim 27259698Sdim const MCExpr *createExprForRelocation(RelocationRef Rel) { 28259698Sdim const MachOObjectFile *Obj = cast<MachOObjectFile>(Rel.getObjectFile()); 29259698Sdim 30259698Sdim uint64_t RelType; Rel.getType(RelType); 31259698Sdim symbol_iterator SymI = Rel.getSymbol(); 32259698Sdim 33259698Sdim StringRef SymName; SymI->getName(SymName); 34259698Sdim uint64_t SymAddr; SymI->getAddress(SymAddr); 35259698Sdim 36259698Sdim any_relocation_info RE = Obj->getRelocation(Rel.getRawDataRefImpl()); 37259698Sdim bool isPCRel = Obj->getAnyRelocationPCRel(RE); 38259698Sdim 39259698Sdim MCSymbol *Sym = Ctx.GetOrCreateSymbol(SymName); 40259698Sdim // FIXME: check that the value is actually the same. 41259698Sdim if (Sym->isVariable() == false) 42259698Sdim Sym->setVariableValue(MCConstantExpr::Create(SymAddr, Ctx)); 43259698Sdim const MCExpr *Expr = 0; 44259698Sdim 45259698Sdim switch(RelType) { 46259698Sdim case X86_64_RELOC_TLV: 47259698Sdim Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_TLVP, Ctx); 48259698Sdim break; 49259698Sdim case X86_64_RELOC_SIGNED_4: 50259698Sdim Expr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Sym, Ctx), 51259698Sdim MCConstantExpr::Create(4, Ctx), 52259698Sdim Ctx); 53259698Sdim break; 54259698Sdim case X86_64_RELOC_SIGNED_2: 55259698Sdim Expr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Sym, Ctx), 56259698Sdim MCConstantExpr::Create(2, Ctx), 57259698Sdim Ctx); 58259698Sdim break; 59259698Sdim case X86_64_RELOC_SIGNED_1: 60259698Sdim Expr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Sym, Ctx), 61259698Sdim MCConstantExpr::Create(1, Ctx), 62259698Sdim Ctx); 63259698Sdim break; 64259698Sdim case X86_64_RELOC_GOT_LOAD: 65259698Sdim Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOTPCREL, Ctx); 66259698Sdim break; 67259698Sdim case X86_64_RELOC_GOT: 68259698Sdim Expr = MCSymbolRefExpr::Create(Sym, isPCRel ? 69259698Sdim MCSymbolRefExpr::VK_GOTPCREL : 70259698Sdim MCSymbolRefExpr::VK_GOT, 71259698Sdim Ctx); 72259698Sdim break; 73259698Sdim case X86_64_RELOC_SUBTRACTOR: 74259698Sdim { 75259698Sdim RelocationRef RelNext; 76259698Sdim Obj->getRelocationNext(Rel.getRawDataRefImpl(), RelNext); 77259698Sdim any_relocation_info RENext = Obj->getRelocation(RelNext.getRawDataRefImpl()); 78259698Sdim 79259698Sdim // X86_64_SUBTRACTOR must be followed by a relocation of type 80259698Sdim // X86_64_RELOC_UNSIGNED. 81259698Sdim // NOTE: Scattered relocations don't exist on x86_64. 82259698Sdim unsigned RType = Obj->getAnyRelocationType(RENext); 83259698Sdim if (RType != X86_64_RELOC_UNSIGNED) 84259698Sdim report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " 85259698Sdim "X86_64_RELOC_SUBTRACTOR."); 86259698Sdim 87259698Sdim const MCExpr *LHS = MCSymbolRefExpr::Create(Sym, Ctx); 88259698Sdim 89259698Sdim symbol_iterator RSymI = RelNext.getSymbol(); 90259698Sdim uint64_t RSymAddr; 91259698Sdim RSymI->getAddress(RSymAddr); 92259698Sdim StringRef RSymName; 93259698Sdim RSymI->getName(RSymName); 94259698Sdim 95259698Sdim MCSymbol *RSym = Ctx.GetOrCreateSymbol(RSymName); 96259698Sdim if (RSym->isVariable() == false) 97259698Sdim RSym->setVariableValue(MCConstantExpr::Create(RSymAddr, Ctx)); 98259698Sdim 99259698Sdim const MCExpr *RHS = MCSymbolRefExpr::Create(RSym, Ctx); 100259698Sdim 101259698Sdim Expr = MCBinaryExpr::CreateSub(LHS, RHS, Ctx); 102259698Sdim break; 103259698Sdim } 104259698Sdim default: 105259698Sdim Expr = MCSymbolRefExpr::Create(Sym, Ctx); 106259698Sdim break; 107259698Sdim } 108259698Sdim return Expr; 109259698Sdim } 110259698Sdim}; 111259698Sdim} // End unnamed namespace 112259698Sdim 113259698Sdim/// createX86_64MachORelocationInfo - Construct an X86-64 Mach-O RelocationInfo. 114259698SdimMCRelocationInfo *llvm::createX86_64MachORelocationInfo(MCContext &Ctx) { 115259698Sdim return new X86_64MachORelocationInfo(Ctx); 116259698Sdim} 117