File indexing completed on 2024-05-12 05:43:31

0001 /*
0002     Copyright (C) 2015 Volker Krause <vkrause@kde.org>
0003 
0004     This program is free software; you can redistribute it and/or modify it
0005     under the terms of the GNU Library General Public License as published by
0006     the Free Software Foundation; either version 2 of the License, or (at your
0007     option) any later version.
0008 
0009     This program is distributed in the hope that it will be useful, but WITHOUT
0010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
0012     License for more details.
0013 
0014     You should have received a copy of the GNU General Public License
0015     along with this program.  If not, see <https://www.gnu.org/licenses/>.
0016 */
0017 
0018 #include "relocationprinter.h"
0019 
0020 #include <elf/elfrelocationentry.h>
0021 #include <elf/elfrelocationsection.h>
0022 #include <elf/elffile.h>
0023 #include <elf/elfheader.h>
0024 
0025 #include <QByteArray>
0026 
0027 #include <elf.h>
0028 
0029 // Fix build on FreeBSD 12, which does not include these ELF relocation
0030 // types; they're standard, and were added to FreeBSD 13 in
0031 // https://cgit.freebsd.org/src/commit/?id=f7d181543fd96a89b84878ddb2d5ac010fadd9b8
0032 #ifndef R_386_32PLT
0033 #define R_386_32PLT             11
0034 #define R_386_16                20
0035 #define R_386_PC16              21
0036 #define R_386_8                 22
0037 #define R_386_PC8               23
0038 #define R_386_SIZE32            38
0039 #define R_386_TLS_GOTDESC       39
0040 #define R_386_TLS_DESC_CALL     40
0041 #define R_386_TLS_DESC          41
0042 #define R_386_GOT32X            43
0043 #define R_X86_64_RELATIVE64     38
0044 /* 39 and 40 were BND-related, already decomissioned */
0045 #define R_X86_64_GOTPCRELX      41
0046 #define R_X86_64_REX_GOTPCRELX  42
0047 #endif
0048 
0049 struct RelocType
0050 {
0051     uint32_t id;
0052     const char* label;
0053     const char* desc;
0054 };
0055 
0056 #define RT(type, desc) { type, #type, desc }
0057 
0058 static const RelocType reloc_types_i386[] {
0059     RT(R_386_NONE, "No reloc"),
0060     RT(R_386_32, "Direct 32 bit"),
0061     RT(R_386_PC32, "PC relative 32 bit"),
0062     RT(R_386_GOT32, "32 bit GOT entry"),
0063     RT(R_386_PLT32, "32 bit PLT address"),
0064     RT(R_386_COPY, "Copy symbol at runtime"),
0065     RT(R_386_GLOB_DAT, "Create GOT entry"),
0066     RT(R_386_JMP_SLOT, "Create PLT entry"),
0067     RT(R_386_RELATIVE, "Adjust by program base"),
0068     RT(R_386_GOTOFF, "32 bit offset to GOT"),
0069     RT(R_386_GOTPC, "32 bit PC relative offset to GOT"),
0070     RT(R_386_32PLT, ""),
0071     RT(R_386_TLS_TPOFF, "Offset in static TLS block"),
0072     RT(R_386_TLS_IE, "Address of GOT entry for static TLS block offset"),
0073     RT(R_386_TLS_GOTIE, "GOT entry for static TLS block offset"),
0074     RT(R_386_TLS_LE, "Offset relative to static TLS block"),
0075     RT(R_386_TLS_GD, "Direct 32 bit for GNU version of general dynamic thread local data"),
0076     RT(R_386_TLS_LDM, "Direct 32 bit for GNU version of local dynamic thread local data in LE code"),
0077     RT(R_386_16, ""),
0078     RT(R_386_PC16, ""),
0079     RT(R_386_8, ""),
0080     RT(R_386_PC8, ""),
0081     RT(R_386_TLS_GD_32, "Direct 32 bit for general dynamic thread local data"),
0082     RT(R_386_TLS_GD_PUSH, "Tag for pushl in GD TLS code"),
0083     RT(R_386_TLS_GD_CALL, "Relocation for call to __tls_get_addr()"),
0084     RT(R_386_TLS_GD_POP, "Tag for popl in GD TLS code"),
0085     RT(R_386_TLS_LDM_32, "Direct 32 bit for local dynamic thread local data in LE code"),
0086     RT(R_386_TLS_LDM_PUSH, "Tag for pushl in LDM TLS code"),
0087     RT(R_386_TLS_LDM_CALL, "Relocation for call to __tls_get_addr() in LDM code"),
0088     RT(R_386_TLS_LDM_POP, "Tag for popl in LDM TLS code"),
0089     RT(R_386_TLS_LDO_32, "Offset relative to TLS block"),
0090     RT(R_386_TLS_IE_32, "GOT entry for negated static TLS block offset"),
0091     RT(R_386_TLS_LE_32, "Negated offset relative to static TLS block"),
0092     RT(R_386_TLS_DTPMOD32, "ID of module containing symbol"),
0093     RT(R_386_TLS_DTPOFF32, "Offset in TLS block"),
0094     RT(R_386_TLS_TPOFF32, "Negated offset in static TLS block"),
0095 #ifdef R_386_SIZE32
0096     RT(R_386_SIZE32, "32-bit symbol size"),
0097 #endif
0098     RT(R_386_TLS_GOTDESC, "GOT offset for TLS descriptor."),
0099     RT(R_386_TLS_DESC_CALL, "Marker of call through TLS descriptor for relaxation."),
0100     RT(R_386_TLS_DESC, "TLS descriptor containing pointer to code and to argument, returning the TLS offset for the symbol."),
0101     RT(R_386_IRELATIVE, "Adjust indirectly by program base")
0102 };
0103 
0104 static const RelocType reloc_types_arm[] {
0105     RT(R_ARM_NONE, "No reloc"),
0106     RT(R_ARM_PC24, "Deprecated PC relative 26 bit branch"),
0107     RT(R_ARM_ABS32, "Direct 32 bit"),
0108     RT(R_ARM_REL32, "PC relative 32 bit"),
0109     RT(R_ARM_PC13, "PC13"),
0110     RT(R_ARM_ABS16, "Direct 16 bit"),
0111     RT(R_ARM_ABS12, "Direct 12 bit"),
0112     RT(R_ARM_THM_ABS5, "Direct & 0x7C (LDR, STR)"),
0113     RT(R_ARM_ABS8, "Direct 8 bit"),
0114     RT(R_ARM_SBREL32, "SBREL32"),
0115     RT(R_ARM_THM_PC22, "PC relative 24 bit (Thumb32 BL)"),
0116     RT(R_ARM_THM_PC8, "PC relative & 0x3FC (Thumb16 LDR, ADD, ADR)"),
0117     RT(R_ARM_AMP_VCALL9, "VCALL9"),
0118 #ifndef R_ARM_TLS_DESC
0119     RT(R_ARM_SWI24, "Obsolete static relocation"),
0120 #else
0121     RT(R_ARM_TLS_DESC, "Dynamic relocation"),
0122 #endif
0123     RT(R_ARM_THM_SWI8, "SWI8"),
0124     RT(R_ARM_XPC25, "XPC25"),
0125     RT(R_ARM_THM_XPC22, "XPC22 (Thumb)"),
0126     RT(R_ARM_TLS_DTPMOD32, "ID of module containing symbol"),
0127     RT(R_ARM_TLS_DTPOFF32, "Offset in TLS block"),
0128     RT(R_ARM_TLS_TPOFF32, "Offset in static TLS block"),
0129     RT(R_ARM_COPY, "Copy symbol at runtime"),
0130     RT(R_ARM_GLOB_DAT, "Create GOT entry"),
0131     RT(R_ARM_JUMP_SLOT, "Create PLT entry"),
0132     RT(R_ARM_RELATIVE, "Adjust by program base"),
0133     RT(R_ARM_GOTOFF, "32 bit offset to GOT"),
0134     RT(R_ARM_GOTPC, "32 bit PC relative offset to GOT"),
0135     RT(R_ARM_GOT32, "32 bit GOT entry"),
0136     RT(R_ARM_PLT32, "Deprecated, 32 bit PLT address"),
0137 #ifdef __GLIBC_PREREQ
0138 #if __GLIBC_PREREQ(2, 18)
0139     RT(R_ARM_CALL, "PC relative 24 bit (BL, BLX)"),
0140     RT(R_ARM_JUMP24, "PC relative 24 bit (B, BL<cond>)"),
0141     RT(R_ARM_THM_JUMP24, "PC relative 24 bit (Thumb32 B.W)"),
0142     RT(R_ARM_BASE_ABS, "Adjust by program base"),
0143 #endif
0144 #endif
0145 #ifdef R_ARM_ALU_PCREL_7_0
0146     RT(R_ARM_ALU_PCREL_7_0, "ALU RCREL 7 0"),
0147     RT(R_ARM_ALU_PCREL_15_8, "ALU PCREL 15 8"),
0148     RT(R_ARM_ALU_PCREL_23_15, "ALU RCREL 23 15"),
0149     RT(R_ARM_LDR_SBREL_11_0, "Program base relative (LDR 11 0)"),
0150     RT(R_ARM_ALU_SBREL_19_12, "Program base relative (ALU 19 12)"),
0151     RT(R_ARM_ALU_SBREL_27_20, "Program base relative (ALU 27 20)"),
0152 #endif
0153 #ifdef __GLIBC_PREREQ
0154 #if __GLIBC_PREREQ(2, 18)
0155     RT(R_ARM_TARGET1, "TARGET1"),
0156     RT(R_ARM_SBREL31, "Program base relative"),
0157     RT(R_ARM_V4BX, "V4BX"),
0158     RT(R_ARM_TARGET2, "TARGET2"),
0159     RT(R_ARM_PREL31, "32 bit PC relative"),
0160     RT(R_ARM_MOVW_ABS_NC, "Direct 16-bit (MOVW)"),
0161     RT(R_ARM_MOVT_ABS, "Direct high 16-bit (MOVT)"),
0162     RT(R_ARM_MOVW_PREL_NC, "PC relative 16-bit (MOVW)"),
0163     RT(R_ARM_MOVT_PREL, "PC relative (MOVT)"),
0164     RT(R_ARM_THM_MOVW_ABS_NC, "Direct 16 bit (Thumb32 MOVW)"),
0165     RT(R_ARM_THM_MOVT_ABS, "Direct high 16 bit (Thumb32 MOVT)"),
0166     RT(R_ARM_THM_MOVW_PREL_NC, "PC relative 16 bit (Thumb32 MOVW)"),
0167     RT(R_ARM_THM_MOVT_PREL, "PC relative high 16 bit (Thumb32 MOVT)"),
0168     RT(R_ARM_THM_JUMP19, "PC relative 20 bit (Thumb32 B<cond>.W)"),
0169     RT(R_ARM_THM_JUMP6, "PC relative X & 0x7E (Thumb16 CBZ, CBNZ)"),
0170     RT(R_ARM_THM_ALU_PREL_11_0, "PC relative 12 bit (Thumb32 ADR.W)"),
0171     RT(R_ARM_THM_PC12, "PC relative 12 bit (Thumb32 LDR{D,SB,H,SH})"),
0172     RT(R_ARM_ABS32_NOI, "Direct 32-bit"),
0173     RT(R_ARM_REL32_NOI, "PC relative 32-bit"),
0174     RT(R_ARM_ALU_PC_G0_NC, "PC relative (ADD, SUB)"),
0175     RT(R_ARM_ALU_PC_G0, "PC relative (ADD, SUB)"),
0176     RT(R_ARM_ALU_PC_G1_NC, "PC relative (ADD, SUB)"),
0177     RT(R_ARM_ALU_PC_G1, "PC relative (ADD, SUB)"),
0178     RT(R_ARM_ALU_PC_G2, "PC relative (ADD, SUB)"),
0179     RT(R_ARM_LDR_PC_G1, "PC relative (LDR,STR,LDRB,STRB)"),
0180     RT(R_ARM_LDR_PC_G2, "PC relative (LDR,STR,LDRB,STRB)"),
0181     RT(R_ARM_LDRS_PC_G0, "PC relative (STR{D,H}, LDR{D,SB,H,SH})"),
0182     RT(R_ARM_LDRS_PC_G1, "PC relative (STR{D,H}, LDR{D,SB,H,SH})"),
0183     RT(R_ARM_LDRS_PC_G2, "PC relative (STR{D,H}, LDR{D,SB,H,SH})"),
0184     RT(R_ARM_LDC_PC_G0, "PC relative (LDC, STC)"),
0185     RT(R_ARM_LDC_PC_G1, "PC relative (LDC, STC)"),
0186     RT(R_ARM_LDC_PC_G2, "PC relative (LDC, STC)"),
0187     RT(R_ARM_ALU_SB_G0_NC, "Program base relative (ADD,SUB)"),
0188     RT(R_ARM_ALU_SB_G0, "Program base relative (ADD,SUB)"),
0189     RT(R_ARM_ALU_SB_G1_NC, "Program base relative (ADD,SUB)"),
0190     RT(R_ARM_ALU_SB_G1, "Program base relative (ADD,SUB)"),
0191     RT(R_ARM_ALU_SB_G2, "Program base relative (ADD,SUB)"),
0192     RT(R_ARM_LDR_SB_G0, "Program base relative (LDR, STR, LDRB, STRB)"),
0193     RT(R_ARM_LDR_SB_G1, "Program base relative (LDR, STR, LDRB, STRB)"),
0194     RT(R_ARM_LDR_SB_G2, "Program base relative (LDR, STR, LDRB, STRB)"),
0195     RT(R_ARM_LDRS_SB_G0, "Program base relative (LDR, STR, LDRB, STRB)"),
0196     RT(R_ARM_LDRS_SB_G1, "Program base relative (LDR, STR, LDRB, STRB)"),
0197     RT(R_ARM_LDRS_SB_G2, "Program base relative (LDR, STR, LDRB, STRB)"),
0198     RT(R_ARM_LDC_SB_G0, "Program base relative (LDC,STC)"),
0199     RT(R_ARM_LDC_SB_G1, "Program base relative (LDC,STC)"),
0200     RT(R_ARM_LDC_SB_G2, "Program base relative (LDC,STC)"),
0201     RT(R_ARM_MOVW_BREL_NC, "Program base relative 16 bit (MOVW)"),
0202     RT(R_ARM_MOVT_BREL, "Program base relative high 16 bit (MOVT)"),
0203     RT(R_ARM_MOVW_BREL, "Program base relative 16 bit (MOVW)"),
0204     RT(R_ARM_THM_MOVW_BREL_NC, "Program base relative 16 bit (Thumb32 MOVW)"),
0205     RT(R_ARM_THM_MOVT_BREL, "Program base relative high 16 bit (Thumb32 MOVT)"),
0206     RT(R_ARM_THM_MOVW_BREL, "Program base relative 16 bit (Thumb32 MOVW)"),
0207 #endif
0208 #if __GLIBC_PREREQ(2, 14)
0209     RT(R_ARM_TLS_GOTDESC, "TLS GOTDESC"),
0210     RT(R_ARM_TLS_CALL, "TLS CALL"),
0211     RT(R_ARM_TLS_DESCSEQ, "TLS relaxation"),
0212     RT(R_ARM_THM_TLS_CALL, "TLS CALL (Thumb)"),
0213 #endif
0214 #if __GLIBC_PREREQ(2, 18)
0215     RT(R_ARM_PLT32_ABS, "PLT32 ABS"),
0216     RT(R_ARM_GOT_ABS, "GOT entry"),
0217     RT(R_ARM_GOT_PREL, "PC relative GOT entry"),
0218     RT(R_ARM_GOT_BREL12, "GOT entry relative to GOT origin (LDR)"),
0219     RT(R_ARM_GOTOFF12, "12 bit, GOT entry relative to GOT origin (LDR, STR)"),
0220     RT(R_ARM_GOTRELAX, "GOTRELAX"),
0221 #endif
0222 #endif
0223     RT(R_ARM_GNU_VTENTRY, "GNU VTENTRY"),
0224     RT(R_ARM_GNU_VTINHERIT, "GNU VTINHERIT"),
0225 #ifdef R_ARM_THM_PC11
0226     RT(R_ARM_THM_PC11, "PC relative & 0xFFE (Thumb16 B)"),
0227     RT(R_ARM_THM_PC9, "PC relative & 0x1FE (Thumb16 B/B<cond>)"),
0228     RT(R_ARM_TLS_GD32, "PC-rel 32 bit for global dynamic thread local data"),
0229     RT(R_ARM_TLS_LDM32, "PC-rel 32 bit for local dynamic thread local data"),
0230     RT(R_ARM_TLS_LDO32, "32 bit offset relative to TLS block"),
0231     RT(R_ARM_TLS_IE32, "PC-rel 32 bit for GOT entry of static TLS block offset"),
0232     RT(R_ARM_TLS_LE32, "32 bit offset relative to static TLS block"),
0233 #endif
0234 #ifdef __GLIBC_PREREQ
0235 #if __GLIBC_PREREQ(2, 18)
0236     RT(R_ARM_TLS_LDO12, "12 bit relative to TLS block (LDR, STR)"),
0237     RT(R_ARM_TLS_LE12, "12 bit relative to static TLS block (LDR, STR)"),
0238     RT(R_ARM_TLS_IE12GP, "12 bit GOT entry relative to GOT origin (LDR)"),
0239     RT(R_ARM_ME_TOO, "ME TOO"),
0240 #endif
0241 #endif
0242 #ifdef R_ARM_THM_TLS_DESCSEQ
0243     RT(R_ARM_THM_TLS_DESCSEQ, "TLS DESCSEQ (Thumb)"),
0244 #endif
0245 #ifdef __GLIBC_PREREQ
0246 #if __GLIBC_PREREQ(2, 18)
0247     RT(R_ARM_THM_TLS_DESCSEQ16, "TLS DESCSEQ16 (Thumb)"),
0248     RT(R_ARM_THM_TLS_DESCSEQ32, "TLS DESCSEQ32 (Thumb)"),
0249     RT(R_ARM_THM_GOT_BREL12, "GOT entry relative to GOT origin, 12 bit (Thumb32 LDR)"),
0250 #endif
0251 #endif
0252 #ifdef R_ARM_IRELATIVE
0253     RT(R_ARM_IRELATIVE, "IRELATIVE"),
0254 #endif
0255 #ifdef R_ARM_RXPC25
0256     RT(R_ARM_RXPC25, "RXPC25"),
0257 #endif
0258     RT(R_ARM_RSBREL32, "RSBREL32"),
0259 #ifdef R_ARM_THM_RPC22
0260     RT(R_ARM_THM_RPC22, "RPC22 (Thumb)"),
0261 #endif
0262     RT(R_ARM_RREL32, "RREL32"),
0263 #ifdef R_ARM_RABS22
0264     RT(R_ARM_RABS22, "RABS22"),
0265 #endif
0266     RT(R_ARM_RPC24, "RPC24"),
0267     RT(R_ARM_RBASE, "RBASE")
0268 };
0269 
0270 static const RelocType reloc_types_x86_64[] {
0271     RT(R_X86_64_NONE, "No reloc"),
0272     RT(R_X86_64_64, "Direct 64 bit "),
0273     RT(R_X86_64_PC32, "PC relative 32 bit signed"),
0274     RT(R_X86_64_GOT32, "32 bit GOT entry"),
0275     RT(R_X86_64_PLT32, "32 bit PLT address"),
0276     RT(R_X86_64_COPY, "Copy symbol at runtime"),
0277     RT(R_X86_64_GLOB_DAT, "Create GOT entry"),
0278 #ifdef R_X86_64_JUMP_SLOT
0279     RT(R_X86_64_JUMP_SLOT, "Create PLT entry"),
0280 #endif
0281     RT(R_X86_64_RELATIVE, "Adjust by program base"),
0282     RT(R_X86_64_GOTPCREL, "32 bit signed PC relative offset to GOT"),
0283     RT(R_X86_64_32, "Direct 32 bit zero extended"),
0284     RT(R_X86_64_32S, "Direct 32 bit sign extended"),
0285     RT(R_X86_64_16, "Direct 16 bit zero extended"),
0286     RT(R_X86_64_PC16, "16 bit sign extended pc relative"),
0287     RT(R_X86_64_8, "Direct 8 bit sign extended "),
0288     RT(R_X86_64_PC8, "8 bit sign extended pc relative"),
0289     RT(R_X86_64_DTPMOD64, "ID of module containing symbol"),
0290     RT(R_X86_64_DTPOFF64, "Offset in module's TLS block"),
0291     RT(R_X86_64_TPOFF64, "Offset in initial TLS block"),
0292     RT(R_X86_64_TLSGD, "32 bit signed PC relative offset to two GOT entries for GD symbol"),
0293     RT(R_X86_64_TLSLD, "32 bit signed PC relative offset to two GOT entries for LD symbol"),
0294     RT(R_X86_64_DTPOFF32, "Offset in TLS block"),
0295     RT(R_X86_64_GOTTPOFF, "32 bit signed PC relative offset to GOT entry for IE symbol"),
0296     RT(R_X86_64_TPOFF32, "Offset in initial TLS block"),
0297     RT(R_X86_64_PC64, "PC relative 64 bit"),
0298     RT(R_X86_64_GOTOFF64, "64 bit offset to GOT"),
0299     RT(R_X86_64_GOTPC32, "32 bit signed pc relative offset to GOT"),
0300     RT(R_X86_64_GOT64, "64-bit GOT entry offset"),
0301     RT(R_X86_64_GOTPCREL64, "64-bit PC relative offset to GOT entry"),
0302     RT(R_X86_64_GOTPC64, "64-bit PC relative offset to GOT"),
0303     RT(R_X86_64_GOTPLT64, "like GOT64, says PLT entry needed"),
0304     RT(R_X86_64_PLTOFF64, "64-bit GOT relative offset to PLT entry"),
0305     RT(R_X86_64_SIZE32, "Size of symbol plus 32-bit addend"),
0306     RT(R_X86_64_SIZE64, "Size of symbol plus 64-bit addend"),
0307     RT(R_X86_64_GOTPC32_TLSDESC, "GOT offset for TLS descriptor"),
0308     RT(R_X86_64_TLSDESC_CALL, "Marker for call through TLS descriptor"),
0309     RT(R_X86_64_TLSDESC, "TLS descriptor. "),
0310     RT(R_X86_64_IRELATIVE, "Adjust indirectly by program base"),
0311 #ifdef R_X86_64_RELATIVE64
0312     RT(R_X86_64_RELATIVE64, "64-bit adjust by program base")
0313 #endif
0314 };
0315 
0316 #ifdef EM_AARCH64
0317 static const RelocType reloc_types_aarch64[] = {
0318     RT(R_AARCH64_NONE, "No relocation"),
0319 #ifdef R_AARCH64_P32_ABS32
0320     RT(R_AARCH64_P32_ABS32, "Direct 32 bit"),
0321     RT(R_AARCH64_P32_COPY, "Copy symbol at runtime"),
0322     RT(R_AARCH64_P32_GLOB_DAT, "Create GOT entry"),
0323     RT(R_AARCH64_P32_JUMP_SLOT, "Create PLT entry"),
0324     RT(R_AARCH64_P32_RELATIVE, "Adjust by program base"),
0325     RT(R_AARCH64_P32_TLS_DTPMOD, "Module number, 32 bit"),
0326     RT(R_AARCH64_P32_TLS_DTPREL, "Module-relative offset, 32 bit"),
0327     RT(R_AARCH64_P32_TLS_TPREL, "TP-relative offset, 32 bit"),
0328     RT(R_AARCH64_P32_TLSDESC, " TLS Descriptor"),
0329     RT(R_AARCH64_P32_IRELATIVE, "STT_GNU_IFUNC relocation"),
0330 #endif
0331     RT(R_AARCH64_ABS64, "Direct 64 bit"),
0332     RT(R_AARCH64_ABS32, "Direct 32 bit"),
0333     RT(R_AARCH64_ABS16, " Direct 16-bit"),
0334     RT(R_AARCH64_PREL64, "PC-relative 64-bit"),
0335     RT(R_AARCH64_PREL32, " PC-relative 32-bit"),
0336     RT(R_AARCH64_PREL16, " PC-relative 16-bit"),
0337 #ifdef R_AARCH64_MOVW_UABS_G0
0338     RT(R_AARCH64_MOVW_UABS_G0, "Dir. MOVZ imm. from bits 15:0"),
0339     RT(R_AARCH64_MOVW_UABS_G0_NC, "Likewise for MOVK; no check"),
0340     RT(R_AARCH64_MOVW_UABS_G1, "Dir. MOVZ imm. from bits 31:16"),
0341     RT(R_AARCH64_MOVW_UABS_G1_NC, "Likewise for MOVK; no check"),
0342     RT(R_AARCH64_MOVW_UABS_G2, "Dir. MOVZ imm. from bits 47:32"),
0343 #endif
0344     RT(R_AARCH64_TSTBR14, "PC-rel. TBZ/TBNZ imm. from 15:2"),
0345     RT(R_AARCH64_CONDBR19, "PC-rel. cond. br. imm. from 20:2"),
0346     RT(R_AARCH64_JUMP26, "PC-rel. B imm. from bits 27:2"),
0347     RT(R_AARCH64_CALL26, "Likewise for CALL"),
0348 #ifdef R_AARCH64_LDST16_ABS_LO12_NC
0349     RT(R_AARCH64_LDST16_ABS_LO12_NC, "Dir. ADD imm. from bits 11:1"),
0350     RT(R_AARCH64_LDST32_ABS_LO12_NC, "Likewise for bits 11:2"),
0351     RT(R_AARCH64_LDST64_ABS_LO12_NC, "Likewise for bits 11:3"),
0352     RT(R_AARCH64_MOVW_PREL_G0, "PC-rel. MOV{N,Z} imm. from 15:0"),
0353     RT(R_AARCH64_MOVW_PREL_G0_NC, "Likewise for MOVK; no check"),
0354     RT(R_AARCH64_MOVW_UABS_G2_NC, "Likewise for MOVK; no check"),
0355     RT(R_AARCH64_MOVW_UABS_G3, "Dir. MOV{K,Z} imm. from 63:48"),
0356     RT(R_AARCH64_MOVW_SABS_G0, "Dir. MOV{N,Z} imm. from 15:0"),
0357     RT(R_AARCH64_MOVW_SABS_G1, "Dir. MOV{N,Z} imm. from 31:16"),
0358     RT(R_AARCH64_MOVW_SABS_G2, "Dir. MOV{N,Z} imm. from 47:32"),
0359     RT(R_AARCH64_LD_PREL_LO19, "PC-rel. LD imm. from bits 20:2"),
0360     RT(R_AARCH64_ADR_PREL_LO21, "PC-rel. ADR imm. from bits 20:0"),
0361     RT(R_AARCH64_ADR_PREL_PG_HI21, "Page-rel. ADRP imm. from 32:12"),
0362     RT(R_AARCH64_ADR_PREL_PG_HI21_NC, "Likewise; no overflow check"),
0363     RT(R_AARCH64_ADD_ABS_LO12_NC, "Dir. ADD imm. from bits 11:0"),
0364     RT(R_AARCH64_LDST8_ABS_LO12_NC, "Likewise for LD/ST; no check"),
0365     RT(R_AARCH64_MOVW_PREL_G1, "PC-rel. MOV{N,Z} imm. from 31:16"),
0366     RT(R_AARCH64_MOVW_PREL_G1_NC, "Likewise for MOVK; no check"),
0367     RT(R_AARCH64_MOVW_PREL_G2, "PC-rel. MOV{N,Z} imm. from 47:32"),
0368     RT(R_AARCH64_MOVW_PREL_G2_NC, "Likewise for MOVK; no check"),
0369     RT(R_AARCH64_MOVW_PREL_G3, "PC-rel. MOV{N,Z} imm. from 63:48"),
0370     RT(R_AARCH64_LDST128_ABS_LO12_NC, "Dir. ADD imm. from bits 11:4"),
0371     RT(R_AARCH64_MOVW_GOTOFF_G0, "GOT-rel. off. MOV{N,Z} imm. 15:0"),
0372     RT(R_AARCH64_MOVW_GOTOFF_G0_NC, "Likewise for MOVK; no check"),
0373     RT(R_AARCH64_MOVW_GOTOFF_G1, "GOT-rel. o. MOV{N,Z} imm. 31:16"),
0374     RT(R_AARCH64_MOVW_GOTOFF_G1_NC, "Likewise for MOVK; no check"),
0375     RT(R_AARCH64_MOVW_GOTOFF_G2, "GOT-rel. o. MOV{N,Z} imm. 47:32"),
0376     RT(R_AARCH64_MOVW_GOTOFF_G2_NC, "Likewise for MOVK; no check"),
0377     RT(R_AARCH64_MOVW_GOTOFF_G3, "GOT-rel. o. MOV{N,Z} imm. 63:48"),
0378     RT(R_AARCH64_GOTREL64, "GOT-relative 64-bit"),
0379     RT(R_AARCH64_GOTREL32, "GOT-relative 32-bit"),
0380     RT(R_AARCH64_GOT_LD_PREL19, "PC-rel. GOT off. load imm. 20:2"),
0381     RT(R_AARCH64_LD64_GOTOFF_LO15, "GOT-rel. off. LD/ST imm. 14:3"),
0382     RT(R_AARCH64_ADR_GOT_PAGE, "P-page-rel. GOT off. ADRP 32:12"),
0383     RT(R_AARCH64_LD64_GOT_LO12_NC, "Dir. GOT off. LD/ST imm. 11:3"),
0384     RT(R_AARCH64_LD64_GOTPAGE_LO15, "GOT-page-rel. GOT off. LD/ST 14:3"),
0385     RT(R_AARCH64_TLSGD_ADR_PREL21, "PC-relative ADR imm. 20:0"),
0386     RT(R_AARCH64_TLSGD_ADR_PAGE21, "page-rel. ADRP imm. 32:12"),
0387     RT(R_AARCH64_TLSGD_ADD_LO12_NC, "direct ADD imm. from 11:0"),
0388     RT(R_AARCH64_TLSGD_MOVW_G1, "GOT-rel. MOV{N,Z} 31:16"),
0389     RT(R_AARCH64_TLSGD_MOVW_G0_NC, "GOT-rel. MOVK imm. 15:0"),
0390     RT(R_AARCH64_TLSLD_ADR_PREL21, "Like 512; local dynamic model"),
0391     RT(R_AARCH64_TLSLD_ADR_PAGE21, "Like 513; local dynamic model"),
0392     RT(R_AARCH64_TLSLD_ADD_LO12_NC, "Like 514; local dynamic model"),
0393     RT(R_AARCH64_TLSLD_MOVW_G1, "Like 515; local dynamic model"),
0394     RT(R_AARCH64_TLSLD_MOVW_G0_NC, "Like 516; local dynamic model"),
0395     RT(R_AARCH64_TLSLD_LD_PREL19, "TLS PC-rel. load imm. 20:2"),
0396     RT(R_AARCH64_TLSLD_MOVW_DTPREL_G2, "TLS DTP-rel. MOV{N,Z} 47:32"),
0397     RT(R_AARCH64_TLSLD_MOVW_DTPREL_G1, "TLS DTP-rel. MOV{N,Z} 31:16"),
0398     RT(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC, "Likewise; MOVK; no check"),
0399     RT(R_AARCH64_TLSLD_MOVW_DTPREL_G0, "TLS DTP-rel. MOV{N,Z} 15:0"),
0400     RT(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC, "Likewise; MOVK; no check"),
0401     RT(R_AARCH64_TLSLD_ADD_DTPREL_HI12, "DTP-rel. ADD imm. from 23:12"),
0402     RT(R_AARCH64_TLSLD_ADD_DTPREL_LO12, "DTP-rel. ADD imm. from 11:0"),
0403     RT(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC, "Likewise; no ovfl. check"),
0404     RT(R_AARCH64_TLSLD_LDST8_DTPREL_LO12, "DTP-rel. LD/ST imm. 11:0"),
0405     RT(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC, "Likewise; no check"),
0406     RT(R_AARCH64_TLSLD_LDST16_DTPREL_LO12, "DTP-rel. LD/ST imm. 11:1"),
0407     RT(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC, "Likewise; no check"),
0408     RT(R_AARCH64_TLSLD_LDST32_DTPREL_LO12, "DTP-rel. LD/ST imm. 11:2"),
0409     RT(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC, "Likewise; no check"),
0410     RT(R_AARCH64_TLSLD_LDST64_DTPREL_LO12, "DTP-rel. LD/ST imm. 11:3"),
0411     RT(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC, "Likewise; no check"),
0412     RT(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1, "GOT-rel. MOV{N,Z} 31:16"),
0413     RT(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC, "GOT-rel. MOVK 15:0"),
0414     RT(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, "Page-rel. ADRP 32:12"),
0415     RT(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, "Direct LD off. 11:3"),
0416     RT(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19, "PC-rel. load imm. 20:2"),
0417     RT(R_AARCH64_TLSLE_MOVW_TPREL_G2, "TLS TP-rel. MOV{N,Z} 47:32"),
0418     RT(R_AARCH64_TLSLE_MOVW_TPREL_G1, "TLS TP-rel. MOV{N,Z} 31:16"),
0419     RT(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC, "Likewise; MOVK; no check"),
0420     RT(R_AARCH64_TLSLE_MOVW_TPREL_G0, "TLS TP-rel. MOV{N,Z} 15:0"),
0421     RT(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC, "Likewise; MOVK; no check"),
0422     RT(R_AARCH64_TLSLE_ADD_TPREL_HI12, "TP-rel. ADD imm. 23:12"),
0423     RT(R_AARCH64_TLSLE_ADD_TPREL_LO12, "TP-rel. ADD imm. 11:0"),
0424     RT(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC, "Likewise; no ovfl. check"),
0425     RT(R_AARCH64_TLSLE_LDST8_TPREL_LO12, "TP-rel. LD/ST off. 11:0"),
0426     RT(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC, "Likewise; no ovfl. check"),
0427     RT(R_AARCH64_TLSLE_LDST16_TPREL_LO12, "TP-rel. LD/ST off. 11:1"),
0428     RT(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC, "Likewise; no check"),
0429     RT(R_AARCH64_TLSLE_LDST32_TPREL_LO12, "TP-rel. LD/ST off. 11:2"),
0430     RT(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC, "Likewise; no check"),
0431     RT(R_AARCH64_TLSLE_LDST64_TPREL_LO12, "TP-rel. LD/ST off. 11:3"),
0432     RT(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC, "Likewise; no check"),
0433     RT(R_AARCH64_TLSDESC_LD_PREL19, "PC-rel. load immediate 20:2"),
0434     RT(R_AARCH64_TLSDESC_ADR_PREL21, "PC-rel. ADR immediate 20:0"),
0435     RT(R_AARCH64_TLSDESC_ADR_PAGE21, "Page-rel. ADRP imm. 32:12"),
0436     RT(R_AARCH64_TLSDESC_LD64_LO12, "Direct LD off. from 11:3"),
0437     RT(R_AARCH64_TLSDESC_ADD_LO12, "Direct ADD imm. from 11:0"),
0438     RT(R_AARCH64_TLSDESC_OFF_G1, "GOT-rel. MOV{N,Z} imm. 31:16"),
0439     RT(R_AARCH64_TLSDESC_OFF_G0_NC, "GOT-rel. MOVK imm. 15:0; no ck"),
0440     RT(R_AARCH64_TLSDESC_LDR, "Relax LDR"),
0441     RT(R_AARCH64_TLSDESC_ADD, "Relax ADD"),
0442     RT(R_AARCH64_TLSDESC_CALL, "Relax BLR"),
0443     RT(R_AARCH64_TLSLE_LDST128_TPREL_LO12, "TP-rel. LD/ST off. 11:4"),
0444     RT(R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC, "Likewise; no check"),
0445     RT(R_AARCH64_TLSLD_LDST128_DTPREL_LO12, "DTP-rel. LD/ST imm. 11:4"),
0446     RT(R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC, "Likewise; no check"),
0447 #endif
0448     RT(R_AARCH64_COPY, "Copy symbol at runtime"),
0449     RT(R_AARCH64_GLOB_DAT, "Create GOT entry"),
0450     RT(R_AARCH64_JUMP_SLOT, "Create PLT entry"),
0451     RT(R_AARCH64_RELATIVE, "Adjust by program base"),
0452 #ifdef R_AARCH64_TLS_DTPMOD
0453     RT(R_AARCH64_TLS_DTPMOD, "Module number, 64 bit"),
0454     RT(R_AARCH64_TLS_DTPREL, "Module-relative offset, 64 bit"),
0455     RT(R_AARCH64_TLS_TPREL, "TP-relative offset, 64 bit"),
0456 #endif
0457     RT(R_AARCH64_TLSDESC, "TLS Descriptor"),
0458     RT(R_AARCH64_IRELATIVE, "STT_GNU_IFUNC relocation"),
0459 };
0460 #endif
0461 
0462 #undef RT
0463 
0464 struct RelocTypeRepository
0465 {
0466     int machine;
0467     int typeInfosSize;
0468     const RelocType* typeInfos;
0469 };
0470 
0471 #define RTR(mach, typeInfo) { mach, sizeof(typeInfo) / sizeof(RelocType), typeInfo }
0472 static const RelocTypeRepository reloc_type_repository[] {
0473     RTR(EM_386, reloc_types_i386),
0474     RTR(EM_ARM, reloc_types_arm),
0475     RTR(EM_X86_64, reloc_types_x86_64),
0476 #ifdef EM_AARCH64
0477     RTR(EM_AARCH64, reloc_types_aarch64),
0478 #endif
0479 };
0480 #undef RTR
0481 
0482 static const int reloc_type_repository_size = sizeof(reloc_type_repository) / sizeof(RelocTypeRepository);
0483 
0484 static const RelocType* relocTypeInfo(uint16_t machine, uint32_t type)
0485 {
0486     // TODO can be optimized, tables are sorted
0487     for (int i = 0; i < reloc_type_repository_size; ++i) {
0488         if (reloc_type_repository[i].machine != machine)
0489             continue;
0490         for (int j = 0; j < reloc_type_repository[i].typeInfosSize; ++j) {
0491             if (reloc_type_repository[i].typeInfos[j].id == type)
0492                 return &reloc_type_repository[i].typeInfos[j];
0493         }
0494     }
0495 
0496     return nullptr;
0497 }
0498 
0499 static const RelocType* relocTypeInfo(ElfRelocationEntry* entry)
0500 {
0501     return relocTypeInfo(entry->relocationTable()->file()->header()->machine(), entry->type());
0502 }
0503 
0504 namespace RelocationPrinter {
0505 
0506 QByteArray label(ElfRelocationEntry* entry)
0507 {
0508     const auto info = relocTypeInfo(entry);
0509     if (!info)
0510         return QByteArray("unknown relocation type ") + QByteArray::number(entry->type());
0511     return QByteArray::fromRawData(info->label, strlen(info->label));
0512 }
0513 
0514 QByteArray label(uint16_t machine, uint32_t type)
0515 {
0516     const auto info = relocTypeInfo(machine, type);
0517     if (!info)
0518         return QByteArray("unknown relocation type ") + QByteArray::number(type);
0519     return QByteArray::fromRawData(info->label, strlen(info->label));
0520 }
0521 
0522 QByteArray description(ElfRelocationEntry* entry)
0523 {
0524     const auto info = relocTypeInfo(entry);
0525     if (!info)
0526         return QByteArray("unknown relocation type ") + QByteArray::number(entry->type());
0527     return QByteArray::fromRawData(info->desc, strlen(info->desc));
0528 }
0529 
0530 }