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