LLVM API Documentation
00001 //===-- ARMELFObjectWriter.cpp - ARM ELF Writer ---------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "MCTargetDesc/ARMMCTargetDesc.h" 00011 #include "MCTargetDesc/ARMFixupKinds.h" 00012 #include "llvm/ADT/Statistic.h" 00013 #include "llvm/ADT/StringSwitch.h" 00014 #include "llvm/MC/MCELFObjectWriter.h" 00015 #include "llvm/MC/MCExpr.h" 00016 #include "llvm/MC/MCSectionELF.h" 00017 #include "llvm/MC/MCValue.h" 00018 #include "llvm/Support/Debug.h" 00019 #include "llvm/Support/ErrorHandling.h" 00020 #include "llvm/Support/raw_ostream.h" 00021 00022 using namespace llvm; 00023 00024 namespace { 00025 class ARMELFObjectWriter : public MCELFObjectTargetWriter { 00026 enum { DefaultEABIVersion = 0x05000000U }; 00027 unsigned GetRelocTypeInner(const MCValue &Target, 00028 const MCFixup &Fixup, 00029 bool IsPCRel) const; 00030 00031 00032 public: 00033 ARMELFObjectWriter(uint8_t OSABI); 00034 00035 virtual ~ARMELFObjectWriter(); 00036 00037 unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 00038 bool IsPCRel) const override; 00039 00040 bool needsRelocateWithSymbol(const MCSymbolData &SD, 00041 unsigned Type) const override; 00042 }; 00043 } 00044 00045 ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI) 00046 : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, 00047 ELF::EM_ARM, 00048 /*HasRelocationAddend*/ false) {} 00049 00050 ARMELFObjectWriter::~ARMELFObjectWriter() {} 00051 00052 bool ARMELFObjectWriter::needsRelocateWithSymbol(const MCSymbolData &SD, 00053 unsigned Type) const { 00054 // FIXME: This is extremelly conservative. This really needs to use a 00055 // whitelist with a clear explanation for why each realocation needs to 00056 // point to the symbol, not to the section. 00057 switch (Type) { 00058 default: 00059 return true; 00060 00061 case ELF::R_ARM_PREL31: 00062 case ELF::R_ARM_ABS32: 00063 return false; 00064 } 00065 } 00066 00067 // Need to examine the Fixup when determining whether to 00068 // emit the relocation as an explicit symbol or as a section relative 00069 // offset 00070 unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target, 00071 const MCFixup &Fixup, 00072 bool IsPCRel) const { 00073 return GetRelocTypeInner(Target, Fixup, IsPCRel); 00074 } 00075 00076 unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, 00077 const MCFixup &Fixup, 00078 bool IsPCRel) const { 00079 MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); 00080 00081 unsigned Type = 0; 00082 if (IsPCRel) { 00083 switch ((unsigned)Fixup.getKind()) { 00084 default: llvm_unreachable("Unimplemented"); 00085 case FK_Data_4: 00086 switch (Modifier) { 00087 default: llvm_unreachable("Unsupported Modifier"); 00088 case MCSymbolRefExpr::VK_None: 00089 Type = ELF::R_ARM_REL32; 00090 break; 00091 case MCSymbolRefExpr::VK_TLSGD: 00092 llvm_unreachable("unimplemented"); 00093 case MCSymbolRefExpr::VK_GOTTPOFF: 00094 Type = ELF::R_ARM_TLS_IE32; 00095 break; 00096 case MCSymbolRefExpr::VK_GOTPCREL: 00097 Type = ELF::R_ARM_GOT_PREL; 00098 break; 00099 } 00100 break; 00101 case ARM::fixup_arm_blx: 00102 case ARM::fixup_arm_uncondbl: 00103 switch (Modifier) { 00104 case MCSymbolRefExpr::VK_PLT: 00105 Type = ELF::R_ARM_PLT32; 00106 break; 00107 case MCSymbolRefExpr::VK_ARM_TLSCALL: 00108 Type = ELF::R_ARM_TLS_CALL; 00109 break; 00110 default: 00111 Type = ELF::R_ARM_CALL; 00112 break; 00113 } 00114 break; 00115 case ARM::fixup_arm_condbl: 00116 case ARM::fixup_arm_condbranch: 00117 case ARM::fixup_arm_uncondbranch: 00118 Type = ELF::R_ARM_JUMP24; 00119 break; 00120 case ARM::fixup_t2_condbranch: 00121 case ARM::fixup_t2_uncondbranch: 00122 Type = ELF::R_ARM_THM_JUMP24; 00123 break; 00124 case ARM::fixup_arm_movt_hi16: 00125 Type = ELF::R_ARM_MOVT_PREL; 00126 break; 00127 case ARM::fixup_arm_movw_lo16: 00128 Type = ELF::R_ARM_MOVW_PREL_NC; 00129 break; 00130 case ARM::fixup_t2_movt_hi16: 00131 Type = ELF::R_ARM_THM_MOVT_PREL; 00132 break; 00133 case ARM::fixup_t2_movw_lo16: 00134 Type = ELF::R_ARM_THM_MOVW_PREL_NC; 00135 break; 00136 case ARM::fixup_arm_thumb_bl: 00137 case ARM::fixup_arm_thumb_blx: 00138 switch (Modifier) { 00139 case MCSymbolRefExpr::VK_ARM_TLSCALL: 00140 Type = ELF::R_ARM_THM_TLS_CALL; 00141 break; 00142 default: 00143 Type = ELF::R_ARM_THM_CALL; 00144 break; 00145 } 00146 break; 00147 } 00148 } else { 00149 switch ((unsigned)Fixup.getKind()) { 00150 default: llvm_unreachable("invalid fixup kind!"); 00151 case FK_Data_4: 00152 switch (Modifier) { 00153 default: llvm_unreachable("Unsupported Modifier"); 00154 case MCSymbolRefExpr::VK_ARM_NONE: 00155 Type = ELF::R_ARM_NONE; 00156 break; 00157 case MCSymbolRefExpr::VK_GOT: 00158 Type = ELF::R_ARM_GOT_BREL; 00159 break; 00160 case MCSymbolRefExpr::VK_TLSGD: 00161 Type = ELF::R_ARM_TLS_GD32; 00162 break; 00163 case MCSymbolRefExpr::VK_TPOFF: 00164 Type = ELF::R_ARM_TLS_LE32; 00165 break; 00166 case MCSymbolRefExpr::VK_GOTTPOFF: 00167 Type = ELF::R_ARM_TLS_IE32; 00168 break; 00169 case MCSymbolRefExpr::VK_None: 00170 Type = ELF::R_ARM_ABS32; 00171 break; 00172 case MCSymbolRefExpr::VK_GOTOFF: 00173 Type = ELF::R_ARM_GOTOFF32; 00174 break; 00175 case MCSymbolRefExpr::VK_GOTPCREL: 00176 Type = ELF::R_ARM_GOT_PREL; 00177 break; 00178 case MCSymbolRefExpr::VK_ARM_TARGET1: 00179 Type = ELF::R_ARM_TARGET1; 00180 break; 00181 case MCSymbolRefExpr::VK_ARM_TARGET2: 00182 Type = ELF::R_ARM_TARGET2; 00183 break; 00184 case MCSymbolRefExpr::VK_ARM_PREL31: 00185 Type = ELF::R_ARM_PREL31; 00186 break; 00187 case MCSymbolRefExpr::VK_ARM_TLSLDO: 00188 Type = ELF::R_ARM_TLS_LDO32; 00189 break; 00190 case MCSymbolRefExpr::VK_ARM_TLSCALL: 00191 Type = ELF::R_ARM_TLS_CALL; 00192 break; 00193 case MCSymbolRefExpr::VK_ARM_TLSDESC: 00194 Type = ELF::R_ARM_TLS_GOTDESC; 00195 break; 00196 case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ: 00197 Type = ELF::R_ARM_TLS_DESCSEQ; 00198 break; 00199 } 00200 break; 00201 case ARM::fixup_arm_ldst_pcrel_12: 00202 case ARM::fixup_arm_pcrel_10: 00203 case ARM::fixup_arm_adr_pcrel_12: 00204 case ARM::fixup_arm_thumb_bl: 00205 case ARM::fixup_arm_thumb_cb: 00206 case ARM::fixup_arm_thumb_cp: 00207 case ARM::fixup_arm_thumb_br: 00208 llvm_unreachable("Unimplemented"); 00209 case ARM::fixup_arm_condbranch: 00210 case ARM::fixup_arm_uncondbranch: 00211 Type = ELF::R_ARM_JUMP24; 00212 break; 00213 case ARM::fixup_arm_movt_hi16: 00214 Type = ELF::R_ARM_MOVT_ABS; 00215 break; 00216 case ARM::fixup_arm_movw_lo16: 00217 Type = ELF::R_ARM_MOVW_ABS_NC; 00218 break; 00219 case ARM::fixup_t2_movt_hi16: 00220 Type = ELF::R_ARM_THM_MOVT_ABS; 00221 break; 00222 case ARM::fixup_t2_movw_lo16: 00223 Type = ELF::R_ARM_THM_MOVW_ABS_NC; 00224 break; 00225 } 00226 } 00227 00228 return Type; 00229 } 00230 00231 MCObjectWriter *llvm::createARMELFObjectWriter(raw_ostream &OS, 00232 uint8_t OSABI, 00233 bool IsLittleEndian) { 00234 MCELFObjectTargetWriter *MOTW = new ARMELFObjectWriter(OSABI); 00235 return createELFObjectWriter(MOTW, OS, IsLittleEndian); 00236 }