1 //===-- RISCVELFObjectWriter.cpp - RISCV ELF Writer -----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "MCTargetDesc/RISCVFixupKinds.h" 10 #include "MCTargetDesc/RISCVMCExpr.h" 11 #include "MCTargetDesc/RISCVMCTargetDesc.h" 12 #include "llvm/MC/MCELFObjectWriter.h" 13 #include "llvm/MC/MCFixup.h" 14 #include "llvm/MC/MCObjectWriter.h" 15 #include "llvm/Support/ErrorHandling.h" 16 17 using namespace llvm; 18 19 namespace { 20 class RISCVELFObjectWriter : public MCELFObjectTargetWriter { 21 public: 22 RISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit); 23 24 ~RISCVELFObjectWriter() override; 25 26 // Return true if the given relocation must be with a symbol rather than 27 // section plus offset. 28 bool needsRelocateWithSymbol(const MCSymbol &Sym, 29 unsigned Type) const override { 30 // TODO: this is very conservative, update once RISC-V psABI requirements 31 // are clarified. 32 return true; 33 } 34 35 protected: 36 unsigned getRelocType(MCContext &Ctx, const MCValue &Target, 37 const MCFixup &Fixup, bool IsPCRel) const override; 38 }; 39 } 40 41 RISCVELFObjectWriter::RISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit) 42 : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_RISCV, 43 /*HasRelocationAddend*/ true) {} 44 45 RISCVELFObjectWriter::~RISCVELFObjectWriter() {} 46 47 unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx, 48 const MCValue &Target, 49 const MCFixup &Fixup, 50 bool IsPCRel) const { 51 const MCExpr *Expr = Fixup.getValue(); 52 // Determine the type of the relocation 53 unsigned Kind = Fixup.getTargetKind(); 54 if (IsPCRel) { 55 switch (Kind) { 56 default: 57 llvm_unreachable("invalid fixup kind!"); 58 case FK_Data_4: 59 case FK_PCRel_4: 60 return ELF::R_RISCV_32_PCREL; 61 case RISCV::fixup_riscv_pcrel_hi20: 62 return ELF::R_RISCV_PCREL_HI20; 63 case RISCV::fixup_riscv_pcrel_lo12_i: 64 return ELF::R_RISCV_PCREL_LO12_I; 65 case RISCV::fixup_riscv_pcrel_lo12_s: 66 return ELF::R_RISCV_PCREL_LO12_S; 67 case RISCV::fixup_riscv_got_hi20: 68 return ELF::R_RISCV_GOT_HI20; 69 case RISCV::fixup_riscv_tls_got_hi20: 70 return ELF::R_RISCV_TLS_GOT_HI20; 71 case RISCV::fixup_riscv_tls_gd_hi20: 72 return ELF::R_RISCV_TLS_GD_HI20; 73 case RISCV::fixup_riscv_jal: 74 return ELF::R_RISCV_JAL; 75 case RISCV::fixup_riscv_branch: 76 return ELF::R_RISCV_BRANCH; 77 case RISCV::fixup_riscv_rvc_jump: 78 return ELF::R_RISCV_RVC_JUMP; 79 case RISCV::fixup_riscv_rvc_branch: 80 return ELF::R_RISCV_RVC_BRANCH; 81 case RISCV::fixup_riscv_call: 82 return ELF::R_RISCV_CALL; 83 case RISCV::fixup_riscv_call_plt: 84 return ELF::R_RISCV_CALL_PLT; 85 } 86 } 87 88 switch (Kind) { 89 default: 90 llvm_unreachable("invalid fixup kind!"); 91 case FK_Data_4: 92 if (Expr->getKind() == MCExpr::Target && 93 cast<RISCVMCExpr>(Expr)->getKind() == RISCVMCExpr::VK_RISCV_32_PCREL) 94 return ELF::R_RISCV_32_PCREL; 95 return ELF::R_RISCV_32; 96 case FK_Data_8: 97 return ELF::R_RISCV_64; 98 case FK_Data_Add_1: 99 return ELF::R_RISCV_ADD8; 100 case FK_Data_Add_2: 101 return ELF::R_RISCV_ADD16; 102 case FK_Data_Add_4: 103 return ELF::R_RISCV_ADD32; 104 case FK_Data_Add_8: 105 return ELF::R_RISCV_ADD64; 106 case FK_Data_Add_6b: 107 return ELF::R_RISCV_SET6; 108 case FK_Data_Sub_1: 109 return ELF::R_RISCV_SUB8; 110 case FK_Data_Sub_2: 111 return ELF::R_RISCV_SUB16; 112 case FK_Data_Sub_4: 113 return ELF::R_RISCV_SUB32; 114 case FK_Data_Sub_8: 115 return ELF::R_RISCV_SUB64; 116 case FK_Data_Sub_6b: 117 return ELF::R_RISCV_SUB6; 118 case RISCV::fixup_riscv_hi20: 119 return ELF::R_RISCV_HI20; 120 case RISCV::fixup_riscv_lo12_i: 121 return ELF::R_RISCV_LO12_I; 122 case RISCV::fixup_riscv_lo12_s: 123 return ELF::R_RISCV_LO12_S; 124 case RISCV::fixup_riscv_tprel_hi20: 125 return ELF::R_RISCV_TPREL_HI20; 126 case RISCV::fixup_riscv_tprel_lo12_i: 127 return ELF::R_RISCV_TPREL_LO12_I; 128 case RISCV::fixup_riscv_tprel_lo12_s: 129 return ELF::R_RISCV_TPREL_LO12_S; 130 case RISCV::fixup_riscv_tprel_add: 131 return ELF::R_RISCV_TPREL_ADD; 132 case RISCV::fixup_riscv_relax: 133 return ELF::R_RISCV_RELAX; 134 case RISCV::fixup_riscv_align: 135 return ELF::R_RISCV_ALIGN; 136 } 137 } 138 139 std::unique_ptr<MCObjectTargetWriter> 140 llvm::createRISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit) { 141 return std::make_unique<RISCVELFObjectWriter>(OSABI, Is64Bit); 142 } 143