blob: 91937cced15e6abe2cfa55e9168293daa3b01180 [file] [log] [blame]
Eli Bendersky3edefab2011-09-16 14:52:54 +03001#!/usr/bin/env python
Eli Bendersky933f6992011-09-09 08:11:06 +03002#-------------------------------------------------------------------------------
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +03003# scripts/readelf.py
Eli Bendersky933f6992011-09-09 08:11:06 +03004#
5# A clone of 'readelf' in Python, based on the pyelftools library
6#
7# Eli Bendersky (eliben@gmail.com)
8# This code is in the public domain
9#-------------------------------------------------------------------------------
Eli Bendersky53e86db2011-09-18 06:04:30 +030010import os, sys
Eli Bendersky933f6992011-09-09 08:11:06 +030011from optparse import OptionParser
Eli Bendersky53e86db2011-09-18 06:04:30 +030012import string
13
Eli Bendersky34d80012013-04-08 06:41:37 -070014# For running from development directory. It should take precedence over the
15# installed pyelftools.
Eli Bendersky8d12cae2013-04-06 07:05:35 -070016sys.path.insert(0, '.')
Eli Bendersky933f6992011-09-09 08:11:06 +030017
Eli Benderskydd71c432013-04-08 06:38:57 -070018
Eli Bendersky0b27ba42011-09-17 06:44:02 +030019from elftools import __version__
Eli Bendersky933f6992011-09-09 08:11:06 +030020from elftools.common.exceptions import ELFError
Eli Bendersky79271e92012-01-27 10:25:47 +020021from elftools.common.py3compat import (
22 ifilter, byte2int, bytes2str, itervalues, str2bytes)
Eli Bendersky933f6992011-09-09 08:11:06 +030023from elftools.elf.elffile import ELFFile
Mike Frysinger5699e182013-03-23 02:47:32 -040024from elftools.elf.dynamic import DynamicSection, DynamicSegment
25from elftools.elf.enums import ENUM_D_TAG
Eli Bendersky3f4de3e2011-09-14 05:58:06 +030026from elftools.elf.segments import InterpSegment
Yann Rouillard7b246702013-05-27 22:44:28 +020027from elftools.elf.sections import (
Yann Rouillardac9b3c82013-05-29 23:23:27 +020028 SymbolTableSection, GNUVerSymTableSection,
29 GNUVerDefTableSection, GNUVerNeedTableSection,
Yann Rouillard7b246702013-05-27 22:44:28 +020030 )
Eli Bendersky149315a2011-11-24 08:12:37 +020031from elftools.elf.relocation import RelocationSection
Eli Bendersky933f6992011-09-09 08:11:06 +030032from elftools.elf.descriptions import (
33 describe_ei_class, describe_ei_data, describe_ei_version,
Eli Benderskyde8d71e2011-09-09 08:22:35 +030034 describe_ei_osabi, describe_e_type, describe_e_machine,
Eli Bendersky26de2ac2011-09-13 06:50:28 +030035 describe_e_version_numeric, describe_p_type, describe_p_flags,
Eli Bendersky377bd862011-09-16 11:10:44 +030036 describe_sh_type, describe_sh_flags,
Eli Bendersky3edefab2011-09-16 14:52:54 +030037 describe_symbol_type, describe_symbol_bind, describe_symbol_visibility,
Mike Frysinger5699e182013-03-23 02:47:32 -040038 describe_symbol_shndx, describe_reloc_type, describe_dyn_tag,
Yann Rouillard7b246702013-05-27 22:44:28 +020039 describe_ver_flags,
Eli Bendersky933f6992011-09-09 08:11:06 +030040 )
Eli Bendersky149315a2011-11-24 08:12:37 +020041from elftools.dwarf.dwarfinfo import DWARFInfo
Eli Bendersky3501f9f2011-12-09 12:29:06 +020042from elftools.dwarf.descriptions import (
Eli Bendersky4682c962011-12-16 06:39:49 +020043 describe_reg_name, describe_attr_value, set_global_machine_arch,
44 describe_CFI_instructions, describe_CFI_register_rule,
45 describe_CFI_CFA_rule,
46 )
Eli Benderskybf83b1b2011-12-06 06:48:10 +020047from elftools.dwarf.constants import (
48 DW_LNS_copy, DW_LNS_set_file, DW_LNE_define_file)
Eli Bendersky7241ff02011-12-12 06:40:34 +020049from elftools.dwarf.callframe import CIE, FDE
Eli Bendersky933f6992011-09-09 08:11:06 +030050
51
52class ReadElf(object):
53 """ display_* methods are used to emit output into the output stream
54 """
55 def __init__(self, file, output):
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080056 """ file:
Eli Bendersky933f6992011-09-09 08:11:06 +030057 stream object with the ELF file to read
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080058
Eli Bendersky933f6992011-09-09 08:11:06 +030059 output:
60 output stream to write to
61 """
62 self.elffile = ELFFile(file)
63 self.output = output
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080064
eliben0fc47af2011-10-02 13:47:12 +020065 # Lazily initialized if a debug dump is requested
66 self._dwarfinfo = None
Eli Bendersky933f6992011-09-09 08:11:06 +030067
Yann Rouillard7b246702013-05-27 22:44:28 +020068 self._versioninfo = None
69
Eli Bendersky933f6992011-09-09 08:11:06 +030070 def display_file_header(self):
71 """ Display the ELF file header
72 """
73 self._emitline('ELF Header:')
74 self._emit(' Magic: ')
Eli Bendersky79271e92012-01-27 10:25:47 +020075 self._emitline(' '.join('%2.2x' % byte2int(b)
Eli Bendersky933f6992011-09-09 08:11:06 +030076 for b in self.elffile.e_ident_raw))
77 header = self.elffile.header
78 e_ident = header['e_ident']
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080079 self._emitline(' Class: %s' %
Eli Bendersky933f6992011-09-09 08:11:06 +030080 describe_ei_class(e_ident['EI_CLASS']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080081 self._emitline(' Data: %s' %
Eli Bendersky933f6992011-09-09 08:11:06 +030082 describe_ei_data(e_ident['EI_DATA']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080083 self._emitline(' Version: %s' %
Eli Bendersky933f6992011-09-09 08:11:06 +030084 describe_ei_version(e_ident['EI_VERSION']))
85 self._emitline(' OS/ABI: %s' %
86 describe_ei_osabi(e_ident['EI_OSABI']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080087 self._emitline(' ABI Version: %d' %
Eli Bendersky933f6992011-09-09 08:11:06 +030088 e_ident['EI_ABIVERSION'])
89 self._emitline(' Type: %s' %
90 describe_e_type(header['e_type']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080091 self._emitline(' Machine: %s' %
Eli Benderskyde8d71e2011-09-09 08:22:35 +030092 describe_e_machine(header['e_machine']))
93 self._emitline(' Version: %s' %
94 describe_e_version_numeric(header['e_version']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080095 self._emitline(' Entry point address: %s' %
Eli Bendersky26de2ac2011-09-13 06:50:28 +030096 self._format_hex(header['e_entry']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080097 self._emit(' Start of program headers: %s' %
Eli Benderskyd62928d2011-09-09 10:05:57 +030098 header['e_phoff'])
99 self._emitline(' (bytes into file)')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800100 self._emit(' Start of section headers: %s' %
Eli Benderskyd62928d2011-09-09 10:05:57 +0300101 header['e_shoff'])
102 self._emitline(' (bytes into file)')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800103 self._emitline(' Flags: %s' %
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300104 self._format_hex(header['e_flags']))
Eli Benderskyd62928d2011-09-09 10:05:57 +0300105 self._emitline(' Size of this header: %s (bytes)' %
106 header['e_ehsize'])
107 self._emitline(' Size of program headers: %s (bytes)' %
108 header['e_phentsize'])
109 self._emitline(' Number of program headers: %s' %
110 header['e_phnum'])
111 self._emitline(' Size of section headers: %s (bytes)' %
112 header['e_shentsize'])
113 self._emitline(' Number of section headers: %s' %
114 header['e_shnum'])
115 self._emitline(' Section header string table index: %s' %
116 header['e_shstrndx'])
Eli Bendersky933f6992011-09-09 08:11:06 +0300117
Eli Bendersky0b27ba42011-09-17 06:44:02 +0300118 def display_program_headers(self, show_heading=True):
119 """ Display the ELF program headers.
120 If show_heading is True, displays the heading for this information
121 (Elf file type is...)
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300122 """
123 self._emitline()
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +0300124 if self.elffile.num_segments() == 0:
125 self._emitline('There are no program headers in this file.')
126 return
127
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300128 elfheader = self.elffile.header
Eli Bendersky0b27ba42011-09-17 06:44:02 +0300129 if show_heading:
130 self._emitline('Elf file type is %s' %
131 describe_e_type(elfheader['e_type']))
132 self._emitline('Entry point is %s' %
133 self._format_hex(elfheader['e_entry']))
134 # readelf weirness - why isn't e_phoff printed as hex? (for section
135 # headers, it is...)
136 self._emitline('There are %s program headers, starting at offset %s' % (
137 elfheader['e_phnum'], elfheader['e_phoff']))
138 self._emitline()
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300139
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +0300140 self._emitline('Program Headers:')
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300141
142 # Now comes the table of program headers with their attributes. Note
143 # that due to different formatting constraints of 32-bit and 64-bit
144 # addresses, there are some conditions on elfclass here.
145 #
146 # First comes the table heading
147 #
148 if self.elffile.elfclass == 32:
149 self._emitline(' Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align')
150 else:
151 self._emitline(' Type Offset VirtAddr PhysAddr')
152 self._emitline(' FileSiz MemSiz Flags Align')
153
154 # Now the entries
155 #
156 for segment in self.elffile.iter_segments():
157 self._emit(' %-14s ' % describe_p_type(segment['p_type']))
158
159 if self.elffile.elfclass == 32:
160 self._emitline('%s %s %s %s %s %-3s %s' % (
161 self._format_hex(segment['p_offset'], fieldsize=6),
162 self._format_hex(segment['p_vaddr'], fullhex=True),
163 self._format_hex(segment['p_paddr'], fullhex=True),
164 self._format_hex(segment['p_filesz'], fieldsize=5),
165 self._format_hex(segment['p_memsz'], fieldsize=5),
166 describe_p_flags(segment['p_flags']),
167 self._format_hex(segment['p_align'])))
Eli Benderskya41c3c02011-09-14 06:18:28 +0300168 else: # 64
169 self._emitline('%s %s %s' % (
170 self._format_hex(segment['p_offset'], fullhex=True),
171 self._format_hex(segment['p_vaddr'], fullhex=True),
172 self._format_hex(segment['p_paddr'], fullhex=True)))
173 self._emitline(' %s %s %-3s %s' % (
174 self._format_hex(segment['p_filesz'], fullhex=True),
175 self._format_hex(segment['p_memsz'], fullhex=True),
176 describe_p_flags(segment['p_flags']),
177 # lead0x set to False for p_align, to mimic readelf.
178 # No idea why the difference from 32-bit mode :-|
179 self._format_hex(segment['p_align'], lead0x=False)))
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300180
Eli Bendersky3f4de3e2011-09-14 05:58:06 +0300181 if isinstance(segment, InterpSegment):
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800182 self._emitline(' [Requesting program interpreter: %s]' %
Eli Bendersky79271e92012-01-27 10:25:47 +0200183 bytes2str(segment.get_interp_name()))
Eli Bendersky3f4de3e2011-09-14 05:58:06 +0300184
Eli Bendersky58585b02011-09-15 07:07:54 +0300185 # Sections to segments mapping
186 #
187 if self.elffile.num_sections() == 0:
188 # No sections? We're done
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800189 return
Eli Bendersky58585b02011-09-15 07:07:54 +0300190
191 self._emitline('\n Section to Segment mapping:')
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +0300192 self._emitline(' Segment Sections...')
Eli Bendersky58585b02011-09-15 07:07:54 +0300193
194 for nseg, segment in enumerate(self.elffile.iter_segments()):
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +0300195 self._emit(' %2.2d ' % nseg)
Eli Bendersky58585b02011-09-15 07:07:54 +0300196
197 for section in self.elffile.iter_sections():
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800198 if ( not section.is_null() and
Eli Bendersky58585b02011-09-15 07:07:54 +0300199 segment.section_in_segment(section)):
Eli Bendersky79271e92012-01-27 10:25:47 +0200200 self._emit('%s ' % bytes2str(section.name))
Eli Bendersky58585b02011-09-15 07:07:54 +0300201
202 self._emitline('')
203
Eli Bendersky0b27ba42011-09-17 06:44:02 +0300204 def display_section_headers(self, show_heading=True):
Eli Bendersky377bd862011-09-16 11:10:44 +0300205 """ Display the ELF section headers
206 """
207 elfheader = self.elffile.header
Eli Bendersky0b27ba42011-09-17 06:44:02 +0300208 if show_heading:
209 self._emitline('There are %s section headers, starting at offset %s' % (
210 elfheader['e_shnum'], self._format_hex(elfheader['e_shoff'])))
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300211
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +0300212 self._emitline('\nSection Header%s:' % (
Eli Bendersky377bd862011-09-16 11:10:44 +0300213 's' if elfheader['e_shnum'] > 1 else ''))
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300214
Eli Bendersky377bd862011-09-16 11:10:44 +0300215 # Different formatting constraints of 32-bit and 64-bit addresses
216 #
217 if self.elffile.elfclass == 32:
218 self._emitline(' [Nr] Name Type Addr Off Size ES Flg Lk Inf Al')
219 else:
220 self._emitline(' [Nr] Name Type Address Offset')
221 self._emitline(' Size EntSize Flags Link Info Align')
222
223 # Now the entries
224 #
225 for nsec, section in enumerate(self.elffile.iter_sections()):
226 self._emit(' [%2u] %-17.17s %-15.15s ' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200227 nsec, bytes2str(section.name), describe_sh_type(section['sh_type'])))
Eli Bendersky377bd862011-09-16 11:10:44 +0300228
229 if self.elffile.elfclass == 32:
230 self._emitline('%s %s %s %s %3s %2s %3s %2s' % (
231 self._format_hex(section['sh_addr'], fieldsize=8, lead0x=False),
232 self._format_hex(section['sh_offset'], fieldsize=6, lead0x=False),
233 self._format_hex(section['sh_size'], fieldsize=6, lead0x=False),
234 self._format_hex(section['sh_entsize'], fieldsize=2, lead0x=False),
235 describe_sh_flags(section['sh_flags']),
236 section['sh_link'], section['sh_info'],
237 section['sh_addralign']))
238 else: # 64
239 self._emitline(' %s %s' % (
240 self._format_hex(section['sh_addr'], fullhex=True, lead0x=False),
241 self._format_hex(section['sh_offset'],
242 fieldsize=16 if section['sh_offset'] > 0xffffffff else 8,
243 lead0x=False)))
244 self._emitline(' %s %s %3s %2s %3s %s' % (
245 self._format_hex(section['sh_size'], fullhex=True, lead0x=False),
246 self._format_hex(section['sh_entsize'], fullhex=True, lead0x=False),
247 describe_sh_flags(section['sh_flags']),
248 section['sh_link'], section['sh_info'],
249 section['sh_addralign']))
250
251 self._emitline('Key to Flags:')
Eli Bendersky93e630d2011-11-16 07:22:57 +0200252 self._emit(' W (write), A (alloc), X (execute), M (merge), S (strings)')
253 if self.elffile['e_machine'] in ('EM_X86_64', 'EM_L10M'):
254 self._emitline(', l (large)')
255 else:
256 self._emitline()
257 self._emitline(' I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)')
Eli Bendersky377bd862011-09-16 11:10:44 +0300258 self._emitline(' O (extra OS processing required) o (OS specific), p (processor specific)')
259
Eli Bendersky3edefab2011-09-16 14:52:54 +0300260 def display_symbol_tables(self):
261 """ Display the symbol tables contained in the file
262 """
Yann Rouillard7b246702013-05-27 22:44:28 +0200263 self._init_versioninfo()
264
Eli Bendersky3edefab2011-09-16 14:52:54 +0300265 for section in self.elffile.iter_sections():
266 if not isinstance(section, SymbolTableSection):
267 continue
268
269 if section['sh_entsize'] == 0:
270 self._emitline("\nSymbol table '%s' has a sh_entsize of zero!" % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200271 bytes2str(section.name)))
Eli Bendersky3edefab2011-09-16 14:52:54 +0300272 continue
273
274 self._emitline("\nSymbol table '%s' contains %s entries:" % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200275 bytes2str(section.name), section.num_symbols()))
Eli Bendersky3edefab2011-09-16 14:52:54 +0300276
277 if self.elffile.elfclass == 32:
278 self._emitline(' Num: Value Size Type Bind Vis Ndx Name')
279 else: # 64
280 self._emitline(' Num: Value Size Type Bind Vis Ndx Name')
281
282 for nsym, symbol in enumerate(section.iter_symbols()):
Yann Rouillard7b246702013-05-27 22:44:28 +0200283
284 version_info = ''
285 # readelf doesn't display version info for Solaris versioning
286 if (section['sh_type'] == 'SHT_DYNSYM' and
287 self._versioninfo['type'] == 'GNU'):
288 version = self._symbol_version(nsym)
Yann Rouillardde179382013-05-29 23:47:50 +0200289 if (version['name'] != bytes2str(symbol.name) and
Yann Rouillard7b246702013-05-27 22:44:28 +0200290 version['index'] not in ('VER_NDX_LOCAL',
291 'VER_NDX_GLOBAL')):
292 if version['filename']:
293 # external symbol
294 version_info = '@%(name)s (%(index)i)' % version
295 else:
296 # internal symbol
297 if version['hidden']:
298 version_info = '@%(name)s' % version
299 else:
300 version_info = '@@%(name)s' % version
301
Eli Benderskyb6fa3652011-09-16 15:20:20 +0300302 # symbol names are truncated to 25 chars, similarly to readelf
Yann Rouillard7b246702013-05-27 22:44:28 +0200303 self._emitline('%6d: %s %5d %-7s %-6s %-7s %4s %.25s%s' % (
Eli Bendersky3edefab2011-09-16 14:52:54 +0300304 nsym,
Yann Rouillardde179382013-05-29 23:47:50 +0200305 self._format_hex(
306 symbol['st_value'], fullhex=True, lead0x=False),
Eli Bendersky3edefab2011-09-16 14:52:54 +0300307 symbol['st_size'],
308 describe_symbol_type(symbol['st_info']['type']),
309 describe_symbol_bind(symbol['st_info']['bind']),
310 describe_symbol_visibility(symbol['st_other']['visibility']),
311 describe_symbol_shndx(symbol['st_shndx']),
Yann Rouillard7b246702013-05-27 22:44:28 +0200312 bytes2str(symbol.name),
313 version_info))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800314
Mike Frysinger5699e182013-03-23 02:47:32 -0400315 def display_dynamic_tags(self):
316 """ Display the dynamic tags contained in the file
317 """
Mike Frysinger5699e182013-03-23 02:47:32 -0400318 for section in self.elffile.iter_sections():
319 if not isinstance(section, DynamicSection):
320 continue
321
Mike Frysinger5699e182013-03-23 02:47:32 -0400322 self._emitline("\nDynamic section at offset %s contains %s entries:" % (
323 self._format_hex(section['sh_offset']),
324 section.num_tags()))
325 self._emitline(" Tag Type Name/Value")
326
Mike Frysinger5699e182013-03-23 02:47:32 -0400327 padding = 20 + (8 if self.elffile.elfclass == 32 else 0)
328 for tag in section.iter_tags():
329 if tag.entry.d_tag == 'DT_NEEDED':
Eli Benderskyccdb5542013-03-31 14:19:21 -0700330 parsed = 'Shared library: [%s]' % bytes2str(tag.needed)
Mike Frysinger5699e182013-03-23 02:47:32 -0400331 elif tag.entry.d_tag == 'DT_RPATH':
Eli Benderskyccdb5542013-03-31 14:19:21 -0700332 parsed = 'Library rpath: [%s]' % bytes2str(tag.rpath)
Mike Frysinger5699e182013-03-23 02:47:32 -0400333 elif tag.entry.d_tag == 'DT_RUNPATH':
Eli Benderskyccdb5542013-03-31 14:19:21 -0700334 parsed = 'Library runpath: [%s]' % bytes2str(tag.runpath)
Eli Benderskyf8d2cf72013-03-31 06:56:56 -0700335 elif tag.entry.d_tag == 'DT_SONAME':
Eli Benderskyccdb5542013-03-31 14:19:21 -0700336 parsed = 'Library soname: [%s]' % bytes2str(tag.soname)
Mike Frysinger5699e182013-03-23 02:47:32 -0400337 elif (tag.entry.d_tag.endswith('SZ') or
338 tag.entry.d_tag.endswith('ENT')):
339 parsed = '%i (bytes)' % tag['d_val']
Eli Benderskybfb1bf52013-03-31 07:58:21 -0700340 elif (tag.entry.d_tag.endswith('NUM') or
341 tag.entry.d_tag.endswith('COUNT')):
Mike Frysinger5699e182013-03-23 02:47:32 -0400342 parsed = '%i' % tag['d_val']
343 elif tag.entry.d_tag == 'DT_PLTREL':
344 s = describe_dyn_tag(tag.entry.d_val)
345 if s.startswith('DT_'):
346 s = s[3:]
347 parsed = '%s' % s
348 else:
349 parsed = '%#x' % tag['d_val']
350
351 self._emitline(" %s %-*s %s" % (
352 self._format_hex(ENUM_D_TAG.get(tag.entry.d_tag, tag.entry.d_tag),
Eli Benderskyf8d2cf72013-03-31 06:56:56 -0700353 fullhex=True, lead0x=True),
Mike Frysinger5699e182013-03-23 02:47:32 -0400354 padding,
355 '(%s)' % (tag.entry.d_tag[3:],),
356 parsed))
357
Eli Bendersky84066b22011-09-20 06:48:52 +0300358 def display_relocations(self):
359 """ Display the relocations contained in the file
360 """
361 has_relocation_sections = False
362 for section in self.elffile.iter_sections():
363 if not isinstance(section, RelocationSection):
364 continue
365
366 has_relocation_sections = True
367 self._emitline("\nRelocation section '%s' at offset %s contains %s entries:" % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200368 bytes2str(section.name),
Eli Bendersky7c1ffa62011-09-22 06:37:07 +0300369 self._format_hex(section['sh_offset']),
370 section.num_relocations()))
Eli Bendersky89a824f2011-09-23 10:59:59 +0300371 if section.is_RELA():
372 self._emitline(" Offset Info Type Sym. Value Sym. Name + Addend")
373 else:
374 self._emitline(" Offset Info Type Sym.Value Sym. Name")
375
376 # The symbol table section pointed to in sh_link
377 symtable = self.elffile.get_section(section['sh_link'])
378
Eli Bendersky84066b22011-09-20 06:48:52 +0300379 for rel in section.iter_relocations():
Eli Bendersky89a824f2011-09-23 10:59:59 +0300380 hexwidth = 8 if self.elffile.elfclass == 32 else 12
Eli Bendersky099d48f2011-09-23 12:03:48 +0300381 self._emit('%s %s %-17.17s' % (
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800382 self._format_hex(rel['r_offset'],
Eli Bendersky89a824f2011-09-23 10:59:59 +0300383 fieldsize=hexwidth, lead0x=False),
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800384 self._format_hex(rel['r_info'],
Eli Bendersky89a824f2011-09-23 10:59:59 +0300385 fieldsize=hexwidth, lead0x=False),
386 describe_reloc_type(
Eli Bendersky067b3fd2011-11-18 12:02:57 +0200387 rel['r_info_type'], self.elffile)))
Eli Bendersky099d48f2011-09-23 12:03:48 +0300388
389 if rel['r_info_sym'] == 0:
390 self._emitline()
391 continue
392
393 symbol = symtable.get_symbol(rel['r_info_sym'])
Eli Benderskyadf707a2011-09-23 15:23:41 +0300394 # Some symbols have zero 'st_name', so instead what's used is
395 # the name of the section they point at
396 if symbol['st_name'] == 0:
397 symsec = self.elffile.get_section(symbol['st_shndx'])
398 symbol_name = symsec.name
399 else:
400 symbol_name = symbol.name
Eli Bendersky6434a962011-09-23 17:14:08 +0300401 self._emit(' %s %s%22.22s' % (
Eli Bendersky89a824f2011-09-23 10:59:59 +0300402 self._format_hex(
403 symbol['st_value'],
404 fullhex=True, lead0x=False),
405 ' ' if self.elffile.elfclass == 32 else '',
Eli Bendersky79271e92012-01-27 10:25:47 +0200406 bytes2str(symbol_name)))
Eli Bendersky89a824f2011-09-23 10:59:59 +0300407 if section.is_RELA():
408 self._emit(' %s %x' % (
409 '+' if rel['r_addend'] >= 0 else '-',
410 abs(rel['r_addend'])))
411 self._emitline()
Eli Bendersky84066b22011-09-20 06:48:52 +0300412
413 if not has_relocation_sections:
414 self._emitline('\nThere are no relocations in this file.')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800415
Yann Rouillard7b246702013-05-27 22:44:28 +0200416 def display_version_info(self):
417 """ Display the version info contained in the file
418 """
419 self._init_versioninfo()
420
421 if not self._versioninfo['type']:
422 self._emitline("\nNo version information found in this file.")
423 return
424
425 for section in self.elffile.iter_sections():
Yann Rouillardac9b3c82013-05-29 23:23:27 +0200426 if isinstance(section, GNUVerSymTableSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200427 self._print_version_section_header(
428 section, 'Version symbols', lead0x=False)
429
430 num_symbols = section.num_symbols()
431
432 # Symbol version info are printed four by four entries
433 for idx_by_4 in range(0, num_symbols, 4):
434
435 self._emit(' %03x:' % idx_by_4)
436
437 for idx in range(idx_by_4, min(idx_by_4 + 4, num_symbols)):
438
439 symbol_version = self._symbol_version(idx)
440 if symbol_version['index'] == 'VER_NDX_LOCAL':
441 version_index = 0
442 version_name = '(*local*)'
443 elif symbol_version['index'] == 'VER_NDX_GLOBAL':
444 version_index = 1
445 version_name = '(*global*)'
446 else:
447 version_index = symbol_version['index']
448 version_name = '(%(name)s)' % symbol_version
449
450 visibility = 'h' if symbol_version['hidden'] else ' '
451
452 self._emit('%4x%s%-13s' % (
453 version_index, visibility, version_name))
454
455 self._emitline()
456
Yann Rouillardac9b3c82013-05-29 23:23:27 +0200457 elif isinstance(section, GNUVerDefTableSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200458 self._print_version_section_header(
459 section, 'Version definition', indent=2)
460
461 offset = 0
462 for verdef, verdaux_iter in section.iter_versions():
463 verdaux = next(verdaux_iter)
464
465 name = verdaux.name
466 if verdef['vd_flags']:
467 flags = describe_ver_flags(verdef['vd_flags'])
468 # Mimic exactly the readelf output
469 flags += ' '
470 else:
471 flags = 'none'
472
473 self._emitline(' %s: Rev: %i Flags: %s Index: %i'
474 ' Cnt: %i Name: %s' % (
475 self._format_hex(offset, fieldsize=6,
476 alternate=True),
477 verdef['vd_version'], flags, verdef['vd_ndx'],
478 verdef['vd_cnt'], bytes2str(name)))
479
480 verdaux_offset = (
481 offset + verdef['vd_aux'] + verdaux['vda_next'])
482 for idx, verdaux in enumerate(verdaux_iter, start=1):
483 self._emitline(' %s: Parent %i: %s' %
484 (self._format_hex(verdaux_offset, fieldsize=4),
485 idx, bytes2str(verdaux.name)))
486 verdaux_offset += verdaux['vda_next']
487
488 offset += verdef['vd_next']
489
Yann Rouillardac9b3c82013-05-29 23:23:27 +0200490 elif isinstance(section, GNUVerNeedTableSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200491 self._print_version_section_header(section, 'Version needs')
492
493 offset = 0
494 for verneed, verneed_iter in section.iter_versions():
495
496 self._emitline(' %s: Version: %i File: %s Cnt: %i' % (
497 self._format_hex(offset, fieldsize=6,
498 alternate=True),
499 verneed['vn_version'], bytes2str(verneed.name),
500 verneed['vn_cnt']))
501
502 vernaux_offset = offset + verneed['vn_aux']
503 for idx, vernaux in enumerate(verneed_iter, start=1):
504 if vernaux['vna_flags']:
505 flags = describe_ver_flags(vernaux['vna_flags'])
506 # Mimic exactly the readelf output
507 flags += ' '
508 else:
509 flags = 'none'
510
511 self._emitline(
512 ' %s: Name: %s Flags: %s Version: %i' % (
513 self._format_hex(vernaux_offset, fieldsize=4),
514 bytes2str(vernaux.name), flags,
515 vernaux['vna_other']))
516
517 vernaux_offset += vernaux['vna_next']
518
519 offset += verneed['vn_next']
520
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300521 def display_hex_dump(self, section_spec):
522 """ Display a hex dump of a section. section_spec is either a section
523 number or a name.
524 """
eliben54e39b22011-09-19 13:10:57 +0300525 section = self._section_from_spec(section_spec)
526 if section is None:
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300527 self._emitline("Section '%s' does not exist in the file!" % (
528 section_spec))
529 return
530
Eli Bendersky79271e92012-01-27 10:25:47 +0200531 self._emitline("\nHex dump of section '%s':" % bytes2str(section.name))
Eli Benderskyadf707a2011-09-23 15:23:41 +0300532 self._note_relocs_for_section(section)
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300533 addr = section['sh_addr']
534 data = section.data()
535 dataptr = 0
536
537 while dataptr < len(data):
538 bytesleft = len(data) - dataptr
539 # chunks of 16 bytes per line
540 linebytes = 16 if bytesleft > 16 else bytesleft
541
542 self._emit(' %s ' % self._format_hex(addr, fieldsize=8))
543 for i in range(16):
544 if i < linebytes:
Eli Bendersky79271e92012-01-27 10:25:47 +0200545 self._emit('%2.2x' % byte2int(data[dataptr + i]))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300546 else:
547 self._emit(' ')
548 if i % 4 == 3:
549 self._emit(' ')
550
551 for i in range(linebytes):
Eli Bendersky79271e92012-01-27 10:25:47 +0200552 c = data[dataptr + i : dataptr + i + 1]
553 if byte2int(c[0]) >= 32 and byte2int(c[0]) < 0x7f:
554 self._emit(bytes2str(c))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300555 else:
Eli Bendersky79271e92012-01-27 10:25:47 +0200556 self._emit(bytes2str(b'.'))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300557
558 self._emitline()
559 addr += linebytes
560 dataptr += linebytes
561
562 self._emitline()
563
Eli Bendersky53e86db2011-09-18 06:04:30 +0300564 def display_string_dump(self, section_spec):
565 """ Display a strings dump of a section. section_spec is either a
566 section number or a name.
567 """
eliben54e39b22011-09-19 13:10:57 +0300568 section = self._section_from_spec(section_spec)
569 if section is None:
Eli Bendersky53e86db2011-09-18 06:04:30 +0300570 self._emitline("Section '%s' does not exist in the file!" % (
571 section_spec))
572 return
573
Eli Bendersky79271e92012-01-27 10:25:47 +0200574 self._emitline("\nString dump of section '%s':" % bytes2str(section.name))
Eli Bendersky53e86db2011-09-18 06:04:30 +0300575
576 found = False
577 data = section.data()
578 dataptr = 0
579
580 while dataptr < len(data):
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800581 while ( dataptr < len(data) and
Eli Bendersky79271e92012-01-27 10:25:47 +0200582 not (32 <= byte2int(data[dataptr]) <= 127)):
Eli Bendersky53e86db2011-09-18 06:04:30 +0300583 dataptr += 1
584
585 if dataptr >= len(data):
586 break
587
588 endptr = dataptr
Eli Bendersky79271e92012-01-27 10:25:47 +0200589 while endptr < len(data) and byte2int(data[endptr]) != 0:
Eli Bendersky53e86db2011-09-18 06:04:30 +0300590 endptr += 1
591
592 found = True
593 self._emitline(' [%6x] %s' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200594 dataptr, bytes2str(data[dataptr:endptr])))
Eli Bendersky53e86db2011-09-18 06:04:30 +0300595
596 dataptr = endptr
597
598 if not found:
599 self._emitline(' No strings found in this section.')
600 else:
601 self._emitline()
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300602
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200603 def display_debug_dump(self, dump_what):
eliben0fc47af2011-10-02 13:47:12 +0200604 """ Dump a DWARF section
605 """
606 self._init_dwarfinfo()
607 if self._dwarfinfo is None:
608 return
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800609
Eli Bendersky3501f9f2011-12-09 12:29:06 +0200610 set_global_machine_arch(self.elffile.get_machine_arch())
611
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200612 if dump_what == 'info':
eliben0fc47af2011-10-02 13:47:12 +0200613 self._dump_debug_info()
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200614 elif dump_what == 'decodedline':
615 self._dump_debug_line_programs()
Eli Bendersky7241ff02011-12-12 06:40:34 +0200616 elif dump_what == 'frames':
617 self._dump_debug_frames()
Eli Bendersky8670bb32011-12-15 16:11:06 +0200618 elif dump_what == 'frames-interp':
619 self._dump_debug_frames_interp()
eliben0fc47af2011-10-02 13:47:12 +0200620 else:
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200621 self._emitline('debug dump not yet supported for "%s"' % dump_what)
eliben0fc47af2011-10-02 13:47:12 +0200622
Yann Rouillard7b246702013-05-27 22:44:28 +0200623 def _format_hex(self, addr, fieldsize=None, fullhex=False, lead0x=True,
624 alternate=False):
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300625 """ Format an address into a hexadecimal string.
Eli Benderskyd62928d2011-09-09 10:05:57 +0300626
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300627 fieldsize:
628 Size of the hexadecimal field (with leading zeros to fit the
629 address into. For example with fieldsize=8, the format will
630 be %08x
631 If None, the minimal required field size will be used.
632
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300633 fullhex:
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800634 If True, override fieldsize to set it to the maximal size
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300635 needed for the elfclass
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300636
637 lead0x:
638 If True, leading 0x is added
Yann Rouillard7b246702013-05-27 22:44:28 +0200639
640 alternate:
641 If True, override lead0x to emulate the alternate
Yann Rouillardde179382013-05-29 23:47:50 +0200642 hexadecimal form specified in format string with the #
Yann Rouillard7b246702013-05-27 22:44:28 +0200643 character: only non-zero values are prefixed with 0x.
644 This form is used by readelf.
Eli Benderskyd62928d2011-09-09 10:05:57 +0300645 """
Yann Rouillard7b246702013-05-27 22:44:28 +0200646 if alternate:
647 if addr == 0:
648 lead0x = False
649 else:
650 lead0x = True
651 fieldsize -= 2
652
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300653 s = '0x' if lead0x else ''
654 if fullhex:
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300655 fieldsize = 8 if self.elffile.elfclass == 32 else 16
656 if fieldsize is None:
657 field = '%x'
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300658 else:
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300659 field = '%' + '0%sx' % fieldsize
660 return s + field % addr
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800661
Yann Rouillardde179382013-05-29 23:47:50 +0200662 def _print_version_section_header(self, version_section, name, lead0x=True,
663 indent=1):
664 """ Print a section header of one version related section (versym,
665 verneed or verdef) with some options to accomodate readelf
666 little differences between each header (e.g. indentation
667 and 0x prefixing).
Yann Rouillard7b246702013-05-27 22:44:28 +0200668 """
669 if hasattr(version_section, 'num_versions'):
670 num_entries = version_section.num_versions()
671 else:
672 num_entries = version_section.num_symbols()
673
674 self._emitline("\n%s section '%s' contains %s entries:" %
675 (name, bytes2str(version_section.name), num_entries))
Yann Rouillardde179382013-05-29 23:47:50 +0200676 self._emitline('%sAddr: %s Offset: %s Link: %i (%s)' % (
677 ' ' * indent,
678 self._format_hex(
679 version_section['sh_addr'], fieldsize=16, lead0x=lead0x),
680 self._format_hex(
681 version_section['sh_offset'], fieldsize=6, lead0x=True),
682 version_section['sh_link'],
683 bytes2str(
684 self.elffile.get_section(version_section['sh_link']).name)
685 )
686 )
Yann Rouillard7b246702013-05-27 22:44:28 +0200687
688 def _init_versioninfo(self):
689 """ Search and initialize informations about version related sections
690 and the kind of versioning used (GNU or Solaris).
691 """
692 if self._versioninfo is not None:
693 return
694
Yann Rouillardde179382013-05-29 23:47:50 +0200695 self._versioninfo = {'versym': None, 'verdef': None,
696 'verneed': None, 'type': None}
Yann Rouillard7b246702013-05-27 22:44:28 +0200697
698 for section in self.elffile.iter_sections():
Yann Rouillardac9b3c82013-05-29 23:23:27 +0200699 if isinstance(section, GNUVerSymTableSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200700 self._versioninfo['versym'] = section
Yann Rouillardac9b3c82013-05-29 23:23:27 +0200701 elif isinstance(section, GNUVerDefTableSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200702 self._versioninfo['verdef'] = section
Yann Rouillardac9b3c82013-05-29 23:23:27 +0200703 elif isinstance(section, GNUVerNeedTableSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200704 self._versioninfo['verneed'] = section
705 elif isinstance(section, DynamicSection):
706 for tag in section.iter_tags():
707 if tag['d_tag'] == 'DT_VERSYM':
708 self._versioninfo['type'] = 'GNU'
Yann Rouillardde179382013-05-29 23:47:50 +0200709 break
Yann Rouillard7b246702013-05-27 22:44:28 +0200710
711 if not self._versioninfo['type'] and (
712 self._versioninfo['verneed'] or self._versioninfo['verdef']):
713 self._versioninfo['type'] = 'Solaris'
714
Yann Rouillard7b246702013-05-27 22:44:28 +0200715 def _symbol_version(self, nsym):
Yann Rouillardde179382013-05-29 23:47:50 +0200716 """ Return a dict containing information on the
Yann Rouillard7b246702013-05-27 22:44:28 +0200717 or None if no version information is available
718 """
719 self._init_versioninfo()
Yann Rouillardde179382013-05-29 23:47:50 +0200720
Yann Rouillard7b246702013-05-27 22:44:28 +0200721 symbol_version = dict.fromkeys(('index', 'name', 'filename', 'hidden'))
722
723 if (not self._versioninfo['versym'] or
724 nsym >= self._versioninfo['versym'].num_symbols()):
725 return None
726
727 symbol = self._versioninfo['versym'].get_symbol(nsym)
728 index = symbol.entry['ndx']
729 if not index in ('VER_NDX_LOCAL', 'VER_NDX_GLOBAL'):
730 index = int(index)
731
732 if self._versioninfo['type'] == 'GNU':
Yann Rouillardde179382013-05-29 23:47:50 +0200733 # In GNU versioning mode, the highest bit is used to
Yann Rouillard7b246702013-05-27 22:44:28 +0200734 # store wether the symbol is hidden or not
735 if index & 0x8000:
Yann Rouillardde179382013-05-29 23:47:50 +0200736 index &= ~0x8000
Yann Rouillard7b246702013-05-27 22:44:28 +0200737 symbol_version['hidden'] = True
738
Yann Rouillardde179382013-05-29 23:47:50 +0200739 if (self._versioninfo['verdef'] and
Yann Rouillard7b246702013-05-27 22:44:28 +0200740 index <= self._versioninfo['verdef'].num_versions()):
741 _, verdaux_iter = \
742 self._versioninfo['verdef'].get_version(index)
743 symbol_version['name'] = bytes2str(next(verdaux_iter).name)
744 else:
745 verneed, vernaux = \
746 self._versioninfo['verneed'].get_version(index)
747 symbol_version['name'] = bytes2str(vernaux.name)
748 symbol_version['filename'] = bytes2str(verneed.name)
749
750 symbol_version['index'] = index
751 return symbol_version
752
eliben54e39b22011-09-19 13:10:57 +0300753 def _section_from_spec(self, spec):
754 """ Retrieve a section given a "spec" (either number or name).
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300755 Return None if no such section exists in the file.
756 """
757 try:
758 num = int(spec)
eliben54e39b22011-09-19 13:10:57 +0300759 if num < self.elffile.num_sections():
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800760 return self.elffile.get_section(num)
eliben54e39b22011-09-19 13:10:57 +0300761 else:
762 return None
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300763 except ValueError:
764 # Not a number. Must be a name then
Eli Bendersky79271e92012-01-27 10:25:47 +0200765 return self.elffile.get_section_by_name(str2bytes(spec))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300766
Eli Benderskyadf707a2011-09-23 15:23:41 +0300767 def _note_relocs_for_section(self, section):
768 """ If there are relocation sections pointing to the givne section,
769 emit a note about it.
770 """
771 for relsec in self.elffile.iter_sections():
772 if isinstance(relsec, RelocationSection):
773 info_idx = relsec['sh_info']
774 if self.elffile.get_section(info_idx) == section:
775 self._emitline(' Note: This section has relocations against it, but these have NOT been applied to this dump.')
776 return
777
eliben0fc47af2011-10-02 13:47:12 +0200778 def _init_dwarfinfo(self):
779 """ Initialize the DWARF info contained in the file and assign it to
780 self._dwarfinfo.
781 Leave self._dwarfinfo at None if no DWARF info was found in the file
782 """
783 if self._dwarfinfo is not None:
784 return
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800785
eliben0fc47af2011-10-02 13:47:12 +0200786 if self.elffile.has_dwarf_info():
787 self._dwarfinfo = self.elffile.get_dwarf_info()
788 else:
789 self._dwarfinfo = None
790
791 def _dump_debug_info(self):
792 """ Dump the debugging info section.
793 """
eliben985c2c12011-11-14 17:53:23 +0200794 self._emitline('Contents of the .debug_info section:\n')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800795
eliben0fc47af2011-10-02 13:47:12 +0200796 # Offset of the .debug_info section in the stream
Eli Bendersky149315a2011-11-24 08:12:37 +0200797 section_offset = self._dwarfinfo.debug_info_sec.global_offset
Eli Bendersky6062bf72011-11-23 06:54:40 +0200798
eliben0fc47af2011-10-02 13:47:12 +0200799 for cu in self._dwarfinfo.iter_CUs():
eliben985c2c12011-11-14 17:53:23 +0200800 self._emitline(' Compilation Unit @ offset %s:' %
Eli Bendersky149315a2011-11-24 08:12:37 +0200801 self._format_hex(cu.cu_offset))
eliben0fc47af2011-10-02 13:47:12 +0200802 self._emitline(' Length: %s (%s)' % (
803 self._format_hex(cu['unit_length']),
804 '%s-bit' % cu.dwarf_format()))
805 self._emitline(' Version: %s' % cu['version']),
Eli Bendersky7eba7182013-03-30 17:23:36 -0700806 self._emitline(' Abbrev Offset: %s' % (
807 self._format_hex(cu['debug_abbrev_offset']))),
eliben0fc47af2011-10-02 13:47:12 +0200808 self._emitline(' Pointer Size: %s' % cu['address_size'])
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800809
810 # The nesting depth of each DIE within the tree of DIEs must be
eliben0fc47af2011-10-02 13:47:12 +0200811 # displayed. To implement this, a counter is incremented each time
812 # the current DIE has children, and decremented when a null die is
813 # encountered. Due to the way the DIE tree is serialized, this will
814 # correctly reflect the nesting depth
815 #
816 die_depth = 0
817 for die in cu.iter_DIEs():
Eli Bendersky9aec9d82013-03-30 16:39:30 -0700818 self._emitline(' <%s><%x>: Abbrev Number: %s%s' % (
elibenaee11d22011-10-26 10:42:34 +0200819 die_depth,
Eli Bendersky149315a2011-11-24 08:12:37 +0200820 die.offset,
elibenaee11d22011-10-26 10:42:34 +0200821 die.abbrev_code,
Eli Bendersky9aec9d82013-03-30 16:39:30 -0700822 (' (%s)' % die.tag) if not die.is_null() else ''))
823 if die.is_null():
824 die_depth -= 1
825 continue
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800826
Eli Bendersky79271e92012-01-27 10:25:47 +0200827 for attr in itervalues(die.attributes):
Eli Bendersky871ad0c2011-12-16 08:13:48 +0200828 name = attr.name
829 # Unknown attribute values are passed-through as integers
830 if isinstance(name, int):
831 name = 'Unknown AT value: %x' % name
elibenaee11d22011-10-26 10:42:34 +0200832 self._emitline(' <%2x> %-18s: %s' % (
Eli Bendersky149315a2011-11-24 08:12:37 +0200833 attr.offset,
Eli Bendersky871ad0c2011-12-16 08:13:48 +0200834 name,
eliben3bc9c342011-10-26 13:10:58 +0200835 describe_attr_value(
Eli Bendersky5be3be82011-10-27 14:28:12 +0200836 attr, die, section_offset)))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800837
eliben0fc47af2011-10-02 13:47:12 +0200838 if die.has_children:
839 die_depth += 1
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800840
Eli Benderskyf5670e82011-11-24 09:05:44 +0200841 self._emitline()
eliben0fc47af2011-10-02 13:47:12 +0200842
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200843 def _dump_debug_line_programs(self):
844 """ Dump the (decoded) line programs from .debug_line
845 The programs are dumped in the order of the CUs they belong to.
846 """
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200847 self._emitline('Decoded dump of debug contents of section .debug_line:\n')
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200848
849 for cu in self._dwarfinfo.iter_CUs():
850 lineprogram = self._dwarfinfo.line_program_for_CU(cu)
851
Eli Bendersky7eba7182013-03-30 17:23:36 -0700852 cu_filename = bytes2str(lineprogram['file_entry'][0].name)
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200853 if len(lineprogram['include_directory']) > 0:
Eli Bendersky7eba7182013-03-30 17:23:36 -0700854 dir_index = lineprogram['file_entry'][0].dir_index
855 if dir_index > 0:
856 dir = lineprogram['include_directory'][dir_index - 1]
857 else:
Eli Benderskyccdb5542013-03-31 14:19:21 -0700858 dir = b'.'
Eli Bendersky7eba7182013-03-30 17:23:36 -0700859 cu_filename = '%s/%s' % (bytes2str(dir), cu_filename)
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200860
861 self._emitline('CU: %s:' % cu_filename)
862 self._emitline('File name Line number Starting address')
863
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200864 # Print each state's file, line and address information. For some
865 # instructions other output is needed to be compatible with
866 # readelf.
867 for entry in lineprogram.get_entries():
868 state = entry.state
869 if state is None:
870 # Special handling for commands that don't set a new state
871 if entry.command == DW_LNS_set_file:
872 file_entry = lineprogram['file_entry'][entry.args[0] - 1]
873 if file_entry.dir_index == 0:
874 # current directory
875 self._emitline('\n./%s:[++]' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200876 bytes2str(file_entry.name)))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200877 else:
878 self._emitline('\n%s/%s:' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200879 bytes2str(lineprogram['include_directory'][file_entry.dir_index - 1]),
880 bytes2str(file_entry.name)))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200881 elif entry.command == DW_LNE_define_file:
882 self._emitline('%s:' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200883 bytes2str(lineprogram['include_directory'][entry.args[0].dir_index])))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200884 elif not state.end_sequence:
885 # readelf doesn't print the state after end_sequence
886 # instructions. I think it's a bug but to be compatible
887 # I don't print them too.
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200888 self._emitline('%-35s %11d %18s' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200889 bytes2str(lineprogram['file_entry'][state.file - 1].name),
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200890 state.line,
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800891 '0' if state.address == 0 else
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200892 self._format_hex(state.address)))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200893 if entry.command == DW_LNS_copy:
894 # Another readelf oddity...
895 self._emitline()
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200896
Eli Bendersky7241ff02011-12-12 06:40:34 +0200897 def _dump_debug_frames(self):
898 """ Dump the raw frame information from .debug_frame
899 """
Eli Bendersky47a47112011-12-14 06:54:09 +0200900 if not self._dwarfinfo.has_CFI():
901 return
Eli Bendersky7241ff02011-12-12 06:40:34 +0200902 self._emitline('Contents of the .debug_frame section:')
903
904 for entry in self._dwarfinfo.CFI_entries():
905 if isinstance(entry, CIE):
906 self._emitline('\n%08x %08x %08x CIE' % (
907 entry.offset, entry['length'], entry['CIE_id']))
908 self._emitline(' Version: %d' % entry['version'])
Eli Bendersky79271e92012-01-27 10:25:47 +0200909 self._emitline(' Augmentation: "%s"' % bytes2str(entry['augmentation']))
Eli Bendersky7241ff02011-12-12 06:40:34 +0200910 self._emitline(' Code alignment factor: %u' % entry['code_alignment_factor'])
911 self._emitline(' Data alignment factor: %d' % entry['data_alignment_factor'])
912 self._emitline(' Return address column: %d' % entry['return_address_register'])
Eli Bendersky47a47112011-12-14 06:54:09 +0200913 self._emitline()
Eli Bendersky7241ff02011-12-12 06:40:34 +0200914 else: # FDE
915 self._emitline('\n%08x %08x %08x FDE cie=%08x pc=%08x..%08x' % (
916 entry.offset,
917 entry['length'],
918 entry['CIE_pointer'],
919 entry.cie.offset,
920 entry['initial_location'],
921 entry['initial_location'] + entry['address_range']))
922
Eli Bendersky47a47112011-12-14 06:54:09 +0200923 self._emit(describe_CFI_instructions(entry))
924 self._emitline()
Eli Bendersky7241ff02011-12-12 06:40:34 +0200925
Eli Bendersky8670bb32011-12-15 16:11:06 +0200926 def _dump_debug_frames_interp(self):
927 """ Dump the interpreted (decoded) frame information from .debug_frame
928 """
929 if not self._dwarfinfo.has_CFI():
930 return
931
932 self._emitline('Contents of the .debug_frame section:')
933
934 for entry in self._dwarfinfo.CFI_entries():
935 if isinstance(entry, CIE):
936 self._emitline('\n%08x %08x %08x CIE "%s" cf=%d df=%d ra=%d' % (
937 entry.offset,
938 entry['length'],
939 entry['CIE_id'],
Eli Bendersky79271e92012-01-27 10:25:47 +0200940 bytes2str(entry['augmentation']),
Eli Bendersky8670bb32011-12-15 16:11:06 +0200941 entry['code_alignment_factor'],
942 entry['data_alignment_factor'],
943 entry['return_address_register']))
Eli Bendersky4682c962011-12-16 06:39:49 +0200944 ra_regnum = entry['return_address_register']
Eli Bendersky8670bb32011-12-15 16:11:06 +0200945 else: # FDE
946 self._emitline('\n%08x %08x %08x FDE cie=%08x pc=%08x..%08x' % (
947 entry.offset,
948 entry['length'],
949 entry['CIE_pointer'],
950 entry.cie.offset,
951 entry['initial_location'],
952 entry['initial_location'] + entry['address_range']))
Eli Bendersky4682c962011-12-16 06:39:49 +0200953 ra_regnum = entry.cie['return_address_register']
Eli Bendersky8670bb32011-12-15 16:11:06 +0200954
955 # Print the heading row for the decoded table
956 self._emit(' LOC')
957 self._emit(' ' if entry.structs.address_size == 4 else ' ')
Eli Bendersky4682c962011-12-16 06:39:49 +0200958 self._emit(' CFA ')
Eli Bendersky8670bb32011-12-15 16:11:06 +0200959
Eli Bendersky4682c962011-12-16 06:39:49 +0200960 # Decode the table nad look at the registers it describes.
961 # We build reg_order here to match readelf's order. In particular,
962 # registers are sorted by their number, and the register matching
963 # ra_regnum is always listed last with a special heading.
Eli Bendersky8670bb32011-12-15 16:11:06 +0200964 decoded_table = entry.get_decoded()
Eli Bendersky4682c962011-12-16 06:39:49 +0200965 reg_order = sorted(ifilter(
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800966 lambda r: r != ra_regnum,
Eli Bendersky4682c962011-12-16 06:39:49 +0200967 decoded_table.reg_order))
968
969 # Headings for the registers
970 for regnum in reg_order:
Eli Bendersky8670bb32011-12-15 16:11:06 +0200971 self._emit('%-6s' % describe_reg_name(regnum))
972 self._emitline('ra ')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800973
Eli Bendersky4682c962011-12-16 06:39:49 +0200974 # Now include ra_regnum in reg_order to print its values similarly
975 # to the other registers.
976 reg_order.append(ra_regnum)
977 for line in decoded_table.table:
978 self._emit(self._format_hex(
979 line['pc'], fullhex=True, lead0x=False))
980 self._emit(' %-9s' % describe_CFI_CFA_rule(line['cfa']))
Eli Bendersky8670bb32011-12-15 16:11:06 +0200981
Eli Bendersky4682c962011-12-16 06:39:49 +0200982 for regnum in reg_order:
983 if regnum in line:
984 s = describe_CFI_register_rule(line[regnum])
985 else:
986 s = 'u'
987 self._emit('%-6s' % s)
988 self._emitline()
989 self._emitline()
Eli Bendersky8670bb32011-12-15 16:11:06 +0200990
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300991 def _emit(self, s=''):
Eli Bendersky933f6992011-09-09 08:11:06 +0300992 """ Emit an object to output
993 """
994 self.output.write(str(s))
Eli Benderskyd62928d2011-09-09 10:05:57 +0300995
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300996 def _emitline(self, s=''):
Eli Bendersky933f6992011-09-09 08:11:06 +0300997 """ Emit an object to output, followed by a newline
998 """
999 self.output.write(str(s) + '\n')
1000
1001
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001002SCRIPT_DESCRIPTION = 'Display information about the contents of ELF format files'
1003VERSION_STRING = '%%prog: based on pyelftools %s' % __version__
1004
1005
Eli Bendersky0193fb82011-11-26 16:16:16 +02001006def main(stream=None):
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001007 # parse the command-line arguments and invoke ReadElf
Eli Bendersky40eb1702011-09-16 16:59:52 +03001008 optparser = OptionParser(
Eli Benderskyecde41b2011-09-16 17:16:20 +03001009 usage='usage: %prog [options] <elf-file>',
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001010 description=SCRIPT_DESCRIPTION,
Eli Bendersky40eb1702011-09-16 16:59:52 +03001011 add_help_option=False, # -h is a real option of readelf
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001012 prog='readelf.py',
1013 version=VERSION_STRING)
Mike Frysinger5699e182013-03-23 02:47:32 -04001014 optparser.add_option('-d', '--dynamic',
1015 action='store_true', dest='show_dynamic_tags',
1016 help='Display the dynamic section')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001017 optparser.add_option('-H', '--help',
1018 action='store_true', dest='help',
1019 help='Display this information')
1020 optparser.add_option('-h', '--file-header',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001021 action='store_true', dest='show_file_header',
1022 help='Display the ELF file header')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001023 optparser.add_option('-l', '--program-headers', '--segments',
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001024 action='store_true', dest='show_program_header',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001025 help='Display the program headers')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001026 optparser.add_option('-S', '--section-headers', '--sections',
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001027 action='store_true', dest='show_section_header',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001028 help="Display the sections' headers")
Eli Bendersky40eb1702011-09-16 16:59:52 +03001029 optparser.add_option('-e', '--headers',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001030 action='store_true', dest='show_all_headers',
1031 help='Equivalent to: -h -l -S')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001032 optparser.add_option('-s', '--symbols', '--syms',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001033 action='store_true', dest='show_symbols',
1034 help='Display the symbol table')
Eli Bendersky84066b22011-09-20 06:48:52 +03001035 optparser.add_option('-r', '--relocs',
1036 action='store_true', dest='show_relocs',
1037 help='Display the relocations (if present)')
Eli Benderskyc4a4c072011-09-17 15:28:28 +03001038 optparser.add_option('-x', '--hex-dump',
1039 action='store', dest='show_hex_dump', metavar='<number|name>',
1040 help='Dump the contents of section <number|name> as bytes')
Eli Bendersky53e86db2011-09-18 06:04:30 +03001041 optparser.add_option('-p', '--string-dump',
1042 action='store', dest='show_string_dump', metavar='<number|name>',
1043 help='Dump the contents of section <number|name> as strings')
Yann Rouillard7b246702013-05-27 22:44:28 +02001044 optparser.add_option('-V', '--version-info',
1045 action='store_true', dest='show_version_info',
1046 help='Display the version sections (if present)')
eliben0fc47af2011-10-02 13:47:12 +02001047 optparser.add_option('--debug-dump',
Eli Bendersky1a516a32011-12-22 15:22:00 +02001048 action='store', dest='debug_dump_what', metavar='<what>',
1049 help=(
1050 'Display the contents of DWARF debug sections. <what> can ' +
1051 'one of {info,decodedline,frames,frames-interp}'))
Eli Bendersky53e86db2011-09-18 06:04:30 +03001052
Eli Bendersky933f6992011-09-09 08:11:06 +03001053 options, args = optparser.parse_args()
1054
Eli Bendersky40eb1702011-09-16 16:59:52 +03001055 if options.help or len(args) == 0:
1056 optparser.print_help()
1057 sys.exit(0)
1058
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001059 if options.show_all_headers:
1060 do_file_header = do_section_header = do_program_header = True
1061 else:
1062 do_file_header = options.show_file_header
1063 do_section_header = options.show_section_header
1064 do_program_header = options.show_program_header
1065
Eli Bendersky933f6992011-09-09 08:11:06 +03001066 with open(args[0], 'rb') as file:
1067 try:
Eli Bendersky0193fb82011-11-26 16:16:16 +02001068 readelf = ReadElf(file, stream or sys.stdout)
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001069 if do_file_header:
1070 readelf.display_file_header()
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001071 if do_section_header:
1072 readelf.display_section_headers(
1073 show_heading=not do_file_header)
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +03001074 if do_program_header:
1075 readelf.display_program_headers(
1076 show_heading=not do_file_header)
Mike Frysinger5699e182013-03-23 02:47:32 -04001077 if options.show_dynamic_tags:
1078 readelf.display_dynamic_tags()
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001079 if options.show_symbols:
1080 readelf.display_symbol_tables()
Eli Bendersky84066b22011-09-20 06:48:52 +03001081 if options.show_relocs:
1082 readelf.display_relocations()
Yann Rouillard7b246702013-05-27 22:44:28 +02001083 if options.show_version_info:
1084 readelf.display_version_info()
Eli Benderskyc4a4c072011-09-17 15:28:28 +03001085 if options.show_hex_dump:
1086 readelf.display_hex_dump(options.show_hex_dump)
Eli Bendersky53e86db2011-09-18 06:04:30 +03001087 if options.show_string_dump:
1088 readelf.display_string_dump(options.show_string_dump)
Eli Bendersky5ec2dde2011-12-04 07:05:31 +02001089 if options.debug_dump_what:
1090 readelf.display_debug_dump(options.debug_dump_what)
Eli Bendersky933f6992011-09-09 08:11:06 +03001091 except ELFError as ex:
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001092 sys.stderr.write('ELF error: %s\n' % ex)
Eli Bendersky933f6992011-09-09 08:11:06 +03001093 sys.exit(1)
1094
1095
Eli Bendersky0193fb82011-11-26 16:16:16 +02001096def profile_main():
1097 # Run 'main' redirecting its output to readelfout.txt
1098 # Saves profiling information in readelf.profile
1099 PROFFILE = 'readelf.profile'
1100 import cProfile
1101 cProfile.run('main(open("readelfout.txt", "w"))', PROFFILE)
1102
1103 # Dig in some profiling stats
1104 import pstats
1105 p = pstats.Stats(PROFFILE)
1106 p.sort_stats('cumulative').print_stats(25)
1107
1108
Eli Bendersky933f6992011-09-09 08:11:06 +03001109#-------------------------------------------------------------------------------
1110if __name__ == '__main__':
Eli Bendersky4f4d80c2011-11-26 16:49:27 +02001111 main()
1112 #profile_main()
Eli Bendersky0193fb82011-11-26 16:16:16 +02001113
Eli Bendersky933f6992011-09-09 08:11:06 +03001114