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