1a34c753fSRafael Auler //===--- Relocation.cpp - Interface for 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 // 9a34c753fSRafael Auler //===----------------------------------------------------------------------===// 10a34c753fSRafael Auler 11a34c753fSRafael Auler #include "bolt/Core/Relocation.h" 12a34c753fSRafael Auler #include "llvm/MC/MCContext.h" 13a34c753fSRafael Auler #include "llvm/MC/MCStreamer.h" 14eb9f4eb6SAmir Ayupov #include "llvm/Object/ELF.h" 15a34c753fSRafael Auler 16a34c753fSRafael Auler using namespace llvm; 17a34c753fSRafael Auler using namespace bolt; 18a34c753fSRafael Auler 19a34c753fSRafael Auler Triple::ArchType Relocation::Arch; 20a34c753fSRafael Auler 21a34c753fSRafael Auler namespace { 22a34c753fSRafael Auler 23a34c753fSRafael Auler bool isSupportedX86(uint64_t Type) { 24a34c753fSRafael Auler switch (Type) { 25a34c753fSRafael Auler default: 26a34c753fSRafael Auler return false; 27a34c753fSRafael Auler case ELF::R_X86_64_8: 28a34c753fSRafael Auler case ELF::R_X86_64_16: 29a34c753fSRafael Auler case ELF::R_X86_64_32: 30a34c753fSRafael Auler case ELF::R_X86_64_32S: 31a34c753fSRafael Auler case ELF::R_X86_64_64: 32a34c753fSRafael Auler case ELF::R_X86_64_PC8: 33a34c753fSRafael Auler case ELF::R_X86_64_PC32: 34a34c753fSRafael Auler case ELF::R_X86_64_PC64: 35a34c753fSRafael Auler case ELF::R_X86_64_PLT32: 36a34c753fSRafael Auler case ELF::R_X86_64_GOTPCREL: 37a34c753fSRafael Auler case ELF::R_X86_64_GOTTPOFF: 38a34c753fSRafael Auler case ELF::R_X86_64_TPOFF32: 39a34c753fSRafael Auler case ELF::R_X86_64_GOTPCRELX: 40a34c753fSRafael Auler case ELF::R_X86_64_REX_GOTPCRELX: 41a34c753fSRafael Auler return true; 42a34c753fSRafael Auler } 43a34c753fSRafael Auler } 44a34c753fSRafael Auler 45a34c753fSRafael Auler bool isSupportedAArch64(uint64_t Type) { 46a34c753fSRafael Auler switch (Type) { 47a34c753fSRafael Auler default: 48a34c753fSRafael Auler return false; 49a34c753fSRafael Auler case ELF::R_AARCH64_CALL26: 50a34c753fSRafael Auler case ELF::R_AARCH64_JUMP26: 51a34c753fSRafael Auler case ELF::R_AARCH64_TSTBR14: 52a34c753fSRafael Auler case ELF::R_AARCH64_CONDBR19: 53a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_LO21: 54a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_PG_HI21: 55a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC: 56a34c753fSRafael Auler case ELF::R_AARCH64_LDST64_ABS_LO12_NC: 57a34c753fSRafael Auler case ELF::R_AARCH64_ADD_ABS_LO12_NC: 58a34c753fSRafael Auler case ELF::R_AARCH64_LDST128_ABS_LO12_NC: 59a34c753fSRafael Auler case ELF::R_AARCH64_LDST32_ABS_LO12_NC: 60a34c753fSRafael Auler case ELF::R_AARCH64_LDST16_ABS_LO12_NC: 61a34c753fSRafael Auler case ELF::R_AARCH64_LDST8_ABS_LO12_NC: 62a34c753fSRafael Auler case ELF::R_AARCH64_ADR_GOT_PAGE: 63a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PREL21: 64a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: 65a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 66a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: 67a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: 68a34c753fSRafael Auler case ELF::R_AARCH64_LD64_GOT_LO12_NC: 69a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_LD64_LO12: 70a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADD_LO12: 71a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_CALL: 72a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: 73a34c753fSRafael Auler case ELF::R_AARCH64_PREL32: 74172deb75SVladislav Khmelevsky case ELF::R_AARCH64_ABS16: 75172deb75SVladislav Khmelevsky case ELF::R_AARCH64_ABS32: 76a34c753fSRafael Auler case ELF::R_AARCH64_ABS64: 77a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G0: 78a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G0_NC: 79a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G1: 80a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G1_NC: 81a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G2: 82a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G2_NC: 83a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G3: 84a34c753fSRafael Auler return true; 85a34c753fSRafael Auler } 86a34c753fSRafael Auler } 87a34c753fSRafael Auler 88a34c753fSRafael Auler size_t getSizeForTypeX86(uint64_t Type) { 89a34c753fSRafael Auler switch (Type) { 90a34c753fSRafael Auler default: 91eb9f4eb6SAmir Ayupov errs() << object::getELFRelocationTypeName(ELF::EM_X86_64, Type) << '\n'; 92a34c753fSRafael Auler llvm_unreachable("unsupported relocation type"); 93a34c753fSRafael Auler case ELF::R_X86_64_8: 94a34c753fSRafael Auler case ELF::R_X86_64_PC8: 95a34c753fSRafael Auler return 1; 96a34c753fSRafael Auler case ELF::R_X86_64_16: 97a34c753fSRafael Auler return 2; 98a34c753fSRafael Auler case ELF::R_X86_64_PLT32: 99a34c753fSRafael Auler case ELF::R_X86_64_PC32: 100a34c753fSRafael Auler case ELF::R_X86_64_32S: 101a34c753fSRafael Auler case ELF::R_X86_64_32: 102a34c753fSRafael Auler case ELF::R_X86_64_GOTPCREL: 103a34c753fSRafael Auler case ELF::R_X86_64_GOTTPOFF: 104a34c753fSRafael Auler case ELF::R_X86_64_TPOFF32: 105a34c753fSRafael Auler case ELF::R_X86_64_GOTPCRELX: 106a34c753fSRafael Auler case ELF::R_X86_64_REX_GOTPCRELX: 107a34c753fSRafael Auler return 4; 108a34c753fSRafael Auler case ELF::R_X86_64_PC64: 109a34c753fSRafael Auler case ELF::R_X86_64_64: 110a34c753fSRafael Auler return 8; 111a34c753fSRafael Auler } 112a34c753fSRafael Auler } 113a34c753fSRafael Auler 114a34c753fSRafael Auler size_t getSizeForTypeAArch64(uint64_t Type) { 115a34c753fSRafael Auler switch (Type) { 116a34c753fSRafael Auler default: 117eb9f4eb6SAmir Ayupov errs() << object::getELFRelocationTypeName(ELF::EM_AARCH64, Type) << '\n'; 118a34c753fSRafael Auler llvm_unreachable("unsupported relocation type"); 119172deb75SVladislav Khmelevsky case ELF::R_AARCH64_ABS16: 120172deb75SVladislav Khmelevsky return 2; 121a34c753fSRafael Auler case ELF::R_AARCH64_CALL26: 122a34c753fSRafael Auler case ELF::R_AARCH64_JUMP26: 123a34c753fSRafael Auler case ELF::R_AARCH64_TSTBR14: 124a34c753fSRafael Auler case ELF::R_AARCH64_CONDBR19: 125a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_LO21: 126a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_PG_HI21: 127a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC: 128a34c753fSRafael Auler case ELF::R_AARCH64_LDST64_ABS_LO12_NC: 129a34c753fSRafael Auler case ELF::R_AARCH64_ADD_ABS_LO12_NC: 130a34c753fSRafael Auler case ELF::R_AARCH64_LDST128_ABS_LO12_NC: 131a34c753fSRafael Auler case ELF::R_AARCH64_LDST32_ABS_LO12_NC: 132a34c753fSRafael Auler case ELF::R_AARCH64_LDST16_ABS_LO12_NC: 133a34c753fSRafael Auler case ELF::R_AARCH64_LDST8_ABS_LO12_NC: 134a34c753fSRafael Auler case ELF::R_AARCH64_ADR_GOT_PAGE: 135a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PREL21: 136a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: 137a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 138a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: 139a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: 140a34c753fSRafael Auler case ELF::R_AARCH64_LD64_GOT_LO12_NC: 141a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_LD64_LO12: 142a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADD_LO12: 143a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_CALL: 144a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: 145a34c753fSRafael Auler case ELF::R_AARCH64_PREL32: 146a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G0: 147a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G0_NC: 148a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G1: 149a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G1_NC: 150a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G2: 151a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G2_NC: 152a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G3: 153172deb75SVladislav Khmelevsky case ELF::R_AARCH64_ABS32: 154a34c753fSRafael Auler return 4; 155a34c753fSRafael Auler case ELF::R_AARCH64_ABS64: 156a34c753fSRafael Auler return 8; 157a34c753fSRafael Auler } 158a34c753fSRafael Auler } 159a34c753fSRafael Auler 160a34c753fSRafael Auler bool skipRelocationProcessX86(uint64_t Type, uint64_t Contents) { 161a34c753fSRafael Auler return false; 162a34c753fSRafael Auler } 163a34c753fSRafael Auler 164a34c753fSRafael Auler bool skipRelocationProcessAArch64(uint64_t Type, uint64_t Contents) { 165a34c753fSRafael Auler auto IsMov = [](uint64_t Contents) -> bool { 166a34c753fSRafael Auler // The bits 28-23 are 0b100101 167a34c753fSRafael Auler if ((Contents & 0x1f800000) == 0x12800000) 168a34c753fSRafael Auler return true; 169a34c753fSRafael Auler return false; 170a34c753fSRafael Auler }; 171a34c753fSRafael Auler 172a34c753fSRafael Auler auto IsB = [](uint64_t Contents) -> bool { 173a34c753fSRafael Auler // The bits 31-26 are 0b000101 174a34c753fSRafael Auler if ((Contents & 0xfc000000) == 0x14000000) 175a34c753fSRafael Auler return true; 176a34c753fSRafael Auler return false; 177a34c753fSRafael Auler }; 178a34c753fSRafael Auler 17940c2e0faSMaksim Panchenko auto IsNop = [](uint64_t Contents) -> bool { return Contents == 0xd503201f; }; 180a34c753fSRafael Auler 181a34c753fSRafael Auler // The linker might eliminate the instruction and replace it with NOP, ignore 182a34c753fSRafael Auler if (IsNop(Contents)) 183a34c753fSRafael Auler return true; 184a34c753fSRafael Auler 185a34c753fSRafael Auler // The linker might perform TLS relocations relaxations, such as 186a34c753fSRafael Auler // changed TLS access model (e.g. changed global dynamic model 187a34c753fSRafael Auler // to initial exec), thus changing the instructions. The static 188a34c753fSRafael Auler // relocations might be invalid at this point and we might no 189a34c753fSRafael Auler // need to proccess these relocations anymore. 190a34c753fSRafael Auler // More information could be found by searching 191a34c753fSRafael Auler // elfNN_aarch64_tls_relax in bfd 192a34c753fSRafael Auler switch (Type) { 193a34c753fSRafael Auler default: 194a34c753fSRafael Auler break; 195a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_LD64_LO12: 196a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: 197a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 198a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: { 199a34c753fSRafael Auler if (IsMov(Contents)) 200a34c753fSRafael Auler return true; 201a34c753fSRafael Auler } 202a34c753fSRafael Auler } 203a34c753fSRafael Auler 204a34c753fSRafael Auler // The ld might replace load/store instruction with jump and 205a34c753fSRafael Auler // veneer due to errata 843419 206a34c753fSRafael Auler // https://documentation-service.arm.com/static/5fa29fddb209f547eebd361d 207a34c753fSRafael Auler // Thus load/store relocations for these instructions must be ignored 208a34c753fSRafael Auler // NOTE: We only process GOT and TLS relocations this way since the 209a34c753fSRafael Auler // addend used in load/store instructions won't change after bolt 210a34c753fSRafael Auler // (it is important since the instruction in veneer won't have relocation) 211a34c753fSRafael Auler switch (Type) { 212a34c753fSRafael Auler default: 213a34c753fSRafael Auler break; 214a34c753fSRafael Auler case ELF::R_AARCH64_LD64_GOT_LO12_NC: 215a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 216a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_LD64_LO12: { 217a34c753fSRafael Auler if (IsB(Contents)) 218a34c753fSRafael Auler return true; 219a34c753fSRafael Auler } 220a34c753fSRafael Auler } 221a34c753fSRafael Auler 222a34c753fSRafael Auler return false; 223a34c753fSRafael Auler } 224a34c753fSRafael Auler 225*4a4045f7SElvina Yakubova uint64_t adjustValueX86(uint64_t Type, uint64_t Value, uint64_t PC) { 226*4a4045f7SElvina Yakubova switch (Type) { 227*4a4045f7SElvina Yakubova default: 228*4a4045f7SElvina Yakubova llvm_unreachable("not supported relocation"); 229*4a4045f7SElvina Yakubova case ELF::R_X86_64_32: 230*4a4045f7SElvina Yakubova break; 231*4a4045f7SElvina Yakubova case ELF::R_X86_64_PC32: 232*4a4045f7SElvina Yakubova Value -= PC; 233*4a4045f7SElvina Yakubova break; 234*4a4045f7SElvina Yakubova } 235*4a4045f7SElvina Yakubova return Value; 236*4a4045f7SElvina Yakubova } 237*4a4045f7SElvina Yakubova 238*4a4045f7SElvina Yakubova uint64_t adjustValueAArch64(uint64_t Type, uint64_t Value, uint64_t PC) { 239*4a4045f7SElvina Yakubova switch (Type) { 240*4a4045f7SElvina Yakubova default: 241*4a4045f7SElvina Yakubova llvm_unreachable("not supported relocation"); 242*4a4045f7SElvina Yakubova case ELF::R_AARCH64_ABS32: 243*4a4045f7SElvina Yakubova break; 244*4a4045f7SElvina Yakubova case ELF::R_AARCH64_PREL32: 245*4a4045f7SElvina Yakubova Value -= PC; 246*4a4045f7SElvina Yakubova break; 247*4a4045f7SElvina Yakubova } 248*4a4045f7SElvina Yakubova return Value; 249*4a4045f7SElvina Yakubova } 250*4a4045f7SElvina Yakubova 251a34c753fSRafael Auler uint64_t extractValueX86(uint64_t Type, uint64_t Contents, uint64_t PC) { 252a34c753fSRafael Auler if (Type == ELF::R_X86_64_32S) 253a34c753fSRafael Auler return SignExtend64<32>(Contents & 0xffffffff); 254a34c753fSRafael Auler return Contents; 255a34c753fSRafael Auler } 256a34c753fSRafael Auler 257a34c753fSRafael Auler uint64_t extractValueAArch64(uint64_t Type, uint64_t Contents, uint64_t PC) { 258a34c753fSRafael Auler switch (Type) { 259a34c753fSRafael Auler default: 260eb9f4eb6SAmir Ayupov errs() << object::getELFRelocationTypeName(ELF::EM_AARCH64, Type) << '\n'; 261a34c753fSRafael Auler llvm_unreachable("unsupported relocation type"); 262172deb75SVladislav Khmelevsky case ELF::R_AARCH64_ABS16: 263172deb75SVladislav Khmelevsky case ELF::R_AARCH64_ABS32: 264a34c753fSRafael Auler case ELF::R_AARCH64_ABS64: 265a34c753fSRafael Auler return Contents; 266a34c753fSRafael Auler case ELF::R_AARCH64_PREL32: 267a34c753fSRafael Auler return static_cast<int64_t>(PC) + SignExtend64<32>(Contents & 0xffffffff); 268a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_CALL: 269a34c753fSRafael Auler case ELF::R_AARCH64_JUMP26: 270a34c753fSRafael Auler case ELF::R_AARCH64_CALL26: 271a34c753fSRafael Auler // Immediate goes in bits 25:0 of B and BL. 272a34c753fSRafael Auler Contents &= ~0xfffffffffc000000ULL; 273a34c753fSRafael Auler return static_cast<int64_t>(PC) + SignExtend64<28>(Contents << 2); 274a34c753fSRafael Auler case ELF::R_AARCH64_TSTBR14: 275a34c753fSRafael Auler // Immediate:15:2 goes in bits 18:5 of TBZ, TBNZ 276a34c753fSRafael Auler Contents &= ~0xfffffffffff8001fULL; 277a34c753fSRafael Auler return static_cast<int64_t>(PC) + SignExtend64<16>(Contents >> 3); 278a34c753fSRafael Auler case ELF::R_AARCH64_CONDBR19: 279a34c753fSRafael Auler // Immediate:20:2 goes in bits 23:5 of Bcc, CBZ, CBNZ 280a34c753fSRafael Auler Contents &= ~0xffffffffff00001fULL; 281a34c753fSRafael Auler return static_cast<int64_t>(PC) + SignExtend64<21>(Contents >> 3); 282a34c753fSRafael Auler case ELF::R_AARCH64_ADR_GOT_PAGE: 283a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PREL21: 284a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: 285a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: 286a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_LO21: 287a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_PG_HI21: 288a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC: { 289a34c753fSRafael Auler // Bits 32:12 of Symbol address goes in bits 30:29 + 23:5 of ADRP 290a34c753fSRafael Auler // and ADR instructions 291a34c753fSRafael Auler bool IsAdr = !!(((Contents >> 31) & 0x1) == 0); 292a34c753fSRafael Auler Contents &= ~0xffffffff9f00001fUll; 293a34c753fSRafael Auler uint64_t LowBits = (Contents >> 29) & 0x3; 294a34c753fSRafael Auler uint64_t HighBits = (Contents >> 5) & 0x7ffff; 295a34c753fSRafael Auler Contents = LowBits | (HighBits << 2); 296a34c753fSRafael Auler if (IsAdr) 297a34c753fSRafael Auler return static_cast<int64_t>(PC) + SignExtend64<21>(Contents); 298a34c753fSRafael Auler 299a34c753fSRafael Auler // ADRP instruction 300a34c753fSRafael Auler Contents = static_cast<int64_t>(PC) + SignExtend64<33>(Contents << 12); 301a34c753fSRafael Auler Contents &= ~0xfffUll; 302a34c753fSRafael Auler return Contents; 303a34c753fSRafael Auler } 304a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 305a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_LD64_LO12: 306a34c753fSRafael Auler case ELF::R_AARCH64_LD64_GOT_LO12_NC: 307a34c753fSRafael Auler case ELF::R_AARCH64_LDST64_ABS_LO12_NC: { 308a34c753fSRafael Auler // Immediate goes in bits 21:10 of LD/ST instruction, taken 309a34c753fSRafael Auler // from bits 11:3 of Symbol address 310a34c753fSRafael Auler Contents &= ~0xffffffffffc003ffU; 311a34c753fSRafael Auler return Contents >> (10 - 3); 312a34c753fSRafael Auler } 313a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: 314a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: 315a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADD_LO12: 316a34c753fSRafael Auler case ELF::R_AARCH64_ADD_ABS_LO12_NC: { 317a34c753fSRafael Auler // Immediate goes in bits 21:10 of ADD instruction 318a34c753fSRafael Auler Contents &= ~0xffffffffffc003ffU; 319a34c753fSRafael Auler return Contents >> (10 - 0); 320a34c753fSRafael Auler } 321a34c753fSRafael Auler case ELF::R_AARCH64_LDST128_ABS_LO12_NC: { 322a34c753fSRafael Auler // Immediate goes in bits 21:10 of ADD instruction, taken 323a34c753fSRafael Auler // from bits 11:4 of Symbol address 324a34c753fSRafael Auler Contents &= ~0xffffffffffc003ffU; 325a34c753fSRafael Auler return Contents >> (10 - 4); 326a34c753fSRafael Auler } 327a34c753fSRafael Auler case ELF::R_AARCH64_LDST32_ABS_LO12_NC: { 328a34c753fSRafael Auler // Immediate goes in bits 21:10 of ADD instruction, taken 329a34c753fSRafael Auler // from bits 11:2 of Symbol address 330a34c753fSRafael Auler Contents &= ~0xffffffffffc003ffU; 331a34c753fSRafael Auler return Contents >> (10 - 2); 332a34c753fSRafael Auler } 333a34c753fSRafael Auler case ELF::R_AARCH64_LDST16_ABS_LO12_NC: { 334a34c753fSRafael Auler // Immediate goes in bits 21:10 of ADD instruction, taken 335a34c753fSRafael Auler // from bits 11:1 of Symbol address 336a34c753fSRafael Auler Contents &= ~0xffffffffffc003ffU; 337a34c753fSRafael Auler return Contents >> (10 - 1); 338a34c753fSRafael Auler } 339a34c753fSRafael Auler case ELF::R_AARCH64_LDST8_ABS_LO12_NC: { 340a34c753fSRafael Auler // Immediate goes in bits 21:10 of ADD instruction, taken 341a34c753fSRafael Auler // from bits 11:0 of Symbol address 342a34c753fSRafael Auler Contents &= ~0xffffffffffc003ffU; 343a34c753fSRafael Auler return Contents >> (10 - 0); 344a34c753fSRafael Auler } 345a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G3: 346a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G2_NC: 347a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G2: 348a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G1_NC: 349a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G1: 350a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G0_NC: 351a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G0: 352a34c753fSRafael Auler // The shift goest in bits 22:21 of MOV* instructions 353a34c753fSRafael Auler uint8_t Shift = (Contents >> 21) & 0x3; 354a34c753fSRafael Auler // Immediate goes in bits 20:5 355a34c753fSRafael Auler Contents = (Contents >> 5) & 0xffff; 356a34c753fSRafael Auler return Contents << (16 * Shift); 357a34c753fSRafael Auler } 358a34c753fSRafael Auler } 359a34c753fSRafael Auler 360a34c753fSRafael Auler bool isGOTX86(uint64_t Type) { 361a34c753fSRafael Auler switch (Type) { 362a34c753fSRafael Auler default: 363a34c753fSRafael Auler return false; 364a34c753fSRafael Auler case ELF::R_X86_64_GOT32: 365a34c753fSRafael Auler case ELF::R_X86_64_GOTPCREL: 366a34c753fSRafael Auler case ELF::R_X86_64_GOTTPOFF: 367a34c753fSRafael Auler case ELF::R_X86_64_GOTOFF64: 368a34c753fSRafael Auler case ELF::R_X86_64_GOTPC32: 369a34c753fSRafael Auler case ELF::R_X86_64_GOT64: 370a34c753fSRafael Auler case ELF::R_X86_64_GOTPCREL64: 371a34c753fSRafael Auler case ELF::R_X86_64_GOTPC64: 372a34c753fSRafael Auler case ELF::R_X86_64_GOTPLT64: 373a34c753fSRafael Auler case ELF::R_X86_64_GOTPC32_TLSDESC: 374a34c753fSRafael Auler case ELF::R_X86_64_GOTPCRELX: 375a34c753fSRafael Auler case ELF::R_X86_64_REX_GOTPCRELX: 376a34c753fSRafael Auler return true; 377a34c753fSRafael Auler } 378a34c753fSRafael Auler } 379a34c753fSRafael Auler 380a34c753fSRafael Auler bool isGOTAArch64(uint64_t Type) { 381a34c753fSRafael Auler switch (Type) { 382a34c753fSRafael Auler default: 383a34c753fSRafael Auler return false; 384a34c753fSRafael Auler case ELF::R_AARCH64_ADR_GOT_PAGE: 385a34c753fSRafael Auler case ELF::R_AARCH64_LD64_GOT_LO12_NC: 386a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 387a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: 388a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PREL21: 389a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: 390a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_LD64_LO12: 391a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADD_LO12: 392a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_CALL: 393a34c753fSRafael Auler return true; 394a34c753fSRafael Auler } 395a34c753fSRafael Auler } 396a34c753fSRafael Auler 397a34c753fSRafael Auler bool isTLSX86(uint64_t Type) { 398a34c753fSRafael Auler switch (Type) { 399a34c753fSRafael Auler default: 400a34c753fSRafael Auler return false; 401a34c753fSRafael Auler case ELF::R_X86_64_TPOFF32: 402a34c753fSRafael Auler case ELF::R_X86_64_TPOFF64: 403a34c753fSRafael Auler case ELF::R_X86_64_GOTTPOFF: 404a34c753fSRafael Auler return true; 405a34c753fSRafael Auler } 406a34c753fSRafael Auler } 407a34c753fSRafael Auler 408a34c753fSRafael Auler bool isTLSAArch64(uint64_t Type) { 409a34c753fSRafael Auler switch (Type) { 410a34c753fSRafael Auler default: 411a34c753fSRafael Auler return false; 412a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PREL21: 413a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: 414a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 415a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: 416a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: 417a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_LD64_LO12: 418a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADD_LO12: 419a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_CALL: 420a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: 421a34c753fSRafael Auler return true; 422a34c753fSRafael Auler } 423a34c753fSRafael Auler } 424a34c753fSRafael Auler 425a34c753fSRafael Auler bool isPCRelativeX86(uint64_t Type) { 426a34c753fSRafael Auler switch (Type) { 427a34c753fSRafael Auler default: 428a34c753fSRafael Auler llvm_unreachable("Unknown relocation type"); 429a34c753fSRafael Auler case ELF::R_X86_64_64: 430a34c753fSRafael Auler case ELF::R_X86_64_32: 431a34c753fSRafael Auler case ELF::R_X86_64_32S: 432a34c753fSRafael Auler case ELF::R_X86_64_16: 433a34c753fSRafael Auler case ELF::R_X86_64_8: 434a34c753fSRafael Auler case ELF::R_X86_64_TPOFF32: 435a34c753fSRafael Auler return false; 436a34c753fSRafael Auler case ELF::R_X86_64_PC8: 437a34c753fSRafael Auler case ELF::R_X86_64_PC32: 438a34c753fSRafael Auler case ELF::R_X86_64_PC64: 439a34c753fSRafael Auler case ELF::R_X86_64_GOTPCREL: 440a34c753fSRafael Auler case ELF::R_X86_64_PLT32: 441a34c753fSRafael Auler case ELF::R_X86_64_GOTTPOFF: 442a34c753fSRafael Auler case ELF::R_X86_64_GOTPCRELX: 443a34c753fSRafael Auler case ELF::R_X86_64_REX_GOTPCRELX: 444a34c753fSRafael Auler return true; 445a34c753fSRafael Auler } 446a34c753fSRafael Auler } 447a34c753fSRafael Auler 448a34c753fSRafael Auler bool isPCRelativeAArch64(uint64_t Type) { 449a34c753fSRafael Auler switch (Type) { 450a34c753fSRafael Auler default: 451a34c753fSRafael Auler llvm_unreachable("Unknown relocation type"); 452172deb75SVladislav Khmelevsky case ELF::R_AARCH64_ABS16: 453172deb75SVladislav Khmelevsky case ELF::R_AARCH64_ABS32: 454a34c753fSRafael Auler case ELF::R_AARCH64_ABS64: 455a34c753fSRafael Auler case ELF::R_AARCH64_LDST64_ABS_LO12_NC: 456a34c753fSRafael Auler case ELF::R_AARCH64_ADD_ABS_LO12_NC: 457a34c753fSRafael Auler case ELF::R_AARCH64_LDST128_ABS_LO12_NC: 458a34c753fSRafael Auler case ELF::R_AARCH64_LDST32_ABS_LO12_NC: 459a34c753fSRafael Auler case ELF::R_AARCH64_LDST16_ABS_LO12_NC: 460a34c753fSRafael Auler case ELF::R_AARCH64_LDST8_ABS_LO12_NC: 461a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 462a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: 463a34c753fSRafael Auler case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: 464a34c753fSRafael Auler case ELF::R_AARCH64_LD64_GOT_LO12_NC: 465a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_LD64_LO12: 466a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADD_LO12: 467a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G0: 468a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G0_NC: 469a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G1: 470a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G1_NC: 471a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G2: 472a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G2_NC: 473a34c753fSRafael Auler case ELF::R_AARCH64_MOVW_UABS_G3: 474a34c753fSRafael Auler return false; 475a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_CALL: 476a34c753fSRafael Auler case ELF::R_AARCH64_CALL26: 477a34c753fSRafael Auler case ELF::R_AARCH64_JUMP26: 478a34c753fSRafael Auler case ELF::R_AARCH64_TSTBR14: 479a34c753fSRafael Auler case ELF::R_AARCH64_CONDBR19: 480a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_LO21: 481a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_PG_HI21: 482a34c753fSRafael Auler case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC: 483a34c753fSRafael Auler case ELF::R_AARCH64_ADR_GOT_PAGE: 484a34c753fSRafael Auler case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: 485a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PREL21: 486a34c753fSRafael Auler case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: 487a34c753fSRafael Auler case ELF::R_AARCH64_PREL32: 488a34c753fSRafael Auler return true; 489a34c753fSRafael Auler } 490a34c753fSRafael Auler } 491a34c753fSRafael Auler 492a34c753fSRafael Auler } // end anonymous namespace 493a34c753fSRafael Auler 494a34c753fSRafael Auler bool Relocation::isSupported(uint64_t Type) { 495a34c753fSRafael Auler if (Arch == Triple::aarch64) 496a34c753fSRafael Auler return isSupportedAArch64(Type); 497a34c753fSRafael Auler return isSupportedX86(Type); 498a34c753fSRafael Auler } 499a34c753fSRafael Auler 500a34c753fSRafael Auler size_t Relocation::getSizeForType(uint64_t Type) { 501a34c753fSRafael Auler if (Arch == Triple::aarch64) 502a34c753fSRafael Auler return getSizeForTypeAArch64(Type); 503a34c753fSRafael Auler return getSizeForTypeX86(Type); 504a34c753fSRafael Auler } 505a34c753fSRafael Auler 506a34c753fSRafael Auler bool Relocation::skipRelocationProcess(uint64_t Type, uint64_t Contents) { 507a34c753fSRafael Auler if (Arch == Triple::aarch64) 508a34c753fSRafael Auler return skipRelocationProcessAArch64(Type, Contents); 509a34c753fSRafael Auler return skipRelocationProcessX86(Type, Contents); 510a34c753fSRafael Auler } 511a34c753fSRafael Auler 512*4a4045f7SElvina Yakubova uint64_t Relocation::adjustValue(uint64_t Type, uint64_t Value, 513*4a4045f7SElvina Yakubova uint64_t PC) { 514*4a4045f7SElvina Yakubova if (Arch == Triple::aarch64) 515*4a4045f7SElvina Yakubova return adjustValueAArch64(Type, Value, PC); 516*4a4045f7SElvina Yakubova return adjustValueX86(Type, Value, PC); 517*4a4045f7SElvina Yakubova } 518*4a4045f7SElvina Yakubova 519a34c753fSRafael Auler uint64_t Relocation::extractValue(uint64_t Type, uint64_t Contents, 520a34c753fSRafael Auler uint64_t PC) { 521a34c753fSRafael Auler if (Arch == Triple::aarch64) 522a34c753fSRafael Auler return extractValueAArch64(Type, Contents, PC); 523a34c753fSRafael Auler return extractValueX86(Type, Contents, PC); 524a34c753fSRafael Auler } 525a34c753fSRafael Auler 526a34c753fSRafael Auler bool Relocation::isGOT(uint64_t Type) { 527a34c753fSRafael Auler if (Arch == Triple::aarch64) 528a34c753fSRafael Auler return isGOTAArch64(Type); 529a34c753fSRafael Auler return isGOTX86(Type); 530a34c753fSRafael Auler } 531a34c753fSRafael Auler 532a34c753fSRafael Auler bool Relocation::isNone(uint64_t Type) { 533a34c753fSRafael Auler if (Arch == Triple::aarch64) 534a34c753fSRafael Auler return Type == ELF::R_AARCH64_NONE; 535a34c753fSRafael Auler return Type == ELF::R_X86_64_NONE; 536a34c753fSRafael Auler } 537a34c753fSRafael Auler 538a34c753fSRafael Auler bool Relocation::isRelative(uint64_t Type) { 539a34c753fSRafael Auler if (Arch == Triple::aarch64) 540a34c753fSRafael Auler return Type == ELF::R_AARCH64_RELATIVE; 541a34c753fSRafael Auler return Type == ELF::R_X86_64_RELATIVE; 542a34c753fSRafael Auler } 543a34c753fSRafael Auler 544a34c753fSRafael Auler bool Relocation::isIRelative(uint64_t Type) { 545a34c753fSRafael Auler if (Arch == Triple::aarch64) 546a34c753fSRafael Auler return Type == ELF::R_AARCH64_IRELATIVE; 547a34c753fSRafael Auler return Type == ELF::R_X86_64_IRELATIVE; 548a34c753fSRafael Auler } 549a34c753fSRafael Auler 550a34c753fSRafael Auler bool Relocation::isTLS(uint64_t Type) { 551a34c753fSRafael Auler if (Arch == Triple::aarch64) 552a34c753fSRafael Auler return isTLSAArch64(Type); 553a34c753fSRafael Auler return isTLSX86(Type); 554a34c753fSRafael Auler } 555a34c753fSRafael Auler 556a34c753fSRafael Auler bool Relocation::isPCRelative(uint64_t Type) { 557a34c753fSRafael Auler if (Arch == Triple::aarch64) 558a34c753fSRafael Auler return isPCRelativeAArch64(Type); 559a34c753fSRafael Auler return isPCRelativeX86(Type); 560a34c753fSRafael Auler } 561a34c753fSRafael Auler 562a34c753fSRafael Auler uint64_t Relocation::getPC32() { 563a34c753fSRafael Auler if (Arch == Triple::aarch64) 564a34c753fSRafael Auler return ELF::R_AARCH64_PREL32; 565a34c753fSRafael Auler return ELF::R_X86_64_PC32; 566a34c753fSRafael Auler } 567a34c753fSRafael Auler 568a34c753fSRafael Auler uint64_t Relocation::getPC64() { 569a34c753fSRafael Auler if (Arch == Triple::aarch64) 570a34c753fSRafael Auler return ELF::R_AARCH64_PREL64; 571a34c753fSRafael Auler return ELF::R_X86_64_PC64; 572a34c753fSRafael Auler } 573a34c753fSRafael Auler 574a34c753fSRafael Auler size_t Relocation::emit(MCStreamer *Streamer) const { 575a34c753fSRafael Auler const size_t Size = getSizeForType(Type); 576a34c753fSRafael Auler MCContext &Ctx = Streamer->getContext(); 577a34c753fSRafael Auler if (isPCRelative(Type)) { 578a34c753fSRafael Auler MCSymbol *TempLabel = Ctx.createNamedTempSymbol(); 579a34c753fSRafael Auler Streamer->emitLabel(TempLabel); 580a34c753fSRafael Auler const MCExpr *Value = nullptr; 581a34c753fSRafael Auler if (Symbol) { 582a34c753fSRafael Auler Value = MCSymbolRefExpr::create(Symbol, Ctx); 583a34c753fSRafael Auler if (Addend) { 58440c2e0faSMaksim Panchenko Value = MCBinaryExpr::createAdd( 58540c2e0faSMaksim Panchenko Value, MCConstantExpr::create(Addend, Ctx), Ctx); 586a34c753fSRafael Auler } 587a34c753fSRafael Auler } else { 588a34c753fSRafael Auler Value = MCConstantExpr::create(Addend, Ctx); 589a34c753fSRafael Auler } 59040c2e0faSMaksim Panchenko Value = MCBinaryExpr::createSub( 59140c2e0faSMaksim Panchenko Value, MCSymbolRefExpr::create(TempLabel, Ctx), Ctx); 592a34c753fSRafael Auler Streamer->emitValue(Value, Size); 593a34c753fSRafael Auler 594a34c753fSRafael Auler return Size; 595a34c753fSRafael Auler } 596a34c753fSRafael Auler 597a34c753fSRafael Auler if (Symbol && Addend) { 59840c2e0faSMaksim Panchenko auto Value = 59940c2e0faSMaksim Panchenko MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Symbol, Ctx), 60040c2e0faSMaksim Panchenko MCConstantExpr::create(Addend, Ctx), Ctx); 601a34c753fSRafael Auler Streamer->emitValue(Value, Size); 602a34c753fSRafael Auler } else if (Symbol) { 603a34c753fSRafael Auler Streamer->emitSymbolValue(Symbol, Size); 604a34c753fSRafael Auler } else { 605a34c753fSRafael Auler Streamer->emitIntValue(Addend, Size); 606a34c753fSRafael Auler } 607a34c753fSRafael Auler 608a34c753fSRafael Auler return Size; 609a34c753fSRafael Auler } 610a34c753fSRafael Auler 611a34c753fSRafael Auler #define ELF_RELOC(name, value) #name, 612a34c753fSRafael Auler 613a34c753fSRafael Auler void Relocation::print(raw_ostream &OS) const { 614a34c753fSRafael Auler static const char *X86RelocNames[] = { 615a34c753fSRafael Auler #include "llvm/BinaryFormat/ELFRelocs/x86_64.def" 616a34c753fSRafael Auler }; 617a34c753fSRafael Auler static const char *AArch64RelocNames[] = { 618a34c753fSRafael Auler #include "llvm/BinaryFormat/ELFRelocs/AArch64.def" 619a34c753fSRafael Auler }; 620a34c753fSRafael Auler if (Arch == Triple::aarch64) 621a34c753fSRafael Auler OS << AArch64RelocNames[Type]; 622a34c753fSRafael Auler else 623a34c753fSRafael Auler OS << X86RelocNames[Type]; 624a34c753fSRafael Auler OS << ", 0x" << Twine::utohexstr(Offset); 625a34c753fSRafael Auler if (Symbol) { 626a34c753fSRafael Auler OS << ", " << Symbol->getName(); 627a34c753fSRafael Auler } 628a34c753fSRafael Auler if (int64_t(Addend) < 0) 629a34c753fSRafael Auler OS << ", -0x" << Twine::utohexstr(-int64_t(Addend)); 630a34c753fSRafael Auler else 631a34c753fSRafael Auler OS << ", 0x" << Twine::utohexstr(Addend); 632a34c753fSRafael Auler OS << ", 0x" << Twine::utohexstr(Value); 633a34c753fSRafael Auler } 634