12f09f445SMaksim Panchenko //===- bolt/Core/Relocation.cpp - Object file relocations -----------------===// 2a34c753fSRafael Auler // 3a34c753fSRafael Auler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a34c753fSRafael Auler // See https://llvm.org/LICENSE.txt for license information. 5a34c753fSRafael Auler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a34c753fSRafael Auler // 7a34c753fSRafael Auler //===----------------------------------------------------------------------===// 8a34c753fSRafael Auler // 92f09f445SMaksim Panchenko // This file implements the Relocation class. 102f09f445SMaksim Panchenko // 11a34c753fSRafael Auler //===----------------------------------------------------------------------===// 12a34c753fSRafael Auler 13a34c753fSRafael Auler #include "bolt/Core/Relocation.h" 14a34c753fSRafael Auler #include "llvm/MC/MCContext.h" 1557f7c7d9Sserge-sans-paille #include "llvm/MC/MCExpr.h" 16a34c753fSRafael Auler #include "llvm/MC/MCStreamer.h" 1757f7c7d9Sserge-sans-paille #include "llvm/MC/MCSymbol.h" 18eb9f4eb6SAmir Ayupov #include "llvm/Object/ELF.h" 19a34c753fSRafael Auler 20a34c753fSRafael Auler using namespace llvm; 21a34c753fSRafael Auler using namespace bolt; 22a34c753fSRafael Auler 23c7d6d622SJob Noorman namespace ELFReserved { 24c7d6d622SJob Noorman enum { 25c7d6d622SJob Noorman R_RISCV_TPREL_I = 49, 26c7d6d622SJob Noorman R_RISCV_TPREL_S = 50, 27c7d6d622SJob Noorman }; 28c7d6d622SJob Noorman } // namespace ELFReserved 29c7d6d622SJob Noorman 30a34c753fSRafael Auler Triple::ArchType Relocation::Arch; 31a34c753fSRafael Auler 32be2f67c4SAmir Ayupov static bool isSupportedX86(uint64_t Type) { 33a34c753fSRafael Auler switch (Type) { 34a34c753fSRafael Auler default: 35a34c753fSRafael Auler return false; 36a34c753fSRafael Auler case ELF::R_X86_64_8: 37a34c753fSRafael Auler case ELF::R_X86_64_16: 38a34c753fSRafael Auler case ELF::R_X86_64_32: 39a34c753fSRafael Auler case ELF::R_X86_64_32S: 40a34c753fSRafael Auler case ELF::R_X86_64_64: 41a34c753fSRafael Auler case ELF::R_X86_64_PC8: 42a34c753fSRafael Auler case ELF::R_X86_64_PC32: 43a34c753fSRafael Auler case ELF::R_X86_64_PC64: 44a34c753fSRafael Auler case ELF::R_X86_64_PLT32: 45853e126cSRafael Auler case ELF::R_X86_64_GOTPC64: 46a34c753fSRafael Auler case ELF::R_X86_64_GOTPCREL: 47a34c753fSRafael Auler case ELF::R_X86_64_GOTTPOFF: 48a34c753fSRafael Auler case ELF::R_X86_64_TPOFF32: 49a34c753fSRafael Auler case ELF::R_X86_64_GOTPCRELX: 50a34c753fSRafael Auler case ELF::R_X86_64_REX_GOTPCRELX: 51a34c753fSRafael Auler return true; 52a34c753fSRafael Auler } 53a34c753fSRafael Auler } 54a34c753fSRafael Auler 55be2f67c4SAmir Ayupov static bool isSupportedAArch64(uint64_t Type) { 56a34c753fSRafael Auler switch (Type) { 57a34c753fSRafael Auler default: 58a34c753fSRafael Auler return false; 59a34c753fSRafael Auler case ELF::R_AARCH64_CALL26: 60a34c753fSRafael Auler case ELF::R_AARCH64_JUMP26: 61a34c753fSRafael Auler case ELF::R_AARCH64_TSTBR14: 62a34c753fSRafael Auler case ELF::R_AARCH64_CONDBR19: 63a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_LO21: 64a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_PG_HI21: 65a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC: 66a34c753fSRafael Auler case ELF::R_AARCH64_LDST64_ABS_LO12_NC: 67a34c753fSRafael Auler case ELF::R_AARCH64_ADD_ABS_LO12_NC: 68a34c753fSRafael Auler case ELF::R_AARCH64_LDST128_ABS_LO12_NC: 69a34c753fSRafael Auler case ELF::R_AARCH64_LDST32_ABS_LO12_NC: 70a34c753fSRafael Auler case ELF::R_AARCH64_LDST16_ABS_LO12_NC: 71a34c753fSRafael Auler case ELF::R_AARCH64_LDST8_ABS_LO12_NC: 72a34c753fSRafael Auler case ELF::R_AARCH64_ADR_GOT_PAGE: 73a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PREL21: 74a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: 75a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 76a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: 77a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: 78*e11d49cbSAlexey Moksyakov case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0: 79*e11d49cbSAlexey Moksyakov case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: 80a34c753fSRafael Auler case ELF::R_AARCH64_LD64_GOT_LO12_NC: 81a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_LD64_LO12: 82a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADD_LO12: 83a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_CALL: 84a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: 8548e894a5SAlexey Moksyakov case ELF::R_AARCH64_PREL16: 86a34c753fSRafael Auler case ELF::R_AARCH64_PREL32: 8748e894a5SAlexey Moksyakov case ELF::R_AARCH64_PREL64: 88172deb75SVladislav Khmelevsky case ELF::R_AARCH64_ABS16: 89172deb75SVladislav Khmelevsky case ELF::R_AARCH64_ABS32: 90a34c753fSRafael Auler case ELF::R_AARCH64_ABS64: 91a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G0: 92a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G0_NC: 93a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G1: 94a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G1_NC: 95a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G2: 96a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G2_NC: 97a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G3: 98a34c753fSRafael Auler return true; 99a34c753fSRafael Auler } 100a34c753fSRafael Auler } 101a34c753fSRafael Auler 102f8730293SJob Noorman static bool isSupportedRISCV(uint64_t Type) { 103f8730293SJob Noorman switch (Type) { 104f8730293SJob Noorman default: 105f8730293SJob Noorman return false; 106f8730293SJob Noorman case ELF::R_RISCV_JAL: 107f8730293SJob Noorman case ELF::R_RISCV_CALL: 108f8730293SJob Noorman case ELF::R_RISCV_CALL_PLT: 109f8730293SJob Noorman case ELF::R_RISCV_BRANCH: 110f8730293SJob Noorman case ELF::R_RISCV_RELAX: 111f8730293SJob Noorman case ELF::R_RISCV_GOT_HI20: 112f8730293SJob Noorman case ELF::R_RISCV_PCREL_HI20: 113f8730293SJob Noorman case ELF::R_RISCV_PCREL_LO12_I: 1141b78742eSJob Noorman case ELF::R_RISCV_PCREL_LO12_S: 115f8730293SJob Noorman case ELF::R_RISCV_RVC_JUMP: 116f8730293SJob Noorman case ELF::R_RISCV_RVC_BRANCH: 117b410d24aSJob Noorman case ELF::R_RISCV_ADD32: 118b410d24aSJob Noorman case ELF::R_RISCV_SUB32: 1199555736aSJob Noorman case ELF::R_RISCV_HI20: 1209555736aSJob Noorman case ELF::R_RISCV_LO12_I: 1219555736aSJob Noorman case ELF::R_RISCV_LO12_S: 122cd7f1714SJob Noorman case ELF::R_RISCV_64: 123c7d6d622SJob Noorman case ELF::R_RISCV_TLS_GOT_HI20: 124c7d6d622SJob Noorman case ELF::R_RISCV_TPREL_HI20: 125c7d6d622SJob Noorman case ELF::R_RISCV_TPREL_ADD: 126c7d6d622SJob Noorman case ELF::R_RISCV_TPREL_LO12_I: 127c7d6d622SJob Noorman case ELF::R_RISCV_TPREL_LO12_S: 128c7d6d622SJob Noorman case ELFReserved::R_RISCV_TPREL_I: 129c7d6d622SJob Noorman case ELFReserved::R_RISCV_TPREL_S: 130f8730293SJob Noorman return true; 131f8730293SJob Noorman } 132f8730293SJob Noorman } 133f8730293SJob Noorman 134be2f67c4SAmir Ayupov static size_t getSizeForTypeX86(uint64_t Type) { 135a34c753fSRafael Auler switch (Type) { 136a34c753fSRafael Auler default: 137eb9f4eb6SAmir Ayupov errs() << object::getELFRelocationTypeName(ELF::EM_X86_64, Type) << '\n'; 138a34c753fSRafael Auler llvm_unreachable("unsupported relocation type"); 139a34c753fSRafael Auler case ELF::R_X86_64_8: 140a34c753fSRafael Auler case ELF::R_X86_64_PC8: 141a34c753fSRafael Auler return 1; 142a34c753fSRafael Auler case ELF::R_X86_64_16: 143a34c753fSRafael Auler return 2; 144a34c753fSRafael Auler case ELF::R_X86_64_PLT32: 145a34c753fSRafael Auler case ELF::R_X86_64_PC32: 146a34c753fSRafael Auler case ELF::R_X86_64_32S: 147a34c753fSRafael Auler case ELF::R_X86_64_32: 148a34c753fSRafael Auler case ELF::R_X86_64_GOTPCREL: 149a34c753fSRafael Auler case ELF::R_X86_64_GOTTPOFF: 150a34c753fSRafael Auler case ELF::R_X86_64_TPOFF32: 151a34c753fSRafael Auler case ELF::R_X86_64_GOTPCRELX: 152a34c753fSRafael Auler case ELF::R_X86_64_REX_GOTPCRELX: 153a34c753fSRafael Auler return 4; 154a34c753fSRafael Auler case ELF::R_X86_64_PC64: 155a34c753fSRafael Auler case ELF::R_X86_64_64: 156853e126cSRafael Auler case ELF::R_X86_64_GOTPC64: 157a34c753fSRafael Auler return 8; 158a34c753fSRafael Auler } 159a34c753fSRafael Auler } 160a34c753fSRafael Auler 161be2f67c4SAmir Ayupov static size_t getSizeForTypeAArch64(uint64_t Type) { 162a34c753fSRafael Auler switch (Type) { 163a34c753fSRafael Auler default: 164eb9f4eb6SAmir Ayupov errs() << object::getELFRelocationTypeName(ELF::EM_AARCH64, Type) << '\n'; 165a34c753fSRafael Auler llvm_unreachable("unsupported relocation type"); 166172deb75SVladislav Khmelevsky case ELF::R_AARCH64_ABS16: 16748e894a5SAlexey Moksyakov case ELF::R_AARCH64_PREL16: 168172deb75SVladislav Khmelevsky return 2; 169a34c753fSRafael Auler case ELF::R_AARCH64_CALL26: 170a34c753fSRafael Auler case ELF::R_AARCH64_JUMP26: 171a34c753fSRafael Auler case ELF::R_AARCH64_TSTBR14: 172a34c753fSRafael Auler case ELF::R_AARCH64_CONDBR19: 173a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_LO21: 174a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_PG_HI21: 175a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC: 176a34c753fSRafael Auler case ELF::R_AARCH64_LDST64_ABS_LO12_NC: 177a34c753fSRafael Auler case ELF::R_AARCH64_ADD_ABS_LO12_NC: 178a34c753fSRafael Auler case ELF::R_AARCH64_LDST128_ABS_LO12_NC: 179a34c753fSRafael Auler case ELF::R_AARCH64_LDST32_ABS_LO12_NC: 180a34c753fSRafael Auler case ELF::R_AARCH64_LDST16_ABS_LO12_NC: 181a34c753fSRafael Auler case ELF::R_AARCH64_LDST8_ABS_LO12_NC: 182a34c753fSRafael Auler case ELF::R_AARCH64_ADR_GOT_PAGE: 183a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PREL21: 184a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: 185a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 186a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: 187a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: 188*e11d49cbSAlexey Moksyakov case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0: 189*e11d49cbSAlexey Moksyakov case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: 190a34c753fSRafael Auler case ELF::R_AARCH64_LD64_GOT_LO12_NC: 191a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_LD64_LO12: 192a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADD_LO12: 193a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_CALL: 194a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: 195a34c753fSRafael Auler case ELF::R_AARCH64_PREL32: 196a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G0: 197a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G0_NC: 198a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G1: 199a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G1_NC: 200a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G2: 201a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G2_NC: 202a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G3: 203172deb75SVladislav Khmelevsky case ELF::R_AARCH64_ABS32: 204a34c753fSRafael Auler return 4; 205a34c753fSRafael Auler case ELF::R_AARCH64_ABS64: 20648e894a5SAlexey Moksyakov case ELF::R_AARCH64_PREL64: 207a34c753fSRafael Auler return 8; 208a34c753fSRafael Auler } 209a34c753fSRafael Auler } 210a34c753fSRafael Auler 211f8730293SJob Noorman static size_t getSizeForTypeRISCV(uint64_t Type) { 212f8730293SJob Noorman switch (Type) { 213f8730293SJob Noorman default: 214f8730293SJob Noorman errs() << object::getELFRelocationTypeName(ELF::EM_RISCV, Type) << '\n'; 215f8730293SJob Noorman llvm_unreachable("unsupported relocation type"); 216f8730293SJob Noorman case ELF::R_RISCV_RVC_JUMP: 217f8730293SJob Noorman case ELF::R_RISCV_RVC_BRANCH: 218f8730293SJob Noorman return 2; 219f8730293SJob Noorman case ELF::R_RISCV_JAL: 220f8730293SJob Noorman case ELF::R_RISCV_BRANCH: 221f8730293SJob Noorman case ELF::R_RISCV_PCREL_HI20: 222f8730293SJob Noorman case ELF::R_RISCV_PCREL_LO12_I: 2231b78742eSJob Noorman case ELF::R_RISCV_PCREL_LO12_S: 224f8730293SJob Noorman case ELF::R_RISCV_32_PCREL: 225f8730293SJob Noorman case ELF::R_RISCV_CALL: 226f8730293SJob Noorman case ELF::R_RISCV_CALL_PLT: 227b410d24aSJob Noorman case ELF::R_RISCV_ADD32: 228b410d24aSJob Noorman case ELF::R_RISCV_SUB32: 2299555736aSJob Noorman case ELF::R_RISCV_HI20: 2309555736aSJob Noorman case ELF::R_RISCV_LO12_I: 2319555736aSJob Noorman case ELF::R_RISCV_LO12_S: 232f8730293SJob Noorman return 4; 233cd7f1714SJob Noorman case ELF::R_RISCV_64: 234f8730293SJob Noorman case ELF::R_RISCV_GOT_HI20: 235c7d6d622SJob Noorman case ELF::R_RISCV_TLS_GOT_HI20: 236f8730293SJob Noorman // See extractValueRISCV for why this is necessary. 237f8730293SJob Noorman return 8; 238f8730293SJob Noorman } 239f8730293SJob Noorman } 240f8730293SJob Noorman 241be2f67c4SAmir Ayupov static bool skipRelocationTypeX86(uint64_t Type) { 242be2f67c4SAmir Ayupov return Type == ELF::R_X86_64_NONE; 243be2f67c4SAmir Ayupov } 2446e26ffa0SVladislav Khmelevsky 245be2f67c4SAmir Ayupov static bool skipRelocationTypeAArch64(uint64_t Type) { 2466e26ffa0SVladislav Khmelevsky return Type == ELF::R_AARCH64_NONE || Type == ELF::R_AARCH64_LD_PREL_LO19; 2476e26ffa0SVladislav Khmelevsky } 2486e26ffa0SVladislav Khmelevsky 249f8730293SJob Noorman static bool skipRelocationTypeRISCV(uint64_t Type) { 250f8730293SJob Noorman switch (Type) { 251f8730293SJob Noorman default: 252f8730293SJob Noorman return false; 253f8730293SJob Noorman case ELF::R_RISCV_NONE: 254f8730293SJob Noorman case ELF::R_RISCV_RELAX: 255f8730293SJob Noorman return true; 256f8730293SJob Noorman } 257f8730293SJob Noorman } 258f8730293SJob Noorman 259be2f67c4SAmir Ayupov static bool skipRelocationProcessX86(uint64_t &Type, uint64_t Contents) { 260a34c753fSRafael Auler return false; 261a34c753fSRafael Auler } 262a34c753fSRafael Auler 263be2f67c4SAmir Ayupov static bool skipRelocationProcessAArch64(uint64_t &Type, uint64_t Contents) { 264a34c753fSRafael Auler auto IsMov = [](uint64_t Contents) -> bool { 265a34c753fSRafael Auler // The bits 28-23 are 0b100101 2662f98c5feSVladislav Khmelevsky return (Contents & 0x1f800000) == 0x12800000; 267a34c753fSRafael Auler }; 268a34c753fSRafael Auler 269a34c753fSRafael Auler auto IsB = [](uint64_t Contents) -> bool { 270a34c753fSRafael Auler // The bits 31-26 are 0b000101 2712f98c5feSVladislav Khmelevsky return (Contents & 0xfc000000) == 0x14000000; 2722f98c5feSVladislav Khmelevsky }; 2732f98c5feSVladislav Khmelevsky 2742f98c5feSVladislav Khmelevsky auto IsAdr = [](uint64_t Contents) -> bool { 2752f98c5feSVladislav Khmelevsky // The bits 31-24 are 0b0xx10000 2762f98c5feSVladislav Khmelevsky return (Contents & 0x9f000000) == 0x10000000; 277a34c753fSRafael Auler }; 278a34c753fSRafael Auler 27917ed8f29SVladislav Khmelevsky auto IsAddImm = [](uint64_t Contents) -> bool { 28017ed8f29SVladislav Khmelevsky // The bits 30-23 are 0b00100010 28117ed8f29SVladislav Khmelevsky return (Contents & 0x7F800000) == 0x11000000; 28217ed8f29SVladislav Khmelevsky }; 28317ed8f29SVladislav Khmelevsky 28440c2e0faSMaksim Panchenko auto IsNop = [](uint64_t Contents) -> bool { return Contents == 0xd503201f; }; 285a34c753fSRafael Auler 286a34c753fSRafael Auler // The linker might eliminate the instruction and replace it with NOP, ignore 287a34c753fSRafael Auler if (IsNop(Contents)) 288a34c753fSRafael Auler return true; 289a34c753fSRafael Auler 29017ed8f29SVladislav Khmelevsky // The linker might relax ADRP+LDR instruction sequence for loading symbol 29117ed8f29SVladislav Khmelevsky // address from GOT table to ADRP+ADD sequence that would point to the 29217ed8f29SVladislav Khmelevsky // binary-local symbol. Change relocation type in order to process it right. 29317ed8f29SVladislav Khmelevsky if (Type == ELF::R_AARCH64_LD64_GOT_LO12_NC && IsAddImm(Contents)) { 29417ed8f29SVladislav Khmelevsky Type = ELF::R_AARCH64_ADD_ABS_LO12_NC; 29517ed8f29SVladislav Khmelevsky return false; 29617ed8f29SVladislav Khmelevsky } 29717ed8f29SVladislav Khmelevsky 298a34c753fSRafael Auler // The linker might perform TLS relocations relaxations, such as 299a34c753fSRafael Auler // changed TLS access model (e.g. changed global dynamic model 300a34c753fSRafael Auler // to initial exec), thus changing the instructions. The static 301a34c753fSRafael Auler // relocations might be invalid at this point and we might no 3021a2f8336Sspaette // need to process these relocations anymore. 303a34c753fSRafael Auler // More information could be found by searching 304a34c753fSRafael Auler // elfNN_aarch64_tls_relax in bfd 305a34c753fSRafael Auler switch (Type) { 306a34c753fSRafael Auler default: 307a34c753fSRafael Auler break; 308a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_LD64_LO12: 309a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: 310a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 311a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: { 312a34c753fSRafael Auler if (IsMov(Contents)) 313a34c753fSRafael Auler return true; 314a34c753fSRafael Auler } 315a34c753fSRafael Auler } 316a34c753fSRafael Auler 3172f98c5feSVladislav Khmelevsky // The linker might replace load/store instruction with jump and 318a34c753fSRafael Auler // veneer due to errata 843419 319a34c753fSRafael Auler // https://documentation-service.arm.com/static/5fa29fddb209f547eebd361d 320a34c753fSRafael Auler // Thus load/store relocations for these instructions must be ignored 321a34c753fSRafael Auler // NOTE: We only process GOT and TLS relocations this way since the 322a34c753fSRafael Auler // addend used in load/store instructions won't change after bolt 323a34c753fSRafael Auler // (it is important since the instruction in veneer won't have relocation) 324a34c753fSRafael Auler switch (Type) { 325a34c753fSRafael Auler default: 326a34c753fSRafael Auler break; 327a34c753fSRafael Auler case ELF::R_AARCH64_LD64_GOT_LO12_NC: 328a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 329a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_LD64_LO12: { 330a34c753fSRafael Auler if (IsB(Contents)) 331a34c753fSRafael Auler return true; 332a34c753fSRafael Auler } 333a34c753fSRafael Auler } 334a34c753fSRafael Auler 3352f98c5feSVladislav Khmelevsky // The linker might relax ADRP+ADD or ADRP+LDR sequences to the ADR+NOP 3362f98c5feSVladislav Khmelevsky switch (Type) { 3372f98c5feSVladislav Khmelevsky default: 3382f98c5feSVladislav Khmelevsky break; 3392f98c5feSVladislav Khmelevsky case ELF::R_AARCH64_ADR_PREL_PG_HI21: 3402f98c5feSVladislav Khmelevsky case ELF::R_AARCH64_ADD_ABS_LO12_NC: 3412f98c5feSVladislav Khmelevsky case ELF::R_AARCH64_ADR_GOT_PAGE: 3422f98c5feSVladislav Khmelevsky case ELF::R_AARCH64_LD64_GOT_LO12_NC: 3432f98c5feSVladislav Khmelevsky if (IsAdr(Contents)) 3442f98c5feSVladislav Khmelevsky return true; 3452f98c5feSVladislav Khmelevsky } 3462f98c5feSVladislav Khmelevsky 347a34c753fSRafael Auler return false; 348a34c753fSRafael Auler } 349a34c753fSRafael Auler 350f8730293SJob Noorman static bool skipRelocationProcessRISCV(uint64_t &Type, uint64_t Contents) { 351f8730293SJob Noorman return false; 352f8730293SJob Noorman } 353f8730293SJob Noorman 35477811752SRafael Auler static uint64_t encodeValueX86(uint64_t Type, uint64_t Value, uint64_t PC) { 3554a4045f7SElvina Yakubova switch (Type) { 3564a4045f7SElvina Yakubova default: 35777811752SRafael Auler llvm_unreachable("unsupported relocation"); 35877811752SRafael Auler case ELF::R_X86_64_64: 3594a4045f7SElvina Yakubova case ELF::R_X86_64_32: 3604a4045f7SElvina Yakubova break; 3614a4045f7SElvina Yakubova case ELF::R_X86_64_PC32: 3624a4045f7SElvina Yakubova Value -= PC; 3634a4045f7SElvina Yakubova break; 3644a4045f7SElvina Yakubova } 3654a4045f7SElvina Yakubova return Value; 3664a4045f7SElvina Yakubova } 3674a4045f7SElvina Yakubova 36877811752SRafael Auler static uint64_t encodeValueAArch64(uint64_t Type, uint64_t Value, uint64_t PC) { 3694a4045f7SElvina Yakubova switch (Type) { 3704a4045f7SElvina Yakubova default: 37177811752SRafael Auler llvm_unreachable("unsupported relocation"); 37296b5e092SJob Noorman case ELF::R_AARCH64_ABS16: 3734a4045f7SElvina Yakubova case ELF::R_AARCH64_ABS32: 37496b5e092SJob Noorman case ELF::R_AARCH64_ABS64: 3754a4045f7SElvina Yakubova break; 37648e894a5SAlexey Moksyakov case ELF::R_AARCH64_PREL16: 3774a4045f7SElvina Yakubova case ELF::R_AARCH64_PREL32: 37848e894a5SAlexey Moksyakov case ELF::R_AARCH64_PREL64: 3794a4045f7SElvina Yakubova Value -= PC; 3804a4045f7SElvina Yakubova break; 38162020a3aSzhoujiapeng case ELF::R_AARCH64_CALL26: 38262020a3aSzhoujiapeng Value -= PC; 38362020a3aSzhoujiapeng assert(isInt<28>(Value) && "only PC +/- 128MB is allowed for direct call"); 38462020a3aSzhoujiapeng // Immediate goes in bits 25:0 of BL. 38562020a3aSzhoujiapeng // OP 1001_01 goes in bits 31:26 of BL. 3867b4b09a5SSinan Lin Value = ((Value >> 2) & 0x3ffffff) | 0x94000000ULL; 38762020a3aSzhoujiapeng break; 38871c2a132Ssinan case ELF::R_AARCH64_JUMP26: 38971c2a132Ssinan Value -= PC; 39071c2a132Ssinan assert(isInt<28>(Value) && 39171c2a132Ssinan "only PC +/- 128MB is allowed for direct branch"); 39271c2a132Ssinan // Immediate goes in bits 25:0 of B. 39371c2a132Ssinan // OP 0001_01 goes in bits 31:26 of B. 39471c2a132Ssinan Value = ((Value >> 2) & 0x3ffffff) | 0x14000000ULL; 39571c2a132Ssinan break; 3964a4045f7SElvina Yakubova } 3974a4045f7SElvina Yakubova return Value; 3984a4045f7SElvina Yakubova } 3994a4045f7SElvina Yakubova 400cd7f1714SJob Noorman static uint64_t encodeValueRISCV(uint64_t Type, uint64_t Value, uint64_t PC) { 401cd7f1714SJob Noorman switch (Type) { 402cd7f1714SJob Noorman default: 403cd7f1714SJob Noorman llvm_unreachable("unsupported relocation"); 404cd7f1714SJob Noorman case ELF::R_RISCV_64: 405cd7f1714SJob Noorman break; 406cd7f1714SJob Noorman } 407cd7f1714SJob Noorman return Value; 408cd7f1714SJob Noorman } 409cd7f1714SJob Noorman 410be2f67c4SAmir Ayupov static uint64_t extractValueX86(uint64_t Type, uint64_t Contents, uint64_t PC) { 411a34c753fSRafael Auler if (Type == ELF::R_X86_64_32S) 4124101aa13SMaksim Panchenko return SignExtend64<32>(Contents); 4134101aa13SMaksim Panchenko if (Relocation::isPCRelative(Type)) 4144101aa13SMaksim Panchenko return SignExtend64(Contents, 8 * Relocation::getSizeForType(Type)); 415a34c753fSRafael Auler return Contents; 416a34c753fSRafael Auler } 417a34c753fSRafael Auler 418be2f67c4SAmir Ayupov static uint64_t extractValueAArch64(uint64_t Type, uint64_t Contents, 419be2f67c4SAmir Ayupov uint64_t PC) { 420a34c753fSRafael Auler switch (Type) { 421a34c753fSRafael Auler default: 422eb9f4eb6SAmir Ayupov errs() << object::getELFRelocationTypeName(ELF::EM_AARCH64, Type) << '\n'; 423a34c753fSRafael Auler llvm_unreachable("unsupported relocation type"); 424172deb75SVladislav Khmelevsky case ELF::R_AARCH64_ABS16: 425172deb75SVladislav Khmelevsky case ELF::R_AARCH64_ABS32: 426a34c753fSRafael Auler case ELF::R_AARCH64_ABS64: 427a34c753fSRafael Auler return Contents; 42848e894a5SAlexey Moksyakov case ELF::R_AARCH64_PREL16: 42948e894a5SAlexey Moksyakov return static_cast<int64_t>(PC) + SignExtend64<16>(Contents & 0xffff); 430a34c753fSRafael Auler case ELF::R_AARCH64_PREL32: 431a34c753fSRafael Auler return static_cast<int64_t>(PC) + SignExtend64<32>(Contents & 0xffffffff); 43248e894a5SAlexey Moksyakov case ELF::R_AARCH64_PREL64: 43348e894a5SAlexey Moksyakov return static_cast<int64_t>(PC) + Contents; 434a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_CALL: 435a34c753fSRafael Auler case ELF::R_AARCH64_JUMP26: 436a34c753fSRafael Auler case ELF::R_AARCH64_CALL26: 437a34c753fSRafael Auler // Immediate goes in bits 25:0 of B and BL. 438a34c753fSRafael Auler Contents &= ~0xfffffffffc000000ULL; 439a34c753fSRafael Auler return static_cast<int64_t>(PC) + SignExtend64<28>(Contents << 2); 440a34c753fSRafael Auler case ELF::R_AARCH64_TSTBR14: 441a34c753fSRafael Auler // Immediate:15:2 goes in bits 18:5 of TBZ, TBNZ 442a34c753fSRafael Auler Contents &= ~0xfffffffffff8001fULL; 443a34c753fSRafael Auler return static_cast<int64_t>(PC) + SignExtend64<16>(Contents >> 3); 444a34c753fSRafael Auler case ELF::R_AARCH64_CONDBR19: 445a34c753fSRafael Auler // Immediate:20:2 goes in bits 23:5 of Bcc, CBZ, CBNZ 446a34c753fSRafael Auler Contents &= ~0xffffffffff00001fULL; 447a34c753fSRafael Auler return static_cast<int64_t>(PC) + SignExtend64<21>(Contents >> 3); 448a34c753fSRafael Auler case ELF::R_AARCH64_ADR_GOT_PAGE: 449a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PREL21: 450a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: 451a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: 452a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_LO21: 453a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_PG_HI21: 454a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC: { 455a34c753fSRafael Auler // Bits 32:12 of Symbol address goes in bits 30:29 + 23:5 of ADRP 456a34c753fSRafael Auler // and ADR instructions 457a34c753fSRafael Auler bool IsAdr = !!(((Contents >> 31) & 0x1) == 0); 458a34c753fSRafael Auler Contents &= ~0xffffffff9f00001fUll; 459a34c753fSRafael Auler uint64_t LowBits = (Contents >> 29) & 0x3; 460a34c753fSRafael Auler uint64_t HighBits = (Contents >> 5) & 0x7ffff; 461a34c753fSRafael Auler Contents = LowBits | (HighBits << 2); 462a34c753fSRafael Auler if (IsAdr) 463a34c753fSRafael Auler return static_cast<int64_t>(PC) + SignExtend64<21>(Contents); 464a34c753fSRafael Auler 465a34c753fSRafael Auler // ADRP instruction 466a34c753fSRafael Auler Contents = static_cast<int64_t>(PC) + SignExtend64<33>(Contents << 12); 467a34c753fSRafael Auler Contents &= ~0xfffUll; 468a34c753fSRafael Auler return Contents; 469a34c753fSRafael Auler } 470a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 471a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_LD64_LO12: 472a34c753fSRafael Auler case ELF::R_AARCH64_LD64_GOT_LO12_NC: 473a34c753fSRafael Auler case ELF::R_AARCH64_LDST64_ABS_LO12_NC: { 474a34c753fSRafael Auler // Immediate goes in bits 21:10 of LD/ST instruction, taken 475a34c753fSRafael Auler // from bits 11:3 of Symbol address 476a34c753fSRafael Auler Contents &= ~0xffffffffffc003ffU; 477a34c753fSRafael Auler return Contents >> (10 - 3); 478a34c753fSRafael Auler } 479a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: 480a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: 481a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADD_LO12: 482a34c753fSRafael Auler case ELF::R_AARCH64_ADD_ABS_LO12_NC: { 483a34c753fSRafael Auler // Immediate goes in bits 21:10 of ADD instruction 484a34c753fSRafael Auler Contents &= ~0xffffffffffc003ffU; 485a34c753fSRafael Auler return Contents >> (10 - 0); 486a34c753fSRafael Auler } 487a34c753fSRafael Auler case ELF::R_AARCH64_LDST128_ABS_LO12_NC: { 488a34c753fSRafael Auler // Immediate goes in bits 21:10 of ADD instruction, taken 489a34c753fSRafael Auler // from bits 11:4 of Symbol address 490a34c753fSRafael Auler Contents &= ~0xffffffffffc003ffU; 491a34c753fSRafael Auler return Contents >> (10 - 4); 492a34c753fSRafael Auler } 493a34c753fSRafael Auler case ELF::R_AARCH64_LDST32_ABS_LO12_NC: { 494a34c753fSRafael Auler // Immediate goes in bits 21:10 of ADD instruction, taken 495a34c753fSRafael Auler // from bits 11:2 of Symbol address 496a34c753fSRafael Auler Contents &= ~0xffffffffffc003ffU; 497a34c753fSRafael Auler return Contents >> (10 - 2); 498a34c753fSRafael Auler } 499a34c753fSRafael Auler case ELF::R_AARCH64_LDST16_ABS_LO12_NC: { 500a34c753fSRafael Auler // Immediate goes in bits 21:10 of ADD instruction, taken 501a34c753fSRafael Auler // from bits 11:1 of Symbol address 502a34c753fSRafael Auler Contents &= ~0xffffffffffc003ffU; 503a34c753fSRafael Auler return Contents >> (10 - 1); 504a34c753fSRafael Auler } 505a34c753fSRafael Auler case ELF::R_AARCH64_LDST8_ABS_LO12_NC: { 506a34c753fSRafael Auler // Immediate goes in bits 21:10 of ADD instruction, taken 507a34c753fSRafael Auler // from bits 11:0 of Symbol address 508a34c753fSRafael Auler Contents &= ~0xffffffffffc003ffU; 509a34c753fSRafael Auler return Contents >> (10 - 0); 510a34c753fSRafael Auler } 511a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G3: 512a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G2_NC: 513a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G2: 514a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G1_NC: 515a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G1: 516a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G0_NC: 517a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G0: 5181a2f8336Sspaette // The shift goes in bits 22:21 of MOV* instructions 519a34c753fSRafael Auler uint8_t Shift = (Contents >> 21) & 0x3; 520a34c753fSRafael Auler // Immediate goes in bits 20:5 521a34c753fSRafael Auler Contents = (Contents >> 5) & 0xffff; 522a34c753fSRafael Auler return Contents << (16 * Shift); 523a34c753fSRafael Auler } 524a34c753fSRafael Auler } 525a34c753fSRafael Auler 526f8730293SJob Noorman static uint64_t extractUImmRISCV(uint32_t Contents) { 527f8730293SJob Noorman return SignExtend64<32>(Contents & 0xfffff000); 528f8730293SJob Noorman } 529f8730293SJob Noorman 530f8730293SJob Noorman static uint64_t extractIImmRISCV(uint32_t Contents) { 531f8730293SJob Noorman return SignExtend64<12>(Contents >> 20); 532f8730293SJob Noorman } 533f8730293SJob Noorman 5341b78742eSJob Noorman static uint64_t extractSImmRISCV(uint32_t Contents) { 5351b78742eSJob Noorman return SignExtend64<12>(((Contents >> 7) & 0x1f) | ((Contents >> 25) << 5)); 5361b78742eSJob Noorman } 5371b78742eSJob Noorman 538f8730293SJob Noorman static uint64_t extractJImmRISCV(uint32_t Contents) { 539f8730293SJob Noorman return SignExtend64<21>( 540f8730293SJob Noorman (((Contents >> 21) & 0x3ff) << 1) | (((Contents >> 20) & 0x1) << 11) | 541f8730293SJob Noorman (((Contents >> 12) & 0xff) << 12) | (((Contents >> 31) & 0x1) << 20)); 542f8730293SJob Noorman } 543f8730293SJob Noorman 544f8730293SJob Noorman static uint64_t extractBImmRISCV(uint32_t Contents) { 545f8730293SJob Noorman return SignExtend64<13>( 546f8730293SJob Noorman (((Contents >> 8) & 0xf) << 1) | (((Contents >> 25) & 0x3f) << 5) | 547f8730293SJob Noorman (((Contents >> 7) & 0x1) << 11) | (((Contents >> 31) & 0x1) << 12)); 548f8730293SJob Noorman } 549f8730293SJob Noorman 550f8730293SJob Noorman static uint64_t extractValueRISCV(uint64_t Type, uint64_t Contents, 551f8730293SJob Noorman uint64_t PC) { 552f8730293SJob Noorman switch (Type) { 553f8730293SJob Noorman default: 554f8730293SJob Noorman errs() << object::getELFRelocationTypeName(ELF::EM_RISCV, Type) << '\n'; 555f8730293SJob Noorman llvm_unreachable("unsupported relocation type"); 556f8730293SJob Noorman case ELF::R_RISCV_JAL: 557f8730293SJob Noorman return extractJImmRISCV(Contents); 558f8730293SJob Noorman case ELF::R_RISCV_CALL: 559f8730293SJob Noorman case ELF::R_RISCV_CALL_PLT: 560f8730293SJob Noorman return extractUImmRISCV(Contents); 561f8730293SJob Noorman case ELF::R_RISCV_BRANCH: 562f8730293SJob Noorman return extractBImmRISCV(Contents); 563f8730293SJob Noorman case ELF::R_RISCV_GOT_HI20: 564c7d6d622SJob Noorman case ELF::R_RISCV_TLS_GOT_HI20: 565f8730293SJob Noorman // We need to know the exact address of the GOT entry so we extract the 566f8730293SJob Noorman // value from both the AUIPC and L[D|W]. We cannot rely on the symbol in the 567f8730293SJob Noorman // relocation for this since it simply refers to the object that is stored 568f8730293SJob Noorman // in the GOT entry, not to the entry itself. 569f8730293SJob Noorman return extractUImmRISCV(Contents & 0xffffffff) + 570f8730293SJob Noorman extractIImmRISCV(Contents >> 32); 571f8730293SJob Noorman case ELF::R_RISCV_PCREL_HI20: 5729555736aSJob Noorman case ELF::R_RISCV_HI20: 573f8730293SJob Noorman return extractUImmRISCV(Contents); 574f8730293SJob Noorman case ELF::R_RISCV_PCREL_LO12_I: 5759555736aSJob Noorman case ELF::R_RISCV_LO12_I: 576f8730293SJob Noorman return extractIImmRISCV(Contents); 5771b78742eSJob Noorman case ELF::R_RISCV_PCREL_LO12_S: 5789555736aSJob Noorman case ELF::R_RISCV_LO12_S: 5791b78742eSJob Noorman return extractSImmRISCV(Contents); 580f8730293SJob Noorman case ELF::R_RISCV_RVC_JUMP: 581f8730293SJob Noorman return SignExtend64<11>(Contents >> 2); 582f8730293SJob Noorman case ELF::R_RISCV_RVC_BRANCH: 583f8730293SJob Noorman return SignExtend64<8>(((Contents >> 2) & 0x1f) | ((Contents >> 5) & 0xe0)); 584b410d24aSJob Noorman case ELF::R_RISCV_ADD32: 585b410d24aSJob Noorman case ELF::R_RISCV_SUB32: 586cd7f1714SJob Noorman case ELF::R_RISCV_64: 587b410d24aSJob Noorman return Contents; 588f8730293SJob Noorman } 589f8730293SJob Noorman } 590f8730293SJob Noorman 591be2f67c4SAmir Ayupov static bool isGOTX86(uint64_t Type) { 592a34c753fSRafael Auler switch (Type) { 593a34c753fSRafael Auler default: 594a34c753fSRafael Auler return false; 595a34c753fSRafael Auler case ELF::R_X86_64_GOT32: 596a34c753fSRafael Auler case ELF::R_X86_64_GOTPCREL: 597a34c753fSRafael Auler case ELF::R_X86_64_GOTTPOFF: 598a34c753fSRafael Auler case ELF::R_X86_64_GOTOFF64: 599a34c753fSRafael Auler case ELF::R_X86_64_GOTPC32: 600a34c753fSRafael Auler case ELF::R_X86_64_GOT64: 601a34c753fSRafael Auler case ELF::R_X86_64_GOTPCREL64: 602a34c753fSRafael Auler case ELF::R_X86_64_GOTPC64: 603a34c753fSRafael Auler case ELF::R_X86_64_GOTPLT64: 604a34c753fSRafael Auler case ELF::R_X86_64_GOTPC32_TLSDESC: 605a34c753fSRafael Auler case ELF::R_X86_64_GOTPCRELX: 606a34c753fSRafael Auler case ELF::R_X86_64_REX_GOTPCRELX: 607a34c753fSRafael Auler return true; 608a34c753fSRafael Auler } 609a34c753fSRafael Auler } 610a34c753fSRafael Auler 611be2f67c4SAmir Ayupov static bool isGOTAArch64(uint64_t Type) { 612a34c753fSRafael Auler switch (Type) { 613a34c753fSRafael Auler default: 614a34c753fSRafael Auler return false; 615a34c753fSRafael Auler case ELF::R_AARCH64_ADR_GOT_PAGE: 616a34c753fSRafael Auler case ELF::R_AARCH64_LD64_GOT_LO12_NC: 617a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 618a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: 619a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PREL21: 620a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: 621a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_LD64_LO12: 622a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADD_LO12: 623a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_CALL: 624a34c753fSRafael Auler return true; 625a34c753fSRafael Auler } 626a34c753fSRafael Auler } 627a34c753fSRafael Auler 628f8730293SJob Noorman static bool isGOTRISCV(uint64_t Type) { 629f8730293SJob Noorman switch (Type) { 630f8730293SJob Noorman default: 631f8730293SJob Noorman return false; 632f8730293SJob Noorman case ELF::R_RISCV_GOT_HI20: 633c7d6d622SJob Noorman case ELF::R_RISCV_TLS_GOT_HI20: 634f8730293SJob Noorman return true; 635f8730293SJob Noorman } 636f8730293SJob Noorman } 637f8730293SJob Noorman 638be2f67c4SAmir Ayupov static bool isTLSX86(uint64_t Type) { 639a34c753fSRafael Auler switch (Type) { 640a34c753fSRafael Auler default: 641a34c753fSRafael Auler return false; 642a34c753fSRafael Auler case ELF::R_X86_64_TPOFF32: 643a34c753fSRafael Auler case ELF::R_X86_64_TPOFF64: 644a34c753fSRafael Auler case ELF::R_X86_64_GOTTPOFF: 645a34c753fSRafael Auler return true; 646a34c753fSRafael Auler } 647a34c753fSRafael Auler } 648a34c753fSRafael Auler 649be2f67c4SAmir Ayupov static bool isTLSAArch64(uint64_t Type) { 650a34c753fSRafael Auler switch (Type) { 651a34c753fSRafael Auler default: 652a34c753fSRafael Auler return false; 653a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PREL21: 654a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: 655a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 656a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: 657a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: 658*e11d49cbSAlexey Moksyakov case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0: 659*e11d49cbSAlexey Moksyakov case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: 660a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_LD64_LO12: 661a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADD_LO12: 662a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_CALL: 663a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: 664a34c753fSRafael Auler return true; 665a34c753fSRafael Auler } 666a34c753fSRafael Auler } 667a34c753fSRafael Auler 668f8730293SJob Noorman static bool isTLSRISCV(uint64_t Type) { 669f8730293SJob Noorman switch (Type) { 670f8730293SJob Noorman default: 671f8730293SJob Noorman return false; 672c7d6d622SJob Noorman case ELF::R_RISCV_TLS_GOT_HI20: 673c7d6d622SJob Noorman case ELF::R_RISCV_TPREL_HI20: 674c7d6d622SJob Noorman case ELF::R_RISCV_TPREL_ADD: 675c7d6d622SJob Noorman case ELF::R_RISCV_TPREL_LO12_I: 676c7d6d622SJob Noorman case ELF::R_RISCV_TPREL_LO12_S: 677c7d6d622SJob Noorman case ELFReserved::R_RISCV_TPREL_I: 678c7d6d622SJob Noorman case ELFReserved::R_RISCV_TPREL_S: 679c7d6d622SJob Noorman return true; 680f8730293SJob Noorman } 681f8730293SJob Noorman } 682f8730293SJob Noorman 683be2f67c4SAmir Ayupov static bool isPCRelativeX86(uint64_t Type) { 684a34c753fSRafael Auler switch (Type) { 685a34c753fSRafael Auler default: 686a34c753fSRafael Auler llvm_unreachable("Unknown relocation type"); 687a34c753fSRafael Auler case ELF::R_X86_64_64: 688a34c753fSRafael Auler case ELF::R_X86_64_32: 689a34c753fSRafael Auler case ELF::R_X86_64_32S: 690a34c753fSRafael Auler case ELF::R_X86_64_16: 691a34c753fSRafael Auler case ELF::R_X86_64_8: 692a34c753fSRafael Auler case ELF::R_X86_64_TPOFF32: 693a34c753fSRafael Auler return false; 694a34c753fSRafael Auler case ELF::R_X86_64_PC8: 695a34c753fSRafael Auler case ELF::R_X86_64_PC32: 696a34c753fSRafael Auler case ELF::R_X86_64_PC64: 697a34c753fSRafael Auler case ELF::R_X86_64_GOTPCREL: 698a34c753fSRafael Auler case ELF::R_X86_64_PLT32: 6994101aa13SMaksim Panchenko case ELF::R_X86_64_GOTOFF64: 7004101aa13SMaksim Panchenko case ELF::R_X86_64_GOTPC32: 701853e126cSRafael Auler case ELF::R_X86_64_GOTPC64: 702a34c753fSRafael Auler case ELF::R_X86_64_GOTTPOFF: 703a34c753fSRafael Auler case ELF::R_X86_64_GOTPCRELX: 704a34c753fSRafael Auler case ELF::R_X86_64_REX_GOTPCRELX: 705a34c753fSRafael Auler return true; 706a34c753fSRafael Auler } 707a34c753fSRafael Auler } 708a34c753fSRafael Auler 709be2f67c4SAmir Ayupov static bool isPCRelativeAArch64(uint64_t Type) { 710a34c753fSRafael Auler switch (Type) { 711a34c753fSRafael Auler default: 712a34c753fSRafael Auler llvm_unreachable("Unknown relocation type"); 713172deb75SVladislav Khmelevsky case ELF::R_AARCH64_ABS16: 714172deb75SVladislav Khmelevsky case ELF::R_AARCH64_ABS32: 715a34c753fSRafael Auler case ELF::R_AARCH64_ABS64: 716a34c753fSRafael Auler case ELF::R_AARCH64_LDST64_ABS_LO12_NC: 717a34c753fSRafael Auler case ELF::R_AARCH64_ADD_ABS_LO12_NC: 718a34c753fSRafael Auler case ELF::R_AARCH64_LDST128_ABS_LO12_NC: 719a34c753fSRafael Auler case ELF::R_AARCH64_LDST32_ABS_LO12_NC: 720a34c753fSRafael Auler case ELF::R_AARCH64_LDST16_ABS_LO12_NC: 721a34c753fSRafael Auler case ELF::R_AARCH64_LDST8_ABS_LO12_NC: 722a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 723a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: 724a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: 725*e11d49cbSAlexey Moksyakov case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0: 726*e11d49cbSAlexey Moksyakov case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: 727a34c753fSRafael Auler case ELF::R_AARCH64_LD64_GOT_LO12_NC: 728a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_LD64_LO12: 729a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADD_LO12: 730a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G0: 731a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G0_NC: 732a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G1: 733a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G1_NC: 734a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G2: 735a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G2_NC: 736a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G3: 737a34c753fSRafael Auler return false; 738a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_CALL: 739a34c753fSRafael Auler case ELF::R_AARCH64_CALL26: 740a34c753fSRafael Auler case ELF::R_AARCH64_JUMP26: 741a34c753fSRafael Auler case ELF::R_AARCH64_TSTBR14: 742a34c753fSRafael Auler case ELF::R_AARCH64_CONDBR19: 743a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_LO21: 744a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_PG_HI21: 745a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC: 746a34c753fSRafael Auler case ELF::R_AARCH64_ADR_GOT_PAGE: 747a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: 748a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PREL21: 749a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: 75048e894a5SAlexey Moksyakov case ELF::R_AARCH64_PREL16: 751a34c753fSRafael Auler case ELF::R_AARCH64_PREL32: 75248e894a5SAlexey Moksyakov case ELF::R_AARCH64_PREL64: 753a34c753fSRafael Auler return true; 754a34c753fSRafael Auler } 755a34c753fSRafael Auler } 756a34c753fSRafael Auler 757f8730293SJob Noorman static bool isPCRelativeRISCV(uint64_t Type) { 758f8730293SJob Noorman switch (Type) { 759f8730293SJob Noorman default: 760f8730293SJob Noorman llvm_unreachable("Unknown relocation type"); 761b410d24aSJob Noorman case ELF::R_RISCV_ADD32: 762b410d24aSJob Noorman case ELF::R_RISCV_SUB32: 7639555736aSJob Noorman case ELF::R_RISCV_HI20: 7649555736aSJob Noorman case ELF::R_RISCV_LO12_I: 7659555736aSJob Noorman case ELF::R_RISCV_LO12_S: 766cd7f1714SJob Noorman case ELF::R_RISCV_64: 767b410d24aSJob Noorman return false; 768f8730293SJob Noorman case ELF::R_RISCV_JAL: 769f8730293SJob Noorman case ELF::R_RISCV_CALL: 770f8730293SJob Noorman case ELF::R_RISCV_CALL_PLT: 771f8730293SJob Noorman case ELF::R_RISCV_BRANCH: 772f8730293SJob Noorman case ELF::R_RISCV_GOT_HI20: 773f8730293SJob Noorman case ELF::R_RISCV_PCREL_HI20: 774f8730293SJob Noorman case ELF::R_RISCV_PCREL_LO12_I: 7751b78742eSJob Noorman case ELF::R_RISCV_PCREL_LO12_S: 776f8730293SJob Noorman case ELF::R_RISCV_RVC_JUMP: 777f8730293SJob Noorman case ELF::R_RISCV_RVC_BRANCH: 778f8730293SJob Noorman case ELF::R_RISCV_32_PCREL: 779c7d6d622SJob Noorman case ELF::R_RISCV_TLS_GOT_HI20: 780f8730293SJob Noorman return true; 781f8730293SJob Noorman } 782f8730293SJob Noorman } 783f8730293SJob Noorman 784a34c753fSRafael Auler bool Relocation::isSupported(uint64_t Type) { 7854308c742SNathan Sidwell switch (Arch) { 7864308c742SNathan Sidwell default: 7874308c742SNathan Sidwell return false; 7884308c742SNathan Sidwell case Triple::aarch64: 789a34c753fSRafael Auler return isSupportedAArch64(Type); 7904308c742SNathan Sidwell case Triple::riscv64: 791f8730293SJob Noorman return isSupportedRISCV(Type); 7924308c742SNathan Sidwell case Triple::x86_64: 793a34c753fSRafael Auler return isSupportedX86(Type); 794a34c753fSRafael Auler } 7954308c742SNathan Sidwell } 796a34c753fSRafael Auler 797a34c753fSRafael Auler size_t Relocation::getSizeForType(uint64_t Type) { 7984308c742SNathan Sidwell switch (Arch) { 7994308c742SNathan Sidwell default: 8004308c742SNathan Sidwell llvm_unreachable("Unsupported architecture"); 8014308c742SNathan Sidwell case Triple::aarch64: 802a34c753fSRafael Auler return getSizeForTypeAArch64(Type); 8034308c742SNathan Sidwell case Triple::riscv64: 804f8730293SJob Noorman return getSizeForTypeRISCV(Type); 8054308c742SNathan Sidwell case Triple::x86_64: 806a34c753fSRafael Auler return getSizeForTypeX86(Type); 807a34c753fSRafael Auler } 8084308c742SNathan Sidwell } 809a34c753fSRafael Auler 8106e26ffa0SVladislav Khmelevsky bool Relocation::skipRelocationType(uint64_t Type) { 8114308c742SNathan Sidwell switch (Arch) { 8124308c742SNathan Sidwell default: 8134308c742SNathan Sidwell llvm_unreachable("Unsupported architecture"); 8144308c742SNathan Sidwell case Triple::aarch64: 8156e26ffa0SVladislav Khmelevsky return skipRelocationTypeAArch64(Type); 8164308c742SNathan Sidwell case Triple::riscv64: 817f8730293SJob Noorman return skipRelocationTypeRISCV(Type); 8184308c742SNathan Sidwell case Triple::x86_64: 8196e26ffa0SVladislav Khmelevsky return skipRelocationTypeX86(Type); 8206e26ffa0SVladislav Khmelevsky } 8214308c742SNathan Sidwell } 8226e26ffa0SVladislav Khmelevsky 82317ed8f29SVladislav Khmelevsky bool Relocation::skipRelocationProcess(uint64_t &Type, uint64_t Contents) { 8244308c742SNathan Sidwell switch (Arch) { 8254308c742SNathan Sidwell default: 8264308c742SNathan Sidwell llvm_unreachable("Unsupported architecture"); 8274308c742SNathan Sidwell case Triple::aarch64: 828a34c753fSRafael Auler return skipRelocationProcessAArch64(Type, Contents); 8294308c742SNathan Sidwell case Triple::riscv64: 8304308c742SNathan Sidwell return skipRelocationProcessRISCV(Type, Contents); 8314308c742SNathan Sidwell case Triple::x86_64: 832a34c753fSRafael Auler return skipRelocationProcessX86(Type, Contents); 833a34c753fSRafael Auler } 8344308c742SNathan Sidwell } 835a34c753fSRafael Auler 83677811752SRafael Auler uint64_t Relocation::encodeValue(uint64_t Type, uint64_t Value, uint64_t PC) { 8374308c742SNathan Sidwell switch (Arch) { 8384308c742SNathan Sidwell default: 8394308c742SNathan Sidwell llvm_unreachable("Unsupported architecture"); 8404308c742SNathan Sidwell case Triple::aarch64: 84177811752SRafael Auler return encodeValueAArch64(Type, Value, PC); 8424308c742SNathan Sidwell case Triple::riscv64: 843cd7f1714SJob Noorman return encodeValueRISCV(Type, Value, PC); 8444308c742SNathan Sidwell case Triple::x86_64: 84577811752SRafael Auler return encodeValueX86(Type, Value, PC); 8464a4045f7SElvina Yakubova } 8474308c742SNathan Sidwell } 8484a4045f7SElvina Yakubova 849a34c753fSRafael Auler uint64_t Relocation::extractValue(uint64_t Type, uint64_t Contents, 850a34c753fSRafael Auler uint64_t PC) { 8514308c742SNathan Sidwell switch (Arch) { 8524308c742SNathan Sidwell default: 8534308c742SNathan Sidwell llvm_unreachable("Unsupported architecture"); 8544308c742SNathan Sidwell case Triple::aarch64: 855a34c753fSRafael Auler return extractValueAArch64(Type, Contents, PC); 8564308c742SNathan Sidwell case Triple::riscv64: 857f8730293SJob Noorman return extractValueRISCV(Type, Contents, PC); 8584308c742SNathan Sidwell case Triple::x86_64: 859a34c753fSRafael Auler return extractValueX86(Type, Contents, PC); 860a34c753fSRafael Auler } 8614308c742SNathan Sidwell } 862a34c753fSRafael Auler 863a34c753fSRafael Auler bool Relocation::isGOT(uint64_t Type) { 8644308c742SNathan Sidwell switch (Arch) { 8654308c742SNathan Sidwell default: 8664308c742SNathan Sidwell llvm_unreachable("Unsupported architecture"); 8674308c742SNathan Sidwell case Triple::aarch64: 868a34c753fSRafael Auler return isGOTAArch64(Type); 8694308c742SNathan Sidwell case Triple::riscv64: 870f8730293SJob Noorman return isGOTRISCV(Type); 8714308c742SNathan Sidwell case Triple::x86_64: 872a34c753fSRafael Auler return isGOTX86(Type); 873a34c753fSRafael Auler } 8744308c742SNathan Sidwell } 875a34c753fSRafael Auler 87618176426SMaksim Panchenko bool Relocation::isX86GOTPCRELX(uint64_t Type) { 87718176426SMaksim Panchenko if (Arch != Triple::x86_64) 87818176426SMaksim Panchenko return false; 87918176426SMaksim Panchenko return Type == ELF::R_X86_64_GOTPCRELX || Type == ELF::R_X86_64_REX_GOTPCRELX; 88018176426SMaksim Panchenko } 88118176426SMaksim Panchenko 882853e126cSRafael Auler bool Relocation::isX86GOTPC64(uint64_t Type) { 883853e126cSRafael Auler if (Arch != Triple::x86_64) 884853e126cSRafael Auler return false; 885853e126cSRafael Auler return Type == ELF::R_X86_64_GOTPC64; 886853e126cSRafael Auler } 887853e126cSRafael Auler 888228970f6Sspupyrev bool Relocation::isNone(uint64_t Type) { return Type == getNone(); } 889a34c753fSRafael Auler 890a34c753fSRafael Auler bool Relocation::isRelative(uint64_t Type) { 8914308c742SNathan Sidwell switch (Arch) { 8924308c742SNathan Sidwell default: 8934308c742SNathan Sidwell llvm_unreachable("Unsupported architecture"); 8944308c742SNathan Sidwell case Triple::aarch64: 895a34c753fSRafael Auler return Type == ELF::R_AARCH64_RELATIVE; 8964308c742SNathan Sidwell case Triple::riscv64: 897f8730293SJob Noorman return Type == ELF::R_RISCV_RELATIVE; 8984308c742SNathan Sidwell case Triple::x86_64: 899a34c753fSRafael Auler return Type == ELF::R_X86_64_RELATIVE; 900a34c753fSRafael Auler } 9014308c742SNathan Sidwell } 902a34c753fSRafael Auler 903a34c753fSRafael Auler bool Relocation::isIRelative(uint64_t Type) { 9044308c742SNathan Sidwell switch (Arch) { 9054308c742SNathan Sidwell default: 9064308c742SNathan Sidwell llvm_unreachable("Unsupported architecture"); 9074308c742SNathan Sidwell case Triple::aarch64: 908a34c753fSRafael Auler return Type == ELF::R_AARCH64_IRELATIVE; 9094308c742SNathan Sidwell case Triple::riscv64: 910f8730293SJob Noorman llvm_unreachable("not implemented"); 9114308c742SNathan Sidwell case Triple::x86_64: 912a34c753fSRafael Auler return Type == ELF::R_X86_64_IRELATIVE; 913a34c753fSRafael Auler } 9144308c742SNathan Sidwell } 915a34c753fSRafael Auler 916a34c753fSRafael Auler bool Relocation::isTLS(uint64_t Type) { 9174308c742SNathan Sidwell switch (Arch) { 9184308c742SNathan Sidwell default: 9194308c742SNathan Sidwell llvm_unreachable("Unsupported architecture"); 9204308c742SNathan Sidwell case Triple::aarch64: 921a34c753fSRafael Auler return isTLSAArch64(Type); 9224308c742SNathan Sidwell case Triple::riscv64: 923f8730293SJob Noorman return isTLSRISCV(Type); 9244308c742SNathan Sidwell case Triple::x86_64: 925a34c753fSRafael Auler return isTLSX86(Type); 926a34c753fSRafael Auler } 9274308c742SNathan Sidwell } 928a34c753fSRafael Auler 929ff5e2babSJob Noorman bool Relocation::isInstructionReference(uint64_t Type) { 930ff5e2babSJob Noorman if (Arch != Triple::riscv64) 931ff5e2babSJob Noorman return false; 932ff5e2babSJob Noorman 933ff5e2babSJob Noorman switch (Type) { 934ff5e2babSJob Noorman default: 935ff5e2babSJob Noorman return false; 936ff5e2babSJob Noorman case ELF::R_RISCV_PCREL_LO12_I: 937ff5e2babSJob Noorman case ELF::R_RISCV_PCREL_LO12_S: 938ff5e2babSJob Noorman return true; 939ff5e2babSJob Noorman } 940ff5e2babSJob Noorman } 941ff5e2babSJob Noorman 942228970f6Sspupyrev uint64_t Relocation::getNone() { 9434308c742SNathan Sidwell switch (Arch) { 9444308c742SNathan Sidwell default: 9454308c742SNathan Sidwell llvm_unreachable("Unsupported architecture"); 9464308c742SNathan Sidwell case Triple::aarch64: 947228970f6Sspupyrev return ELF::R_AARCH64_NONE; 9484308c742SNathan Sidwell case Triple::riscv64: 949f8730293SJob Noorman return ELF::R_RISCV_NONE; 9504308c742SNathan Sidwell case Triple::x86_64: 951228970f6Sspupyrev return ELF::R_X86_64_NONE; 952a34c753fSRafael Auler } 9534308c742SNathan Sidwell } 954a34c753fSRafael Auler 955a34c753fSRafael Auler uint64_t Relocation::getPC32() { 9564308c742SNathan Sidwell switch (Arch) { 9574308c742SNathan Sidwell default: 9584308c742SNathan Sidwell llvm_unreachable("Unsupported architecture"); 9594308c742SNathan Sidwell case Triple::aarch64: 960a34c753fSRafael Auler return ELF::R_AARCH64_PREL32; 9614308c742SNathan Sidwell case Triple::riscv64: 962f8730293SJob Noorman return ELF::R_RISCV_32_PCREL; 9634308c742SNathan Sidwell case Triple::x86_64: 964a34c753fSRafael Auler return ELF::R_X86_64_PC32; 965a34c753fSRafael Auler } 9664308c742SNathan Sidwell } 967a34c753fSRafael Auler 968a34c753fSRafael Auler uint64_t Relocation::getPC64() { 9694308c742SNathan Sidwell switch (Arch) { 9704308c742SNathan Sidwell default: 9714308c742SNathan Sidwell llvm_unreachable("Unsupported architecture"); 9724308c742SNathan Sidwell case Triple::aarch64: 973a34c753fSRafael Auler return ELF::R_AARCH64_PREL64; 9744308c742SNathan Sidwell case Triple::riscv64: 975f8730293SJob Noorman llvm_unreachable("not implemented"); 9764308c742SNathan Sidwell case Triple::x86_64: 977a34c753fSRafael Auler return ELF::R_X86_64_PC64; 978a34c753fSRafael Auler } 9794308c742SNathan Sidwell } 980a34c753fSRafael Auler 981228970f6Sspupyrev bool Relocation::isPCRelative(uint64_t Type) { 9824308c742SNathan Sidwell switch (Arch) { 9834308c742SNathan Sidwell default: 9844308c742SNathan Sidwell llvm_unreachable("Unsupported architecture"); 9854308c742SNathan Sidwell case Triple::aarch64: 986228970f6Sspupyrev return isPCRelativeAArch64(Type); 9874308c742SNathan Sidwell case Triple::riscv64: 988f8730293SJob Noorman return isPCRelativeRISCV(Type); 9894308c742SNathan Sidwell case Triple::x86_64: 990228970f6Sspupyrev return isPCRelativeX86(Type); 991228970f6Sspupyrev } 9924308c742SNathan Sidwell } 993228970f6Sspupyrev 994b0d1f87bSVladislav Khmelevsky uint64_t Relocation::getAbs64() { 9954308c742SNathan Sidwell switch (Arch) { 9964308c742SNathan Sidwell default: 9974308c742SNathan Sidwell llvm_unreachable("Unsupported architecture"); 9984308c742SNathan Sidwell case Triple::aarch64: 999b0d1f87bSVladislav Khmelevsky return ELF::R_AARCH64_ABS64; 10004308c742SNathan Sidwell case Triple::riscv64: 1001cd7f1714SJob Noorman return ELF::R_RISCV_64; 10024308c742SNathan Sidwell case Triple::x86_64: 1003b0d1f87bSVladislav Khmelevsky return ELF::R_X86_64_64; 1004b0d1f87bSVladislav Khmelevsky } 10054308c742SNathan Sidwell } 1006b0d1f87bSVladislav Khmelevsky 1007f9bf9f92SVladislav Khmelevsky uint64_t Relocation::getRelative() { 10084308c742SNathan Sidwell switch (Arch) { 10094308c742SNathan Sidwell default: 10104308c742SNathan Sidwell llvm_unreachable("Unsupported architecture"); 10114308c742SNathan Sidwell case Triple::aarch64: 1012f9bf9f92SVladislav Khmelevsky return ELF::R_AARCH64_RELATIVE; 10134308c742SNathan Sidwell case Triple::riscv64: 10144308c742SNathan Sidwell llvm_unreachable("not implemented"); 10154308c742SNathan Sidwell case Triple::x86_64: 1016f9bf9f92SVladislav Khmelevsky return ELF::R_X86_64_RELATIVE; 1017f9bf9f92SVladislav Khmelevsky } 10184308c742SNathan Sidwell } 1019f9bf9f92SVladislav Khmelevsky 1020a34c753fSRafael Auler size_t Relocation::emit(MCStreamer *Streamer) const { 1021a34c753fSRafael Auler const size_t Size = getSizeForType(Type); 1022b4bb6211SJob Noorman const auto *Value = createExpr(Streamer); 1023b4bb6211SJob Noorman Streamer->emitValue(Value, Size); 1024b4bb6211SJob Noorman return Size; 1025a34c753fSRafael Auler } 1026b4bb6211SJob Noorman 1027b4bb6211SJob Noorman const MCExpr *Relocation::createExpr(MCStreamer *Streamer) const { 1028b4bb6211SJob Noorman MCContext &Ctx = Streamer->getContext(); 1029b4bb6211SJob Noorman const MCExpr *Value = nullptr; 1030b4bb6211SJob Noorman 1031b4bb6211SJob Noorman if (Symbol && Addend) { 1032b4bb6211SJob Noorman Value = MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Symbol, Ctx), 1033b4bb6211SJob Noorman MCConstantExpr::create(Addend, Ctx), Ctx); 1034b4bb6211SJob Noorman } else if (Symbol) { 1035b4bb6211SJob Noorman Value = MCSymbolRefExpr::create(Symbol, Ctx); 1036a34c753fSRafael Auler } else { 1037a34c753fSRafael Auler Value = MCConstantExpr::create(Addend, Ctx); 1038a34c753fSRafael Auler } 1039b4bb6211SJob Noorman 1040b4bb6211SJob Noorman if (isPCRelative(Type)) { 1041b4bb6211SJob Noorman MCSymbol *TempLabel = Ctx.createNamedTempSymbol(); 1042b4bb6211SJob Noorman Streamer->emitLabel(TempLabel); 104340c2e0faSMaksim Panchenko Value = MCBinaryExpr::createSub( 104440c2e0faSMaksim Panchenko Value, MCSymbolRefExpr::create(TempLabel, Ctx), Ctx); 1045a34c753fSRafael Auler } 1046a34c753fSRafael Auler 1047b4bb6211SJob Noorman return Value; 1048a34c753fSRafael Auler } 1049a34c753fSRafael Auler 1050b4bb6211SJob Noorman const MCExpr *Relocation::createExpr(MCStreamer *Streamer, 1051b4bb6211SJob Noorman const MCExpr *RetainedValue) const { 1052b4bb6211SJob Noorman const auto *Value = createExpr(Streamer); 1053b4bb6211SJob Noorman 1054b4bb6211SJob Noorman if (RetainedValue) { 1055b4bb6211SJob Noorman Value = MCBinaryExpr::create(getComposeOpcodeFor(Type), RetainedValue, 1056b4bb6211SJob Noorman Value, Streamer->getContext()); 1057b4bb6211SJob Noorman } 1058b4bb6211SJob Noorman 1059b4bb6211SJob Noorman return Value; 1060b4bb6211SJob Noorman } 1061b4bb6211SJob Noorman 1062b4bb6211SJob Noorman MCBinaryExpr::Opcode Relocation::getComposeOpcodeFor(uint64_t Type) { 1063b410d24aSJob Noorman assert(Arch == Triple::riscv64 && "only implemented for RISC-V"); 1064b410d24aSJob Noorman 1065b410d24aSJob Noorman switch (Type) { 1066b410d24aSJob Noorman default: 1067b4bb6211SJob Noorman llvm_unreachable("not implemented"); 1068b410d24aSJob Noorman case ELF::R_RISCV_ADD32: 1069b410d24aSJob Noorman return MCBinaryExpr::Add; 1070b410d24aSJob Noorman case ELF::R_RISCV_SUB32: 1071b410d24aSJob Noorman return MCBinaryExpr::Sub; 1072b410d24aSJob Noorman } 1073a34c753fSRafael Auler } 1074a34c753fSRafael Auler 1075a34c753fSRafael Auler void Relocation::print(raw_ostream &OS) const { 10764308c742SNathan Sidwell switch (Arch) { 10774308c742SNathan Sidwell default: 10784308c742SNathan Sidwell OS << "RType:" << Twine::utohexstr(Type); 10794308c742SNathan Sidwell break; 10804308c742SNathan Sidwell 10814308c742SNathan Sidwell case Triple::aarch64: 108267e733d3SNathan Sidwell static const char *const AArch64RelocNames[] = { 108367e733d3SNathan Sidwell #define ELF_RELOC(name, value) #name, 108467e733d3SNathan Sidwell #include "llvm/BinaryFormat/ELFRelocs/AArch64.def" 108567e733d3SNathan Sidwell #undef ELF_RELOC 108667e733d3SNathan Sidwell }; 108767e733d3SNathan Sidwell assert(Type < ArrayRef(AArch64RelocNames).size()); 1088a34c753fSRafael Auler OS << AArch64RelocNames[Type]; 10894308c742SNathan Sidwell break; 10904308c742SNathan Sidwell 10914308c742SNathan Sidwell case Triple::riscv64: 1092f8730293SJob Noorman // RISC-V relocations are not sequentially numbered so we cannot use an 1093f8730293SJob Noorman // array 1094f8730293SJob Noorman switch (Type) { 1095f8730293SJob Noorman default: 1096f8730293SJob Noorman llvm_unreachable("illegal RISC-V relocation"); 1097f8730293SJob Noorman #define ELF_RELOC(name, value) \ 1098f8730293SJob Noorman case value: \ 1099f8730293SJob Noorman OS << #name; \ 1100f8730293SJob Noorman break; 1101f8730293SJob Noorman #include "llvm/BinaryFormat/ELFRelocs/RISCV.def" 110267e733d3SNathan Sidwell #undef ELF_RELOC 1103f8730293SJob Noorman } 11044308c742SNathan Sidwell break; 11054308c742SNathan Sidwell 11064308c742SNathan Sidwell case Triple::x86_64: 110767e733d3SNathan Sidwell static const char *const X86RelocNames[] = { 110867e733d3SNathan Sidwell #define ELF_RELOC(name, value) #name, 110967e733d3SNathan Sidwell #include "llvm/BinaryFormat/ELFRelocs/x86_64.def" 111067e733d3SNathan Sidwell #undef ELF_RELOC 111167e733d3SNathan Sidwell }; 111267e733d3SNathan Sidwell assert(Type < ArrayRef(X86RelocNames).size()); 1113a34c753fSRafael Auler OS << X86RelocNames[Type]; 11144308c742SNathan Sidwell break; 11154308c742SNathan Sidwell } 1116a34c753fSRafael Auler OS << ", 0x" << Twine::utohexstr(Offset); 1117a34c753fSRafael Auler if (Symbol) { 1118a34c753fSRafael Auler OS << ", " << Symbol->getName(); 1119a34c753fSRafael Auler } 1120a34c753fSRafael Auler if (int64_t(Addend) < 0) 1121a34c753fSRafael Auler OS << ", -0x" << Twine::utohexstr(-int64_t(Addend)); 1122a34c753fSRafael Auler else 1123a34c753fSRafael Auler OS << ", 0x" << Twine::utohexstr(Addend); 1124a34c753fSRafael Auler OS << ", 0x" << Twine::utohexstr(Value); 1125a34c753fSRafael Auler } 1126