13adc2a0bSKai Nacke //===-- SystemZELFObjectWriter.cpp - SystemZ ELF writer -------------------===// 23adc2a0bSKai Nacke // 33adc2a0bSKai Nacke // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43adc2a0bSKai Nacke // See https://llvm.org/LICENSE.txt for license information. 53adc2a0bSKai Nacke // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63adc2a0bSKai Nacke // 73adc2a0bSKai Nacke //===----------------------------------------------------------------------===// 83adc2a0bSKai Nacke 93adc2a0bSKai Nacke #include "MCTargetDesc/SystemZMCFixups.h" 103adc2a0bSKai Nacke #include "MCTargetDesc/SystemZMCTargetDesc.h" 113adc2a0bSKai Nacke #include "llvm/BinaryFormat/ELF.h" 123adc2a0bSKai Nacke #include "llvm/MC/MCContext.h" 133adc2a0bSKai Nacke #include "llvm/MC/MCELFObjectWriter.h" 143adc2a0bSKai Nacke #include "llvm/MC/MCExpr.h" 153adc2a0bSKai Nacke #include "llvm/MC/MCFixup.h" 163adc2a0bSKai Nacke #include "llvm/MC/MCObjectWriter.h" 173adc2a0bSKai Nacke #include "llvm/MC/MCValue.h" 183adc2a0bSKai Nacke #include "llvm/Support/ErrorHandling.h" 193adc2a0bSKai Nacke #include <cassert> 203adc2a0bSKai Nacke #include <cstdint> 219104e824SKai Nacke #include <memory> 223adc2a0bSKai Nacke 233adc2a0bSKai Nacke using namespace llvm; 243adc2a0bSKai Nacke 253adc2a0bSKai Nacke namespace { 263adc2a0bSKai Nacke 273adc2a0bSKai Nacke class SystemZELFObjectWriter : public MCELFObjectTargetWriter { 283adc2a0bSKai Nacke public: 293adc2a0bSKai Nacke SystemZELFObjectWriter(uint8_t OSABI); 303adc2a0bSKai Nacke ~SystemZELFObjectWriter() override = default; 313adc2a0bSKai Nacke 323adc2a0bSKai Nacke protected: 333adc2a0bSKai Nacke // Override MCELFObjectTargetWriter. 343adc2a0bSKai Nacke unsigned getRelocType(MCContext &Ctx, const MCValue &Target, 353adc2a0bSKai Nacke const MCFixup &Fixup, bool IsPCRel) const override; 363adc2a0bSKai Nacke }; 373adc2a0bSKai Nacke 383adc2a0bSKai Nacke } // end anonymous namespace 393adc2a0bSKai Nacke 403adc2a0bSKai Nacke SystemZELFObjectWriter::SystemZELFObjectWriter(uint8_t OSABI) 413adc2a0bSKai Nacke : MCELFObjectTargetWriter(/*Is64Bit_=*/true, OSABI, ELF::EM_S390, 423adc2a0bSKai Nacke /*HasRelocationAddend_=*/true) {} 433adc2a0bSKai Nacke 443adc2a0bSKai Nacke // Return the relocation type for an absolute value of MCFixupKind Kind. 453adc2a0bSKai Nacke static unsigned getAbsoluteReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) { 463adc2a0bSKai Nacke switch (Kind) { 473adc2a0bSKai Nacke case FK_Data_1: 483adc2a0bSKai Nacke case SystemZ::FK_390_U8Imm: 493adc2a0bSKai Nacke case SystemZ::FK_390_S8Imm: 503adc2a0bSKai Nacke return ELF::R_390_8; 513adc2a0bSKai Nacke case SystemZ::FK_390_U12Imm: 523adc2a0bSKai Nacke return ELF::R_390_12; 533adc2a0bSKai Nacke case FK_Data_2: 543adc2a0bSKai Nacke case SystemZ::FK_390_U16Imm: 553adc2a0bSKai Nacke case SystemZ::FK_390_S16Imm: 563adc2a0bSKai Nacke return ELF::R_390_16; 573adc2a0bSKai Nacke case SystemZ::FK_390_S20Imm: 583adc2a0bSKai Nacke return ELF::R_390_20; 593adc2a0bSKai Nacke case FK_Data_4: 603adc2a0bSKai Nacke case SystemZ::FK_390_U32Imm: 613adc2a0bSKai Nacke case SystemZ::FK_390_S32Imm: 623adc2a0bSKai Nacke return ELF::R_390_32; 633adc2a0bSKai Nacke case FK_Data_8: 643adc2a0bSKai Nacke return ELF::R_390_64; 653adc2a0bSKai Nacke } 663adc2a0bSKai Nacke Ctx.reportError(Loc, "Unsupported absolute address"); 673adc2a0bSKai Nacke return 0; 683adc2a0bSKai Nacke } 693adc2a0bSKai Nacke 703adc2a0bSKai Nacke // Return the relocation type for a PC-relative value of MCFixupKind Kind. 713adc2a0bSKai Nacke static unsigned getPCRelReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) { 723adc2a0bSKai Nacke switch (Kind) { 733adc2a0bSKai Nacke case FK_Data_2: 743adc2a0bSKai Nacke case SystemZ::FK_390_U16Imm: 753adc2a0bSKai Nacke case SystemZ::FK_390_S16Imm: 763adc2a0bSKai Nacke return ELF::R_390_PC16; 773adc2a0bSKai Nacke case FK_Data_4: 783adc2a0bSKai Nacke case SystemZ::FK_390_U32Imm: 793adc2a0bSKai Nacke case SystemZ::FK_390_S32Imm: 803adc2a0bSKai Nacke return ELF::R_390_PC32; 813adc2a0bSKai Nacke case FK_Data_8: 823adc2a0bSKai Nacke return ELF::R_390_PC64; 833adc2a0bSKai Nacke case SystemZ::FK_390_PC12DBL: 843adc2a0bSKai Nacke return ELF::R_390_PC12DBL; 853adc2a0bSKai Nacke case SystemZ::FK_390_PC16DBL: 863adc2a0bSKai Nacke return ELF::R_390_PC16DBL; 873adc2a0bSKai Nacke case SystemZ::FK_390_PC24DBL: 883adc2a0bSKai Nacke return ELF::R_390_PC24DBL; 893adc2a0bSKai Nacke case SystemZ::FK_390_PC32DBL: 903adc2a0bSKai Nacke return ELF::R_390_PC32DBL; 913adc2a0bSKai Nacke } 923adc2a0bSKai Nacke Ctx.reportError(Loc, "Unsupported PC-relative address"); 933adc2a0bSKai Nacke return 0; 943adc2a0bSKai Nacke } 953adc2a0bSKai Nacke 963adc2a0bSKai Nacke // Return the R_390_TLS_LE* relocation type for MCFixupKind Kind. 973adc2a0bSKai Nacke static unsigned getTLSLEReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) { 983adc2a0bSKai Nacke switch (Kind) { 993adc2a0bSKai Nacke case FK_Data_4: return ELF::R_390_TLS_LE32; 1003adc2a0bSKai Nacke case FK_Data_8: return ELF::R_390_TLS_LE64; 1013adc2a0bSKai Nacke } 1023adc2a0bSKai Nacke Ctx.reportError(Loc, "Unsupported thread-local address (local-exec)"); 1033adc2a0bSKai Nacke return 0; 1043adc2a0bSKai Nacke } 1053adc2a0bSKai Nacke 1063adc2a0bSKai Nacke // Return the R_390_TLS_LDO* relocation type for MCFixupKind Kind. 1073adc2a0bSKai Nacke static unsigned getTLSLDOReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) { 1083adc2a0bSKai Nacke switch (Kind) { 1093adc2a0bSKai Nacke case FK_Data_4: return ELF::R_390_TLS_LDO32; 1103adc2a0bSKai Nacke case FK_Data_8: return ELF::R_390_TLS_LDO64; 1113adc2a0bSKai Nacke } 1123adc2a0bSKai Nacke Ctx.reportError(Loc, "Unsupported thread-local address (local-dynamic)"); 1133adc2a0bSKai Nacke return 0; 1143adc2a0bSKai Nacke } 1153adc2a0bSKai Nacke 1163adc2a0bSKai Nacke // Return the R_390_TLS_LDM* relocation type for MCFixupKind Kind. 1173adc2a0bSKai Nacke static unsigned getTLSLDMReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) { 1183adc2a0bSKai Nacke switch (Kind) { 1193adc2a0bSKai Nacke case FK_Data_4: return ELF::R_390_TLS_LDM32; 1203adc2a0bSKai Nacke case FK_Data_8: return ELF::R_390_TLS_LDM64; 1213adc2a0bSKai Nacke case SystemZ::FK_390_TLS_CALL: return ELF::R_390_TLS_LDCALL; 1223adc2a0bSKai Nacke } 1233adc2a0bSKai Nacke Ctx.reportError(Loc, "Unsupported thread-local address (local-dynamic)"); 1243adc2a0bSKai Nacke return 0; 1253adc2a0bSKai Nacke } 1263adc2a0bSKai Nacke 1273adc2a0bSKai Nacke // Return the R_390_TLS_GD* relocation type for MCFixupKind Kind. 1283adc2a0bSKai Nacke static unsigned getTLSGDReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) { 1293adc2a0bSKai Nacke switch (Kind) { 1303adc2a0bSKai Nacke case FK_Data_4: return ELF::R_390_TLS_GD32; 1313adc2a0bSKai Nacke case FK_Data_8: return ELF::R_390_TLS_GD64; 1323adc2a0bSKai Nacke case SystemZ::FK_390_TLS_CALL: return ELF::R_390_TLS_GDCALL; 1333adc2a0bSKai Nacke } 1343adc2a0bSKai Nacke Ctx.reportError(Loc, "Unsupported thread-local address (general-dynamic)"); 1353adc2a0bSKai Nacke return 0; 1363adc2a0bSKai Nacke } 1373adc2a0bSKai Nacke 1383adc2a0bSKai Nacke // Return the PLT relocation counterpart of MCFixupKind Kind. 1393adc2a0bSKai Nacke static unsigned getPLTReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) { 1403adc2a0bSKai Nacke switch (Kind) { 1413adc2a0bSKai Nacke case SystemZ::FK_390_PC12DBL: return ELF::R_390_PLT12DBL; 1423adc2a0bSKai Nacke case SystemZ::FK_390_PC16DBL: return ELF::R_390_PLT16DBL; 1433adc2a0bSKai Nacke case SystemZ::FK_390_PC24DBL: return ELF::R_390_PLT24DBL; 1443adc2a0bSKai Nacke case SystemZ::FK_390_PC32DBL: return ELF::R_390_PLT32DBL; 1453adc2a0bSKai Nacke } 1463adc2a0bSKai Nacke Ctx.reportError(Loc, "Unsupported PC-relative PLT address"); 1473adc2a0bSKai Nacke return 0; 1483adc2a0bSKai Nacke } 1493adc2a0bSKai Nacke 1503adc2a0bSKai Nacke unsigned SystemZELFObjectWriter::getRelocType(MCContext &Ctx, 1513adc2a0bSKai Nacke const MCValue &Target, 1523adc2a0bSKai Nacke const MCFixup &Fixup, 1533adc2a0bSKai Nacke bool IsPCRel) const { 1543adc2a0bSKai Nacke SMLoc Loc = Fixup.getLoc(); 1553adc2a0bSKai Nacke unsigned Kind = Fixup.getKind(); 1563adc2a0bSKai Nacke if (Kind >= FirstLiteralRelocationKind) 1573adc2a0bSKai Nacke return Kind - FirstLiteralRelocationKind; 1583adc2a0bSKai Nacke MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); 1593adc2a0bSKai Nacke switch (Modifier) { 1603adc2a0bSKai Nacke case MCSymbolRefExpr::VK_None: 1613adc2a0bSKai Nacke if (IsPCRel) 1623adc2a0bSKai Nacke return getPCRelReloc(Ctx, Loc, Kind); 1633adc2a0bSKai Nacke return getAbsoluteReloc(Ctx, Loc, Kind); 1643adc2a0bSKai Nacke 1653adc2a0bSKai Nacke case MCSymbolRefExpr::VK_NTPOFF: 1663adc2a0bSKai Nacke assert(!IsPCRel && "NTPOFF shouldn't be PC-relative"); 1673adc2a0bSKai Nacke return getTLSLEReloc(Ctx, Loc, Kind); 1683adc2a0bSKai Nacke 1693adc2a0bSKai Nacke case MCSymbolRefExpr::VK_INDNTPOFF: 1703adc2a0bSKai Nacke if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL) 1713adc2a0bSKai Nacke return ELF::R_390_TLS_IEENT; 1723adc2a0bSKai Nacke Ctx.reportError(Loc, "Only PC-relative INDNTPOFF accesses are supported for now"); 1733adc2a0bSKai Nacke return 0; 1743adc2a0bSKai Nacke 1753adc2a0bSKai Nacke case MCSymbolRefExpr::VK_DTPOFF: 1763adc2a0bSKai Nacke assert(!IsPCRel && "DTPOFF shouldn't be PC-relative"); 1773adc2a0bSKai Nacke return getTLSLDOReloc(Ctx, Loc, Kind); 1783adc2a0bSKai Nacke 1793adc2a0bSKai Nacke case MCSymbolRefExpr::VK_TLSLDM: 1803adc2a0bSKai Nacke assert(!IsPCRel && "TLSLDM shouldn't be PC-relative"); 1813adc2a0bSKai Nacke return getTLSLDMReloc(Ctx, Loc, Kind); 1823adc2a0bSKai Nacke 1833adc2a0bSKai Nacke case MCSymbolRefExpr::VK_TLSGD: 1843adc2a0bSKai Nacke assert(!IsPCRel && "TLSGD shouldn't be PC-relative"); 1853adc2a0bSKai Nacke return getTLSGDReloc(Ctx, Loc, Kind); 1863adc2a0bSKai Nacke 1873adc2a0bSKai Nacke case MCSymbolRefExpr::VK_GOT: 188*bedac64dSAlex Rønne Petersen case MCSymbolRefExpr::VK_GOTENT: 1893adc2a0bSKai Nacke if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL) 1903adc2a0bSKai Nacke return ELF::R_390_GOTENT; 1913adc2a0bSKai Nacke Ctx.reportError(Loc, "Only PC-relative GOT accesses are supported for now"); 1923adc2a0bSKai Nacke return 0; 1933adc2a0bSKai Nacke 1943adc2a0bSKai Nacke case MCSymbolRefExpr::VK_PLT: 1953adc2a0bSKai Nacke assert(IsPCRel && "@PLT shouldn't be PC-relative"); 1963adc2a0bSKai Nacke return getPLTReloc(Ctx, Loc, Kind); 1973adc2a0bSKai Nacke 1983adc2a0bSKai Nacke default: 1993adc2a0bSKai Nacke llvm_unreachable("Modifier not supported"); 2003adc2a0bSKai Nacke } 2013adc2a0bSKai Nacke } 2023adc2a0bSKai Nacke 2033adc2a0bSKai Nacke std::unique_ptr<MCObjectTargetWriter> 2043adc2a0bSKai Nacke llvm::createSystemZELFObjectWriter(uint8_t OSABI) { 2053adc2a0bSKai Nacke return std::make_unique<SystemZELFObjectWriter>(OSABI); 2063adc2a0bSKai Nacke } 207