1b1c73532SDimitry Andric //===-- SystemZELFObjectWriter.cpp - SystemZ ELF writer -------------------===//
259d6cff9SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
659d6cff9SDimitry Andric //
759d6cff9SDimitry Andric //===----------------------------------------------------------------------===//
859d6cff9SDimitry Andric
959d6cff9SDimitry Andric #include "MCTargetDesc/SystemZMCFixups.h"
1071d5a254SDimitry Andric #include "MCTargetDesc/SystemZMCTargetDesc.h"
117ab83427SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
127fa27ce4SDimitry Andric #include "llvm/MC/MCContext.h"
1359d6cff9SDimitry Andric #include "llvm/MC/MCELFObjectWriter.h"
1459d6cff9SDimitry Andric #include "llvm/MC/MCExpr.h"
1571d5a254SDimitry Andric #include "llvm/MC/MCFixup.h"
16044eb2f6SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
1759d6cff9SDimitry Andric #include "llvm/MC/MCValue.h"
1871d5a254SDimitry Andric #include "llvm/Support/ErrorHandling.h"
1971d5a254SDimitry Andric #include <cassert>
2071d5a254SDimitry Andric #include <cstdint>
21b1c73532SDimitry Andric #include <memory>
2259d6cff9SDimitry Andric
2359d6cff9SDimitry Andric using namespace llvm;
2459d6cff9SDimitry Andric
2559d6cff9SDimitry Andric namespace {
2671d5a254SDimitry Andric
27b1c73532SDimitry Andric class SystemZELFObjectWriter : public MCELFObjectTargetWriter {
2859d6cff9SDimitry Andric public:
29b1c73532SDimitry Andric SystemZELFObjectWriter(uint8_t OSABI);
30b1c73532SDimitry Andric ~SystemZELFObjectWriter() override = default;
3159d6cff9SDimitry Andric
3259d6cff9SDimitry Andric protected:
3359d6cff9SDimitry Andric // Override MCELFObjectTargetWriter.
3401095a5dSDimitry Andric unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
3501095a5dSDimitry Andric const MCFixup &Fixup, bool IsPCRel) const override;
3659d6cff9SDimitry Andric };
3771d5a254SDimitry Andric
385ca98fd9SDimitry Andric } // end anonymous namespace
3959d6cff9SDimitry Andric
SystemZELFObjectWriter(uint8_t OSABI)40b1c73532SDimitry Andric SystemZELFObjectWriter::SystemZELFObjectWriter(uint8_t OSABI)
41e6d15924SDimitry Andric : MCELFObjectTargetWriter(/*Is64Bit_=*/true, OSABI, ELF::EM_S390,
42e6d15924SDimitry Andric /*HasRelocationAddend_=*/true) {}
4359d6cff9SDimitry Andric
4459d6cff9SDimitry Andric // Return the relocation type for an absolute value of MCFixupKind Kind.
getAbsoluteReloc(MCContext & Ctx,SMLoc Loc,unsigned Kind)457fa27ce4SDimitry Andric static unsigned getAbsoluteReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) {
4659d6cff9SDimitry Andric switch (Kind) {
477fa27ce4SDimitry Andric case FK_Data_1:
487fa27ce4SDimitry Andric case SystemZ::FK_390_U8Imm:
497fa27ce4SDimitry Andric case SystemZ::FK_390_S8Imm:
507fa27ce4SDimitry Andric return ELF::R_390_8;
517fa27ce4SDimitry Andric case SystemZ::FK_390_U12Imm:
527fa27ce4SDimitry Andric return ELF::R_390_12;
537fa27ce4SDimitry Andric case FK_Data_2:
547fa27ce4SDimitry Andric case SystemZ::FK_390_U16Imm:
557fa27ce4SDimitry Andric case SystemZ::FK_390_S16Imm:
567fa27ce4SDimitry Andric return ELF::R_390_16;
577fa27ce4SDimitry Andric case SystemZ::FK_390_S20Imm:
587fa27ce4SDimitry Andric return ELF::R_390_20;
597fa27ce4SDimitry Andric case FK_Data_4:
607fa27ce4SDimitry Andric case SystemZ::FK_390_U32Imm:
617fa27ce4SDimitry Andric case SystemZ::FK_390_S32Imm:
627fa27ce4SDimitry Andric return ELF::R_390_32;
637fa27ce4SDimitry Andric case FK_Data_8:
647fa27ce4SDimitry Andric return ELF::R_390_64;
6559d6cff9SDimitry Andric }
667fa27ce4SDimitry Andric Ctx.reportError(Loc, "Unsupported absolute address");
677fa27ce4SDimitry Andric return 0;
6859d6cff9SDimitry Andric }
6959d6cff9SDimitry Andric
7059d6cff9SDimitry Andric // Return the relocation type for a PC-relative value of MCFixupKind Kind.
getPCRelReloc(MCContext & Ctx,SMLoc Loc,unsigned Kind)717fa27ce4SDimitry Andric static unsigned getPCRelReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) {
7259d6cff9SDimitry Andric switch (Kind) {
737fa27ce4SDimitry Andric case FK_Data_2:
747fa27ce4SDimitry Andric case SystemZ::FK_390_U16Imm:
757fa27ce4SDimitry Andric case SystemZ::FK_390_S16Imm:
767fa27ce4SDimitry Andric return ELF::R_390_PC16;
777fa27ce4SDimitry Andric case FK_Data_4:
787fa27ce4SDimitry Andric case SystemZ::FK_390_U32Imm:
797fa27ce4SDimitry Andric case SystemZ::FK_390_S32Imm:
807fa27ce4SDimitry Andric return ELF::R_390_PC32;
817fa27ce4SDimitry Andric case FK_Data_8:
827fa27ce4SDimitry Andric return ELF::R_390_PC64;
837fa27ce4SDimitry Andric case SystemZ::FK_390_PC12DBL:
847fa27ce4SDimitry Andric return ELF::R_390_PC12DBL;
857fa27ce4SDimitry Andric case SystemZ::FK_390_PC16DBL:
867fa27ce4SDimitry Andric return ELF::R_390_PC16DBL;
877fa27ce4SDimitry Andric case SystemZ::FK_390_PC24DBL:
887fa27ce4SDimitry Andric return ELF::R_390_PC24DBL;
897fa27ce4SDimitry Andric case SystemZ::FK_390_PC32DBL:
907fa27ce4SDimitry Andric return ELF::R_390_PC32DBL;
9159d6cff9SDimitry Andric }
927fa27ce4SDimitry Andric Ctx.reportError(Loc, "Unsupported PC-relative address");
937fa27ce4SDimitry Andric return 0;
9459d6cff9SDimitry Andric }
9559d6cff9SDimitry Andric
9659d6cff9SDimitry Andric // Return the R_390_TLS_LE* relocation type for MCFixupKind Kind.
getTLSLEReloc(MCContext & Ctx,SMLoc Loc,unsigned Kind)977fa27ce4SDimitry Andric static unsigned getTLSLEReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) {
9859d6cff9SDimitry Andric switch (Kind) {
9959d6cff9SDimitry Andric case FK_Data_4: return ELF::R_390_TLS_LE32;
10059d6cff9SDimitry Andric case FK_Data_8: return ELF::R_390_TLS_LE64;
10159d6cff9SDimitry Andric }
1027fa27ce4SDimitry Andric Ctx.reportError(Loc, "Unsupported thread-local address (local-exec)");
1037fa27ce4SDimitry Andric return 0;
10459d6cff9SDimitry Andric }
10559d6cff9SDimitry Andric
1065a5ac124SDimitry Andric // Return the R_390_TLS_LDO* relocation type for MCFixupKind Kind.
getTLSLDOReloc(MCContext & Ctx,SMLoc Loc,unsigned Kind)1077fa27ce4SDimitry Andric static unsigned getTLSLDOReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) {
1085a5ac124SDimitry Andric switch (Kind) {
1095a5ac124SDimitry Andric case FK_Data_4: return ELF::R_390_TLS_LDO32;
1105a5ac124SDimitry Andric case FK_Data_8: return ELF::R_390_TLS_LDO64;
1115a5ac124SDimitry Andric }
1127fa27ce4SDimitry Andric Ctx.reportError(Loc, "Unsupported thread-local address (local-dynamic)");
1137fa27ce4SDimitry Andric return 0;
1145a5ac124SDimitry Andric }
1155a5ac124SDimitry Andric
1165a5ac124SDimitry Andric // Return the R_390_TLS_LDM* relocation type for MCFixupKind Kind.
getTLSLDMReloc(MCContext & Ctx,SMLoc Loc,unsigned Kind)1177fa27ce4SDimitry Andric static unsigned getTLSLDMReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) {
1185a5ac124SDimitry Andric switch (Kind) {
1195a5ac124SDimitry Andric case FK_Data_4: return ELF::R_390_TLS_LDM32;
1205a5ac124SDimitry Andric case FK_Data_8: return ELF::R_390_TLS_LDM64;
1215a5ac124SDimitry Andric case SystemZ::FK_390_TLS_CALL: return ELF::R_390_TLS_LDCALL;
1225a5ac124SDimitry Andric }
1237fa27ce4SDimitry Andric Ctx.reportError(Loc, "Unsupported thread-local address (local-dynamic)");
1247fa27ce4SDimitry Andric return 0;
1255a5ac124SDimitry Andric }
1265a5ac124SDimitry Andric
1275a5ac124SDimitry Andric // Return the R_390_TLS_GD* relocation type for MCFixupKind Kind.
getTLSGDReloc(MCContext & Ctx,SMLoc Loc,unsigned Kind)1287fa27ce4SDimitry Andric static unsigned getTLSGDReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) {
1295a5ac124SDimitry Andric switch (Kind) {
1305a5ac124SDimitry Andric case FK_Data_4: return ELF::R_390_TLS_GD32;
1315a5ac124SDimitry Andric case FK_Data_8: return ELF::R_390_TLS_GD64;
1325a5ac124SDimitry Andric case SystemZ::FK_390_TLS_CALL: return ELF::R_390_TLS_GDCALL;
1335a5ac124SDimitry Andric }
1347fa27ce4SDimitry Andric Ctx.reportError(Loc, "Unsupported thread-local address (general-dynamic)");
1357fa27ce4SDimitry Andric return 0;
1365a5ac124SDimitry Andric }
1375a5ac124SDimitry Andric
13859d6cff9SDimitry Andric // Return the PLT relocation counterpart of MCFixupKind Kind.
getPLTReloc(MCContext & Ctx,SMLoc Loc,unsigned Kind)1397fa27ce4SDimitry Andric static unsigned getPLTReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) {
14059d6cff9SDimitry Andric switch (Kind) {
141b915e9e0SDimitry Andric case SystemZ::FK_390_PC12DBL: return ELF::R_390_PLT12DBL;
14259d6cff9SDimitry Andric case SystemZ::FK_390_PC16DBL: return ELF::R_390_PLT16DBL;
143b915e9e0SDimitry Andric case SystemZ::FK_390_PC24DBL: return ELF::R_390_PLT24DBL;
14459d6cff9SDimitry Andric case SystemZ::FK_390_PC32DBL: return ELF::R_390_PLT32DBL;
14559d6cff9SDimitry Andric }
1467fa27ce4SDimitry Andric Ctx.reportError(Loc, "Unsupported PC-relative PLT address");
1477fa27ce4SDimitry Andric return 0;
14859d6cff9SDimitry Andric }
14959d6cff9SDimitry Andric
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const150b1c73532SDimitry Andric unsigned SystemZELFObjectWriter::getRelocType(MCContext &Ctx,
15101095a5dSDimitry Andric const MCValue &Target,
15259d6cff9SDimitry Andric const MCFixup &Fixup,
1535ca98fd9SDimitry Andric bool IsPCRel) const {
1547fa27ce4SDimitry Andric SMLoc Loc = Fixup.getLoc();
15559d6cff9SDimitry Andric unsigned Kind = Fixup.getKind();
156344a3780SDimitry Andric if (Kind >= FirstLiteralRelocationKind)
157344a3780SDimitry Andric return Kind - FirstLiteralRelocationKind;
158344a3780SDimitry Andric MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
15959d6cff9SDimitry Andric switch (Modifier) {
16059d6cff9SDimitry Andric case MCSymbolRefExpr::VK_None:
16159d6cff9SDimitry Andric if (IsPCRel)
1627fa27ce4SDimitry Andric return getPCRelReloc(Ctx, Loc, Kind);
1637fa27ce4SDimitry Andric return getAbsoluteReloc(Ctx, Loc, Kind);
16459d6cff9SDimitry Andric
16559d6cff9SDimitry Andric case MCSymbolRefExpr::VK_NTPOFF:
16659d6cff9SDimitry Andric assert(!IsPCRel && "NTPOFF shouldn't be PC-relative");
1677fa27ce4SDimitry Andric return getTLSLEReloc(Ctx, Loc, Kind);
16859d6cff9SDimitry Andric
1695a5ac124SDimitry Andric case MCSymbolRefExpr::VK_INDNTPOFF:
1705a5ac124SDimitry Andric if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL)
1715a5ac124SDimitry Andric return ELF::R_390_TLS_IEENT;
1727fa27ce4SDimitry Andric Ctx.reportError(Loc, "Only PC-relative INDNTPOFF accesses are supported for now");
1737fa27ce4SDimitry Andric return 0;
1745a5ac124SDimitry Andric
1755a5ac124SDimitry Andric case MCSymbolRefExpr::VK_DTPOFF:
1765a5ac124SDimitry Andric assert(!IsPCRel && "DTPOFF shouldn't be PC-relative");
1777fa27ce4SDimitry Andric return getTLSLDOReloc(Ctx, Loc, Kind);
1785a5ac124SDimitry Andric
1795a5ac124SDimitry Andric case MCSymbolRefExpr::VK_TLSLDM:
1805a5ac124SDimitry Andric assert(!IsPCRel && "TLSLDM shouldn't be PC-relative");
1817fa27ce4SDimitry Andric return getTLSLDMReloc(Ctx, Loc, Kind);
1825a5ac124SDimitry Andric
1835a5ac124SDimitry Andric case MCSymbolRefExpr::VK_TLSGD:
1845a5ac124SDimitry Andric assert(!IsPCRel && "TLSGD shouldn't be PC-relative");
1857fa27ce4SDimitry Andric return getTLSGDReloc(Ctx, Loc, Kind);
1865a5ac124SDimitry Andric
18759d6cff9SDimitry Andric case MCSymbolRefExpr::VK_GOT:
18859d6cff9SDimitry Andric if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL)
18959d6cff9SDimitry Andric return ELF::R_390_GOTENT;
1907fa27ce4SDimitry Andric Ctx.reportError(Loc, "Only PC-relative GOT accesses are supported for now");
1917fa27ce4SDimitry Andric return 0;
19259d6cff9SDimitry Andric
19359d6cff9SDimitry Andric case MCSymbolRefExpr::VK_PLT:
1947fa27ce4SDimitry Andric assert(IsPCRel && "@PLT shouldn't be PC-relative");
1957fa27ce4SDimitry Andric return getPLTReloc(Ctx, Loc, Kind);
19659d6cff9SDimitry Andric
19759d6cff9SDimitry Andric default:
19859d6cff9SDimitry Andric llvm_unreachable("Modifier not supported");
19959d6cff9SDimitry Andric }
20059d6cff9SDimitry Andric }
20159d6cff9SDimitry Andric
202eb11fae6SDimitry Andric std::unique_ptr<MCObjectTargetWriter>
createSystemZELFObjectWriter(uint8_t OSABI)203b1c73532SDimitry Andric llvm::createSystemZELFObjectWriter(uint8_t OSABI) {
204b1c73532SDimitry Andric return std::make_unique<SystemZELFObjectWriter>(OSABI);
20559d6cff9SDimitry Andric }
206