152 lines · cpp
1//===-- RISCVELFObjectWriter.cpp - RISC-V 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-exception6//7//===----------------------------------------------------------------------===//8 9#include "MCTargetDesc/RISCVFixupKinds.h"10#include "MCTargetDesc/RISCVMCAsmInfo.h"11#include "MCTargetDesc/RISCVMCTargetDesc.h"12#include "llvm/MC/MCContext.h"13#include "llvm/MC/MCELFObjectWriter.h"14#include "llvm/MC/MCFixup.h"15#include "llvm/MC/MCObjectWriter.h"16#include "llvm/MC/MCValue.h"17#include "llvm/Support/ErrorHandling.h"18 19using namespace llvm;20 21namespace {22class RISCVELFObjectWriter : public MCELFObjectTargetWriter {23public:24 RISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit);25 26 ~RISCVELFObjectWriter() override;27 28 // Return true if the given relocation must be with a symbol rather than29 // section plus offset.30 bool needsRelocateWithSymbol(const MCValue &, unsigned Type) const override {31 // TODO: this is very conservative, update once RISC-V psABI requirements32 // are clarified.33 return true;34 }35 36protected:37 unsigned getRelocType(const MCFixup &, const MCValue &,38 bool IsPCRel) const override;39};40}41 42RISCVELFObjectWriter::RISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit)43 : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_RISCV,44 /*HasRelocationAddend*/ true) {}45 46RISCVELFObjectWriter::~RISCVELFObjectWriter() = default;47 48unsigned RISCVELFObjectWriter::getRelocType(const MCFixup &Fixup,49 const MCValue &Target,50 bool IsPCRel) const {51 auto Kind = Fixup.getKind();52 auto Spec = Target.getSpecifier();53 switch (Spec) {54 case ELF::R_RISCV_TPREL_HI20:55 case ELF::R_RISCV_TLS_GOT_HI20:56 case ELF::R_RISCV_TLS_GD_HI20:57 case ELF::R_RISCV_TLSDESC_HI20:58 if (auto *SA = const_cast<MCSymbol *>(Target.getAddSym()))59 static_cast<MCSymbolELF *>(SA)->setType(ELF::STT_TLS);60 break;61 case ELF::R_RISCV_PLT32:62 case ELF::R_RISCV_GOT32_PCREL:63 if (Kind == FK_Data_4)64 break;65 reportError(Fixup.getLoc(), "%" + RISCV::getSpecifierName(Spec) +66 " can only be used in a .word directive");67 return ELF::R_RISCV_NONE;68 default:69 break;70 }71 72 // Extract the relocation type from the fixup kind, after applying STT_TLS as73 // needed.74 if (mc::isRelocation(Fixup.getKind()))75 return Kind;76 77 if (IsPCRel) {78 switch (Kind) {79 default:80 reportError(Fixup.getLoc(), "unsupported relocation type");81 return ELF::R_RISCV_NONE;82 case FK_Data_4:83 return ELF::R_RISCV_32_PCREL;84 case RISCV::fixup_riscv_pcrel_hi20:85 return ELF::R_RISCV_PCREL_HI20;86 case RISCV::fixup_riscv_pcrel_lo12_i:87 return ELF::R_RISCV_PCREL_LO12_I;88 case RISCV::fixup_riscv_pcrel_lo12_s:89 return ELF::R_RISCV_PCREL_LO12_S;90 case RISCV::fixup_riscv_jal:91 return ELF::R_RISCV_JAL;92 case RISCV::fixup_riscv_branch:93 return ELF::R_RISCV_BRANCH;94 case RISCV::fixup_riscv_rvc_jump:95 return ELF::R_RISCV_RVC_JUMP;96 case RISCV::fixup_riscv_rvc_branch:97 return ELF::R_RISCV_RVC_BRANCH;98 case RISCV::fixup_riscv_call:99 return ELF::R_RISCV_CALL_PLT;100 case RISCV::fixup_riscv_call_plt:101 return ELF::R_RISCV_CALL_PLT;102 case RISCV::fixup_riscv_qc_e_branch:103 return ELF::R_RISCV_QC_E_BRANCH;104 case RISCV::fixup_riscv_qc_e_call_plt:105 return ELF::R_RISCV_QC_E_CALL_PLT;106 case RISCV::fixup_riscv_nds_branch_10:107 return ELF::R_RISCV_NDS_BRANCH_10;108 }109 }110 111 switch (Kind) {112 default:113 reportError(Fixup.getLoc(), "unsupported relocation type");114 return ELF::R_RISCV_NONE;115 116 case FK_Data_1:117 reportError(Fixup.getLoc(), "1-byte data relocations not supported");118 return ELF::R_RISCV_NONE;119 case FK_Data_2:120 reportError(Fixup.getLoc(), "2-byte data relocations not supported");121 return ELF::R_RISCV_NONE;122 case FK_Data_4:123 switch (Spec) {124 case ELF::R_RISCV_32_PCREL:125 case ELF::R_RISCV_GOT32_PCREL:126 case ELF::R_RISCV_PLT32:127 return Spec;128 }129 return ELF::R_RISCV_32;130 case FK_Data_8:131 return ELF::R_RISCV_64;132 case RISCV::fixup_riscv_hi20:133 return ELF::R_RISCV_HI20;134 case RISCV::fixup_riscv_lo12_i:135 return ELF::R_RISCV_LO12_I;136 case RISCV::fixup_riscv_lo12_s:137 return ELF::R_RISCV_LO12_S;138 case RISCV::fixup_riscv_rvc_imm:139 reportError(Fixup.getLoc(), "No relocation for CI-type instructions");140 return ELF::R_RISCV_NONE;141 case RISCV::fixup_riscv_qc_e_32:142 return ELF::R_RISCV_QC_E_32;143 case RISCV::fixup_riscv_qc_abs20_u:144 return ELF::R_RISCV_QC_ABS20_U;145 }146}147 148std::unique_ptr<MCObjectTargetWriter>149llvm::createRISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit) {150 return std::make_unique<RISCVELFObjectWriter>(OSABI, Is64Bit);151}152