1 //===-- SystemZMCObjectWriter.cpp - SystemZ ELF writer --------------------===// 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/SystemZMCTargetDesc.h" 11 #include "MCTargetDesc/SystemZMCFixups.h" 12 #include "llvm/MC/MCELFObjectWriter.h" 13 #include "llvm/MC/MCExpr.h" 14 #include "llvm/MC/MCValue.h" 15 16 using namespace llvm; 17 18 namespace { 19 class SystemZObjectWriter : public MCELFObjectTargetWriter { 20 public: 21 SystemZObjectWriter(uint8_t OSABI); 22 23 virtual ~SystemZObjectWriter(); 24 25 protected: 26 // Override MCELFObjectTargetWriter. 27 virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 28 bool IsPCRel, bool IsRelocWithSymbol, 29 int64_t Addend) const LLVM_OVERRIDE; 30 virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, 31 const MCValue &Target, 32 const MCFragment &F, 33 const MCFixup &Fixup, 34 bool IsPCRel) const LLVM_OVERRIDE; 35 }; 36 } // end anonymouse namespace 37 38 SystemZObjectWriter::SystemZObjectWriter(uint8_t OSABI) 39 : MCELFObjectTargetWriter(/*Is64Bit=*/true, OSABI, ELF::EM_S390, 40 /*HasRelocationAddend=*/ true) {} 41 42 SystemZObjectWriter::~SystemZObjectWriter() { 43 } 44 45 // Return the relocation type for an absolute value of MCFixupKind Kind. 46 static unsigned getAbsoluteReloc(unsigned Kind) { 47 switch (Kind) { 48 case FK_Data_1: return ELF::R_390_8; 49 case FK_Data_2: return ELF::R_390_16; 50 case FK_Data_4: return ELF::R_390_32; 51 case FK_Data_8: return ELF::R_390_64; 52 } 53 llvm_unreachable("Unsupported absolute address"); 54 } 55 56 // Return the relocation type for a PC-relative value of MCFixupKind Kind. 57 static unsigned getPCRelReloc(unsigned Kind) { 58 switch (Kind) { 59 case FK_Data_2: return ELF::R_390_PC16; 60 case FK_Data_4: return ELF::R_390_PC32; 61 case FK_Data_8: return ELF::R_390_PC64; 62 case SystemZ::FK_390_PC16DBL: return ELF::R_390_PC16DBL; 63 case SystemZ::FK_390_PC32DBL: return ELF::R_390_PC32DBL; 64 case SystemZ::FK_390_PLT16DBL: return ELF::R_390_PLT16DBL; 65 case SystemZ::FK_390_PLT32DBL: return ELF::R_390_PLT32DBL; 66 } 67 llvm_unreachable("Unsupported PC-relative address"); 68 } 69 70 // Return the R_390_TLS_LE* relocation type for MCFixupKind Kind. 71 static unsigned getTLSLEReloc(unsigned Kind) { 72 switch (Kind) { 73 case FK_Data_4: return ELF::R_390_TLS_LE32; 74 case FK_Data_8: return ELF::R_390_TLS_LE64; 75 } 76 llvm_unreachable("Unsupported absolute address"); 77 } 78 79 // Return the PLT relocation counterpart of MCFixupKind Kind. 80 static unsigned getPLTReloc(unsigned Kind) { 81 switch (Kind) { 82 case SystemZ::FK_390_PC16DBL: return ELF::R_390_PLT16DBL; 83 case SystemZ::FK_390_PC32DBL: return ELF::R_390_PLT32DBL; 84 } 85 llvm_unreachable("Unsupported absolute address"); 86 } 87 88 unsigned SystemZObjectWriter::GetRelocType(const MCValue &Target, 89 const MCFixup &Fixup, 90 bool IsPCRel, 91 bool IsRelocWithSymbol, 92 int64_t Addend) const { 93 MCSymbolRefExpr::VariantKind Modifier = (Target.isAbsolute() ? 94 MCSymbolRefExpr::VK_None : 95 Target.getSymA()->getKind()); 96 unsigned Kind = Fixup.getKind(); 97 switch (Modifier) { 98 case MCSymbolRefExpr::VK_None: 99 if (IsPCRel) 100 return getPCRelReloc(Kind); 101 return getAbsoluteReloc(Kind); 102 103 case MCSymbolRefExpr::VK_NTPOFF: 104 assert(!IsPCRel && "NTPOFF shouldn't be PC-relative"); 105 return getTLSLEReloc(Kind); 106 107 case MCSymbolRefExpr::VK_GOT: 108 if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL) 109 return ELF::R_390_GOTENT; 110 llvm_unreachable("Only PC-relative GOT accesses are supported for now"); 111 112 case MCSymbolRefExpr::VK_PLT: 113 assert(IsPCRel && "@PLT shouldt be PC-relative"); 114 return getPLTReloc(Kind); 115 116 default: 117 llvm_unreachable("Modifier not supported"); 118 } 119 } 120 121 const MCSymbol *SystemZObjectWriter::ExplicitRelSym(const MCAssembler &Asm, 122 const MCValue &Target, 123 const MCFragment &F, 124 const MCFixup &Fixup, 125 bool IsPCRel) const { 126 // The addend in a PC-relative R_390_* relocation is always applied to 127 // the PC-relative part of the address. If some kind of indirection 128 // is applied to the symbol first, we can't use an addend there too. 129 if (!Target.isAbsolute() && 130 Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None && 131 IsPCRel) 132 return &Target.getSymA()->getSymbol().AliasedSymbol(); 133 return NULL; 134 } 135 136 MCObjectWriter *llvm::createSystemZObjectWriter(raw_ostream &OS, 137 uint8_t OSABI) { 138 MCELFObjectTargetWriter *MOTW = new SystemZObjectWriter(OSABI); 139 return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false); 140 } 141