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