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