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