1//===-- ARMELFObjectWriter.cpp - ARM 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/ARMFixupKinds.h"
10#include "MCTargetDesc/ARMMCAsmInfo.h"
11#include "MCTargetDesc/ARMMCTargetDesc.h"
12#include "llvm/BinaryFormat/ELF.h"
13#include "llvm/MC/MCAssembler.h"
14#include "llvm/MC/MCContext.h"
15#include "llvm/MC/MCELFObjectWriter.h"
16#include "llvm/MC/MCExpr.h"
17#include "llvm/MC/MCFixup.h"
18#include "llvm/MC/MCObjectWriter.h"
19#include "llvm/MC/MCValue.h"
20#include "llvm/Object/ELF.h"
21#include "llvm/Support/ErrorHandling.h"
22#include <cstdint>
23
24using namespace llvm;
25
26namespace {
27
28class ARMELFObjectWriter : public MCELFObjectTargetWriter {
29 enum { DefaultEABIVersion = 0x05000000U };
30
31public:
32 ARMELFObjectWriter(uint8_t OSABI);
33
34 ~ARMELFObjectWriter() override = default;
35
36 unsigned getRelocType(const MCFixup &, const MCValue &,
37 bool IsPCRel) const override;
38
39 bool needsRelocateWithSymbol(const MCValue &Val,
40 unsigned Type) const override;
41};
42
43} // end anonymous namespace
44
45ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI)
46 : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI,
47 ELF::EM_ARM,
48 /*HasRelocationAddend*/ false) {}
49
50bool ARMELFObjectWriter::needsRelocateWithSymbol(const MCValue &V,
51 unsigned Type) const {
52 // If the symbol is a thumb function the final relocation must set the lowest
53 // bit. With a symbol that is done by just having the symbol have that bit
54 // set, so we would lose the bit if we relocated with the section.
55 // We could use the section but add the bit to the relocation value.
56 if (Asm->isThumbFunc(Func: V.getAddSym()))
57 return true;
58
59 // FIXME: This is extremely conservative. This really needs to use an
60 // explicit list with a clear explanation for why each realocation needs to
61 // point to the symbol, not to the section.
62 switch (Type) {
63 default:
64 return true;
65
66 case ELF::R_ARM_PREL31:
67 case ELF::R_ARM_ABS32:
68 return false;
69 }
70}
71
72// Need to examine the Fixup when determining whether to
73// emit the relocation as an explicit symbol or as a section relative
74// offset
75unsigned ARMELFObjectWriter::getRelocType(const MCFixup &Fixup,
76 const MCValue &Target,
77 bool IsPCRel) const {
78 unsigned Kind = Fixup.getTargetKind();
79 uint8_t Specifier = Target.getSpecifier();
80 auto CheckFDPIC = [&](uint32_t Type) {
81 if (getOSABI() != ELF::ELFOSABI_ARM_FDPIC)
82 reportError(L: Fixup.getLoc(),
83 Msg: "relocation " +
84 object::getELFRelocationTypeName(Machine: ELF::EM_ARM, Type) +
85 " only supported in FDPIC mode");
86 return Type;
87 };
88
89 switch (Specifier) {
90 case ARM::S_GOTTPOFF:
91 case ARM::S_GOTTPOFF_FDPIC:
92 case ARM::S_TLSCALL:
93 case ARM::S_TLSDESC:
94 case ARM::S_TLSGD:
95 case ARM::S_TLSGD_FDPIC:
96 case ARM::S_TLSLDM:
97 case ARM::S_TLSLDM_FDPIC:
98 case ARM::S_TLSLDO:
99 case ARM::S_TPOFF:
100 if (auto *SA = Target.getAddSym())
101 cast<MCSymbolELF>(Val: SA)->setType(ELF::STT_TLS);
102 break;
103 default:
104 break;
105 }
106
107 if (IsPCRel) {
108 switch (Fixup.getTargetKind()) {
109 default:
110 reportError(L: Fixup.getLoc(), Msg: "unsupported relocation type");
111 return ELF::R_ARM_NONE;
112 case FK_Data_4:
113 switch (Specifier) {
114 default:
115 reportError(L: Fixup.getLoc(),
116 Msg: "invalid fixup for 4-byte pc-relative data relocation");
117 return ELF::R_ARM_NONE;
118 case ARM::S_None: {
119 if (const auto *SA = Target.getAddSym()) {
120 // For GNU AS compatibility expressions such as
121 // _GLOBAL_OFFSET_TABLE_ - label emit a R_ARM_BASE_PREL relocation.
122 if (SA->getName() == "_GLOBAL_OFFSET_TABLE_")
123 return ELF::R_ARM_BASE_PREL;
124 }
125 return ELF::R_ARM_REL32;
126 }
127 case ARM::S_GOTTPOFF:
128 return ELF::R_ARM_TLS_IE32;
129 case ARM::S_GOT_PREL:
130 return ELF::R_ARM_GOT_PREL;
131 case ARM::S_PREL31:
132 return ELF::R_ARM_PREL31;
133 }
134 case ARM::fixup_arm_blx:
135 case ARM::fixup_arm_uncondbl:
136 switch (Specifier) {
137 case ARM::S_PLT:
138 return ELF::R_ARM_CALL;
139 case ARM::S_TLSCALL:
140 return ELF::R_ARM_TLS_CALL;
141 default:
142 return ELF::R_ARM_CALL;
143 }
144 case ARM::fixup_arm_condbl:
145 case ARM::fixup_arm_condbranch:
146 case ARM::fixup_arm_uncondbranch:
147 return ELF::R_ARM_JUMP24;
148 case ARM::fixup_t2_condbranch:
149 return ELF::R_ARM_THM_JUMP19;
150 case ARM::fixup_t2_uncondbranch:
151 return ELF::R_ARM_THM_JUMP24;
152 case ARM::fixup_arm_movt_hi16:
153 return ELF::R_ARM_MOVT_PREL;
154 case ARM::fixup_arm_movw_lo16:
155 return ELF::R_ARM_MOVW_PREL_NC;
156 case ARM::fixup_t2_movt_hi16:
157 return ELF::R_ARM_THM_MOVT_PREL;
158 case ARM::fixup_t2_movw_lo16:
159 return ELF::R_ARM_THM_MOVW_PREL_NC;
160 case ARM::fixup_arm_thumb_upper_8_15:
161 return ELF::R_ARM_THM_ALU_ABS_G3;
162 case ARM::fixup_arm_thumb_upper_0_7:
163 return ELF::R_ARM_THM_ALU_ABS_G2_NC;
164 case ARM::fixup_arm_thumb_lower_8_15:
165 return ELF::R_ARM_THM_ALU_ABS_G1_NC;
166 case ARM::fixup_arm_thumb_lower_0_7:
167 return ELF::R_ARM_THM_ALU_ABS_G0_NC;
168 case ARM::fixup_arm_thumb_br:
169 return ELF::R_ARM_THM_JUMP11;
170 case ARM::fixup_arm_thumb_bcc:
171 return ELF::R_ARM_THM_JUMP8;
172 case ARM::fixup_arm_thumb_bl:
173 case ARM::fixup_arm_thumb_blx:
174 switch (Specifier) {
175 case ARM::S_TLSCALL:
176 return ELF::R_ARM_THM_TLS_CALL;
177 default:
178 return ELF::R_ARM_THM_CALL;
179 }
180 case ARM::fixup_arm_ldst_pcrel_12:
181 return ELF::R_ARM_LDR_PC_G0;
182 case ARM::fixup_arm_pcrel_10_unscaled:
183 return ELF::R_ARM_LDRS_PC_G0;
184 case ARM::fixup_t2_ldst_pcrel_12:
185 return ELF::R_ARM_THM_PC12;
186 case ARM::fixup_arm_adr_pcrel_12:
187 return ELF::R_ARM_ALU_PC_G0;
188 case ARM::fixup_thumb_adr_pcrel_10:
189 return ELF::R_ARM_THM_PC8;
190 case ARM::fixup_t2_adr_pcrel_12:
191 return ELF::R_ARM_THM_ALU_PREL_11_0;
192 case ARM::fixup_bf_target:
193 return ELF::R_ARM_THM_BF16;
194 case ARM::fixup_bfc_target:
195 return ELF::R_ARM_THM_BF12;
196 case ARM::fixup_bfl_target:
197 return ELF::R_ARM_THM_BF18;
198 }
199 }
200 switch (Kind) {
201 default:
202 reportError(L: Fixup.getLoc(), Msg: "unsupported relocation type");
203 return ELF::R_ARM_NONE;
204 case FK_Data_1:
205 switch (Specifier) {
206 default:
207 reportError(L: Fixup.getLoc(), Msg: "invalid fixup for 1-byte data relocation");
208 return ELF::R_ARM_NONE;
209 case ARM::S_None:
210 return ELF::R_ARM_ABS8;
211 }
212 case FK_Data_2:
213 switch (Specifier) {
214 default:
215 reportError(L: Fixup.getLoc(), Msg: "invalid fixup for 2-byte data relocation");
216 return ELF::R_ARM_NONE;
217 case ARM::S_None:
218 return ELF::R_ARM_ABS16;
219 }
220 case FK_Data_4:
221 switch (Specifier) {
222 default:
223 reportError(L: Fixup.getLoc(), Msg: "invalid fixup for 4-byte data relocation");
224 return ELF::R_ARM_NONE;
225 case ARM::S_ARM_NONE:
226 return ELF::R_ARM_NONE;
227 case ARM::S_GOT:
228 return ELF::R_ARM_GOT_BREL;
229 case ARM::S_TLSGD:
230 return ELF::R_ARM_TLS_GD32;
231 case ARM::S_TPOFF:
232 return ELF::R_ARM_TLS_LE32;
233 case ARM::S_GOTTPOFF:
234 return ELF::R_ARM_TLS_IE32;
235 case ARM::S_None:
236 return ELF::R_ARM_ABS32;
237 case ARM::S_GOTOFF:
238 return ELF::R_ARM_GOTOFF32;
239 case ARM::S_GOT_PREL:
240 return ELF::R_ARM_GOT_PREL;
241 case ARM::S_TARGET1:
242 return ELF::R_ARM_TARGET1;
243 case ARM::S_TARGET2:
244 return ELF::R_ARM_TARGET2;
245 case ARM::S_PREL31:
246 return ELF::R_ARM_PREL31;
247 case ARM::S_SBREL:
248 return ELF::R_ARM_SBREL32;
249 case ARM::S_TLSLDO:
250 return ELF::R_ARM_TLS_LDO32;
251 case ARM::S_TLSCALL:
252 return ELF::R_ARM_TLS_CALL;
253 case ARM::S_TLSDESC:
254 return ELF::R_ARM_TLS_GOTDESC;
255 case ARM::S_TLSLDM:
256 return ELF::R_ARM_TLS_LDM32;
257 case ARM::S_TLSDESCSEQ:
258 return ELF::R_ARM_TLS_DESCSEQ;
259 case ARM::S_FUNCDESC:
260 return CheckFDPIC(ELF::R_ARM_FUNCDESC);
261 case ARM::S_GOTFUNCDESC:
262 return CheckFDPIC(ELF::R_ARM_GOTFUNCDESC);
263 case ARM::S_GOTOFFFUNCDESC:
264 return CheckFDPIC(ELF::R_ARM_GOTOFFFUNCDESC);
265 case ARM::S_TLSGD_FDPIC:
266 return CheckFDPIC(ELF::R_ARM_TLS_GD32_FDPIC);
267 case ARM::S_TLSLDM_FDPIC:
268 return CheckFDPIC(ELF::R_ARM_TLS_LDM32_FDPIC);
269 case ARM::S_GOTTPOFF_FDPIC:
270 return CheckFDPIC(ELF::R_ARM_TLS_IE32_FDPIC);
271 }
272 case ARM::fixup_arm_condbranch:
273 case ARM::fixup_arm_uncondbranch:
274 return ELF::R_ARM_JUMP24;
275 case ARM::fixup_arm_movt_hi16:
276 switch (Specifier) {
277 default:
278 reportError(L: Fixup.getLoc(), Msg: "invalid fixup for ARM MOVT instruction");
279 return ELF::R_ARM_NONE;
280 case ARM::S_None:
281 return ELF::R_ARM_MOVT_ABS;
282 case ARM::S_SBREL:
283 return ELF::R_ARM_MOVT_BREL;
284 }
285 case ARM::fixup_arm_movw_lo16:
286 switch (Specifier) {
287 default:
288 reportError(L: Fixup.getLoc(), Msg: "invalid fixup for ARM MOVW instruction");
289 return ELF::R_ARM_NONE;
290 case ARM::S_None:
291 return ELF::R_ARM_MOVW_ABS_NC;
292 case ARM::S_SBREL:
293 return ELF::R_ARM_MOVW_BREL_NC;
294 }
295 case ARM::fixup_t2_movt_hi16:
296 switch (Specifier) {
297 default:
298 reportError(L: Fixup.getLoc(), Msg: "invalid fixup for Thumb MOVT instruction");
299 return ELF::R_ARM_NONE;
300 case ARM::S_None:
301 return ELF::R_ARM_THM_MOVT_ABS;
302 case ARM::S_SBREL:
303 return ELF::R_ARM_THM_MOVT_BREL;
304 }
305 case ARM::fixup_t2_movw_lo16:
306 switch (Specifier) {
307 default:
308 reportError(L: Fixup.getLoc(), Msg: "invalid fixup for Thumb MOVW instruction");
309 return ELF::R_ARM_NONE;
310 case ARM::S_None:
311 return ELF::R_ARM_THM_MOVW_ABS_NC;
312 case ARM::S_SBREL:
313 return ELF::R_ARM_THM_MOVW_BREL_NC;
314 }
315
316 case ARM::fixup_arm_thumb_upper_8_15:
317 return ELF::R_ARM_THM_ALU_ABS_G3;
318 case ARM::fixup_arm_thumb_upper_0_7:
319 return ELF::R_ARM_THM_ALU_ABS_G2_NC;
320 case ARM::fixup_arm_thumb_lower_8_15:
321 return ELF::R_ARM_THM_ALU_ABS_G1_NC;
322 case ARM::fixup_arm_thumb_lower_0_7:
323 return ELF::R_ARM_THM_ALU_ABS_G0_NC;
324 }
325}
326
327std::unique_ptr<MCObjectTargetWriter>
328llvm::createARMELFObjectWriter(uint8_t OSABI) {
329 return std::make_unique<ARMELFObjectWriter>(args&: OSABI);
330}
331