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 virtual ~ARMELFObjectWriter(); 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: llvm_unreachable("Unimplemented"); 85 case FK_Data_4: 86 switch (Modifier) { 87 default: llvm_unreachable("Unsupported Modifier"); 88 case MCSymbolRefExpr::VK_None: 89 Type = ELF::R_ARM_REL32; 90 break; 91 case MCSymbolRefExpr::VK_TLSGD: 92 llvm_unreachable("unimplemented"); 93 case MCSymbolRefExpr::VK_GOTTPOFF: 94 Type = ELF::R_ARM_TLS_IE32; 95 break; 96 case MCSymbolRefExpr::VK_GOTPCREL: 97 Type = ELF::R_ARM_GOT_PREL; 98 break; 99 } 100 break; 101 case ARM::fixup_arm_blx: 102 case ARM::fixup_arm_uncondbl: 103 switch (Modifier) { 104 case MCSymbolRefExpr::VK_PLT: 105 Type = ELF::R_ARM_CALL; 106 break; 107 case MCSymbolRefExpr::VK_ARM_TLSCALL: 108 Type = ELF::R_ARM_TLS_CALL; 109 break; 110 default: 111 Type = ELF::R_ARM_CALL; 112 break; 113 } 114 break; 115 case ARM::fixup_arm_condbl: 116 case ARM::fixup_arm_condbranch: 117 case ARM::fixup_arm_uncondbranch: 118 Type = ELF::R_ARM_JUMP24; 119 break; 120 case ARM::fixup_t2_condbranch: 121 case ARM::fixup_t2_uncondbranch: 122 Type = ELF::R_ARM_THM_JUMP24; 123 break; 124 case ARM::fixup_arm_movt_hi16: 125 Type = ELF::R_ARM_MOVT_PREL; 126 break; 127 case ARM::fixup_arm_movw_lo16: 128 Type = ELF::R_ARM_MOVW_PREL_NC; 129 break; 130 case ARM::fixup_t2_movt_hi16: 131 Type = ELF::R_ARM_THM_MOVT_PREL; 132 break; 133 case ARM::fixup_t2_movw_lo16: 134 Type = ELF::R_ARM_THM_MOVW_PREL_NC; 135 break; 136 case ARM::fixup_arm_thumb_bl: 137 case ARM::fixup_arm_thumb_blx: 138 switch (Modifier) { 139 case MCSymbolRefExpr::VK_ARM_TLSCALL: 140 Type = ELF::R_ARM_THM_TLS_CALL; 141 break; 142 default: 143 Type = ELF::R_ARM_THM_CALL; 144 break; 145 } 146 break; 147 } 148 } else { 149 switch ((unsigned)Fixup.getKind()) { 150 default: llvm_unreachable("invalid fixup kind!"); 151 case FK_Data_1: 152 switch (Modifier) { 153 default: llvm_unreachable("unsupported Modifier"); 154 case MCSymbolRefExpr::VK_None: 155 Type = ELF::R_ARM_ABS8; 156 break; 157 } 158 break; 159 case FK_Data_2: 160 switch (Modifier) { 161 default: llvm_unreachable("unsupported modifier"); 162 case MCSymbolRefExpr::VK_None: 163 Type = ELF::R_ARM_ABS16; 164 break; 165 } 166 break; 167 case FK_Data_4: 168 switch (Modifier) { 169 default: llvm_unreachable("Unsupported Modifier"); 170 case MCSymbolRefExpr::VK_ARM_NONE: 171 Type = ELF::R_ARM_NONE; 172 break; 173 case MCSymbolRefExpr::VK_GOT: 174 Type = ELF::R_ARM_GOT_BREL; 175 break; 176 case MCSymbolRefExpr::VK_TLSGD: 177 Type = ELF::R_ARM_TLS_GD32; 178 break; 179 case MCSymbolRefExpr::VK_TPOFF: 180 Type = ELF::R_ARM_TLS_LE32; 181 break; 182 case MCSymbolRefExpr::VK_GOTTPOFF: 183 Type = ELF::R_ARM_TLS_IE32; 184 break; 185 case MCSymbolRefExpr::VK_None: 186 Type = ELF::R_ARM_ABS32; 187 break; 188 case MCSymbolRefExpr::VK_GOTOFF: 189 Type = ELF::R_ARM_GOTOFF32; 190 break; 191 case MCSymbolRefExpr::VK_GOTPCREL: 192 Type = ELF::R_ARM_GOT_PREL; 193 break; 194 case MCSymbolRefExpr::VK_ARM_TARGET1: 195 Type = ELF::R_ARM_TARGET1; 196 break; 197 case MCSymbolRefExpr::VK_ARM_TARGET2: 198 Type = ELF::R_ARM_TARGET2; 199 break; 200 case MCSymbolRefExpr::VK_ARM_PREL31: 201 Type = ELF::R_ARM_PREL31; 202 break; 203 case MCSymbolRefExpr::VK_ARM_SBREL: 204 Type = ELF::R_ARM_SBREL32; 205 break; 206 case MCSymbolRefExpr::VK_ARM_TLSLDO: 207 Type = ELF::R_ARM_TLS_LDO32; 208 break; 209 case MCSymbolRefExpr::VK_ARM_TLSCALL: 210 Type = ELF::R_ARM_TLS_CALL; 211 break; 212 case MCSymbolRefExpr::VK_ARM_TLSDESC: 213 Type = ELF::R_ARM_TLS_GOTDESC; 214 break; 215 case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ: 216 Type = ELF::R_ARM_TLS_DESCSEQ; 217 break; 218 } 219 break; 220 case ARM::fixup_arm_ldst_pcrel_12: 221 case ARM::fixup_arm_pcrel_10: 222 case ARM::fixup_arm_adr_pcrel_12: 223 case ARM::fixup_arm_thumb_bl: 224 case ARM::fixup_arm_thumb_cb: 225 case ARM::fixup_arm_thumb_cp: 226 case ARM::fixup_arm_thumb_br: 227 llvm_unreachable("Unimplemented"); 228 case ARM::fixup_arm_condbranch: 229 case ARM::fixup_arm_uncondbranch: 230 Type = ELF::R_ARM_JUMP24; 231 break; 232 case ARM::fixup_arm_movt_hi16: 233 Type = ELF::R_ARM_MOVT_ABS; 234 break; 235 case ARM::fixup_arm_movw_lo16: 236 Type = ELF::R_ARM_MOVW_ABS_NC; 237 break; 238 case ARM::fixup_t2_movt_hi16: 239 Type = ELF::R_ARM_THM_MOVT_ABS; 240 break; 241 case ARM::fixup_t2_movw_lo16: 242 Type = ELF::R_ARM_THM_MOVW_ABS_NC; 243 break; 244 } 245 } 246 247 return Type; 248 } 249 250 MCObjectWriter *llvm::createARMELFObjectWriter(raw_ostream &OS, 251 uint8_t OSABI, 252 bool IsLittleEndian) { 253 MCELFObjectTargetWriter *MOTW = new ARMELFObjectWriter(OSABI); 254 return createELFObjectWriter(MOTW, OS, IsLittleEndian); 255 } 256