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 
23a34c753fSRafael Auler Triple::ArchType Relocation::Arch;
24a34c753fSRafael Auler 
25a34c753fSRafael Auler namespace {
26a34c753fSRafael Auler 
isSupportedX86(uint64_t Type)27a34c753fSRafael Auler bool isSupportedX86(uint64_t Type) {
28a34c753fSRafael Auler   switch (Type) {
29a34c753fSRafael Auler   default:
30a34c753fSRafael Auler     return false;
31a34c753fSRafael Auler   case ELF::R_X86_64_8:
32a34c753fSRafael Auler   case ELF::R_X86_64_16:
33a34c753fSRafael Auler   case ELF::R_X86_64_32:
34a34c753fSRafael Auler   case ELF::R_X86_64_32S:
35a34c753fSRafael Auler   case ELF::R_X86_64_64:
36a34c753fSRafael Auler   case ELF::R_X86_64_PC8:
37a34c753fSRafael Auler   case ELF::R_X86_64_PC32:
38a34c753fSRafael Auler   case ELF::R_X86_64_PC64:
39a34c753fSRafael Auler   case ELF::R_X86_64_PLT32:
40a34c753fSRafael Auler   case ELF::R_X86_64_GOTPCREL:
41a34c753fSRafael Auler   case ELF::R_X86_64_GOTTPOFF:
42a34c753fSRafael Auler   case ELF::R_X86_64_TPOFF32:
43a34c753fSRafael Auler   case ELF::R_X86_64_GOTPCRELX:
44a34c753fSRafael Auler   case ELF::R_X86_64_REX_GOTPCRELX:
45a34c753fSRafael Auler     return true;
46a34c753fSRafael Auler   }
47a34c753fSRafael Auler }
48a34c753fSRafael Auler 
isSupportedAArch64(uint64_t Type)49a34c753fSRafael Auler bool isSupportedAArch64(uint64_t Type) {
50a34c753fSRafael Auler   switch (Type) {
51a34c753fSRafael Auler   default:
52a34c753fSRafael Auler     return false;
53a34c753fSRafael Auler   case ELF::R_AARCH64_CALL26:
54a34c753fSRafael Auler   case ELF::R_AARCH64_JUMP26:
55a34c753fSRafael Auler   case ELF::R_AARCH64_TSTBR14:
56a34c753fSRafael Auler   case ELF::R_AARCH64_CONDBR19:
57a34c753fSRafael Auler   case ELF::R_AARCH64_ADR_PREL_LO21:
58a34c753fSRafael Auler   case ELF::R_AARCH64_ADR_PREL_PG_HI21:
59a34c753fSRafael Auler   case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC:
60a34c753fSRafael Auler   case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
61a34c753fSRafael Auler   case ELF::R_AARCH64_ADD_ABS_LO12_NC:
62a34c753fSRafael Auler   case ELF::R_AARCH64_LDST128_ABS_LO12_NC:
63a34c753fSRafael Auler   case ELF::R_AARCH64_LDST32_ABS_LO12_NC:
64a34c753fSRafael Auler   case ELF::R_AARCH64_LDST16_ABS_LO12_NC:
65a34c753fSRafael Auler   case ELF::R_AARCH64_LDST8_ABS_LO12_NC:
66a34c753fSRafael Auler   case ELF::R_AARCH64_ADR_GOT_PAGE:
67a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADR_PREL21:
68a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
69a34c753fSRafael Auler   case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
70a34c753fSRafael Auler   case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12:
71a34c753fSRafael Auler   case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
72a34c753fSRafael Auler   case ELF::R_AARCH64_LD64_GOT_LO12_NC:
73a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_LD64_LO12:
74a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADD_LO12:
75a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_CALL:
76a34c753fSRafael Auler   case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
7748e894a5SAlexey Moksyakov   case ELF::R_AARCH64_PREL16:
78a34c753fSRafael Auler   case ELF::R_AARCH64_PREL32:
7948e894a5SAlexey Moksyakov   case ELF::R_AARCH64_PREL64:
80172deb75SVladislav Khmelevsky   case ELF::R_AARCH64_ABS16:
81172deb75SVladislav Khmelevsky   case ELF::R_AARCH64_ABS32:
82a34c753fSRafael Auler   case ELF::R_AARCH64_ABS64:
83a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G0:
84a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G0_NC:
85a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G1:
86a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G1_NC:
87a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G2:
88a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G2_NC:
89a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G3:
90a34c753fSRafael Auler     return true;
91a34c753fSRafael Auler   }
92a34c753fSRafael Auler }
93a34c753fSRafael Auler 
getSizeForTypeX86(uint64_t Type)94a34c753fSRafael Auler size_t getSizeForTypeX86(uint64_t Type) {
95a34c753fSRafael Auler   switch (Type) {
96a34c753fSRafael Auler   default:
97eb9f4eb6SAmir Ayupov     errs() << object::getELFRelocationTypeName(ELF::EM_X86_64, Type) << '\n';
98a34c753fSRafael Auler     llvm_unreachable("unsupported relocation type");
99a34c753fSRafael Auler   case ELF::R_X86_64_8:
100a34c753fSRafael Auler   case ELF::R_X86_64_PC8:
101a34c753fSRafael Auler     return 1;
102a34c753fSRafael Auler   case ELF::R_X86_64_16:
103a34c753fSRafael Auler     return 2;
104a34c753fSRafael Auler   case ELF::R_X86_64_PLT32:
105a34c753fSRafael Auler   case ELF::R_X86_64_PC32:
106a34c753fSRafael Auler   case ELF::R_X86_64_32S:
107a34c753fSRafael Auler   case ELF::R_X86_64_32:
108a34c753fSRafael Auler   case ELF::R_X86_64_GOTPCREL:
109a34c753fSRafael Auler   case ELF::R_X86_64_GOTTPOFF:
110a34c753fSRafael Auler   case ELF::R_X86_64_TPOFF32:
111a34c753fSRafael Auler   case ELF::R_X86_64_GOTPCRELX:
112a34c753fSRafael Auler   case ELF::R_X86_64_REX_GOTPCRELX:
113a34c753fSRafael Auler     return 4;
114a34c753fSRafael Auler   case ELF::R_X86_64_PC64:
115a34c753fSRafael Auler   case ELF::R_X86_64_64:
116a34c753fSRafael Auler     return 8;
117a34c753fSRafael Auler   }
118a34c753fSRafael Auler }
119a34c753fSRafael Auler 
getSizeForTypeAArch64(uint64_t Type)120a34c753fSRafael Auler size_t getSizeForTypeAArch64(uint64_t Type) {
121a34c753fSRafael Auler   switch (Type) {
122a34c753fSRafael Auler   default:
123eb9f4eb6SAmir Ayupov     errs() << object::getELFRelocationTypeName(ELF::EM_AARCH64, Type) << '\n';
124a34c753fSRafael Auler     llvm_unreachable("unsupported relocation type");
125172deb75SVladislav Khmelevsky   case ELF::R_AARCH64_ABS16:
12648e894a5SAlexey Moksyakov   case ELF::R_AARCH64_PREL16:
127172deb75SVladislav Khmelevsky     return 2;
128a34c753fSRafael Auler   case ELF::R_AARCH64_CALL26:
129a34c753fSRafael Auler   case ELF::R_AARCH64_JUMP26:
130a34c753fSRafael Auler   case ELF::R_AARCH64_TSTBR14:
131a34c753fSRafael Auler   case ELF::R_AARCH64_CONDBR19:
132a34c753fSRafael Auler   case ELF::R_AARCH64_ADR_PREL_LO21:
133a34c753fSRafael Auler   case ELF::R_AARCH64_ADR_PREL_PG_HI21:
134a34c753fSRafael Auler   case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC:
135a34c753fSRafael Auler   case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
136a34c753fSRafael Auler   case ELF::R_AARCH64_ADD_ABS_LO12_NC:
137a34c753fSRafael Auler   case ELF::R_AARCH64_LDST128_ABS_LO12_NC:
138a34c753fSRafael Auler   case ELF::R_AARCH64_LDST32_ABS_LO12_NC:
139a34c753fSRafael Auler   case ELF::R_AARCH64_LDST16_ABS_LO12_NC:
140a34c753fSRafael Auler   case ELF::R_AARCH64_LDST8_ABS_LO12_NC:
141a34c753fSRafael Auler   case ELF::R_AARCH64_ADR_GOT_PAGE:
142a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADR_PREL21:
143a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
144a34c753fSRafael Auler   case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
145a34c753fSRafael Auler   case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12:
146a34c753fSRafael Auler   case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
147a34c753fSRafael Auler   case ELF::R_AARCH64_LD64_GOT_LO12_NC:
148a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_LD64_LO12:
149a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADD_LO12:
150a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_CALL:
151a34c753fSRafael Auler   case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
152a34c753fSRafael Auler   case ELF::R_AARCH64_PREL32:
153a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G0:
154a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G0_NC:
155a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G1:
156a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G1_NC:
157a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G2:
158a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G2_NC:
159a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G3:
160172deb75SVladislav Khmelevsky   case ELF::R_AARCH64_ABS32:
161a34c753fSRafael Auler     return 4;
162a34c753fSRafael Auler   case ELF::R_AARCH64_ABS64:
16348e894a5SAlexey Moksyakov   case ELF::R_AARCH64_PREL64:
164a34c753fSRafael Auler     return 8;
165a34c753fSRafael Auler   }
166a34c753fSRafael Auler }
167a34c753fSRafael Auler 
skipRelocationTypeX86(uint64_t Type)1686e26ffa0SVladislav Khmelevsky bool skipRelocationTypeX86(uint64_t Type) { return Type == ELF::R_X86_64_NONE; }
1696e26ffa0SVladislav Khmelevsky 
skipRelocationTypeAArch64(uint64_t Type)1706e26ffa0SVladislav Khmelevsky bool skipRelocationTypeAArch64(uint64_t Type) {
1716e26ffa0SVladislav Khmelevsky   return Type == ELF::R_AARCH64_NONE || Type == ELF::R_AARCH64_LD_PREL_LO19;
1726e26ffa0SVladislav Khmelevsky }
1736e26ffa0SVladislav Khmelevsky 
skipRelocationProcessX86(uint64_t Type,uint64_t Contents)174a34c753fSRafael Auler bool skipRelocationProcessX86(uint64_t Type, uint64_t Contents) {
175a34c753fSRafael Auler   return false;
176a34c753fSRafael Auler }
177a34c753fSRafael Auler 
skipRelocationProcessAArch64(uint64_t Type,uint64_t Contents)178a34c753fSRafael Auler bool skipRelocationProcessAArch64(uint64_t Type, uint64_t Contents) {
179a34c753fSRafael Auler   auto IsMov = [](uint64_t Contents) -> bool {
180a34c753fSRafael Auler     // The bits 28-23 are 0b100101
1812f98c5feSVladislav Khmelevsky     return (Contents & 0x1f800000) == 0x12800000;
182a34c753fSRafael Auler   };
183a34c753fSRafael Auler 
184a34c753fSRafael Auler   auto IsB = [](uint64_t Contents) -> bool {
185a34c753fSRafael Auler     // The bits 31-26 are 0b000101
1862f98c5feSVladislav Khmelevsky     return (Contents & 0xfc000000) == 0x14000000;
1872f98c5feSVladislav Khmelevsky   };
1882f98c5feSVladislav Khmelevsky 
1892f98c5feSVladislav Khmelevsky   auto IsAdr = [](uint64_t Contents) -> bool {
1902f98c5feSVladislav Khmelevsky     // The bits 31-24 are 0b0xx10000
1912f98c5feSVladislav Khmelevsky     return (Contents & 0x9f000000) == 0x10000000;
192a34c753fSRafael Auler   };
193a34c753fSRafael Auler 
19440c2e0faSMaksim Panchenko   auto IsNop = [](uint64_t Contents) -> bool { return Contents == 0xd503201f; };
195a34c753fSRafael Auler 
196a34c753fSRafael Auler   // The linker might eliminate the instruction and replace it with NOP, ignore
197a34c753fSRafael Auler   if (IsNop(Contents))
198a34c753fSRafael Auler     return true;
199a34c753fSRafael Auler 
200a34c753fSRafael Auler   // The linker might perform TLS relocations relaxations, such as
201a34c753fSRafael Auler   // changed TLS access model (e.g. changed global dynamic model
202a34c753fSRafael Auler   // to initial exec), thus changing the instructions. The static
203a34c753fSRafael Auler   // relocations might be invalid at this point and we might no
204a34c753fSRafael Auler   // need to proccess these relocations anymore.
205a34c753fSRafael Auler   // More information could be found by searching
206a34c753fSRafael Auler   // elfNN_aarch64_tls_relax in bfd
207a34c753fSRafael Auler   switch (Type) {
208a34c753fSRafael Auler   default:
209a34c753fSRafael Auler     break;
210a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_LD64_LO12:
211a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
212a34c753fSRafael Auler   case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
213a34c753fSRafael Auler   case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: {
214a34c753fSRafael Auler     if (IsMov(Contents))
215a34c753fSRafael Auler       return true;
216a34c753fSRafael Auler   }
217a34c753fSRafael Auler   }
218a34c753fSRafael Auler 
2192f98c5feSVladislav Khmelevsky   // The linker might replace load/store instruction with jump and
220a34c753fSRafael Auler   // veneer due to errata 843419
221a34c753fSRafael Auler   // https://documentation-service.arm.com/static/5fa29fddb209f547eebd361d
222a34c753fSRafael Auler   // Thus load/store relocations for these instructions must be ignored
223a34c753fSRafael Auler   // NOTE: We only process GOT and TLS relocations this way since the
224a34c753fSRafael Auler   // addend used in load/store instructions won't change after bolt
225a34c753fSRafael Auler   // (it is important since the instruction in veneer won't have relocation)
226a34c753fSRafael Auler   switch (Type) {
227a34c753fSRafael Auler   default:
228a34c753fSRafael Auler     break;
229a34c753fSRafael Auler   case ELF::R_AARCH64_LD64_GOT_LO12_NC:
230a34c753fSRafael Auler   case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
231a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_LD64_LO12: {
232a34c753fSRafael Auler     if (IsB(Contents))
233a34c753fSRafael Auler       return true;
234a34c753fSRafael Auler   }
235a34c753fSRafael Auler   }
236a34c753fSRafael Auler 
2372f98c5feSVladislav Khmelevsky   // The linker might relax ADRP+ADD or ADRP+LDR sequences to the ADR+NOP
2382f98c5feSVladislav Khmelevsky   switch (Type) {
2392f98c5feSVladislav Khmelevsky   default:
2402f98c5feSVladislav Khmelevsky     break;
2412f98c5feSVladislav Khmelevsky   case ELF::R_AARCH64_ADR_PREL_PG_HI21:
2422f98c5feSVladislav Khmelevsky   case ELF::R_AARCH64_ADD_ABS_LO12_NC:
2432f98c5feSVladislav Khmelevsky   case ELF::R_AARCH64_ADR_GOT_PAGE:
2442f98c5feSVladislav Khmelevsky   case ELF::R_AARCH64_LD64_GOT_LO12_NC:
2452f98c5feSVladislav Khmelevsky     if (IsAdr(Contents))
2462f98c5feSVladislav Khmelevsky       return true;
2472f98c5feSVladislav Khmelevsky   }
2482f98c5feSVladislav Khmelevsky 
249a34c753fSRafael Auler   return false;
250a34c753fSRafael Auler }
251a34c753fSRafael Auler 
adjustValueX86(uint64_t Type,uint64_t Value,uint64_t PC)2524a4045f7SElvina Yakubova uint64_t adjustValueX86(uint64_t Type, uint64_t Value, uint64_t PC) {
2534a4045f7SElvina Yakubova   switch (Type) {
2544a4045f7SElvina Yakubova   default:
2554a4045f7SElvina Yakubova     llvm_unreachable("not supported relocation");
2564a4045f7SElvina Yakubova   case ELF::R_X86_64_32:
2574a4045f7SElvina Yakubova     break;
2584a4045f7SElvina Yakubova   case ELF::R_X86_64_PC32:
2594a4045f7SElvina Yakubova     Value -= PC;
2604a4045f7SElvina Yakubova     break;
2614a4045f7SElvina Yakubova   }
2624a4045f7SElvina Yakubova   return Value;
2634a4045f7SElvina Yakubova }
2644a4045f7SElvina Yakubova 
adjustValueAArch64(uint64_t Type,uint64_t Value,uint64_t PC)2654a4045f7SElvina Yakubova uint64_t adjustValueAArch64(uint64_t Type, uint64_t Value, uint64_t PC) {
2664a4045f7SElvina Yakubova   switch (Type) {
2674a4045f7SElvina Yakubova   default:
2684a4045f7SElvina Yakubova     llvm_unreachable("not supported relocation");
2694a4045f7SElvina Yakubova   case ELF::R_AARCH64_ABS32:
2704a4045f7SElvina Yakubova     break;
27148e894a5SAlexey Moksyakov   case ELF::R_AARCH64_PREL16:
2724a4045f7SElvina Yakubova   case ELF::R_AARCH64_PREL32:
27348e894a5SAlexey Moksyakov   case ELF::R_AARCH64_PREL64:
2744a4045f7SElvina Yakubova     Value -= PC;
2754a4045f7SElvina Yakubova     break;
2764a4045f7SElvina Yakubova   }
2774a4045f7SElvina Yakubova   return Value;
2784a4045f7SElvina Yakubova }
2794a4045f7SElvina Yakubova 
extractValueX86(uint64_t Type,uint64_t Contents,uint64_t PC)280a34c753fSRafael Auler uint64_t extractValueX86(uint64_t Type, uint64_t Contents, uint64_t PC) {
281a34c753fSRafael Auler   if (Type == ELF::R_X86_64_32S)
2824101aa13SMaksim Panchenko     return SignExtend64<32>(Contents);
2834101aa13SMaksim Panchenko   if (Relocation::isPCRelative(Type))
2844101aa13SMaksim Panchenko     return SignExtend64(Contents, 8 * Relocation::getSizeForType(Type));
285a34c753fSRafael Auler   return Contents;
286a34c753fSRafael Auler }
287a34c753fSRafael Auler 
extractValueAArch64(uint64_t Type,uint64_t Contents,uint64_t PC)288a34c753fSRafael Auler uint64_t extractValueAArch64(uint64_t Type, uint64_t Contents, uint64_t PC) {
289a34c753fSRafael Auler   switch (Type) {
290a34c753fSRafael Auler   default:
291eb9f4eb6SAmir Ayupov     errs() << object::getELFRelocationTypeName(ELF::EM_AARCH64, Type) << '\n';
292a34c753fSRafael Auler     llvm_unreachable("unsupported relocation type");
293172deb75SVladislav Khmelevsky   case ELF::R_AARCH64_ABS16:
294172deb75SVladislav Khmelevsky   case ELF::R_AARCH64_ABS32:
295a34c753fSRafael Auler   case ELF::R_AARCH64_ABS64:
296a34c753fSRafael Auler     return Contents;
29748e894a5SAlexey Moksyakov   case ELF::R_AARCH64_PREL16:
29848e894a5SAlexey Moksyakov     return static_cast<int64_t>(PC) + SignExtend64<16>(Contents & 0xffff);
299a34c753fSRafael Auler   case ELF::R_AARCH64_PREL32:
300a34c753fSRafael Auler     return static_cast<int64_t>(PC) + SignExtend64<32>(Contents & 0xffffffff);
30148e894a5SAlexey Moksyakov   case ELF::R_AARCH64_PREL64:
30248e894a5SAlexey Moksyakov     return static_cast<int64_t>(PC) + Contents;
303a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_CALL:
304a34c753fSRafael Auler   case ELF::R_AARCH64_JUMP26:
305a34c753fSRafael Auler   case ELF::R_AARCH64_CALL26:
306a34c753fSRafael Auler     // Immediate goes in bits 25:0 of B and BL.
307a34c753fSRafael Auler     Contents &= ~0xfffffffffc000000ULL;
308a34c753fSRafael Auler     return static_cast<int64_t>(PC) + SignExtend64<28>(Contents << 2);
309a34c753fSRafael Auler   case ELF::R_AARCH64_TSTBR14:
310a34c753fSRafael Auler     // Immediate:15:2 goes in bits 18:5 of TBZ, TBNZ
311a34c753fSRafael Auler     Contents &= ~0xfffffffffff8001fULL;
312a34c753fSRafael Auler     return static_cast<int64_t>(PC) + SignExtend64<16>(Contents >> 3);
313a34c753fSRafael Auler   case ELF::R_AARCH64_CONDBR19:
314a34c753fSRafael Auler     // Immediate:20:2 goes in bits 23:5 of Bcc, CBZ, CBNZ
315a34c753fSRafael Auler     Contents &= ~0xffffffffff00001fULL;
316a34c753fSRafael Auler     return static_cast<int64_t>(PC) + SignExtend64<21>(Contents >> 3);
317a34c753fSRafael Auler   case ELF::R_AARCH64_ADR_GOT_PAGE:
318a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADR_PREL21:
319a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
320a34c753fSRafael Auler   case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
321a34c753fSRafael Auler   case ELF::R_AARCH64_ADR_PREL_LO21:
322a34c753fSRafael Auler   case ELF::R_AARCH64_ADR_PREL_PG_HI21:
323a34c753fSRafael Auler   case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC: {
324a34c753fSRafael Auler     // Bits 32:12 of Symbol address goes in bits 30:29 + 23:5 of ADRP
325a34c753fSRafael Auler     // and ADR instructions
326a34c753fSRafael Auler     bool IsAdr = !!(((Contents >> 31) & 0x1) == 0);
327a34c753fSRafael Auler     Contents &= ~0xffffffff9f00001fUll;
328a34c753fSRafael Auler     uint64_t LowBits = (Contents >> 29) & 0x3;
329a34c753fSRafael Auler     uint64_t HighBits = (Contents >> 5) & 0x7ffff;
330a34c753fSRafael Auler     Contents = LowBits | (HighBits << 2);
331a34c753fSRafael Auler     if (IsAdr)
332a34c753fSRafael Auler       return static_cast<int64_t>(PC) + SignExtend64<21>(Contents);
333a34c753fSRafael Auler 
334a34c753fSRafael Auler     // ADRP instruction
335a34c753fSRafael Auler     Contents = static_cast<int64_t>(PC) + SignExtend64<33>(Contents << 12);
336a34c753fSRafael Auler     Contents &= ~0xfffUll;
337a34c753fSRafael Auler     return Contents;
338a34c753fSRafael Auler   }
339a34c753fSRafael Auler   case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
340a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_LD64_LO12:
341a34c753fSRafael Auler   case ELF::R_AARCH64_LD64_GOT_LO12_NC:
342a34c753fSRafael Auler   case ELF::R_AARCH64_LDST64_ABS_LO12_NC: {
343a34c753fSRafael Auler     // Immediate goes in bits 21:10 of LD/ST instruction, taken
344a34c753fSRafael Auler     // from bits 11:3 of Symbol address
345a34c753fSRafael Auler     Contents &= ~0xffffffffffc003ffU;
346a34c753fSRafael Auler     return Contents >> (10 - 3);
347a34c753fSRafael Auler   }
348a34c753fSRafael Auler   case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12:
349a34c753fSRafael Auler   case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
350a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADD_LO12:
351a34c753fSRafael Auler   case ELF::R_AARCH64_ADD_ABS_LO12_NC: {
352a34c753fSRafael Auler     // Immediate goes in bits 21:10 of ADD instruction
353a34c753fSRafael Auler     Contents &= ~0xffffffffffc003ffU;
354a34c753fSRafael Auler     return Contents >> (10 - 0);
355a34c753fSRafael Auler   }
356a34c753fSRafael Auler   case ELF::R_AARCH64_LDST128_ABS_LO12_NC: {
357a34c753fSRafael Auler     // Immediate goes in bits 21:10 of ADD instruction, taken
358a34c753fSRafael Auler     // from bits 11:4 of Symbol address
359a34c753fSRafael Auler     Contents &= ~0xffffffffffc003ffU;
360a34c753fSRafael Auler     return Contents >> (10 - 4);
361a34c753fSRafael Auler   }
362a34c753fSRafael Auler   case ELF::R_AARCH64_LDST32_ABS_LO12_NC: {
363a34c753fSRafael Auler     // Immediate goes in bits 21:10 of ADD instruction, taken
364a34c753fSRafael Auler     // from bits 11:2 of Symbol address
365a34c753fSRafael Auler     Contents &= ~0xffffffffffc003ffU;
366a34c753fSRafael Auler     return Contents >> (10 - 2);
367a34c753fSRafael Auler   }
368a34c753fSRafael Auler   case ELF::R_AARCH64_LDST16_ABS_LO12_NC: {
369a34c753fSRafael Auler     // Immediate goes in bits 21:10 of ADD instruction, taken
370a34c753fSRafael Auler     // from bits 11:1 of Symbol address
371a34c753fSRafael Auler     Contents &= ~0xffffffffffc003ffU;
372a34c753fSRafael Auler     return Contents >> (10 - 1);
373a34c753fSRafael Auler   }
374a34c753fSRafael Auler   case ELF::R_AARCH64_LDST8_ABS_LO12_NC: {
375a34c753fSRafael Auler     // Immediate goes in bits 21:10 of ADD instruction, taken
376a34c753fSRafael Auler     // from bits 11:0 of Symbol address
377a34c753fSRafael Auler     Contents &= ~0xffffffffffc003ffU;
378a34c753fSRafael Auler     return Contents >> (10 - 0);
379a34c753fSRafael Auler   }
380a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G3:
381a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G2_NC:
382a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G2:
383a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G1_NC:
384a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G1:
385a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G0_NC:
386a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G0:
387a34c753fSRafael Auler     // The shift goest in bits 22:21 of MOV* instructions
388a34c753fSRafael Auler     uint8_t Shift = (Contents >> 21) & 0x3;
389a34c753fSRafael Auler     // Immediate goes in bits 20:5
390a34c753fSRafael Auler     Contents = (Contents >> 5) & 0xffff;
391a34c753fSRafael Auler     return Contents << (16 * Shift);
392a34c753fSRafael Auler   }
393a34c753fSRafael Auler }
394a34c753fSRafael Auler 
isGOTX86(uint64_t Type)395a34c753fSRafael Auler bool isGOTX86(uint64_t Type) {
396a34c753fSRafael Auler   switch (Type) {
397a34c753fSRafael Auler   default:
398a34c753fSRafael Auler     return false;
399a34c753fSRafael Auler   case ELF::R_X86_64_GOT32:
400a34c753fSRafael Auler   case ELF::R_X86_64_GOTPCREL:
401a34c753fSRafael Auler   case ELF::R_X86_64_GOTTPOFF:
402a34c753fSRafael Auler   case ELF::R_X86_64_GOTOFF64:
403a34c753fSRafael Auler   case ELF::R_X86_64_GOTPC32:
404a34c753fSRafael Auler   case ELF::R_X86_64_GOT64:
405a34c753fSRafael Auler   case ELF::R_X86_64_GOTPCREL64:
406a34c753fSRafael Auler   case ELF::R_X86_64_GOTPC64:
407a34c753fSRafael Auler   case ELF::R_X86_64_GOTPLT64:
408a34c753fSRafael Auler   case ELF::R_X86_64_GOTPC32_TLSDESC:
409a34c753fSRafael Auler   case ELF::R_X86_64_GOTPCRELX:
410a34c753fSRafael Auler   case ELF::R_X86_64_REX_GOTPCRELX:
411a34c753fSRafael Auler     return true;
412a34c753fSRafael Auler   }
413a34c753fSRafael Auler }
414a34c753fSRafael Auler 
isGOTAArch64(uint64_t Type)415a34c753fSRafael Auler bool isGOTAArch64(uint64_t Type) {
416a34c753fSRafael Auler   switch (Type) {
417a34c753fSRafael Auler   default:
418a34c753fSRafael Auler     return false;
419a34c753fSRafael Auler   case ELF::R_AARCH64_ADR_GOT_PAGE:
420a34c753fSRafael Auler   case ELF::R_AARCH64_LD64_GOT_LO12_NC:
421a34c753fSRafael Auler   case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
422a34c753fSRafael Auler   case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
423a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADR_PREL21:
424a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
425a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_LD64_LO12:
426a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADD_LO12:
427a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_CALL:
428a34c753fSRafael Auler     return true;
429a34c753fSRafael Auler   }
430a34c753fSRafael Auler }
431a34c753fSRafael Auler 
isTLSX86(uint64_t Type)432a34c753fSRafael Auler bool isTLSX86(uint64_t Type) {
433a34c753fSRafael Auler   switch (Type) {
434a34c753fSRafael Auler   default:
435a34c753fSRafael Auler     return false;
436a34c753fSRafael Auler   case ELF::R_X86_64_TPOFF32:
437a34c753fSRafael Auler   case ELF::R_X86_64_TPOFF64:
438a34c753fSRafael Auler   case ELF::R_X86_64_GOTTPOFF:
439a34c753fSRafael Auler     return true;
440a34c753fSRafael Auler   }
441a34c753fSRafael Auler }
442a34c753fSRafael Auler 
isTLSAArch64(uint64_t Type)443a34c753fSRafael Auler bool isTLSAArch64(uint64_t Type) {
444a34c753fSRafael Auler   switch (Type) {
445a34c753fSRafael Auler   default:
446a34c753fSRafael Auler     return false;
447a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADR_PREL21:
448a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
449a34c753fSRafael Auler   case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
450a34c753fSRafael Auler   case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12:
451a34c753fSRafael Auler   case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
452a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_LD64_LO12:
453a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADD_LO12:
454a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_CALL:
455a34c753fSRafael Auler   case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
456a34c753fSRafael Auler     return true;
457a34c753fSRafael Auler   }
458a34c753fSRafael Auler }
459a34c753fSRafael Auler 
isPCRelativeX86(uint64_t Type)460a34c753fSRafael Auler bool isPCRelativeX86(uint64_t Type) {
461a34c753fSRafael Auler   switch (Type) {
462a34c753fSRafael Auler   default:
463a34c753fSRafael Auler     llvm_unreachable("Unknown relocation type");
464a34c753fSRafael Auler   case ELF::R_X86_64_64:
465a34c753fSRafael Auler   case ELF::R_X86_64_32:
466a34c753fSRafael Auler   case ELF::R_X86_64_32S:
467a34c753fSRafael Auler   case ELF::R_X86_64_16:
468a34c753fSRafael Auler   case ELF::R_X86_64_8:
469a34c753fSRafael Auler   case ELF::R_X86_64_TPOFF32:
470a34c753fSRafael Auler     return false;
471a34c753fSRafael Auler   case ELF::R_X86_64_PC8:
472a34c753fSRafael Auler   case ELF::R_X86_64_PC32:
473a34c753fSRafael Auler   case ELF::R_X86_64_PC64:
474a34c753fSRafael Auler   case ELF::R_X86_64_GOTPCREL:
475a34c753fSRafael Auler   case ELF::R_X86_64_PLT32:
4764101aa13SMaksim Panchenko   case ELF::R_X86_64_GOTOFF64:
4774101aa13SMaksim Panchenko   case ELF::R_X86_64_GOTPC32:
478a34c753fSRafael Auler   case ELF::R_X86_64_GOTTPOFF:
479a34c753fSRafael Auler   case ELF::R_X86_64_GOTPCRELX:
480a34c753fSRafael Auler   case ELF::R_X86_64_REX_GOTPCRELX:
481a34c753fSRafael Auler     return true;
482a34c753fSRafael Auler   }
483a34c753fSRafael Auler }
484a34c753fSRafael Auler 
isPCRelativeAArch64(uint64_t Type)485a34c753fSRafael Auler bool isPCRelativeAArch64(uint64_t Type) {
486a34c753fSRafael Auler   switch (Type) {
487a34c753fSRafael Auler   default:
488a34c753fSRafael Auler     llvm_unreachable("Unknown relocation type");
489172deb75SVladislav Khmelevsky   case ELF::R_AARCH64_ABS16:
490172deb75SVladislav Khmelevsky   case ELF::R_AARCH64_ABS32:
491a34c753fSRafael Auler   case ELF::R_AARCH64_ABS64:
492a34c753fSRafael Auler   case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
493a34c753fSRafael Auler   case ELF::R_AARCH64_ADD_ABS_LO12_NC:
494a34c753fSRafael Auler   case ELF::R_AARCH64_LDST128_ABS_LO12_NC:
495a34c753fSRafael Auler   case ELF::R_AARCH64_LDST32_ABS_LO12_NC:
496a34c753fSRafael Auler   case ELF::R_AARCH64_LDST16_ABS_LO12_NC:
497a34c753fSRafael Auler   case ELF::R_AARCH64_LDST8_ABS_LO12_NC:
498a34c753fSRafael Auler   case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
499a34c753fSRafael Auler   case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12:
500a34c753fSRafael Auler   case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
501a34c753fSRafael Auler   case ELF::R_AARCH64_LD64_GOT_LO12_NC:
502a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_LD64_LO12:
503a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADD_LO12:
504a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G0:
505a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G0_NC:
506a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G1:
507a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G1_NC:
508a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G2:
509a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G2_NC:
510a34c753fSRafael Auler   case ELF::R_AARCH64_MOVW_UABS_G3:
511a34c753fSRafael Auler     return false;
512a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_CALL:
513a34c753fSRafael Auler   case ELF::R_AARCH64_CALL26:
514a34c753fSRafael Auler   case ELF::R_AARCH64_JUMP26:
515a34c753fSRafael Auler   case ELF::R_AARCH64_TSTBR14:
516a34c753fSRafael Auler   case ELF::R_AARCH64_CONDBR19:
517a34c753fSRafael Auler   case ELF::R_AARCH64_ADR_PREL_LO21:
518a34c753fSRafael Auler   case ELF::R_AARCH64_ADR_PREL_PG_HI21:
519a34c753fSRafael Auler   case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC:
520a34c753fSRafael Auler   case ELF::R_AARCH64_ADR_GOT_PAGE:
521a34c753fSRafael Auler   case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
522a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADR_PREL21:
523a34c753fSRafael Auler   case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
52448e894a5SAlexey Moksyakov   case ELF::R_AARCH64_PREL16:
525a34c753fSRafael Auler   case ELF::R_AARCH64_PREL32:
52648e894a5SAlexey Moksyakov   case ELF::R_AARCH64_PREL64:
527a34c753fSRafael Auler     return true;
528a34c753fSRafael Auler   }
529a34c753fSRafael Auler }
530a34c753fSRafael Auler 
531a34c753fSRafael Auler } // end anonymous namespace
532a34c753fSRafael Auler 
isSupported(uint64_t Type)533a34c753fSRafael Auler bool Relocation::isSupported(uint64_t Type) {
534a34c753fSRafael Auler   if (Arch == Triple::aarch64)
535a34c753fSRafael Auler     return isSupportedAArch64(Type);
536a34c753fSRafael Auler   return isSupportedX86(Type);
537a34c753fSRafael Auler }
538a34c753fSRafael Auler 
getSizeForType(uint64_t Type)539a34c753fSRafael Auler size_t Relocation::getSizeForType(uint64_t Type) {
540a34c753fSRafael Auler   if (Arch == Triple::aarch64)
541a34c753fSRafael Auler     return getSizeForTypeAArch64(Type);
542a34c753fSRafael Auler   return getSizeForTypeX86(Type);
543a34c753fSRafael Auler }
544a34c753fSRafael Auler 
skipRelocationType(uint64_t Type)5456e26ffa0SVladislav Khmelevsky bool Relocation::skipRelocationType(uint64_t Type) {
5466e26ffa0SVladislav Khmelevsky   if (Arch == Triple::aarch64)
5476e26ffa0SVladislav Khmelevsky     return skipRelocationTypeAArch64(Type);
5486e26ffa0SVladislav Khmelevsky   return skipRelocationTypeX86(Type);
5496e26ffa0SVladislav Khmelevsky }
5506e26ffa0SVladislav Khmelevsky 
skipRelocationProcess(uint64_t Type,uint64_t Contents)551a34c753fSRafael Auler bool Relocation::skipRelocationProcess(uint64_t Type, uint64_t Contents) {
552a34c753fSRafael Auler   if (Arch == Triple::aarch64)
553a34c753fSRafael Auler     return skipRelocationProcessAArch64(Type, Contents);
554a34c753fSRafael Auler   return skipRelocationProcessX86(Type, Contents);
555a34c753fSRafael Auler }
556a34c753fSRafael Auler 
adjustValue(uint64_t Type,uint64_t Value,uint64_t PC)5574a4045f7SElvina Yakubova uint64_t Relocation::adjustValue(uint64_t Type, uint64_t Value,
5584a4045f7SElvina Yakubova                                  uint64_t PC) {
5594a4045f7SElvina Yakubova   if (Arch == Triple::aarch64)
5604a4045f7SElvina Yakubova     return adjustValueAArch64(Type, Value, PC);
5614a4045f7SElvina Yakubova   return adjustValueX86(Type, Value, PC);
5624a4045f7SElvina Yakubova }
5634a4045f7SElvina Yakubova 
extractValue(uint64_t Type,uint64_t Contents,uint64_t PC)564a34c753fSRafael Auler uint64_t Relocation::extractValue(uint64_t Type, uint64_t Contents,
565a34c753fSRafael Auler                                   uint64_t PC) {
566a34c753fSRafael Auler   if (Arch == Triple::aarch64)
567a34c753fSRafael Auler     return extractValueAArch64(Type, Contents, PC);
568a34c753fSRafael Auler   return extractValueX86(Type, Contents, PC);
569a34c753fSRafael Auler }
570a34c753fSRafael Auler 
isGOT(uint64_t Type)571a34c753fSRafael Auler bool Relocation::isGOT(uint64_t Type) {
572a34c753fSRafael Auler   if (Arch == Triple::aarch64)
573a34c753fSRafael Auler     return isGOTAArch64(Type);
574a34c753fSRafael Auler   return isGOTX86(Type);
575a34c753fSRafael Auler }
576a34c753fSRafael Auler 
isX86GOTPCRELX(uint64_t Type)57718176426SMaksim Panchenko bool Relocation::isX86GOTPCRELX(uint64_t Type) {
57818176426SMaksim Panchenko   if (Arch != Triple::x86_64)
57918176426SMaksim Panchenko     return false;
58018176426SMaksim Panchenko   return Type == ELF::R_X86_64_GOTPCRELX || Type == ELF::R_X86_64_REX_GOTPCRELX;
58118176426SMaksim Panchenko }
58218176426SMaksim Panchenko 
isNone(uint64_t Type)583*228970f6Sspupyrev bool Relocation::isNone(uint64_t Type) { return Type == getNone(); }
584a34c753fSRafael Auler 
isRelative(uint64_t Type)585a34c753fSRafael Auler bool Relocation::isRelative(uint64_t Type) {
586a34c753fSRafael Auler   if (Arch == Triple::aarch64)
587a34c753fSRafael Auler     return Type == ELF::R_AARCH64_RELATIVE;
588a34c753fSRafael Auler   return Type == ELF::R_X86_64_RELATIVE;
589a34c753fSRafael Auler }
590a34c753fSRafael Auler 
isIRelative(uint64_t Type)591a34c753fSRafael Auler bool Relocation::isIRelative(uint64_t Type) {
592a34c753fSRafael Auler   if (Arch == Triple::aarch64)
593a34c753fSRafael Auler     return Type == ELF::R_AARCH64_IRELATIVE;
594a34c753fSRafael Auler   return Type == ELF::R_X86_64_IRELATIVE;
595a34c753fSRafael Auler }
596a34c753fSRafael Auler 
isTLS(uint64_t Type)597a34c753fSRafael Auler bool Relocation::isTLS(uint64_t Type) {
598a34c753fSRafael Auler   if (Arch == Triple::aarch64)
599a34c753fSRafael Auler     return isTLSAArch64(Type);
600a34c753fSRafael Auler   return isTLSX86(Type);
601a34c753fSRafael Auler }
602a34c753fSRafael Auler 
getNone()603*228970f6Sspupyrev uint64_t Relocation::getNone() {
604a34c753fSRafael Auler   if (Arch == Triple::aarch64)
605*228970f6Sspupyrev     return ELF::R_AARCH64_NONE;
606*228970f6Sspupyrev   return ELF::R_X86_64_NONE;
607a34c753fSRafael Auler }
608a34c753fSRafael Auler 
getPC32()609a34c753fSRafael Auler uint64_t Relocation::getPC32() {
610a34c753fSRafael Auler   if (Arch == Triple::aarch64)
611a34c753fSRafael Auler     return ELF::R_AARCH64_PREL32;
612a34c753fSRafael Auler   return ELF::R_X86_64_PC32;
613a34c753fSRafael Auler }
614a34c753fSRafael Auler 
getPC64()615a34c753fSRafael Auler uint64_t Relocation::getPC64() {
616a34c753fSRafael Auler   if (Arch == Triple::aarch64)
617a34c753fSRafael Auler     return ELF::R_AARCH64_PREL64;
618a34c753fSRafael Auler   return ELF::R_X86_64_PC64;
619a34c753fSRafael Auler }
620a34c753fSRafael Auler 
isPCRelative(uint64_t Type)621*228970f6Sspupyrev bool Relocation::isPCRelative(uint64_t Type) {
622*228970f6Sspupyrev   if (Arch == Triple::aarch64)
623*228970f6Sspupyrev     return isPCRelativeAArch64(Type);
624*228970f6Sspupyrev   return isPCRelativeX86(Type);
625*228970f6Sspupyrev }
626*228970f6Sspupyrev 
emit(MCStreamer * Streamer) const627a34c753fSRafael Auler size_t Relocation::emit(MCStreamer *Streamer) const {
628a34c753fSRafael Auler   const size_t Size = getSizeForType(Type);
629a34c753fSRafael Auler   MCContext &Ctx = Streamer->getContext();
630a34c753fSRafael Auler   if (isPCRelative(Type)) {
631a34c753fSRafael Auler     MCSymbol *TempLabel = Ctx.createNamedTempSymbol();
632a34c753fSRafael Auler     Streamer->emitLabel(TempLabel);
633a34c753fSRafael Auler     const MCExpr *Value = nullptr;
634a34c753fSRafael Auler     if (Symbol) {
635a34c753fSRafael Auler       Value = MCSymbolRefExpr::create(Symbol, Ctx);
636a34c753fSRafael Auler       if (Addend) {
63740c2e0faSMaksim Panchenko         Value = MCBinaryExpr::createAdd(
63840c2e0faSMaksim Panchenko             Value, MCConstantExpr::create(Addend, Ctx), Ctx);
639a34c753fSRafael Auler       }
640a34c753fSRafael Auler     } else {
641a34c753fSRafael Auler       Value = MCConstantExpr::create(Addend, Ctx);
642a34c753fSRafael Auler     }
64340c2e0faSMaksim Panchenko     Value = MCBinaryExpr::createSub(
64440c2e0faSMaksim Panchenko         Value, MCSymbolRefExpr::create(TempLabel, Ctx), Ctx);
645a34c753fSRafael Auler     Streamer->emitValue(Value, Size);
646a34c753fSRafael Auler 
647a34c753fSRafael Auler     return Size;
648a34c753fSRafael Auler   }
649a34c753fSRafael Auler 
650a34c753fSRafael Auler   if (Symbol && Addend) {
65140c2e0faSMaksim Panchenko     auto Value =
65240c2e0faSMaksim Panchenko         MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Symbol, Ctx),
65340c2e0faSMaksim Panchenko                                 MCConstantExpr::create(Addend, Ctx), Ctx);
654a34c753fSRafael Auler     Streamer->emitValue(Value, Size);
655a34c753fSRafael Auler   } else if (Symbol) {
656a34c753fSRafael Auler     Streamer->emitSymbolValue(Symbol, Size);
657a34c753fSRafael Auler   } else {
658a34c753fSRafael Auler     Streamer->emitIntValue(Addend, Size);
659a34c753fSRafael Auler   }
660a34c753fSRafael Auler 
661a34c753fSRafael Auler   return Size;
662a34c753fSRafael Auler }
663a34c753fSRafael Auler 
664a34c753fSRafael Auler #define ELF_RELOC(name, value) #name,
665a34c753fSRafael Auler 
print(raw_ostream & OS) const666a34c753fSRafael Auler void Relocation::print(raw_ostream &OS) const {
667a34c753fSRafael Auler   static const char *X86RelocNames[] = {
668a34c753fSRafael Auler #include "llvm/BinaryFormat/ELFRelocs/x86_64.def"
669a34c753fSRafael Auler   };
670a34c753fSRafael Auler   static const char *AArch64RelocNames[] = {
671a34c753fSRafael Auler #include "llvm/BinaryFormat/ELFRelocs/AArch64.def"
672a34c753fSRafael Auler   };
673a34c753fSRafael Auler   if (Arch == Triple::aarch64)
674a34c753fSRafael Auler     OS << AArch64RelocNames[Type];
675a34c753fSRafael Auler   else
676a34c753fSRafael Auler     OS << X86RelocNames[Type];
677a34c753fSRafael Auler   OS << ", 0x" << Twine::utohexstr(Offset);
678a34c753fSRafael Auler   if (Symbol) {
679a34c753fSRafael Auler     OS << ", " << Symbol->getName();
680a34c753fSRafael Auler   }
681a34c753fSRafael Auler   if (int64_t(Addend) < 0)
682a34c753fSRafael Auler     OS << ", -0x" << Twine::utohexstr(-int64_t(Addend));
683a34c753fSRafael Auler   else
684a34c753fSRafael Auler     OS << ", 0x" << Twine::utohexstr(Addend);
685a34c753fSRafael Auler   OS << ", 0x" << Twine::utohexstr(Value);
686a34c753fSRafael Auler }
687