1263320Sdim//===-- ARMELFObjectWriter.cpp - ARM ELF Writer ---------------------------===//
2263320Sdim//
3263320Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4263320Sdim// See https://llvm.org/LICENSE.txt for license information.
5263320Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6263320Sdim//
7263320Sdim//===----------------------------------------------------------------------===//
8263320Sdim
9263320Sdim#include "MCTargetDesc/ARMFixupKinds.h"
10263320Sdim#include "MCTargetDesc/ARMMCTargetDesc.h"
11263320Sdim#include "llvm/BinaryFormat/ELF.h"
12263320Sdim#include "llvm/MC/MCContext.h"
13263320Sdim#include "llvm/MC/MCELFObjectWriter.h"
14263320Sdim#include "llvm/MC/MCExpr.h"
15263320Sdim#include "llvm/MC/MCFixup.h"
16263320Sdim#include "llvm/MC/MCObjectFileInfo.h"
17263320Sdim#include "llvm/MC/MCObjectWriter.h"
18263320Sdim#include "llvm/MC/MCValue.h"
19263320Sdim#include "llvm/Support/ErrorHandling.h"
20263320Sdim#include "llvm/Support/raw_ostream.h"
21263320Sdim#include <cstdint>
22263320Sdim
23263320Sdimusing namespace llvm;
24263320Sdim
25263320Sdimnamespace {
26263320Sdim
27263320Sdim  class ARMELFObjectWriter : public MCELFObjectTargetWriter {
28263320Sdim    enum { DefaultEABIVersion = 0x05000000U };
29263320Sdim
30263320Sdim    unsigned GetRelocTypeInner(const MCValue &Target, const MCFixup &Fixup,
31263320Sdim                               bool IsPCRel, MCContext &Ctx) const;
32263320Sdim
33263320Sdim  public:
34263320Sdim    ARMELFObjectWriter(uint8_t OSABI);
35263320Sdim
36263320Sdim    ~ARMELFObjectWriter() override = default;
37263320Sdim
38263320Sdim    unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
39263320Sdim                          const MCFixup &Fixup, bool IsPCRel) const override;
40263320Sdim
41263320Sdim    bool needsRelocateWithSymbol(const MCValue &Val, const MCSymbol &Sym,
42263320Sdim                                 unsigned Type) const override;
43263320Sdim
44263320Sdim    void addTargetSectionFlags(MCContext &Ctx, MCSectionELF &Sec) override;
45263320Sdim  };
46263320Sdim
47263320Sdim} // end anonymous namespace
48263320Sdim
49263320SdimARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI)
50  : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI,
51                            ELF::EM_ARM,
52                            /*HasRelocationAddend*/ false) {}
53
54bool 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
73unsigned ARMELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
74                                          const MCFixup &Fixup,
75                                          bool IsPCRel) const {
76  return GetRelocTypeInner(Target, Fixup, IsPCRel, Ctx);
77}
78
79unsigned 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
301void 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
319std::unique_ptr<MCObjectTargetWriter>
320llvm::createARMELFObjectWriter(uint8_t OSABI) {
321  return std::make_unique<ARMELFObjectWriter>(OSABI);
322}
323