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