1 /*
2 Copyright (C) 2015 Volker Krause <vkrause@kde.org>
3
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18 #include "relocationprinter.h"
19
20 #include <elf/elfrelocationentry.h>
21 #include <elf/elfrelocationsection.h>
22 #include <elf/elffile.h>
23 #include <elf/elfheader.h>
24
25 #include <QByteArray>
26
27 #include <elf.h>
28
29 #ifndef R_386_NONE
30 #define R_386_NONE 0
31 #define R_386_32 1
32 #define R_386_PC32 2
33 #define R_386_GOT32 3
34 #define R_386_PLT32 4
35 #define R_386_COPY 5
36 #define R_386_GLOB_DAT 6
37 #define R_386_JMP_SLOT 7
38 #define R_386_RELATIVE 8
39 #define R_386_GOTOFF 9
40 #define R_386_GOTPC 10
41 #endif
42
43 #ifndef R_386_TLS_TPOFF
44 #define R_386_TLS_TPOFF 14
45 #define R_386_TLS_IE 15
46 #define R_386_TLS_GOTIE 16
47 #define R_386_TLS_LE 17
48 #define R_386_TLS_GD 18
49 #define R_386_TLS_LDM 19
50 #endif
51
52 #ifndef R_386_TLS_GD_32
53 #define R_386_TLS_GD_32 24
54 #define R_386_TLS_GD_PUSH 25
55 #define R_386_TLS_GD_CALL 26
56 #define R_386_TLS_GD_POP 27
57 #define R_386_TLS_LDM_32 28
58 #define R_386_TLS_LDM_PUSH 29
59 #define R_386_TLS_LDM_CALL 30
60 #define R_386_TLS_LDM_POP 31
61 #define R_386_TLS_LDO_32 32
62 #define R_386_TLS_IE_32 33
63 #define R_386_TLS_LE_32 34
64 #define R_386_TLS_DTPMOD32 35
65 #define R_386_TLS_DTPOFF32 36
66 #define R_386_TLS_TPOFF32 37
67 #endif
68
69 #ifndef R_386_IRELATIVE
70 #define R_386_IRELATIVE 42
71 #endif
72
73 #ifndef R_ARM_NONE
74 #define R_ARM_NONE 0
75 #define R_ARM_PC24 1
76 #define R_ARM_ABS32 2
77 #define R_ARM_REL32 3
78 #define R_ARM_PC13 4
79 #define R_ARM_ABS16 5
80 #define R_ARM_ABS12 6
81 #define R_ARM_THM_ABS5 7
82 #define R_ARM_ABS8 8
83 #define R_ARM_SBREL32 9
84 #define R_ARM_THM_PC22 10
85 #define R_ARM_THM_PC8 11
86 #define R_ARM_AMP_VCALL9 12
87 #define R_ARM_SWI24 13
88 #define R_ARM_THM_SWI8 14
89 #define R_ARM_XPC25 15
90 #define R_ARM_THM_XPC22 16
91 #define R_ARM_TLS_DTPMOD32 17
92 #define R_ARM_TLS_DTPOFF32 18
93 #define R_ARM_TLS_TPOFF32 19
94 #define R_ARM_COPY 20
95 #define R_ARM_GLOB_DAT 21
96 #define R_ARM_JUMP_SLOT 22
97 #define R_ARM_RELATIVE 23
98 #define R_ARM_GOTOFF 24
99 #define R_ARM_GOTPC 25
100 #define R_ARM_GOT32 26
101 #define R_ARM_PLT32 27
102 #define R_ARM_GNU_VTENTRY 100
103 #define R_ARM_GNU_VTINHERIT 101
104 #define R_ARM_RSBREL32 250
105 #define R_ARM_THM_RPC22 251
106 #define R_ARM_RREL32 252
107 #define R_ARM_RABS32 253
108 #define R_ARM_RPC24 254
109 #define R_ARM_RBASE 255
110 #endif
111
112 #ifndef R_X86_64_PC64
113 #define R_X86_64_PC64 24
114 #define R_X86_64_GOTOFF64 25
115 #define R_X86_64_GOTPC32 26
116 #define R_X86_64_GOT64 27
117 #define R_X86_64_GOTPCREL64 28
118 #define R_X86_64_GOTPC64 29
119 #define R_X86_64_GOTPLT64 30
120 #define R_X86_64_PLTOFF64 31
121 #define R_X86_64_SIZE32 32
122 #define R_X86_64_SIZE64 33
123 #define R_X86_64_GOTPC32_TLSDESC 34
124 #define R_X86_64_TLSDESC_CALL 35
125 #define R_X86_64_TLSDESC 36
126 #endif
127
128 // Fix build on FreeBSD 12, which does not include these ELF relocation
129 // types; they're standard, and were added to FreeBSD 13 in
130 // https://cgit.freebsd.org/src/commit/?id=f7d181543fd96a89b84878ddb2d5ac010fadd9b8
131 #ifndef R_386_32PLT
132 #define R_386_32PLT 11
133 #define R_386_16 20
134 #define R_386_PC16 21
135 #define R_386_8 22
136 #define R_386_PC8 23
137 #define R_386_SIZE32 38
138 #define R_386_TLS_GOTDESC 39
139 #define R_386_TLS_DESC_CALL 40
140 #define R_386_TLS_DESC 41
141 #define R_386_GOT32X 43
142 #define R_X86_64_RELATIVE64 38
143 /* 39 and 40 were BND-related, already decomissioned */
144 #define R_X86_64_GOTPCRELX 41
145 #define R_X86_64_REX_GOTPCRELX 42
146 #endif
147
148 struct RelocType
149 {
150 uint32_t id;
151 const char* label;
152 const char* desc;
153 };
154
155 #define RT(type, desc) { type, #type, desc }
156
157 static const RelocType reloc_types_i386[] {
158 RT(R_386_NONE, "No reloc"),
159 RT(R_386_32, "Direct 32 bit"),
160 RT(R_386_PC32, "PC relative 32 bit"),
161 RT(R_386_GOT32, "32 bit GOT entry"),
162 RT(R_386_PLT32, "32 bit PLT address"),
163 RT(R_386_COPY, "Copy symbol at runtime"),
164 RT(R_386_GLOB_DAT, "Create GOT entry"),
165 RT(R_386_JMP_SLOT, "Create PLT entry"),
166 RT(R_386_RELATIVE, "Adjust by program base"),
167 RT(R_386_GOTOFF, "32 bit offset to GOT"),
168 RT(R_386_GOTPC, "32 bit PC relative offset to GOT"),
169 RT(R_386_32PLT, ""),
170 RT(R_386_TLS_TPOFF, "Offset in static TLS block"),
171 RT(R_386_TLS_IE, "Address of GOT entry for static TLS block offset"),
172 RT(R_386_TLS_GOTIE, "GOT entry for static TLS block offset"),
173 RT(R_386_TLS_LE, "Offset relative to static TLS block"),
174 RT(R_386_TLS_GD, "Direct 32 bit for GNU version of general dynamic thread local data"),
175 RT(R_386_TLS_LDM, "Direct 32 bit for GNU version of local dynamic thread local data in LE code"),
176 RT(R_386_16, ""),
177 RT(R_386_PC16, ""),
178 RT(R_386_8, ""),
179 RT(R_386_PC8, ""),
180 RT(R_386_TLS_GD_32, "Direct 32 bit for general dynamic thread local data"),
181 RT(R_386_TLS_GD_PUSH, "Tag for pushl in GD TLS code"),
182 RT(R_386_TLS_GD_CALL, "Relocation for call to __tls_get_addr()"),
183 RT(R_386_TLS_GD_POP, "Tag for popl in GD TLS code"),
184 RT(R_386_TLS_LDM_32, "Direct 32 bit for local dynamic thread local data in LE code"),
185 RT(R_386_TLS_LDM_PUSH, "Tag for pushl in LDM TLS code"),
186 RT(R_386_TLS_LDM_CALL, "Relocation for call to __tls_get_addr() in LDM code"),
187 RT(R_386_TLS_LDM_POP, "Tag for popl in LDM TLS code"),
188 RT(R_386_TLS_LDO_32, "Offset relative to TLS block"),
189 RT(R_386_TLS_IE_32, "GOT entry for negated static TLS block offset"),
190 RT(R_386_TLS_LE_32, "Negated offset relative to static TLS block"),
191 RT(R_386_TLS_DTPMOD32, "ID of module containing symbol"),
192 RT(R_386_TLS_DTPOFF32, "Offset in TLS block"),
193 RT(R_386_TLS_TPOFF32, "Negated offset in static TLS block"),
194 #ifdef R_386_SIZE32
195 RT(R_386_SIZE32, "32-bit symbol size"),
196 #endif
197 RT(R_386_TLS_GOTDESC, "GOT offset for TLS descriptor."),
198 RT(R_386_TLS_DESC_CALL, "Marker of call through TLS descriptor for relaxation."),
199 RT(R_386_TLS_DESC, "TLS descriptor containing pointer to code and to argument, returning the TLS offset for the symbol."),
200 RT(R_386_IRELATIVE, "Adjust indirectly by program base")
201 };
202
203 static const RelocType reloc_types_arm[] {
204 RT(R_ARM_NONE, "No reloc"),
205 RT(R_ARM_PC24, "Deprecated PC relative 26 bit branch"),
206 RT(R_ARM_ABS32, "Direct 32 bit"),
207 RT(R_ARM_REL32, "PC relative 32 bit"),
208 RT(R_ARM_PC13, "PC13"),
209 RT(R_ARM_ABS16, "Direct 16 bit"),
210 RT(R_ARM_ABS12, "Direct 12 bit"),
211 RT(R_ARM_THM_ABS5, "Direct & 0x7C (LDR, STR)"),
212 RT(R_ARM_ABS8, "Direct 8 bit"),
213 RT(R_ARM_SBREL32, "SBREL32"),
214 RT(R_ARM_THM_PC22, "PC relative 24 bit (Thumb32 BL)"),
215 RT(R_ARM_THM_PC8, "PC relative & 0x3FC (Thumb16 LDR, ADD, ADR)"),
216 RT(R_ARM_AMP_VCALL9, "VCALL9"),
217 #ifndef R_ARM_TLS_DESC
218 RT(R_ARM_SWI24, "Obsolete static relocation"),
219 #else
220 RT(R_ARM_TLS_DESC, "Dynamic relocation"),
221 #endif
222 RT(R_ARM_THM_SWI8, "SWI8"),
223 RT(R_ARM_XPC25, "XPC25"),
224 RT(R_ARM_THM_XPC22, "XPC22 (Thumb)"),
225 RT(R_ARM_TLS_DTPMOD32, "ID of module containing symbol"),
226 RT(R_ARM_TLS_DTPOFF32, "Offset in TLS block"),
227 RT(R_ARM_TLS_TPOFF32, "Offset in static TLS block"),
228 RT(R_ARM_COPY, "Copy symbol at runtime"),
229 RT(R_ARM_GLOB_DAT, "Create GOT entry"),
230 RT(R_ARM_JUMP_SLOT, "Create PLT entry"),
231 RT(R_ARM_RELATIVE, "Adjust by program base"),
232 RT(R_ARM_GOTOFF, "32 bit offset to GOT"),
233 RT(R_ARM_GOTPC, "32 bit PC relative offset to GOT"),
234 RT(R_ARM_GOT32, "32 bit GOT entry"),
235 RT(R_ARM_PLT32, "Deprecated, 32 bit PLT address"),
236 #ifdef __GLIBC_PREREQ
237 #if __GLIBC_PREREQ(2, 18)
238 RT(R_ARM_CALL, "PC relative 24 bit (BL, BLX)"),
239 RT(R_ARM_JUMP24, "PC relative 24 bit (B, BL<cond>)"),
240 RT(R_ARM_THM_JUMP24, "PC relative 24 bit (Thumb32 B.W)"),
241 RT(R_ARM_BASE_ABS, "Adjust by program base"),
242 #endif
243 #endif
244 #ifdef R_ARM_ALU_PCREL_7_0
245 RT(R_ARM_ALU_PCREL_7_0, "ALU RCREL 7 0"),
246 RT(R_ARM_ALU_PCREL_15_8, "ALU PCREL 15 8"),
247 RT(R_ARM_ALU_PCREL_23_15, "ALU RCREL 23 15"),
248 RT(R_ARM_LDR_SBREL_11_0, "Program base relative (LDR 11 0)"),
249 RT(R_ARM_ALU_SBREL_19_12, "Program base relative (ALU 19 12)"),
250 RT(R_ARM_ALU_SBREL_27_20, "Program base relative (ALU 27 20)"),
251 #endif
252 #ifdef __GLIBC_PREREQ
253 #if __GLIBC_PREREQ(2, 18)
254 RT(R_ARM_TARGET1, "TARGET1"),
255 RT(R_ARM_SBREL31, "Program base relative"),
256 RT(R_ARM_V4BX, "V4BX"),
257 RT(R_ARM_TARGET2, "TARGET2"),
258 RT(R_ARM_PREL31, "32 bit PC relative"),
259 RT(R_ARM_MOVW_ABS_NC, "Direct 16-bit (MOVW)"),
260 RT(R_ARM_MOVT_ABS, "Direct high 16-bit (MOVT)"),
261 RT(R_ARM_MOVW_PREL_NC, "PC relative 16-bit (MOVW)"),
262 RT(R_ARM_MOVT_PREL, "PC relative (MOVT)"),
263 RT(R_ARM_THM_MOVW_ABS_NC, "Direct 16 bit (Thumb32 MOVW)"),
264 RT(R_ARM_THM_MOVT_ABS, "Direct high 16 bit (Thumb32 MOVT)"),
265 RT(R_ARM_THM_MOVW_PREL_NC, "PC relative 16 bit (Thumb32 MOVW)"),
266 RT(R_ARM_THM_MOVT_PREL, "PC relative high 16 bit (Thumb32 MOVT)"),
267 RT(R_ARM_THM_JUMP19, "PC relative 20 bit (Thumb32 B<cond>.W)"),
268 RT(R_ARM_THM_JUMP6, "PC relative X & 0x7E (Thumb16 CBZ, CBNZ)"),
269 RT(R_ARM_THM_ALU_PREL_11_0, "PC relative 12 bit (Thumb32 ADR.W)"),
270 RT(R_ARM_THM_PC12, "PC relative 12 bit (Thumb32 LDR{D,SB,H,SH})"),
271 RT(R_ARM_ABS32_NOI, "Direct 32-bit"),
272 RT(R_ARM_REL32_NOI, "PC relative 32-bit"),
273 RT(R_ARM_ALU_PC_G0_NC, "PC relative (ADD, SUB)"),
274 RT(R_ARM_ALU_PC_G0, "PC relative (ADD, SUB)"),
275 RT(R_ARM_ALU_PC_G1_NC, "PC relative (ADD, SUB)"),
276 RT(R_ARM_ALU_PC_G1, "PC relative (ADD, SUB)"),
277 RT(R_ARM_ALU_PC_G2, "PC relative (ADD, SUB)"),
278 RT(R_ARM_LDR_PC_G1, "PC relative (LDR,STR,LDRB,STRB)"),
279 RT(R_ARM_LDR_PC_G2, "PC relative (LDR,STR,LDRB,STRB)"),
280 RT(R_ARM_LDRS_PC_G0, "PC relative (STR{D,H}, LDR{D,SB,H,SH})"),
281 RT(R_ARM_LDRS_PC_G1, "PC relative (STR{D,H}, LDR{D,SB,H,SH})"),
282 RT(R_ARM_LDRS_PC_G2, "PC relative (STR{D,H}, LDR{D,SB,H,SH})"),
283 RT(R_ARM_LDC_PC_G0, "PC relative (LDC, STC)"),
284 RT(R_ARM_LDC_PC_G1, "PC relative (LDC, STC)"),
285 RT(R_ARM_LDC_PC_G2, "PC relative (LDC, STC)"),
286 RT(R_ARM_ALU_SB_G0_NC, "Program base relative (ADD,SUB)"),
287 RT(R_ARM_ALU_SB_G0, "Program base relative (ADD,SUB)"),
288 RT(R_ARM_ALU_SB_G1_NC, "Program base relative (ADD,SUB)"),
289 RT(R_ARM_ALU_SB_G1, "Program base relative (ADD,SUB)"),
290 RT(R_ARM_ALU_SB_G2, "Program base relative (ADD,SUB)"),
291 RT(R_ARM_LDR_SB_G0, "Program base relative (LDR, STR, LDRB, STRB)"),
292 RT(R_ARM_LDR_SB_G1, "Program base relative (LDR, STR, LDRB, STRB)"),
293 RT(R_ARM_LDR_SB_G2, "Program base relative (LDR, STR, LDRB, STRB)"),
294 RT(R_ARM_LDRS_SB_G0, "Program base relative (LDR, STR, LDRB, STRB)"),
295 RT(R_ARM_LDRS_SB_G1, "Program base relative (LDR, STR, LDRB, STRB)"),
296 RT(R_ARM_LDRS_SB_G2, "Program base relative (LDR, STR, LDRB, STRB)"),
297 RT(R_ARM_LDC_SB_G0, "Program base relative (LDC,STC)"),
298 RT(R_ARM_LDC_SB_G1, "Program base relative (LDC,STC)"),
299 RT(R_ARM_LDC_SB_G2, "Program base relative (LDC,STC)"),
300 RT(R_ARM_MOVW_BREL_NC, "Program base relative 16 bit (MOVW)"),
301 RT(R_ARM_MOVT_BREL, "Program base relative high 16 bit (MOVT)"),
302 RT(R_ARM_MOVW_BREL, "Program base relative 16 bit (MOVW)"),
303 RT(R_ARM_THM_MOVW_BREL_NC, "Program base relative 16 bit (Thumb32 MOVW)"),
304 RT(R_ARM_THM_MOVT_BREL, "Program base relative high 16 bit (Thumb32 MOVT)"),
305 RT(R_ARM_THM_MOVW_BREL, "Program base relative 16 bit (Thumb32 MOVW)"),
306 #endif
307 #if __GLIBC_PREREQ(2, 14)
308 RT(R_ARM_TLS_GOTDESC, "TLS GOTDESC"),
309 RT(R_ARM_TLS_CALL, "TLS CALL"),
310 RT(R_ARM_TLS_DESCSEQ, "TLS relaxation"),
311 RT(R_ARM_THM_TLS_CALL, "TLS CALL (Thumb)"),
312 #endif
313 #if __GLIBC_PREREQ(2, 18)
314 RT(R_ARM_PLT32_ABS, "PLT32 ABS"),
315 RT(R_ARM_GOT_ABS, "GOT entry"),
316 RT(R_ARM_GOT_PREL, "PC relative GOT entry"),
317 RT(R_ARM_GOT_BREL12, "GOT entry relative to GOT origin (LDR)"),
318 RT(R_ARM_GOTOFF12, "12 bit, GOT entry relative to GOT origin (LDR, STR)"),
319 RT(R_ARM_GOTRELAX, "GOTRELAX"),
320 #endif
321 #endif
322 RT(R_ARM_GNU_VTENTRY, "GNU VTENTRY"),
323 RT(R_ARM_GNU_VTINHERIT, "GNU VTINHERIT"),
324 #ifdef R_ARM_THM_PC11
325 RT(R_ARM_THM_PC11, "PC relative & 0xFFE (Thumb16 B)"),
326 RT(R_ARM_THM_PC9, "PC relative & 0x1FE (Thumb16 B/B<cond>)"),
327 RT(R_ARM_TLS_GD32, "PC-rel 32 bit for global dynamic thread local data"),
328 RT(R_ARM_TLS_LDM32, "PC-rel 32 bit for local dynamic thread local data"),
329 RT(R_ARM_TLS_LDO32, "32 bit offset relative to TLS block"),
330 RT(R_ARM_TLS_IE32, "PC-rel 32 bit for GOT entry of static TLS block offset"),
331 RT(R_ARM_TLS_LE32, "32 bit offset relative to static TLS block"),
332 #endif
333 #ifdef __GLIBC_PREREQ
334 #if __GLIBC_PREREQ(2, 18)
335 RT(R_ARM_TLS_LDO12, "12 bit relative to TLS block (LDR, STR)"),
336 RT(R_ARM_TLS_LE12, "12 bit relative to static TLS block (LDR, STR)"),
337 RT(R_ARM_TLS_IE12GP, "12 bit GOT entry relative to GOT origin (LDR)"),
338 RT(R_ARM_ME_TOO, "ME TOO"),
339 #endif
340 #endif
341 #ifdef R_ARM_THM_TLS_DESCSEQ
342 RT(R_ARM_THM_TLS_DESCSEQ, "TLS DESCSEQ (Thumb)"),
343 #endif
344 #ifdef __GLIBC_PREREQ
345 #if __GLIBC_PREREQ(2, 18)
346 RT(R_ARM_THM_TLS_DESCSEQ16, "TLS DESCSEQ16 (Thumb)"),
347 RT(R_ARM_THM_TLS_DESCSEQ32, "TLS DESCSEQ32 (Thumb)"),
348 RT(R_ARM_THM_GOT_BREL12, "GOT entry relative to GOT origin, 12 bit (Thumb32 LDR)"),
349 #endif
350 #endif
351 #ifdef R_ARM_IRELATIVE
352 RT(R_ARM_IRELATIVE, "IRELATIVE"),
353 #endif
354 #ifdef R_ARM_RXPC25
355 RT(R_ARM_RXPC25, "RXPC25"),
356 #endif
357 RT(R_ARM_RSBREL32, "RSBREL32"),
358 #ifdef R_ARM_THM_RPC22
359 RT(R_ARM_THM_RPC22, "RPC22 (Thumb)"),
360 #endif
361 RT(R_ARM_RREL32, "RREL32"),
362 #ifdef R_ARM_RABS22
363 RT(R_ARM_RABS22, "RABS22"),
364 #endif
365 RT(R_ARM_RPC24, "RPC24"),
366 RT(R_ARM_RBASE, "RBASE")
367 };
368
369 static const RelocType reloc_types_x86_64[] {
370 RT(R_X86_64_NONE, "No reloc"),
371 RT(R_X86_64_64, "Direct 64 bit "),
372 RT(R_X86_64_PC32, "PC relative 32 bit signed"),
373 RT(R_X86_64_GOT32, "32 bit GOT entry"),
374 RT(R_X86_64_PLT32, "32 bit PLT address"),
375 RT(R_X86_64_COPY, "Copy symbol at runtime"),
376 RT(R_X86_64_GLOB_DAT, "Create GOT entry"),
377 #ifdef R_X86_64_JUMP_SLOT
378 RT(R_X86_64_JUMP_SLOT, "Create PLT entry"),
379 #endif
380 RT(R_X86_64_RELATIVE, "Adjust by program base"),
381 RT(R_X86_64_GOTPCREL, "32 bit signed PC relative offset to GOT"),
382 RT(R_X86_64_32, "Direct 32 bit zero extended"),
383 RT(R_X86_64_32S, "Direct 32 bit sign extended"),
384 RT(R_X86_64_16, "Direct 16 bit zero extended"),
385 RT(R_X86_64_PC16, "16 bit sign extended pc relative"),
386 RT(R_X86_64_8, "Direct 8 bit sign extended "),
387 RT(R_X86_64_PC8, "8 bit sign extended pc relative"),
388 RT(R_X86_64_DTPMOD64, "ID of module containing symbol"),
389 RT(R_X86_64_DTPOFF64, "Offset in module's TLS block"),
390 RT(R_X86_64_TPOFF64, "Offset in initial TLS block"),
391 RT(R_X86_64_TLSGD, "32 bit signed PC relative offset to two GOT entries for GD symbol"),
392 RT(R_X86_64_TLSLD, "32 bit signed PC relative offset to two GOT entries for LD symbol"),
393 RT(R_X86_64_DTPOFF32, "Offset in TLS block"),
394 RT(R_X86_64_GOTTPOFF, "32 bit signed PC relative offset to GOT entry for IE symbol"),
395 RT(R_X86_64_TPOFF32, "Offset in initial TLS block"),
396 RT(R_X86_64_PC64, "PC relative 64 bit"),
397 RT(R_X86_64_GOTOFF64, "64 bit offset to GOT"),
398 RT(R_X86_64_GOTPC32, "32 bit signed pc relative offset to GOT"),
399 RT(R_X86_64_GOT64, "64-bit GOT entry offset"),
400 RT(R_X86_64_GOTPCREL64, "64-bit PC relative offset to GOT entry"),
401 RT(R_X86_64_GOTPC64, "64-bit PC relative offset to GOT"),
402 RT(R_X86_64_GOTPLT64, "like GOT64, says PLT entry needed"),
403 RT(R_X86_64_PLTOFF64, "64-bit GOT relative offset to PLT entry"),
404 RT(R_X86_64_SIZE32, "Size of symbol plus 32-bit addend"),
405 RT(R_X86_64_SIZE64, "Size of symbol plus 64-bit addend"),
406 RT(R_X86_64_GOTPC32_TLSDESC, "GOT offset for TLS descriptor"),
407 RT(R_X86_64_TLSDESC_CALL, "Marker for call through TLS descriptor"),
408 RT(R_X86_64_TLSDESC, "TLS descriptor. "),
409 RT(R_X86_64_IRELATIVE, "Adjust indirectly by program base"),
410 #ifdef R_X86_64_RELATIVE64
411 RT(R_X86_64_RELATIVE64, "64-bit adjust by program base")
412 #endif
413 };
414
415 #ifdef EM_AARCH64
416 static const RelocType reloc_types_aarch64[] = {
417 RT(R_AARCH64_NONE, "No relocation"),
418 #ifdef R_AARCH64_P32_ABS32
419 RT(R_AARCH64_P32_ABS32, "Direct 32 bit"),
420 RT(R_AARCH64_P32_COPY, "Copy symbol at runtime"),
421 RT(R_AARCH64_P32_GLOB_DAT, "Create GOT entry"),
422 RT(R_AARCH64_P32_JUMP_SLOT, "Create PLT entry"),
423 RT(R_AARCH64_P32_RELATIVE, "Adjust by program base"),
424 RT(R_AARCH64_P32_TLS_DTPMOD, "Module number, 32 bit"),
425 RT(R_AARCH64_P32_TLS_DTPREL, "Module-relative offset, 32 bit"),
426 RT(R_AARCH64_P32_TLS_TPREL, "TP-relative offset, 32 bit"),
427 RT(R_AARCH64_P32_TLSDESC, " TLS Descriptor"),
428 RT(R_AARCH64_P32_IRELATIVE, "STT_GNU_IFUNC relocation"),
429 #endif
430 RT(R_AARCH64_ABS64, "Direct 64 bit"),
431 RT(R_AARCH64_ABS32, "Direct 32 bit"),
432 RT(R_AARCH64_ABS16, " Direct 16-bit"),
433 RT(R_AARCH64_PREL64, "PC-relative 64-bit"),
434 RT(R_AARCH64_PREL32, " PC-relative 32-bit"),
435 RT(R_AARCH64_PREL16, " PC-relative 16-bit"),
436 #ifdef R_AARCH64_MOVW_UABS_G0
437 RT(R_AARCH64_MOVW_UABS_G0, "Dir. MOVZ imm. from bits 15:0"),
438 RT(R_AARCH64_MOVW_UABS_G0_NC, "Likewise for MOVK; no check"),
439 RT(R_AARCH64_MOVW_UABS_G1, "Dir. MOVZ imm. from bits 31:16"),
440 RT(R_AARCH64_MOVW_UABS_G1_NC, "Likewise for MOVK; no check"),
441 RT(R_AARCH64_MOVW_UABS_G2, "Dir. MOVZ imm. from bits 47:32"),
442 #endif
443 RT(R_AARCH64_TSTBR14, "PC-rel. TBZ/TBNZ imm. from 15:2"),
444 RT(R_AARCH64_CONDBR19, "PC-rel. cond. br. imm. from 20:2"),
445 RT(R_AARCH64_JUMP26, "PC-rel. B imm. from bits 27:2"),
446 RT(R_AARCH64_CALL26, "Likewise for CALL"),
447 #ifdef R_AARCH64_LDST16_ABS_LO12_NC
448 RT(R_AARCH64_LDST16_ABS_LO12_NC, "Dir. ADD imm. from bits 11:1"),
449 RT(R_AARCH64_LDST32_ABS_LO12_NC, "Likewise for bits 11:2"),
450 RT(R_AARCH64_LDST64_ABS_LO12_NC, "Likewise for bits 11:3"),
451 RT(R_AARCH64_MOVW_PREL_G0, "PC-rel. MOV{N,Z} imm. from 15:0"),
452 RT(R_AARCH64_MOVW_PREL_G0_NC, "Likewise for MOVK; no check"),
453 RT(R_AARCH64_MOVW_UABS_G2_NC, "Likewise for MOVK; no check"),
454 RT(R_AARCH64_MOVW_UABS_G3, "Dir. MOV{K,Z} imm. from 63:48"),
455 RT(R_AARCH64_MOVW_SABS_G0, "Dir. MOV{N,Z} imm. from 15:0"),
456 RT(R_AARCH64_MOVW_SABS_G1, "Dir. MOV{N,Z} imm. from 31:16"),
457 RT(R_AARCH64_MOVW_SABS_G2, "Dir. MOV{N,Z} imm. from 47:32"),
458 RT(R_AARCH64_LD_PREL_LO19, "PC-rel. LD imm. from bits 20:2"),
459 RT(R_AARCH64_ADR_PREL_LO21, "PC-rel. ADR imm. from bits 20:0"),
460 RT(R_AARCH64_ADR_PREL_PG_HI21, "Page-rel. ADRP imm. from 32:12"),
461 RT(R_AARCH64_ADR_PREL_PG_HI21_NC, "Likewise; no overflow check"),
462 RT(R_AARCH64_ADD_ABS_LO12_NC, "Dir. ADD imm. from bits 11:0"),
463 RT(R_AARCH64_LDST8_ABS_LO12_NC, "Likewise for LD/ST; no check"),
464 RT(R_AARCH64_MOVW_PREL_G1, "PC-rel. MOV{N,Z} imm. from 31:16"),
465 RT(R_AARCH64_MOVW_PREL_G1_NC, "Likewise for MOVK; no check"),
466 RT(R_AARCH64_MOVW_PREL_G2, "PC-rel. MOV{N,Z} imm. from 47:32"),
467 RT(R_AARCH64_MOVW_PREL_G2_NC, "Likewise for MOVK; no check"),
468 RT(R_AARCH64_MOVW_PREL_G3, "PC-rel. MOV{N,Z} imm. from 63:48"),
469 RT(R_AARCH64_LDST128_ABS_LO12_NC, "Dir. ADD imm. from bits 11:4"),
470 RT(R_AARCH64_MOVW_GOTOFF_G0, "GOT-rel. off. MOV{N,Z} imm. 15:0"),
471 RT(R_AARCH64_MOVW_GOTOFF_G0_NC, "Likewise for MOVK; no check"),
472 RT(R_AARCH64_MOVW_GOTOFF_G1, "GOT-rel. o. MOV{N,Z} imm. 31:16"),
473 RT(R_AARCH64_MOVW_GOTOFF_G1_NC, "Likewise for MOVK; no check"),
474 RT(R_AARCH64_MOVW_GOTOFF_G2, "GOT-rel. o. MOV{N,Z} imm. 47:32"),
475 RT(R_AARCH64_MOVW_GOTOFF_G2_NC, "Likewise for MOVK; no check"),
476 RT(R_AARCH64_MOVW_GOTOFF_G3, "GOT-rel. o. MOV{N,Z} imm. 63:48"),
477 RT(R_AARCH64_GOTREL64, "GOT-relative 64-bit"),
478 RT(R_AARCH64_GOTREL32, "GOT-relative 32-bit"),
479 RT(R_AARCH64_GOT_LD_PREL19, "PC-rel. GOT off. load imm. 20:2"),
480 RT(R_AARCH64_LD64_GOTOFF_LO15, "GOT-rel. off. LD/ST imm. 14:3"),
481 RT(R_AARCH64_ADR_GOT_PAGE, "P-page-rel. GOT off. ADRP 32:12"),
482 RT(R_AARCH64_LD64_GOT_LO12_NC, "Dir. GOT off. LD/ST imm. 11:3"),
483 RT(R_AARCH64_LD64_GOTPAGE_LO15, "GOT-page-rel. GOT off. LD/ST 14:3"),
484 RT(R_AARCH64_TLSGD_ADR_PREL21, "PC-relative ADR imm. 20:0"),
485 RT(R_AARCH64_TLSGD_ADR_PAGE21, "page-rel. ADRP imm. 32:12"),
486 RT(R_AARCH64_TLSGD_ADD_LO12_NC, "direct ADD imm. from 11:0"),
487 RT(R_AARCH64_TLSGD_MOVW_G1, "GOT-rel. MOV{N,Z} 31:16"),
488 RT(R_AARCH64_TLSGD_MOVW_G0_NC, "GOT-rel. MOVK imm. 15:0"),
489 RT(R_AARCH64_TLSLD_ADR_PREL21, "Like 512; local dynamic model"),
490 RT(R_AARCH64_TLSLD_ADR_PAGE21, "Like 513; local dynamic model"),
491 RT(R_AARCH64_TLSLD_ADD_LO12_NC, "Like 514; local dynamic model"),
492 RT(R_AARCH64_TLSLD_MOVW_G1, "Like 515; local dynamic model"),
493 RT(R_AARCH64_TLSLD_MOVW_G0_NC, "Like 516; local dynamic model"),
494 RT(R_AARCH64_TLSLD_LD_PREL19, "TLS PC-rel. load imm. 20:2"),
495 RT(R_AARCH64_TLSLD_MOVW_DTPREL_G2, "TLS DTP-rel. MOV{N,Z} 47:32"),
496 RT(R_AARCH64_TLSLD_MOVW_DTPREL_G1, "TLS DTP-rel. MOV{N,Z} 31:16"),
497 RT(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC, "Likewise; MOVK; no check"),
498 RT(R_AARCH64_TLSLD_MOVW_DTPREL_G0, "TLS DTP-rel. MOV{N,Z} 15:0"),
499 RT(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC, "Likewise; MOVK; no check"),
500 RT(R_AARCH64_TLSLD_ADD_DTPREL_HI12, "DTP-rel. ADD imm. from 23:12"),
501 RT(R_AARCH64_TLSLD_ADD_DTPREL_LO12, "DTP-rel. ADD imm. from 11:0"),
502 RT(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC, "Likewise; no ovfl. check"),
503 RT(R_AARCH64_TLSLD_LDST8_DTPREL_LO12, "DTP-rel. LD/ST imm. 11:0"),
504 RT(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC, "Likewise; no check"),
505 RT(R_AARCH64_TLSLD_LDST16_DTPREL_LO12, "DTP-rel. LD/ST imm. 11:1"),
506 RT(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC, "Likewise; no check"),
507 RT(R_AARCH64_TLSLD_LDST32_DTPREL_LO12, "DTP-rel. LD/ST imm. 11:2"),
508 RT(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC, "Likewise; no check"),
509 RT(R_AARCH64_TLSLD_LDST64_DTPREL_LO12, "DTP-rel. LD/ST imm. 11:3"),
510 RT(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC, "Likewise; no check"),
511 RT(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1, "GOT-rel. MOV{N,Z} 31:16"),
512 RT(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC, "GOT-rel. MOVK 15:0"),
513 RT(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, "Page-rel. ADRP 32:12"),
514 RT(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, "Direct LD off. 11:3"),
515 RT(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19, "PC-rel. load imm. 20:2"),
516 RT(R_AARCH64_TLSLE_MOVW_TPREL_G2, "TLS TP-rel. MOV{N,Z} 47:32"),
517 RT(R_AARCH64_TLSLE_MOVW_TPREL_G1, "TLS TP-rel. MOV{N,Z} 31:16"),
518 RT(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC, "Likewise; MOVK; no check"),
519 RT(R_AARCH64_TLSLE_MOVW_TPREL_G0, "TLS TP-rel. MOV{N,Z} 15:0"),
520 RT(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC, "Likewise; MOVK; no check"),
521 RT(R_AARCH64_TLSLE_ADD_TPREL_HI12, "TP-rel. ADD imm. 23:12"),
522 RT(R_AARCH64_TLSLE_ADD_TPREL_LO12, "TP-rel. ADD imm. 11:0"),
523 RT(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC, "Likewise; no ovfl. check"),
524 RT(R_AARCH64_TLSLE_LDST8_TPREL_LO12, "TP-rel. LD/ST off. 11:0"),
525 RT(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC, "Likewise; no ovfl. check"),
526 RT(R_AARCH64_TLSLE_LDST16_TPREL_LO12, "TP-rel. LD/ST off. 11:1"),
527 RT(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC, "Likewise; no check"),
528 RT(R_AARCH64_TLSLE_LDST32_TPREL_LO12, "TP-rel. LD/ST off. 11:2"),
529 RT(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC, "Likewise; no check"),
530 RT(R_AARCH64_TLSLE_LDST64_TPREL_LO12, "TP-rel. LD/ST off. 11:3"),
531 RT(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC, "Likewise; no check"),
532 RT(R_AARCH64_TLSDESC_LD_PREL19, "PC-rel. load immediate 20:2"),
533 RT(R_AARCH64_TLSDESC_ADR_PREL21, "PC-rel. ADR immediate 20:0"),
534 RT(R_AARCH64_TLSDESC_ADR_PAGE21, "Page-rel. ADRP imm. 32:12"),
535 RT(R_AARCH64_TLSDESC_LD64_LO12, "Direct LD off. from 11:3"),
536 RT(R_AARCH64_TLSDESC_ADD_LO12, "Direct ADD imm. from 11:0"),
537 RT(R_AARCH64_TLSDESC_OFF_G1, "GOT-rel. MOV{N,Z} imm. 31:16"),
538 RT(R_AARCH64_TLSDESC_OFF_G0_NC, "GOT-rel. MOVK imm. 15:0; no ck"),
539 RT(R_AARCH64_TLSDESC_LDR, "Relax LDR"),
540 RT(R_AARCH64_TLSDESC_ADD, "Relax ADD"),
541 RT(R_AARCH64_TLSDESC_CALL, "Relax BLR"),
542 RT(R_AARCH64_TLSLE_LDST128_TPREL_LO12, "TP-rel. LD/ST off. 11:4"),
543 RT(R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC, "Likewise; no check"),
544 RT(R_AARCH64_TLSLD_LDST128_DTPREL_LO12, "DTP-rel. LD/ST imm. 11:4"),
545 RT(R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC, "Likewise; no check"),
546 #endif
547 RT(R_AARCH64_COPY, "Copy symbol at runtime"),
548 RT(R_AARCH64_GLOB_DAT, "Create GOT entry"),
549 RT(R_AARCH64_JUMP_SLOT, "Create PLT entry"),
550 RT(R_AARCH64_RELATIVE, "Adjust by program base"),
551 #ifdef R_AARCH64_TLS_DTPMOD
552 RT(R_AARCH64_TLS_DTPMOD, "Module number, 64 bit"),
553 RT(R_AARCH64_TLS_DTPREL, "Module-relative offset, 64 bit"),
554 RT(R_AARCH64_TLS_TPREL, "TP-relative offset, 64 bit"),
555 #endif
556 RT(R_AARCH64_TLSDESC, "TLS Descriptor"),
557 RT(R_AARCH64_IRELATIVE, "STT_GNU_IFUNC relocation"),
558 };
559 #endif
560
561 #undef RT
562
563 struct RelocTypeRepository
564 {
565 int machine;
566 int typeInfosSize;
567 const RelocType* typeInfos;
568 };
569
570 #define RTR(mach, typeInfo) { mach, sizeof(typeInfo) / sizeof(RelocType), typeInfo }
571 static const RelocTypeRepository reloc_type_repository[] {
572 RTR(EM_386, reloc_types_i386),
573 RTR(EM_ARM, reloc_types_arm),
574 RTR(EM_X86_64, reloc_types_x86_64),
575 #ifdef EM_AARCH64
576 RTR(EM_AARCH64, reloc_types_aarch64),
577 #endif
578 };
579 #undef RTR
580
581 static const int reloc_type_repository_size = sizeof(reloc_type_repository) / sizeof(RelocTypeRepository);
582
relocTypeInfo(uint16_t machine,uint32_t type)583 static const RelocType* relocTypeInfo(uint16_t machine, uint32_t type)
584 {
585 // TODO can be optimized, tables are sorted
586 for (int i = 0; i < reloc_type_repository_size; ++i) {
587 if (reloc_type_repository[i].machine != machine)
588 continue;
589 for (int j = 0; j < reloc_type_repository[i].typeInfosSize; ++j) {
590 if (reloc_type_repository[i].typeInfos[j].id == type)
591 return &reloc_type_repository[i].typeInfos[j];
592 }
593 }
594
595 return nullptr;
596 }
597
relocTypeInfo(ElfRelocationEntry * entry)598 static const RelocType* relocTypeInfo(ElfRelocationEntry* entry)
599 {
600 return relocTypeInfo(entry->relocationTable()->file()->header()->machine(), entry->type());
601 }
602
603 namespace RelocationPrinter {
604
label(ElfRelocationEntry * entry)605 QByteArray label(ElfRelocationEntry* entry)
606 {
607 const auto info = relocTypeInfo(entry);
608 if (!info)
609 return QByteArray("unknown relocation type ") + QByteArray::number(entry->type());
610 return QByteArray::fromRawData(info->label, strlen(info->label));
611 }
612
label(uint16_t machine,uint32_t type)613 QByteArray label(uint16_t machine, uint32_t type)
614 {
615 const auto info = relocTypeInfo(machine, type);
616 if (!info)
617 return QByteArray("unknown relocation type ") + QByteArray::number(type);
618 return QByteArray::fromRawData(info->label, strlen(info->label));
619 }
620
description(ElfRelocationEntry * entry)621 QByteArray description(ElfRelocationEntry* entry)
622 {
623 const auto info = relocTypeInfo(entry);
624 if (!info)
625 return QByteArray("unknown relocation type ") + QByteArray::number(entry->type());
626 return QByteArray::fromRawData(info->desc, strlen(info->desc));
627 }
628
629 }
630