15f613dfdSUlrich Weigand //===-- SystemZMCObjectWriter.cpp - SystemZ ELF writer --------------------===// 25f613dfdSUlrich Weigand // 35f613dfdSUlrich Weigand // The LLVM Compiler Infrastructure 45f613dfdSUlrich Weigand // 55f613dfdSUlrich Weigand // This file is distributed under the University of Illinois Open Source 65f613dfdSUlrich Weigand // License. See LICENSE.TXT for details. 75f613dfdSUlrich Weigand // 85f613dfdSUlrich Weigand //===----------------------------------------------------------------------===// 95f613dfdSUlrich Weigand 105f613dfdSUlrich Weigand #include "MCTargetDesc/SystemZMCTargetDesc.h" 115f613dfdSUlrich Weigand #include "MCTargetDesc/SystemZMCFixups.h" 125f613dfdSUlrich Weigand #include "llvm/MC/MCELFObjectWriter.h" 135f613dfdSUlrich Weigand #include "llvm/MC/MCExpr.h" 145f613dfdSUlrich Weigand #include "llvm/MC/MCValue.h" 155f613dfdSUlrich Weigand 165f613dfdSUlrich Weigand using namespace llvm; 175f613dfdSUlrich Weigand 185f613dfdSUlrich Weigand namespace { 195f613dfdSUlrich Weigand class SystemZObjectWriter : public MCELFObjectTargetWriter { 205f613dfdSUlrich Weigand public: 215f613dfdSUlrich Weigand SystemZObjectWriter(uint8_t OSABI); 225f613dfdSUlrich Weigand 235f613dfdSUlrich Weigand virtual ~SystemZObjectWriter(); 245f613dfdSUlrich Weigand 255f613dfdSUlrich Weigand protected: 265f613dfdSUlrich Weigand // Override MCELFObjectTargetWriter. 27*b4d67b59SRichard Sandiford unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 285f613dfdSUlrich Weigand bool IsPCRel, bool IsRelocWithSymbol, 2973156025SCraig Topper int64_t Addend) const override; 30*b4d67b59SRichard Sandiford const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, const MCValue &Target, 31*b4d67b59SRichard Sandiford const MCFragment &F, const MCFixup &Fixup, 3273156025SCraig Topper bool IsPCRel) const override; 335f613dfdSUlrich Weigand }; 34c231269fSRichard Sandiford } // end anonymous namespace 355f613dfdSUlrich Weigand 365f613dfdSUlrich Weigand SystemZObjectWriter::SystemZObjectWriter(uint8_t OSABI) 375f613dfdSUlrich Weigand : MCELFObjectTargetWriter(/*Is64Bit=*/true, OSABI, ELF::EM_S390, 385f613dfdSUlrich Weigand /*HasRelocationAddend=*/ true) {} 395f613dfdSUlrich Weigand 405f613dfdSUlrich Weigand SystemZObjectWriter::~SystemZObjectWriter() { 415f613dfdSUlrich Weigand } 425f613dfdSUlrich Weigand 435f613dfdSUlrich Weigand // Return the relocation type for an absolute value of MCFixupKind Kind. 445f613dfdSUlrich Weigand static unsigned getAbsoluteReloc(unsigned Kind) { 455f613dfdSUlrich Weigand switch (Kind) { 465f613dfdSUlrich Weigand case FK_Data_1: return ELF::R_390_8; 475f613dfdSUlrich Weigand case FK_Data_2: return ELF::R_390_16; 485f613dfdSUlrich Weigand case FK_Data_4: return ELF::R_390_32; 495f613dfdSUlrich Weigand case FK_Data_8: return ELF::R_390_64; 505f613dfdSUlrich Weigand } 515f613dfdSUlrich Weigand llvm_unreachable("Unsupported absolute address"); 525f613dfdSUlrich Weigand } 535f613dfdSUlrich Weigand 545f613dfdSUlrich Weigand // Return the relocation type for a PC-relative value of MCFixupKind Kind. 555f613dfdSUlrich Weigand static unsigned getPCRelReloc(unsigned Kind) { 565f613dfdSUlrich Weigand switch (Kind) { 575f613dfdSUlrich Weigand case FK_Data_2: return ELF::R_390_PC16; 585f613dfdSUlrich Weigand case FK_Data_4: return ELF::R_390_PC32; 595f613dfdSUlrich Weigand case FK_Data_8: return ELF::R_390_PC64; 605f613dfdSUlrich Weigand case SystemZ::FK_390_PC16DBL: return ELF::R_390_PC16DBL; 615f613dfdSUlrich Weigand case SystemZ::FK_390_PC32DBL: return ELF::R_390_PC32DBL; 625f613dfdSUlrich Weigand case SystemZ::FK_390_PLT16DBL: return ELF::R_390_PLT16DBL; 635f613dfdSUlrich Weigand case SystemZ::FK_390_PLT32DBL: return ELF::R_390_PLT32DBL; 645f613dfdSUlrich Weigand } 655f613dfdSUlrich Weigand llvm_unreachable("Unsupported PC-relative address"); 665f613dfdSUlrich Weigand } 675f613dfdSUlrich Weigand 685f613dfdSUlrich Weigand // Return the R_390_TLS_LE* relocation type for MCFixupKind Kind. 695f613dfdSUlrich Weigand static unsigned getTLSLEReloc(unsigned Kind) { 705f613dfdSUlrich Weigand switch (Kind) { 715f613dfdSUlrich Weigand case FK_Data_4: return ELF::R_390_TLS_LE32; 725f613dfdSUlrich Weigand case FK_Data_8: return ELF::R_390_TLS_LE64; 735f613dfdSUlrich Weigand } 745f613dfdSUlrich Weigand llvm_unreachable("Unsupported absolute address"); 755f613dfdSUlrich Weigand } 765f613dfdSUlrich Weigand 775f613dfdSUlrich Weigand // Return the PLT relocation counterpart of MCFixupKind Kind. 785f613dfdSUlrich Weigand static unsigned getPLTReloc(unsigned Kind) { 795f613dfdSUlrich Weigand switch (Kind) { 805f613dfdSUlrich Weigand case SystemZ::FK_390_PC16DBL: return ELF::R_390_PLT16DBL; 815f613dfdSUlrich Weigand case SystemZ::FK_390_PC32DBL: return ELF::R_390_PLT32DBL; 825f613dfdSUlrich Weigand } 835f613dfdSUlrich Weigand llvm_unreachable("Unsupported absolute address"); 845f613dfdSUlrich Weigand } 855f613dfdSUlrich Weigand 865f613dfdSUlrich Weigand unsigned SystemZObjectWriter::GetRelocType(const MCValue &Target, 875f613dfdSUlrich Weigand const MCFixup &Fixup, 885f613dfdSUlrich Weigand bool IsPCRel, 895f613dfdSUlrich Weigand bool IsRelocWithSymbol, 905f613dfdSUlrich Weigand int64_t Addend) const { 915f613dfdSUlrich Weigand MCSymbolRefExpr::VariantKind Modifier = (Target.isAbsolute() ? 925f613dfdSUlrich Weigand MCSymbolRefExpr::VK_None : 935f613dfdSUlrich Weigand Target.getSymA()->getKind()); 945f613dfdSUlrich Weigand unsigned Kind = Fixup.getKind(); 955f613dfdSUlrich Weigand switch (Modifier) { 965f613dfdSUlrich Weigand case MCSymbolRefExpr::VK_None: 975f613dfdSUlrich Weigand if (IsPCRel) 985f613dfdSUlrich Weigand return getPCRelReloc(Kind); 995f613dfdSUlrich Weigand return getAbsoluteReloc(Kind); 1005f613dfdSUlrich Weigand 1015f613dfdSUlrich Weigand case MCSymbolRefExpr::VK_NTPOFF: 1025f613dfdSUlrich Weigand assert(!IsPCRel && "NTPOFF shouldn't be PC-relative"); 1035f613dfdSUlrich Weigand return getTLSLEReloc(Kind); 1045f613dfdSUlrich Weigand 1055f613dfdSUlrich Weigand case MCSymbolRefExpr::VK_GOT: 1065f613dfdSUlrich Weigand if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL) 1075f613dfdSUlrich Weigand return ELF::R_390_GOTENT; 1085f613dfdSUlrich Weigand llvm_unreachable("Only PC-relative GOT accesses are supported for now"); 1095f613dfdSUlrich Weigand 1105f613dfdSUlrich Weigand case MCSymbolRefExpr::VK_PLT: 1115f613dfdSUlrich Weigand assert(IsPCRel && "@PLT shouldt be PC-relative"); 1125f613dfdSUlrich Weigand return getPLTReloc(Kind); 1135f613dfdSUlrich Weigand 1145f613dfdSUlrich Weigand default: 1155f613dfdSUlrich Weigand llvm_unreachable("Modifier not supported"); 1165f613dfdSUlrich Weigand } 1175f613dfdSUlrich Weigand } 1185f613dfdSUlrich Weigand 1195f613dfdSUlrich Weigand const MCSymbol *SystemZObjectWriter::ExplicitRelSym(const MCAssembler &Asm, 1205f613dfdSUlrich Weigand const MCValue &Target, 1215f613dfdSUlrich Weigand const MCFragment &F, 1225f613dfdSUlrich Weigand const MCFixup &Fixup, 1235f613dfdSUlrich Weigand bool IsPCRel) const { 1245f613dfdSUlrich Weigand // The addend in a PC-relative R_390_* relocation is always applied to 1255f613dfdSUlrich Weigand // the PC-relative part of the address. If some kind of indirection 1265f613dfdSUlrich Weigand // is applied to the symbol first, we can't use an addend there too. 1275f613dfdSUlrich Weigand if (!Target.isAbsolute() && 1285f613dfdSUlrich Weigand Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None && 1295f613dfdSUlrich Weigand IsPCRel) 1305f613dfdSUlrich Weigand return &Target.getSymA()->getSymbol().AliasedSymbol(); 1315f613dfdSUlrich Weigand return NULL; 1325f613dfdSUlrich Weigand } 1335f613dfdSUlrich Weigand 1345f613dfdSUlrich Weigand MCObjectWriter *llvm::createSystemZObjectWriter(raw_ostream &OS, 1355f613dfdSUlrich Weigand uint8_t OSABI) { 1365f613dfdSUlrich Weigand MCELFObjectTargetWriter *MOTW = new SystemZObjectWriter(OSABI); 1375f613dfdSUlrich Weigand return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false); 1385f613dfdSUlrich Weigand } 139