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