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