16b2cca7fSAlex Bradbury //===-- RISCVELFObjectWriter.cpp - RISCV ELF Writer -----------------------===//
26b2cca7fSAlex Bradbury //
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
66b2cca7fSAlex Bradbury //
76b2cca7fSAlex Bradbury //===----------------------------------------------------------------------===//
86b2cca7fSAlex Bradbury
99d3f1250SAlex Bradbury #include "MCTargetDesc/RISCVFixupKinds.h"
107cb3cd34SAlex Bradbury #include "MCTargetDesc/RISCVMCExpr.h"
116b2cca7fSAlex Bradbury #include "MCTargetDesc/RISCVMCTargetDesc.h"
12ec4f06a7SLuís Marques #include "llvm/MC/MCContext.h"
136b2cca7fSAlex Bradbury #include "llvm/MC/MCELFObjectWriter.h"
146b2cca7fSAlex Bradbury #include "llvm/MC/MCFixup.h"
155c1eef46SAlex Bradbury #include "llvm/MC/MCObjectWriter.h"
166b2cca7fSAlex Bradbury #include "llvm/Support/ErrorHandling.h"
176b2cca7fSAlex Bradbury
186b2cca7fSAlex Bradbury using namespace llvm;
196b2cca7fSAlex Bradbury
206b2cca7fSAlex Bradbury namespace {
216b2cca7fSAlex Bradbury class RISCVELFObjectWriter : public MCELFObjectTargetWriter {
226b2cca7fSAlex Bradbury public:
236b2cca7fSAlex Bradbury RISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit);
246b2cca7fSAlex Bradbury
256b2cca7fSAlex Bradbury ~RISCVELFObjectWriter() override;
266b2cca7fSAlex Bradbury
2798f9389fSShiva Chen // Return true if the given relocation must be with a symbol rather than
2898f9389fSShiva Chen // section plus offset.
needsRelocateWithSymbol(const MCSymbol & Sym,unsigned Type) const2998f9389fSShiva Chen bool needsRelocateWithSymbol(const MCSymbol &Sym,
3098f9389fSShiva Chen unsigned Type) const override {
3198f9389fSShiva Chen // TODO: this is very conservative, update once RISC-V psABI requirements
3298f9389fSShiva Chen // are clarified.
3398f9389fSShiva Chen return true;
3498f9389fSShiva Chen }
3598f9389fSShiva Chen
366b2cca7fSAlex Bradbury protected:
376b2cca7fSAlex Bradbury unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
386b2cca7fSAlex Bradbury const MCFixup &Fixup, bool IsPCRel) const override;
396b2cca7fSAlex Bradbury };
406b2cca7fSAlex Bradbury }
416b2cca7fSAlex Bradbury
RISCVELFObjectWriter(uint8_t OSABI,bool Is64Bit)426b2cca7fSAlex Bradbury RISCVELFObjectWriter::RISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit)
436b2cca7fSAlex Bradbury : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_RISCV,
44dd83484aSAlex Bradbury /*HasRelocationAddend*/ true) {}
456b2cca7fSAlex Bradbury
46*3a3cb929SKazu Hirata RISCVELFObjectWriter::~RISCVELFObjectWriter() = default;
476b2cca7fSAlex Bradbury
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const486b2cca7fSAlex Bradbury unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
496b2cca7fSAlex Bradbury const MCValue &Target,
506b2cca7fSAlex Bradbury const MCFixup &Fixup,
516b2cca7fSAlex Bradbury bool IsPCRel) const {
527cb3cd34SAlex Bradbury const MCExpr *Expr = Fixup.getValue();
539d3f1250SAlex Bradbury // Determine the type of the relocation
5490b6bb75SSam Clegg unsigned Kind = Fixup.getTargetKind();
55a7aaaf70SFangrui Song if (Kind >= FirstLiteralRelocationKind)
56a7aaaf70SFangrui Song return Kind - FirstLiteralRelocationKind;
574ac0b9beSAlex Bradbury if (IsPCRel) {
584ac0b9beSAlex Bradbury switch (Kind) {
594ac0b9beSAlex Bradbury default:
60ec4f06a7SLuís Marques Ctx.reportError(Fixup.getLoc(), "Unsupported relocation type");
61ec4f06a7SLuís Marques return ELF::R_RISCV_NONE;
624ac0b9beSAlex Bradbury case FK_Data_4:
634ac0b9beSAlex Bradbury case FK_PCRel_4:
644ac0b9beSAlex Bradbury return ELF::R_RISCV_32_PCREL;
654ac0b9beSAlex Bradbury case RISCV::fixup_riscv_pcrel_hi20:
664ac0b9beSAlex Bradbury return ELF::R_RISCV_PCREL_HI20;
674ac0b9beSAlex Bradbury case RISCV::fixup_riscv_pcrel_lo12_i:
684ac0b9beSAlex Bradbury return ELF::R_RISCV_PCREL_LO12_I;
694ac0b9beSAlex Bradbury case RISCV::fixup_riscv_pcrel_lo12_s:
704ac0b9beSAlex Bradbury return ELF::R_RISCV_PCREL_LO12_S;
714ac0b9beSAlex Bradbury case RISCV::fixup_riscv_got_hi20:
724ac0b9beSAlex Bradbury return ELF::R_RISCV_GOT_HI20;
734ac0b9beSAlex Bradbury case RISCV::fixup_riscv_tls_got_hi20:
744ac0b9beSAlex Bradbury return ELF::R_RISCV_TLS_GOT_HI20;
754ac0b9beSAlex Bradbury case RISCV::fixup_riscv_tls_gd_hi20:
764ac0b9beSAlex Bradbury return ELF::R_RISCV_TLS_GD_HI20;
774ac0b9beSAlex Bradbury case RISCV::fixup_riscv_jal:
784ac0b9beSAlex Bradbury return ELF::R_RISCV_JAL;
794ac0b9beSAlex Bradbury case RISCV::fixup_riscv_branch:
804ac0b9beSAlex Bradbury return ELF::R_RISCV_BRANCH;
814ac0b9beSAlex Bradbury case RISCV::fixup_riscv_rvc_jump:
824ac0b9beSAlex Bradbury return ELF::R_RISCV_RVC_JUMP;
834ac0b9beSAlex Bradbury case RISCV::fixup_riscv_rvc_branch:
844ac0b9beSAlex Bradbury return ELF::R_RISCV_RVC_BRANCH;
854ac0b9beSAlex Bradbury case RISCV::fixup_riscv_call:
864ac0b9beSAlex Bradbury return ELF::R_RISCV_CALL;
874ac0b9beSAlex Bradbury case RISCV::fixup_riscv_call_plt:
884ac0b9beSAlex Bradbury return ELF::R_RISCV_CALL_PLT;
89bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_add_8:
90bbea6425SSaleem Abdulrasool return ELF::R_RISCV_ADD8;
91bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_sub_8:
92bbea6425SSaleem Abdulrasool return ELF::R_RISCV_SUB8;
93bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_add_16:
94bbea6425SSaleem Abdulrasool return ELF::R_RISCV_ADD16;
95bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_sub_16:
96bbea6425SSaleem Abdulrasool return ELF::R_RISCV_SUB16;
97bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_add_32:
98bbea6425SSaleem Abdulrasool return ELF::R_RISCV_ADD32;
99bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_sub_32:
100bbea6425SSaleem Abdulrasool return ELF::R_RISCV_SUB32;
101bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_add_64:
102bbea6425SSaleem Abdulrasool return ELF::R_RISCV_ADD64;
103bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_sub_64:
104bbea6425SSaleem Abdulrasool return ELF::R_RISCV_SUB64;
1054ac0b9beSAlex Bradbury }
1064ac0b9beSAlex Bradbury }
1074ac0b9beSAlex Bradbury
1084ac0b9beSAlex Bradbury switch (Kind) {
1099d3f1250SAlex Bradbury default:
110ec4f06a7SLuís Marques Ctx.reportError(Fixup.getLoc(), "Unsupported relocation type");
111ec4f06a7SLuís Marques return ELF::R_RISCV_NONE;
112ec4f06a7SLuís Marques case FK_Data_1:
113ec4f06a7SLuís Marques Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
114ec4f06a7SLuís Marques return ELF::R_RISCV_NONE;
115ec4f06a7SLuís Marques case FK_Data_2:
116ec4f06a7SLuís Marques Ctx.reportError(Fixup.getLoc(), "2-byte data relocations not supported");
117ec4f06a7SLuís Marques return ELF::R_RISCV_NONE;
1189d3f1250SAlex Bradbury case FK_Data_4:
1197cb3cd34SAlex Bradbury if (Expr->getKind() == MCExpr::Target &&
1207cb3cd34SAlex Bradbury cast<RISCVMCExpr>(Expr)->getKind() == RISCVMCExpr::VK_RISCV_32_PCREL)
1217cb3cd34SAlex Bradbury return ELF::R_RISCV_32_PCREL;
1229d3f1250SAlex Bradbury return ELF::R_RISCV_32;
1239d3f1250SAlex Bradbury case FK_Data_8:
1249d3f1250SAlex Bradbury return ELF::R_RISCV_64;
1259d3f1250SAlex Bradbury case RISCV::fixup_riscv_hi20:
1269d3f1250SAlex Bradbury return ELF::R_RISCV_HI20;
1279d3f1250SAlex Bradbury case RISCV::fixup_riscv_lo12_i:
1289d3f1250SAlex Bradbury return ELF::R_RISCV_LO12_I;
1299d3f1250SAlex Bradbury case RISCV::fixup_riscv_lo12_s:
1309d3f1250SAlex Bradbury return ELF::R_RISCV_LO12_S;
131aa79a3feSLewis Revill case RISCV::fixup_riscv_tprel_hi20:
132aa79a3feSLewis Revill return ELF::R_RISCV_TPREL_HI20;
133aa79a3feSLewis Revill case RISCV::fixup_riscv_tprel_lo12_i:
134aa79a3feSLewis Revill return ELF::R_RISCV_TPREL_LO12_I;
135aa79a3feSLewis Revill case RISCV::fixup_riscv_tprel_lo12_s:
136aa79a3feSLewis Revill return ELF::R_RISCV_TPREL_LO12_S;
137aa79a3feSLewis Revill case RISCV::fixup_riscv_tprel_add:
138aa79a3feSLewis Revill return ELF::R_RISCV_TPREL_ADD;
13943bfe844SShiva Chen case RISCV::fixup_riscv_relax:
14043bfe844SShiva Chen return ELF::R_RISCV_RELAX;
1415af037f1SShiva Chen case RISCV::fixup_riscv_align:
1425af037f1SShiva Chen return ELF::R_RISCV_ALIGN;
143bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_set_6b:
144bbea6425SSaleem Abdulrasool return ELF::R_RISCV_SET6;
145bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_sub_6b:
146bbea6425SSaleem Abdulrasool return ELF::R_RISCV_SUB6;
147bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_add_8:
148bbea6425SSaleem Abdulrasool return ELF::R_RISCV_ADD8;
149bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_set_8:
150bbea6425SSaleem Abdulrasool return ELF::R_RISCV_SET8;
151bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_sub_8:
152bbea6425SSaleem Abdulrasool return ELF::R_RISCV_SUB8;
153bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_set_16:
154bbea6425SSaleem Abdulrasool return ELF::R_RISCV_SET16;
155bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_add_16:
156bbea6425SSaleem Abdulrasool return ELF::R_RISCV_ADD16;
157bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_sub_16:
158bbea6425SSaleem Abdulrasool return ELF::R_RISCV_SUB16;
159bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_set_32:
160bbea6425SSaleem Abdulrasool return ELF::R_RISCV_SET32;
161bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_add_32:
162bbea6425SSaleem Abdulrasool return ELF::R_RISCV_ADD32;
163bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_sub_32:
164bbea6425SSaleem Abdulrasool return ELF::R_RISCV_SUB32;
165bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_add_64:
166bbea6425SSaleem Abdulrasool return ELF::R_RISCV_ADD64;
167bbea6425SSaleem Abdulrasool case RISCV::fixup_riscv_sub_64:
168bbea6425SSaleem Abdulrasool return ELF::R_RISCV_SUB64;
1699d3f1250SAlex Bradbury }
1706b2cca7fSAlex Bradbury }
1716b2cca7fSAlex Bradbury
172dcd7d6c3SPeter Collingbourne std::unique_ptr<MCObjectTargetWriter>
createRISCVELFObjectWriter(uint8_t OSABI,bool Is64Bit)173dcd7d6c3SPeter Collingbourne llvm::createRISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit) {
1740eaee545SJonas Devlieghere return std::make_unique<RISCVELFObjectWriter>(OSABI, Is64Bit);
1756b2cca7fSAlex Bradbury }
176