106c3fb27SDimitry Andric //===-- RISCVELFObjectWriter.cpp - RISC-V ELF Writer ----------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "MCTargetDesc/RISCVFixupKinds.h" 100b57cec5SDimitry Andric #include "MCTargetDesc/RISCVMCExpr.h" 110b57cec5SDimitry Andric #include "MCTargetDesc/RISCVMCTargetDesc.h" 12480093f4SDimitry Andric #include "llvm/MC/MCContext.h" 130b57cec5SDimitry Andric #include "llvm/MC/MCELFObjectWriter.h" 140b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h" 150b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h" 1606c3fb27SDimitry Andric #include "llvm/MC/MCValue.h" 170b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric using namespace llvm; 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric namespace { 220b57cec5SDimitry Andric class RISCVELFObjectWriter : public MCELFObjectTargetWriter { 230b57cec5SDimitry Andric public: 240b57cec5SDimitry Andric RISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit); 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric ~RISCVELFObjectWriter() override; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric // Return true if the given relocation must be with a symbol rather than 290b57cec5SDimitry Andric // section plus offset. 305f757f3fSDimitry Andric bool needsRelocateWithSymbol(const MCValue &Val, const MCSymbol &Sym, 310b57cec5SDimitry Andric unsigned Type) const override { 320b57cec5SDimitry Andric // TODO: this is very conservative, update once RISC-V psABI requirements 330b57cec5SDimitry Andric // are clarified. 340b57cec5SDimitry Andric return true; 350b57cec5SDimitry Andric } 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric protected: 380b57cec5SDimitry Andric unsigned getRelocType(MCContext &Ctx, const MCValue &Target, 390b57cec5SDimitry Andric const MCFixup &Fixup, bool IsPCRel) const override; 400b57cec5SDimitry Andric }; 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric RISCVELFObjectWriter::RISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit) 440b57cec5SDimitry Andric : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_RISCV, 450b57cec5SDimitry Andric /*HasRelocationAddend*/ true) {} 460b57cec5SDimitry Andric 4781ad6265SDimitry Andric RISCVELFObjectWriter::~RISCVELFObjectWriter() = default; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx, 500b57cec5SDimitry Andric const MCValue &Target, 510b57cec5SDimitry Andric const MCFixup &Fixup, 520b57cec5SDimitry Andric bool IsPCRel) const { 530b57cec5SDimitry Andric const MCExpr *Expr = Fixup.getValue(); 540b57cec5SDimitry Andric // Determine the type of the relocation 558bcb0991SDimitry Andric unsigned Kind = Fixup.getTargetKind(); 565ffd83dbSDimitry Andric if (Kind >= FirstLiteralRelocationKind) 575ffd83dbSDimitry Andric return Kind - FirstLiteralRelocationKind; 580b57cec5SDimitry Andric if (IsPCRel) { 590b57cec5SDimitry Andric switch (Kind) { 600b57cec5SDimitry Andric default: 6106c3fb27SDimitry Andric Ctx.reportError(Fixup.getLoc(), "unsupported relocation type"); 62480093f4SDimitry Andric return ELF::R_RISCV_NONE; 630b57cec5SDimitry Andric case FK_Data_4: 640b57cec5SDimitry Andric case FK_PCRel_4: 6506c3fb27SDimitry Andric return Target.getAccessVariant() == MCSymbolRefExpr::VK_PLT 6606c3fb27SDimitry Andric ? ELF::R_RISCV_PLT32 6706c3fb27SDimitry Andric : ELF::R_RISCV_32_PCREL; 680b57cec5SDimitry Andric case RISCV::fixup_riscv_pcrel_hi20: 690b57cec5SDimitry Andric return ELF::R_RISCV_PCREL_HI20; 700b57cec5SDimitry Andric case RISCV::fixup_riscv_pcrel_lo12_i: 710b57cec5SDimitry Andric return ELF::R_RISCV_PCREL_LO12_I; 720b57cec5SDimitry Andric case RISCV::fixup_riscv_pcrel_lo12_s: 730b57cec5SDimitry Andric return ELF::R_RISCV_PCREL_LO12_S; 740b57cec5SDimitry Andric case RISCV::fixup_riscv_got_hi20: 750b57cec5SDimitry Andric return ELF::R_RISCV_GOT_HI20; 760b57cec5SDimitry Andric case RISCV::fixup_riscv_tls_got_hi20: 770b57cec5SDimitry Andric return ELF::R_RISCV_TLS_GOT_HI20; 780b57cec5SDimitry Andric case RISCV::fixup_riscv_tls_gd_hi20: 790b57cec5SDimitry Andric return ELF::R_RISCV_TLS_GD_HI20; 80*7a6dacacSDimitry Andric case RISCV::fixup_riscv_tlsdesc_hi20: 81*7a6dacacSDimitry Andric return ELF::R_RISCV_TLSDESC_HI20; 82*7a6dacacSDimitry Andric case RISCV::fixup_riscv_tlsdesc_load_lo12: 83*7a6dacacSDimitry Andric return ELF::R_RISCV_TLSDESC_LOAD_LO12; 84*7a6dacacSDimitry Andric case RISCV::fixup_riscv_tlsdesc_add_lo12: 85*7a6dacacSDimitry Andric return ELF::R_RISCV_TLSDESC_ADD_LO12; 86*7a6dacacSDimitry Andric case RISCV::fixup_riscv_tlsdesc_call: 87*7a6dacacSDimitry Andric return ELF::R_RISCV_TLSDESC_CALL; 880b57cec5SDimitry Andric case RISCV::fixup_riscv_jal: 890b57cec5SDimitry Andric return ELF::R_RISCV_JAL; 900b57cec5SDimitry Andric case RISCV::fixup_riscv_branch: 910b57cec5SDimitry Andric return ELF::R_RISCV_BRANCH; 920b57cec5SDimitry Andric case RISCV::fixup_riscv_rvc_jump: 930b57cec5SDimitry Andric return ELF::R_RISCV_RVC_JUMP; 940b57cec5SDimitry Andric case RISCV::fixup_riscv_rvc_branch: 950b57cec5SDimitry Andric return ELF::R_RISCV_RVC_BRANCH; 960b57cec5SDimitry Andric case RISCV::fixup_riscv_call: 97bdd1243dSDimitry Andric return ELF::R_RISCV_CALL_PLT; 980b57cec5SDimitry Andric case RISCV::fixup_riscv_call_plt: 990b57cec5SDimitry Andric return ELF::R_RISCV_CALL_PLT; 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric switch (Kind) { 1040b57cec5SDimitry Andric default: 10506c3fb27SDimitry Andric Ctx.reportError(Fixup.getLoc(), "unsupported relocation type"); 106480093f4SDimitry Andric return ELF::R_RISCV_NONE; 107*7a6dacacSDimitry Andric case RISCV::fixup_riscv_tlsdesc_load_lo12: 108*7a6dacacSDimitry Andric return ELF::R_RISCV_TLSDESC_LOAD_LO12; 109*7a6dacacSDimitry Andric case RISCV::fixup_riscv_tlsdesc_add_lo12: 110*7a6dacacSDimitry Andric return ELF::R_RISCV_TLSDESC_ADD_LO12; 111*7a6dacacSDimitry Andric case RISCV::fixup_riscv_tlsdesc_call: 112*7a6dacacSDimitry Andric return ELF::R_RISCV_TLSDESC_CALL; 113*7a6dacacSDimitry Andric 114480093f4SDimitry Andric case FK_Data_1: 115480093f4SDimitry Andric Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported"); 116480093f4SDimitry Andric return ELF::R_RISCV_NONE; 117480093f4SDimitry Andric case FK_Data_2: 118480093f4SDimitry Andric Ctx.reportError(Fixup.getLoc(), "2-byte data relocations not supported"); 119480093f4SDimitry Andric return ELF::R_RISCV_NONE; 1200b57cec5SDimitry Andric case FK_Data_4: 1210b57cec5SDimitry Andric if (Expr->getKind() == MCExpr::Target && 1220b57cec5SDimitry Andric cast<RISCVMCExpr>(Expr)->getKind() == RISCVMCExpr::VK_RISCV_32_PCREL) 1230b57cec5SDimitry Andric return ELF::R_RISCV_32_PCREL; 124297eecfbSDimitry Andric if (Target.getSymA()->getKind() == MCSymbolRefExpr::VK_GOTPCREL) 125297eecfbSDimitry Andric return ELF::R_RISCV_GOT32_PCREL; 1260b57cec5SDimitry Andric return ELF::R_RISCV_32; 1270b57cec5SDimitry Andric case FK_Data_8: 1280b57cec5SDimitry Andric return ELF::R_RISCV_64; 1290b57cec5SDimitry Andric case RISCV::fixup_riscv_hi20: 1300b57cec5SDimitry Andric return ELF::R_RISCV_HI20; 1310b57cec5SDimitry Andric case RISCV::fixup_riscv_lo12_i: 1320b57cec5SDimitry Andric return ELF::R_RISCV_LO12_I; 1330b57cec5SDimitry Andric case RISCV::fixup_riscv_lo12_s: 1340b57cec5SDimitry Andric return ELF::R_RISCV_LO12_S; 1350b57cec5SDimitry Andric case RISCV::fixup_riscv_tprel_hi20: 1360b57cec5SDimitry Andric return ELF::R_RISCV_TPREL_HI20; 1370b57cec5SDimitry Andric case RISCV::fixup_riscv_tprel_lo12_i: 1380b57cec5SDimitry Andric return ELF::R_RISCV_TPREL_LO12_I; 1390b57cec5SDimitry Andric case RISCV::fixup_riscv_tprel_lo12_s: 1400b57cec5SDimitry Andric return ELF::R_RISCV_TPREL_LO12_S; 1410b57cec5SDimitry Andric case RISCV::fixup_riscv_tprel_add: 1420b57cec5SDimitry Andric return ELF::R_RISCV_TPREL_ADD; 1430b57cec5SDimitry Andric case RISCV::fixup_riscv_relax: 1440b57cec5SDimitry Andric return ELF::R_RISCV_RELAX; 1450b57cec5SDimitry Andric case RISCV::fixup_riscv_align: 1460b57cec5SDimitry Andric return ELF::R_RISCV_ALIGN; 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric std::unique_ptr<MCObjectTargetWriter> 1510b57cec5SDimitry Andric llvm::createRISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit) { 1528bcb0991SDimitry Andric return std::make_unique<RISCVELFObjectWriter>(OSABI, Is64Bit); 1530b57cec5SDimitry Andric } 154