1//===-- ARMELFObjectWriter.cpp - ARM ELF Writer ---------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/ARMMCTargetDesc.h"
11#include "MCTargetDesc/ARMFixupKinds.h"
12#include "llvm/ADT/Statistic.h"
13#include "llvm/ADT/StringSwitch.h"
14#include "llvm/MC/MCELFObjectWriter.h"
15#include "llvm/MC/MCExpr.h"
16#include "llvm/MC/MCSectionELF.h"
17#include "llvm/MC/MCValue.h"
18#include "llvm/Support/Debug.h"
19#include "llvm/Support/ErrorHandling.h"
20#include "llvm/Support/raw_ostream.h"
21
22using namespace llvm;
23
24namespace {
25  class ARMELFObjectWriter : public MCELFObjectTargetWriter {
26    enum { DefaultEABIVersion = 0x05000000U };
27    unsigned GetRelocTypeInner(const MCValue &Target,
28                               const MCFixup &Fixup,
29                               bool IsPCRel) const;
30
31
32  public:
33    ARMELFObjectWriter(uint8_t OSABI);
34
35    ~ARMELFObjectWriter() override;
36
37    unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
38                          const MCFixup &Fixup, bool IsPCRel) const override;
39
40    bool needsRelocateWithSymbol(const MCSymbol &Sym,
41                                 unsigned Type) const override;
42  };
43}
44
45ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI)
46  : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI,
47                            ELF::EM_ARM,
48                            /*HasRelocationAddend*/ false) {}
49
50ARMELFObjectWriter::~ARMELFObjectWriter() {}
51
52bool ARMELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
53                                                 unsigned Type) const {
54  // FIXME: This is extremely conservative. This really needs to use a
55  // whitelist with a clear explanation for why each realocation needs to
56  // point to the symbol, not to the section.
57  switch (Type) {
58  default:
59    return true;
60
61  case ELF::R_ARM_PREL31:
62  case ELF::R_ARM_ABS32:
63    return false;
64  }
65}
66
67// Need to examine the Fixup when determining whether to
68// emit the relocation as an explicit symbol or as a section relative
69// offset
70unsigned ARMELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
71                                          const MCFixup &Fixup,
72                                          bool IsPCRel) const {
73  return GetRelocTypeInner(Target, Fixup, IsPCRel);
74}
75
76unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
77                                               const MCFixup &Fixup,
78                                               bool IsPCRel) const  {
79  MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
80
81  unsigned Type = 0;
82  if (IsPCRel) {
83    switch ((unsigned)Fixup.getKind()) {
84    default:
85      report_fatal_error("unsupported relocation on symbol");
86      return ELF::R_ARM_NONE;
87    case FK_Data_4:
88      switch (Modifier) {
89      default: llvm_unreachable("Unsupported Modifier");
90      case MCSymbolRefExpr::VK_None:
91        Type = ELF::R_ARM_REL32;
92        break;
93      case MCSymbolRefExpr::VK_TLSGD:
94        llvm_unreachable("unimplemented");
95      case MCSymbolRefExpr::VK_GOTTPOFF:
96        Type = ELF::R_ARM_TLS_IE32;
97        break;
98      case MCSymbolRefExpr::VK_ARM_GOT_PREL:
99        Type = ELF::R_ARM_GOT_PREL;
100        break;
101      case MCSymbolRefExpr::VK_ARM_PREL31:
102        Type = ELF::R_ARM_PREL31;
103        break;
104      }
105      break;
106    case ARM::fixup_arm_blx:
107    case ARM::fixup_arm_uncondbl:
108      switch (Modifier) {
109      case MCSymbolRefExpr::VK_PLT:
110        Type = ELF::R_ARM_CALL;
111        break;
112      case MCSymbolRefExpr::VK_TLSCALL:
113        Type = ELF::R_ARM_TLS_CALL;
114        break;
115      default:
116        Type = ELF::R_ARM_CALL;
117        break;
118      }
119      break;
120    case ARM::fixup_arm_condbl:
121    case ARM::fixup_arm_condbranch:
122    case ARM::fixup_arm_uncondbranch:
123      Type = ELF::R_ARM_JUMP24;
124      break;
125    case ARM::fixup_t2_condbranch:
126      Type = ELF::R_ARM_THM_JUMP19;
127      break;
128    case ARM::fixup_t2_uncondbranch:
129      Type = ELF::R_ARM_THM_JUMP24;
130      break;
131    case ARM::fixup_arm_movt_hi16:
132      Type = ELF::R_ARM_MOVT_PREL;
133      break;
134    case ARM::fixup_arm_movw_lo16:
135      Type = ELF::R_ARM_MOVW_PREL_NC;
136      break;
137    case ARM::fixup_t2_movt_hi16:
138      Type = ELF::R_ARM_THM_MOVT_PREL;
139      break;
140    case ARM::fixup_t2_movw_lo16:
141      Type = ELF::R_ARM_THM_MOVW_PREL_NC;
142      break;
143    case ARM::fixup_arm_thumb_bl:
144    case ARM::fixup_arm_thumb_blx:
145      switch (Modifier) {
146      case MCSymbolRefExpr::VK_TLSCALL:
147        Type = ELF::R_ARM_THM_TLS_CALL;
148        break;
149      default:
150        Type = ELF::R_ARM_THM_CALL;
151        break;
152      }
153      break;
154    }
155  } else {
156    switch ((unsigned)Fixup.getKind()) {
157    default:
158      report_fatal_error("unsupported relocation on symbol");
159      return ELF::R_ARM_NONE;
160    case FK_Data_1:
161      switch (Modifier) {
162      default: llvm_unreachable("unsupported Modifier");
163      case MCSymbolRefExpr::VK_None:
164        Type = ELF::R_ARM_ABS8;
165        break;
166      }
167      break;
168    case FK_Data_2:
169      switch (Modifier) {
170      default: llvm_unreachable("unsupported modifier");
171      case MCSymbolRefExpr::VK_None:
172        Type = ELF::R_ARM_ABS16;
173        break;
174      }
175      break;
176    case FK_Data_4:
177      switch (Modifier) {
178      default: llvm_unreachable("Unsupported Modifier");
179      case MCSymbolRefExpr::VK_ARM_NONE:
180        Type = ELF::R_ARM_NONE;
181        break;
182      case MCSymbolRefExpr::VK_GOT:
183        Type = ELF::R_ARM_GOT_BREL;
184        break;
185      case MCSymbolRefExpr::VK_TLSGD:
186        Type = ELF::R_ARM_TLS_GD32;
187        break;
188      case MCSymbolRefExpr::VK_TPOFF:
189        Type = ELF::R_ARM_TLS_LE32;
190        break;
191      case MCSymbolRefExpr::VK_GOTTPOFF:
192        Type = ELF::R_ARM_TLS_IE32;
193        break;
194      case MCSymbolRefExpr::VK_None:
195        Type = ELF::R_ARM_ABS32;
196        break;
197      case MCSymbolRefExpr::VK_GOTOFF:
198        Type = ELF::R_ARM_GOTOFF32;
199        break;
200      case MCSymbolRefExpr::VK_ARM_GOT_PREL:
201        Type = ELF::R_ARM_GOT_PREL;
202        break;
203      case MCSymbolRefExpr::VK_ARM_TARGET1:
204        Type = ELF::R_ARM_TARGET1;
205        break;
206      case MCSymbolRefExpr::VK_ARM_TARGET2:
207        Type = ELF::R_ARM_TARGET2;
208        break;
209      case MCSymbolRefExpr::VK_ARM_PREL31:
210        Type = ELF::R_ARM_PREL31;
211        break;
212      case MCSymbolRefExpr::VK_ARM_SBREL:
213        Type = ELF::R_ARM_SBREL32;
214        break;
215      case MCSymbolRefExpr::VK_ARM_TLSLDO:
216        Type = ELF::R_ARM_TLS_LDO32;
217        break;
218      case MCSymbolRefExpr::VK_TLSCALL:
219        Type = ELF::R_ARM_TLS_CALL;
220        break;
221      case MCSymbolRefExpr::VK_TLSDESC:
222        Type = ELF::R_ARM_TLS_GOTDESC;
223        break;
224      case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ:
225        Type = ELF::R_ARM_TLS_DESCSEQ;
226        break;
227      }
228      break;
229    case ARM::fixup_arm_ldst_pcrel_12:
230    case ARM::fixup_arm_pcrel_10:
231    case ARM::fixup_arm_adr_pcrel_12:
232    case ARM::fixup_arm_thumb_bl:
233    case ARM::fixup_arm_thumb_cb:
234    case ARM::fixup_arm_thumb_cp:
235    case ARM::fixup_arm_thumb_br:
236      llvm_unreachable("Unimplemented");
237    case ARM::fixup_arm_condbranch:
238    case ARM::fixup_arm_uncondbranch:
239      Type = ELF::R_ARM_JUMP24;
240      break;
241    case ARM::fixup_arm_movt_hi16:
242      Type = ELF::R_ARM_MOVT_ABS;
243      break;
244    case ARM::fixup_arm_movw_lo16:
245      Type = ELF::R_ARM_MOVW_ABS_NC;
246      break;
247    case ARM::fixup_t2_movt_hi16:
248      Type = ELF::R_ARM_THM_MOVT_ABS;
249      break;
250    case ARM::fixup_t2_movw_lo16:
251      Type = ELF::R_ARM_THM_MOVW_ABS_NC;
252      break;
253    }
254  }
255
256  return Type;
257}
258
259MCObjectWriter *llvm::createARMELFObjectWriter(raw_pwrite_stream &OS,
260                                               uint8_t OSABI,
261                                               bool IsLittleEndian) {
262  MCELFObjectTargetWriter *MOTW = new ARMELFObjectWriter(OSABI);
263  return createELFObjectWriter(MOTW, OS, IsLittleEndian);
264}
265