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