LLVM  4.0.0
AArch64ELFObjectWriter.cpp
Go to the documentation of this file.
1 //===-- AArch64ELFObjectWriter.cpp - AArch64 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 // This file handles ELF-specific object emission, converting LLVM's internal
11 // fixups into the appropriate relocations.
12 //
13 //===----------------------------------------------------------------------===//
14 
18 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCFixup.h"
21 #include "llvm/MC/MCValue.h"
22 #include "llvm/Support/ELF.h"
24 #include <cassert>
25 #include <cstdint>
26 
27 using namespace llvm;
28 
29 namespace {
30 
31 class AArch64ELFObjectWriter : public MCELFObjectTargetWriter {
32 public:
33  AArch64ELFObjectWriter(uint8_t OSABI, bool IsLittleEndian, bool IsILP32);
34 
35  ~AArch64ELFObjectWriter() override = default;
36 
37 protected:
38  unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
39  const MCFixup &Fixup, bool IsPCRel) const override;
40  bool IsILP32;
41 };
42 
43 } // end anonymous namespace
44 
45 AArch64ELFObjectWriter::AArch64ELFObjectWriter(uint8_t OSABI,
46  bool IsLittleEndian,
47  bool IsILP32)
48  : MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_AARCH64,
49  /*HasRelocationAddend*/ true),
50  IsILP32(IsILP32) {}
51 
52 #define R_CLS(rtype) \
53  IsILP32 ? ELF::R_AARCH64_P32_##rtype : ELF::R_AARCH64_##rtype
54 #define BAD_ILP32_MOV(lp64rtype) "ILP32 absolute MOV relocation not "\
55  "supported (LP64 eqv: " #lp64rtype ")"
56 
57 // assumes IsILP32 is true
58 static bool isNonILP32reloc(const MCFixup &Fixup,
60  MCContext &Ctx) {
61  if ((unsigned)Fixup.getKind() != AArch64::fixup_aarch64_movw)
62  return false;
63  switch(RefKind) {
65  Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G3));
66  return true;
68  Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G2));
69  return true;
71  Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_SABS_G2));
72  return ELF::R_AARCH64_NONE;
74  Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G2_NC));
75  return ELF::R_AARCH64_NONE;
77  Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_SABS_G1));
78  return ELF::R_AARCH64_NONE;
80  Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G1_NC));
81  return ELF::R_AARCH64_NONE;
83  Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLD_MOVW_DTPREL_G2));
84  return ELF::R_AARCH64_NONE;
86  Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLD_MOVW_DTPREL_G1_NC));
87  return ELF::R_AARCH64_NONE;
89  Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLE_MOVW_TPREL_G2));
90  return ELF::R_AARCH64_NONE;
92  Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLE_MOVW_TPREL_G1_NC));
93  return ELF::R_AARCH64_NONE;
95  Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSIE_MOVW_GOTTPREL_G1));
96  return ELF::R_AARCH64_NONE;
98  Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSIE_MOVW_GOTTPREL_G0_NC));
99  return ELF::R_AARCH64_NONE;
100  default: return false;
101  }
102  return false;
103 }
104 
106  const MCValue &Target,
107  const MCFixup &Fixup,
108  bool IsPCRel) const {
110  static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
112  bool IsNC = AArch64MCExpr::isNotChecked(RefKind);
113 
114  assert((!Target.getSymA() ||
115  Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None) &&
116  "Should only be expression-level modifiers here");
117 
118  assert((!Target.getSymB() ||
119  Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None) &&
120  "Should only be expression-level modifiers here");
121 
122  if (IsPCRel) {
123  switch ((unsigned)Fixup.getKind()) {
124  case FK_Data_1:
125  Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
126  return ELF::R_AARCH64_NONE;
127  case FK_Data_2:
128  return R_CLS(PREL16);
129  case FK_Data_4:
130  return R_CLS(PREL32);
131  case FK_Data_8:
132  if (IsILP32) {
133  Ctx.reportError(Fixup.getLoc(), "ILP32 8 byte PC relative data "
134  "relocation not supported (LP64 eqv: PREL64)");
135  return ELF::R_AARCH64_NONE;
136  } else
137  return ELF::R_AARCH64_PREL64;
139  assert(SymLoc == AArch64MCExpr::VK_NONE && "unexpected ADR relocation");
140  return R_CLS(ADR_PREL_LO21);
142  if (SymLoc == AArch64MCExpr::VK_ABS && !IsNC)
143  return R_CLS(ADR_PREL_PG_HI21);
144  if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC)
145  return R_CLS(ADR_GOT_PAGE);
146  if (SymLoc == AArch64MCExpr::VK_GOTTPREL && !IsNC)
147  return R_CLS(TLSIE_ADR_GOTTPREL_PAGE21);
148  if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC)
149  return R_CLS(TLSDESC_ADR_PAGE21);
150  Ctx.reportError(Fixup.getLoc(),
151  "invalid symbol kind for ADRP relocation");
152  return ELF::R_AARCH64_NONE;
154  return R_CLS(JUMP26);
156  return R_CLS(CALL26);
158  if (SymLoc == AArch64MCExpr::VK_GOTTPREL)
159  return R_CLS(TLSIE_LD_GOTTPREL_PREL19);
160  return R_CLS(LD_PREL_LO19);
162  return R_CLS(TSTBR14);
164  return R_CLS(CONDBR19);
165  default:
166  Ctx.reportError(Fixup.getLoc(), "Unsupported pc-relative fixup kind");
167  return ELF::R_AARCH64_NONE;
168  }
169  } else {
170  if (IsILP32 && isNonILP32reloc(Fixup, RefKind, Ctx))
171  return ELF::R_AARCH64_NONE;
172  switch ((unsigned)Fixup.getKind()) {
173  case FK_Data_1:
174  Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
175  return ELF::R_AARCH64_NONE;
176  case FK_Data_2:
177  return R_CLS(ABS16);
178  case FK_Data_4:
179  return R_CLS(ABS32);
180  case FK_Data_8:
181  if (IsILP32) {
182  Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(ABS64));
183  return ELF::R_AARCH64_NONE;
184  } else
185  return ELF::R_AARCH64_ABS64;
187  if (RefKind == AArch64MCExpr::VK_DTPREL_HI12)
188  return R_CLS(TLSLD_ADD_DTPREL_HI12);
189  if (RefKind == AArch64MCExpr::VK_TPREL_HI12)
190  return R_CLS(TLSLE_ADD_TPREL_HI12);
191  if (RefKind == AArch64MCExpr::VK_DTPREL_LO12_NC)
192  return R_CLS(TLSLD_ADD_DTPREL_LO12_NC);
193  if (RefKind == AArch64MCExpr::VK_DTPREL_LO12)
194  return R_CLS(TLSLD_ADD_DTPREL_LO12);
195  if (RefKind == AArch64MCExpr::VK_TPREL_LO12_NC)
196  return R_CLS(TLSLE_ADD_TPREL_LO12_NC);
197  if (RefKind == AArch64MCExpr::VK_TPREL_LO12)
198  return R_CLS(TLSLE_ADD_TPREL_LO12);
199  if (RefKind == AArch64MCExpr::VK_TLSDESC_LO12)
200  return R_CLS(TLSDESC_ADD_LO12_NC);
201  if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
202  return R_CLS(ADD_ABS_LO12_NC);
203 
204  Ctx.reportError(Fixup.getLoc(),
205  "invalid fixup for add (uimm12) instruction");
206  return ELF::R_AARCH64_NONE;
208  if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
209  return R_CLS(LDST8_ABS_LO12_NC);
210  if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
211  return R_CLS(TLSLD_LDST8_DTPREL_LO12);
212  if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
213  return R_CLS(TLSLD_LDST8_DTPREL_LO12_NC);
214  if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
215  return R_CLS(TLSLE_LDST8_TPREL_LO12);
216  if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
217  return R_CLS(TLSLE_LDST8_TPREL_LO12_NC);
218 
219  Ctx.reportError(Fixup.getLoc(),
220  "invalid fixup for 8-bit load/store instruction");
221  return ELF::R_AARCH64_NONE;
223  if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
224  return R_CLS(LDST16_ABS_LO12_NC);
225  if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
226  return R_CLS(TLSLD_LDST16_DTPREL_LO12);
227  if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
228  return R_CLS(TLSLD_LDST16_DTPREL_LO12_NC);
229  if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
230  return R_CLS(TLSLE_LDST16_TPREL_LO12);
231  if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
232  return R_CLS(TLSLE_LDST16_TPREL_LO12_NC);
233 
234  Ctx.reportError(Fixup.getLoc(),
235  "invalid fixup for 16-bit load/store instruction");
236  return ELF::R_AARCH64_NONE;
238  if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
239  return R_CLS(LDST32_ABS_LO12_NC);
240  if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
241  return R_CLS(TLSLD_LDST32_DTPREL_LO12);
242  if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
243  return R_CLS(TLSLD_LDST32_DTPREL_LO12_NC);
244  if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
245  return R_CLS(TLSLE_LDST32_TPREL_LO12);
246  if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
247  return R_CLS(TLSLE_LDST32_TPREL_LO12_NC);
248 
249  Ctx.reportError(Fixup.getLoc(),
250  "invalid fixup for 32-bit load/store instruction");
251  return ELF::R_AARCH64_NONE;
253  if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
254  return R_CLS(LDST64_ABS_LO12_NC);
255  if (SymLoc == AArch64MCExpr::VK_GOT && IsNC)
256  return R_CLS(LD64_GOT_LO12_NC);
257  if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
258  return R_CLS(TLSLD_LDST64_DTPREL_LO12);
259  if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
260  return R_CLS(TLSLD_LDST64_DTPREL_LO12_NC);
261  if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
262  return R_CLS(TLSLE_LDST64_TPREL_LO12);
263  if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
264  return R_CLS(TLSLE_LDST64_TPREL_LO12_NC);
265  if (SymLoc == AArch64MCExpr::VK_GOTTPREL && IsNC)
266  return IsILP32 ? ELF::R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC
267  : ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
268  if (SymLoc == AArch64MCExpr::VK_TLSDESC && IsNC)
269  return IsILP32 ? ELF::R_AARCH64_P32_TLSDESC_LD32_LO12_NC
270  : ELF::R_AARCH64_TLSDESC_LD64_LO12_NC;
271 
272  Ctx.reportError(Fixup.getLoc(),
273  "invalid fixup for 64-bit load/store instruction");
274  return ELF::R_AARCH64_NONE;
276  if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
277  return R_CLS(LDST128_ABS_LO12_NC);
278 
279  Ctx.reportError(Fixup.getLoc(),
280  "invalid fixup for 128-bit load/store instruction");
281  return ELF::R_AARCH64_NONE;
282  // ILP32 case not reached here, tested with isNonILP32reloc
284  if (RefKind == AArch64MCExpr::VK_ABS_G3)
285  return ELF::R_AARCH64_MOVW_UABS_G3;
286  if (RefKind == AArch64MCExpr::VK_ABS_G2)
287  return ELF::R_AARCH64_MOVW_UABS_G2;
288  if (RefKind == AArch64MCExpr::VK_ABS_G2_S)
289  return ELF::R_AARCH64_MOVW_SABS_G2;
290  if (RefKind == AArch64MCExpr::VK_ABS_G2_NC)
291  return ELF::R_AARCH64_MOVW_UABS_G2_NC;
292  if (RefKind == AArch64MCExpr::VK_ABS_G1)
293  return R_CLS(MOVW_UABS_G1);
294  if (RefKind == AArch64MCExpr::VK_ABS_G1_S)
295  return ELF::R_AARCH64_MOVW_SABS_G1;
296  if (RefKind == AArch64MCExpr::VK_ABS_G1_NC)
297  return ELF::R_AARCH64_MOVW_UABS_G1_NC;
298  if (RefKind == AArch64MCExpr::VK_ABS_G0)
299  return R_CLS(MOVW_UABS_G0);
300  if (RefKind == AArch64MCExpr::VK_ABS_G0_S)
301  return R_CLS(MOVW_SABS_G0);
302  if (RefKind == AArch64MCExpr::VK_ABS_G0_NC)
303  return R_CLS(MOVW_UABS_G0_NC);
304  if (RefKind == AArch64MCExpr::VK_DTPREL_G2)
305  return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G2;
306  if (RefKind == AArch64MCExpr::VK_DTPREL_G1)
307  return R_CLS(TLSLD_MOVW_DTPREL_G1);
308  if (RefKind == AArch64MCExpr::VK_DTPREL_G1_NC)
309  return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC;
310  if (RefKind == AArch64MCExpr::VK_DTPREL_G0)
311  return R_CLS(TLSLD_MOVW_DTPREL_G0);
312  if (RefKind == AArch64MCExpr::VK_DTPREL_G0_NC)
313  return R_CLS(TLSLD_MOVW_DTPREL_G0_NC);
314  if (RefKind == AArch64MCExpr::VK_TPREL_G2)
315  return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G2;
316  if (RefKind == AArch64MCExpr::VK_TPREL_G1)
317  return R_CLS(TLSLE_MOVW_TPREL_G1);
318  if (RefKind == AArch64MCExpr::VK_TPREL_G1_NC)
319  return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC;
320  if (RefKind == AArch64MCExpr::VK_TPREL_G0)
321  return R_CLS(TLSLE_MOVW_TPREL_G0);
322  if (RefKind == AArch64MCExpr::VK_TPREL_G0_NC)
323  return R_CLS(TLSLE_MOVW_TPREL_G0_NC);
324  if (RefKind == AArch64MCExpr::VK_GOTTPREL_G1)
325  return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G1;
326  if (RefKind == AArch64MCExpr::VK_GOTTPREL_G0_NC)
327  return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC;
328  Ctx.reportError(Fixup.getLoc(),
329  "invalid fixup for movz/movk instruction");
330  return ELF::R_AARCH64_NONE;
332  return R_CLS(TLSDESC_CALL);
333  default:
334  Ctx.reportError(Fixup.getLoc(), "Unknown ELF relocation type");
335  return ELF::R_AARCH64_NONE;
336  }
337  }
338 
339  llvm_unreachable("Unimplemented fixup -> relocation");
340 }
341 
343  uint8_t OSABI,
344  bool IsLittleEndian,
345  bool IsILP32) {
347  new AArch64ELFObjectWriter(OSABI, IsLittleEndian, IsILP32);
348  return createELFObjectWriter(MOTW, OS, IsLittleEndian);
349 }
SMLoc getLoc() const
Definition: MCFixup.h:112
This represents an "assembler immediate".
Definition: MCValue.h:40
#define BAD_ILP32_MOV(lp64rtype)
#define R_CLS(rtype)
Defines the object file and target independent interfaces used by the assembler backend to write nati...
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:66
static unsigned getRelocType(const MCValue &Target, const MCFixupKind FixupKind, const bool IsPCRel)
Translates generic PPC fixup kind to Mach-O/PPC relocation type enum.
A four-byte fixup.
Definition: MCFixup.h:26
Context object for machine code objects.
Definition: MCContext.h:51
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:510
static bool isNonILP32reloc(const MCFixup &Fixup, AArch64MCExpr::VariantKind RefKind, MCContext &Ctx)
MCFixupKind getKind() const
Definition: MCFixup.h:93
const MCSymbolRefExpr * getSymB() const
Definition: MCValue.h:48
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
A one-byte fixup.
Definition: MCFixup.h:24
MCObjectWriter * createAArch64ELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI, bool IsLittleEndian, bool IsILP32)
const MCSymbolRefExpr * getSymA() const
Definition: MCValue.h:47
uint32_t getRefKind() const
Definition: MCValue.h:49
Target - Wrapper for Target specific information.
MCObjectWriter * createELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_pwrite_stream &OS, bool IsLittleEndian)
Construct a new ELF writer instance.
Basic Alias true
static bool isNotChecked(VariantKind Kind)
A eight-byte fixup.
Definition: MCFixup.h:27
An abstract base class for streams implementations that also support a pwrite operation.
Definition: raw_ostream.h:333
static VariantKind getSymbolLoc(VariantKind Kind)
VariantKind getKind() const
Definition: MCExpr.h:313
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A two-byte fixup.
Definition: MCFixup.h:25