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