15f613dfdSUlrich Weigand //===-- SystemZMCObjectWriter.cpp - SystemZ ELF writer --------------------===// 25f613dfdSUlrich Weigand // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65f613dfdSUlrich Weigand // 75f613dfdSUlrich Weigand //===----------------------------------------------------------------------===// 85f613dfdSUlrich Weigand 95f613dfdSUlrich Weigand #include "MCTargetDesc/SystemZMCFixups.h" 103943d2b0SEugene Zelenko #include "MCTargetDesc/SystemZMCTargetDesc.h" 11264b5d9eSZachary Turner #include "llvm/BinaryFormat/ELF.h" 125f613dfdSUlrich Weigand #include "llvm/MC/MCELFObjectWriter.h" 135f613dfdSUlrich Weigand #include "llvm/MC/MCExpr.h" 143943d2b0SEugene Zelenko #include "llvm/MC/MCFixup.h" 1560fbc7ccSLang Hames #include "llvm/MC/MCObjectWriter.h" 165f613dfdSUlrich Weigand #include "llvm/MC/MCValue.h" 173943d2b0SEugene Zelenko #include "llvm/Support/ErrorHandling.h" 183943d2b0SEugene Zelenko #include <cassert> 193943d2b0SEugene Zelenko #include <cstdint> 205f613dfdSUlrich Weigand 215f613dfdSUlrich Weigand using namespace llvm; 225f613dfdSUlrich Weigand 235f613dfdSUlrich Weigand namespace { 243943d2b0SEugene Zelenko 255f613dfdSUlrich Weigand class SystemZObjectWriter : public MCELFObjectTargetWriter { 265f613dfdSUlrich Weigand public: 275f613dfdSUlrich Weigand SystemZObjectWriter(uint8_t OSABI); 283943d2b0SEugene Zelenko ~SystemZObjectWriter() override = default; 295f613dfdSUlrich Weigand 305f613dfdSUlrich Weigand protected: 315f613dfdSUlrich Weigand // Override MCELFObjectTargetWriter. 328340f94dSRafael Espindola unsigned getRelocType(MCContext &Ctx, const MCValue &Target, 338340f94dSRafael Espindola const MCFixup &Fixup, bool IsPCRel) const override; 345f613dfdSUlrich Weigand }; 353943d2b0SEugene Zelenko 36c231269fSRichard Sandiford } // end anonymous namespace 375f613dfdSUlrich Weigand 385f613dfdSUlrich Weigand SystemZObjectWriter::SystemZObjectWriter(uint8_t OSABI) 3949a3ad21SRui Ueyama : MCELFObjectTargetWriter(/*Is64Bit_=*/true, OSABI, ELF::EM_S390, 4049a3ad21SRui Ueyama /*HasRelocationAddend_=*/ true) {} 415f613dfdSUlrich Weigand 425f613dfdSUlrich Weigand // Return the relocation type for an absolute value of MCFixupKind Kind. 435f613dfdSUlrich Weigand static unsigned getAbsoluteReloc(unsigned Kind) { 445f613dfdSUlrich Weigand switch (Kind) { 455f613dfdSUlrich Weigand case FK_Data_1: return ELF::R_390_8; 465f613dfdSUlrich Weigand case FK_Data_2: return ELF::R_390_16; 475f613dfdSUlrich Weigand case FK_Data_4: return ELF::R_390_32; 485f613dfdSUlrich Weigand case FK_Data_8: return ELF::R_390_64; 495f613dfdSUlrich Weigand } 505f613dfdSUlrich Weigand llvm_unreachable("Unsupported absolute address"); 515f613dfdSUlrich Weigand } 525f613dfdSUlrich Weigand 535f613dfdSUlrich Weigand // Return the relocation type for a PC-relative value of MCFixupKind Kind. 545f613dfdSUlrich Weigand static unsigned getPCRelReloc(unsigned Kind) { 555f613dfdSUlrich Weigand switch (Kind) { 565f613dfdSUlrich Weigand case FK_Data_2: return ELF::R_390_PC16; 575f613dfdSUlrich Weigand case FK_Data_4: return ELF::R_390_PC32; 585f613dfdSUlrich Weigand case FK_Data_8: return ELF::R_390_PC64; 5984404f30SUlrich Weigand case SystemZ::FK_390_PC12DBL: return ELF::R_390_PC12DBL; 605f613dfdSUlrich Weigand case SystemZ::FK_390_PC16DBL: return ELF::R_390_PC16DBL; 6184404f30SUlrich Weigand case SystemZ::FK_390_PC24DBL: return ELF::R_390_PC24DBL; 625f613dfdSUlrich Weigand case SystemZ::FK_390_PC32DBL: return ELF::R_390_PC32DBL; 635f613dfdSUlrich Weigand } 645f613dfdSUlrich Weigand llvm_unreachable("Unsupported PC-relative address"); 655f613dfdSUlrich Weigand } 665f613dfdSUlrich Weigand 675f613dfdSUlrich Weigand // Return the R_390_TLS_LE* relocation type for MCFixupKind Kind. 685f613dfdSUlrich Weigand static unsigned getTLSLEReloc(unsigned Kind) { 695f613dfdSUlrich Weigand switch (Kind) { 705f613dfdSUlrich Weigand case FK_Data_4: return ELF::R_390_TLS_LE32; 715f613dfdSUlrich Weigand case FK_Data_8: return ELF::R_390_TLS_LE64; 725f613dfdSUlrich Weigand } 735f613dfdSUlrich Weigand llvm_unreachable("Unsupported absolute address"); 745f613dfdSUlrich Weigand } 755f613dfdSUlrich Weigand 767bdd7c23SUlrich Weigand // Return the R_390_TLS_LDO* relocation type for MCFixupKind Kind. 777bdd7c23SUlrich Weigand static unsigned getTLSLDOReloc(unsigned Kind) { 787bdd7c23SUlrich Weigand switch (Kind) { 797bdd7c23SUlrich Weigand case FK_Data_4: return ELF::R_390_TLS_LDO32; 807bdd7c23SUlrich Weigand case FK_Data_8: return ELF::R_390_TLS_LDO64; 817bdd7c23SUlrich Weigand } 827bdd7c23SUlrich Weigand llvm_unreachable("Unsupported absolute address"); 837bdd7c23SUlrich Weigand } 847bdd7c23SUlrich Weigand 857bdd7c23SUlrich Weigand // Return the R_390_TLS_LDM* relocation type for MCFixupKind Kind. 867bdd7c23SUlrich Weigand static unsigned getTLSLDMReloc(unsigned Kind) { 877bdd7c23SUlrich Weigand switch (Kind) { 887bdd7c23SUlrich Weigand case FK_Data_4: return ELF::R_390_TLS_LDM32; 897bdd7c23SUlrich Weigand case FK_Data_8: return ELF::R_390_TLS_LDM64; 907bdd7c23SUlrich Weigand case SystemZ::FK_390_TLS_CALL: return ELF::R_390_TLS_LDCALL; 917bdd7c23SUlrich Weigand } 927bdd7c23SUlrich Weigand llvm_unreachable("Unsupported absolute address"); 937bdd7c23SUlrich Weigand } 947bdd7c23SUlrich Weigand 957bdd7c23SUlrich Weigand // Return the R_390_TLS_GD* relocation type for MCFixupKind Kind. 967bdd7c23SUlrich Weigand static unsigned getTLSGDReloc(unsigned Kind) { 977bdd7c23SUlrich Weigand switch (Kind) { 987bdd7c23SUlrich Weigand case FK_Data_4: return ELF::R_390_TLS_GD32; 997bdd7c23SUlrich Weigand case FK_Data_8: return ELF::R_390_TLS_GD64; 1007bdd7c23SUlrich Weigand case SystemZ::FK_390_TLS_CALL: return ELF::R_390_TLS_GDCALL; 1017bdd7c23SUlrich Weigand } 1027bdd7c23SUlrich Weigand llvm_unreachable("Unsupported absolute address"); 1037bdd7c23SUlrich Weigand } 1047bdd7c23SUlrich Weigand 1055f613dfdSUlrich Weigand // Return the PLT relocation counterpart of MCFixupKind Kind. 1065f613dfdSUlrich Weigand static unsigned getPLTReloc(unsigned Kind) { 1075f613dfdSUlrich Weigand switch (Kind) { 10884404f30SUlrich Weigand case SystemZ::FK_390_PC12DBL: return ELF::R_390_PLT12DBL; 1095f613dfdSUlrich Weigand case SystemZ::FK_390_PC16DBL: return ELF::R_390_PLT16DBL; 11084404f30SUlrich Weigand case SystemZ::FK_390_PC24DBL: return ELF::R_390_PLT24DBL; 1115f613dfdSUlrich Weigand case SystemZ::FK_390_PC32DBL: return ELF::R_390_PLT32DBL; 1125f613dfdSUlrich Weigand } 1135f613dfdSUlrich Weigand llvm_unreachable("Unsupported absolute address"); 1145f613dfdSUlrich Weigand } 1155f613dfdSUlrich Weigand 1168340f94dSRafael Espindola unsigned SystemZObjectWriter::getRelocType(MCContext &Ctx, 1178340f94dSRafael Espindola const MCValue &Target, 118c03f44caSRafael Espindola const MCFixup &Fixup, 119c03f44caSRafael Espindola bool IsPCRel) const { 1203d082fa5SRafael Espindola MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); 1215f613dfdSUlrich Weigand unsigned Kind = Fixup.getKind(); 1225f613dfdSUlrich Weigand switch (Modifier) { 1235f613dfdSUlrich Weigand case MCSymbolRefExpr::VK_None: 1245f613dfdSUlrich Weigand if (IsPCRel) 1255f613dfdSUlrich Weigand return getPCRelReloc(Kind); 1265f613dfdSUlrich Weigand return getAbsoluteReloc(Kind); 1275f613dfdSUlrich Weigand 1285f613dfdSUlrich Weigand case MCSymbolRefExpr::VK_NTPOFF: 1295f613dfdSUlrich Weigand assert(!IsPCRel && "NTPOFF shouldn't be PC-relative"); 1305f613dfdSUlrich Weigand return getTLSLEReloc(Kind); 1315f613dfdSUlrich Weigand 1327bdd7c23SUlrich Weigand case MCSymbolRefExpr::VK_INDNTPOFF: 1337bdd7c23SUlrich Weigand if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL) 1347bdd7c23SUlrich Weigand return ELF::R_390_TLS_IEENT; 1357bdd7c23SUlrich Weigand llvm_unreachable("Only PC-relative INDNTPOFF accesses are supported for now"); 1367bdd7c23SUlrich Weigand 1377bdd7c23SUlrich Weigand case MCSymbolRefExpr::VK_DTPOFF: 1387bdd7c23SUlrich Weigand assert(!IsPCRel && "DTPOFF shouldn't be PC-relative"); 1397bdd7c23SUlrich Weigand return getTLSLDOReloc(Kind); 1407bdd7c23SUlrich Weigand 1417bdd7c23SUlrich Weigand case MCSymbolRefExpr::VK_TLSLDM: 1427bdd7c23SUlrich Weigand assert(!IsPCRel && "TLSLDM shouldn't be PC-relative"); 1437bdd7c23SUlrich Weigand return getTLSLDMReloc(Kind); 1447bdd7c23SUlrich Weigand 1457bdd7c23SUlrich Weigand case MCSymbolRefExpr::VK_TLSGD: 1467bdd7c23SUlrich Weigand assert(!IsPCRel && "TLSGD shouldn't be PC-relative"); 1477bdd7c23SUlrich Weigand return getTLSGDReloc(Kind); 1487bdd7c23SUlrich Weigand 1495f613dfdSUlrich Weigand case MCSymbolRefExpr::VK_GOT: 1505f613dfdSUlrich Weigand if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL) 1515f613dfdSUlrich Weigand return ELF::R_390_GOTENT; 1525f613dfdSUlrich Weigand llvm_unreachable("Only PC-relative GOT accesses are supported for now"); 1535f613dfdSUlrich Weigand 1545f613dfdSUlrich Weigand case MCSymbolRefExpr::VK_PLT: 1555f613dfdSUlrich Weigand assert(IsPCRel && "@PLT shouldt be PC-relative"); 1565f613dfdSUlrich Weigand return getPLTReloc(Kind); 1575f613dfdSUlrich Weigand 1585f613dfdSUlrich Weigand default: 1595f613dfdSUlrich Weigand llvm_unreachable("Modifier not supported"); 1605f613dfdSUlrich Weigand } 1615f613dfdSUlrich Weigand } 1625f613dfdSUlrich Weigand 163dcd7d6c3SPeter Collingbourne std::unique_ptr<MCObjectTargetWriter> 164dcd7d6c3SPeter Collingbourne llvm::createSystemZObjectWriter(uint8_t OSABI) { 165*0eaee545SJonas Devlieghere return std::make_unique<SystemZObjectWriter>(OSABI); 1665f613dfdSUlrich Weigand } 167