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/ARMMCTargetDesc.h"
11 #include "llvm/BinaryFormat/ELF.h"
12 #include "llvm/MC/MCContext.h"
13 #include "llvm/MC/MCELFObjectWriter.h"
14 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCFixup.h"
16 #include "llvm/MC/MCObjectFileInfo.h"
17 #include "llvm/MC/MCObjectWriter.h"
18 #include "llvm/MC/MCValue.h"
19 #include "llvm/Support/ErrorHandling.h"
20 #include "llvm/Support/raw_ostream.h"
21 #include <cstdint>
22
23 using namespace llvm;
24
25 namespace {
26
27 class ARMELFObjectWriter : public MCELFObjectTargetWriter {
28 enum { DefaultEABIVersion = 0x05000000U };
29
30 unsigned GetRelocTypeInner(const MCValue &Target, const MCFixup &Fixup,
31 bool IsPCRel, MCContext &Ctx) const;
32
33 public:
34 ARMELFObjectWriter(uint8_t OSABI);
35
36 ~ARMELFObjectWriter() override = default;
37
38 unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
39 const MCFixup &Fixup, bool IsPCRel) const override;
40
41 bool needsRelocateWithSymbol(const MCValue &Val, const MCSymbol &Sym,
42 unsigned Type) const override;
43
44 void addTargetSectionFlags(MCContext &Ctx, MCSectionELF &Sec) override;
45 };
46
47 } // end anonymous namespace
48
ARMELFObjectWriter(uint8_t OSABI)49 ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI)
50 : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI,
51 ELF::EM_ARM,
52 /*HasRelocationAddend*/ false) {}
53
needsRelocateWithSymbol(const MCValue &,const MCSymbol &,unsigned Type) const54 bool ARMELFObjectWriter::needsRelocateWithSymbol(const MCValue &,
55 const MCSymbol &,
56 unsigned Type) const {
57 // FIXME: This is extremely conservative. This really needs to use an
58 // explicit list with a clear explanation for why each realocation needs to
59 // point to the symbol, not to the section.
60 switch (Type) {
61 default:
62 return true;
63
64 case ELF::R_ARM_PREL31:
65 case ELF::R_ARM_ABS32:
66 return false;
67 }
68 }
69
70 // Need to examine the Fixup when determining whether to
71 // emit the relocation as an explicit symbol or as a section relative
72 // offset
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const73 unsigned ARMELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
74 const MCFixup &Fixup,
75 bool IsPCRel) const {
76 return GetRelocTypeInner(Target, Fixup, IsPCRel, Ctx);
77 }
78
GetRelocTypeInner(const MCValue & Target,const MCFixup & Fixup,bool IsPCRel,MCContext & Ctx) const79 unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
80 const MCFixup &Fixup,
81 bool IsPCRel,
82 MCContext &Ctx) const {
83 unsigned Kind = Fixup.getTargetKind();
84 if (Kind >= FirstLiteralRelocationKind)
85 return Kind - FirstLiteralRelocationKind;
86 MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
87
88 if (IsPCRel) {
89 switch (Fixup.getTargetKind()) {
90 default:
91 Ctx.reportError(Fixup.getLoc(), "unsupported relocation type");
92 return ELF::R_ARM_NONE;
93 case FK_Data_4:
94 switch (Modifier) {
95 default:
96 Ctx.reportError(Fixup.getLoc(),
97 "invalid fixup for 4-byte pc-relative data relocation");
98 return ELF::R_ARM_NONE;
99 case MCSymbolRefExpr::VK_None: {
100 if (const MCSymbolRefExpr *SymRef = Target.getSymA()) {
101 // For GNU AS compatibility expressions such as
102 // _GLOBAL_OFFSET_TABLE_ - label emit a R_ARM_BASE_PREL relocation.
103 if (SymRef->getSymbol().getName() == "_GLOBAL_OFFSET_TABLE_")
104 return ELF::R_ARM_BASE_PREL;
105 }
106 return ELF::R_ARM_REL32;
107 }
108 case MCSymbolRefExpr::VK_GOTTPOFF:
109 return ELF::R_ARM_TLS_IE32;
110 case MCSymbolRefExpr::VK_ARM_GOT_PREL:
111 return ELF::R_ARM_GOT_PREL;
112 case MCSymbolRefExpr::VK_ARM_PREL31:
113 return ELF::R_ARM_PREL31;
114 }
115 case ARM::fixup_arm_blx:
116 case ARM::fixup_arm_uncondbl:
117 switch (Modifier) {
118 case MCSymbolRefExpr::VK_PLT:
119 return ELF::R_ARM_CALL;
120 case MCSymbolRefExpr::VK_TLSCALL:
121 return ELF::R_ARM_TLS_CALL;
122 default:
123 return ELF::R_ARM_CALL;
124 }
125 case ARM::fixup_arm_condbl:
126 case ARM::fixup_arm_condbranch:
127 case ARM::fixup_arm_uncondbranch:
128 return ELF::R_ARM_JUMP24;
129 case ARM::fixup_t2_condbranch:
130 return ELF::R_ARM_THM_JUMP19;
131 case ARM::fixup_t2_uncondbranch:
132 return ELF::R_ARM_THM_JUMP24;
133 case ARM::fixup_arm_movt_hi16:
134 return ELF::R_ARM_MOVT_PREL;
135 case ARM::fixup_arm_movw_lo16:
136 return ELF::R_ARM_MOVW_PREL_NC;
137 case ARM::fixup_t2_movt_hi16:
138 return ELF::R_ARM_THM_MOVT_PREL;
139 case ARM::fixup_t2_movw_lo16:
140 return ELF::R_ARM_THM_MOVW_PREL_NC;
141 case ARM::fixup_arm_thumb_upper_8_15:
142 return ELF::R_ARM_THM_ALU_ABS_G3;
143 case ARM::fixup_arm_thumb_upper_0_7:
144 return ELF::R_ARM_THM_ALU_ABS_G2_NC;
145 case ARM::fixup_arm_thumb_lower_8_15:
146 return ELF::R_ARM_THM_ALU_ABS_G1_NC;
147 case ARM::fixup_arm_thumb_lower_0_7:
148 return ELF::R_ARM_THM_ALU_ABS_G0_NC;
149 case ARM::fixup_arm_thumb_br:
150 return ELF::R_ARM_THM_JUMP11;
151 case ARM::fixup_arm_thumb_bcc:
152 return ELF::R_ARM_THM_JUMP8;
153 case ARM::fixup_arm_thumb_bl:
154 case ARM::fixup_arm_thumb_blx:
155 switch (Modifier) {
156 case MCSymbolRefExpr::VK_TLSCALL:
157 return ELF::R_ARM_THM_TLS_CALL;
158 default:
159 return ELF::R_ARM_THM_CALL;
160 }
161 case ARM::fixup_arm_ldst_pcrel_12:
162 return ELF::R_ARM_LDR_PC_G0;
163 case ARM::fixup_arm_pcrel_10_unscaled:
164 return ELF::R_ARM_LDRS_PC_G0;
165 case ARM::fixup_t2_ldst_pcrel_12:
166 return ELF::R_ARM_THM_PC12;
167 case ARM::fixup_arm_adr_pcrel_12:
168 return ELF::R_ARM_ALU_PC_G0;
169 case ARM::fixup_thumb_adr_pcrel_10:
170 return ELF::R_ARM_THM_PC8;
171 case ARM::fixup_t2_adr_pcrel_12:
172 return ELF::R_ARM_THM_ALU_PREL_11_0;
173 case ARM::fixup_bf_target:
174 return ELF::R_ARM_THM_BF16;
175 case ARM::fixup_bfc_target:
176 return ELF::R_ARM_THM_BF12;
177 case ARM::fixup_bfl_target:
178 return ELF::R_ARM_THM_BF18;
179 }
180 }
181 switch (Kind) {
182 default:
183 Ctx.reportError(Fixup.getLoc(), "unsupported relocation type");
184 return ELF::R_ARM_NONE;
185 case FK_Data_1:
186 switch (Modifier) {
187 default:
188 Ctx.reportError(Fixup.getLoc(),
189 "invalid fixup for 1-byte data relocation");
190 return ELF::R_ARM_NONE;
191 case MCSymbolRefExpr::VK_None:
192 return ELF::R_ARM_ABS8;
193 }
194 case FK_Data_2:
195 switch (Modifier) {
196 default:
197 Ctx.reportError(Fixup.getLoc(),
198 "invalid fixup for 2-byte data relocation");
199 return ELF::R_ARM_NONE;
200 case MCSymbolRefExpr::VK_None:
201 return ELF::R_ARM_ABS16;
202 }
203 case FK_Data_4:
204 switch (Modifier) {
205 default:
206 Ctx.reportError(Fixup.getLoc(),
207 "invalid fixup for 4-byte data relocation");
208 return ELF::R_ARM_NONE;
209 case MCSymbolRefExpr::VK_ARM_NONE:
210 return ELF::R_ARM_NONE;
211 case MCSymbolRefExpr::VK_GOT:
212 return ELF::R_ARM_GOT_BREL;
213 case MCSymbolRefExpr::VK_TLSGD:
214 return ELF::R_ARM_TLS_GD32;
215 case MCSymbolRefExpr::VK_TPOFF:
216 return ELF::R_ARM_TLS_LE32;
217 case MCSymbolRefExpr::VK_GOTTPOFF:
218 return ELF::R_ARM_TLS_IE32;
219 case MCSymbolRefExpr::VK_None:
220 return ELF::R_ARM_ABS32;
221 case MCSymbolRefExpr::VK_GOTOFF:
222 return ELF::R_ARM_GOTOFF32;
223 case MCSymbolRefExpr::VK_ARM_GOT_PREL:
224 return ELF::R_ARM_GOT_PREL;
225 case MCSymbolRefExpr::VK_ARM_TARGET1:
226 return ELF::R_ARM_TARGET1;
227 case MCSymbolRefExpr::VK_ARM_TARGET2:
228 return ELF::R_ARM_TARGET2;
229 case MCSymbolRefExpr::VK_ARM_PREL31:
230 return ELF::R_ARM_PREL31;
231 case MCSymbolRefExpr::VK_ARM_SBREL:
232 return ELF::R_ARM_SBREL32;
233 case MCSymbolRefExpr::VK_ARM_TLSLDO:
234 return ELF::R_ARM_TLS_LDO32;
235 case MCSymbolRefExpr::VK_TLSCALL:
236 return ELF::R_ARM_TLS_CALL;
237 case MCSymbolRefExpr::VK_TLSDESC:
238 return ELF::R_ARM_TLS_GOTDESC;
239 case MCSymbolRefExpr::VK_TLSLDM:
240 return ELF::R_ARM_TLS_LDM32;
241 case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ:
242 return ELF::R_ARM_TLS_DESCSEQ;
243 }
244 case ARM::fixup_arm_condbranch:
245 case ARM::fixup_arm_uncondbranch:
246 return ELF::R_ARM_JUMP24;
247 case ARM::fixup_arm_movt_hi16:
248 switch (Modifier) {
249 default:
250 Ctx.reportError(Fixup.getLoc(), "invalid fixup for ARM MOVT instruction");
251 return ELF::R_ARM_NONE;
252 case MCSymbolRefExpr::VK_None:
253 return ELF::R_ARM_MOVT_ABS;
254 case MCSymbolRefExpr::VK_ARM_SBREL:
255 return ELF::R_ARM_MOVT_BREL;
256 }
257 case ARM::fixup_arm_movw_lo16:
258 switch (Modifier) {
259 default:
260 Ctx.reportError(Fixup.getLoc(), "invalid fixup for ARM MOVW instruction");
261 return ELF::R_ARM_NONE;
262 case MCSymbolRefExpr::VK_None:
263 return ELF::R_ARM_MOVW_ABS_NC;
264 case MCSymbolRefExpr::VK_ARM_SBREL:
265 return ELF::R_ARM_MOVW_BREL_NC;
266 }
267 case ARM::fixup_t2_movt_hi16:
268 switch (Modifier) {
269 default:
270 Ctx.reportError(Fixup.getLoc(),
271 "invalid fixup for Thumb MOVT instruction");
272 return ELF::R_ARM_NONE;
273 case MCSymbolRefExpr::VK_None:
274 return ELF::R_ARM_THM_MOVT_ABS;
275 case MCSymbolRefExpr::VK_ARM_SBREL:
276 return ELF::R_ARM_THM_MOVT_BREL;
277 }
278 case ARM::fixup_t2_movw_lo16:
279 switch (Modifier) {
280 default:
281 Ctx.reportError(Fixup.getLoc(),
282 "invalid fixup for Thumb MOVW instruction");
283 return ELF::R_ARM_NONE;
284 case MCSymbolRefExpr::VK_None:
285 return ELF::R_ARM_THM_MOVW_ABS_NC;
286 case MCSymbolRefExpr::VK_ARM_SBREL:
287 return ELF::R_ARM_THM_MOVW_BREL_NC;
288 }
289
290 case ARM::fixup_arm_thumb_upper_8_15:
291 return ELF::R_ARM_THM_ALU_ABS_G3;
292 case ARM::fixup_arm_thumb_upper_0_7:
293 return ELF::R_ARM_THM_ALU_ABS_G2_NC;
294 case ARM::fixup_arm_thumb_lower_8_15:
295 return ELF::R_ARM_THM_ALU_ABS_G1_NC;
296 case ARM::fixup_arm_thumb_lower_0_7:
297 return ELF::R_ARM_THM_ALU_ABS_G0_NC;
298 }
299 }
300
addTargetSectionFlags(MCContext & Ctx,MCSectionELF & Sec)301 void ARMELFObjectWriter::addTargetSectionFlags(MCContext &Ctx,
302 MCSectionELF &Sec) {
303 // The mix of execute-only and non-execute-only at link time is
304 // non-execute-only. To avoid the empty implicitly created .text
305 // section from making the whole .text section non-execute-only, we
306 // mark it execute-only if it is empty and there is at least one
307 // execute-only section in the object.
308 MCSectionELF *TextSection =
309 static_cast<MCSectionELF *>(Ctx.getObjectFileInfo()->getTextSection());
310 if (Sec.getKind().isExecuteOnly() && !TextSection->hasInstructions()) {
311 for (auto &F : TextSection->getFragmentList())
312 if (auto *DF = dyn_cast<MCDataFragment>(&F))
313 if (!DF->getContents().empty())
314 return;
315 TextSection->setFlags(TextSection->getFlags() | ELF::SHF_ARM_PURECODE);
316 }
317 }
318
319 std::unique_ptr<MCObjectTargetWriter>
createARMELFObjectWriter(uint8_t OSABI)320 llvm::createARMELFObjectWriter(uint8_t OSABI) {
321 return std::make_unique<ARMELFObjectWriter>(OSABI);
322 }
323