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
15 # If elftools is not installed, maybe we're running from the root or scripts
16 # dir of the source distribution
21 sys
.path
.extend(['.', '..'])
23 from elftools
import __version__
24 from elftools
.common
.exceptions
import ELFError
25 from elftools
.elf
.elffile
import ELFFile
26 from elftools
.elf
.segments
import InterpSegment
27 from elftools
.elf
.sections
import SymbolTableSection
28 from elftools
.elf
.relocation
import RelocationSection
29 from elftools
.elf
.descriptions
import (
30 describe_ei_class
, describe_ei_data
, describe_ei_version
,
31 describe_ei_osabi
, describe_e_type
, describe_e_machine
,
32 describe_e_version_numeric
, describe_p_type
, describe_p_flags
,
33 describe_sh_type
, describe_sh_flags
,
34 describe_symbol_type
, describe_symbol_bind
, describe_symbol_visibility
,
35 describe_symbol_shndx
, describe_reloc_type
,
37 from elftools
.dwarf
.dwarfinfo
import DWARFInfo
38 from elftools
.dwarf
.descriptions
import (
39 describe_attr_value
, set_global_machine_arch
, describe_CFI_instructions
)
40 from elftools
.dwarf
.constants
import (
41 DW_LNS_copy
, DW_LNS_set_file
, DW_LNE_define_file
)
42 from elftools
.dwarf
.callframe
import CIE
, FDE
45 class ReadElf(object):
46 """ display_* methods are used to emit output into the output stream
48 def __init__(self
, file, output
):
50 stream object with the ELF file to read
53 output stream to write to
55 self
.elffile
= ELFFile(file)
58 # Lazily initialized if a debug dump is requested
59 self
._dwarfinfo
= None
61 def display_file_header(self
):
62 """ Display the ELF file header
64 self
._emitline
('ELF Header:')
65 self
._emit
(' Magic: ')
66 self
._emitline
(' '.join('%2.2x' % ord(b
)
67 for b
in self
.elffile
.e_ident_raw
))
68 header
= self
.elffile
.header
69 e_ident
= header
['e_ident']
70 self
._emitline
(' Class: %s' %
71 describe_ei_class(e_ident
['EI_CLASS']))
72 self
._emitline
(' Data: %s' %
73 describe_ei_data(e_ident
['EI_DATA']))
74 self
._emitline
(' Version: %s' %
75 describe_ei_version(e_ident
['EI_VERSION']))
76 self
._emitline
(' OS/ABI: %s' %
77 describe_ei_osabi(e_ident
['EI_OSABI']))
78 self
._emitline
(' ABI Version: %d' %
79 e_ident
['EI_ABIVERSION'])
80 self
._emitline
(' Type: %s' %
81 describe_e_type(header
['e_type']))
82 self
._emitline
(' Machine: %s' %
83 describe_e_machine(header
['e_machine']))
84 self
._emitline
(' Version: %s' %
85 describe_e_version_numeric(header
['e_version']))
86 self
._emitline
(' Entry point address: %s' %
87 self
._format
_hex
(header
['e_entry']))
88 self
._emit
(' Start of program headers: %s' %
90 self
._emitline
(' (bytes into file)')
91 self
._emit
(' Start of section headers: %s' %
93 self
._emitline
(' (bytes into file)')
94 self
._emitline
(' Flags: %s' %
95 self
._format
_hex
(header
['e_flags']))
96 self
._emitline
(' Size of this header: %s (bytes)' %
98 self
._emitline
(' Size of program headers: %s (bytes)' %
99 header
['e_phentsize'])
100 self
._emitline
(' Number of program headers: %s' %
102 self
._emitline
(' Size of section headers: %s (bytes)' %
103 header
['e_shentsize'])
104 self
._emitline
(' Number of section headers: %s' %
106 self
._emitline
(' Section header string table index: %s' %
107 header
['e_shstrndx'])
109 def display_program_headers(self
, show_heading
=True):
110 """ Display the ELF program headers.
111 If show_heading is True, displays the heading for this information
112 (Elf file type is...)
115 if self
.elffile
.num_segments() == 0:
116 self
._emitline
('There are no program headers in this file.')
119 elfheader
= self
.elffile
.header
121 self
._emitline
('Elf file type is %s' %
122 describe_e_type(elfheader
['e_type']))
123 self
._emitline
('Entry point is %s' %
124 self
._format
_hex
(elfheader
['e_entry']))
125 # readelf weirness - why isn't e_phoff printed as hex? (for section
127 self
._emitline
('There are %s program headers, starting at offset %s' % (
128 elfheader
['e_phnum'], elfheader
['e_phoff']))
131 self
._emitline
('Program Headers:')
133 # Now comes the table of program headers with their attributes. Note
134 # that due to different formatting constraints of 32-bit and 64-bit
135 # addresses, there are some conditions on elfclass here.
137 # First comes the table heading
139 if self
.elffile
.elfclass
== 32:
140 self
._emitline
(' Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align')
142 self
._emitline
(' Type Offset VirtAddr PhysAddr')
143 self
._emitline
(' FileSiz MemSiz Flags Align')
147 for segment
in self
.elffile
.iter_segments():
148 self
._emit
(' %-14s ' % describe_p_type(segment
['p_type']))
150 if self
.elffile
.elfclass
== 32:
151 self
._emitline
('%s %s %s %s %s %-3s %s' % (
152 self
._format
_hex
(segment
['p_offset'], fieldsize
=6),
153 self
._format
_hex
(segment
['p_vaddr'], fullhex
=True),
154 self
._format
_hex
(segment
['p_paddr'], fullhex
=True),
155 self
._format
_hex
(segment
['p_filesz'], fieldsize
=5),
156 self
._format
_hex
(segment
['p_memsz'], fieldsize
=5),
157 describe_p_flags(segment
['p_flags']),
158 self
._format
_hex
(segment
['p_align'])))
160 self
._emitline
('%s %s %s' % (
161 self
._format
_hex
(segment
['p_offset'], fullhex
=True),
162 self
._format
_hex
(segment
['p_vaddr'], fullhex
=True),
163 self
._format
_hex
(segment
['p_paddr'], fullhex
=True)))
164 self
._emitline
(' %s %s %-3s %s' % (
165 self
._format
_hex
(segment
['p_filesz'], fullhex
=True),
166 self
._format
_hex
(segment
['p_memsz'], fullhex
=True),
167 describe_p_flags(segment
['p_flags']),
168 # lead0x set to False for p_align, to mimic readelf.
169 # No idea why the difference from 32-bit mode :-|
170 self
._format
_hex
(segment
['p_align'], lead0x
=False)))
172 if isinstance(segment
, InterpSegment
):
173 self
._emitline
(' [Requesting program interpreter: %s]' %
174 segment
.get_interp_name())
176 # Sections to segments mapping
178 if self
.elffile
.num_sections() == 0:
179 # No sections? We're done
182 self
._emitline
('\n Section to Segment mapping:')
183 self
._emitline
(' Segment Sections...')
185 for nseg
, segment
in enumerate(self
.elffile
.iter_segments()):
186 self
._emit
(' %2.2d ' % nseg
)
188 for section
in self
.elffile
.iter_sections():
189 if ( not section
.is_null() and
190 segment
.section_in_segment(section
)):
191 self
._emit
('%s ' % section
.name
)
195 def display_section_headers(self
, show_heading
=True):
196 """ Display the ELF section headers
198 elfheader
= self
.elffile
.header
200 self
._emitline
('There are %s section headers, starting at offset %s' % (
201 elfheader
['e_shnum'], self
._format
_hex
(elfheader
['e_shoff'])))
203 self
._emitline
('\nSection Header%s:' % (
204 's' if elfheader
['e_shnum'] > 1 else ''))
206 # Different formatting constraints of 32-bit and 64-bit addresses
208 if self
.elffile
.elfclass
== 32:
209 self
._emitline
(' [Nr] Name Type Addr Off Size ES Flg Lk Inf Al')
211 self
._emitline
(' [Nr] Name Type Address Offset')
212 self
._emitline
(' Size EntSize Flags Link Info Align')
216 for nsec
, section
in enumerate(self
.elffile
.iter_sections()):
217 self
._emit
(' [%2u] %-17.17s %-15.15s ' % (
218 nsec
, section
.name
, describe_sh_type(section
['sh_type'])))
220 if self
.elffile
.elfclass
== 32:
221 self
._emitline
('%s %s %s %s %3s %2s %3s %2s' % (
222 self
._format
_hex
(section
['sh_addr'], fieldsize
=8, lead0x
=False),
223 self
._format
_hex
(section
['sh_offset'], fieldsize
=6, lead0x
=False),
224 self
._format
_hex
(section
['sh_size'], fieldsize
=6, lead0x
=False),
225 self
._format
_hex
(section
['sh_entsize'], fieldsize
=2, lead0x
=False),
226 describe_sh_flags(section
['sh_flags']),
227 section
['sh_link'], section
['sh_info'],
228 section
['sh_addralign']))
230 self
._emitline
(' %s %s' % (
231 self
._format
_hex
(section
['sh_addr'], fullhex
=True, lead0x
=False),
232 self
._format
_hex
(section
['sh_offset'],
233 fieldsize
=16 if section
['sh_offset'] > 0xffffffff else 8,
235 self
._emitline
(' %s %s %3s %2s %3s %s' % (
236 self
._format
_hex
(section
['sh_size'], fullhex
=True, lead0x
=False),
237 self
._format
_hex
(section
['sh_entsize'], fullhex
=True, lead0x
=False),
238 describe_sh_flags(section
['sh_flags']),
239 section
['sh_link'], section
['sh_info'],
240 section
['sh_addralign']))
242 self
._emitline
('Key to Flags:')
243 self
._emit
(' W (write), A (alloc), X (execute), M (merge), S (strings)')
244 if self
.elffile
['e_machine'] in ('EM_X86_64', 'EM_L10M'):
245 self
._emitline
(', l (large)')
248 self
._emitline
(' I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)')
249 self
._emitline
(' O (extra OS processing required) o (OS specific), p (processor specific)')
251 def display_symbol_tables(self
):
252 """ Display the symbol tables contained in the file
254 for section
in self
.elffile
.iter_sections():
255 if not isinstance(section
, SymbolTableSection
):
258 if section
['sh_entsize'] == 0:
259 self
._emitline
("\nSymbol table '%s' has a sh_entsize of zero!" % (
263 self
._emitline
("\nSymbol table '%s' contains %s entries:" % (
264 section
.name
, section
.num_symbols()))
266 if self
.elffile
.elfclass
== 32:
267 self
._emitline
(' Num: Value Size Type Bind Vis Ndx Name')
269 self
._emitline
(' Num: Value Size Type Bind Vis Ndx Name')
271 for nsym
, symbol
in enumerate(section
.iter_symbols()):
272 # symbol names are truncated to 25 chars, similarly to readelf
273 self
._emitline
('%6d: %s %5d %-7s %-6s %-7s %4s %.25s' % (
275 self
._format
_hex
(symbol
['st_value'], fullhex
=True, lead0x
=False),
277 describe_symbol_type(symbol
['st_info']['type']),
278 describe_symbol_bind(symbol
['st_info']['bind']),
279 describe_symbol_visibility(symbol
['st_other']['visibility']),
280 describe_symbol_shndx(symbol
['st_shndx']),
283 def display_relocations(self
):
284 """ Display the relocations contained in the file
286 has_relocation_sections
= False
287 for section
in self
.elffile
.iter_sections():
288 if not isinstance(section
, RelocationSection
):
291 has_relocation_sections
= True
292 self
._emitline
("\nRelocation section '%s' at offset %s contains %s entries:" % (
294 self
._format
_hex
(section
['sh_offset']),
295 section
.num_relocations()))
296 if section
.is_RELA():
297 self
._emitline
(" Offset Info Type Sym. Value Sym. Name + Addend")
299 self
._emitline
(" Offset Info Type Sym.Value Sym. Name")
301 # The symbol table section pointed to in sh_link
302 symtable
= self
.elffile
.get_section(section
['sh_link'])
304 for rel
in section
.iter_relocations():
305 hexwidth
= 8 if self
.elffile
.elfclass
== 32 else 12
306 self
._emit
('%s %s %-17.17s' % (
307 self
._format
_hex
(rel
['r_offset'],
308 fieldsize
=hexwidth
, lead0x
=False),
309 self
._format
_hex
(rel
['r_info'],
310 fieldsize
=hexwidth
, lead0x
=False),
312 rel
['r_info_type'], self
.elffile
)))
314 if rel
['r_info_sym'] == 0:
318 symbol
= symtable
.get_symbol(rel
['r_info_sym'])
319 # Some symbols have zero 'st_name', so instead what's used is
320 # the name of the section they point at
321 if symbol
['st_name'] == 0:
322 symsec
= self
.elffile
.get_section(symbol
['st_shndx'])
323 symbol_name
= symsec
.name
325 symbol_name
= symbol
.name
326 self
._emit
(' %s %s%22.22s' % (
329 fullhex
=True, lead0x
=False),
330 ' ' if self
.elffile
.elfclass
== 32 else '',
332 if section
.is_RELA():
333 self
._emit
(' %s %x' % (
334 '+' if rel
['r_addend'] >= 0 else '-',
335 abs(rel
['r_addend'])))
338 if not has_relocation_sections
:
339 self
._emitline
('\nThere are no relocations in this file.')
341 def display_hex_dump(self
, section_spec
):
342 """ Display a hex dump of a section. section_spec is either a section
345 section
= self
._section
_from
_spec
(section_spec
)
347 self
._emitline
("Section '%s' does not exist in the file!" % (
351 self
._emitline
("\nHex dump of section '%s':" % section
.name
)
352 self
._note
_relocs
_for
_section
(section
)
353 addr
= section
['sh_addr']
354 data
= section
.data()
357 while dataptr
< len(data
):
358 bytesleft
= len(data
) - dataptr
359 # chunks of 16 bytes per line
360 linebytes
= 16 if bytesleft
> 16 else bytesleft
362 self
._emit
(' %s ' % self
._format
_hex
(addr
, fieldsize
=8))
365 self
._emit
('%2.2x' % ord(data
[dataptr
+ i
]))
371 for i
in range(linebytes
):
372 c
= data
[dataptr
+ i
]
373 if c
>= ' ' and ord(c
) < 0x7f:
384 def display_string_dump(self
, section_spec
):
385 """ Display a strings dump of a section. section_spec is either a
386 section number or a name.
388 section
= self
._section
_from
_spec
(section_spec
)
390 self
._emitline
("Section '%s' does not exist in the file!" % (
394 printables
= set(string
.printable
)
395 self
._emitline
("\nString dump of section '%s':" % section
.name
)
398 data
= section
.data()
401 while dataptr
< len(data
):
402 while dataptr
< len(data
) and data
[dataptr
] not in printables
:
405 if dataptr
>= len(data
):
409 while endptr
< len(data
) and data
[endptr
] != '\x00':
413 self
._emitline
(' [%6x] %s' % (
414 dataptr
, data
[dataptr
:endptr
]))
419 self
._emitline
(' No strings found in this section.')
423 def display_debug_dump(self
, dump_what
):
424 """ Dump a DWARF section
426 self
._init
_dwarfinfo
()
427 if self
._dwarfinfo
is None:
430 set_global_machine_arch(self
.elffile
.get_machine_arch())
432 if dump_what
== 'info':
433 self
._dump
_debug
_info
()
434 elif dump_what
== 'decodedline':
435 self
._dump
_debug
_line
_programs
()
436 elif dump_what
== 'frames':
437 self
._dump
_debug
_frames
()
439 self
._emitline
('debug dump not yet supported for "%s"' % dump_what
)
441 def _format_hex(self
, addr
, fieldsize
=None, fullhex
=False, lead0x
=True):
442 """ Format an address into a hexadecimal string.
445 Size of the hexadecimal field (with leading zeros to fit the
446 address into. For example with fieldsize=8, the format will
448 If None, the minimal required field size will be used.
451 If True, override fieldsize to set it to the maximal size
452 needed for the elfclass
455 If True, leading 0x is added
457 s
= '0x' if lead0x
else ''
459 fieldsize
= 8 if self
.elffile
.elfclass
== 32 else 16
460 if fieldsize
is None:
463 field
= '%' + '0%sx' % fieldsize
464 return s
+ field
% addr
466 def _section_from_spec(self
, spec
):
467 """ Retrieve a section given a "spec" (either number or name).
468 Return None if no such section exists in the file.
472 if num
< self
.elffile
.num_sections():
473 return self
.elffile
.get_section(num
)
477 # Not a number. Must be a name then
478 return self
.elffile
.get_section_by_name(spec
)
480 def _note_relocs_for_section(self
, section
):
481 """ If there are relocation sections pointing to the givne section,
482 emit a note about it.
484 for relsec
in self
.elffile
.iter_sections():
485 if isinstance(relsec
, RelocationSection
):
486 info_idx
= relsec
['sh_info']
487 if self
.elffile
.get_section(info_idx
) == section
:
488 self
._emitline
(' Note: This section has relocations against it, but these have NOT been applied to this dump.')
491 def _init_dwarfinfo(self
):
492 """ Initialize the DWARF info contained in the file and assign it to
494 Leave self._dwarfinfo at None if no DWARF info was found in the file
496 if self
._dwarfinfo
is not None:
499 if self
.elffile
.has_dwarf_info():
500 self
._dwarfinfo
= self
.elffile
.get_dwarf_info()
502 self
._dwarfinfo
= None
504 def _dump_debug_info(self
):
505 """ Dump the debugging info section.
507 self
._emitline
('Contents of the .debug_info section:\n')
509 # Offset of the .debug_info section in the stream
510 section_offset
= self
._dwarfinfo
.debug_info_sec
.global_offset
512 for cu
in self
._dwarfinfo
.iter_CUs():
513 self
._emitline
(' Compilation Unit @ offset %s:' %
514 self
._format
_hex
(cu
.cu_offset
))
515 self
._emitline
(' Length: %s (%s)' % (
516 self
._format
_hex
(cu
['unit_length']),
517 '%s-bit' % cu
.dwarf_format()))
518 self
._emitline
(' Version: %s' % cu
['version']),
519 self
._emitline
(' Abbrev Offset: %s' % cu
['debug_abbrev_offset']),
520 self
._emitline
(' Pointer Size: %s' % cu
['address_size'])
522 # The nesting depth of each DIE within the tree of DIEs must be
523 # displayed. To implement this, a counter is incremented each time
524 # the current DIE has children, and decremented when a null die is
525 # encountered. Due to the way the DIE tree is serialized, this will
526 # correctly reflect the nesting depth
529 for die
in cu
.iter_DIEs():
533 self
._emitline
(' <%s><%x>: Abbrev Number: %s (%s)' % (
539 for attr
in die
.attributes
.itervalues():
540 self
._emitline
(' <%2x> %-18s: %s' % (
544 attr
, die
, section_offset
)))
551 def _dump_debug_line_programs(self
):
552 """ Dump the (decoded) line programs from .debug_line
553 The programs are dumped in the order of the CUs they belong to.
555 self
._emitline
('Decoded dump of debug contents of section .debug_line:\n')
557 for cu
in self
._dwarfinfo
.iter_CUs():
558 lineprogram
= self
._dwarfinfo
.line_program_for_CU(cu
)
561 if len(lineprogram
['include_directory']) > 0:
562 cu_filename
= '%s/%s' % (
563 lineprogram
['include_directory'][0],
564 lineprogram
['file_entry'][0].name
)
566 cu_filename
= lineprogram
['file_entry'][0].name
568 self
._emitline
('CU: %s:' % cu_filename
)
569 self
._emitline
('File name Line number Starting address')
571 # Print each state's file, line and address information. For some
572 # instructions other output is needed to be compatible with
574 for entry
in lineprogram
.get_entries():
577 # Special handling for commands that don't set a new state
578 if entry
.command
== DW_LNS_set_file
:
579 file_entry
= lineprogram
['file_entry'][entry
.args
[0] - 1]
580 if file_entry
.dir_index
== 0:
582 self
._emitline
('\n./%s:[++]' % (
585 self
._emitline
('\n%s/%s:' % (
586 lineprogram
['include_directory'][file_entry
.dir_index
- 1],
588 elif entry
.command
== DW_LNE_define_file
:
589 self
._emitline
('%s:' % (
590 lineprogram
['include_directory'][entry
.args
[0].dir_index
]))
591 elif not state
.end_sequence
:
592 # readelf doesn't print the state after end_sequence
593 # instructions. I think it's a bug but to be compatible
594 # I don't print them too.
595 self
._emitline
('%-35s %11d %18s' % (
596 lineprogram
['file_entry'][state
.file - 1].name
,
598 '0' if state
.address
== 0 else
599 self
._format
_hex
(state
.address
)))
600 if entry
.command
== DW_LNS_copy
:
601 # Another readelf oddity...
604 def _dump_debug_frames(self
):
605 """ Dump the raw frame information from .debug_frame
607 if not self
._dwarfinfo
.has_CFI():
609 self
._emitline
('Contents of the .debug_frame section:')
611 for entry
in self
._dwarfinfo
.CFI_entries():
612 if isinstance(entry
, CIE
):
613 self
._emitline
('\n%08x %08x %08x CIE' % (
614 entry
.offset
, entry
['length'], entry
['CIE_id']))
615 self
._emitline
(' Version: %d' % entry
['version'])
616 self
._emitline
(' Augmentation: "%s"' % entry
['augmentation'])
617 self
._emitline
(' Code alignment factor: %u' % entry
['code_alignment_factor'])
618 self
._emitline
(' Data alignment factor: %d' % entry
['data_alignment_factor'])
619 self
._emitline
(' Return address column: %d' % entry
['return_address_register'])
622 self
._emitline
('\n%08x %08x %08x FDE cie=%08x pc=%08x..%08x' % (
625 entry
['CIE_pointer'],
627 entry
['initial_location'],
628 entry
['initial_location'] + entry
['address_range']))
630 self
._emit
(describe_CFI_instructions(entry
))
633 def _emit(self
, s
=''):
634 """ Emit an object to output
636 self
.output
.write(str(s
))
638 def _emitline(self
, s
=''):
639 """ Emit an object to output, followed by a newline
641 self
.output
.write(str(s
) + '\n')
644 SCRIPT_DESCRIPTION
= 'Display information about the contents of ELF format files'
645 VERSION_STRING
= '%%prog: based on pyelftools %s' % __version__
648 def main(stream
=None):
649 # parse the command-line arguments and invoke ReadElf
650 optparser
= OptionParser(
651 usage
='usage: %prog [options] <elf-file>',
652 description
=SCRIPT_DESCRIPTION
,
653 add_help_option
=False, # -h is a real option of readelf
655 version
=VERSION_STRING
)
656 optparser
.add_option('-H', '--help',
657 action
='store_true', dest
='help',
658 help='Display this information')
659 optparser
.add_option('-h', '--file-header',
660 action
='store_true', dest
='show_file_header',
661 help='Display the ELF file header')
662 optparser
.add_option('-l', '--program-headers', '--segments',
663 action
='store_true', dest
='show_program_header',
664 help='Display the program headers')
665 optparser
.add_option('-S', '--section-headers', '--sections',
666 action
='store_true', dest
='show_section_header',
667 help="Display the sections' headers")
668 optparser
.add_option('-e', '--headers',
669 action
='store_true', dest
='show_all_headers',
670 help='Equivalent to: -h -l -S')
671 optparser
.add_option('-s', '--symbols', '--syms',
672 action
='store_true', dest
='show_symbols',
673 help='Display the symbol table')
674 optparser
.add_option('-r', '--relocs',
675 action
='store_true', dest
='show_relocs',
676 help='Display the relocations (if present)')
677 optparser
.add_option('-x', '--hex-dump',
678 action
='store', dest
='show_hex_dump', metavar
='<number|name>',
679 help='Dump the contents of section <number|name> as bytes')
680 optparser
.add_option('-p', '--string-dump',
681 action
='store', dest
='show_string_dump', metavar
='<number|name>',
682 help='Dump the contents of section <number|name> as strings')
683 optparser
.add_option('--debug-dump',
684 action
='store', dest
='debug_dump_what', metavar
='<section>',
685 help='Display the contents of DWARF debug sections')
687 options
, args
= optparser
.parse_args()
689 if options
.help or len(args
) == 0:
690 optparser
.print_help()
693 if options
.show_all_headers
:
694 do_file_header
= do_section_header
= do_program_header
= True
696 do_file_header
= options
.show_file_header
697 do_section_header
= options
.show_section_header
698 do_program_header
= options
.show_program_header
700 with
open(args
[0], 'rb') as file:
702 readelf
= ReadElf(file, stream
or sys
.stdout
)
704 readelf
.display_file_header()
705 if do_section_header
:
706 readelf
.display_section_headers(
707 show_heading
=not do_file_header
)
708 if do_program_header
:
709 readelf
.display_program_headers(
710 show_heading
=not do_file_header
)
711 if options
.show_symbols
:
712 readelf
.display_symbol_tables()
713 if options
.show_relocs
:
714 readelf
.display_relocations()
715 if options
.show_hex_dump
:
716 readelf
.display_hex_dump(options
.show_hex_dump
)
717 if options
.show_string_dump
:
718 readelf
.display_string_dump(options
.show_string_dump
)
719 if options
.debug_dump_what
:
720 readelf
.display_debug_dump(options
.debug_dump_what
)
721 except ELFError
as ex
:
722 sys
.stderr
.write('ELF error: %s\n' % ex
)
727 # Run 'main' redirecting its output to readelfout.txt
728 # Saves profiling information in readelf.profile
729 PROFFILE
= 'readelf.profile'
731 cProfile
.run('main(open("readelfout.txt", "w"))', PROFFILE
)
733 # Dig in some profiling stats
735 p
= pstats
.Stats(PROFFILE
)
736 p
.sort_stats('cumulative').print_stats(25)
739 #-------------------------------------------------------------------------------
740 if __name__
== '__main__':