2 #-------------------------------------------------------------------------------
5 # A clone of 'readelf' in Python, based on the pyelftools library
7 # Eli Bendersky (eliben@gmail.com)
8 # This code is in the public domain
9 #-------------------------------------------------------------------------------
11 from optparse
import OptionParser
14 # For running from development directory. It should take precedence over the
15 # installed pyelftools.
16 sys
.path
.insert(0, '.')
19 from elftools
import __version__
20 from elftools
.common
.exceptions
import ELFError
21 from elftools
.common
.py3compat
import (
22 ifilter
, byte2int
, bytes2str
, itervalues
, str2bytes
, iterbytes
)
23 from elftools
.elf
.elffile
import ELFFile
24 from elftools
.elf
.dynamic
import DynamicSection
, DynamicSegment
25 from elftools
.elf
.enums
import ENUM_D_TAG
26 from elftools
.elf
.segments
import InterpSegment
27 from elftools
.elf
.sections
import NoteSection
, SymbolTableSection
28 from elftools
.elf
.gnuversions
import (
29 GNUVerSymSection
, GNUVerDefSection
,
32 from elftools
.elf
.relocation
import RelocationSection
33 from elftools
.elf
.descriptions
import (
34 describe_ei_class
, describe_ei_data
, describe_ei_version
,
35 describe_ei_osabi
, describe_e_type
, describe_e_machine
,
36 describe_e_version_numeric
, describe_p_type
, describe_p_flags
,
37 describe_sh_type
, describe_sh_flags
,
38 describe_symbol_type
, describe_symbol_bind
, describe_symbol_visibility
,
39 describe_symbol_shndx
, describe_reloc_type
, describe_dyn_tag
,
40 describe_ver_flags
, describe_note
, describe_attr_tag_arm
42 from elftools
.elf
.constants
import E_FLAGS
43 from elftools
.dwarf
.dwarfinfo
import DWARFInfo
44 from elftools
.dwarf
.descriptions
import (
45 describe_reg_name
, describe_attr_value
, set_global_machine_arch
,
46 describe_CFI_instructions
, describe_CFI_register_rule
,
47 describe_CFI_CFA_rule
,
49 from elftools
.dwarf
.constants
import (
50 DW_LNS_copy
, DW_LNS_set_file
, DW_LNE_define_file
)
51 from elftools
.dwarf
.callframe
import CIE
, FDE
, ZERO
54 class ReadElf(object):
55 """ display_* methods are used to emit output into the output stream
57 def __init__(self
, file, output
):
59 stream object with the ELF file to read
62 output stream to write to
64 self
.elffile
= ELFFile(file)
67 # Lazily initialized if a debug dump is requested
68 self
._dwarfinfo
= None
70 self
._versioninfo
= None
72 def display_file_header(self
):
73 """ Display the ELF file header
75 self
._emitline
('ELF Header:')
76 self
._emit
(' Magic: ')
77 self
._emit
(' '.join('%2.2x' % byte2int(b
)
78 for b
in self
.elffile
.e_ident_raw
))
80 header
= self
.elffile
.header
81 e_ident
= header
['e_ident']
82 self
._emitline
(' Class: %s' %
83 describe_ei_class(e_ident
['EI_CLASS']))
84 self
._emitline
(' Data: %s' %
85 describe_ei_data(e_ident
['EI_DATA']))
86 self
._emitline
(' Version: %s' %
87 describe_ei_version(e_ident
['EI_VERSION']))
88 self
._emitline
(' OS/ABI: %s' %
89 describe_ei_osabi(e_ident
['EI_OSABI']))
90 self
._emitline
(' ABI Version: %d' %
91 e_ident
['EI_ABIVERSION'])
92 self
._emitline
(' Type: %s' %
93 describe_e_type(header
['e_type']))
94 self
._emitline
(' Machine: %s' %
95 describe_e_machine(header
['e_machine']))
96 self
._emitline
(' Version: %s' %
97 describe_e_version_numeric(header
['e_version']))
98 self
._emitline
(' Entry point address: %s' %
99 self
._format
_hex
(header
['e_entry']))
100 self
._emit
(' Start of program headers: %s' %
102 self
._emitline
(' (bytes into file)')
103 self
._emit
(' Start of section headers: %s' %
105 self
._emitline
(' (bytes into file)')
106 self
._emitline
(' Flags: %s%s' %
107 (self
._format
_hex
(header
['e_flags']),
108 self
.decode_flags(header
['e_flags'])))
109 self
._emitline
(' Size of this header: %s (bytes)' %
111 self
._emitline
(' Size of program headers: %s (bytes)' %
112 header
['e_phentsize'])
113 self
._emitline
(' Number of program headers: %s' %
115 self
._emitline
(' Size of section headers: %s (bytes)' %
116 header
['e_shentsize'])
117 self
._emitline
(' Number of section headers: %s' %
119 self
._emitline
(' Section header string table index: %s' %
120 header
['e_shstrndx'])
122 def decode_flags(self
, flags
):
124 if self
.elffile
['e_machine'] == "EM_ARM":
125 eabi
= flags
& E_FLAGS
.EF_ARM_EABIMASK
126 flags
&= ~E_FLAGS
.EF_ARM_EABIMASK
128 if flags
& E_FLAGS
.EF_ARM_RELEXEC
:
129 description
+= ', relocatable executabl'
130 flags
&= ~E_FLAGS
.EF_ARM_RELEXEC
132 if eabi
== E_FLAGS
.EF_ARM_EABI_VER5
:
133 description
+= ', Version5 EABI'
135 description
+= ', <unknown>'
137 desrciption
+= ', <unrecognized EABI>'
139 elif self
.elffile
['e_machine'] == "EM_MIPS":
140 if flags
& E_FLAGS
.EF_MIPS_NOREORDER
:
141 description
+= ", noreorder"
142 if flags
& E_FLAGS
.EF_MIPS_CPIC
:
143 description
+= ", cpic"
144 if not (flags
& E_FLAGS
.EF_MIPS_ABI2
) and not (flags
& E_FLAGS
.EF_MIPS_ABI_ON32
):
145 description
+= ", o32"
146 if (flags
& E_FLAGS
.EF_MIPS_ARCH
) == E_FLAGS
.EF_MIPS_ARCH_1
:
147 description
+= ", mips1"
151 def display_program_headers(self
, show_heading
=True):
152 """ Display the ELF program headers.
153 If show_heading is True, displays the heading for this information
154 (Elf file type is...)
157 if self
.elffile
.num_segments() == 0:
158 self
._emitline
('There are no program headers in this file.')
161 elfheader
= self
.elffile
.header
163 self
._emitline
('Elf file type is %s' %
164 describe_e_type(elfheader
['e_type']))
165 self
._emitline
('Entry point is %s' %
166 self
._format
_hex
(elfheader
['e_entry']))
167 # readelf weirness - why isn't e_phoff printed as hex? (for section
169 self
._emitline
('There are %s program headers, starting at offset %s' % (
170 elfheader
['e_phnum'], elfheader
['e_phoff']))
173 self
._emitline
('Program Headers:')
175 # Now comes the table of program headers with their attributes. Note
176 # that due to different formatting constraints of 32-bit and 64-bit
177 # addresses, there are some conditions on elfclass here.
179 # First comes the table heading
181 if self
.elffile
.elfclass
== 32:
182 self
._emitline
(' Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align')
184 self
._emitline
(' Type Offset VirtAddr PhysAddr')
185 self
._emitline
(' FileSiz MemSiz Flags Align')
189 for segment
in self
.elffile
.iter_segments():
190 self
._emit
(' %-14s ' % describe_p_type(segment
['p_type']))
192 if self
.elffile
.elfclass
== 32:
193 self
._emitline
('%s %s %s %s %s %-3s %s' % (
194 self
._format
_hex
(segment
['p_offset'], fieldsize
=6),
195 self
._format
_hex
(segment
['p_vaddr'], fullhex
=True),
196 self
._format
_hex
(segment
['p_paddr'], fullhex
=True),
197 self
._format
_hex
(segment
['p_filesz'], fieldsize
=5),
198 self
._format
_hex
(segment
['p_memsz'], fieldsize
=5),
199 describe_p_flags(segment
['p_flags']),
200 self
._format
_hex
(segment
['p_align'])))
202 self
._emitline
('%s %s %s' % (
203 self
._format
_hex
(segment
['p_offset'], fullhex
=True),
204 self
._format
_hex
(segment
['p_vaddr'], fullhex
=True),
205 self
._format
_hex
(segment
['p_paddr'], fullhex
=True)))
206 self
._emitline
(' %s %s %-3s %s' % (
207 self
._format
_hex
(segment
['p_filesz'], fullhex
=True),
208 self
._format
_hex
(segment
['p_memsz'], fullhex
=True),
209 describe_p_flags(segment
['p_flags']),
210 # lead0x set to False for p_align, to mimic readelf.
211 # No idea why the difference from 32-bit mode :-|
212 self
._format
_hex
(segment
['p_align'], lead0x
=False)))
214 if isinstance(segment
, InterpSegment
):
215 self
._emitline
(' [Requesting program interpreter: %s]' %
216 segment
.get_interp_name())
218 # Sections to segments mapping
220 if self
.elffile
.num_sections() == 0:
221 # No sections? We're done
224 self
._emitline
('\n Section to Segment mapping:')
225 self
._emitline
(' Segment Sections...')
227 for nseg
, segment
in enumerate(self
.elffile
.iter_segments()):
228 self
._emit
(' %2.2d ' % nseg
)
230 for section
in self
.elffile
.iter_sections():
231 if ( not section
.is_null() and
232 segment
.section_in_segment(section
)):
233 self
._emit
('%s ' % section
.name
)
237 def display_section_headers(self
, show_heading
=True):
238 """ Display the ELF section headers
240 elfheader
= self
.elffile
.header
242 self
._emitline
('There are %s section headers, starting at offset %s' % (
243 elfheader
['e_shnum'], self
._format
_hex
(elfheader
['e_shoff'])))
245 if self
.elffile
.num_sections() == 0:
246 self
._emitline
('There are no sections in this file.')
249 self
._emitline
('\nSection Header%s:' % (
250 's' if elfheader
['e_shnum'] > 1 else ''))
252 # Different formatting constraints of 32-bit and 64-bit addresses
254 if self
.elffile
.elfclass
== 32:
255 self
._emitline
(' [Nr] Name Type Addr Off Size ES Flg Lk Inf Al')
257 self
._emitline
(' [Nr] Name Type Address Offset')
258 self
._emitline
(' Size EntSize Flags Link Info Align')
262 for nsec
, section
in enumerate(self
.elffile
.iter_sections()):
263 self
._emit
(' [%2u] %-17.17s %-15.15s ' % (
264 nsec
, section
.name
, describe_sh_type(section
['sh_type'])))
266 if self
.elffile
.elfclass
== 32:
267 self
._emitline
('%s %s %s %s %3s %2s %3s %2s' % (
268 self
._format
_hex
(section
['sh_addr'], fieldsize
=8, lead0x
=False),
269 self
._format
_hex
(section
['sh_offset'], fieldsize
=6, lead0x
=False),
270 self
._format
_hex
(section
['sh_size'], fieldsize
=6, lead0x
=False),
271 self
._format
_hex
(section
['sh_entsize'], fieldsize
=2, lead0x
=False),
272 describe_sh_flags(section
['sh_flags']),
273 section
['sh_link'], section
['sh_info'],
274 section
['sh_addralign']))
276 self
._emitline
(' %s %s' % (
277 self
._format
_hex
(section
['sh_addr'], fullhex
=True, lead0x
=False),
278 self
._format
_hex
(section
['sh_offset'],
279 fieldsize
=16 if section
['sh_offset'] > 0xffffffff else 8,
281 self
._emitline
(' %s %s %3s %2s %3s %s' % (
282 self
._format
_hex
(section
['sh_size'], fullhex
=True, lead0x
=False),
283 self
._format
_hex
(section
['sh_entsize'], fullhex
=True, lead0x
=False),
284 describe_sh_flags(section
['sh_flags']),
285 section
['sh_link'], section
['sh_info'],
286 section
['sh_addralign']))
288 self
._emitline
('Key to Flags:')
289 self
._emitline
(' W (write), A (alloc), X (execute), M (merge),'
290 ' S (strings), I (info),')
291 self
._emitline
(' L (link order), O (extra OS processing required),'
292 ' G (group), T (TLS),')
293 self
._emitline
(' C (compressed), x (unknown), o (OS specific),'
296 if self
.elffile
['e_machine'] == 'EM_ARM':
297 self
._emit
('y (purecode), ')
298 self
._emitline
('p (processor specific)')
300 def display_symbol_tables(self
):
301 """ Display the symbol tables contained in the file
303 self
._init
_versioninfo
()
305 symbol_tables
= [s
for s
in self
.elffile
.iter_sections()
306 if isinstance(s
, SymbolTableSection
)]
308 if not symbol_tables
and self
.elffile
.num_sections() == 0:
310 self
._emitline
('Dynamic symbol information is not available for'
311 ' displaying symbols.')
313 for section
in symbol_tables
:
314 if not isinstance(section
, SymbolTableSection
):
317 if section
['sh_entsize'] == 0:
318 self
._emitline
("\nSymbol table '%s' has a sh_entsize of zero!" % (
322 self
._emitline
("\nSymbol table '%s' contains %s entries:" % (
323 section
.name
, section
.num_symbols()))
325 if self
.elffile
.elfclass
== 32:
326 self
._emitline
(' Num: Value Size Type Bind Vis Ndx Name')
328 self
._emitline
(' Num: Value Size Type Bind Vis Ndx Name')
330 for nsym
, symbol
in enumerate(section
.iter_symbols()):
332 # readelf doesn't display version info for Solaris versioning
333 if (section
['sh_type'] == 'SHT_DYNSYM' and
334 self
._versioninfo
['type'] == 'GNU'):
335 version
= self
._symbol
_version
(nsym
)
336 if (version
['name'] != symbol
.name
and
337 version
['index'] not in ('VER_NDX_LOCAL',
339 if version
['filename']:
341 version_info
= '@%(name)s (%(index)i)' % version
344 if version
['hidden']:
345 version_info
= '@%(name)s' % version
347 version_info
= '@@%(name)s' % version
349 # symbol names are truncated to 25 chars, similarly to readelf
350 self
._emitline
('%6d: %s %5d %-7s %-6s %-7s %4s %.25s%s' % (
353 symbol
['st_value'], fullhex
=True, lead0x
=False),
355 describe_symbol_type(symbol
['st_info']['type']),
356 describe_symbol_bind(symbol
['st_info']['bind']),
357 describe_symbol_visibility(symbol
['st_other']['visibility']),
358 describe_symbol_shndx(symbol
['st_shndx']),
362 def display_dynamic_tags(self
):
363 """ Display the dynamic tags contained in the file
365 has_dynamic_sections
= False
366 for section
in self
.elffile
.iter_sections():
367 if not isinstance(section
, DynamicSection
):
370 has_dynamic_sections
= True
371 self
._emitline
("\nDynamic section at offset %s contains %s entries:" % (
372 self
._format
_hex
(section
['sh_offset']),
374 self
._emitline
(" Tag Type Name/Value")
376 padding
= 20 + (8 if self
.elffile
.elfclass
== 32 else 0)
377 for tag
in section
.iter_tags():
378 if tag
.entry
.d_tag
== 'DT_NEEDED':
379 parsed
= 'Shared library: [%s]' % tag
.needed
380 elif tag
.entry
.d_tag
== 'DT_RPATH':
381 parsed
= 'Library rpath: [%s]' % tag
.rpath
382 elif tag
.entry
.d_tag
== 'DT_RUNPATH':
383 parsed
= 'Library runpath: [%s]' % tag
.runpath
384 elif tag
.entry
.d_tag
== 'DT_SONAME':
385 parsed
= 'Library soname: [%s]' % tag
.soname
386 elif tag
.entry
.d_tag
.endswith(('SZ', 'ENT')):
387 parsed
= '%i (bytes)' % tag
['d_val']
388 elif tag
.entry
.d_tag
.endswith(('NUM', 'COUNT')):
389 parsed
= '%i' % tag
['d_val']
390 elif tag
.entry
.d_tag
== 'DT_PLTREL':
391 s
= describe_dyn_tag(tag
.entry
.d_val
)
392 if s
.startswith('DT_'):
396 parsed
= '%#x' % tag
['d_val']
398 self
._emitline
(" %s %-*s %s" % (
399 self
._format
_hex
(ENUM_D_TAG
.get(tag
.entry
.d_tag
, tag
.entry
.d_tag
),
400 fullhex
=True, lead0x
=True),
402 '(%s)' % (tag
.entry
.d_tag
[3:],),
404 if not has_dynamic_sections
:
405 self
._emitline
("\nThere is no dynamic section in this file.")
407 def display_notes(self
):
408 """ Display the notes contained in the file
410 for section
in self
.elffile
.iter_sections():
411 if isinstance(section
, NoteSection
):
412 for note
in section
.iter_notes():
413 self
._emitline
("\nDisplaying notes found in: {}".format(
415 self
._emitline
(' Owner Data size Description')
416 self
._emitline
(' %s %s\t%s' % (
417 note
['n_name'].ljust(20),
418 self
._format
_hex
(note
['n_descsz'], fieldsize
=8),
419 describe_note(note
)))
421 def display_relocations(self
):
422 """ Display the relocations contained in the file
424 has_relocation_sections
= False
425 for section
in self
.elffile
.iter_sections():
426 if not isinstance(section
, RelocationSection
):
429 has_relocation_sections
= True
430 self
._emitline
("\nRelocation section '%s' at offset %s contains %s entries:" % (
432 self
._format
_hex
(section
['sh_offset']),
433 section
.num_relocations()))
434 if section
.is_RELA():
435 self
._emitline
(" Offset Info Type Sym. Value Sym. Name + Addend")
437 self
._emitline
(" Offset Info Type Sym.Value Sym. Name")
439 # The symbol table section pointed to in sh_link
440 symtable
= self
.elffile
.get_section(section
['sh_link'])
442 for rel
in section
.iter_relocations():
443 hexwidth
= 8 if self
.elffile
.elfclass
== 32 else 12
444 self
._emit
('%s %s %-17.17s' % (
445 self
._format
_hex
(rel
['r_offset'],
446 fieldsize
=hexwidth
, lead0x
=False),
447 self
._format
_hex
(rel
['r_info'],
448 fieldsize
=hexwidth
, lead0x
=False),
450 rel
['r_info_type'], self
.elffile
)))
452 if rel
['r_info_sym'] == 0:
456 symbol
= symtable
.get_symbol(rel
['r_info_sym'])
457 # Some symbols have zero 'st_name', so instead what's used is
458 # the name of the section they point at. Truncate symbol names
459 # (excluding version info) to 22 chars, similarly to readelf.
460 if symbol
['st_name'] == 0:
461 symsec
= self
.elffile
.get_section(symbol
['st_shndx'])
462 symbol_name
= symsec
.name
465 symbol_name
= symbol
.name
466 version
= self
._symbol
_version
(rel
['r_info_sym'])
467 version
= (version
['name']
468 if version
and version
['name'] else '')
469 symbol_name
= '%.22s' % symbol_name
471 symbol_name
+= '@' + version
473 self
._emit
(' %s %s' % (
476 fullhex
=True, lead0x
=False),
478 if section
.is_RELA():
479 self
._emit
(' %s %x' % (
480 '+' if rel
['r_addend'] >= 0 else '-',
481 abs(rel
['r_addend'])))
484 if not has_relocation_sections
:
485 self
._emitline
('\nThere are no relocations in this file.')
487 def display_version_info(self
):
488 """ Display the version info contained in the file
490 self
._init
_versioninfo
()
492 if not self
._versioninfo
['type']:
493 self
._emitline
("\nNo version information found in this file.")
496 for section
in self
.elffile
.iter_sections():
497 if isinstance(section
, GNUVerSymSection
):
498 self
._print
_version
_section
_header
(
499 section
, 'Version symbols', lead0x
=False)
501 num_symbols
= section
.num_symbols()
503 # Symbol version info are printed four by four entries
504 for idx_by_4
in range(0, num_symbols
, 4):
506 self
._emit
(' %03x:' % idx_by_4
)
508 for idx
in range(idx_by_4
, min(idx_by_4
+ 4, num_symbols
)):
510 symbol_version
= self
._symbol
_version
(idx
)
511 if symbol_version
['index'] == 'VER_NDX_LOCAL':
513 version_name
= '(*local*)'
514 elif symbol_version
['index'] == 'VER_NDX_GLOBAL':
516 version_name
= '(*global*)'
518 version_index
= symbol_version
['index']
519 version_name
= '(%(name)s)' % symbol_version
521 visibility
= 'h' if symbol_version
['hidden'] else ' '
523 self
._emit
('%4x%s%-13s' % (
524 version_index
, visibility
, version_name
))
528 elif isinstance(section
, GNUVerDefSection
):
529 self
._print
_version
_section
_header
(
530 section
, 'Version definition', indent
=2)
533 for verdef
, verdaux_iter
in section
.iter_versions():
534 verdaux
= next(verdaux_iter
)
537 if verdef
['vd_flags']:
538 flags
= describe_ver_flags(verdef
['vd_flags'])
539 # Mimic exactly the readelf output
544 self
._emitline
(' %s: Rev: %i Flags: %s Index: %i'
545 ' Cnt: %i Name: %s' % (
546 self
._format
_hex
(offset
, fieldsize
=6,
548 verdef
['vd_version'], flags
, verdef
['vd_ndx'],
549 verdef
['vd_cnt'], name
))
552 offset
+ verdef
['vd_aux'] + verdaux
['vda_next'])
553 for idx
, verdaux
in enumerate(verdaux_iter
, start
=1):
554 self
._emitline
(' %s: Parent %i: %s' %
555 (self
._format
_hex
(verdaux_offset
, fieldsize
=4),
557 verdaux_offset
+= verdaux
['vda_next']
559 offset
+= verdef
['vd_next']
561 elif isinstance(section
, GNUVerNeedSection
):
562 self
._print
_version
_section
_header
(section
, 'Version needs')
565 for verneed
, verneed_iter
in section
.iter_versions():
567 self
._emitline
(' %s: Version: %i File: %s Cnt: %i' % (
568 self
._format
_hex
(offset
, fieldsize
=6,
570 verneed
['vn_version'], verneed
.name
,
573 vernaux_offset
= offset
+ verneed
['vn_aux']
574 for idx
, vernaux
in enumerate(verneed_iter
, start
=1):
575 if vernaux
['vna_flags']:
576 flags
= describe_ver_flags(vernaux
['vna_flags'])
577 # Mimic exactly the readelf output
583 ' %s: Name: %s Flags: %s Version: %i' % (
584 self
._format
_hex
(vernaux_offset
, fieldsize
=4),
586 vernaux
['vna_other']))
588 vernaux_offset
+= vernaux
['vna_next']
590 offset
+= verneed
['vn_next']
592 def display_arch_specific(self
):
593 """ Display the architecture-specific info contained in the file.
595 if self
.elffile
['e_machine'] == 'EM_ARM':
596 self
._display
_arch
_specific
_arm
()
598 def display_hex_dump(self
, section_spec
):
599 """ Display a hex dump of a section. section_spec is either a section
602 section
= self
._section
_from
_spec
(section_spec
)
604 # readelf prints the warning to stderr. Even though stderrs are not compared
605 # in tests, we comply with that behavior.
606 sys
.stderr
.write('readelf: Warning: Section \'%s\' was not dumped because it does not exist!\n' % (
609 if section
['sh_type'] == 'SHT_NOBITS':
610 self
._emitline
("\nSection '%s' has no data to dump." % (
614 self
._emitline
("\nHex dump of section '%s':" % section
.name
)
615 self
._note
_relocs
_for
_section
(section
)
616 addr
= section
['sh_addr']
617 data
= section
.data()
620 while dataptr
< len(data
):
621 bytesleft
= len(data
) - dataptr
622 # chunks of 16 bytes per line
623 linebytes
= 16 if bytesleft
> 16 else bytesleft
625 self
._emit
(' %s ' % self
._format
_hex
(addr
, fieldsize
=8))
628 self
._emit
('%2.2x' % byte2int(data
[dataptr
+ i
]))
634 for i
in range(linebytes
):
635 c
= data
[dataptr
+ i
: dataptr
+ i
+ 1]
636 if byte2int(c
[0]) >= 32 and byte2int(c
[0]) < 0x7f:
637 self
._emit
(bytes2str(c
))
639 self
._emit
(bytes2str(b
'.'))
647 def display_string_dump(self
, section_spec
):
648 """ Display a strings dump of a section. section_spec is either a
649 section number or a name.
651 section
= self
._section
_from
_spec
(section_spec
)
653 # readelf prints the warning to stderr. Even though stderrs are not compared
654 # in tests, we comply with that behavior.
655 sys
.stderr
.write('readelf.py: Warning: Section \'%s\' was not dumped because it does not exist!\n' % (
658 if section
['sh_type'] == 'SHT_NOBITS':
659 self
._emitline
("\nSection '%s' has no data to dump." % (
663 self
._emitline
("\nString dump of section '%s':" % section
.name
)
666 data
= section
.data()
669 while dataptr
< len(data
):
670 while ( dataptr
< len(data
) and
671 not (32 <= byte2int(data
[dataptr
]) <= 127)):
674 if dataptr
>= len(data
):
678 while endptr
< len(data
) and byte2int(data
[endptr
]) != 0:
682 self
._emitline
(' [%6x] %s' % (
683 dataptr
, bytes2str(data
[dataptr
:endptr
])))
688 self
._emitline
(' No strings found in this section.')
692 def display_debug_dump(self
, dump_what
):
693 """ Dump a DWARF section
695 self
._init
_dwarfinfo
()
696 if self
._dwarfinfo
is None:
699 set_global_machine_arch(self
.elffile
.get_machine_arch())
701 if dump_what
== 'info':
702 self
._dump
_debug
_info
()
703 elif dump_what
== 'decodedline':
704 self
._dump
_debug
_line
_programs
()
705 elif dump_what
== 'frames':
706 self
._dump
_debug
_frames
()
707 elif dump_what
== 'frames-interp':
708 self
._dump
_debug
_frames
_interp
()
709 elif dump_what
== 'aranges':
710 self
._dump
_debug
_aranges
()
712 self
._emitline
('debug dump not yet supported for "%s"' % dump_what
)
714 def _format_hex(self
, addr
, fieldsize
=None, fullhex
=False, lead0x
=True,
716 """ Format an address into a hexadecimal string.
719 Size of the hexadecimal field (with leading zeros to fit the
720 address into. For example with fieldsize=8, the format will
722 If None, the minimal required field size will be used.
725 If True, override fieldsize to set it to the maximal size
726 needed for the elfclass
729 If True, leading 0x is added
732 If True, override lead0x to emulate the alternate
733 hexadecimal form specified in format string with the #
734 character: only non-zero values are prefixed with 0x.
735 This form is used by readelf.
744 s
= '0x' if lead0x
else ''
746 fieldsize
= 8 if self
.elffile
.elfclass
== 32 else 16
747 if fieldsize
is None:
750 field
= '%' + '0%sx' % fieldsize
751 return s
+ field
% addr
753 def _print_version_section_header(self
, version_section
, name
, lead0x
=True,
755 """ Print a section header of one version related section (versym,
756 verneed or verdef) with some options to accomodate readelf
757 little differences between each header (e.g. indentation
760 if hasattr(version_section
, 'num_versions'):
761 num_entries
= version_section
.num_versions()
763 num_entries
= version_section
.num_symbols()
765 self
._emitline
("\n%s section '%s' contains %s entries:" %
766 (name
, version_section
.name
, num_entries
))
767 self
._emitline
('%sAddr: %s Offset: %s Link: %i (%s)' % (
770 version_section
['sh_addr'], fieldsize
=16, lead0x
=lead0x
),
772 version_section
['sh_offset'], fieldsize
=6, lead0x
=True),
773 version_section
['sh_link'],
774 self
.elffile
.get_section(version_section
['sh_link']).name
778 def _init_versioninfo(self
):
779 """ Search and initialize informations about version related sections
780 and the kind of versioning used (GNU or Solaris).
782 if self
._versioninfo
is not None:
785 self
._versioninfo
= {'versym': None, 'verdef': None,
786 'verneed': None, 'type': None}
788 for section
in self
.elffile
.iter_sections():
789 if isinstance(section
, GNUVerSymSection
):
790 self
._versioninfo
['versym'] = section
791 elif isinstance(section
, GNUVerDefSection
):
792 self
._versioninfo
['verdef'] = section
793 elif isinstance(section
, GNUVerNeedSection
):
794 self
._versioninfo
['verneed'] = section
795 elif isinstance(section
, DynamicSection
):
796 for tag
in section
.iter_tags():
797 if tag
['d_tag'] == 'DT_VERSYM':
798 self
._versioninfo
['type'] = 'GNU'
801 if not self
._versioninfo
['type'] and (
802 self
._versioninfo
['verneed'] or self
._versioninfo
['verdef']):
803 self
._versioninfo
['type'] = 'Solaris'
805 def _symbol_version(self
, nsym
):
806 """ Return a dict containing information on the
807 or None if no version information is available
809 self
._init
_versioninfo
()
811 symbol_version
= dict.fromkeys(('index', 'name', 'filename', 'hidden'))
813 if (not self
._versioninfo
['versym'] or
814 nsym
>= self
._versioninfo
['versym'].num_symbols()):
817 symbol
= self
._versioninfo
['versym'].get_symbol(nsym
)
818 index
= symbol
.entry
['ndx']
819 if not index
in ('VER_NDX_LOCAL', 'VER_NDX_GLOBAL'):
822 if self
._versioninfo
['type'] == 'GNU':
823 # In GNU versioning mode, the highest bit is used to
824 # store wether the symbol is hidden or not
827 symbol_version
['hidden'] = True
829 if (self
._versioninfo
['verdef'] and
830 index
<= self
._versioninfo
['verdef'].num_versions()):
832 self
._versioninfo
['verdef'].get_version(index
)
833 symbol_version
['name'] = next(verdaux_iter
).name
836 self
._versioninfo
['verneed'].get_version(index
)
837 symbol_version
['name'] = vernaux
.name
838 symbol_version
['filename'] = verneed
.name
840 symbol_version
['index'] = index
841 return symbol_version
843 def _section_from_spec(self
, spec
):
844 """ Retrieve a section given a "spec" (either number or name).
845 Return None if no such section exists in the file.
849 if num
< self
.elffile
.num_sections():
850 return self
.elffile
.get_section(num
)
854 # Not a number. Must be a name then
855 return self
.elffile
.get_section_by_name(spec
)
857 def _note_relocs_for_section(self
, section
):
858 """ If there are relocation sections pointing to the givne section,
859 emit a note about it.
861 for relsec
in self
.elffile
.iter_sections():
862 if isinstance(relsec
, RelocationSection
):
863 info_idx
= relsec
['sh_info']
864 if self
.elffile
.get_section(info_idx
) == section
:
865 self
._emitline
(' Note: This section has relocations against it, but these have NOT been applied to this dump.')
868 def _init_dwarfinfo(self
):
869 """ Initialize the DWARF info contained in the file and assign it to
871 Leave self._dwarfinfo at None if no DWARF info was found in the file
873 if self
._dwarfinfo
is not None:
876 if self
.elffile
.has_dwarf_info():
877 self
._dwarfinfo
= self
.elffile
.get_dwarf_info()
879 self
._dwarfinfo
= None
881 def _dump_debug_info(self
):
882 """ Dump the debugging info section.
884 if not self
._dwarfinfo
.has_debug_info
:
886 self
._emitline
('Contents of the %s section:\n' % self
._dwarfinfo
.debug_info_sec
.name
)
888 # Offset of the .debug_info section in the stream
889 section_offset
= self
._dwarfinfo
.debug_info_sec
.global_offset
891 for cu
in self
._dwarfinfo
.iter_CUs():
892 self
._emitline
(' Compilation Unit @ offset %s:' %
893 self
._format
_hex
(cu
.cu_offset
))
894 self
._emitline
(' Length: %s (%s)' % (
895 self
._format
_hex
(cu
['unit_length']),
896 '%s-bit' % cu
.dwarf_format()))
897 self
._emitline
(' Version: %s' % cu
['version']),
898 self
._emitline
(' Abbrev Offset: %s' % (
899 self
._format
_hex
(cu
['debug_abbrev_offset']))),
900 self
._emitline
(' Pointer Size: %s' % cu
['address_size'])
902 # The nesting depth of each DIE within the tree of DIEs must be
903 # displayed. To implement this, a counter is incremented each time
904 # the current DIE has children, and decremented when a null die is
905 # encountered. Due to the way the DIE tree is serialized, this will
906 # correctly reflect the nesting depth
909 for die
in cu
.iter_DIEs():
910 self
._emitline
(' <%s><%x>: Abbrev Number: %s%s' % (
914 (' (%s)' % die
.tag
) if not die
.is_null() else ''))
919 for attr
in itervalues(die
.attributes
):
921 # Unknown attribute values are passed-through as integers
922 if isinstance(name
, int):
923 name
= 'Unknown AT value: %x' % name
924 self
._emitline
(' <%x> %-18s: %s' % (
928 attr
, die
, section_offset
)))
935 def _dump_debug_line_programs(self
):
936 """ Dump the (decoded) line programs from .debug_line
937 The programs are dumped in the order of the CUs they belong to.
939 if not self
._dwarfinfo
.has_debug_info
:
941 self
._emitline
('Decoded dump of debug contents of section %s:\n' % self
._dwarfinfo
.debug_line_sec
.name
)
943 for cu
in self
._dwarfinfo
.iter_CUs():
944 lineprogram
= self
._dwarfinfo
.line_program_for_CU(cu
)
946 cu_filename
= bytes2str(lineprogram
['file_entry'][0].name
)
947 if len(lineprogram
['include_directory']) > 0:
948 dir_index
= lineprogram
['file_entry'][0].dir_index
950 dir = lineprogram
['include_directory'][dir_index
- 1]
953 cu_filename
= '%s/%s' % (bytes2str(dir), cu_filename
)
955 self
._emitline
('CU: %s:' % cu_filename
)
956 self
._emitline
('File name Line number Starting address')
958 # Print each state's file, line and address information. For some
959 # instructions other output is needed to be compatible with
961 for entry
in lineprogram
.get_entries():
964 # Special handling for commands that don't set a new state
965 if entry
.command
== DW_LNS_set_file
:
966 file_entry
= lineprogram
['file_entry'][entry
.args
[0] - 1]
967 if file_entry
.dir_index
== 0:
969 self
._emitline
('\n./%s:[++]' % (
970 bytes2str(file_entry
.name
)))
972 self
._emitline
('\n%s/%s:' % (
973 bytes2str(lineprogram
['include_directory'][file_entry
.dir_index
- 1]),
974 bytes2str(file_entry
.name
)))
975 elif entry
.command
== DW_LNE_define_file
:
976 self
._emitline
('%s:' % (
977 bytes2str(lineprogram
['include_directory'][entry
.args
[0].dir_index
])))
978 elif not state
.end_sequence
:
979 # readelf doesn't print the state after end_sequence
980 # instructions. I think it's a bug but to be compatible
981 # I don't print them too.
982 if lineprogram
['version'] < 4:
983 self
._emitline
('%-35s %11d %18s' % (
984 bytes2str(lineprogram
['file_entry'][state
.file - 1].name
),
986 '0' if state
.address
== 0 else
987 self
._format
_hex
(state
.address
)))
989 self
._emitline
('%-35s %11d %18s[%d]' % (
990 bytes2str(lineprogram
['file_entry'][state
.file - 1].name
),
992 '0' if state
.address
== 0 else
993 self
._format
_hex
(state
.address
),
995 if entry
.command
== DW_LNS_copy
:
996 # Another readelf oddity...
999 def _dump_frames_info(self
, section
, cfi_entries
):
1000 """ Dump the raw call frame info in a section.
1002 `section` is the Section instance that contains the call frame info
1003 while `cfi_entries` must be an iterable that yields the sequence of
1004 CIE or FDE instances.
1006 self
._emitline
('Contents of the %s section:' % section
.name
)
1008 for entry
in cfi_entries
:
1009 if isinstance(entry
, CIE
):
1010 self
._emitline
('\n%08x %s %s CIE' % (
1012 self
._format
_hex
(entry
['length'], fullhex
=True, lead0x
=False),
1013 self
._format
_hex
(entry
['CIE_id'], fieldsize
=8, lead0x
=False)))
1014 self
._emitline
(' Version: %d' % entry
['version'])
1015 self
._emitline
(' Augmentation: "%s"' % bytes2str(entry
['augmentation']))
1016 self
._emitline
(' Code alignment factor: %u' % entry
['code_alignment_factor'])
1017 self
._emitline
(' Data alignment factor: %d' % entry
['data_alignment_factor'])
1018 self
._emitline
(' Return address column: %d' % entry
['return_address_register'])
1019 if entry
.augmentation_bytes
:
1020 self
._emitline
(' Augmentation data: {}'.format(' '.join(
1021 '{:02x}'.format(ord(b
))
1022 for b
in iterbytes(entry
.augmentation_bytes
)
1026 elif isinstance(entry
, FDE
):
1027 self
._emitline
('\n%08x %s %s FDE cie=%08x pc=%s..%s' % (
1029 self
._format
_hex
(entry
['length'], fullhex
=True, lead0x
=False),
1030 self
._format
_hex
(entry
['CIE_pointer'], fieldsize
=8, lead0x
=False),
1032 self
._format
_hex
(entry
['initial_location'], fullhex
=True, lead0x
=False),
1034 entry
['initial_location'] + entry
['address_range'],
1035 fullhex
=True, lead0x
=False)))
1036 if entry
.augmentation_bytes
:
1037 self
._emitline
(' Augmentation data: {}'.format(' '.join(
1038 '{:02x}'.format(ord(b
))
1039 for b
in iterbytes(entry
.augmentation_bytes
)
1042 else: # ZERO terminator
1043 assert isinstance(entry
, ZERO
)
1044 self
._emitline
('\n%08x ZERO terminator' % entry
.offset
)
1047 self
._emit
(describe_CFI_instructions(entry
))
1050 def _dump_debug_frames(self
):
1051 """ Dump the raw frame info from .debug_frame and .eh_frame sections.
1053 if self
._dwarfinfo
.has_EH_CFI():
1054 self
._dump
_frames
_info
(
1055 self
._dwarfinfo
.eh_frame_sec
,
1056 self
._dwarfinfo
.EH_CFI_entries())
1059 if self
._dwarfinfo
.has_CFI():
1060 self
._dump
_frames
_info
(
1061 self
._dwarfinfo
.debug_frame_sec
,
1062 self
._dwarfinfo
.CFI_entries())
1064 def _dump_debug_aranges(self
):
1065 """ Dump the aranges table
1067 aranges_table
= self
._dwarfinfo
.get_aranges()
1068 if aranges_table
== None:
1070 # seems redundent, but we need to get the unsorted set of entries to match system readelf
1071 unordered_entries
= aranges_table
._get
_entries
()
1073 if len(unordered_entries
) == 0:
1075 self
._emitline
("Section '.debug_aranges' has no debugging data.")
1078 self
._emitline
('Contents of the %s section:' % self
._dwarfinfo
.debug_aranges_sec
.name
)
1081 for entry
in unordered_entries
:
1082 if prev_offset
!= entry
.info_offset
:
1083 if entry
!= unordered_entries
[0]:
1084 self
._emitline
(' %s %s' % (
1085 self
._format
_hex
(0, fullhex
=True, lead0x
=False),
1086 self
._format
_hex
(0, fullhex
=True, lead0x
=False)))
1087 self
._emitline
(' Length: %d' % (entry
.unit_length
))
1088 self
._emitline
(' Version: %d' % (entry
.version
))
1089 self
._emitline
(' Offset into .debug_info: 0x%x' % (entry
.info_offset
))
1090 self
._emitline
(' Pointer Size: %d' % (entry
.address_size
))
1091 self
._emitline
(' Segment Size: %d' % (entry
.segment_size
))
1093 self
._emitline
(' Address Length')
1094 self
._emitline
(' %s %s' % (
1095 self
._format
_hex
(entry
.begin_addr
, fullhex
=True, lead0x
=False),
1096 self
._format
_hex
(entry
.length
, fullhex
=True, lead0x
=False)))
1097 prev_offset
= entry
.info_offset
1098 self
._emitline
(' %s %s' % (
1099 self
._format
_hex
(0, fullhex
=True, lead0x
=False),
1100 self
._format
_hex
(0, fullhex
=True, lead0x
=False)))
1102 def _dump_frames_interp_info(self
, section
, cfi_entries
):
1103 """ Dump interpreted (decoded) frame information in a section.
1105 `section` is the Section instance that contains the call frame info
1106 while `cfi_entries` must be an iterable that yields the sequence of
1107 CIE or FDE instances.
1109 self
._emitline
('Contents of the %s section:' % section
.name
)
1111 for entry
in cfi_entries
:
1112 if isinstance(entry
, CIE
):
1113 self
._emitline
('\n%08x %s %s CIE "%s" cf=%d df=%d ra=%d' % (
1115 self
._format
_hex
(entry
['length'], fullhex
=True, lead0x
=False),
1116 self
._format
_hex
(entry
['CIE_id'], fieldsize
=8, lead0x
=False),
1117 bytes2str(entry
['augmentation']),
1118 entry
['code_alignment_factor'],
1119 entry
['data_alignment_factor'],
1120 entry
['return_address_register']))
1121 ra_regnum
= entry
['return_address_register']
1123 elif isinstance(entry
, FDE
):
1124 self
._emitline
('\n%08x %s %s FDE cie=%08x pc=%s..%s' % (
1126 self
._format
_hex
(entry
['length'], fullhex
=True, lead0x
=False),
1127 self
._format
_hex
(entry
['CIE_pointer'], fieldsize
=8, lead0x
=False),
1129 self
._format
_hex
(entry
['initial_location'], fullhex
=True, lead0x
=False),
1130 self
._format
_hex
(entry
['initial_location'] + entry
['address_range'],
1131 fullhex
=True, lead0x
=False)))
1132 ra_regnum
= entry
.cie
['return_address_register']
1134 # If the FDE brings adds no unwinding information compared to
1135 # its CIE, omit its table.
1136 if (len(entry
.get_decoded().table
) ==
1137 len(entry
.cie
.get_decoded().table
)):
1140 else: # ZERO terminator
1141 assert isinstance(entry
, ZERO
)
1142 self
._emitline
('\n%08x ZERO terminator' % entry
.offset
)
1146 # Print the heading row for the decoded table
1148 self
._emit
(' ' if entry
.structs
.address_size
== 4 else ' ')
1151 # Decode the table and look at the registers it describes.
1152 # We build reg_order here to match readelf's order. In particular,
1153 # registers are sorted by their number, and the register matching
1154 # ra_regnum is always listed last with a special heading.
1155 decoded_table
= entry
.get_decoded()
1156 reg_order
= sorted(ifilter(
1157 lambda r
: r
!= ra_regnum
,
1158 decoded_table
.reg_order
))
1159 if len(decoded_table
.reg_order
):
1161 # Headings for the registers
1162 for regnum
in reg_order
:
1163 self
._emit
('%-6s' % describe_reg_name(regnum
))
1164 self
._emitline
('ra ')
1166 # Now include ra_regnum in reg_order to print its values
1167 # similarly to the other registers.
1168 reg_order
.append(ra_regnum
)
1172 for line
in decoded_table
.table
:
1173 self
._emit
(self
._format
_hex
(
1174 line
['pc'], fullhex
=True, lead0x
=False))
1175 self
._emit
(' %-9s' % describe_CFI_CFA_rule(line
['cfa']))
1177 for regnum
in reg_order
:
1179 s
= describe_CFI_register_rule(line
[regnum
])
1182 self
._emit
('%-6s' % s
)
1186 def _dump_debug_frames_interp(self
):
1187 """ Dump the interpreted (decoded) frame information from .debug_frame
1188 and .eh_framae sections.
1190 if self
._dwarfinfo
.has_EH_CFI():
1191 self
._dump
_frames
_interp
_info
(
1192 self
._dwarfinfo
.eh_frame_sec
,
1193 self
._dwarfinfo
.EH_CFI_entries())
1196 if self
._dwarfinfo
.has_CFI():
1197 self
._dump
_frames
_interp
_info
(
1198 self
._dwarfinfo
.debug_frame_sec
,
1199 self
._dwarfinfo
.CFI_entries())
1201 def _display_arch_specific_arm(self
):
1202 """ Display the ARM architecture-specific info contained in the file.
1204 attr_sec
= self
.elffile
.get_section_by_name('.ARM.attributes')
1206 for s
in attr_sec
.iter_subsections():
1207 self
._emitline
("Attribute Section: %s" % s
.header
['vendor_name'])
1208 for ss
in s
.iter_subsubsections():
1209 h_val
= "" if ss
.header
.extra
is None else " ".join("%d" % x
for x
in ss
.header
.extra
)
1210 self
._emitline
(describe_attr_tag_arm(ss
.header
.tag
, h_val
, None))
1212 for attr
in ss
.iter_attributes():
1214 self
._emitline
(describe_attr_tag_arm(attr
.tag
,
1218 def _emit(self
, s
=''):
1219 """ Emit an object to output
1221 self
.output
.write(str(s
))
1223 def _emitline(self
, s
=''):
1224 """ Emit an object to output, followed by a newline
1226 self
.output
.write(str(s
).rstrip() + '\n')
1229 SCRIPT_DESCRIPTION
= 'Display information about the contents of ELF format files'
1230 VERSION_STRING
= '%%prog: based on pyelftools %s' % __version__
1233 def main(stream
=None):
1234 # parse the command-line arguments and invoke ReadElf
1235 optparser
= OptionParser(
1236 usage
='usage: %prog [options] <elf-file>',
1237 description
=SCRIPT_DESCRIPTION
,
1238 add_help_option
=False, # -h is a real option of readelf
1240 version
=VERSION_STRING
)
1241 optparser
.add_option('-d', '--dynamic',
1242 action
='store_true', dest
='show_dynamic_tags',
1243 help='Display the dynamic section')
1244 optparser
.add_option('-H', '--help',
1245 action
='store_true', dest
='help',
1246 help='Display this information')
1247 optparser
.add_option('-h', '--file-header',
1248 action
='store_true', dest
='show_file_header',
1249 help='Display the ELF file header')
1250 optparser
.add_option('-l', '--program-headers', '--segments',
1251 action
='store_true', dest
='show_program_header',
1252 help='Display the program headers')
1253 optparser
.add_option('-S', '--section-headers', '--sections',
1254 action
='store_true', dest
='show_section_header',
1255 help="Display the sections' headers")
1256 optparser
.add_option('-e', '--headers',
1257 action
='store_true', dest
='show_all_headers',
1258 help='Equivalent to: -h -l -S')
1259 optparser
.add_option('-s', '--symbols', '--syms',
1260 action
='store_true', dest
='show_symbols',
1261 help='Display the symbol table')
1262 optparser
.add_option('-n', '--notes',
1263 action
='store_true', dest
='show_notes',
1264 help='Display the core notes (if present)')
1265 optparser
.add_option('-r', '--relocs',
1266 action
='store_true', dest
='show_relocs',
1267 help='Display the relocations (if present)')
1268 optparser
.add_option('-x', '--hex-dump',
1269 action
='store', dest
='show_hex_dump', metavar
='<number|name>',
1270 help='Dump the contents of section <number|name> as bytes')
1271 optparser
.add_option('-p', '--string-dump',
1272 action
='store', dest
='show_string_dump', metavar
='<number|name>',
1273 help='Dump the contents of section <number|name> as strings')
1274 optparser
.add_option('-V', '--version-info',
1275 action
='store_true', dest
='show_version_info',
1276 help='Display the version sections (if present)')
1277 optparser
.add_option('-A', '--arch-specific',
1278 action
='store_true', dest
='show_arch_specific',
1279 help='Display the architecture-specific information (if present)')
1280 optparser
.add_option('--debug-dump',
1281 action
='store', dest
='debug_dump_what', metavar
='<what>',
1283 'Display the contents of DWARF debug sections. <what> can ' +
1284 'one of {info,decodedline,frames,frames-interp}'))
1286 options
, args
= optparser
.parse_args()
1288 if options
.help or len(args
) == 0:
1289 optparser
.print_help()
1292 if options
.show_all_headers
:
1293 do_file_header
= do_section_header
= do_program_header
= True
1295 do_file_header
= options
.show_file_header
1296 do_section_header
= options
.show_section_header
1297 do_program_header
= options
.show_program_header
1299 with
open(args
[0], 'rb') as file:
1301 readelf
= ReadElf(file, stream
or sys
.stdout
)
1303 readelf
.display_file_header()
1304 if do_section_header
:
1305 readelf
.display_section_headers(
1306 show_heading
=not do_file_header
)
1307 if do_program_header
:
1308 readelf
.display_program_headers(
1309 show_heading
=not do_file_header
)
1310 if options
.show_dynamic_tags
:
1311 readelf
.display_dynamic_tags()
1312 if options
.show_symbols
:
1313 readelf
.display_symbol_tables()
1314 if options
.show_notes
:
1315 readelf
.display_notes()
1316 if options
.show_relocs
:
1317 readelf
.display_relocations()
1318 if options
.show_version_info
:
1319 readelf
.display_version_info()
1320 if options
.show_arch_specific
:
1321 readelf
.display_arch_specific()
1322 if options
.show_hex_dump
:
1323 readelf
.display_hex_dump(options
.show_hex_dump
)
1324 if options
.show_string_dump
:
1325 readelf
.display_string_dump(options
.show_string_dump
)
1326 if options
.debug_dump_what
:
1327 readelf
.display_debug_dump(options
.debug_dump_what
)
1328 except ELFError
as ex
:
1329 sys
.stderr
.write('ELF error: %s\n' % ex
)
1334 # Run 'main' redirecting its output to readelfout.txt
1335 # Saves profiling information in readelf.profile
1336 PROFFILE
= 'readelf.profile'
1338 cProfile
.run('main(open("readelfout.txt", "w"))', PROFFILE
)
1340 # Dig in some profiling stats
1342 p
= pstats
.Stats(PROFFILE
)
1343 p
.sort_stats('cumulative').print_stats(25)
1346 #-------------------------------------------------------------------------------
1347 if __name__
== '__main__':