xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
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 
24 using namespace llvm;
25 
26 namespace {
27 
28 class ARMELFObjectWriter : public MCELFObjectTargetWriter {
29   enum { DefaultEABIVersion = 0x05000000U };
30 
31 public:
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 
45 ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI)
46   : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI,
47                             ELF::EM_ARM,
48                             /*HasRelocationAddend*/ false) {}
49 
50 bool 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(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
75 unsigned ARMELFObjectWriter::getRelocType(const MCFixup &Fixup,
76                                           const MCValue &Target,
77                                           bool IsPCRel) const {
78   auto Kind = Fixup.getKind();
79   uint8_t Specifier = Target.getSpecifier();
80   auto CheckFDPIC = [&](uint32_t Type) {
81     if (getOSABI() != ELF::ELFOSABI_ARM_FDPIC)
82       reportError(Fixup.getLoc(),
83                   "relocation " +
84                       object::getELFRelocationTypeName(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>(SA)->setType(ELF::STT_TLS);
102     break;
103   default:
104     break;
105   }
106 
107   if (IsPCRel) {
108     switch (Fixup.getKind()) {
109     default:
110       reportError(Fixup.getLoc(), "unsupported relocation type");
111       return ELF::R_ARM_NONE;
112     case FK_Data_4:
113       switch (Specifier) {
114       default:
115         reportError(Fixup.getLoc(),
116                     "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(Fixup.getLoc(), "unsupported relocation type");
203     return ELF::R_ARM_NONE;
204   case FK_Data_1:
205     switch (Specifier) {
206     default:
207       reportError(Fixup.getLoc(), "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(Fixup.getLoc(), "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(Fixup.getLoc(), "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(Fixup.getLoc(), "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(Fixup.getLoc(), "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(Fixup.getLoc(), "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(Fixup.getLoc(), "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 
327 std::unique_ptr<MCObjectTargetWriter>
328 llvm::createARMELFObjectWriter(uint8_t OSABI) {
329   return std::make_unique<ARMELFObjectWriter>(OSABI);
330 }
331