xref: /llvm-project/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp (revision dcb312bdb9616c19f1e58afc9d06b49f81f648e8)
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/BinaryFormat/ELF.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCELFObjectWriter.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCFixup.h"
17 #include "llvm/MC/MCValue.h"
18 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include <cstdint>
21 
22 using namespace llvm;
23 
24 namespace {
25 
26   class ARMELFObjectWriter : public MCELFObjectTargetWriter {
27     enum { DefaultEABIVersion = 0x05000000U };
28 
29     unsigned GetRelocTypeInner(const MCValue &Target, const MCFixup &Fixup,
30                                bool IsPCRel, MCContext &Ctx) 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, Ctx);
73 }
74 
75 unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
76                                                const MCFixup &Fixup,
77                                                bool IsPCRel,
78                                                MCContext &Ctx) const {
79   MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
80 
81   if (IsPCRel) {
82     switch ((unsigned)Fixup.getKind()) {
83     default:
84       Ctx.reportFatalError(Fixup.getLoc(), "unsupported relocation on symbol");
85       return ELF::R_ARM_NONE;
86     case FK_Data_4:
87       switch (Modifier) {
88       default:
89         llvm_unreachable("Unsupported Modifier");
90       case MCSymbolRefExpr::VK_None:
91         return ELF::R_ARM_REL32;
92       case MCSymbolRefExpr::VK_GOTTPOFF:
93         return ELF::R_ARM_TLS_IE32;
94       case MCSymbolRefExpr::VK_ARM_GOT_PREL:
95         return ELF::R_ARM_GOT_PREL;
96       case MCSymbolRefExpr::VK_ARM_PREL31:
97         return ELF::R_ARM_PREL31;
98       }
99     case ARM::fixup_arm_blx:
100     case ARM::fixup_arm_uncondbl:
101       switch (Modifier) {
102       case MCSymbolRefExpr::VK_PLT:
103         return ELF::R_ARM_CALL;
104       case MCSymbolRefExpr::VK_TLSCALL:
105         return ELF::R_ARM_TLS_CALL;
106       default:
107         return ELF::R_ARM_CALL;
108       }
109     case ARM::fixup_arm_condbl:
110     case ARM::fixup_arm_condbranch:
111     case ARM::fixup_arm_uncondbranch:
112       return ELF::R_ARM_JUMP24;
113     case ARM::fixup_t2_condbranch:
114       return ELF::R_ARM_THM_JUMP19;
115     case ARM::fixup_t2_uncondbranch:
116       return ELF::R_ARM_THM_JUMP24;
117     case ARM::fixup_arm_movt_hi16:
118       return ELF::R_ARM_MOVT_PREL;
119     case ARM::fixup_arm_movw_lo16:
120       return ELF::R_ARM_MOVW_PREL_NC;
121     case ARM::fixup_t2_movt_hi16:
122       return ELF::R_ARM_THM_MOVT_PREL;
123     case ARM::fixup_t2_movw_lo16:
124       return ELF::R_ARM_THM_MOVW_PREL_NC;
125     case ARM::fixup_arm_thumb_br:
126       return ELF::R_ARM_THM_JUMP11;
127     case ARM::fixup_arm_thumb_bcc:
128       return ELF::R_ARM_THM_JUMP8;
129     case ARM::fixup_arm_thumb_bl:
130     case ARM::fixup_arm_thumb_blx:
131       switch (Modifier) {
132       case MCSymbolRefExpr::VK_TLSCALL:
133         return ELF::R_ARM_THM_TLS_CALL;
134       default:
135         return ELF::R_ARM_THM_CALL;
136       }
137     }
138   }
139   switch ((unsigned)Fixup.getKind()) {
140   default:
141     Ctx.reportFatalError(Fixup.getLoc(), "unsupported relocation on symbol");
142     return ELF::R_ARM_NONE;
143   case FK_Data_1:
144     switch (Modifier) {
145     default:
146       llvm_unreachable("unsupported Modifier");
147     case MCSymbolRefExpr::VK_None:
148       return ELF::R_ARM_ABS8;
149     }
150   case FK_Data_2:
151     switch (Modifier) {
152     default:
153       llvm_unreachable("unsupported modifier");
154     case MCSymbolRefExpr::VK_None:
155       return ELF::R_ARM_ABS16;
156     }
157   case FK_Data_4:
158     switch (Modifier) {
159     default:
160       llvm_unreachable("Unsupported Modifier");
161     case MCSymbolRefExpr::VK_ARM_NONE:
162       return ELF::R_ARM_NONE;
163     case MCSymbolRefExpr::VK_GOT:
164       return ELF::R_ARM_GOT_BREL;
165     case MCSymbolRefExpr::VK_TLSGD:
166       return ELF::R_ARM_TLS_GD32;
167     case MCSymbolRefExpr::VK_TPOFF:
168       return ELF::R_ARM_TLS_LE32;
169     case MCSymbolRefExpr::VK_GOTTPOFF:
170       return ELF::R_ARM_TLS_IE32;
171     case MCSymbolRefExpr::VK_None:
172       return ELF::R_ARM_ABS32;
173     case MCSymbolRefExpr::VK_GOTOFF:
174       return ELF::R_ARM_GOTOFF32;
175     case MCSymbolRefExpr::VK_ARM_GOT_PREL:
176       return ELF::R_ARM_GOT_PREL;
177     case MCSymbolRefExpr::VK_ARM_TARGET1:
178       return ELF::R_ARM_TARGET1;
179     case MCSymbolRefExpr::VK_ARM_TARGET2:
180       return ELF::R_ARM_TARGET2;
181     case MCSymbolRefExpr::VK_ARM_PREL31:
182       return ELF::R_ARM_PREL31;
183     case MCSymbolRefExpr::VK_ARM_SBREL:
184       return ELF::R_ARM_SBREL32;
185     case MCSymbolRefExpr::VK_ARM_TLSLDO:
186       return ELF::R_ARM_TLS_LDO32;
187     case MCSymbolRefExpr::VK_TLSCALL:
188       return ELF::R_ARM_TLS_CALL;
189     case MCSymbolRefExpr::VK_TLSDESC:
190       return ELF::R_ARM_TLS_GOTDESC;
191     case MCSymbolRefExpr::VK_TLSLDM:
192       return ELF::R_ARM_TLS_LDM32;
193     case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ:
194       return ELF::R_ARM_TLS_DESCSEQ;
195     }
196   case ARM::fixup_arm_condbranch:
197   case ARM::fixup_arm_uncondbranch:
198     return ELF::R_ARM_JUMP24;
199   case ARM::fixup_arm_movt_hi16:
200     switch (Modifier) {
201     default:
202       llvm_unreachable("Unsupported Modifier");
203     case MCSymbolRefExpr::VK_None:
204       return ELF::R_ARM_MOVT_ABS;
205     case MCSymbolRefExpr::VK_ARM_SBREL:
206       return ELF::R_ARM_MOVT_BREL;
207     }
208   case ARM::fixup_arm_movw_lo16:
209     switch (Modifier) {
210     default:
211       llvm_unreachable("Unsupported Modifier");
212     case MCSymbolRefExpr::VK_None:
213       return ELF::R_ARM_MOVW_ABS_NC;
214     case MCSymbolRefExpr::VK_ARM_SBREL:
215       return ELF::R_ARM_MOVW_BREL_NC;
216     }
217   case ARM::fixup_t2_movt_hi16:
218     switch (Modifier) {
219     default:
220       llvm_unreachable("Unsupported Modifier");
221     case MCSymbolRefExpr::VK_None:
222       return ELF::R_ARM_THM_MOVT_ABS;
223     case MCSymbolRefExpr::VK_ARM_SBREL:
224       return ELF::R_ARM_THM_MOVT_BREL;
225     }
226   case ARM::fixup_t2_movw_lo16:
227     switch (Modifier) {
228     default:
229       llvm_unreachable("Unsupported Modifier");
230     case MCSymbolRefExpr::VK_None:
231       return ELF::R_ARM_THM_MOVW_ABS_NC;
232     case MCSymbolRefExpr::VK_ARM_SBREL:
233       return ELF::R_ARM_THM_MOVW_BREL_NC;
234     }
235   }
236 }
237 
238 MCObjectWriter *llvm::createARMELFObjectWriter(raw_pwrite_stream &OS,
239                                                uint8_t OSABI,
240                                                bool IsLittleEndian) {
241   return createELFObjectWriter(llvm::make_unique<ARMELFObjectWriter>(OSABI), OS,
242                                IsLittleEndian);
243 }
244