12c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha//===-- X86MachORelocationInfo.cpp ----------------------------------------===//
22c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha//
32c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha//                     The LLVM Compiler Infrastructure
42c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha//
52c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha// This file is distributed under the University of Illinois Open Source
62c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha// License. See LICENSE.TXT for details.
72c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha//
82c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha//===----------------------------------------------------------------------===//
92c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
102c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha#include "MCTargetDesc/X86MCTargetDesc.h"
112c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha#include "llvm/MC/MCContext.h"
122c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha#include "llvm/MC/MCExpr.h"
132c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha#include "llvm/MC/MCInst.h"
142c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha#include "llvm/MC/MCRelocationInfo.h"
1536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/MC/MCSymbol.h"
162c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha#include "llvm/Object/MachO.h"
172c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
182c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougachausing namespace llvm;
192c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougachausing namespace object;
205510728d28bb1ee04abc32da3d21b7df12948053Charles Davisusing namespace MachO;
212c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
222c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougachanamespace {
232c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougachaclass X86_64MachORelocationInfo : public MCRelocationInfo {
242c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougachapublic:
252c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha  X86_64MachORelocationInfo(MCContext &Ctx) : MCRelocationInfo(Ctx) {}
262c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
2736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  const MCExpr *createExprForRelocation(RelocationRef Rel) override {
282c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    const MachOObjectFile *Obj = cast<MachOObjectFile>(Rel.getObjectFile());
292c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
302c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    uint64_t RelType; Rel.getType(RelType);
316c1202c459ffa6d693ad92fa84e43902bc780bcaRafael Espindola    symbol_iterator SymI = Rel.getSymbol();
322c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
336c1202c459ffa6d693ad92fa84e43902bc780bcaRafael Espindola    StringRef SymName; SymI->getName(SymName);
346c1202c459ffa6d693ad92fa84e43902bc780bcaRafael Espindola    uint64_t  SymAddr; SymI->getAddress(SymAddr);
352c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
365510728d28bb1ee04abc32da3d21b7df12948053Charles Davis    any_relocation_info RE = Obj->getRelocation(Rel.getRawDataRefImpl());
372c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    bool isPCRel = Obj->getAnyRelocationPCRel(RE);
382c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
392c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    MCSymbol *Sym = Ctx.GetOrCreateSymbol(SymName);
402c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    // FIXME: check that the value is actually the same.
412c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    if (Sym->isVariable() == false)
422c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      Sym->setVariableValue(MCConstantExpr::Create(SymAddr, Ctx));
43dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    const MCExpr *Expr = nullptr;
442c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
452c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    switch(RelType) {
465510728d28bb1ee04abc32da3d21b7df12948053Charles Davis    case X86_64_RELOC_TLV:
472c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_TLVP, Ctx);
482c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      break;
495510728d28bb1ee04abc32da3d21b7df12948053Charles Davis    case X86_64_RELOC_SIGNED_4:
502c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      Expr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Sym, Ctx),
512c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha                                     MCConstantExpr::Create(4, Ctx),
522c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha                                     Ctx);
532c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      break;
545510728d28bb1ee04abc32da3d21b7df12948053Charles Davis    case X86_64_RELOC_SIGNED_2:
552c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      Expr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Sym, Ctx),
562c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha                                     MCConstantExpr::Create(2, Ctx),
572c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha                                     Ctx);
582c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      break;
595510728d28bb1ee04abc32da3d21b7df12948053Charles Davis    case X86_64_RELOC_SIGNED_1:
602c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      Expr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Sym, Ctx),
612c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha                                     MCConstantExpr::Create(1, Ctx),
622c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha                                     Ctx);
632c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      break;
645510728d28bb1ee04abc32da3d21b7df12948053Charles Davis    case X86_64_RELOC_GOT_LOAD:
652c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOTPCREL, Ctx);
662c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      break;
675510728d28bb1ee04abc32da3d21b7df12948053Charles Davis    case X86_64_RELOC_GOT:
682c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      Expr = MCSymbolRefExpr::Create(Sym, isPCRel ?
692c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha                                     MCSymbolRefExpr::VK_GOTPCREL :
702c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha                                     MCSymbolRefExpr::VK_GOT,
712c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha                                     Ctx);
722c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      break;
735510728d28bb1ee04abc32da3d21b7df12948053Charles Davis    case X86_64_RELOC_SUBTRACTOR:
742c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      {
7536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        Rel.moveNext();
7636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        any_relocation_info RENext =
7736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            Obj->getRelocation(Rel.getRawDataRefImpl());
782c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
792c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha        // X86_64_SUBTRACTOR must be followed by a relocation of type
805510728d28bb1ee04abc32da3d21b7df12948053Charles Davis        // X86_64_RELOC_UNSIGNED.
812c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha        // NOTE: Scattered relocations don't exist on x86_64.
822c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha        unsigned RType = Obj->getAnyRelocationType(RENext);
835510728d28bb1ee04abc32da3d21b7df12948053Charles Davis        if (RType != X86_64_RELOC_UNSIGNED)
842c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha          report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
852c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha                             "X86_64_RELOC_SUBTRACTOR.");
862c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
872c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha        const MCExpr *LHS = MCSymbolRefExpr::Create(Sym, Ctx);
882c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
8936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        symbol_iterator RSymI = Rel.getSymbol();
902c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha        uint64_t RSymAddr;
916c1202c459ffa6d693ad92fa84e43902bc780bcaRafael Espindola        RSymI->getAddress(RSymAddr);
922c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha        StringRef RSymName;
936c1202c459ffa6d693ad92fa84e43902bc780bcaRafael Espindola        RSymI->getName(RSymName);
942c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
952c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha        MCSymbol *RSym = Ctx.GetOrCreateSymbol(RSymName);
962c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha        if (RSym->isVariable() == false)
972c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha          RSym->setVariableValue(MCConstantExpr::Create(RSymAddr, Ctx));
982c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
992c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha        const MCExpr *RHS = MCSymbolRefExpr::Create(RSym, Ctx);
1002c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
1012c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha        Expr = MCBinaryExpr::CreateSub(LHS, RHS, Ctx);
1022c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha        break;
1032c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      }
1042c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    default:
1052c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      Expr = MCSymbolRefExpr::Create(Sym, Ctx);
1062c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      break;
1072c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    }
1082c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    return Expr;
1092c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha  }
1102c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha};
1112c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha} // End unnamed namespace
1122c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
1132c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha/// createX86_64MachORelocationInfo - Construct an X86-64 Mach-O RelocationInfo.
1142c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed BougachaMCRelocationInfo *llvm::createX86_64MachORelocationInfo(MCContext &Ctx) {
1152c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha  return new X86_64MachORelocationInfo(Ctx);
1162c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha}
117