2 #-------------------------------------------------------------------------------
5 # A clone of 'elfdump' in Python, based on the pyelftools library
7 # Eli Bendersky (eliben@gmail.com)
8 # Yann Rouillard (yann@pleiades.fr.eu.org)
9 # This code is in the public domain
10 #-------------------------------------------------------------------------------
12 from optparse
import OptionParser
15 # For running from development directory. It should take precedence over the
16 # installed pyelftools.
17 sys
.path
.insert(0, '.')
20 from elftools
import __version__
21 from elftools
.common
.exceptions
import ELFError
22 from elftools
.common
.py3compat
import (
23 ifilter
, byte2int
, bytes2str
, itervalues
, str2bytes
)
24 from elftools
.elf
.elffile
import ELFFile
25 from elftools
.elf
.dynamic
import DynamicSection
, DynamicSegment
26 from elftools
.elf
.enums
import ENUM_D_TAG
27 from elftools
.elf
.constants
import SYMINFO_FLAGS
28 from elftools
.elf
.segments
import InterpSegment
29 from elftools
.elf
.sections
import SUNWSyminfoTableSection
30 from elftools
.elf
.relocation
import RelocationSection
31 from elftools
.elf
.descriptions
import (
32 describe_ei_class
, describe_ei_data
, describe_ei_version
,
33 describe_ei_osabi
, describe_e_type
, describe_e_machine
,
34 describe_e_version_numeric
, describe_p_type
, describe_p_flags
,
35 describe_sh_type
, describe_sh_flags
,
36 describe_symbol_type
, describe_symbol_bind
, describe_symbol_visibility
,
37 describe_symbol_shndx
, describe_reloc_type
, describe_dyn_tag
,
38 describe_syminfo_flags
,
40 from elftools
.dwarf
.dwarfinfo
import DWARFInfo
41 from elftools
.dwarf
.descriptions
import (
42 describe_reg_name
, describe_attr_value
, set_global_machine_arch
,
43 describe_CFI_instructions
, describe_CFI_register_rule
,
44 describe_CFI_CFA_rule
,
46 from elftools
.dwarf
.constants
import (
47 DW_LNS_copy
, DW_LNS_set_file
, DW_LNE_define_file
)
48 from elftools
.dwarf
.callframe
import CIE
, FDE
51 class Elfdump(object):
52 """ display_* methods are used to emit output into the output stream
54 def __init__(self
, file, output
):
56 stream object with the ELF file to read
59 output stream to write to
61 self
.elffile
= ELFFile(file)
64 def display_syminfo_table(self
):
65 """ Display the SUNW syminfo tables contained in the file
67 for section
in self
.elffile
.iter_sections():
68 if isinstance(section
, SUNWSyminfoTableSection
):
69 syminfo_section
= section
73 # We need to dyntable to do get the soname names
74 dyntable
= self
.elffile
.get_section_by_name('.dynamic')
76 if section
['sh_entsize'] == 0:
77 self
._emitline
("\nSymbol table '%s' has a sh_entsize of zero!"
78 % (bytes2str(section
.name
)))
81 # The symbol table section pointed to in sh_link
82 symtable
= self
.elffile
.get_section(section
['sh_link'])
84 self
._emitline
("\nSyminfo Section: %s" % bytes2str(section
.name
))
85 self
._emitline
('%10s %-5s %10s %-24s %s'
86 % ('index', 'flags', '', 'bound to', 'symbol'))
88 for nsym
, syminfo
in enumerate(section
.iter_symbols(), start
=1):
90 # elfdump doesn't display anything for this kind of symbols
91 symbol
= symtable
.get_symbol(nsym
)
92 if (symbol
['st_info']['type'] == 'STT_NOTYPE' and
93 symbol
['st_shndx'] == 'SHN_UNDEF'):
97 if syminfo
['si_flags'] & SYMINFO_FLAGS
.SYMINFO_FLG_CAP
:
98 boundto
= '<symbol capabilities>'
99 elif syminfo
['si_boundto'] == 0xffff:
101 elif syminfo
['si_boundto'] == 0xfffe:
103 elif syminfo
['si_boundto'] == 0xfffd:
106 dyn_tag
= dyntable
.get_tag(syminfo
['si_boundto'])
107 boundto
= bytes2str(dyn_tag
.needed
)
108 index
= '[%d]' % syminfo
['si_boundto']
110 # syminfo names are truncated to 25 chars, similarly to readelf
111 self
._emitline
('%10s %-5s %10s %-24s %s' % (
112 '[%d]' % (int(nsym
)),
113 describe_syminfo_flags(syminfo
['si_flags']),
116 bytes2str(syminfo
.name
)))
118 def _emit(self
, s
=''):
119 """ Emit an object to output
121 self
.output
.write(str(s
))
123 def _emitline(self
, s
=''):
124 """ Emit an object to output, followed by a newline
126 self
.output
.write(str(s
) + '\n')
129 SCRIPT_DESCRIPTION
= 'Dumps selected parts of an object file'
130 VERSION_STRING
= '%%prog: based on pyelftools %s' % __version__
133 def main(stream
=None):
134 # parse the command-line arguments and invoke ReadElf
135 optparser
= OptionParser(
136 usage
='usage: %prog [options] <elf-file>',
137 description
=SCRIPT_DESCRIPTION
,
138 add_help_option
=False, # -h is a real option of readelf
140 version
=VERSION_STRING
)
141 optparser
.add_option('--help',
142 action
='store_true', dest
='help',
143 help='Display this information')
144 optparser
.add_option('-y',
145 action
='store_true', dest
='show_syminfo',
146 help='dump the contents of the .SUNW_syminfo section')
148 options
, args
= optparser
.parse_args()
150 if options
.help or len(args
) == 0:
151 optparser
.print_help()
154 with
open(args
[0], 'rb') as file:
156 readelf
= Elfdump(file, stream
or sys
.stdout
)
157 if options
.show_syminfo
:
158 readelf
.display_syminfo_table()
159 except ELFError
as ex
:
160 sys
.stderr
.write('ELF error: %s\n' % ex
)
165 # Run 'main' redirecting its output to readelfout.txt
166 # Saves profiling information in readelf.profile
167 PROFFILE
= 'elfdump.profile'
169 cProfile
.run('main(open("elfdumpout.txt", "w"))', PROFFILE
)
171 # Dig in some profiling stats
173 p
= pstats
.Stats(PROFFILE
)
174 p
.sort_stats('cumulative').print_stats(25)
177 #-------------------------------------------------------------------------------
178 if __name__
== '__main__':