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