LLVM API Documentation
00001 //===-- AArch64ELFObjectWriter.cpp - AArch64 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 // This file handles ELF-specific object emission, converting LLVM's internal 00011 // fixups into the appropriate relocations. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "MCTargetDesc/AArch64FixupKinds.h" 00016 #include "MCTargetDesc/AArch64MCExpr.h" 00017 #include "MCTargetDesc/AArch64MCTargetDesc.h" 00018 #include "llvm/MC/MCELFObjectWriter.h" 00019 #include "llvm/MC/MCValue.h" 00020 #include "llvm/Support/ErrorHandling.h" 00021 00022 using namespace llvm; 00023 00024 namespace { 00025 class AArch64ELFObjectWriter : public MCELFObjectTargetWriter { 00026 public: 00027 AArch64ELFObjectWriter(uint8_t OSABI, bool IsLittleEndian); 00028 00029 virtual ~AArch64ELFObjectWriter(); 00030 00031 protected: 00032 unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 00033 bool IsPCRel) const override; 00034 00035 private: 00036 }; 00037 } 00038 00039 AArch64ELFObjectWriter::AArch64ELFObjectWriter(uint8_t OSABI, 00040 bool IsLittleEndian) 00041 : MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_AARCH64, 00042 /*HasRelocationAddend*/ true) {} 00043 00044 AArch64ELFObjectWriter::~AArch64ELFObjectWriter() {} 00045 00046 unsigned AArch64ELFObjectWriter::GetRelocType(const MCValue &Target, 00047 const MCFixup &Fixup, 00048 bool IsPCRel) const { 00049 AArch64MCExpr::VariantKind RefKind = 00050 static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind()); 00051 AArch64MCExpr::VariantKind SymLoc = AArch64MCExpr::getSymbolLoc(RefKind); 00052 bool IsNC = AArch64MCExpr::isNotChecked(RefKind); 00053 00054 assert((!Target.getSymA() || 00055 Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None) && 00056 "Should only be expression-level modifiers here"); 00057 00058 assert((!Target.getSymB() || 00059 Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None) && 00060 "Should only be expression-level modifiers here"); 00061 00062 if (IsPCRel) { 00063 switch ((unsigned)Fixup.getKind()) { 00064 case FK_Data_2: 00065 return ELF::R_AARCH64_PREL16; 00066 case FK_Data_4: 00067 return ELF::R_AARCH64_PREL32; 00068 case FK_Data_8: 00069 return ELF::R_AARCH64_PREL64; 00070 case AArch64::fixup_aarch64_pcrel_adr_imm21: 00071 assert(SymLoc == AArch64MCExpr::VK_NONE && "unexpected ADR relocation"); 00072 return ELF::R_AARCH64_ADR_PREL_LO21; 00073 case AArch64::fixup_aarch64_pcrel_adrp_imm21: 00074 if (SymLoc == AArch64MCExpr::VK_ABS && !IsNC) 00075 return ELF::R_AARCH64_ADR_PREL_PG_HI21; 00076 if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC) 00077 return ELF::R_AARCH64_ADR_GOT_PAGE; 00078 if (SymLoc == AArch64MCExpr::VK_GOTTPREL && !IsNC) 00079 return ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21; 00080 if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC) 00081 return ELF::R_AARCH64_TLSDESC_ADR_PAGE; 00082 llvm_unreachable("invalid symbol kind for ADRP relocation"); 00083 case AArch64::fixup_aarch64_pcrel_branch26: 00084 return ELF::R_AARCH64_JUMP26; 00085 case AArch64::fixup_aarch64_pcrel_call26: 00086 return ELF::R_AARCH64_CALL26; 00087 case AArch64::fixup_aarch64_ldr_pcrel_imm19: 00088 if (SymLoc == AArch64MCExpr::VK_GOTTPREL) 00089 return ELF::R_AARCH64_TLSIE_LD_GOTTPREL_PREL19; 00090 return ELF::R_AARCH64_LD_PREL_LO19; 00091 case AArch64::fixup_aarch64_pcrel_branch14: 00092 return ELF::R_AARCH64_TSTBR14; 00093 case AArch64::fixup_aarch64_pcrel_branch19: 00094 return ELF::R_AARCH64_CONDBR19; 00095 default: 00096 llvm_unreachable("Unsupported pc-relative fixup kind"); 00097 } 00098 } else { 00099 switch ((unsigned)Fixup.getKind()) { 00100 case FK_Data_2: 00101 return ELF::R_AARCH64_ABS16; 00102 case FK_Data_4: 00103 return ELF::R_AARCH64_ABS32; 00104 case FK_Data_8: 00105 return ELF::R_AARCH64_ABS64; 00106 case AArch64::fixup_aarch64_add_imm12: 00107 if (RefKind == AArch64MCExpr::VK_DTPREL_HI12) 00108 return ELF::R_AARCH64_TLSLD_ADD_DTPREL_HI12; 00109 if (RefKind == AArch64MCExpr::VK_TPREL_HI12) 00110 return ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12; 00111 if (RefKind == AArch64MCExpr::VK_DTPREL_LO12_NC) 00112 return ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC; 00113 if (RefKind == AArch64MCExpr::VK_DTPREL_LO12) 00114 return ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12; 00115 if (RefKind == AArch64MCExpr::VK_TPREL_LO12_NC) 00116 return ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC; 00117 if (RefKind == AArch64MCExpr::VK_TPREL_LO12) 00118 return ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12; 00119 if (RefKind == AArch64MCExpr::VK_TLSDESC_LO12) 00120 return ELF::R_AARCH64_TLSDESC_ADD_LO12_NC; 00121 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) 00122 return ELF::R_AARCH64_ADD_ABS_LO12_NC; 00123 00124 report_fatal_error("invalid fixup for add (uimm12) instruction"); 00125 return 0; 00126 case AArch64::fixup_aarch64_ldst_imm12_scale1: 00127 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) 00128 return ELF::R_AARCH64_LDST8_ABS_LO12_NC; 00129 if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC) 00130 return ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12; 00131 if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC) 00132 return ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC; 00133 if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC) 00134 return ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12; 00135 if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC) 00136 return ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC; 00137 00138 report_fatal_error("invalid fixup for 8-bit load/store instruction"); 00139 return 0; 00140 case AArch64::fixup_aarch64_ldst_imm12_scale2: 00141 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) 00142 return ELF::R_AARCH64_LDST16_ABS_LO12_NC; 00143 if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC) 00144 return ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12; 00145 if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC) 00146 return ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC; 00147 if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC) 00148 return ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12; 00149 if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC) 00150 return ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC; 00151 00152 report_fatal_error("invalid fixup for 16-bit load/store instruction"); 00153 return 0; 00154 case AArch64::fixup_aarch64_ldst_imm12_scale4: 00155 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) 00156 return ELF::R_AARCH64_LDST32_ABS_LO12_NC; 00157 if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC) 00158 return ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12; 00159 if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC) 00160 return ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC; 00161 if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC) 00162 return ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12; 00163 if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC) 00164 return ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC; 00165 00166 report_fatal_error("invalid fixup for 32-bit load/store instruction"); 00167 return 0; 00168 case AArch64::fixup_aarch64_ldst_imm12_scale8: 00169 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) 00170 return ELF::R_AARCH64_LDST64_ABS_LO12_NC; 00171 if (SymLoc == AArch64MCExpr::VK_GOT && IsNC) 00172 return ELF::R_AARCH64_LD64_GOT_LO12_NC; 00173 if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC) 00174 return ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12; 00175 if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC) 00176 return ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC; 00177 if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC) 00178 return ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12; 00179 if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC) 00180 return ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC; 00181 if (SymLoc == AArch64MCExpr::VK_GOTTPREL && IsNC) 00182 return ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC; 00183 if (SymLoc == AArch64MCExpr::VK_TLSDESC && IsNC) 00184 return ELF::R_AARCH64_TLSDESC_LD64_LO12_NC; 00185 00186 report_fatal_error("invalid fixup for 64-bit load/store instruction"); 00187 return 0; 00188 case AArch64::fixup_aarch64_ldst_imm12_scale16: 00189 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) 00190 return ELF::R_AARCH64_LDST128_ABS_LO12_NC; 00191 00192 report_fatal_error("invalid fixup for 128-bit load/store instruction"); 00193 return 0; 00194 case AArch64::fixup_aarch64_movw: 00195 if (RefKind == AArch64MCExpr::VK_ABS_G3) 00196 return ELF::R_AARCH64_MOVW_UABS_G3; 00197 if (RefKind == AArch64MCExpr::VK_ABS_G2) 00198 return ELF::R_AARCH64_MOVW_UABS_G2; 00199 if (RefKind == AArch64MCExpr::VK_ABS_G2_S) 00200 return ELF::R_AARCH64_MOVW_SABS_G2; 00201 if (RefKind == AArch64MCExpr::VK_ABS_G2_NC) 00202 return ELF::R_AARCH64_MOVW_UABS_G2_NC; 00203 if (RefKind == AArch64MCExpr::VK_ABS_G1) 00204 return ELF::R_AARCH64_MOVW_UABS_G1; 00205 if (RefKind == AArch64MCExpr::VK_ABS_G1_S) 00206 return ELF::R_AARCH64_MOVW_SABS_G1; 00207 if (RefKind == AArch64MCExpr::VK_ABS_G1_NC) 00208 return ELF::R_AARCH64_MOVW_UABS_G1_NC; 00209 if (RefKind == AArch64MCExpr::VK_ABS_G0) 00210 return ELF::R_AARCH64_MOVW_UABS_G0; 00211 if (RefKind == AArch64MCExpr::VK_ABS_G0_S) 00212 return ELF::R_AARCH64_MOVW_SABS_G0; 00213 if (RefKind == AArch64MCExpr::VK_ABS_G0_NC) 00214 return ELF::R_AARCH64_MOVW_UABS_G0_NC; 00215 if (RefKind == AArch64MCExpr::VK_DTPREL_G2) 00216 return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G2; 00217 if (RefKind == AArch64MCExpr::VK_DTPREL_G1) 00218 return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1; 00219 if (RefKind == AArch64MCExpr::VK_DTPREL_G1_NC) 00220 return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC; 00221 if (RefKind == AArch64MCExpr::VK_DTPREL_G0) 00222 return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0; 00223 if (RefKind == AArch64MCExpr::VK_DTPREL_G0_NC) 00224 return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC; 00225 if (RefKind == AArch64MCExpr::VK_TPREL_G2) 00226 return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G2; 00227 if (RefKind == AArch64MCExpr::VK_TPREL_G1) 00228 return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1; 00229 if (RefKind == AArch64MCExpr::VK_TPREL_G1_NC) 00230 return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC; 00231 if (RefKind == AArch64MCExpr::VK_TPREL_G0) 00232 return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0; 00233 if (RefKind == AArch64MCExpr::VK_TPREL_G0_NC) 00234 return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC; 00235 if (RefKind == AArch64MCExpr::VK_GOTTPREL_G1) 00236 return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G1; 00237 if (RefKind == AArch64MCExpr::VK_GOTTPREL_G0_NC) 00238 return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC; 00239 report_fatal_error("invalid fixup for movz/movk instruction"); 00240 return 0; 00241 case AArch64::fixup_aarch64_tlsdesc_call: 00242 return ELF::R_AARCH64_TLSDESC_CALL; 00243 default: 00244 llvm_unreachable("Unknown ELF relocation type"); 00245 } 00246 } 00247 00248 llvm_unreachable("Unimplemented fixup -> relocation"); 00249 } 00250 00251 MCObjectWriter *llvm::createAArch64ELFObjectWriter(raw_ostream &OS, 00252 uint8_t OSABI, 00253 bool IsLittleEndian) { 00254 MCELFObjectTargetWriter *MOTW = 00255 new AArch64ELFObjectWriter(OSABI, IsLittleEndian); 00256 return createELFObjectWriter(MOTW, OS, IsLittleEndian); 00257 }