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 22using namespace llvm; 23 24namespace { 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(unsigned Type) const override; 41 }; 42} 43 44ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI) 45 : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, 46 ELF::EM_ARM, 47 /*HasRelocationAddend*/ false) {} 48 49ARMELFObjectWriter::~ARMELFObjectWriter() {} 50 51bool ARMELFObjectWriter::needsRelocateWithSymbol(unsigned Type) const { 52 // FIXME: This is extremelly conservative. This really needs to use a 53 // whitelist with a clear explanation for why each realocation needs to 54 // point to the symbol, not to the section. 55 switch (Type) { 56 default: 57 return true; 58 59 case ELF::R_ARM_PREL31: 60 case ELF::R_ARM_ABS32: 61 return false; 62 } 63} 64 65// Need to examine the Fixup when determining whether to 66// emit the relocation as an explicit symbol or as a section relative 67// offset 68unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target, 69 const MCFixup &Fixup, 70 bool IsPCRel) const { 71 return GetRelocTypeInner(Target, Fixup, IsPCRel); 72} 73 74unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, 75 const MCFixup &Fixup, 76 bool IsPCRel) const { 77 MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); 78 79 unsigned Type = 0; 80 if (IsPCRel) { 81 switch ((unsigned)Fixup.getKind()) { 82 default: llvm_unreachable("Unimplemented"); 83 case FK_Data_4: 84 switch (Modifier) { 85 default: llvm_unreachable("Unsupported Modifier"); 86 case MCSymbolRefExpr::VK_None: 87 Type = ELF::R_ARM_REL32; 88 break; 89 case MCSymbolRefExpr::VK_TLSGD: 90 llvm_unreachable("unimplemented"); 91 case MCSymbolRefExpr::VK_GOTTPOFF: 92 Type = ELF::R_ARM_TLS_IE32; 93 break; 94 case MCSymbolRefExpr::VK_GOTPCREL: 95 Type = ELF::R_ARM_GOT_PREL; 96 break; 97 } 98 break; 99 case ARM::fixup_arm_blx: 100 case ARM::fixup_arm_uncondbl: 101 switch (Modifier) { 102 case MCSymbolRefExpr::VK_PLT: 103 Type = ELF::R_ARM_PLT32; 104 break; 105 case MCSymbolRefExpr::VK_ARM_TLSCALL: 106 Type = ELF::R_ARM_TLS_CALL; 107 break; 108 default: 109 Type = ELF::R_ARM_CALL; 110 break; 111 } 112 break; 113 case ARM::fixup_arm_condbl: 114 case ARM::fixup_arm_condbranch: 115 case ARM::fixup_arm_uncondbranch: 116 Type = ELF::R_ARM_JUMP24; 117 break; 118 case ARM::fixup_t2_condbranch: 119 case ARM::fixup_t2_uncondbranch: 120 Type = ELF::R_ARM_THM_JUMP24; 121 break; 122 case ARM::fixup_arm_movt_hi16: 123 Type = ELF::R_ARM_MOVT_PREL; 124 break; 125 case ARM::fixup_arm_movw_lo16: 126 Type = ELF::R_ARM_MOVW_PREL_NC; 127 break; 128 case ARM::fixup_t2_movt_hi16: 129 Type = ELF::R_ARM_THM_MOVT_PREL; 130 break; 131 case ARM::fixup_t2_movw_lo16: 132 Type = ELF::R_ARM_THM_MOVW_PREL_NC; 133 break; 134 case ARM::fixup_arm_thumb_bl: 135 case ARM::fixup_arm_thumb_blx: 136 switch (Modifier) { 137 case MCSymbolRefExpr::VK_ARM_TLSCALL: 138 Type = ELF::R_ARM_THM_TLS_CALL; 139 break; 140 default: 141 Type = ELF::R_ARM_THM_CALL; 142 break; 143 } 144 break; 145 } 146 } else { 147 switch ((unsigned)Fixup.getKind()) { 148 default: llvm_unreachable("invalid fixup kind!"); 149 case FK_Data_4: 150 switch (Modifier) { 151 default: llvm_unreachable("Unsupported Modifier"); 152 case MCSymbolRefExpr::VK_ARM_NONE: 153 Type = ELF::R_ARM_NONE; 154 break; 155 case MCSymbolRefExpr::VK_GOT: 156 Type = ELF::R_ARM_GOT_BREL; 157 break; 158 case MCSymbolRefExpr::VK_TLSGD: 159 Type = ELF::R_ARM_TLS_GD32; 160 break; 161 case MCSymbolRefExpr::VK_TPOFF: 162 Type = ELF::R_ARM_TLS_LE32; 163 break; 164 case MCSymbolRefExpr::VK_GOTTPOFF: 165 Type = ELF::R_ARM_TLS_IE32; 166 break; 167 case MCSymbolRefExpr::VK_None: 168 Type = ELF::R_ARM_ABS32; 169 break; 170 case MCSymbolRefExpr::VK_GOTOFF: 171 Type = ELF::R_ARM_GOTOFF32; 172 break; 173 case MCSymbolRefExpr::VK_GOTPCREL: 174 Type = ELF::R_ARM_GOT_PREL; 175 break; 176 case MCSymbolRefExpr::VK_ARM_TARGET1: 177 Type = ELF::R_ARM_TARGET1; 178 break; 179 case MCSymbolRefExpr::VK_ARM_TARGET2: 180 Type = ELF::R_ARM_TARGET2; 181 break; 182 case MCSymbolRefExpr::VK_ARM_PREL31: 183 Type = ELF::R_ARM_PREL31; 184 break; 185 case MCSymbolRefExpr::VK_ARM_TLSLDO: 186 Type = ELF::R_ARM_TLS_LDO32; 187 break; 188 case MCSymbolRefExpr::VK_ARM_TLSCALL: 189 Type = ELF::R_ARM_TLS_CALL; 190 break; 191 case MCSymbolRefExpr::VK_ARM_TLSDESC: 192 Type = ELF::R_ARM_TLS_GOTDESC; 193 break; 194 case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ: 195 Type = ELF::R_ARM_TLS_DESCSEQ; 196 break; 197 } 198 break; 199 case ARM::fixup_arm_ldst_pcrel_12: 200 case ARM::fixup_arm_pcrel_10: 201 case ARM::fixup_arm_adr_pcrel_12: 202 case ARM::fixup_arm_thumb_bl: 203 case ARM::fixup_arm_thumb_cb: 204 case ARM::fixup_arm_thumb_cp: 205 case ARM::fixup_arm_thumb_br: 206 llvm_unreachable("Unimplemented"); 207 case ARM::fixup_arm_condbranch: 208 case ARM::fixup_arm_uncondbranch: 209 Type = ELF::R_ARM_JUMP24; 210 break; 211 case ARM::fixup_arm_movt_hi16: 212 Type = ELF::R_ARM_MOVT_ABS; 213 break; 214 case ARM::fixup_arm_movw_lo16: 215 Type = ELF::R_ARM_MOVW_ABS_NC; 216 break; 217 case ARM::fixup_t2_movt_hi16: 218 Type = ELF::R_ARM_THM_MOVT_ABS; 219 break; 220 case ARM::fixup_t2_movw_lo16: 221 Type = ELF::R_ARM_THM_MOVW_ABS_NC; 222 break; 223 } 224 } 225 226 return Type; 227} 228 229MCObjectWriter *llvm::createARMELFObjectWriter(raw_ostream &OS, 230 uint8_t OSABI, 231 bool IsLittleEndian) { 232 MCELFObjectTargetWriter *MOTW = new ARMELFObjectWriter(OSABI); 233 return createELFObjectWriter(MOTW, OS, IsLittleEndian); 234} 235