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 unsigned Type = 0; 82 if (IsPCRel) { 83 switch ((unsigned)Fixup.getKind()) { 84 default: 85 Ctx.reportFatalError(Fixup.getLoc(), "unsupported relocation on symbol"); 86 return ELF::R_ARM_NONE; 87 case FK_Data_4: 88 switch (Modifier) { 89 default: llvm_unreachable("Unsupported Modifier"); 90 case MCSymbolRefExpr::VK_None: 91 Type = ELF::R_ARM_REL32; 92 break; 93 case MCSymbolRefExpr::VK_TLSGD: 94 llvm_unreachable("unimplemented"); 95 case MCSymbolRefExpr::VK_GOTTPOFF: 96 Type = ELF::R_ARM_TLS_IE32; 97 break; 98 case MCSymbolRefExpr::VK_ARM_GOT_PREL: 99 Type = ELF::R_ARM_GOT_PREL; 100 break; 101 case MCSymbolRefExpr::VK_ARM_PREL31: 102 Type = ELF::R_ARM_PREL31; 103 break; 104 } 105 break; 106 case ARM::fixup_arm_blx: 107 case ARM::fixup_arm_uncondbl: 108 switch (Modifier) { 109 case MCSymbolRefExpr::VK_PLT: 110 Type = ELF::R_ARM_CALL; 111 break; 112 case MCSymbolRefExpr::VK_TLSCALL: 113 Type = ELF::R_ARM_TLS_CALL; 114 break; 115 default: 116 Type = ELF::R_ARM_CALL; 117 break; 118 } 119 break; 120 case ARM::fixup_arm_condbl: 121 case ARM::fixup_arm_condbranch: 122 case ARM::fixup_arm_uncondbranch: 123 Type = ELF::R_ARM_JUMP24; 124 break; 125 case ARM::fixup_t2_condbranch: 126 Type = ELF::R_ARM_THM_JUMP19; 127 break; 128 case ARM::fixup_t2_uncondbranch: 129 Type = ELF::R_ARM_THM_JUMP24; 130 break; 131 case ARM::fixup_arm_movt_hi16: 132 Type = ELF::R_ARM_MOVT_PREL; 133 break; 134 case ARM::fixup_arm_movw_lo16: 135 Type = ELF::R_ARM_MOVW_PREL_NC; 136 break; 137 case ARM::fixup_t2_movt_hi16: 138 Type = ELF::R_ARM_THM_MOVT_PREL; 139 break; 140 case ARM::fixup_t2_movw_lo16: 141 Type = ELF::R_ARM_THM_MOVW_PREL_NC; 142 break; 143 case ARM::fixup_arm_thumb_br: 144 Type = ELF::R_ARM_THM_JUMP11; 145 break; 146 case ARM::fixup_arm_thumb_bcc: 147 Type = ELF::R_ARM_THM_JUMP8; 148 break; 149 case ARM::fixup_arm_thumb_bl: 150 case ARM::fixup_arm_thumb_blx: 151 switch (Modifier) { 152 case MCSymbolRefExpr::VK_TLSCALL: 153 Type = ELF::R_ARM_THM_TLS_CALL; 154 break; 155 default: 156 Type = ELF::R_ARM_THM_CALL; 157 break; 158 } 159 break; 160 } 161 } else { 162 switch ((unsigned)Fixup.getKind()) { 163 default: 164 Ctx.reportFatalError(Fixup.getLoc(), "unsupported relocation on symbol"); 165 return ELF::R_ARM_NONE; 166 case FK_Data_1: 167 switch (Modifier) { 168 default: llvm_unreachable("unsupported Modifier"); 169 case MCSymbolRefExpr::VK_None: 170 Type = ELF::R_ARM_ABS8; 171 break; 172 } 173 break; 174 case FK_Data_2: 175 switch (Modifier) { 176 default: llvm_unreachable("unsupported modifier"); 177 case MCSymbolRefExpr::VK_None: 178 Type = ELF::R_ARM_ABS16; 179 break; 180 } 181 break; 182 case FK_Data_4: 183 switch (Modifier) { 184 default: llvm_unreachable("Unsupported Modifier"); 185 case MCSymbolRefExpr::VK_ARM_NONE: 186 Type = ELF::R_ARM_NONE; 187 break; 188 case MCSymbolRefExpr::VK_GOT: 189 Type = ELF::R_ARM_GOT_BREL; 190 break; 191 case MCSymbolRefExpr::VK_TLSGD: 192 Type = ELF::R_ARM_TLS_GD32; 193 break; 194 case MCSymbolRefExpr::VK_TPOFF: 195 Type = ELF::R_ARM_TLS_LE32; 196 break; 197 case MCSymbolRefExpr::VK_GOTTPOFF: 198 Type = ELF::R_ARM_TLS_IE32; 199 break; 200 case MCSymbolRefExpr::VK_None: 201 Type = ELF::R_ARM_ABS32; 202 break; 203 case MCSymbolRefExpr::VK_GOTOFF: 204 Type = ELF::R_ARM_GOTOFF32; 205 break; 206 case MCSymbolRefExpr::VK_ARM_GOT_PREL: 207 Type = ELF::R_ARM_GOT_PREL; 208 break; 209 case MCSymbolRefExpr::VK_ARM_TARGET1: 210 Type = ELF::R_ARM_TARGET1; 211 break; 212 case MCSymbolRefExpr::VK_ARM_TARGET2: 213 Type = ELF::R_ARM_TARGET2; 214 break; 215 case MCSymbolRefExpr::VK_ARM_PREL31: 216 Type = ELF::R_ARM_PREL31; 217 break; 218 case MCSymbolRefExpr::VK_ARM_SBREL: 219 Type = ELF::R_ARM_SBREL32; 220 break; 221 case MCSymbolRefExpr::VK_ARM_TLSLDO: 222 Type = ELF::R_ARM_TLS_LDO32; 223 break; 224 case MCSymbolRefExpr::VK_TLSCALL: 225 Type = ELF::R_ARM_TLS_CALL; 226 break; 227 case MCSymbolRefExpr::VK_TLSDESC: 228 Type = ELF::R_ARM_TLS_GOTDESC; 229 break; 230 case MCSymbolRefExpr::VK_TLSLDM: 231 Type = ELF::R_ARM_TLS_LDM32; 232 break; 233 case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ: 234 Type = ELF::R_ARM_TLS_DESCSEQ; 235 break; 236 } 237 break; 238 case ARM::fixup_arm_ldst_pcrel_12: 239 case ARM::fixup_arm_pcrel_10: 240 case ARM::fixup_arm_adr_pcrel_12: 241 case ARM::fixup_arm_thumb_bl: 242 case ARM::fixup_arm_thumb_cb: 243 case ARM::fixup_arm_thumb_cp: 244 case ARM::fixup_arm_thumb_br: 245 llvm_unreachable("Unimplemented"); 246 case ARM::fixup_arm_condbranch: 247 case ARM::fixup_arm_uncondbranch: 248 Type = ELF::R_ARM_JUMP24; 249 break; 250 case ARM::fixup_arm_movt_hi16: 251 switch (Modifier) { 252 default: llvm_unreachable("Unsupported Modifier"); 253 case MCSymbolRefExpr::VK_None: 254 Type = ELF::R_ARM_MOVT_ABS; 255 break; 256 case MCSymbolRefExpr::VK_ARM_SBREL: 257 Type = ELF:: R_ARM_MOVT_BREL; 258 break; 259 } 260 break; 261 case ARM::fixup_arm_movw_lo16: 262 switch (Modifier) { 263 default: llvm_unreachable("Unsupported Modifier"); 264 case MCSymbolRefExpr::VK_None: 265 Type = ELF::R_ARM_MOVW_ABS_NC; 266 break; 267 case MCSymbolRefExpr::VK_ARM_SBREL: 268 Type = ELF:: R_ARM_MOVW_BREL_NC; 269 break; 270 } 271 break; 272 case ARM::fixup_t2_movt_hi16: 273 switch (Modifier) { 274 default: llvm_unreachable("Unsupported Modifier"); 275 case MCSymbolRefExpr::VK_None: 276 Type = ELF::R_ARM_THM_MOVT_ABS; 277 break; 278 case MCSymbolRefExpr::VK_ARM_SBREL: 279 Type = ELF:: R_ARM_THM_MOVT_BREL; 280 break; 281 } 282 break; 283 case ARM::fixup_t2_movw_lo16: 284 switch (Modifier) { 285 default: llvm_unreachable("Unsupported Modifier"); 286 case MCSymbolRefExpr::VK_None: 287 Type = ELF::R_ARM_THM_MOVW_ABS_NC; 288 break; 289 case MCSymbolRefExpr::VK_ARM_SBREL: 290 Type = ELF:: R_ARM_THM_MOVW_BREL_NC; 291 break; 292 } 293 break; 294 } 295 } 296 297 return Type; 298 } 299 300 MCObjectWriter *llvm::createARMELFObjectWriter(raw_pwrite_stream &OS, 301 uint8_t OSABI, 302 bool IsLittleEndian) { 303 MCELFObjectTargetWriter *MOTW = new ARMELFObjectWriter(OSABI); 304 return createELFObjectWriter(MOTW, OS, IsLittleEndian); 305 } 306