1 //===-- AArch64ELFObjectWriter.cpp - AArch64 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 // This file handles ELF-specific object emission, converting LLVM's internal 11 // fixups into the appropriate relocations. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "MCTargetDesc/AArch64FixupKinds.h" 16 #include "MCTargetDesc/AArch64MCExpr.h" 17 #include "MCTargetDesc/AArch64MCTargetDesc.h" 18 #include "llvm/MC/MCELFObjectWriter.h" 19 #include "llvm/MC/MCValue.h" 20 #include "llvm/Support/ErrorHandling.h" 21 22 using namespace llvm; 23 24 namespace { 25 class AArch64ELFObjectWriter : public MCELFObjectTargetWriter { 26 public: 27 AArch64ELFObjectWriter(uint8_t OSABI, bool IsLittleEndian); 28 29 ~AArch64ELFObjectWriter() override; 30 31 protected: 32 unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 33 bool IsPCRel) const override; 34 35 private: 36 }; 37 } 38 39 AArch64ELFObjectWriter::AArch64ELFObjectWriter(uint8_t OSABI, 40 bool IsLittleEndian) 41 : MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_AARCH64, 42 /*HasRelocationAddend*/ true) {} 43 44 AArch64ELFObjectWriter::~AArch64ELFObjectWriter() {} 45 46 unsigned AArch64ELFObjectWriter::GetRelocType(const MCValue &Target, 47 const MCFixup &Fixup, 48 bool IsPCRel) const { 49 AArch64MCExpr::VariantKind RefKind = 50 static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind()); 51 AArch64MCExpr::VariantKind SymLoc = AArch64MCExpr::getSymbolLoc(RefKind); 52 bool IsNC = AArch64MCExpr::isNotChecked(RefKind); 53 54 assert((!Target.getSymA() || 55 Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None) && 56 "Should only be expression-level modifiers here"); 57 58 assert((!Target.getSymB() || 59 Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None) && 60 "Should only be expression-level modifiers here"); 61 62 if (IsPCRel) { 63 switch ((unsigned)Fixup.getKind()) { 64 case FK_Data_2: 65 return ELF::R_AARCH64_PREL16; 66 case FK_Data_4: 67 return ELF::R_AARCH64_PREL32; 68 case FK_Data_8: 69 return ELF::R_AARCH64_PREL64; 70 case AArch64::fixup_aarch64_pcrel_adr_imm21: 71 assert(SymLoc == AArch64MCExpr::VK_NONE && "unexpected ADR relocation"); 72 return ELF::R_AARCH64_ADR_PREL_LO21; 73 case AArch64::fixup_aarch64_pcrel_adrp_imm21: 74 if (SymLoc == AArch64MCExpr::VK_ABS && !IsNC) 75 return ELF::R_AARCH64_ADR_PREL_PG_HI21; 76 if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC) 77 return ELF::R_AARCH64_ADR_GOT_PAGE; 78 if (SymLoc == AArch64MCExpr::VK_GOTTPREL && !IsNC) 79 return ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21; 80 if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC) 81 return ELF::R_AARCH64_TLSDESC_ADR_PAGE21; 82 llvm_unreachable("invalid symbol kind for ADRP relocation"); 83 case AArch64::fixup_aarch64_pcrel_branch26: 84 return ELF::R_AARCH64_JUMP26; 85 case AArch64::fixup_aarch64_pcrel_call26: 86 return ELF::R_AARCH64_CALL26; 87 case AArch64::fixup_aarch64_ldr_pcrel_imm19: 88 if (SymLoc == AArch64MCExpr::VK_GOTTPREL) 89 return ELF::R_AARCH64_TLSIE_LD_GOTTPREL_PREL19; 90 return ELF::R_AARCH64_LD_PREL_LO19; 91 case AArch64::fixup_aarch64_pcrel_branch14: 92 return ELF::R_AARCH64_TSTBR14; 93 case AArch64::fixup_aarch64_pcrel_branch19: 94 return ELF::R_AARCH64_CONDBR19; 95 default: 96 llvm_unreachable("Unsupported pc-relative fixup kind"); 97 } 98 } else { 99 switch ((unsigned)Fixup.getKind()) { 100 case FK_Data_2: 101 return ELF::R_AARCH64_ABS16; 102 case FK_Data_4: 103 return ELF::R_AARCH64_ABS32; 104 case FK_Data_8: 105 return ELF::R_AARCH64_ABS64; 106 case AArch64::fixup_aarch64_add_imm12: 107 if (RefKind == AArch64MCExpr::VK_DTPREL_HI12) 108 return ELF::R_AARCH64_TLSLD_ADD_DTPREL_HI12; 109 if (RefKind == AArch64MCExpr::VK_TPREL_HI12) 110 return ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12; 111 if (RefKind == AArch64MCExpr::VK_DTPREL_LO12_NC) 112 return ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC; 113 if (RefKind == AArch64MCExpr::VK_DTPREL_LO12) 114 return ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12; 115 if (RefKind == AArch64MCExpr::VK_TPREL_LO12_NC) 116 return ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC; 117 if (RefKind == AArch64MCExpr::VK_TPREL_LO12) 118 return ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12; 119 if (RefKind == AArch64MCExpr::VK_TLSDESC_LO12) 120 return ELF::R_AARCH64_TLSDESC_ADD_LO12_NC; 121 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) 122 return ELF::R_AARCH64_ADD_ABS_LO12_NC; 123 124 report_fatal_error("invalid fixup for add (uimm12) instruction"); 125 return 0; 126 case AArch64::fixup_aarch64_ldst_imm12_scale1: 127 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) 128 return ELF::R_AARCH64_LDST8_ABS_LO12_NC; 129 if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC) 130 return ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12; 131 if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC) 132 return ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC; 133 if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC) 134 return ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12; 135 if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC) 136 return ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC; 137 138 report_fatal_error("invalid fixup for 8-bit load/store instruction"); 139 return 0; 140 case AArch64::fixup_aarch64_ldst_imm12_scale2: 141 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) 142 return ELF::R_AARCH64_LDST16_ABS_LO12_NC; 143 if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC) 144 return ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12; 145 if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC) 146 return ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC; 147 if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC) 148 return ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12; 149 if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC) 150 return ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC; 151 152 report_fatal_error("invalid fixup for 16-bit load/store instruction"); 153 return 0; 154 case AArch64::fixup_aarch64_ldst_imm12_scale4: 155 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) 156 return ELF::R_AARCH64_LDST32_ABS_LO12_NC; 157 if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC) 158 return ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12; 159 if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC) 160 return ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC; 161 if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC) 162 return ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12; 163 if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC) 164 return ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC; 165 166 report_fatal_error("invalid fixup for 32-bit load/store instruction"); 167 return 0; 168 case AArch64::fixup_aarch64_ldst_imm12_scale8: 169 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) 170 return ELF::R_AARCH64_LDST64_ABS_LO12_NC; 171 if (SymLoc == AArch64MCExpr::VK_GOT && IsNC) 172 return ELF::R_AARCH64_LD64_GOT_LO12_NC; 173 if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC) 174 return ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12; 175 if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC) 176 return ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC; 177 if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC) 178 return ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12; 179 if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC) 180 return ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC; 181 if (SymLoc == AArch64MCExpr::VK_GOTTPREL && IsNC) 182 return ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC; 183 if (SymLoc == AArch64MCExpr::VK_TLSDESC && IsNC) 184 return ELF::R_AARCH64_TLSDESC_LD64_LO12_NC; 185 186 report_fatal_error("invalid fixup for 64-bit load/store instruction"); 187 return 0; 188 case AArch64::fixup_aarch64_ldst_imm12_scale16: 189 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) 190 return ELF::R_AARCH64_LDST128_ABS_LO12_NC; 191 192 report_fatal_error("invalid fixup for 128-bit load/store instruction"); 193 return 0; 194 case AArch64::fixup_aarch64_movw: 195 if (RefKind == AArch64MCExpr::VK_ABS_G3) 196 return ELF::R_AARCH64_MOVW_UABS_G3; 197 if (RefKind == AArch64MCExpr::VK_ABS_G2) 198 return ELF::R_AARCH64_MOVW_UABS_G2; 199 if (RefKind == AArch64MCExpr::VK_ABS_G2_S) 200 return ELF::R_AARCH64_MOVW_SABS_G2; 201 if (RefKind == AArch64MCExpr::VK_ABS_G2_NC) 202 return ELF::R_AARCH64_MOVW_UABS_G2_NC; 203 if (RefKind == AArch64MCExpr::VK_ABS_G1) 204 return ELF::R_AARCH64_MOVW_UABS_G1; 205 if (RefKind == AArch64MCExpr::VK_ABS_G1_S) 206 return ELF::R_AARCH64_MOVW_SABS_G1; 207 if (RefKind == AArch64MCExpr::VK_ABS_G1_NC) 208 return ELF::R_AARCH64_MOVW_UABS_G1_NC; 209 if (RefKind == AArch64MCExpr::VK_ABS_G0) 210 return ELF::R_AARCH64_MOVW_UABS_G0; 211 if (RefKind == AArch64MCExpr::VK_ABS_G0_S) 212 return ELF::R_AARCH64_MOVW_SABS_G0; 213 if (RefKind == AArch64MCExpr::VK_ABS_G0_NC) 214 return ELF::R_AARCH64_MOVW_UABS_G0_NC; 215 if (RefKind == AArch64MCExpr::VK_DTPREL_G2) 216 return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G2; 217 if (RefKind == AArch64MCExpr::VK_DTPREL_G1) 218 return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1; 219 if (RefKind == AArch64MCExpr::VK_DTPREL_G1_NC) 220 return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC; 221 if (RefKind == AArch64MCExpr::VK_DTPREL_G0) 222 return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0; 223 if (RefKind == AArch64MCExpr::VK_DTPREL_G0_NC) 224 return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC; 225 if (RefKind == AArch64MCExpr::VK_TPREL_G2) 226 return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G2; 227 if (RefKind == AArch64MCExpr::VK_TPREL_G1) 228 return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1; 229 if (RefKind == AArch64MCExpr::VK_TPREL_G1_NC) 230 return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC; 231 if (RefKind == AArch64MCExpr::VK_TPREL_G0) 232 return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0; 233 if (RefKind == AArch64MCExpr::VK_TPREL_G0_NC) 234 return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC; 235 if (RefKind == AArch64MCExpr::VK_GOTTPREL_G1) 236 return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G1; 237 if (RefKind == AArch64MCExpr::VK_GOTTPREL_G0_NC) 238 return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC; 239 report_fatal_error("invalid fixup for movz/movk instruction"); 240 return 0; 241 case AArch64::fixup_aarch64_tlsdesc_call: 242 return ELF::R_AARCH64_TLSDESC_CALL; 243 default: 244 llvm_unreachable("Unknown ELF relocation type"); 245 } 246 } 247 248 llvm_unreachable("Unimplemented fixup -> relocation"); 249 } 250 251 MCObjectWriter *llvm::createAArch64ELFObjectWriter(raw_pwrite_stream &OS, 252 uint8_t OSABI, 253 bool IsLittleEndian) { 254 MCELFObjectTargetWriter *MOTW = 255 new AArch64ELFObjectWriter(OSABI, IsLittleEndian); 256 return createELFObjectWriter(MOTW, OS, IsLittleEndian); 257 } 258