1 //===-- CSKYELFObjectWriter.cpp - CSKY 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 "CSKYFixupKinds.h"
10 #include "CSKYMCAsmInfo.h"
11 #include "CSKYMCTargetDesc.h"
12 #include "MCTargetDesc/CSKYMCAsmInfo.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCELFObjectWriter.h"
15 #include "llvm/MC/MCObjectWriter.h"
16 #include "llvm/MC/MCSymbolELF.h"
17
18 #define DEBUG_TYPE "csky-elf-object-writer"
19
20 using namespace llvm;
21
22 namespace {
23
24 class CSKYELFObjectWriter : public MCELFObjectTargetWriter {
25 public:
CSKYELFObjectWriter(uint8_t OSABI=0)26 CSKYELFObjectWriter(uint8_t OSABI = 0)
27 : MCELFObjectTargetWriter(false, OSABI, ELF::EM_CSKY, true){};
~CSKYELFObjectWriter()28 ~CSKYELFObjectWriter() {}
29
30 unsigned getRelocType(const MCFixup &, const MCValue &,
31 bool IsPCRel) const override;
32 bool needsRelocateWithSymbol(const MCValue &, unsigned Type) const override;
33 };
34
35 } // namespace
36
getRelocType(const MCFixup & Fixup,const MCValue & Target,bool IsPCRel) const37 unsigned CSKYELFObjectWriter::getRelocType(const MCFixup &Fixup,
38 const MCValue &Target,
39 bool IsPCRel) const {
40 const MCExpr *Expr = Fixup.getValue();
41 // Determine the type of the relocation
42 auto Kind = Fixup.getKind();
43 uint8_t Modifier = Target.getSpecifier();
44
45 switch (Target.getSpecifier()) {
46 case CSKY::S_TLSIE:
47 case CSKY::S_TLSLE:
48 case CSKY::S_TLSGD:
49 case CSKY::S_TLSLDM:
50 case CSKY::S_TLSLDO:
51 if (auto *SA = Target.getAddSym())
52 cast<MCSymbolELF>(SA)->setType(ELF::STT_TLS);
53 break;
54 default:
55 break;
56 }
57
58 if (IsPCRel) {
59 switch (Kind) {
60 default:
61 LLVM_DEBUG(dbgs() << "Unknown Kind1 = " << Kind);
62 reportError(Fixup.getLoc(), "Unsupported relocation type");
63 return ELF::R_CKCORE_NONE;
64 case FK_Data_4:
65 return ELF::R_CKCORE_PCREL32;
66 case CSKY::fixup_csky_pcrel_uimm16_scale4:
67 return ELF::R_CKCORE_PCREL_IMM16_4;
68 case CSKY::fixup_csky_pcrel_uimm8_scale4:
69 return ELF::R_CKCORE_PCREL_IMM8_4;
70 case CSKY::fixup_csky_pcrel_imm26_scale2:
71 return ELF::R_CKCORE_PCREL_IMM26_2;
72 case CSKY::fixup_csky_pcrel_imm18_scale2:
73 return ELF::R_CKCORE_PCREL_IMM18_2;
74 case CSKY::fixup_csky_pcrel_imm16_scale2:
75 return ELF::R_CKCORE_PCREL_IMM16_2;
76 case CSKY::fixup_csky_pcrel_imm10_scale2:
77 return ELF::R_CKCORE_PCREL_IMM10_2;
78 case CSKY::fixup_csky_pcrel_uimm7_scale4:
79 return ELF::R_CKCORE_PCREL_IMM7_4;
80 }
81 }
82
83 switch (Kind) {
84 default:
85 LLVM_DEBUG(dbgs() << "Unknown Kind2 = " << Kind);
86 reportError(Fixup.getLoc(), "Unsupported relocation type");
87 return ELF::R_CKCORE_NONE;
88 case FK_Data_1:
89 reportError(Fixup.getLoc(), "1-byte data relocations not supported");
90 return ELF::R_CKCORE_NONE;
91 case FK_Data_2:
92 reportError(Fixup.getLoc(), "2-byte data relocations not supported");
93 return ELF::R_CKCORE_NONE;
94 case FK_Data_4:
95 if (Expr->getKind() == MCExpr::Specifier) {
96 auto TK = cast<MCSpecifierExpr>(Expr)->getSpecifier();
97 if (TK == CSKY::S_ADDR)
98 return ELF::R_CKCORE_ADDR32;
99 if (TK == CSKY::S_GOT)
100 return ELF::R_CKCORE_GOT32;
101 if (TK == CSKY::S_GOTOFF)
102 return ELF::R_CKCORE_GOTOFF;
103 if (TK == CSKY::S_PLT)
104 return ELF::R_CKCORE_PLT32;
105 if (TK == CSKY::S_TLSIE)
106 return ELF::R_CKCORE_TLS_IE32;
107 if (TK == CSKY::S_TLSLE)
108 return ELF::R_CKCORE_TLS_LE32;
109 if (TK == CSKY::S_TLSGD)
110 return ELF::R_CKCORE_TLS_GD32;
111 if (TK == CSKY::S_TLSLDM)
112 return ELF::R_CKCORE_TLS_LDM32;
113 if (TK == CSKY::S_TLSLDO)
114 return ELF::R_CKCORE_TLS_LDO32;
115 if (TK == CSKY::S_GOTPC)
116 return ELF::R_CKCORE_GOTPC;
117 if (TK == CSKY::S_None)
118 return ELF::R_CKCORE_ADDR32;
119
120 LLVM_DEBUG(dbgs() << "Unknown FK_Data_4 TK = " << TK);
121 reportError(Fixup.getLoc(), "unknown target FK_Data_4");
122 } else {
123 switch (Modifier) {
124 default:
125 reportError(Fixup.getLoc(), "invalid fixup for 4-byte data relocation");
126 return ELF::R_CKCORE_NONE;
127 case CSKY::S_GOT:
128 return ELF::R_CKCORE_GOT32;
129 case CSKY::S_GOTOFF:
130 return ELF::R_CKCORE_GOTOFF;
131 case CSKY::S_PLT:
132 return ELF::R_CKCORE_PLT32;
133 case CSKY::S_TLSGD:
134 return ELF::R_CKCORE_TLS_GD32;
135 case CSKY::S_TLSLDM:
136 return ELF::R_CKCORE_TLS_LDM32;
137 case CSKY::S_TPOFF:
138 return ELF::R_CKCORE_TLS_LE32;
139 case CSKY::S_None:
140 return ELF::R_CKCORE_ADDR32;
141 }
142 }
143 return ELF::R_CKCORE_NONE;
144 case FK_Data_8:
145 reportError(Fixup.getLoc(), "8-byte data relocations not supported");
146 return ELF::R_CKCORE_NONE;
147 case CSKY::fixup_csky_addr32:
148 return ELF::R_CKCORE_ADDR32;
149 case CSKY::fixup_csky_addr_hi16:
150 return ELF::R_CKCORE_ADDR_HI16;
151 case CSKY::fixup_csky_addr_lo16:
152 return ELF::R_CKCORE_ADDR_LO16;
153 case CSKY::fixup_csky_doffset_imm18:
154 return ELF::R_CKCORE_DOFFSET_IMM18;
155 case CSKY::fixup_csky_doffset_imm18_scale2:
156 return ELF::R_CKCORE_DOFFSET_IMM18_2;
157 case CSKY::fixup_csky_doffset_imm18_scale4:
158 return ELF::R_CKCORE_DOFFSET_IMM18_4;
159 case CSKY::fixup_csky_got_imm18_scale4:
160 return ELF::R_CKCORE_GOT_IMM18_4;
161 case CSKY::fixup_csky_plt_imm18_scale4:
162 return ELF::R_CKCORE_PLT_IMM18_4;
163 }
164 }
165
needsRelocateWithSymbol(const MCValue & V,unsigned Type) const166 bool CSKYELFObjectWriter::needsRelocateWithSymbol(const MCValue &V,
167 unsigned Type) const {
168 switch (V.getSpecifier()) {
169 case CSKY::S_PLT:
170 case CSKY::S_GOT:
171 return true;
172 default:
173 return false;
174 }
175 }
176
createCSKYELFObjectWriter()177 std::unique_ptr<MCObjectTargetWriter> llvm::createCSKYELFObjectWriter() {
178 return std::make_unique<CSKYELFObjectWriter>();
179 }
180