144 lines · cpp
1//===-- SparcELFObjectWriter.cpp - Sparc 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/SparcFixupKinds.h"10#include "MCTargetDesc/SparcMCTargetDesc.h"11#include "llvm/MC/MCContext.h"12#include "llvm/MC/MCELFObjectWriter.h"13#include "llvm/MC/MCExpr.h"14#include "llvm/MC/MCObjectFileInfo.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 {22 class SparcELFObjectWriter : public MCELFObjectTargetWriter {23 public:24 SparcELFObjectWriter(bool Is64Bit, bool IsV8Plus, uint8_t OSABI)25 : MCELFObjectTargetWriter(26 Is64Bit, OSABI,27 Is64Bit ? ELF::EM_SPARCV928 : (IsV8Plus ? ELF::EM_SPARC32PLUS : ELF::EM_SPARC),29 /*HasRelocationAddend*/ true) {}30 31 ~SparcELFObjectWriter() override = default;32 33 protected:34 unsigned getRelocType(const MCFixup &Fixup, const MCValue &Target,35 bool IsPCRel) const override;36 37 bool needsRelocateWithSymbol(const MCValue &, unsigned Type) const override;38 };39}40 41unsigned SparcELFObjectWriter::getRelocType(const MCFixup &Fixup,42 const MCValue &Target,43 bool IsPCRel) const {44 switch (Target.getSpecifier()) {45 case ELF::R_SPARC_TLS_GD_HI22:46 case ELF::R_SPARC_TLS_GD_LO10:47 case ELF::R_SPARC_TLS_GD_ADD:48 case ELF::R_SPARC_TLS_LDM_HI22:49 case ELF::R_SPARC_TLS_LDM_LO10:50 case ELF::R_SPARC_TLS_LDM_ADD:51 case ELF::R_SPARC_TLS_LDO_HIX22:52 case ELF::R_SPARC_TLS_LDO_LOX10:53 case ELF::R_SPARC_TLS_LDO_ADD:54 case ELF::R_SPARC_TLS_IE_HI22:55 case ELF::R_SPARC_TLS_IE_LO10:56 case ELF::R_SPARC_TLS_IE_LD:57 case ELF::R_SPARC_TLS_IE_LDX:58 case ELF::R_SPARC_TLS_IE_ADD:59 case ELF::R_SPARC_TLS_LE_HIX22:60 case ELF::R_SPARC_TLS_LE_LOX10:61 if (auto *SA = const_cast<MCSymbol *>(Target.getAddSym()))62 static_cast<MCSymbolELF *>(SA)->setType(ELF::STT_TLS);63 break;64 default:65 break;66 }67 68 // Extract the relocation type from the fixup kind, after applying STT_TLS as69 // needed.70 auto Kind = Fixup.getKind();71 if (mc::isRelocation(Fixup.getKind()))72 return Kind;73 74 if (const auto *SExpr = dyn_cast<MCSpecifierExpr>(Fixup.getValue())) {75 if (SExpr->getSpecifier() == ELF::R_SPARC_DISP32)76 return ELF::R_SPARC_DISP32;77 }78 79 if (IsPCRel) {80 switch (Kind) {81 default:82 llvm_unreachable("Unimplemented fixup -> relocation");83 case FK_Data_1: return ELF::R_SPARC_DISP8;84 case FK_Data_2: return ELF::R_SPARC_DISP16;85 case FK_Data_4: return ELF::R_SPARC_DISP32;86 case FK_Data_8: return ELF::R_SPARC_DISP64;87 case Sparc::fixup_sparc_call30:88 if (getContext().getObjectFileInfo()->isPositionIndependent())89 return ELF::R_SPARC_WPLT30;90 return ELF::R_SPARC_WDISP30;91 }92 }93 94 // clang-format off95 switch(Fixup.getKind()) {96 default:97 llvm_unreachable("Unimplemented fixup -> relocation");98 case FK_NONE: return ELF::R_SPARC_NONE;99 case FK_Data_1: return ELF::R_SPARC_8;100 case FK_Data_2: return ((Fixup.getOffset() % 2)101 ? ELF::R_SPARC_UA16102 : ELF::R_SPARC_16);103 case FK_Data_4: return ((Fixup.getOffset() % 4)104 ? ELF::R_SPARC_UA32105 : ELF::R_SPARC_32);106 case FK_Data_8: return ((Fixup.getOffset() % 8)107 ? ELF::R_SPARC_UA64108 : ELF::R_SPARC_64);109 case Sparc::fixup_sparc_13:110 if (getContext().getObjectFileInfo()->isPositionIndependent())111 return ELF::R_SPARC_GOT13;112 return ELF::R_SPARC_13;113 }114 // clang-format on115 116 return ELF::R_SPARC_NONE;117}118 119bool SparcELFObjectWriter::needsRelocateWithSymbol(const MCValue &,120 unsigned Type) const {121 switch (Type) {122 default:123 return false;124 125 // All relocations that use a GOT need a symbol, not an offset, as126 // the offset of the symbol within the section is irrelevant to127 // where the GOT entry is. Don't need to list all the TLS entries,128 // as they're all marked as requiring a symbol anyways.129 case ELF::R_SPARC_GOT10:130 case ELF::R_SPARC_GOT13:131 case ELF::R_SPARC_GOT22:132 case ELF::R_SPARC_GOTDATA_HIX22:133 case ELF::R_SPARC_GOTDATA_LOX10:134 case ELF::R_SPARC_GOTDATA_OP_HIX22:135 case ELF::R_SPARC_GOTDATA_OP_LOX10:136 return true;137 }138}139 140std::unique_ptr<MCObjectTargetWriter>141llvm::createSparcELFObjectWriter(bool Is64Bit, bool IsV8Plus, uint8_t OSABI) {142 return std::make_unique<SparcELFObjectWriter>(Is64Bit, IsV8Plus, OSABI);143}144