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