Add bounds check to __libc_ifunc_impl_list
[glibc.git] / scripts / glibcelf.py
blob47f95d07baefb4ae46ed1e602ec1684f2012b26f
1 #!/usr/bin/python3
2 # ELF support functionality for Python.
3 # Copyright (C) 2022 Free Software Foundation, Inc.
4 # This file is part of the GNU C Library.
6 # The GNU C Library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2.1 of the License, or (at your option) any later version.
11 # The GNU C Library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # Lesser General Public License for more details.
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with the GNU C Library; if not, see
18 # <https://www.gnu.org/licenses/>.
20 """Basic ELF parser.
22 Use Image.readfile(path) to read an ELF file into memory and begin
23 parsing it.
25 """
27 import collections
28 import enum
29 import struct
31 if not hasattr(enum, 'IntFlag'):
32 import sys
33 sys.stdout.write(
34 'warning: glibcelf.py needs Python 3.6 for enum support\n')
35 sys.exit(77)
37 class _OpenIntEnum(enum.IntEnum):
38 """Integer enumeration that supports arbitrary int values."""
39 @classmethod
40 def _missing_(cls, value):
41 # See enum.IntFlag._create_pseudo_member_. This allows
42 # creating of enum constants with arbitrary integer values.
43 pseudo_member = int.__new__(cls, value)
44 pseudo_member._name_ = None
45 pseudo_member._value_ = value
46 return pseudo_member
48 def __repr__(self):
49 name = self._name_
50 if name is not None:
51 # The names have prefixes like SHT_, implying their type.
52 return name
53 return '{}({})'.format(self.__class__.__name__, self._value_)
55 def __str__(self):
56 name = self._name_
57 if name is not None:
58 return name
59 return str(self._value_)
61 class ElfClass(_OpenIntEnum):
62 """ELF word size. Type of EI_CLASS values."""
63 ELFCLASSNONE = 0
64 ELFCLASS32 = 1
65 ELFCLASS64 = 2
67 class ElfData(_OpenIntEnum):
68 """ELF endianess. Type of EI_DATA values."""
69 ELFDATANONE = 0
70 ELFDATA2LSB = 1
71 ELFDATA2MSB = 2
73 class Machine(_OpenIntEnum):
74 """ELF machine type. Type of values in Ehdr.e_machine field."""
75 EM_NONE = 0
76 EM_M32 = 1
77 EM_SPARC = 2
78 EM_386 = 3
79 EM_68K = 4
80 EM_88K = 5
81 EM_IAMCU = 6
82 EM_860 = 7
83 EM_MIPS = 8
84 EM_S370 = 9
85 EM_MIPS_RS3_LE = 10
86 EM_PARISC = 15
87 EM_VPP500 = 17
88 EM_SPARC32PLUS = 18
89 EM_960 = 19
90 EM_PPC = 20
91 EM_PPC64 = 21
92 EM_S390 = 22
93 EM_SPU = 23
94 EM_V800 = 36
95 EM_FR20 = 37
96 EM_RH32 = 38
97 EM_RCE = 39
98 EM_ARM = 40
99 EM_FAKE_ALPHA = 41
100 EM_SH = 42
101 EM_SPARCV9 = 43
102 EM_TRICORE = 44
103 EM_ARC = 45
104 EM_H8_300 = 46
105 EM_H8_300H = 47
106 EM_H8S = 48
107 EM_H8_500 = 49
108 EM_IA_64 = 50
109 EM_MIPS_X = 51
110 EM_COLDFIRE = 52
111 EM_68HC12 = 53
112 EM_MMA = 54
113 EM_PCP = 55
114 EM_NCPU = 56
115 EM_NDR1 = 57
116 EM_STARCORE = 58
117 EM_ME16 = 59
118 EM_ST100 = 60
119 EM_TINYJ = 61
120 EM_X86_64 = 62
121 EM_PDSP = 63
122 EM_PDP10 = 64
123 EM_PDP11 = 65
124 EM_FX66 = 66
125 EM_ST9PLUS = 67
126 EM_ST7 = 68
127 EM_68HC16 = 69
128 EM_68HC11 = 70
129 EM_68HC08 = 71
130 EM_68HC05 = 72
131 EM_SVX = 73
132 EM_ST19 = 74
133 EM_VAX = 75
134 EM_CRIS = 76
135 EM_JAVELIN = 77
136 EM_FIREPATH = 78
137 EM_ZSP = 79
138 EM_MMIX = 80
139 EM_HUANY = 81
140 EM_PRISM = 82
141 EM_AVR = 83
142 EM_FR30 = 84
143 EM_D10V = 85
144 EM_D30V = 86
145 EM_V850 = 87
146 EM_M32R = 88
147 EM_MN10300 = 89
148 EM_MN10200 = 90
149 EM_PJ = 91
150 EM_OPENRISC = 92
151 EM_ARC_COMPACT = 93
152 EM_XTENSA = 94
153 EM_VIDEOCORE = 95
154 EM_TMM_GPP = 96
155 EM_NS32K = 97
156 EM_TPC = 98
157 EM_SNP1K = 99
158 EM_ST200 = 100
159 EM_IP2K = 101
160 EM_MAX = 102
161 EM_CR = 103
162 EM_F2MC16 = 104
163 EM_MSP430 = 105
164 EM_BLACKFIN = 106
165 EM_SE_C33 = 107
166 EM_SEP = 108
167 EM_ARCA = 109
168 EM_UNICORE = 110
169 EM_EXCESS = 111
170 EM_DXP = 112
171 EM_ALTERA_NIOS2 = 113
172 EM_CRX = 114
173 EM_XGATE = 115
174 EM_C166 = 116
175 EM_M16C = 117
176 EM_DSPIC30F = 118
177 EM_CE = 119
178 EM_M32C = 120
179 EM_TSK3000 = 131
180 EM_RS08 = 132
181 EM_SHARC = 133
182 EM_ECOG2 = 134
183 EM_SCORE7 = 135
184 EM_DSP24 = 136
185 EM_VIDEOCORE3 = 137
186 EM_LATTICEMICO32 = 138
187 EM_SE_C17 = 139
188 EM_TI_C6000 = 140
189 EM_TI_C2000 = 141
190 EM_TI_C5500 = 142
191 EM_TI_ARP32 = 143
192 EM_TI_PRU = 144
193 EM_MMDSP_PLUS = 160
194 EM_CYPRESS_M8C = 161
195 EM_R32C = 162
196 EM_TRIMEDIA = 163
197 EM_QDSP6 = 164
198 EM_8051 = 165
199 EM_STXP7X = 166
200 EM_NDS32 = 167
201 EM_ECOG1X = 168
202 EM_MAXQ30 = 169
203 EM_XIMO16 = 170
204 EM_MANIK = 171
205 EM_CRAYNV2 = 172
206 EM_RX = 173
207 EM_METAG = 174
208 EM_MCST_ELBRUS = 175
209 EM_ECOG16 = 176
210 EM_CR16 = 177
211 EM_ETPU = 178
212 EM_SLE9X = 179
213 EM_L10M = 180
214 EM_K10M = 181
215 EM_AARCH64 = 183
216 EM_AVR32 = 185
217 EM_STM8 = 186
218 EM_TILE64 = 187
219 EM_TILEPRO = 188
220 EM_MICROBLAZE = 189
221 EM_CUDA = 190
222 EM_TILEGX = 191
223 EM_CLOUDSHIELD = 192
224 EM_COREA_1ST = 193
225 EM_COREA_2ND = 194
226 EM_ARCV2 = 195
227 EM_OPEN8 = 196
228 EM_RL78 = 197
229 EM_VIDEOCORE5 = 198
230 EM_78KOR = 199
231 EM_56800EX = 200
232 EM_BA1 = 201
233 EM_BA2 = 202
234 EM_XCORE = 203
235 EM_MCHP_PIC = 204
236 EM_INTELGT = 205
237 EM_KM32 = 210
238 EM_KMX32 = 211
239 EM_EMX16 = 212
240 EM_EMX8 = 213
241 EM_KVARC = 214
242 EM_CDP = 215
243 EM_COGE = 216
244 EM_COOL = 217
245 EM_NORC = 218
246 EM_CSR_KALIMBA = 219
247 EM_Z80 = 220
248 EM_VISIUM = 221
249 EM_FT32 = 222
250 EM_MOXIE = 223
251 EM_AMDGPU = 224
252 EM_RISCV = 243
253 EM_BPF = 247
254 EM_CSKY = 252
255 EM_NUM = 253
256 EM_ALPHA = 0x9026
258 class Et(_OpenIntEnum):
259 """ELF file type. Type of ET_* values and the Ehdr.e_type field."""
260 ET_NONE = 0
261 ET_REL = 1
262 ET_EXEC = 2
263 ET_DYN = 3
264 ET_CORE = 4
266 class Shn(_OpenIntEnum):
267 """ELF reserved section indices."""
268 SHN_UNDEF = 0
269 SHN_BEFORE = 0xff00
270 SHN_AFTER = 0xff01
271 SHN_ABS = 0xfff1
272 SHN_COMMON = 0xfff2
273 SHN_XINDEX = 0xffff
275 class ShnMIPS(enum.Enum):
276 """Supplemental SHN_* constants for EM_MIPS."""
277 SHN_MIPS_ACOMMON = 0xff00
278 SHN_MIPS_TEXT = 0xff01
279 SHN_MIPS_DATA = 0xff02
280 SHN_MIPS_SCOMMON = 0xff03
281 SHN_MIPS_SUNDEFINED = 0xff04
283 class ShnPARISC(enum.Enum):
284 """Supplemental SHN_* constants for EM_PARISC."""
285 SHN_PARISC_ANSI_COMMON = 0xff00
286 SHN_PARISC_HUGE_COMMON = 0xff01
288 class Sht(_OpenIntEnum):
289 """ELF section types. Type of SHT_* values."""
290 SHT_NULL = 0
291 SHT_PROGBITS = 1
292 SHT_SYMTAB = 2
293 SHT_STRTAB = 3
294 SHT_RELA = 4
295 SHT_HASH = 5
296 SHT_DYNAMIC = 6
297 SHT_NOTE = 7
298 SHT_NOBITS = 8
299 SHT_REL = 9
300 SHT_SHLIB = 10
301 SHT_DYNSYM = 11
302 SHT_INIT_ARRAY = 14
303 SHT_FINI_ARRAY = 15
304 SHT_PREINIT_ARRAY = 16
305 SHT_GROUP = 17
306 SHT_SYMTAB_SHNDX = 18
307 SHT_RELR = 19
308 SHT_GNU_ATTRIBUTES = 0x6ffffff5
309 SHT_GNU_HASH = 0x6ffffff6
310 SHT_GNU_LIBLIST = 0x6ffffff7
311 SHT_CHECKSUM = 0x6ffffff8
312 SHT_SUNW_move = 0x6ffffffa
313 SHT_SUNW_COMDAT = 0x6ffffffb
314 SHT_SUNW_syminfo = 0x6ffffffc
315 SHT_GNU_verdef = 0x6ffffffd
316 SHT_GNU_verneed = 0x6ffffffe
317 SHT_GNU_versym = 0x6fffffff
319 class ShtALPHA(enum.Enum):
320 """Supplemental SHT_* constants for EM_ALPHA."""
321 SHT_ALPHA_DEBUG = 0x70000001
322 SHT_ALPHA_REGINFO = 0x70000002
324 class ShtARM(enum.Enum):
325 """Supplemental SHT_* constants for EM_ARM."""
326 SHT_ARM_EXIDX = 0x70000001
327 SHT_ARM_PREEMPTMAP = 0x70000002
328 SHT_ARM_ATTRIBUTES = 0x70000003
330 class ShtCSKY(enum.Enum):
331 """Supplemental SHT_* constants for EM_CSKY."""
332 SHT_CSKY_ATTRIBUTES = 0x70000001
334 class ShtIA_64(enum.Enum):
335 """Supplemental SHT_* constants for EM_IA_64."""
336 SHT_IA_64_EXT = 0x70000000
337 SHT_IA_64_UNWIND = 0x70000001
339 class ShtMIPS(enum.Enum):
340 """Supplemental SHT_* constants for EM_MIPS."""
341 SHT_MIPS_LIBLIST = 0x70000000
342 SHT_MIPS_MSYM = 0x70000001
343 SHT_MIPS_CONFLICT = 0x70000002
344 SHT_MIPS_GPTAB = 0x70000003
345 SHT_MIPS_UCODE = 0x70000004
346 SHT_MIPS_DEBUG = 0x70000005
347 SHT_MIPS_REGINFO = 0x70000006
348 SHT_MIPS_PACKAGE = 0x70000007
349 SHT_MIPS_PACKSYM = 0x70000008
350 SHT_MIPS_RELD = 0x70000009
351 SHT_MIPS_IFACE = 0x7000000b
352 SHT_MIPS_CONTENT = 0x7000000c
353 SHT_MIPS_OPTIONS = 0x7000000d
354 SHT_MIPS_SHDR = 0x70000010
355 SHT_MIPS_FDESC = 0x70000011
356 SHT_MIPS_EXTSYM = 0x70000012
357 SHT_MIPS_DENSE = 0x70000013
358 SHT_MIPS_PDESC = 0x70000014
359 SHT_MIPS_LOCSYM = 0x70000015
360 SHT_MIPS_AUXSYM = 0x70000016
361 SHT_MIPS_OPTSYM = 0x70000017
362 SHT_MIPS_LOCSTR = 0x70000018
363 SHT_MIPS_LINE = 0x70000019
364 SHT_MIPS_RFDESC = 0x7000001a
365 SHT_MIPS_DELTASYM = 0x7000001b
366 SHT_MIPS_DELTAINST = 0x7000001c
367 SHT_MIPS_DELTACLASS = 0x7000001d
368 SHT_MIPS_DWARF = 0x7000001e
369 SHT_MIPS_DELTADECL = 0x7000001f
370 SHT_MIPS_SYMBOL_LIB = 0x70000020
371 SHT_MIPS_EVENTS = 0x70000021
372 SHT_MIPS_TRANSLATE = 0x70000022
373 SHT_MIPS_PIXIE = 0x70000023
374 SHT_MIPS_XLATE = 0x70000024
375 SHT_MIPS_XLATE_DEBUG = 0x70000025
376 SHT_MIPS_WHIRL = 0x70000026
377 SHT_MIPS_EH_REGION = 0x70000027
378 SHT_MIPS_XLATE_OLD = 0x70000028
379 SHT_MIPS_PDR_EXCEPTION = 0x70000029
380 SHT_MIPS_XHASH = 0x7000002b
382 class ShtPARISC(enum.Enum):
383 """Supplemental SHT_* constants for EM_PARISC."""
384 SHT_PARISC_EXT = 0x70000000
385 SHT_PARISC_UNWIND = 0x70000001
386 SHT_PARISC_DOC = 0x70000002
388 class ShtRISCV(enum.Enum):
389 """Supplemental SHT_* constants for EM_RISCV."""
390 SHT_RISCV_ATTRIBUTES = 0x70000003
392 class Pf(enum.IntFlag):
393 """Program header flags. Type of Phdr.p_flags values."""
394 PF_X = 1
395 PF_W = 2
396 PF_R = 4
398 class PfARM(enum.IntFlag):
399 """Supplemental PF_* flags for EM_ARM."""
400 PF_ARM_SB = 0x10000000
401 PF_ARM_PI = 0x20000000
402 PF_ARM_ABS = 0x40000000
404 class PfPARISC(enum.IntFlag):
405 """Supplemental PF_* flags for EM_PARISC."""
406 PF_HP_PAGE_SIZE = 0x00100000
407 PF_HP_FAR_SHARED = 0x00200000
408 PF_HP_NEAR_SHARED = 0x00400000
409 PF_HP_CODE = 0x01000000
410 PF_HP_MODIFY = 0x02000000
411 PF_HP_LAZYSWAP = 0x04000000
412 PF_HP_SBP = 0x08000000
414 class PfIA_64(enum.IntFlag):
415 """Supplemental PF_* flags for EM_IA_64."""
416 PF_IA_64_NORECOV = 0x80000000
418 class PfMIPS(enum.IntFlag):
419 """Supplemental PF_* flags for EM_MIPS."""
420 PF_MIPS_LOCAL = 0x10000000
422 class Shf(enum.IntFlag):
423 """Section flags. Type of Shdr.sh_type values."""
424 SHF_WRITE = 1 << 0
425 SHF_ALLOC = 1 << 1
426 SHF_EXECINSTR = 1 << 2
427 SHF_MERGE = 1 << 4
428 SHF_STRINGS = 1 << 5
429 SHF_INFO_LINK = 1 << 6
430 SHF_LINK_ORDER = 1 << 7
431 SHF_OS_NONCONFORMING = 256
432 SHF_GROUP = 1 << 9
433 SHF_TLS = 1 << 10
434 SHF_COMPRESSED = 1 << 11
435 SHF_GNU_RETAIN = 1 << 21
436 SHF_ORDERED = 1 << 30
437 SHF_EXCLUDE = 1 << 31
439 class ShfALPHA(enum.IntFlag):
440 """Supplemental SHF_* constants for EM_ALPHA."""
441 SHF_ALPHA_GPREL = 0x10000000
443 class ShfARM(enum.IntFlag):
444 """Supplemental SHF_* constants for EM_ARM."""
445 SHF_ARM_ENTRYSECT = 0x10000000
446 SHF_ARM_COMDEF = 0x80000000
448 class ShfIA_64(enum.IntFlag):
449 """Supplemental SHF_* constants for EM_IA_64."""
450 SHF_IA_64_SHORT = 0x10000000
451 SHF_IA_64_NORECOV = 0x20000000
453 class ShfMIPS(enum.IntFlag):
454 """Supplemental SHF_* constants for EM_MIPS."""
455 SHF_MIPS_GPREL = 0x10000000
456 SHF_MIPS_MERGE = 0x20000000
457 SHF_MIPS_ADDR = 0x40000000
458 SHF_MIPS_STRINGS = 0x80000000
459 SHF_MIPS_NOSTRIP = 0x08000000
460 SHF_MIPS_LOCAL = 0x04000000
461 SHF_MIPS_NAMES = 0x02000000
462 SHF_MIPS_NODUPE = 0x01000000
464 class ShfPARISC(enum.IntFlag):
465 """Supplemental SHF_* constants for EM_PARISC."""
466 SHF_PARISC_SHORT = 0x20000000
467 SHF_PARISC_HUGE = 0x40000000
468 SHF_PARISC_SBP = 0x80000000
470 class Stb(_OpenIntEnum):
471 """ELF symbol binding type."""
472 STB_LOCAL = 0
473 STB_GLOBAL = 1
474 STB_WEAK = 2
475 STB_GNU_UNIQUE = 10
476 STB_MIPS_SPLIT_COMMON = 13
478 class Stt(_OpenIntEnum):
479 """ELF symbol type."""
480 STT_NOTYPE = 0
481 STT_OBJECT = 1
482 STT_FUNC = 2
483 STT_SECTION = 3
484 STT_FILE = 4
485 STT_COMMON = 5
486 STT_TLS = 6
487 STT_GNU_IFUNC = 10
489 class SttARM(enum.Enum):
490 """Supplemental STT_* constants for EM_ARM."""
491 STT_ARM_TFUNC = 13
492 STT_ARM_16BIT = 15
494 class SttPARISC(enum.Enum):
495 """Supplemental STT_* constants for EM_PARISC."""
496 STT_HP_OPAQUE = 11
497 STT_HP_STUB = 12
498 STT_PARISC_MILLICODE = 13
500 class SttSPARC(enum.Enum):
501 """Supplemental STT_* constants for EM_SPARC."""
502 STT_SPARC_REGISTER = 13
504 class SttX86_64(enum.Enum):
505 """Supplemental STT_* constants for EM_X86_64."""
506 SHT_X86_64_UNWIND = 0x70000001
508 class Pt(_OpenIntEnum):
509 """ELF program header types. Type of Phdr.p_type."""
510 PT_NULL = 0
511 PT_LOAD = 1
512 PT_DYNAMIC = 2
513 PT_INTERP = 3
514 PT_NOTE = 4
515 PT_SHLIB = 5
516 PT_PHDR = 6
517 PT_TLS = 7
518 PT_NUM = 8
519 PT_GNU_EH_FRAME = 0x6474e550
520 PT_GNU_STACK = 0x6474e551
521 PT_GNU_RELRO = 0x6474e552
522 PT_GNU_PROPERTY = 0x6474e553
523 PT_SUNWBSS = 0x6ffffffa
524 PT_SUNWSTACK = 0x6ffffffb
526 class PtAARCH64(enum.Enum):
527 """Supplemental PT_* constants for EM_AARCH64."""
528 PT_AARCH64_MEMTAG_MTE = 0x70000002
530 class PtARM(enum.Enum):
531 """Supplemental PT_* constants for EM_ARM."""
532 PT_ARM_EXIDX = 0x70000001
534 class PtIA_64(enum.Enum):
535 """Supplemental PT_* constants for EM_IA_64."""
536 PT_IA_64_HP_OPT_ANOT = 0x60000012
537 PT_IA_64_HP_HSL_ANOT = 0x60000013
538 PT_IA_64_HP_STACK = 0x60000014
539 PT_IA_64_ARCHEXT = 0x70000000
540 PT_IA_64_UNWIND = 0x70000001
542 class PtMIPS(enum.Enum):
543 """Supplemental PT_* constants for EM_MIPS."""
544 PT_MIPS_REGINFO = 0x70000000
545 PT_MIPS_RTPROC = 0x70000001
546 PT_MIPS_OPTIONS = 0x70000002
547 PT_MIPS_ABIFLAGS = 0x70000003
549 class PtPARISC(enum.Enum):
550 """Supplemental PT_* constants for EM_PARISC."""
551 PT_HP_TLS = 0x60000000
552 PT_HP_CORE_NONE = 0x60000001
553 PT_HP_CORE_VERSION = 0x60000002
554 PT_HP_CORE_KERNEL = 0x60000003
555 PT_HP_CORE_COMM = 0x60000004
556 PT_HP_CORE_PROC = 0x60000005
557 PT_HP_CORE_LOADABLE = 0x60000006
558 PT_HP_CORE_STACK = 0x60000007
559 PT_HP_CORE_SHM = 0x60000008
560 PT_HP_CORE_MMF = 0x60000009
561 PT_HP_PARALLEL = 0x60000010
562 PT_HP_FASTBIND = 0x60000011
563 PT_HP_OPT_ANNOT = 0x60000012
564 PT_HP_HSL_ANNOT = 0x60000013
565 PT_HP_STACK = 0x60000014
566 PT_PARISC_ARCHEXT = 0x70000000
567 PT_PARISC_UNWIND = 0x70000001
569 class PtRISCV(enum.Enum):
570 """Supplemental PT_* constants for EM_RISCV."""
571 PT_RISCV_ATTRIBUTES = 0x70000003
573 class Dt(_OpenIntEnum):
574 """ELF dynamic segment tags. Type of Dyn.d_val."""
575 DT_NULL = 0
576 DT_NEEDED = 1
577 DT_PLTRELSZ = 2
578 DT_PLTGOT = 3
579 DT_HASH = 4
580 DT_STRTAB = 5
581 DT_SYMTAB = 6
582 DT_RELA = 7
583 DT_RELASZ = 8
584 DT_RELAENT = 9
585 DT_STRSZ = 10
586 DT_SYMENT = 11
587 DT_INIT = 12
588 DT_FINI = 13
589 DT_SONAME = 14
590 DT_RPATH = 15
591 DT_SYMBOLIC = 16
592 DT_REL = 17
593 DT_RELSZ = 18
594 DT_RELENT = 19
595 DT_PLTREL = 20
596 DT_DEBUG = 21
597 DT_TEXTREL = 22
598 DT_JMPREL = 23
599 DT_BIND_NOW = 24
600 DT_INIT_ARRAY = 25
601 DT_FINI_ARRAY = 26
602 DT_INIT_ARRAYSZ = 27
603 DT_FINI_ARRAYSZ = 28
604 DT_RUNPATH = 29
605 DT_FLAGS = 30
606 DT_PREINIT_ARRAY = 32
607 DT_PREINIT_ARRAYSZ = 33
608 DT_SYMTAB_SHNDX = 34
609 DT_RELRSZ = 35
610 DT_RELR = 36
611 DT_RELRENT = 37
612 DT_GNU_PRELINKED = 0x6ffffdf5
613 DT_GNU_CONFLICTSZ = 0x6ffffdf6
614 DT_GNU_LIBLISTSZ = 0x6ffffdf7
615 DT_CHECKSUM = 0x6ffffdf8
616 DT_PLTPADSZ = 0x6ffffdf9
617 DT_MOVEENT = 0x6ffffdfa
618 DT_MOVESZ = 0x6ffffdfb
619 DT_FEATURE_1 = 0x6ffffdfc
620 DT_POSFLAG_1 = 0x6ffffdfd
621 DT_SYMINSZ = 0x6ffffdfe
622 DT_SYMINENT = 0x6ffffdff
623 DT_GNU_HASH = 0x6ffffef5
624 DT_TLSDESC_PLT = 0x6ffffef6
625 DT_TLSDESC_GOT = 0x6ffffef7
626 DT_GNU_CONFLICT = 0x6ffffef8
627 DT_GNU_LIBLIST = 0x6ffffef9
628 DT_CONFIG = 0x6ffffefa
629 DT_DEPAUDIT = 0x6ffffefb
630 DT_AUDIT = 0x6ffffefc
631 DT_PLTPAD = 0x6ffffefd
632 DT_MOVETAB = 0x6ffffefe
633 DT_SYMINFO = 0x6ffffeff
634 DT_VERSYM = 0x6ffffff0
635 DT_RELACOUNT = 0x6ffffff9
636 DT_RELCOUNT = 0x6ffffffa
637 DT_FLAGS_1 = 0x6ffffffb
638 DT_VERDEF = 0x6ffffffc
639 DT_VERDEFNUM = 0x6ffffffd
640 DT_VERNEED = 0x6ffffffe
641 DT_VERNEEDNUM = 0x6fffffff
642 DT_AUXILIARY = 0x7ffffffd
643 DT_FILTER = 0x7fffffff
645 class DtAARCH64(enum.Enum):
646 """Supplemental DT_* constants for EM_AARCH64."""
647 DT_AARCH64_BTI_PLT = 0x70000001
648 DT_AARCH64_PAC_PLT = 0x70000003
649 DT_AARCH64_VARIANT_PCS = 0x70000005
651 class DtALPHA(enum.Enum):
652 """Supplemental DT_* constants for EM_ALPHA."""
653 DT_ALPHA_PLTRO = 0x70000000
655 class DtALTERA_NIOS2(enum.Enum):
656 """Supplemental DT_* constants for EM_ALTERA_NIOS2."""
657 DT_NIOS2_GP = 0x70000002
659 class DtIA_64(enum.Enum):
660 """Supplemental DT_* constants for EM_IA_64."""
661 DT_IA_64_PLT_RESERVE = 0x70000000
663 class DtMIPS(enum.Enum):
664 """Supplemental DT_* constants for EM_MIPS."""
665 DT_MIPS_RLD_VERSION = 0x70000001
666 DT_MIPS_TIME_STAMP = 0x70000002
667 DT_MIPS_ICHECKSUM = 0x70000003
668 DT_MIPS_IVERSION = 0x70000004
669 DT_MIPS_FLAGS = 0x70000005
670 DT_MIPS_BASE_ADDRESS = 0x70000006
671 DT_MIPS_MSYM = 0x70000007
672 DT_MIPS_CONFLICT = 0x70000008
673 DT_MIPS_LIBLIST = 0x70000009
674 DT_MIPS_LOCAL_GOTNO = 0x7000000a
675 DT_MIPS_CONFLICTNO = 0x7000000b
676 DT_MIPS_LIBLISTNO = 0x70000010
677 DT_MIPS_SYMTABNO = 0x70000011
678 DT_MIPS_UNREFEXTNO = 0x70000012
679 DT_MIPS_GOTSYM = 0x70000013
680 DT_MIPS_HIPAGENO = 0x70000014
681 DT_MIPS_RLD_MAP = 0x70000016
682 DT_MIPS_DELTA_CLASS = 0x70000017
683 DT_MIPS_DELTA_CLASS_NO = 0x70000018
684 DT_MIPS_DELTA_INSTANCE = 0x70000019
685 DT_MIPS_DELTA_INSTANCE_NO = 0x7000001a
686 DT_MIPS_DELTA_RELOC = 0x7000001b
687 DT_MIPS_DELTA_RELOC_NO = 0x7000001c
688 DT_MIPS_DELTA_SYM = 0x7000001d
689 DT_MIPS_DELTA_SYM_NO = 0x7000001e
690 DT_MIPS_DELTA_CLASSSYM = 0x70000020
691 DT_MIPS_DELTA_CLASSSYM_NO = 0x70000021
692 DT_MIPS_CXX_FLAGS = 0x70000022
693 DT_MIPS_PIXIE_INIT = 0x70000023
694 DT_MIPS_SYMBOL_LIB = 0x70000024
695 DT_MIPS_LOCALPAGE_GOTIDX = 0x70000025
696 DT_MIPS_LOCAL_GOTIDX = 0x70000026
697 DT_MIPS_HIDDEN_GOTIDX = 0x70000027
698 DT_MIPS_PROTECTED_GOTIDX = 0x70000028
699 DT_MIPS_OPTIONS = 0x70000029
700 DT_MIPS_INTERFACE = 0x7000002a
701 DT_MIPS_DYNSTR_ALIGN = 0x7000002b
702 DT_MIPS_INTERFACE_SIZE = 0x7000002c
703 DT_MIPS_RLD_TEXT_RESOLVE_ADDR = 0x7000002d
704 DT_MIPS_PERF_SUFFIX = 0x7000002e
705 DT_MIPS_COMPACT_SIZE = 0x7000002f
706 DT_MIPS_GP_VALUE = 0x70000030
707 DT_MIPS_AUX_DYNAMIC = 0x70000031
708 DT_MIPS_PLTGOT = 0x70000032
709 DT_MIPS_RWPLT = 0x70000034
710 DT_MIPS_RLD_MAP_REL = 0x70000035
711 DT_MIPS_XHASH = 0x70000036
713 class DtPPC(enum.Enum):
714 """Supplemental DT_* constants for EM_PPC."""
715 DT_PPC_GOT = 0x70000000
716 DT_PPC_OPT = 0x70000001
718 class DtPPC64(enum.Enum):
719 """Supplemental DT_* constants for EM_PPC64."""
720 DT_PPC64_GLINK = 0x70000000
721 DT_PPC64_OPD = 0x70000001
722 DT_PPC64_OPDSZ = 0x70000002
723 DT_PPC64_OPT = 0x70000003
725 class DtRISCV(enum.Enum):
726 """Supplemental DT_* constants for EM_RISCV."""
727 DT_RISCV_VARIANT_CC = 0x70000001
729 class DtSPARC(enum.Enum):
730 """Supplemental DT_* constants for EM_SPARC."""
731 DT_SPARC_REGISTER = 0x70000001
733 class StInfo:
734 """ELF symbol binding and type. Type of the Sym.st_info field."""
735 def __init__(self, arg0, arg1=None):
736 if isinstance(arg0, int) and arg1 is None:
737 self.bind = Stb(arg0 >> 4)
738 self.type = Stt(arg0 & 15)
739 else:
740 self.bind = Stb(arg0)
741 self.type = Stt(arg1)
743 def value(self):
744 """Returns the raw value for the bind/type combination."""
745 return (self.bind.value() << 4) | (self.type.value())
747 # Type in an ELF file. Used for deserialization.
748 _Layout = collections.namedtuple('_Layout', 'unpack size')
750 def _define_layouts(baseclass: type, layout32: str, layout64: str,
751 types=None, fields32=None):
752 """Assign variants dict to baseclass.
754 The variants dict is indexed by (ElfClass, ElfData) pairs, and its
755 values are _Layout instances.
758 struct32 = struct.Struct(layout32)
759 struct64 = struct.Struct(layout64)
761 # Check that the struct formats yield the right number of components.
762 for s in (struct32, struct64):
763 example = s.unpack(b' ' * s.size)
764 if len(example) != len(baseclass._fields):
765 raise ValueError('{!r} yields wrong field count: {} != {}'.format(
766 s.format, len(example), len(baseclass._fields)))
768 # Check that field names in types are correct.
769 if types is None:
770 types = ()
771 for n in types:
772 if n not in baseclass._fields:
773 raise ValueError('{} does not have field {!r}'.format(
774 baseclass.__name__, n))
776 if fields32 is not None \
777 and set(fields32) != set(baseclass._fields):
778 raise ValueError('{!r} is not a permutation of the fields {!r}'.format(
779 fields32, baseclass._fields))
781 def unique_name(name, used_names = (set((baseclass.__name__,))
782 | set(baseclass._fields)
783 | {n.__name__
784 for n in (types or {}).values()})):
785 """Find a name that is not used for a class or field name."""
786 candidate = name
787 n = 0
788 while candidate in used_names:
789 n += 1
790 candidate = '{}{}'.format(name, n)
791 used_names.add(candidate)
792 return candidate
794 blob_name = unique_name('blob')
795 struct_unpack_name = unique_name('struct_unpack')
796 comps_name = unique_name('comps')
798 layouts = {}
799 for (bits, elfclass, layout, fields) in (
800 (32, ElfClass.ELFCLASS32, layout32, fields32),
801 (64, ElfClass.ELFCLASS64, layout64, None),
803 for (elfdata, structprefix, funcsuffix) in (
804 (ElfData.ELFDATA2LSB, '<', 'LE'),
805 (ElfData.ELFDATA2MSB, '>', 'BE'),
807 env = {
808 baseclass.__name__: baseclass,
809 struct_unpack_name: struct.unpack,
812 # Add the type converters.
813 if types:
814 for cls in types.values():
815 env[cls.__name__] = cls
817 funcname = ''.join(
818 ('unpack_', baseclass.__name__, str(bits), funcsuffix))
820 code = '''
821 def {funcname}({blob_name}):
822 '''.format(funcname=funcname, blob_name=blob_name)
824 indent = ' ' * 4
825 unpack_call = '{}({!r}, {})'.format(
826 struct_unpack_name, structprefix + layout, blob_name)
827 field_names = ', '.join(baseclass._fields)
828 if types is None and fields is None:
829 code += '{}return {}({})\n'.format(
830 indent, baseclass.__name__, unpack_call)
831 else:
832 # Destructuring tuple assignment.
833 if fields is None:
834 code += '{}{} = {}\n'.format(
835 indent, field_names, unpack_call)
836 else:
837 # Use custom field order.
838 code += '{}{} = {}\n'.format(
839 indent, ', '.join(fields), unpack_call)
841 # Perform the type conversions.
842 for n in baseclass._fields:
843 if n in types:
844 code += '{}{} = {}({})\n'.format(
845 indent, n, types[n].__name__, n)
846 # Create the named tuple.
847 code += '{}return {}({})\n'.format(
848 indent, baseclass.__name__, field_names)
850 exec(code, env)
851 layouts[(elfclass, elfdata)] = _Layout(
852 env[funcname], struct.calcsize(layout))
853 baseclass.layouts = layouts
856 # Corresponds to EI_* indices into Elf*_Ehdr.e_indent.
857 class Ident(collections.namedtuple('Ident',
858 'ei_mag ei_class ei_data ei_version ei_osabi ei_abiversion ei_pad')):
860 def __new__(cls, *args):
861 """Construct an object from a blob or its constituent fields."""
862 if len(args) == 1:
863 return cls.unpack(args[0])
864 return cls.__base__.__new__(cls, *args)
866 @staticmethod
867 def unpack(blob: memoryview) -> 'Ident':
868 """Parse raws data into a tuple."""
869 ei_mag, ei_class, ei_data, ei_version, ei_osabi, ei_abiversion, \
870 ei_pad = struct.unpack('4s5B7s', blob)
871 return Ident(ei_mag, ElfClass(ei_class), ElfData(ei_data),
872 ei_version, ei_osabi, ei_abiversion, ei_pad)
873 size = 16
875 # Corresponds to Elf32_Ehdr and Elf64_Ehdr.
876 Ehdr = collections.namedtuple('Ehdr',
877 'e_ident e_type e_machine e_version e_entry e_phoff e_shoff e_flags'
878 + ' e_ehsize e_phentsize e_phnum e_shentsize e_shnum e_shstrndx')
879 _define_layouts(Ehdr,
880 layout32='16s2H5I6H',
881 layout64='16s2HI3QI6H',
882 types=dict(e_ident=Ident,
883 e_machine=Machine,
884 e_type=Et,
885 e_shstrndx=Shn))
887 # Corresponds to Elf32_Phdr and Elf64_Pdhr. Order follows the latter.
888 Phdr = collections.namedtuple('Phdr',
889 'p_type p_flags p_offset p_vaddr p_paddr p_filesz p_memsz p_align')
890 _define_layouts(Phdr,
891 layout32='8I',
892 fields32=('p_type', 'p_offset', 'p_vaddr', 'p_paddr',
893 'p_filesz', 'p_memsz', 'p_flags', 'p_align'),
894 layout64='2I6Q',
895 types=dict(p_type=Pt, p_flags=Pf))
898 # Corresponds to Elf32_Shdr and Elf64_Shdr.
899 class Shdr(collections.namedtuple('Shdr',
900 'sh_name sh_type sh_flags sh_addr sh_offset sh_size sh_link sh_info'
901 + ' sh_addralign sh_entsize')):
902 def resolve(self, strtab: 'StringTable') -> 'Shdr':
903 """Resolve sh_name using a string table."""
904 return self.__class__(strtab.get(self[0]), *self[1:])
905 _define_layouts(Shdr,
906 layout32='10I',
907 layout64='2I4Q2I2Q',
908 types=dict(sh_type=Sht,
909 sh_flags=Shf,
910 sh_link=Shn))
912 # Corresponds to Elf32_Dyn and Elf64_Dyn. The nesting through the
913 # d_un union is skipped, and d_ptr is missing (its representation in
914 # Python would be identical to d_val).
915 Dyn = collections.namedtuple('Dyn', 'd_tag d_val')
916 _define_layouts(Dyn,
917 layout32='2i',
918 layout64='2q',
919 types=dict(d_tag=Dt))
921 # Corresponds to Elf32_Sym and Elf64_Sym.
922 class Sym(collections.namedtuple('Sym',
923 'st_name st_info st_other st_shndx st_value st_size')):
924 def resolve(self, strtab: 'StringTable') -> 'Sym':
925 """Resolve st_name using a string table."""
926 return self.__class__(strtab.get(self[0]), *self[1:])
927 _define_layouts(Sym,
928 layout32='3I2BH',
929 layout64='I2BH2Q',
930 fields32=('st_name', 'st_value', 'st_size', 'st_info',
931 'st_other', 'st_shndx'),
932 types=dict(st_shndx=Shn,
933 st_info=StInfo))
935 # Corresponds to Elf32_Rel and Elf64_Rel.
936 Rel = collections.namedtuple('Rel', 'r_offset r_info')
937 _define_layouts(Rel,
938 layout32='2I',
939 layout64='2Q')
941 # Corresponds to Elf32_Rel and Elf64_Rel.
942 Rela = collections.namedtuple('Rela', 'r_offset r_info r_addend')
943 _define_layouts(Rela,
944 layout32='3I',
945 layout64='3Q')
947 class StringTable:
948 """ELF string table."""
949 def __init__(self, blob):
950 """Create a new string table backed by the data in the blob.
952 blob: a memoryview-like object
955 self.blob = blob
957 def get(self, index) -> bytes:
958 """Returns the null-terminated byte string at the index."""
959 blob = self.blob
960 endindex = index
961 while True:
962 if blob[endindex] == 0:
963 return bytes(blob[index:endindex])
964 endindex += 1
966 class Image:
967 """ELF image parser."""
968 def __init__(self, image):
969 """Create an ELF image from binary image data.
971 image: a memoryview-like object that supports efficient range
972 subscripting.
975 self.image = image
976 ident = self.read(Ident, 0)
977 classdata = (ident.ei_class, ident.ei_data)
978 # Set self.Ehdr etc. to the subtypes with the right parsers.
979 for typ in (Ehdr, Phdr, Shdr, Dyn, Sym, Rel, Rela):
980 setattr(self, typ.__name__, typ.layouts.get(classdata, None))
982 if self.Ehdr is not None:
983 self.ehdr = self.read(self.Ehdr, 0)
984 self._shdr_num = self._compute_shdr_num()
985 else:
986 self.ehdr = None
987 self._shdr_num = 0
989 self._section = {}
990 self._stringtab = {}
992 if self._shdr_num > 0:
993 self._shdr_strtab = self._find_shdr_strtab()
994 else:
995 self._shdr_strtab = None
997 @staticmethod
998 def readfile(path: str) -> 'Image':
999 """Reads the ELF file at the specified path."""
1000 with open(path, 'rb') as inp:
1001 return Image(memoryview(inp.read()))
1003 def _compute_shdr_num(self) -> int:
1004 """Computes the actual number of section headers."""
1005 shnum = self.ehdr.e_shnum
1006 if shnum == 0:
1007 if self.ehdr.e_shoff == 0 or self.ehdr.e_shentsize == 0:
1008 # No section headers.
1009 return 0
1010 # Otherwise the extension mechanism is used (which may be
1011 # needed because e_shnum is just 16 bits).
1012 return self.read(self.Shdr, self.ehdr.e_shoff).sh_size
1013 return shnum
1015 def _find_shdr_strtab(self) -> StringTable:
1016 """Finds the section header string table (maybe via extensions)."""
1017 shstrndx = self.ehdr.e_shstrndx
1018 if shstrndx == Shn.SHN_XINDEX:
1019 shstrndx = self.read(self.Shdr, self.ehdr.e_shoff).sh_link
1020 return self._find_stringtab(shstrndx)
1022 def read(self, typ: type, offset:int ):
1023 """Reads an object at a specific offset.
1025 The type must have been enhanced using _define_variants.
1028 return typ.unpack(self.image[offset: offset + typ.size])
1030 def phdrs(self) -> Phdr:
1031 """Generator iterating over the program headers."""
1032 if self.ehdr is None:
1033 return
1034 size = self.ehdr.e_phentsize
1035 if size != self.Phdr.size:
1036 raise ValueError('Unexpected Phdr size in ELF header: {} != {}'
1037 .format(size, self.Phdr.size))
1039 offset = self.ehdr.e_phoff
1040 for _ in range(self.ehdr.e_phnum):
1041 yield self.read(self.Phdr, offset)
1042 offset += size
1044 def shdrs(self, resolve: bool=True) -> Shdr:
1045 """Generator iterating over the section headers.
1047 If resolve, section names are automatically translated
1048 using the section header string table.
1051 if self._shdr_num == 0:
1052 return
1054 size = self.ehdr.e_shentsize
1055 if size != self.Shdr.size:
1056 raise ValueError('Unexpected Shdr size in ELF header: {} != {}'
1057 .format(size, self.Shdr.size))
1059 offset = self.ehdr.e_shoff
1060 for _ in range(self._shdr_num):
1061 shdr = self.read(self.Shdr, offset)
1062 if resolve:
1063 shdr = shdr.resolve(self._shdr_strtab)
1064 yield shdr
1065 offset += size
1067 def dynamic(self) -> Dyn:
1068 """Generator iterating over the dynamic segment."""
1069 for phdr in self.phdrs():
1070 if phdr.p_type == Pt.PT_DYNAMIC:
1071 # Pick the first dynamic segment, like the loader.
1072 if phdr.p_filesz == 0:
1073 # Probably separated debuginfo.
1074 return
1075 offset = phdr.p_offset
1076 end = offset + phdr.p_memsz
1077 size = self.Dyn.size
1078 while True:
1079 next_offset = offset + size
1080 if next_offset > end:
1081 raise ValueError(
1082 'Dynamic segment size {} is not a multiple of Dyn size {}'.format(
1083 phdr.p_memsz, size))
1084 yield self.read(self.Dyn, offset)
1085 if next_offset == end:
1086 return
1087 offset = next_offset
1089 def syms(self, shdr: Shdr, resolve: bool=True) -> Sym:
1090 """A generator iterating over a symbol table.
1092 If resolve, symbol names are automatically translated using
1093 the string table for the symbol table.
1096 assert shdr.sh_type == Sht.SHT_SYMTAB
1097 size = shdr.sh_entsize
1098 if size != self.Sym.size:
1099 raise ValueError('Invalid symbol table entry size {}'.format(size))
1100 offset = shdr.sh_offset
1101 end = shdr.sh_offset + shdr.sh_size
1102 if resolve:
1103 strtab = self._find_stringtab(shdr.sh_link)
1104 while offset < end:
1105 sym = self.read(self.Sym, offset)
1106 if resolve:
1107 sym = sym.resolve(strtab)
1108 yield sym
1109 offset += size
1110 if offset != end:
1111 raise ValueError('Symbol table is not a multiple of entry size')
1113 def lookup_string(self, strtab_index: int, strtab_offset: int) -> bytes:
1114 """Looks up a string in a string table identified by its link index."""
1115 try:
1116 strtab = self._stringtab[strtab_index]
1117 except KeyError:
1118 strtab = self._find_stringtab(strtab_index)
1119 return strtab.get(strtab_offset)
1121 def find_section(self, shndx: Shn) -> Shdr:
1122 """Returns the section header for the indexed section.
1124 The section name is not resolved.
1126 try:
1127 return self._section[shndx]
1128 except KeyError:
1129 pass
1130 if shndx in Shn:
1131 raise ValueError('Reserved section index {}'.format(shndx))
1132 idx = shndx.value
1133 if idx < 0 or idx > self._shdr_num:
1134 raise ValueError('Section index {} out of range [0, {})'.format(
1135 idx, self._shdr_num))
1136 shdr = self.read(
1137 self.Shdr, self.ehdr.e_shoff + idx * self.Shdr.size)
1138 self._section[shndx] = shdr
1139 return shdr
1141 def _find_stringtab(self, sh_link: int) -> StringTable:
1142 if sh_link in self._stringtab:
1143 return self._stringtab
1144 if sh_link < 0 or sh_link >= self._shdr_num:
1145 raise ValueError('Section index {} out of range [0, {})'.format(
1146 sh_link, self._shdr_num))
1147 shdr = self.read(
1148 self.Shdr, self.ehdr.e_shoff + sh_link * self.Shdr.size)
1149 if shdr.sh_type != Sht.SHT_STRTAB:
1150 raise ValueError(
1151 'Section {} is not a string table: {}'.format(
1152 sh_link, shdr.sh_type))
1153 strtab = StringTable(
1154 self.image[shdr.sh_offset:shdr.sh_offset + shdr.sh_size])
1155 # This could retrain essentially arbitrary amounts of data,
1156 # but caching string tables seems important for performance.
1157 self._stringtab[sh_link] = strtab
1158 return strtab
1161 __all__ = [name for name in dir() if name[0].isupper()]