1dff0c46cSDimitry Andric //===-- ARMELFObjectWriter.cpp - ARM ELF Writer ---------------------------===//
2dff0c46cSDimitry Andric //
3dff0c46cSDimitry Andric //                     The LLVM Compiler Infrastructure
4dff0c46cSDimitry Andric //
5dff0c46cSDimitry Andric // This file is distributed under the University of Illinois Open Source
6dff0c46cSDimitry Andric // License. See LICENSE.TXT for details.
7dff0c46cSDimitry Andric //
8dff0c46cSDimitry Andric //===----------------------------------------------------------------------===//
9dff0c46cSDimitry Andric 
10139f7f9bSDimitry Andric #include "MCTargetDesc/ARMFixupKinds.h"
117a7e6055SDimitry Andric #include "MCTargetDesc/ARMMCTargetDesc.h"
12db17bf38SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
137a7e6055SDimitry Andric #include "llvm/MC/MCContext.h"
14dff0c46cSDimitry Andric #include "llvm/MC/MCELFObjectWriter.h"
15dff0c46cSDimitry Andric #include "llvm/MC/MCExpr.h"
167a7e6055SDimitry Andric #include "llvm/MC/MCFixup.h"
17*b5893f02SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
182cab237bSDimitry Andric #include "llvm/MC/MCObjectWriter.h"
19dff0c46cSDimitry Andric #include "llvm/MC/MCValue.h"
20139f7f9bSDimitry Andric #include "llvm/Support/ErrorHandling.h"
21139f7f9bSDimitry Andric #include "llvm/Support/raw_ostream.h"
227a7e6055SDimitry Andric #include <cstdint>
23dff0c46cSDimitry Andric 
24dff0c46cSDimitry Andric using namespace llvm;
25dff0c46cSDimitry Andric 
26dff0c46cSDimitry Andric namespace {
277a7e6055SDimitry Andric 
28dff0c46cSDimitry Andric   class ARMELFObjectWriter : public MCELFObjectTargetWriter {
29dff0c46cSDimitry Andric     enum { DefaultEABIVersion = 0x05000000U };
30dff0c46cSDimitry Andric 
317a7e6055SDimitry Andric     unsigned GetRelocTypeInner(const MCValue &Target, const MCFixup &Fixup,
327a7e6055SDimitry Andric                                bool IsPCRel, MCContext &Ctx) const;
33dff0c46cSDimitry Andric 
34dff0c46cSDimitry Andric   public:
35dff0c46cSDimitry Andric     ARMELFObjectWriter(uint8_t OSABI);
36dff0c46cSDimitry Andric 
377a7e6055SDimitry Andric     ~ARMELFObjectWriter() override = default;
38dff0c46cSDimitry Andric 
393ca95b02SDimitry Andric     unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
403ca95b02SDimitry Andric                           const MCFixup &Fixup, bool IsPCRel) const override;
4191bc56edSDimitry Andric 
4297bc6c73SDimitry Andric     bool needsRelocateWithSymbol(const MCSymbol &Sym,
4391bc56edSDimitry Andric                                  unsigned Type) const override;
44*b5893f02SDimitry Andric 
45*b5893f02SDimitry Andric     void addTargetSectionFlags(MCContext &Ctx, MCSectionELF &Sec) override;
46dff0c46cSDimitry Andric   };
477a7e6055SDimitry Andric 
487a7e6055SDimitry Andric } // end anonymous namespace
49dff0c46cSDimitry Andric 
ARMELFObjectWriter(uint8_t OSABI)50dff0c46cSDimitry Andric ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI)
51dff0c46cSDimitry Andric   : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI,
52dff0c46cSDimitry Andric                             ELF::EM_ARM,
53dff0c46cSDimitry Andric                             /*HasRelocationAddend*/ false) {}
54dff0c46cSDimitry Andric 
needsRelocateWithSymbol(const MCSymbol & Sym,unsigned Type) const5597bc6c73SDimitry Andric bool ARMELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
5691bc56edSDimitry Andric                                                  unsigned Type) const {
5739d628a0SDimitry Andric   // FIXME: This is extremely conservative. This really needs to use a
5891bc56edSDimitry Andric   // whitelist with a clear explanation for why each realocation needs to
5991bc56edSDimitry Andric   // point to the symbol, not to the section.
6091bc56edSDimitry Andric   switch (Type) {
61dff0c46cSDimitry Andric   default:
6291bc56edSDimitry Andric     return true;
6391bc56edSDimitry Andric 
6491bc56edSDimitry Andric   case ELF::R_ARM_PREL31:
65dff0c46cSDimitry Andric   case ELF::R_ARM_ABS32:
6691bc56edSDimitry Andric     return false;
67dff0c46cSDimitry Andric   }
68dff0c46cSDimitry Andric }
69dff0c46cSDimitry Andric 
70dff0c46cSDimitry Andric // Need to examine the Fixup when determining whether to
71dff0c46cSDimitry Andric // emit the relocation as an explicit symbol or as a section relative
72dff0c46cSDimitry Andric // offset
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const733ca95b02SDimitry Andric unsigned ARMELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
74dff0c46cSDimitry Andric                                           const MCFixup &Fixup,
7591bc56edSDimitry Andric                                           bool IsPCRel) const {
767a7e6055SDimitry Andric   return GetRelocTypeInner(Target, Fixup, IsPCRel, Ctx);
77dff0c46cSDimitry Andric }
78dff0c46cSDimitry Andric 
GetRelocTypeInner(const MCValue & Target,const MCFixup & Fixup,bool IsPCRel,MCContext & Ctx) const79dff0c46cSDimitry Andric unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
80dff0c46cSDimitry Andric                                                const MCFixup &Fixup,
817a7e6055SDimitry Andric                                                bool IsPCRel,
827a7e6055SDimitry Andric                                                MCContext &Ctx) const {
8391bc56edSDimitry Andric   MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
84dff0c46cSDimitry Andric 
85dff0c46cSDimitry Andric   if (IsPCRel) {
86dff0c46cSDimitry Andric     switch ((unsigned)Fixup.getKind()) {
87ff0cc061SDimitry Andric     default:
887a7e6055SDimitry Andric       Ctx.reportFatalError(Fixup.getLoc(), "unsupported relocation on symbol");
89ff0cc061SDimitry Andric       return ELF::R_ARM_NONE;
90dff0c46cSDimitry Andric     case FK_Data_4:
91dff0c46cSDimitry Andric       switch (Modifier) {
922cab237bSDimitry Andric       default:
932cab237bSDimitry Andric         llvm_unreachable("Unsupported Modifier");
94dff0c46cSDimitry Andric       case MCSymbolRefExpr::VK_None:
952cab237bSDimitry Andric         return ELF::R_ARM_REL32;
9691bc56edSDimitry Andric       case MCSymbolRefExpr::VK_GOTTPOFF:
972cab237bSDimitry Andric         return ELF::R_ARM_TLS_IE32;
987d523365SDimitry Andric       case MCSymbolRefExpr::VK_ARM_GOT_PREL:
992cab237bSDimitry Andric         return ELF::R_ARM_GOT_PREL;
1003ca95b02SDimitry Andric       case MCSymbolRefExpr::VK_ARM_PREL31:
1012cab237bSDimitry Andric         return ELF::R_ARM_PREL31;
102dff0c46cSDimitry Andric       }
103dff0c46cSDimitry Andric     case ARM::fixup_arm_blx:
1047ae0e2c9SDimitry Andric     case ARM::fixup_arm_uncondbl:
105dff0c46cSDimitry Andric       switch (Modifier) {
10691bc56edSDimitry Andric       case MCSymbolRefExpr::VK_PLT:
1072cab237bSDimitry Andric         return ELF::R_ARM_CALL;
1083ca95b02SDimitry Andric       case MCSymbolRefExpr::VK_TLSCALL:
1092cab237bSDimitry Andric         return ELF::R_ARM_TLS_CALL;
110dff0c46cSDimitry Andric       default:
1112cab237bSDimitry Andric         return ELF::R_ARM_CALL;
112dff0c46cSDimitry Andric       }
113dff0c46cSDimitry Andric     case ARM::fixup_arm_condbl:
114dff0c46cSDimitry Andric     case ARM::fixup_arm_condbranch:
1157ae0e2c9SDimitry Andric     case ARM::fixup_arm_uncondbranch:
1162cab237bSDimitry Andric       return ELF::R_ARM_JUMP24;
1173861d79fSDimitry Andric     case ARM::fixup_t2_condbranch:
1182cab237bSDimitry Andric       return ELF::R_ARM_THM_JUMP19;
1193861d79fSDimitry Andric     case ARM::fixup_t2_uncondbranch:
1202cab237bSDimitry Andric       return ELF::R_ARM_THM_JUMP24;
121dff0c46cSDimitry Andric     case ARM::fixup_arm_movt_hi16:
1222cab237bSDimitry Andric       return ELF::R_ARM_MOVT_PREL;
123dff0c46cSDimitry Andric     case ARM::fixup_arm_movw_lo16:
1242cab237bSDimitry Andric       return ELF::R_ARM_MOVW_PREL_NC;
125dff0c46cSDimitry Andric     case ARM::fixup_t2_movt_hi16:
1262cab237bSDimitry Andric       return ELF::R_ARM_THM_MOVT_PREL;
127dff0c46cSDimitry Andric     case ARM::fixup_t2_movw_lo16:
1282cab237bSDimitry Andric       return ELF::R_ARM_THM_MOVW_PREL_NC;
129d88c1a5aSDimitry Andric     case ARM::fixup_arm_thumb_br:
1302cab237bSDimitry Andric       return ELF::R_ARM_THM_JUMP11;
131d88c1a5aSDimitry Andric     case ARM::fixup_arm_thumb_bcc:
1322cab237bSDimitry Andric       return ELF::R_ARM_THM_JUMP8;
133dff0c46cSDimitry Andric     case ARM::fixup_arm_thumb_bl:
134dff0c46cSDimitry Andric     case ARM::fixup_arm_thumb_blx:
13591bc56edSDimitry Andric       switch (Modifier) {
1363ca95b02SDimitry Andric       case MCSymbolRefExpr::VK_TLSCALL:
1372cab237bSDimitry Andric         return ELF::R_ARM_THM_TLS_CALL;
13891bc56edSDimitry Andric       default:
1392cab237bSDimitry Andric         return ELF::R_ARM_THM_CALL;
140dff0c46cSDimitry Andric       }
14191bc56edSDimitry Andric     }
1422cab237bSDimitry Andric   }
143dff0c46cSDimitry Andric   switch ((unsigned)Fixup.getKind()) {
144ff0cc061SDimitry Andric   default:
1457a7e6055SDimitry Andric     Ctx.reportFatalError(Fixup.getLoc(), "unsupported relocation on symbol");
146ff0cc061SDimitry Andric     return ELF::R_ARM_NONE;
14739d628a0SDimitry Andric   case FK_Data_1:
14839d628a0SDimitry Andric     switch (Modifier) {
1492cab237bSDimitry Andric     default:
1502cab237bSDimitry Andric       llvm_unreachable("unsupported Modifier");
15139d628a0SDimitry Andric     case MCSymbolRefExpr::VK_None:
1522cab237bSDimitry Andric       return ELF::R_ARM_ABS8;
15339d628a0SDimitry Andric     }
15439d628a0SDimitry Andric   case FK_Data_2:
15539d628a0SDimitry Andric     switch (Modifier) {
1562cab237bSDimitry Andric     default:
1572cab237bSDimitry Andric       llvm_unreachable("unsupported modifier");
15839d628a0SDimitry Andric     case MCSymbolRefExpr::VK_None:
1592cab237bSDimitry Andric       return ELF::R_ARM_ABS16;
16039d628a0SDimitry Andric     }
161dff0c46cSDimitry Andric   case FK_Data_4:
162dff0c46cSDimitry Andric     switch (Modifier) {
1632cab237bSDimitry Andric     default:
1642cab237bSDimitry Andric       llvm_unreachable("Unsupported Modifier");
165139f7f9bSDimitry Andric     case MCSymbolRefExpr::VK_ARM_NONE:
1662cab237bSDimitry Andric       return ELF::R_ARM_NONE;
16791bc56edSDimitry Andric     case MCSymbolRefExpr::VK_GOT:
1682cab237bSDimitry Andric       return ELF::R_ARM_GOT_BREL;
16991bc56edSDimitry Andric     case MCSymbolRefExpr::VK_TLSGD:
1702cab237bSDimitry Andric       return ELF::R_ARM_TLS_GD32;
17191bc56edSDimitry Andric     case MCSymbolRefExpr::VK_TPOFF:
1722cab237bSDimitry Andric       return ELF::R_ARM_TLS_LE32;
17391bc56edSDimitry Andric     case MCSymbolRefExpr::VK_GOTTPOFF:
1742cab237bSDimitry Andric       return ELF::R_ARM_TLS_IE32;
175dff0c46cSDimitry Andric     case MCSymbolRefExpr::VK_None:
1762cab237bSDimitry Andric       return ELF::R_ARM_ABS32;
17791bc56edSDimitry Andric     case MCSymbolRefExpr::VK_GOTOFF:
1782cab237bSDimitry Andric       return ELF::R_ARM_GOTOFF32;
1797d523365SDimitry Andric     case MCSymbolRefExpr::VK_ARM_GOT_PREL:
1802cab237bSDimitry Andric       return ELF::R_ARM_GOT_PREL;
181dff0c46cSDimitry Andric     case MCSymbolRefExpr::VK_ARM_TARGET1:
1822cab237bSDimitry Andric       return ELF::R_ARM_TARGET1;
1833861d79fSDimitry Andric     case MCSymbolRefExpr::VK_ARM_TARGET2:
1842cab237bSDimitry Andric       return ELF::R_ARM_TARGET2;
185139f7f9bSDimitry Andric     case MCSymbolRefExpr::VK_ARM_PREL31:
1862cab237bSDimitry Andric       return ELF::R_ARM_PREL31;
18739d628a0SDimitry Andric     case MCSymbolRefExpr::VK_ARM_SBREL:
1882cab237bSDimitry Andric       return ELF::R_ARM_SBREL32;
18991bc56edSDimitry Andric     case MCSymbolRefExpr::VK_ARM_TLSLDO:
1902cab237bSDimitry Andric       return ELF::R_ARM_TLS_LDO32;
1913ca95b02SDimitry Andric     case MCSymbolRefExpr::VK_TLSCALL:
1922cab237bSDimitry Andric       return ELF::R_ARM_TLS_CALL;
1933ca95b02SDimitry Andric     case MCSymbolRefExpr::VK_TLSDESC:
1942cab237bSDimitry Andric       return ELF::R_ARM_TLS_GOTDESC;
195d88c1a5aSDimitry Andric     case MCSymbolRefExpr::VK_TLSLDM:
1962cab237bSDimitry Andric       return ELF::R_ARM_TLS_LDM32;
19791bc56edSDimitry Andric     case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ:
1982cab237bSDimitry Andric       return ELF::R_ARM_TLS_DESCSEQ;
199dff0c46cSDimitry Andric     }
200dff0c46cSDimitry Andric   case ARM::fixup_arm_condbranch:
2017ae0e2c9SDimitry Andric   case ARM::fixup_arm_uncondbranch:
2022cab237bSDimitry Andric     return ELF::R_ARM_JUMP24;
203dff0c46cSDimitry Andric   case ARM::fixup_arm_movt_hi16:
204d88c1a5aSDimitry Andric     switch (Modifier) {
2052cab237bSDimitry Andric     default:
2062cab237bSDimitry Andric       llvm_unreachable("Unsupported Modifier");
207d88c1a5aSDimitry Andric     case MCSymbolRefExpr::VK_None:
2082cab237bSDimitry Andric       return ELF::R_ARM_MOVT_ABS;
209d88c1a5aSDimitry Andric     case MCSymbolRefExpr::VK_ARM_SBREL:
2102cab237bSDimitry Andric       return ELF::R_ARM_MOVT_BREL;
211d88c1a5aSDimitry Andric     }
212dff0c46cSDimitry Andric   case ARM::fixup_arm_movw_lo16:
213d88c1a5aSDimitry Andric     switch (Modifier) {
2142cab237bSDimitry Andric     default:
2152cab237bSDimitry Andric       llvm_unreachable("Unsupported Modifier");
216d88c1a5aSDimitry Andric     case MCSymbolRefExpr::VK_None:
2172cab237bSDimitry Andric       return ELF::R_ARM_MOVW_ABS_NC;
218d88c1a5aSDimitry Andric     case MCSymbolRefExpr::VK_ARM_SBREL:
2192cab237bSDimitry Andric       return ELF::R_ARM_MOVW_BREL_NC;
220d88c1a5aSDimitry Andric     }
221dff0c46cSDimitry Andric   case ARM::fixup_t2_movt_hi16:
2227a7e6055SDimitry Andric     switch (Modifier) {
2232cab237bSDimitry Andric     default:
2242cab237bSDimitry Andric       llvm_unreachable("Unsupported Modifier");
2257a7e6055SDimitry Andric     case MCSymbolRefExpr::VK_None:
2262cab237bSDimitry Andric       return ELF::R_ARM_THM_MOVT_ABS;
2277a7e6055SDimitry Andric     case MCSymbolRefExpr::VK_ARM_SBREL:
2282cab237bSDimitry Andric       return ELF::R_ARM_THM_MOVT_BREL;
2297a7e6055SDimitry Andric     }
230dff0c46cSDimitry Andric   case ARM::fixup_t2_movw_lo16:
2317a7e6055SDimitry Andric     switch (Modifier) {
2322cab237bSDimitry Andric     default:
2332cab237bSDimitry Andric       llvm_unreachable("Unsupported Modifier");
2347a7e6055SDimitry Andric     case MCSymbolRefExpr::VK_None:
2352cab237bSDimitry Andric       return ELF::R_ARM_THM_MOVW_ABS_NC;
2367a7e6055SDimitry Andric     case MCSymbolRefExpr::VK_ARM_SBREL:
2372cab237bSDimitry Andric       return ELF::R_ARM_THM_MOVW_BREL_NC;
2387a7e6055SDimitry Andric     }
239dff0c46cSDimitry Andric   }
240dff0c46cSDimitry Andric }
241dff0c46cSDimitry Andric 
addTargetSectionFlags(MCContext & Ctx,MCSectionELF & Sec)242*b5893f02SDimitry Andric void ARMELFObjectWriter::addTargetSectionFlags(MCContext &Ctx,
243*b5893f02SDimitry Andric                                                MCSectionELF &Sec) {
244*b5893f02SDimitry Andric   // The mix of execute-only and non-execute-only at link time is
245*b5893f02SDimitry Andric   // non-execute-only. To avoid the empty implicitly created .text
246*b5893f02SDimitry Andric   // section from making the whole .text section non-execute-only, we
247*b5893f02SDimitry Andric   // mark it execute-only if it is empty and there is at least one
248*b5893f02SDimitry Andric   // execute-only section in the object.
249*b5893f02SDimitry Andric   MCSectionELF *TextSection =
250*b5893f02SDimitry Andric       static_cast<MCSectionELF *>(Ctx.getObjectFileInfo()->getTextSection());
251*b5893f02SDimitry Andric   if (Sec.getKind().isExecuteOnly() && !TextSection->hasInstructions() &&
252*b5893f02SDimitry Andric       !TextSection->hasData()) {
253*b5893f02SDimitry Andric     TextSection->setFlags(TextSection->getFlags() | ELF::SHF_ARM_PURECODE);
254*b5893f02SDimitry Andric   }
255*b5893f02SDimitry Andric }
256*b5893f02SDimitry Andric 
2574ba319b5SDimitry Andric std::unique_ptr<MCObjectTargetWriter>
createARMELFObjectWriter(uint8_t OSABI)2584ba319b5SDimitry Andric llvm::createARMELFObjectWriter(uint8_t OSABI) {
2594ba319b5SDimitry Andric   return llvm::make_unique<ARMELFObjectWriter>(OSABI);
260dff0c46cSDimitry Andric }
261