DWARF 5 operations and DWARF5 location lists (#418)
[pyelftools.git] / elftools / elf / elffile.py
1 #-------------------------------------------------------------------------------
2 # elftools: elf/elffile.py
3 #
4 # ELFFile - main class for accessing ELF files
5 #
6 # Eli Bendersky (eliben@gmail.com)
7 # This code is in the public domain
8 #-------------------------------------------------------------------------------
9 import io
10 import struct
11 import zlib
12
13 try:
14 import resource
15 PAGESIZE = resource.getpagesize()
16 except ImportError:
17 try:
18 # Windows system
19 import mmap
20 PAGESIZE = mmap.PAGESIZE
21 except ImportError:
22 # Jython
23 PAGESIZE = 4096
24
25 from ..common.py3compat import BytesIO
26 from ..common.exceptions import ELFError
27 from ..common.utils import struct_parse, elf_assert
28 from .structs import ELFStructs
29 from .sections import (
30 Section, StringTableSection, SymbolTableSection,
31 SymbolTableIndexSection, SUNWSyminfoTableSection, NullSection,
32 NoteSection, StabSection, ARMAttributesSection)
33 from .dynamic import DynamicSection, DynamicSegment
34 from .relocation import (RelocationSection, RelocationHandler,
35 RelrRelocationSection)
36 from .gnuversions import (
37 GNUVerNeedSection, GNUVerDefSection,
38 GNUVerSymSection)
39 from .segments import Segment, InterpSegment, NoteSegment
40 from ..dwarf.dwarfinfo import DWARFInfo, DebugSectionDescriptor, DwarfConfig
41 from ..ehabi.ehabiinfo import EHABIInfo
42 from .hash import ELFHashSection, GNUHashSection
43 from .constants import SHN_INDICES
44
45 class ELFFile(object):
46 """ Creation: the constructor accepts a stream (file-like object) with the
47 contents of an ELF file.
48
49 Accessible attributes:
50
51 stream:
52 The stream holding the data of the file - must be a binary
53 stream (bytes, not string).
54
55 elfclass:
56 32 or 64 - specifies the word size of the target machine
57
58 little_endian:
59 boolean - specifies the target machine's endianness
60
61 elftype:
62 string or int, either known value of E_TYPE enum defining ELF
63 type (e.g. executable, dynamic library or core dump) or integral
64 unparsed value
65
66 header:
67 the complete ELF file header
68
69 e_ident_raw:
70 the raw e_ident field of the header
71 """
72 def __init__(self, stream):
73 self.stream = stream
74 self._identify_file()
75 self.structs = ELFStructs(
76 little_endian=self.little_endian,
77 elfclass=self.elfclass)
78
79 self.structs.create_basic_structs()
80 self.header = self._parse_elf_header()
81 self.structs.create_advanced_structs(
82 self['e_type'],
83 self['e_machine'],
84 self['e_ident']['EI_OSABI'])
85 self.stream.seek(0)
86 self.e_ident_raw = self.stream.read(16)
87
88 self._section_header_stringtable = \
89 self._get_section_header_stringtable()
90 self._section_name_map = None
91
92 def num_sections(self):
93 """ Number of sections in the file
94 """
95 if self['e_shoff'] == 0:
96 return 0
97 # From the ELF ABI documentation at
98 # https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.sheader.html:
99 # "e_shnum normally tells how many entries the section header table
100 # contains. [...] If the number of sections is greater than or equal to
101 # SHN_LORESERVE (0xff00), e_shnum has the value SHN_UNDEF (0) and the
102 # actual number of section header table entries is contained in the
103 # sh_size field of the section header at index 0 (otherwise, the sh_size
104 # member of the initial entry contains 0)."
105 if self['e_shnum'] == 0:
106 return self._get_section_header(0)['sh_size']
107 return self['e_shnum']
108
109 def get_section(self, n):
110 """ Get the section at index #n from the file (Section object or a
111 subclass)
112 """
113 section_header = self._get_section_header(n)
114 return self._make_section(section_header)
115
116 def get_section_by_name(self, name):
117 """ Get a section from the file, by name. Return None if no such
118 section exists.
119 """
120 # The first time this method is called, construct a name to number
121 # mapping
122 #
123 if self._section_name_map is None:
124 self._make_section_name_map()
125 secnum = self._section_name_map.get(name, None)
126 return None if secnum is None else self.get_section(secnum)
127
128 def get_section_index(self, section_name):
129 """ Gets the index of the section by name. Return None if no such
130 section name exists.
131 """
132 # The first time this method is called, construct a name to number
133 # mapping
134 #
135 if self._section_name_map is None:
136 self._make_section_name_map()
137 return self._section_name_map.get(section_name, None)
138
139 def iter_sections(self, type=None):
140 """ Yield all the sections in the file. If the optional |type|
141 parameter is passed, this method will only yield sections of the
142 given type. The parameter value must be a string containing the
143 name of the type as defined in the ELF specification, e.g.
144 'SHT_SYMTAB'.
145 """
146 for i in range(self.num_sections()):
147 section = self.get_section(i)
148 if type is None or section['sh_type'] == type:
149 yield section
150
151 def num_segments(self):
152 """ Number of segments in the file
153 """
154 # From: https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI
155 # Section: 4.1.2 Number of Program Headers
156 # If the number of program headers is greater than or equal to
157 # PN_XNUM (0xffff), this member has the value PN_XNUM
158 # (0xffff). The actual number of program header table entries
159 # is contained in the sh_info field of the section header at
160 # index 0.
161 if self['e_phnum'] < 0xffff:
162 return self['e_phnum']
163 else:
164 return self.get_section(0)['sh_info']
165
166 def get_segment(self, n):
167 """ Get the segment at index #n from the file (Segment object)
168 """
169 segment_header = self._get_segment_header(n)
170 return self._make_segment(segment_header)
171
172 def iter_segments(self, type=None):
173 """ Yield all the segments in the file. If the optional |type|
174 parameter is passed, this method will only yield segments of the
175 given type. The parameter value must be a string containing the
176 name of the type as defined in the ELF specification, e.g.
177 'PT_LOAD'.
178 """
179 for i in range(self.num_segments()):
180 segment = self.get_segment(i)
181 if type is None or segment['p_type'] == type:
182 yield segment
183
184 def address_offsets(self, start, size=1):
185 """ Yield a file offset for each ELF segment containing a memory region.
186
187 A memory region is defined by the range [start...start+size). The
188 offset of the region is yielded.
189 """
190 end = start + size
191 # consider LOAD only to prevent same address being yielded twice
192 for seg in self.iter_segments(type='PT_LOAD'):
193 if (start >= seg['p_vaddr'] and
194 end <= seg['p_vaddr'] + seg['p_filesz']):
195 yield start - seg['p_vaddr'] + seg['p_offset']
196
197 def has_dwarf_info(self):
198 """ Check whether this file appears to have debugging information.
199 We assume that if it has the .debug_info or .zdebug_info section, it
200 has all the other required sections as well.
201 """
202 return bool(self.get_section_by_name('.debug_info') or
203 self.get_section_by_name('.zdebug_info') or
204 self.get_section_by_name('.eh_frame'))
205
206 def get_dwarf_info(self, relocate_dwarf_sections=True):
207 """ Return a DWARFInfo object representing the debugging information in
208 this file.
209
210 If relocate_dwarf_sections is True, relocations for DWARF sections
211 are looked up and applied.
212 """
213 # Expect that has_dwarf_info was called, so at least .debug_info is
214 # present.
215 # Sections that aren't found will be passed as None to DWARFInfo.
216
217 section_names = ('.debug_info', '.debug_aranges', '.debug_abbrev',
218 '.debug_str', '.debug_line', '.debug_frame',
219 '.debug_loc', '.debug_ranges', '.debug_pubtypes',
220 '.debug_pubnames', '.debug_addr',
221 '.debug_str_offsets', '.debug_line_str',
222 '.debug_loclists', '.debug_rnglists')
223
224
225 compressed = bool(self.get_section_by_name('.zdebug_info'))
226 if compressed:
227 section_names = tuple(map(lambda x: '.z' + x[1:], section_names))
228
229 # As it is loaded in the process image, .eh_frame cannot be compressed
230 section_names += ('.eh_frame', )
231
232 (debug_info_sec_name, debug_aranges_sec_name, debug_abbrev_sec_name,
233 debug_str_sec_name, debug_line_sec_name, debug_frame_sec_name,
234 debug_loc_sec_name, debug_ranges_sec_name, debug_pubtypes_name,
235 debug_pubnames_name, debug_addr_name, debug_str_offsets_name,
236 debug_line_str_name, debug_loclists_sec_name, debug_rnglists_sec_name,
237 eh_frame_sec_name) = section_names
238
239 debug_sections = {}
240 for secname in section_names:
241 section = self.get_section_by_name(secname)
242 if section is None:
243 debug_sections[secname] = None
244 else:
245 dwarf_section = self._read_dwarf_section(
246 section,
247 relocate_dwarf_sections)
248 if compressed and secname.startswith('.z'):
249 dwarf_section = self._decompress_dwarf_section(dwarf_section)
250 debug_sections[secname] = dwarf_section
251
252 return DWARFInfo(
253 config=DwarfConfig(
254 little_endian=self.little_endian,
255 default_address_size=self.elfclass // 8,
256 machine_arch=self.get_machine_arch()),
257 debug_info_sec=debug_sections[debug_info_sec_name],
258 debug_aranges_sec=debug_sections[debug_aranges_sec_name],
259 debug_abbrev_sec=debug_sections[debug_abbrev_sec_name],
260 debug_frame_sec=debug_sections[debug_frame_sec_name],
261 eh_frame_sec=debug_sections[eh_frame_sec_name],
262 debug_str_sec=debug_sections[debug_str_sec_name],
263 debug_loc_sec=debug_sections[debug_loc_sec_name],
264 debug_ranges_sec=debug_sections[debug_ranges_sec_name],
265 debug_line_sec=debug_sections[debug_line_sec_name],
266 debug_pubtypes_sec=debug_sections[debug_pubtypes_name],
267 debug_pubnames_sec=debug_sections[debug_pubnames_name],
268 debug_addr_sec=debug_sections[debug_addr_name],
269 debug_str_offsets_sec=debug_sections[debug_str_offsets_name],
270 debug_line_str_sec=debug_sections[debug_line_str_name],
271 debug_loclists_sec=debug_sections[debug_loclists_sec_name],
272 debug_rnglists_sec=debug_sections[debug_rnglists_sec_name]
273 )
274
275 def has_ehabi_info(self):
276 """ Check whether this file appears to have arm exception handler index table.
277 """
278 return any(self.iter_sections(type='SHT_ARM_EXIDX'))
279
280 def get_ehabi_infos(self):
281 """ Generally, shared library and executable contain 1 .ARM.exidx section.
282 Object file contains many .ARM.exidx sections.
283 So we must traverse every section and filter sections whose type is SHT_ARM_EXIDX.
284 """
285 _ret = []
286 if self['e_type'] == 'ET_REL':
287 # TODO: support relocatable file
288 assert False, "Current version of pyelftools doesn't support relocatable file."
289 for section in self.iter_sections(type='SHT_ARM_EXIDX'):
290 _ret.append(EHABIInfo(section, self.little_endian))
291 return _ret if len(_ret) > 0 else None
292
293 def get_machine_arch(self):
294 """ Return the machine architecture, as detected from the ELF header.
295 """
296 architectures = {
297 'EM_M32' : 'AT&T WE 32100',
298 'EM_SPARC' : 'SPARC',
299 'EM_386' : 'x86',
300 'EM_68K' : 'Motorola 68000',
301 'EM_88K' : 'Motorola 88000',
302 'EM_IAMCU' : 'Intel MCU',
303 'EM_860' : 'Intel 80860',
304 'EM_MIPS' : 'MIPS',
305 'EM_S370' : 'IBM System/370',
306 'EM_MIPS_RS3_LE' : 'MIPS RS3000 Little-endian',
307 'EM_PARISC' : 'Hewlett-Packard PA-RISC',
308 'EM_VPP500' : 'Fujitsu VPP500',
309 'EM_SPARC32PLUS' : 'Enhanced SPARC',
310 'EM_960' : 'Intel 80960',
311 'EM_PPC' : 'PowerPC',
312 'EM_PPC64' : '64-bit PowerPC',
313 'EM_S390' : 'IBM System/390',
314 'EM_SPU' : 'IBM SPU/SPC',
315 'EM_V800' : 'NEC V800',
316 'EM_FR20' : 'Fujitsu FR20',
317 'EM_RH32' : 'TRW RH-32',
318 'EM_RCE' : 'Motorola RCE',
319 'EM_ARM' : 'ARM',
320 'EM_ALPHA' : 'Digital Alpha',
321 'EM_SH' : 'Hitachi SH',
322 'EM_SPARCV9' : 'SPARC Version 9',
323 'EM_TRICORE' : 'Siemens TriCore embedded processor',
324 'EM_ARC' : 'Argonaut RISC Core, Argonaut Technologies Inc.',
325 'EM_H8_300' : 'Hitachi H8/300',
326 'EM_H8_300H' : 'Hitachi H8/300H',
327 'EM_H8S' : 'Hitachi H8S',
328 'EM_H8_500' : 'Hitachi H8/500',
329 'EM_IA_64' : 'Intel IA-64',
330 'EM_MIPS_X' : 'MIPS-X',
331 'EM_COLDFIRE' : 'Motorola ColdFire',
332 'EM_68HC12' : 'Motorola M68HC12',
333 'EM_MMA' : 'Fujitsu MMA',
334 'EM_PCP' : 'Siemens PCP',
335 'EM_NCPU' : 'Sony nCPU',
336 'EM_NDR1' : 'Denso NDR1',
337 'EM_STARCORE' : 'Motorola Star*Core',
338 'EM_ME16' : 'Toyota ME16',
339 'EM_ST100' : 'STMicroelectronics ST100',
340 'EM_TINYJ' : 'Advanced Logic TinyJ',
341 'EM_X86_64' : 'x64',
342 'EM_PDSP' : 'Sony DSP',
343 'EM_PDP10' : 'Digital Equipment PDP-10',
344 'EM_PDP11' : 'Digital Equipment PDP-11',
345 'EM_FX66' : 'Siemens FX66',
346 'EM_ST9PLUS' : 'STMicroelectronics ST9+ 8/16 bit',
347 'EM_ST7' : 'STMicroelectronics ST7 8-bit',
348 'EM_68HC16' : 'Motorola MC68HC16',
349 'EM_68HC11' : 'Motorola MC68HC11',
350 'EM_68HC08' : 'Motorola MC68HC08',
351 'EM_68HC05' : 'Motorola MC68HC05',
352 'EM_SVX' : 'Silicon Graphics SVx',
353 'EM_ST19' : 'STMicroelectronics ST19 8-bit',
354 'EM_VAX' : 'Digital VAX',
355 'EM_CRIS' : 'Axis Communications 32-bit',
356 'EM_JAVELIN' : 'Infineon Technologies 32-bit',
357 'EM_FIREPATH' : 'Element 14 64-bit DSP',
358 'EM_ZSP' : 'LSI Logic 16-bit DSP',
359 'EM_MMIX' : 'Donald Knuth\'s educational 64-bit',
360 'EM_HUANY' : 'Harvard University machine-independent object files',
361 'EM_PRISM' : 'SiTera Prism',
362 'EM_AVR' : 'Atmel AVR 8-bit',
363 'EM_FR30' : 'Fujitsu FR30',
364 'EM_D10V' : 'Mitsubishi D10V',
365 'EM_D30V' : 'Mitsubishi D30V',
366 'EM_V850' : 'NEC v850',
367 'EM_M32R' : 'Mitsubishi M32R',
368 'EM_MN10300' : 'Matsushita MN10300',
369 'EM_MN10200' : 'Matsushita MN10200',
370 'EM_PJ' : 'picoJava',
371 'EM_OPENRISC' : 'OpenRISC 32-bit',
372 'EM_ARC_COMPACT' : 'ARC International ARCompact',
373 'EM_XTENSA' : 'Tensilica Xtensa',
374 'EM_VIDEOCORE' : 'Alphamosaic VideoCore',
375 'EM_TMM_GPP' : 'Thompson Multimedia',
376 'EM_NS32K' : 'National Semiconductor 32000 series',
377 'EM_TPC' : 'Tenor Network TPC',
378 'EM_SNP1K' : 'Trebia SNP 1000',
379 'EM_ST200' : 'STMicroelectronics ST200',
380 'EM_IP2K' : 'Ubicom IP2xxx',
381 'EM_MAX' : 'MAX',
382 'EM_CR' : 'National Semiconductor CompactRISC',
383 'EM_F2MC16' : 'Fujitsu F2MC16',
384 'EM_MSP430' : 'Texas Instruments msp430',
385 'EM_BLACKFIN' : 'Analog Devices Blackfin',
386 'EM_SE_C33' : 'Seiko Epson S1C33',
387 'EM_SEP' : 'Sharp',
388 'EM_ARCA' : 'Arca RISC',
389 'EM_UNICORE' : 'PKU-Unity MPRC',
390 'EM_EXCESS' : 'eXcess',
391 'EM_DXP' : 'Icera Semiconductor Deep Execution Processor',
392 'EM_ALTERA_NIOS2' : 'Altera Nios II',
393 'EM_CRX' : 'National Semiconductor CompactRISC CRX',
394 'EM_XGATE' : 'Motorola XGATE',
395 'EM_C166' : 'Infineon C16x/XC16x',
396 'EM_M16C' : 'Renesas M16C',
397 'EM_DSPIC30F' : 'Microchip Technology dsPIC30F',
398 'EM_CE' : 'Freescale Communication Engine RISC core',
399 'EM_M32C' : 'Renesas M32C',
400 'EM_TSK3000' : 'Altium TSK3000',
401 'EM_RS08' : 'Freescale RS08',
402 'EM_SHARC' : 'Analog Devices SHARC',
403 'EM_ECOG2' : 'Cyan Technology eCOG2',
404 'EM_SCORE7' : 'Sunplus S+core7 RISC',
405 'EM_DSP24' : 'New Japan Radio (NJR) 24-bit DSP',
406 'EM_VIDEOCORE3' : 'Broadcom VideoCore III',
407 'EM_LATTICEMICO32' : 'Lattice FPGA RISC',
408 'EM_SE_C17' : 'Seiko Epson C17',
409 'EM_TI_C6000' : 'TI TMS320C6000',
410 'EM_TI_C2000' : 'TI TMS320C2000',
411 'EM_TI_C5500' : 'TI TMS320C55x',
412 'EM_TI_ARP32' : 'TI Application Specific RISC, 32bit',
413 'EM_TI_PRU' : 'TI Programmable Realtime Unit',
414 'EM_MMDSP_PLUS' : 'STMicroelectronics 64bit VLIW',
415 'EM_CYPRESS_M8C' : 'Cypress M8C',
416 'EM_R32C' : 'Renesas R32C',
417 'EM_TRIMEDIA' : 'NXP Semiconductors TriMedia',
418 'EM_QDSP6' : 'QUALCOMM DSP6',
419 'EM_8051' : 'Intel 8051',
420 'EM_STXP7X' : 'STMicroelectronics STxP7x',
421 'EM_NDS32' : 'Andes Technology RISC',
422 'EM_ECOG1' : 'Cyan Technology eCOG1X',
423 'EM_ECOG1X' : 'Cyan Technology eCOG1X',
424 'EM_MAXQ30' : 'Dallas Semiconductor MAXQ30',
425 'EM_XIMO16' : 'New Japan Radio (NJR) 16-bit',
426 'EM_MANIK' : 'M2000 Reconfigurable RISC',
427 'EM_CRAYNV2' : 'Cray Inc. NV2',
428 'EM_RX' : 'Renesas RX',
429 'EM_METAG' : 'Imagination Technologies META',
430 'EM_MCST_ELBRUS' : 'MCST Elbrus',
431 'EM_ECOG16' : 'Cyan Technology eCOG16',
432 'EM_CR16' : 'National Semiconductor CompactRISC CR16 16-bit',
433 'EM_ETPU' : 'Freescale',
434 'EM_SLE9X' : 'Infineon Technologies SLE9X',
435 'EM_L10M' : 'Intel L10M',
436 'EM_K10M' : 'Intel K10M',
437 'EM_AARCH64' : 'AArch64',
438 'EM_AVR32' : 'Atmel 32-bit',
439 'EM_STM8' : 'STMicroeletronics STM8 8-bit',
440 'EM_TILE64' : 'Tilera TILE64',
441 'EM_TILEPRO' : 'Tilera TILEPro',
442 'EM_MICROBLAZE' : 'Xilinx MicroBlaze 32-bit RISC',
443 'EM_CUDA' : 'NVIDIA CUDA',
444 'EM_TILEGX' : 'Tilera TILE-Gx',
445 'EM_CLOUDSHIELD' : 'CloudShield',
446 'EM_COREA_1ST' : 'KIPO-KAIST Core-A 1st generation',
447 'EM_COREA_2ND' : 'KIPO-KAIST Core-A 2nd generation',
448 'EM_ARC_COMPACT2' : 'Synopsys ARCompact V2',
449 'EM_OPEN8' : 'Open8 8-bit RISC',
450 'EM_RL78' : 'Renesas RL78',
451 'EM_VIDEOCORE5' : 'Broadcom VideoCore V',
452 'EM_78KOR' : 'Renesas 78KOR',
453 'EM_56800EX' : 'Freescale 56800EX',
454 'EM_BA1' : 'Beyond BA1',
455 'EM_BA2' : 'Beyond BA2',
456 'EM_XCORE' : 'XMOS xCORE',
457 'EM_MCHP_PIC' : 'Microchip 8-bit PIC',
458 'EM_INTEL205' : 'Reserved by Intel',
459 'EM_INTEL206' : 'Reserved by Intel',
460 'EM_INTEL207' : 'Reserved by Intel',
461 'EM_INTEL208' : 'Reserved by Intel',
462 'EM_INTEL209' : 'Reserved by Intel',
463 'EM_KM32' : 'KM211 KM32 32-bit',
464 'EM_KMX32' : 'KM211 KMX32 32-bit',
465 'EM_KMX16' : 'KM211 KMX16 16-bit',
466 'EM_KMX8' : 'KM211 KMX8 8-bit',
467 'EM_KVARC' : 'KM211 KVARC',
468 'EM_CDP' : 'Paneve CDP',
469 'EM_COGE' : 'Cognitive',
470 'EM_COOL' : 'Bluechip Systems CoolEngine',
471 'EM_NORC' : 'Nanoradio Optimized RISC',
472 'EM_CSR_KALIMBA' : 'CSR Kalimba',
473 'EM_Z80' : 'Zilog Z80',
474 'EM_VISIUM' : 'VISIUMcore',
475 'EM_FT32' : 'FTDI Chip FT32 32-bit RISC',
476 'EM_MOXIE' : 'Moxie',
477 'EM_AMDGPU' : 'AMD GPU',
478 'EM_RISCV' : 'RISC-V',
479 'EM_BPF' : 'Linux BPF - in-kernel virtual machine',
480 'EM_CSKY' : 'C-SKY',
481 'EM_FRV' : 'Fujitsu FR-V'
482 }
483
484 return architectures.get(self['e_machine'], '<unknown>')
485
486 def get_shstrndx(self):
487 """ Find the string table section index for the section header table
488 """
489 # From https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html:
490 # If the section name string table section index is greater than or
491 # equal to SHN_LORESERVE (0xff00), this member has the value SHN_XINDEX
492 # (0xffff) and the actual index of the section name string table section
493 # is contained in the sh_link field of the section header at index 0.
494 if self['e_shstrndx'] != SHN_INDICES.SHN_XINDEX:
495 return self['e_shstrndx']
496 else:
497 return self._get_section_header(0)['sh_link']
498
499 #-------------------------------- PRIVATE --------------------------------#
500
501 def __getitem__(self, name):
502 """ Implement dict-like access to header entries
503 """
504 return self.header[name]
505
506 def _identify_file(self):
507 """ Verify the ELF file and identify its class and endianness.
508 """
509 # Note: this code reads the stream directly, without using ELFStructs,
510 # since we don't yet know its exact format. ELF was designed to be
511 # read like this - its e_ident field is word-size and endian agnostic.
512 self.stream.seek(0)
513 magic = self.stream.read(4)
514 elf_assert(magic == b'\x7fELF', 'Magic number does not match')
515
516 ei_class = self.stream.read(1)
517 if ei_class == b'\x01':
518 self.elfclass = 32
519 elif ei_class == b'\x02':
520 self.elfclass = 64
521 else:
522 raise ELFError('Invalid EI_CLASS %s' % repr(ei_class))
523
524 ei_data = self.stream.read(1)
525 if ei_data == b'\x01':
526 self.little_endian = True
527 elif ei_data == b'\x02':
528 self.little_endian = False
529 else:
530 raise ELFError('Invalid EI_DATA %s' % repr(ei_data))
531
532 def _section_offset(self, n):
533 """ Compute the offset of section #n in the file
534 """
535 return self['e_shoff'] + n * self['e_shentsize']
536
537 def _segment_offset(self, n):
538 """ Compute the offset of segment #n in the file
539 """
540 return self['e_phoff'] + n * self['e_phentsize']
541
542 def _make_segment(self, segment_header):
543 """ Create a Segment object of the appropriate type
544 """
545 segtype = segment_header['p_type']
546 if segtype == 'PT_INTERP':
547 return InterpSegment(segment_header, self.stream)
548 elif segtype == 'PT_DYNAMIC':
549 return DynamicSegment(segment_header, self.stream, self)
550 elif segtype == 'PT_NOTE':
551 return NoteSegment(segment_header, self.stream, self)
552 else:
553 return Segment(segment_header, self.stream)
554
555 def _get_section_header(self, n):
556 """ Find the header of section #n, parse it and return the struct
557 """
558 return struct_parse(
559 self.structs.Elf_Shdr,
560 self.stream,
561 stream_pos=self._section_offset(n))
562
563 def _get_section_name(self, section_header):
564 """ Given a section header, find this section's name in the file's
565 string table
566 """
567 name_offset = section_header['sh_name']
568 return self._section_header_stringtable.get_string(name_offset)
569
570 def _make_section(self, section_header):
571 """ Create a section object of the appropriate type
572 """
573 name = self._get_section_name(section_header)
574 sectype = section_header['sh_type']
575
576 if sectype == 'SHT_STRTAB':
577 return StringTableSection(section_header, name, self)
578 elif sectype == 'SHT_NULL':
579 return NullSection(section_header, name, self)
580 elif sectype in ('SHT_SYMTAB', 'SHT_DYNSYM', 'SHT_SUNW_LDYNSYM'):
581 return self._make_symbol_table_section(section_header, name)
582 elif sectype == 'SHT_SYMTAB_SHNDX':
583 return self._make_symbol_table_index_section(section_header, name)
584 elif sectype == 'SHT_SUNW_syminfo':
585 return self._make_sunwsyminfo_table_section(section_header, name)
586 elif sectype == 'SHT_GNU_verneed':
587 return self._make_gnu_verneed_section(section_header, name)
588 elif sectype == 'SHT_GNU_verdef':
589 return self._make_gnu_verdef_section(section_header, name)
590 elif sectype == 'SHT_GNU_versym':
591 return self._make_gnu_versym_section(section_header, name)
592 elif sectype in ('SHT_REL', 'SHT_RELA'):
593 return RelocationSection(section_header, name, self)
594 elif sectype == 'SHT_DYNAMIC':
595 return DynamicSection(section_header, name, self)
596 elif sectype == 'SHT_NOTE':
597 return NoteSection(section_header, name, self)
598 elif sectype == 'SHT_PROGBITS' and name == '.stab':
599 return StabSection(section_header, name, self)
600 elif sectype == 'SHT_ARM_ATTRIBUTES':
601 return ARMAttributesSection(section_header, name, self)
602 elif sectype == 'SHT_HASH':
603 return self._make_elf_hash_section(section_header, name)
604 elif sectype == 'SHT_GNU_HASH':
605 return self._make_gnu_hash_section(section_header, name)
606 elif sectype == 'SHT_RELR':
607 return RelrRelocationSection(section_header, name, self)
608 else:
609 return Section(section_header, name, self)
610
611 def _make_section_name_map(self):
612 self._section_name_map = {}
613 for i, sec in enumerate(self.iter_sections()):
614 self._section_name_map[sec.name] = i
615
616 def _make_symbol_table_section(self, section_header, name):
617 """ Create a SymbolTableSection
618 """
619 linked_strtab_index = section_header['sh_link']
620 strtab_section = self.get_section(linked_strtab_index)
621 return SymbolTableSection(
622 section_header, name,
623 elffile=self,
624 stringtable=strtab_section)
625
626 def _make_symbol_table_index_section(self, section_header, name):
627 """ Create a SymbolTableIndexSection object
628 """
629 linked_symtab_index = section_header['sh_link']
630 return SymbolTableIndexSection(
631 section_header, name, elffile=self,
632 symboltable=linked_symtab_index)
633
634 def _make_sunwsyminfo_table_section(self, section_header, name):
635 """ Create a SUNWSyminfoTableSection
636 """
637 linked_strtab_index = section_header['sh_link']
638 strtab_section = self.get_section(linked_strtab_index)
639 return SUNWSyminfoTableSection(
640 section_header, name,
641 elffile=self,
642 symboltable=strtab_section)
643
644 def _make_gnu_verneed_section(self, section_header, name):
645 """ Create a GNUVerNeedSection
646 """
647 linked_strtab_index = section_header['sh_link']
648 strtab_section = self.get_section(linked_strtab_index)
649 return GNUVerNeedSection(
650 section_header, name,
651 elffile=self,
652 stringtable=strtab_section)
653
654 def _make_gnu_verdef_section(self, section_header, name):
655 """ Create a GNUVerDefSection
656 """
657 linked_strtab_index = section_header['sh_link']
658 strtab_section = self.get_section(linked_strtab_index)
659 return GNUVerDefSection(
660 section_header, name,
661 elffile=self,
662 stringtable=strtab_section)
663
664 def _make_gnu_versym_section(self, section_header, name):
665 """ Create a GNUVerSymSection
666 """
667 linked_strtab_index = section_header['sh_link']
668 strtab_section = self.get_section(linked_strtab_index)
669 return GNUVerSymSection(
670 section_header, name,
671 elffile=self,
672 symboltable=strtab_section)
673
674 def _make_elf_hash_section(self, section_header, name):
675 linked_symtab_index = section_header['sh_link']
676 symtab_section = self.get_section(linked_symtab_index)
677 return ELFHashSection(
678 section_header, name, self, symtab_section
679 )
680
681 def _make_gnu_hash_section(self, section_header, name):
682 linked_symtab_index = section_header['sh_link']
683 symtab_section = self.get_section(linked_symtab_index)
684 return GNUHashSection(
685 section_header, name, self, symtab_section
686 )
687
688 def _get_segment_header(self, n):
689 """ Find the header of segment #n, parse it and return the struct
690 """
691 return struct_parse(
692 self.structs.Elf_Phdr,
693 self.stream,
694 stream_pos=self._segment_offset(n))
695
696 def _get_section_header_stringtable(self):
697 """ Get the string table section corresponding to the section header
698 table.
699 """
700 stringtable_section_num = self.get_shstrndx()
701 return StringTableSection(
702 header=self._get_section_header(stringtable_section_num),
703 name='',
704 elffile=self)
705
706 def _parse_elf_header(self):
707 """ Parses the ELF file header and assigns the result to attributes
708 of this object.
709 """
710 return struct_parse(self.structs.Elf_Ehdr, self.stream, stream_pos=0)
711
712 def _read_dwarf_section(self, section, relocate_dwarf_sections):
713 """ Read the contents of a DWARF section from the stream and return a
714 DebugSectionDescriptor. Apply relocations if asked to.
715 """
716 # The section data is read into a new stream, for processing
717 section_stream = BytesIO()
718 section_stream.write(section.data())
719
720 if relocate_dwarf_sections:
721 reloc_handler = RelocationHandler(self)
722 reloc_section = reloc_handler.find_relocations_for_section(section)
723 if reloc_section is not None:
724 reloc_handler.apply_section_relocations(
725 section_stream, reloc_section)
726
727 return DebugSectionDescriptor(
728 stream=section_stream,
729 name=section.name,
730 global_offset=section['sh_offset'],
731 size=section.data_size,
732 address=section['sh_addr'])
733
734 @staticmethod
735 def _decompress_dwarf_section(section):
736 """ Returns the uncompressed contents of the provided DWARF section.
737 """
738 # TODO: support other compression formats from readelf.c
739 assert section.size > 12, 'Unsupported compression format.'
740
741 section.stream.seek(0)
742 # According to readelf.c the content should contain "ZLIB"
743 # followed by the uncompressed section size - 8 bytes in
744 # big-endian order
745 compression_type = section.stream.read(4)
746 assert compression_type == b'ZLIB', \
747 'Invalid compression type: %r' % (compression_type)
748
749 uncompressed_size = struct.unpack('>Q', section.stream.read(8))[0]
750
751 decompressor = zlib.decompressobj()
752 uncompressed_stream = BytesIO()
753 while True:
754 chunk = section.stream.read(PAGESIZE)
755 if not chunk:
756 break
757 uncompressed_stream.write(decompressor.decompress(chunk))
758 uncompressed_stream.write(decompressor.flush())
759
760 uncompressed_stream.seek(0, io.SEEK_END)
761 size = uncompressed_stream.tell()
762 assert uncompressed_size == size, \
763 'Wrong uncompressed size: expected %r, but got %r' % (
764 uncompressed_size, size,
765 )
766
767 return section._replace(stream=uncompressed_stream, size=size)