xref: /llvm-project/bolt/lib/Core/Relocation.cpp (revision 4a4045f7408120a638be22672c52ae7e99644998)
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