blob: 3263cfe5c1e8ad60495faacdb6381718f9a077cc [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 Rouillard3a1ccaf2013-05-29 23:52:39 +020027from elftools.elf.sections import SymbolTableSection
28from elftools.elf.gnuversions import (
Yann Rouillard478a4592013-05-31 21:01:25 +020029 GNUVerSymSection, GNUVerDefSection,
30 GNUVerNeedSection,
Yann Rouillard7b246702013-05-27 22:44:28 +020031 )
Eli Bendersky149315a2011-11-24 08:12:37 +020032from elftools.elf.relocation import RelocationSection
Eli Bendersky933f6992011-09-09 08:11:06 +030033from elftools.elf.descriptions import (
34 describe_ei_class, describe_ei_data, describe_ei_version,
Eli Benderskyde8d71e2011-09-09 08:22:35 +030035 describe_ei_osabi, describe_e_type, describe_e_machine,
Eli Bendersky26de2ac2011-09-13 06:50:28 +030036 describe_e_version_numeric, describe_p_type, describe_p_flags,
Eli Bendersky377bd862011-09-16 11:10:44 +030037 describe_sh_type, describe_sh_flags,
Eli Bendersky3edefab2011-09-16 14:52:54 +030038 describe_symbol_type, describe_symbol_bind, describe_symbol_visibility,
Mike Frysinger5699e182013-03-23 02:47:32 -040039 describe_symbol_shndx, describe_reloc_type, describe_dyn_tag,
Yann Rouillard7b246702013-05-27 22:44:28 +020040 describe_ver_flags,
Eli Bendersky933f6992011-09-09 08:11:06 +030041 )
Eli Bendersky6fdebd92013-06-08 09:40:41 -070042from elftools.elf.constants import E_FLAGS
Eli Bendersky149315a2011-11-24 08:12:37 +020043from elftools.dwarf.dwarfinfo import DWARFInfo
Eli Bendersky3501f9f2011-12-09 12:29:06 +020044from elftools.dwarf.descriptions import (
Eli Bendersky4682c962011-12-16 06:39:49 +020045 describe_reg_name, describe_attr_value, set_global_machine_arch,
46 describe_CFI_instructions, describe_CFI_register_rule,
47 describe_CFI_CFA_rule,
48 )
Eli Benderskybf83b1b2011-12-06 06:48:10 +020049from elftools.dwarf.constants import (
50 DW_LNS_copy, DW_LNS_set_file, DW_LNE_define_file)
Eli Bendersky7241ff02011-12-12 06:40:34 +020051from elftools.dwarf.callframe import CIE, FDE
Eli Bendersky933f6992011-09-09 08:11:06 +030052
53
54class ReadElf(object):
55 """ display_* methods are used to emit output into the output stream
56 """
57 def __init__(self, file, output):
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080058 """ file:
Eli Bendersky933f6992011-09-09 08:11:06 +030059 stream object with the ELF file to read
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080060
Eli Bendersky933f6992011-09-09 08:11:06 +030061 output:
62 output stream to write to
63 """
64 self.elffile = ELFFile(file)
65 self.output = output
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080066
eliben0fc47af2011-10-02 13:47:12 +020067 # Lazily initialized if a debug dump is requested
68 self._dwarfinfo = None
Eli Bendersky933f6992011-09-09 08:11:06 +030069
Yann Rouillard7b246702013-05-27 22:44:28 +020070 self._versioninfo = None
71
Eli Bendersky933f6992011-09-09 08:11:06 +030072 def display_file_header(self):
73 """ Display the ELF file header
74 """
75 self._emitline('ELF Header:')
76 self._emit(' Magic: ')
Eli Bendersky79271e92012-01-27 10:25:47 +020077 self._emitline(' '.join('%2.2x' % byte2int(b)
Eli Bendersky933f6992011-09-09 08:11:06 +030078 for b in self.elffile.e_ident_raw))
79 header = self.elffile.header
80 e_ident = header['e_ident']
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080081 self._emitline(' Class: %s' %
Eli Bendersky933f6992011-09-09 08:11:06 +030082 describe_ei_class(e_ident['EI_CLASS']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080083 self._emitline(' Data: %s' %
Eli Bendersky933f6992011-09-09 08:11:06 +030084 describe_ei_data(e_ident['EI_DATA']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080085 self._emitline(' Version: %s' %
Eli Bendersky933f6992011-09-09 08:11:06 +030086 describe_ei_version(e_ident['EI_VERSION']))
87 self._emitline(' OS/ABI: %s' %
88 describe_ei_osabi(e_ident['EI_OSABI']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080089 self._emitline(' ABI Version: %d' %
Eli Bendersky933f6992011-09-09 08:11:06 +030090 e_ident['EI_ABIVERSION'])
91 self._emitline(' Type: %s' %
92 describe_e_type(header['e_type']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080093 self._emitline(' Machine: %s' %
Eli Benderskyde8d71e2011-09-09 08:22:35 +030094 describe_e_machine(header['e_machine']))
95 self._emitline(' Version: %s' %
96 describe_e_version_numeric(header['e_version']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080097 self._emitline(' Entry point address: %s' %
Eli Bendersky26de2ac2011-09-13 06:50:28 +030098 self._format_hex(header['e_entry']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080099 self._emit(' Start of program headers: %s' %
Eli Benderskyd62928d2011-09-09 10:05:57 +0300100 header['e_phoff'])
101 self._emitline(' (bytes into file)')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800102 self._emit(' Start of section headers: %s' %
Eli Benderskyd62928d2011-09-09 10:05:57 +0300103 header['e_shoff'])
104 self._emitline(' (bytes into file)')
Eli Bendersky6fdebd92013-06-08 09:40:41 -0700105 self._emitline(' Flags: %s%s' %
106 (self._format_hex(header['e_flags']),
107 self.decode_flags(header['e_flags'])))
Eli Benderskyd62928d2011-09-09 10:05:57 +0300108 self._emitline(' Size of this header: %s (bytes)' %
109 header['e_ehsize'])
110 self._emitline(' Size of program headers: %s (bytes)' %
111 header['e_phentsize'])
112 self._emitline(' Number of program headers: %s' %
113 header['e_phnum'])
114 self._emitline(' Size of section headers: %s (bytes)' %
115 header['e_shentsize'])
116 self._emitline(' Number of section headers: %s' %
117 header['e_shnum'])
118 self._emitline(' Section header string table index: %s' %
119 header['e_shstrndx'])
Eli Bendersky933f6992011-09-09 08:11:06 +0300120
Eli Bendersky6fdebd92013-06-08 09:40:41 -0700121 def decode_flags(self, flags):
122 description = ""
123 if self.elffile['e_machine'] == "EM_ARM":
124 if flags & E_FLAGS.EF_ARM_HASENTRY:
125 description += ", has entry point"
126
127 version = flags & E_FLAGS.EF_ARM_EABIMASK
128 if version == E_FLAGS.EF_ARM_EABI_VER5:
129 description += ", Version5 EABI"
130 return description
131
Eli Bendersky0b27ba42011-09-17 06:44:02 +0300132 def display_program_headers(self, show_heading=True):
133 """ Display the ELF program headers.
134 If show_heading is True, displays the heading for this information
135 (Elf file type is...)
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300136 """
137 self._emitline()
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +0300138 if self.elffile.num_segments() == 0:
139 self._emitline('There are no program headers in this file.')
140 return
141
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300142 elfheader = self.elffile.header
Eli Bendersky0b27ba42011-09-17 06:44:02 +0300143 if show_heading:
144 self._emitline('Elf file type is %s' %
145 describe_e_type(elfheader['e_type']))
146 self._emitline('Entry point is %s' %
147 self._format_hex(elfheader['e_entry']))
148 # readelf weirness - why isn't e_phoff printed as hex? (for section
149 # headers, it is...)
150 self._emitline('There are %s program headers, starting at offset %s' % (
151 elfheader['e_phnum'], elfheader['e_phoff']))
152 self._emitline()
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300153
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +0300154 self._emitline('Program Headers:')
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300155
156 # Now comes the table of program headers with their attributes. Note
157 # that due to different formatting constraints of 32-bit and 64-bit
158 # addresses, there are some conditions on elfclass here.
159 #
160 # First comes the table heading
161 #
162 if self.elffile.elfclass == 32:
163 self._emitline(' Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align')
164 else:
165 self._emitline(' Type Offset VirtAddr PhysAddr')
166 self._emitline(' FileSiz MemSiz Flags Align')
167
168 # Now the entries
169 #
170 for segment in self.elffile.iter_segments():
171 self._emit(' %-14s ' % describe_p_type(segment['p_type']))
172
173 if self.elffile.elfclass == 32:
174 self._emitline('%s %s %s %s %s %-3s %s' % (
175 self._format_hex(segment['p_offset'], fieldsize=6),
176 self._format_hex(segment['p_vaddr'], fullhex=True),
177 self._format_hex(segment['p_paddr'], fullhex=True),
178 self._format_hex(segment['p_filesz'], fieldsize=5),
179 self._format_hex(segment['p_memsz'], fieldsize=5),
180 describe_p_flags(segment['p_flags']),
181 self._format_hex(segment['p_align'])))
Eli Benderskya41c3c02011-09-14 06:18:28 +0300182 else: # 64
183 self._emitline('%s %s %s' % (
184 self._format_hex(segment['p_offset'], fullhex=True),
185 self._format_hex(segment['p_vaddr'], fullhex=True),
186 self._format_hex(segment['p_paddr'], fullhex=True)))
187 self._emitline(' %s %s %-3s %s' % (
188 self._format_hex(segment['p_filesz'], fullhex=True),
189 self._format_hex(segment['p_memsz'], fullhex=True),
190 describe_p_flags(segment['p_flags']),
191 # lead0x set to False for p_align, to mimic readelf.
192 # No idea why the difference from 32-bit mode :-|
193 self._format_hex(segment['p_align'], lead0x=False)))
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300194
Eli Bendersky3f4de3e2011-09-14 05:58:06 +0300195 if isinstance(segment, InterpSegment):
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800196 self._emitline(' [Requesting program interpreter: %s]' %
Eli Bendersky79271e92012-01-27 10:25:47 +0200197 bytes2str(segment.get_interp_name()))
Eli Bendersky3f4de3e2011-09-14 05:58:06 +0300198
Eli Bendersky58585b02011-09-15 07:07:54 +0300199 # Sections to segments mapping
200 #
201 if self.elffile.num_sections() == 0:
202 # No sections? We're done
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800203 return
Eli Bendersky58585b02011-09-15 07:07:54 +0300204
205 self._emitline('\n Section to Segment mapping:')
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +0300206 self._emitline(' Segment Sections...')
Eli Bendersky58585b02011-09-15 07:07:54 +0300207
208 for nseg, segment in enumerate(self.elffile.iter_segments()):
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +0300209 self._emit(' %2.2d ' % nseg)
Eli Bendersky58585b02011-09-15 07:07:54 +0300210
211 for section in self.elffile.iter_sections():
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800212 if ( not section.is_null() and
Eli Bendersky58585b02011-09-15 07:07:54 +0300213 segment.section_in_segment(section)):
Eli Bendersky79271e92012-01-27 10:25:47 +0200214 self._emit('%s ' % bytes2str(section.name))
Eli Bendersky58585b02011-09-15 07:07:54 +0300215
216 self._emitline('')
217
Eli Bendersky0b27ba42011-09-17 06:44:02 +0300218 def display_section_headers(self, show_heading=True):
Eli Bendersky377bd862011-09-16 11:10:44 +0300219 """ Display the ELF section headers
220 """
221 elfheader = self.elffile.header
Eli Bendersky0b27ba42011-09-17 06:44:02 +0300222 if show_heading:
223 self._emitline('There are %s section headers, starting at offset %s' % (
224 elfheader['e_shnum'], self._format_hex(elfheader['e_shoff'])))
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300225
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +0300226 self._emitline('\nSection Header%s:' % (
Eli Bendersky377bd862011-09-16 11:10:44 +0300227 's' if elfheader['e_shnum'] > 1 else ''))
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300228
Eli Bendersky377bd862011-09-16 11:10:44 +0300229 # Different formatting constraints of 32-bit and 64-bit addresses
230 #
231 if self.elffile.elfclass == 32:
232 self._emitline(' [Nr] Name Type Addr Off Size ES Flg Lk Inf Al')
233 else:
234 self._emitline(' [Nr] Name Type Address Offset')
235 self._emitline(' Size EntSize Flags Link Info Align')
236
237 # Now the entries
238 #
239 for nsec, section in enumerate(self.elffile.iter_sections()):
240 self._emit(' [%2u] %-17.17s %-15.15s ' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200241 nsec, bytes2str(section.name), describe_sh_type(section['sh_type'])))
Eli Bendersky377bd862011-09-16 11:10:44 +0300242
243 if self.elffile.elfclass == 32:
244 self._emitline('%s %s %s %s %3s %2s %3s %2s' % (
245 self._format_hex(section['sh_addr'], fieldsize=8, lead0x=False),
246 self._format_hex(section['sh_offset'], fieldsize=6, lead0x=False),
247 self._format_hex(section['sh_size'], fieldsize=6, lead0x=False),
248 self._format_hex(section['sh_entsize'], fieldsize=2, lead0x=False),
249 describe_sh_flags(section['sh_flags']),
250 section['sh_link'], section['sh_info'],
251 section['sh_addralign']))
252 else: # 64
253 self._emitline(' %s %s' % (
254 self._format_hex(section['sh_addr'], fullhex=True, lead0x=False),
255 self._format_hex(section['sh_offset'],
256 fieldsize=16 if section['sh_offset'] > 0xffffffff else 8,
257 lead0x=False)))
258 self._emitline(' %s %s %3s %2s %3s %s' % (
259 self._format_hex(section['sh_size'], fullhex=True, lead0x=False),
260 self._format_hex(section['sh_entsize'], fullhex=True, lead0x=False),
261 describe_sh_flags(section['sh_flags']),
262 section['sh_link'], section['sh_info'],
263 section['sh_addralign']))
264
265 self._emitline('Key to Flags:')
Eli Bendersky93e630d2011-11-16 07:22:57 +0200266 self._emit(' W (write), A (alloc), X (execute), M (merge), S (strings)')
267 if self.elffile['e_machine'] in ('EM_X86_64', 'EM_L10M'):
268 self._emitline(', l (large)')
269 else:
270 self._emitline()
271 self._emitline(' I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)')
Eli Bendersky377bd862011-09-16 11:10:44 +0300272 self._emitline(' O (extra OS processing required) o (OS specific), p (processor specific)')
273
Eli Bendersky3edefab2011-09-16 14:52:54 +0300274 def display_symbol_tables(self):
275 """ Display the symbol tables contained in the file
276 """
Yann Rouillard7b246702013-05-27 22:44:28 +0200277 self._init_versioninfo()
278
Eli Bendersky3edefab2011-09-16 14:52:54 +0300279 for section in self.elffile.iter_sections():
280 if not isinstance(section, SymbolTableSection):
281 continue
282
283 if section['sh_entsize'] == 0:
284 self._emitline("\nSymbol table '%s' has a sh_entsize of zero!" % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200285 bytes2str(section.name)))
Eli Bendersky3edefab2011-09-16 14:52:54 +0300286 continue
287
288 self._emitline("\nSymbol table '%s' contains %s entries:" % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200289 bytes2str(section.name), section.num_symbols()))
Eli Bendersky3edefab2011-09-16 14:52:54 +0300290
291 if self.elffile.elfclass == 32:
292 self._emitline(' Num: Value Size Type Bind Vis Ndx Name')
293 else: # 64
294 self._emitline(' Num: Value Size Type Bind Vis Ndx Name')
295
296 for nsym, symbol in enumerate(section.iter_symbols()):
Yann Rouillard7b246702013-05-27 22:44:28 +0200297
298 version_info = ''
299 # readelf doesn't display version info for Solaris versioning
300 if (section['sh_type'] == 'SHT_DYNSYM' and
301 self._versioninfo['type'] == 'GNU'):
302 version = self._symbol_version(nsym)
Yann Rouillardde179382013-05-29 23:47:50 +0200303 if (version['name'] != bytes2str(symbol.name) and
Yann Rouillard7b246702013-05-27 22:44:28 +0200304 version['index'] not in ('VER_NDX_LOCAL',
305 'VER_NDX_GLOBAL')):
306 if version['filename']:
307 # external symbol
308 version_info = '@%(name)s (%(index)i)' % version
309 else:
310 # internal symbol
311 if version['hidden']:
312 version_info = '@%(name)s' % version
313 else:
314 version_info = '@@%(name)s' % version
315
Eli Benderskyb6fa3652011-09-16 15:20:20 +0300316 # symbol names are truncated to 25 chars, similarly to readelf
Yann Rouillard7b246702013-05-27 22:44:28 +0200317 self._emitline('%6d: %s %5d %-7s %-6s %-7s %4s %.25s%s' % (
Eli Bendersky3edefab2011-09-16 14:52:54 +0300318 nsym,
Yann Rouillardde179382013-05-29 23:47:50 +0200319 self._format_hex(
320 symbol['st_value'], fullhex=True, lead0x=False),
Eli Bendersky3edefab2011-09-16 14:52:54 +0300321 symbol['st_size'],
322 describe_symbol_type(symbol['st_info']['type']),
323 describe_symbol_bind(symbol['st_info']['bind']),
324 describe_symbol_visibility(symbol['st_other']['visibility']),
325 describe_symbol_shndx(symbol['st_shndx']),
Yann Rouillard7b246702013-05-27 22:44:28 +0200326 bytes2str(symbol.name),
327 version_info))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800328
Mike Frysinger5699e182013-03-23 02:47:32 -0400329 def display_dynamic_tags(self):
330 """ Display the dynamic tags contained in the file
331 """
Eli Bendersky6fdebd92013-06-08 09:40:41 -0700332 has_dynamic_sections = False
Mike Frysinger5699e182013-03-23 02:47:32 -0400333 for section in self.elffile.iter_sections():
334 if not isinstance(section, DynamicSection):
335 continue
336
Eli Bendersky6fdebd92013-06-08 09:40:41 -0700337 has_dynamic_sections = True
Mike Frysinger5699e182013-03-23 02:47:32 -0400338 self._emitline("\nDynamic section at offset %s contains %s entries:" % (
339 self._format_hex(section['sh_offset']),
340 section.num_tags()))
341 self._emitline(" Tag Type Name/Value")
342
Mike Frysinger5699e182013-03-23 02:47:32 -0400343 padding = 20 + (8 if self.elffile.elfclass == 32 else 0)
344 for tag in section.iter_tags():
345 if tag.entry.d_tag == 'DT_NEEDED':
Eli Benderskyccdb5542013-03-31 14:19:21 -0700346 parsed = 'Shared library: [%s]' % bytes2str(tag.needed)
Mike Frysinger5699e182013-03-23 02:47:32 -0400347 elif tag.entry.d_tag == 'DT_RPATH':
Eli Benderskyccdb5542013-03-31 14:19:21 -0700348 parsed = 'Library rpath: [%s]' % bytes2str(tag.rpath)
Mike Frysinger5699e182013-03-23 02:47:32 -0400349 elif tag.entry.d_tag == 'DT_RUNPATH':
Eli Benderskyccdb5542013-03-31 14:19:21 -0700350 parsed = 'Library runpath: [%s]' % bytes2str(tag.runpath)
Eli Benderskyf8d2cf72013-03-31 06:56:56 -0700351 elif tag.entry.d_tag == 'DT_SONAME':
Eli Benderskyccdb5542013-03-31 14:19:21 -0700352 parsed = 'Library soname: [%s]' % bytes2str(tag.soname)
Mike Frysinger5699e182013-03-23 02:47:32 -0400353 elif (tag.entry.d_tag.endswith('SZ') or
354 tag.entry.d_tag.endswith('ENT')):
355 parsed = '%i (bytes)' % tag['d_val']
Eli Benderskybfb1bf52013-03-31 07:58:21 -0700356 elif (tag.entry.d_tag.endswith('NUM') or
357 tag.entry.d_tag.endswith('COUNT')):
Mike Frysinger5699e182013-03-23 02:47:32 -0400358 parsed = '%i' % tag['d_val']
359 elif tag.entry.d_tag == 'DT_PLTREL':
360 s = describe_dyn_tag(tag.entry.d_val)
361 if s.startswith('DT_'):
362 s = s[3:]
363 parsed = '%s' % s
364 else:
365 parsed = '%#x' % tag['d_val']
366
367 self._emitline(" %s %-*s %s" % (
368 self._format_hex(ENUM_D_TAG.get(tag.entry.d_tag, tag.entry.d_tag),
Eli Benderskyf8d2cf72013-03-31 06:56:56 -0700369 fullhex=True, lead0x=True),
Mike Frysinger5699e182013-03-23 02:47:32 -0400370 padding,
371 '(%s)' % (tag.entry.d_tag[3:],),
372 parsed))
Eli Bendersky6fdebd92013-06-08 09:40:41 -0700373 if not has_dynamic_sections:
374 # readelf only prints this if there is at least one segment
375 if self.elffile.num_segments():
376 self._emitline("\nThere is no dynamic section in this file.")
Mike Frysinger5699e182013-03-23 02:47:32 -0400377
Eli Bendersky84066b22011-09-20 06:48:52 +0300378 def display_relocations(self):
379 """ Display the relocations contained in the file
380 """
381 has_relocation_sections = False
382 for section in self.elffile.iter_sections():
383 if not isinstance(section, RelocationSection):
384 continue
385
386 has_relocation_sections = True
387 self._emitline("\nRelocation section '%s' at offset %s contains %s entries:" % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200388 bytes2str(section.name),
Eli Bendersky7c1ffa62011-09-22 06:37:07 +0300389 self._format_hex(section['sh_offset']),
390 section.num_relocations()))
Eli Bendersky89a824f2011-09-23 10:59:59 +0300391 if section.is_RELA():
392 self._emitline(" Offset Info Type Sym. Value Sym. Name + Addend")
393 else:
394 self._emitline(" Offset Info Type Sym.Value Sym. Name")
395
396 # The symbol table section pointed to in sh_link
397 symtable = self.elffile.get_section(section['sh_link'])
398
Eli Bendersky84066b22011-09-20 06:48:52 +0300399 for rel in section.iter_relocations():
Eli Bendersky89a824f2011-09-23 10:59:59 +0300400 hexwidth = 8 if self.elffile.elfclass == 32 else 12
Eli Bendersky099d48f2011-09-23 12:03:48 +0300401 self._emit('%s %s %-17.17s' % (
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800402 self._format_hex(rel['r_offset'],
Eli Bendersky89a824f2011-09-23 10:59:59 +0300403 fieldsize=hexwidth, lead0x=False),
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800404 self._format_hex(rel['r_info'],
Eli Bendersky89a824f2011-09-23 10:59:59 +0300405 fieldsize=hexwidth, lead0x=False),
406 describe_reloc_type(
Eli Bendersky067b3fd2011-11-18 12:02:57 +0200407 rel['r_info_type'], self.elffile)))
Eli Bendersky099d48f2011-09-23 12:03:48 +0300408
409 if rel['r_info_sym'] == 0:
410 self._emitline()
411 continue
412
413 symbol = symtable.get_symbol(rel['r_info_sym'])
Eli Benderskyadf707a2011-09-23 15:23:41 +0300414 # Some symbols have zero 'st_name', so instead what's used is
415 # the name of the section they point at
416 if symbol['st_name'] == 0:
417 symsec = self.elffile.get_section(symbol['st_shndx'])
418 symbol_name = symsec.name
419 else:
420 symbol_name = symbol.name
Eli Bendersky6434a962011-09-23 17:14:08 +0300421 self._emit(' %s %s%22.22s' % (
Eli Bendersky89a824f2011-09-23 10:59:59 +0300422 self._format_hex(
423 symbol['st_value'],
424 fullhex=True, lead0x=False),
425 ' ' if self.elffile.elfclass == 32 else '',
Eli Bendersky79271e92012-01-27 10:25:47 +0200426 bytes2str(symbol_name)))
Eli Bendersky89a824f2011-09-23 10:59:59 +0300427 if section.is_RELA():
428 self._emit(' %s %x' % (
429 '+' if rel['r_addend'] >= 0 else '-',
430 abs(rel['r_addend'])))
431 self._emitline()
Eli Bendersky84066b22011-09-20 06:48:52 +0300432
433 if not has_relocation_sections:
434 self._emitline('\nThere are no relocations in this file.')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800435
Yann Rouillard7b246702013-05-27 22:44:28 +0200436 def display_version_info(self):
437 """ Display the version info contained in the file
438 """
439 self._init_versioninfo()
440
441 if not self._versioninfo['type']:
442 self._emitline("\nNo version information found in this file.")
443 return
444
445 for section in self.elffile.iter_sections():
Yann Rouillard478a4592013-05-31 21:01:25 +0200446 if isinstance(section, GNUVerSymSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200447 self._print_version_section_header(
448 section, 'Version symbols', lead0x=False)
449
450 num_symbols = section.num_symbols()
451
452 # Symbol version info are printed four by four entries
453 for idx_by_4 in range(0, num_symbols, 4):
454
455 self._emit(' %03x:' % idx_by_4)
456
457 for idx in range(idx_by_4, min(idx_by_4 + 4, num_symbols)):
458
459 symbol_version = self._symbol_version(idx)
460 if symbol_version['index'] == 'VER_NDX_LOCAL':
461 version_index = 0
462 version_name = '(*local*)'
463 elif symbol_version['index'] == 'VER_NDX_GLOBAL':
464 version_index = 1
465 version_name = '(*global*)'
466 else:
467 version_index = symbol_version['index']
468 version_name = '(%(name)s)' % symbol_version
469
470 visibility = 'h' if symbol_version['hidden'] else ' '
471
472 self._emit('%4x%s%-13s' % (
473 version_index, visibility, version_name))
474
475 self._emitline()
476
Yann Rouillard478a4592013-05-31 21:01:25 +0200477 elif isinstance(section, GNUVerDefSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200478 self._print_version_section_header(
479 section, 'Version definition', indent=2)
480
481 offset = 0
482 for verdef, verdaux_iter in section.iter_versions():
483 verdaux = next(verdaux_iter)
484
485 name = verdaux.name
486 if verdef['vd_flags']:
487 flags = describe_ver_flags(verdef['vd_flags'])
488 # Mimic exactly the readelf output
489 flags += ' '
490 else:
491 flags = 'none'
492
493 self._emitline(' %s: Rev: %i Flags: %s Index: %i'
494 ' Cnt: %i Name: %s' % (
495 self._format_hex(offset, fieldsize=6,
496 alternate=True),
497 verdef['vd_version'], flags, verdef['vd_ndx'],
498 verdef['vd_cnt'], bytes2str(name)))
499
500 verdaux_offset = (
501 offset + verdef['vd_aux'] + verdaux['vda_next'])
502 for idx, verdaux in enumerate(verdaux_iter, start=1):
503 self._emitline(' %s: Parent %i: %s' %
504 (self._format_hex(verdaux_offset, fieldsize=4),
505 idx, bytes2str(verdaux.name)))
506 verdaux_offset += verdaux['vda_next']
507
508 offset += verdef['vd_next']
509
Yann Rouillard478a4592013-05-31 21:01:25 +0200510 elif isinstance(section, GNUVerNeedSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200511 self._print_version_section_header(section, 'Version needs')
512
513 offset = 0
514 for verneed, verneed_iter in section.iter_versions():
515
516 self._emitline(' %s: Version: %i File: %s Cnt: %i' % (
517 self._format_hex(offset, fieldsize=6,
518 alternate=True),
519 verneed['vn_version'], bytes2str(verneed.name),
520 verneed['vn_cnt']))
521
522 vernaux_offset = offset + verneed['vn_aux']
523 for idx, vernaux in enumerate(verneed_iter, start=1):
524 if vernaux['vna_flags']:
525 flags = describe_ver_flags(vernaux['vna_flags'])
526 # Mimic exactly the readelf output
527 flags += ' '
528 else:
529 flags = 'none'
530
531 self._emitline(
532 ' %s: Name: %s Flags: %s Version: %i' % (
533 self._format_hex(vernaux_offset, fieldsize=4),
534 bytes2str(vernaux.name), flags,
535 vernaux['vna_other']))
536
537 vernaux_offset += vernaux['vna_next']
538
539 offset += verneed['vn_next']
540
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300541 def display_hex_dump(self, section_spec):
542 """ Display a hex dump of a section. section_spec is either a section
543 number or a name.
544 """
eliben54e39b22011-09-19 13:10:57 +0300545 section = self._section_from_spec(section_spec)
546 if section is None:
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300547 self._emitline("Section '%s' does not exist in the file!" % (
548 section_spec))
549 return
550
Eli Bendersky79271e92012-01-27 10:25:47 +0200551 self._emitline("\nHex dump of section '%s':" % bytes2str(section.name))
Eli Benderskyadf707a2011-09-23 15:23:41 +0300552 self._note_relocs_for_section(section)
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300553 addr = section['sh_addr']
554 data = section.data()
555 dataptr = 0
556
557 while dataptr < len(data):
558 bytesleft = len(data) - dataptr
559 # chunks of 16 bytes per line
560 linebytes = 16 if bytesleft > 16 else bytesleft
561
562 self._emit(' %s ' % self._format_hex(addr, fieldsize=8))
563 for i in range(16):
564 if i < linebytes:
Eli Bendersky79271e92012-01-27 10:25:47 +0200565 self._emit('%2.2x' % byte2int(data[dataptr + i]))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300566 else:
567 self._emit(' ')
568 if i % 4 == 3:
569 self._emit(' ')
570
571 for i in range(linebytes):
Eli Bendersky79271e92012-01-27 10:25:47 +0200572 c = data[dataptr + i : dataptr + i + 1]
573 if byte2int(c[0]) >= 32 and byte2int(c[0]) < 0x7f:
574 self._emit(bytes2str(c))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300575 else:
Eli Bendersky79271e92012-01-27 10:25:47 +0200576 self._emit(bytes2str(b'.'))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300577
578 self._emitline()
579 addr += linebytes
580 dataptr += linebytes
581
582 self._emitline()
583
Eli Bendersky53e86db2011-09-18 06:04:30 +0300584 def display_string_dump(self, section_spec):
585 """ Display a strings dump of a section. section_spec is either a
586 section number or a name.
587 """
eliben54e39b22011-09-19 13:10:57 +0300588 section = self._section_from_spec(section_spec)
589 if section is None:
Eli Bendersky53e86db2011-09-18 06:04:30 +0300590 self._emitline("Section '%s' does not exist in the file!" % (
591 section_spec))
592 return
593
Eli Bendersky79271e92012-01-27 10:25:47 +0200594 self._emitline("\nString dump of section '%s':" % bytes2str(section.name))
Eli Bendersky53e86db2011-09-18 06:04:30 +0300595
596 found = False
597 data = section.data()
598 dataptr = 0
599
600 while dataptr < len(data):
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800601 while ( dataptr < len(data) and
Eli Bendersky79271e92012-01-27 10:25:47 +0200602 not (32 <= byte2int(data[dataptr]) <= 127)):
Eli Bendersky53e86db2011-09-18 06:04:30 +0300603 dataptr += 1
604
605 if dataptr >= len(data):
606 break
607
608 endptr = dataptr
Eli Bendersky79271e92012-01-27 10:25:47 +0200609 while endptr < len(data) and byte2int(data[endptr]) != 0:
Eli Bendersky53e86db2011-09-18 06:04:30 +0300610 endptr += 1
611
612 found = True
613 self._emitline(' [%6x] %s' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200614 dataptr, bytes2str(data[dataptr:endptr])))
Eli Bendersky53e86db2011-09-18 06:04:30 +0300615
616 dataptr = endptr
617
618 if not found:
619 self._emitline(' No strings found in this section.')
620 else:
621 self._emitline()
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300622
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200623 def display_debug_dump(self, dump_what):
eliben0fc47af2011-10-02 13:47:12 +0200624 """ Dump a DWARF section
625 """
626 self._init_dwarfinfo()
627 if self._dwarfinfo is None:
628 return
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800629
Eli Bendersky3501f9f2011-12-09 12:29:06 +0200630 set_global_machine_arch(self.elffile.get_machine_arch())
631
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200632 if dump_what == 'info':
eliben0fc47af2011-10-02 13:47:12 +0200633 self._dump_debug_info()
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200634 elif dump_what == 'decodedline':
635 self._dump_debug_line_programs()
Eli Bendersky7241ff02011-12-12 06:40:34 +0200636 elif dump_what == 'frames':
637 self._dump_debug_frames()
Eli Bendersky8670bb32011-12-15 16:11:06 +0200638 elif dump_what == 'frames-interp':
639 self._dump_debug_frames_interp()
eliben0fc47af2011-10-02 13:47:12 +0200640 else:
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200641 self._emitline('debug dump not yet supported for "%s"' % dump_what)
eliben0fc47af2011-10-02 13:47:12 +0200642
Yann Rouillard7b246702013-05-27 22:44:28 +0200643 def _format_hex(self, addr, fieldsize=None, fullhex=False, lead0x=True,
644 alternate=False):
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300645 """ Format an address into a hexadecimal string.
Eli Benderskyd62928d2011-09-09 10:05:57 +0300646
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300647 fieldsize:
648 Size of the hexadecimal field (with leading zeros to fit the
649 address into. For example with fieldsize=8, the format will
650 be %08x
651 If None, the minimal required field size will be used.
652
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300653 fullhex:
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800654 If True, override fieldsize to set it to the maximal size
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300655 needed for the elfclass
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300656
657 lead0x:
658 If True, leading 0x is added
Yann Rouillard7b246702013-05-27 22:44:28 +0200659
660 alternate:
661 If True, override lead0x to emulate the alternate
Yann Rouillardde179382013-05-29 23:47:50 +0200662 hexadecimal form specified in format string with the #
Yann Rouillard7b246702013-05-27 22:44:28 +0200663 character: only non-zero values are prefixed with 0x.
664 This form is used by readelf.
Eli Benderskyd62928d2011-09-09 10:05:57 +0300665 """
Yann Rouillard7b246702013-05-27 22:44:28 +0200666 if alternate:
667 if addr == 0:
668 lead0x = False
669 else:
670 lead0x = True
671 fieldsize -= 2
672
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300673 s = '0x' if lead0x else ''
674 if fullhex:
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300675 fieldsize = 8 if self.elffile.elfclass == 32 else 16
676 if fieldsize is None:
677 field = '%x'
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300678 else:
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300679 field = '%' + '0%sx' % fieldsize
680 return s + field % addr
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800681
Yann Rouillardde179382013-05-29 23:47:50 +0200682 def _print_version_section_header(self, version_section, name, lead0x=True,
683 indent=1):
684 """ Print a section header of one version related section (versym,
685 verneed or verdef) with some options to accomodate readelf
686 little differences between each header (e.g. indentation
687 and 0x prefixing).
Yann Rouillard7b246702013-05-27 22:44:28 +0200688 """
689 if hasattr(version_section, 'num_versions'):
690 num_entries = version_section.num_versions()
691 else:
692 num_entries = version_section.num_symbols()
693
694 self._emitline("\n%s section '%s' contains %s entries:" %
695 (name, bytes2str(version_section.name), num_entries))
Yann Rouillardde179382013-05-29 23:47:50 +0200696 self._emitline('%sAddr: %s Offset: %s Link: %i (%s)' % (
697 ' ' * indent,
698 self._format_hex(
699 version_section['sh_addr'], fieldsize=16, lead0x=lead0x),
700 self._format_hex(
701 version_section['sh_offset'], fieldsize=6, lead0x=True),
702 version_section['sh_link'],
703 bytes2str(
704 self.elffile.get_section(version_section['sh_link']).name)
705 )
706 )
Yann Rouillard7b246702013-05-27 22:44:28 +0200707
708 def _init_versioninfo(self):
709 """ Search and initialize informations about version related sections
710 and the kind of versioning used (GNU or Solaris).
711 """
712 if self._versioninfo is not None:
713 return
714
Yann Rouillardde179382013-05-29 23:47:50 +0200715 self._versioninfo = {'versym': None, 'verdef': None,
716 'verneed': None, 'type': None}
Yann Rouillard7b246702013-05-27 22:44:28 +0200717
718 for section in self.elffile.iter_sections():
Yann Rouillard478a4592013-05-31 21:01:25 +0200719 if isinstance(section, GNUVerSymSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200720 self._versioninfo['versym'] = section
Yann Rouillard478a4592013-05-31 21:01:25 +0200721 elif isinstance(section, GNUVerDefSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200722 self._versioninfo['verdef'] = section
Yann Rouillard478a4592013-05-31 21:01:25 +0200723 elif isinstance(section, GNUVerNeedSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200724 self._versioninfo['verneed'] = section
725 elif isinstance(section, DynamicSection):
726 for tag in section.iter_tags():
727 if tag['d_tag'] == 'DT_VERSYM':
728 self._versioninfo['type'] = 'GNU'
Yann Rouillardde179382013-05-29 23:47:50 +0200729 break
Yann Rouillard7b246702013-05-27 22:44:28 +0200730
731 if not self._versioninfo['type'] and (
732 self._versioninfo['verneed'] or self._versioninfo['verdef']):
733 self._versioninfo['type'] = 'Solaris'
734
Yann Rouillard7b246702013-05-27 22:44:28 +0200735 def _symbol_version(self, nsym):
Yann Rouillardde179382013-05-29 23:47:50 +0200736 """ Return a dict containing information on the
Yann Rouillard7b246702013-05-27 22:44:28 +0200737 or None if no version information is available
738 """
739 self._init_versioninfo()
Yann Rouillardde179382013-05-29 23:47:50 +0200740
Yann Rouillard7b246702013-05-27 22:44:28 +0200741 symbol_version = dict.fromkeys(('index', 'name', 'filename', 'hidden'))
742
743 if (not self._versioninfo['versym'] or
744 nsym >= self._versioninfo['versym'].num_symbols()):
745 return None
746
747 symbol = self._versioninfo['versym'].get_symbol(nsym)
748 index = symbol.entry['ndx']
749 if not index in ('VER_NDX_LOCAL', 'VER_NDX_GLOBAL'):
750 index = int(index)
751
752 if self._versioninfo['type'] == 'GNU':
Yann Rouillardde179382013-05-29 23:47:50 +0200753 # In GNU versioning mode, the highest bit is used to
Yann Rouillard7b246702013-05-27 22:44:28 +0200754 # store wether the symbol is hidden or not
755 if index & 0x8000:
Yann Rouillardde179382013-05-29 23:47:50 +0200756 index &= ~0x8000
Yann Rouillard7b246702013-05-27 22:44:28 +0200757 symbol_version['hidden'] = True
758
Yann Rouillardde179382013-05-29 23:47:50 +0200759 if (self._versioninfo['verdef'] and
Yann Rouillard7b246702013-05-27 22:44:28 +0200760 index <= self._versioninfo['verdef'].num_versions()):
761 _, verdaux_iter = \
762 self._versioninfo['verdef'].get_version(index)
763 symbol_version['name'] = bytes2str(next(verdaux_iter).name)
764 else:
765 verneed, vernaux = \
766 self._versioninfo['verneed'].get_version(index)
767 symbol_version['name'] = bytes2str(vernaux.name)
768 symbol_version['filename'] = bytes2str(verneed.name)
769
770 symbol_version['index'] = index
771 return symbol_version
772
eliben54e39b22011-09-19 13:10:57 +0300773 def _section_from_spec(self, spec):
774 """ Retrieve a section given a "spec" (either number or name).
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300775 Return None if no such section exists in the file.
776 """
777 try:
778 num = int(spec)
eliben54e39b22011-09-19 13:10:57 +0300779 if num < self.elffile.num_sections():
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800780 return self.elffile.get_section(num)
eliben54e39b22011-09-19 13:10:57 +0300781 else:
782 return None
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300783 except ValueError:
784 # Not a number. Must be a name then
Eli Bendersky79271e92012-01-27 10:25:47 +0200785 return self.elffile.get_section_by_name(str2bytes(spec))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300786
Eli Benderskyadf707a2011-09-23 15:23:41 +0300787 def _note_relocs_for_section(self, section):
788 """ If there are relocation sections pointing to the givne section,
789 emit a note about it.
790 """
791 for relsec in self.elffile.iter_sections():
792 if isinstance(relsec, RelocationSection):
793 info_idx = relsec['sh_info']
794 if self.elffile.get_section(info_idx) == section:
795 self._emitline(' Note: This section has relocations against it, but these have NOT been applied to this dump.')
796 return
797
eliben0fc47af2011-10-02 13:47:12 +0200798 def _init_dwarfinfo(self):
799 """ Initialize the DWARF info contained in the file and assign it to
800 self._dwarfinfo.
801 Leave self._dwarfinfo at None if no DWARF info was found in the file
802 """
803 if self._dwarfinfo is not None:
804 return
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800805
eliben0fc47af2011-10-02 13:47:12 +0200806 if self.elffile.has_dwarf_info():
807 self._dwarfinfo = self.elffile.get_dwarf_info()
808 else:
809 self._dwarfinfo = None
810
811 def _dump_debug_info(self):
812 """ Dump the debugging info section.
813 """
eliben985c2c12011-11-14 17:53:23 +0200814 self._emitline('Contents of the .debug_info section:\n')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800815
eliben0fc47af2011-10-02 13:47:12 +0200816 # Offset of the .debug_info section in the stream
Eli Bendersky149315a2011-11-24 08:12:37 +0200817 section_offset = self._dwarfinfo.debug_info_sec.global_offset
Eli Bendersky6062bf72011-11-23 06:54:40 +0200818
eliben0fc47af2011-10-02 13:47:12 +0200819 for cu in self._dwarfinfo.iter_CUs():
eliben985c2c12011-11-14 17:53:23 +0200820 self._emitline(' Compilation Unit @ offset %s:' %
Eli Bendersky149315a2011-11-24 08:12:37 +0200821 self._format_hex(cu.cu_offset))
eliben0fc47af2011-10-02 13:47:12 +0200822 self._emitline(' Length: %s (%s)' % (
823 self._format_hex(cu['unit_length']),
824 '%s-bit' % cu.dwarf_format()))
825 self._emitline(' Version: %s' % cu['version']),
Eli Bendersky7eba7182013-03-30 17:23:36 -0700826 self._emitline(' Abbrev Offset: %s' % (
827 self._format_hex(cu['debug_abbrev_offset']))),
eliben0fc47af2011-10-02 13:47:12 +0200828 self._emitline(' Pointer Size: %s' % cu['address_size'])
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800829
830 # The nesting depth of each DIE within the tree of DIEs must be
eliben0fc47af2011-10-02 13:47:12 +0200831 # displayed. To implement this, a counter is incremented each time
832 # the current DIE has children, and decremented when a null die is
833 # encountered. Due to the way the DIE tree is serialized, this will
834 # correctly reflect the nesting depth
835 #
836 die_depth = 0
837 for die in cu.iter_DIEs():
Eli Bendersky9aec9d82013-03-30 16:39:30 -0700838 self._emitline(' <%s><%x>: Abbrev Number: %s%s' % (
elibenaee11d22011-10-26 10:42:34 +0200839 die_depth,
Eli Bendersky149315a2011-11-24 08:12:37 +0200840 die.offset,
elibenaee11d22011-10-26 10:42:34 +0200841 die.abbrev_code,
Eli Bendersky9aec9d82013-03-30 16:39:30 -0700842 (' (%s)' % die.tag) if not die.is_null() else ''))
843 if die.is_null():
844 die_depth -= 1
845 continue
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800846
Eli Bendersky79271e92012-01-27 10:25:47 +0200847 for attr in itervalues(die.attributes):
Eli Bendersky871ad0c2011-12-16 08:13:48 +0200848 name = attr.name
849 # Unknown attribute values are passed-through as integers
850 if isinstance(name, int):
851 name = 'Unknown AT value: %x' % name
elibenaee11d22011-10-26 10:42:34 +0200852 self._emitline(' <%2x> %-18s: %s' % (
Eli Bendersky149315a2011-11-24 08:12:37 +0200853 attr.offset,
Eli Bendersky871ad0c2011-12-16 08:13:48 +0200854 name,
eliben3bc9c342011-10-26 13:10:58 +0200855 describe_attr_value(
Eli Bendersky5be3be82011-10-27 14:28:12 +0200856 attr, die, section_offset)))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800857
eliben0fc47af2011-10-02 13:47:12 +0200858 if die.has_children:
859 die_depth += 1
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800860
Eli Benderskyf5670e82011-11-24 09:05:44 +0200861 self._emitline()
eliben0fc47af2011-10-02 13:47:12 +0200862
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200863 def _dump_debug_line_programs(self):
864 """ Dump the (decoded) line programs from .debug_line
865 The programs are dumped in the order of the CUs they belong to.
866 """
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200867 self._emitline('Decoded dump of debug contents of section .debug_line:\n')
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200868
869 for cu in self._dwarfinfo.iter_CUs():
870 lineprogram = self._dwarfinfo.line_program_for_CU(cu)
871
Eli Bendersky7eba7182013-03-30 17:23:36 -0700872 cu_filename = bytes2str(lineprogram['file_entry'][0].name)
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200873 if len(lineprogram['include_directory']) > 0:
Eli Bendersky7eba7182013-03-30 17:23:36 -0700874 dir_index = lineprogram['file_entry'][0].dir_index
875 if dir_index > 0:
876 dir = lineprogram['include_directory'][dir_index - 1]
877 else:
Eli Benderskyccdb5542013-03-31 14:19:21 -0700878 dir = b'.'
Eli Bendersky7eba7182013-03-30 17:23:36 -0700879 cu_filename = '%s/%s' % (bytes2str(dir), cu_filename)
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200880
881 self._emitline('CU: %s:' % cu_filename)
882 self._emitline('File name Line number Starting address')
883
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200884 # Print each state's file, line and address information. For some
885 # instructions other output is needed to be compatible with
886 # readelf.
887 for entry in lineprogram.get_entries():
888 state = entry.state
889 if state is None:
890 # Special handling for commands that don't set a new state
891 if entry.command == DW_LNS_set_file:
892 file_entry = lineprogram['file_entry'][entry.args[0] - 1]
893 if file_entry.dir_index == 0:
894 # current directory
895 self._emitline('\n./%s:[++]' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200896 bytes2str(file_entry.name)))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200897 else:
898 self._emitline('\n%s/%s:' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200899 bytes2str(lineprogram['include_directory'][file_entry.dir_index - 1]),
900 bytes2str(file_entry.name)))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200901 elif entry.command == DW_LNE_define_file:
902 self._emitline('%s:' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200903 bytes2str(lineprogram['include_directory'][entry.args[0].dir_index])))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200904 elif not state.end_sequence:
905 # readelf doesn't print the state after end_sequence
906 # instructions. I think it's a bug but to be compatible
907 # I don't print them too.
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200908 self._emitline('%-35s %11d %18s' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200909 bytes2str(lineprogram['file_entry'][state.file - 1].name),
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200910 state.line,
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800911 '0' if state.address == 0 else
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200912 self._format_hex(state.address)))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200913 if entry.command == DW_LNS_copy:
914 # Another readelf oddity...
915 self._emitline()
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200916
Eli Bendersky7241ff02011-12-12 06:40:34 +0200917 def _dump_debug_frames(self):
918 """ Dump the raw frame information from .debug_frame
919 """
Eli Bendersky47a47112011-12-14 06:54:09 +0200920 if not self._dwarfinfo.has_CFI():
921 return
Eli Bendersky7241ff02011-12-12 06:40:34 +0200922 self._emitline('Contents of the .debug_frame section:')
923
924 for entry in self._dwarfinfo.CFI_entries():
925 if isinstance(entry, CIE):
Eli Benderskycb4eb992013-11-28 09:54:41 -0800926 self._emitline('\n%08x %s %s CIE' % (
927 entry.offset,
928 self._format_hex(entry['length'], fullhex=True, lead0x=False),
929 self._format_hex(entry['CIE_id'], fullhex=True, lead0x=False)))
Eli Bendersky7241ff02011-12-12 06:40:34 +0200930 self._emitline(' Version: %d' % entry['version'])
Eli Bendersky79271e92012-01-27 10:25:47 +0200931 self._emitline(' Augmentation: "%s"' % bytes2str(entry['augmentation']))
Eli Bendersky7241ff02011-12-12 06:40:34 +0200932 self._emitline(' Code alignment factor: %u' % entry['code_alignment_factor'])
933 self._emitline(' Data alignment factor: %d' % entry['data_alignment_factor'])
934 self._emitline(' Return address column: %d' % entry['return_address_register'])
Eli Bendersky47a47112011-12-14 06:54:09 +0200935 self._emitline()
Eli Bendersky7241ff02011-12-12 06:40:34 +0200936 else: # FDE
Eli Benderskycb4eb992013-11-28 09:54:41 -0800937 self._emitline('\n%08x %s %s FDE cie=%08x pc=%s..%s' % (
Eli Bendersky7241ff02011-12-12 06:40:34 +0200938 entry.offset,
Eli Benderskycb4eb992013-11-28 09:54:41 -0800939 self._format_hex(entry['length'], fullhex=True, lead0x=False),
940 self._format_hex(entry['CIE_pointer'], fullhex=True, lead0x=False),
Eli Bendersky7241ff02011-12-12 06:40:34 +0200941 entry.cie.offset,
Eli Benderskycb4eb992013-11-28 09:54:41 -0800942 self._format_hex(entry['initial_location'], fullhex=True, lead0x=False),
943 self._format_hex(
944 entry['initial_location'] + entry['address_range'],
945 fullhex=True, lead0x=False)))
Eli Bendersky7241ff02011-12-12 06:40:34 +0200946
Eli Bendersky47a47112011-12-14 06:54:09 +0200947 self._emit(describe_CFI_instructions(entry))
948 self._emitline()
Eli Bendersky7241ff02011-12-12 06:40:34 +0200949
Eli Bendersky8670bb32011-12-15 16:11:06 +0200950 def _dump_debug_frames_interp(self):
951 """ Dump the interpreted (decoded) frame information from .debug_frame
952 """
953 if not self._dwarfinfo.has_CFI():
954 return
955
956 self._emitline('Contents of the .debug_frame section:')
957
958 for entry in self._dwarfinfo.CFI_entries():
959 if isinstance(entry, CIE):
Eli Benderskycb4eb992013-11-28 09:54:41 -0800960 self._emitline('\n%08x %s %s CIE "%s" cf=%d df=%d ra=%d' % (
Eli Bendersky8670bb32011-12-15 16:11:06 +0200961 entry.offset,
Eli Benderskycb4eb992013-11-28 09:54:41 -0800962 self._format_hex(entry['length'], fullhex=True, lead0x=False),
963 self._format_hex(entry['CIE_id'], fullhex=True, lead0x=False),
Eli Bendersky79271e92012-01-27 10:25:47 +0200964 bytes2str(entry['augmentation']),
Eli Bendersky8670bb32011-12-15 16:11:06 +0200965 entry['code_alignment_factor'],
966 entry['data_alignment_factor'],
967 entry['return_address_register']))
Eli Bendersky4682c962011-12-16 06:39:49 +0200968 ra_regnum = entry['return_address_register']
Eli Bendersky8670bb32011-12-15 16:11:06 +0200969 else: # FDE
Eli Benderskycb4eb992013-11-28 09:54:41 -0800970 self._emitline('\n%08x %s %s FDE cie=%08x pc=%s..%s' % (
Eli Bendersky8670bb32011-12-15 16:11:06 +0200971 entry.offset,
Eli Benderskycb4eb992013-11-28 09:54:41 -0800972 self._format_hex(entry['length'], fullhex=True, lead0x=False),
973 self._format_hex(entry['CIE_pointer'], fullhex=True, lead0x=False),
Eli Bendersky8670bb32011-12-15 16:11:06 +0200974 entry.cie.offset,
Eli Benderskycb4eb992013-11-28 09:54:41 -0800975 self._format_hex(entry['initial_location'], fullhex=True, lead0x=False),
976 self._format_hex(entry['initial_location'] + entry['address_range'],
977 fullhex=True, lead0x=False)))
Eli Bendersky4682c962011-12-16 06:39:49 +0200978 ra_regnum = entry.cie['return_address_register']
Eli Bendersky8670bb32011-12-15 16:11:06 +0200979
980 # Print the heading row for the decoded table
981 self._emit(' LOC')
982 self._emit(' ' if entry.structs.address_size == 4 else ' ')
Eli Bendersky4682c962011-12-16 06:39:49 +0200983 self._emit(' CFA ')
Eli Bendersky8670bb32011-12-15 16:11:06 +0200984
Eli Bendersky4682c962011-12-16 06:39:49 +0200985 # Decode the table nad look at the registers it describes.
986 # We build reg_order here to match readelf's order. In particular,
987 # registers are sorted by their number, and the register matching
988 # ra_regnum is always listed last with a special heading.
Eli Bendersky8670bb32011-12-15 16:11:06 +0200989 decoded_table = entry.get_decoded()
Eli Bendersky4682c962011-12-16 06:39:49 +0200990 reg_order = sorted(ifilter(
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800991 lambda r: r != ra_regnum,
Eli Bendersky4682c962011-12-16 06:39:49 +0200992 decoded_table.reg_order))
993
994 # Headings for the registers
995 for regnum in reg_order:
Eli Bendersky8670bb32011-12-15 16:11:06 +0200996 self._emit('%-6s' % describe_reg_name(regnum))
997 self._emitline('ra ')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800998
Eli Bendersky4682c962011-12-16 06:39:49 +0200999 # Now include ra_regnum in reg_order to print its values similarly
1000 # to the other registers.
1001 reg_order.append(ra_regnum)
1002 for line in decoded_table.table:
1003 self._emit(self._format_hex(
1004 line['pc'], fullhex=True, lead0x=False))
1005 self._emit(' %-9s' % describe_CFI_CFA_rule(line['cfa']))
Eli Bendersky8670bb32011-12-15 16:11:06 +02001006
Eli Bendersky4682c962011-12-16 06:39:49 +02001007 for regnum in reg_order:
1008 if regnum in line:
1009 s = describe_CFI_register_rule(line[regnum])
1010 else:
1011 s = 'u'
1012 self._emit('%-6s' % s)
1013 self._emitline()
1014 self._emitline()
Eli Bendersky8670bb32011-12-15 16:11:06 +02001015
Eli Bendersky26de2ac2011-09-13 06:50:28 +03001016 def _emit(self, s=''):
Eli Bendersky933f6992011-09-09 08:11:06 +03001017 """ Emit an object to output
1018 """
1019 self.output.write(str(s))
Eli Benderskyd62928d2011-09-09 10:05:57 +03001020
Eli Bendersky26de2ac2011-09-13 06:50:28 +03001021 def _emitline(self, s=''):
Eli Bendersky933f6992011-09-09 08:11:06 +03001022 """ Emit an object to output, followed by a newline
1023 """
1024 self.output.write(str(s) + '\n')
1025
1026
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001027SCRIPT_DESCRIPTION = 'Display information about the contents of ELF format files'
1028VERSION_STRING = '%%prog: based on pyelftools %s' % __version__
1029
1030
Eli Bendersky0193fb82011-11-26 16:16:16 +02001031def main(stream=None):
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001032 # parse the command-line arguments and invoke ReadElf
Eli Bendersky40eb1702011-09-16 16:59:52 +03001033 optparser = OptionParser(
Eli Benderskyecde41b2011-09-16 17:16:20 +03001034 usage='usage: %prog [options] <elf-file>',
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001035 description=SCRIPT_DESCRIPTION,
Eli Bendersky40eb1702011-09-16 16:59:52 +03001036 add_help_option=False, # -h is a real option of readelf
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001037 prog='readelf.py',
1038 version=VERSION_STRING)
Mike Frysinger5699e182013-03-23 02:47:32 -04001039 optparser.add_option('-d', '--dynamic',
1040 action='store_true', dest='show_dynamic_tags',
1041 help='Display the dynamic section')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001042 optparser.add_option('-H', '--help',
1043 action='store_true', dest='help',
1044 help='Display this information')
1045 optparser.add_option('-h', '--file-header',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001046 action='store_true', dest='show_file_header',
1047 help='Display the ELF file header')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001048 optparser.add_option('-l', '--program-headers', '--segments',
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001049 action='store_true', dest='show_program_header',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001050 help='Display the program headers')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001051 optparser.add_option('-S', '--section-headers', '--sections',
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001052 action='store_true', dest='show_section_header',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001053 help="Display the sections' headers")
Eli Bendersky40eb1702011-09-16 16:59:52 +03001054 optparser.add_option('-e', '--headers',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001055 action='store_true', dest='show_all_headers',
1056 help='Equivalent to: -h -l -S')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001057 optparser.add_option('-s', '--symbols', '--syms',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001058 action='store_true', dest='show_symbols',
1059 help='Display the symbol table')
Eli Bendersky84066b22011-09-20 06:48:52 +03001060 optparser.add_option('-r', '--relocs',
1061 action='store_true', dest='show_relocs',
1062 help='Display the relocations (if present)')
Eli Benderskyc4a4c072011-09-17 15:28:28 +03001063 optparser.add_option('-x', '--hex-dump',
1064 action='store', dest='show_hex_dump', metavar='<number|name>',
1065 help='Dump the contents of section <number|name> as bytes')
Eli Bendersky53e86db2011-09-18 06:04:30 +03001066 optparser.add_option('-p', '--string-dump',
1067 action='store', dest='show_string_dump', metavar='<number|name>',
1068 help='Dump the contents of section <number|name> as strings')
Yann Rouillard7b246702013-05-27 22:44:28 +02001069 optparser.add_option('-V', '--version-info',
1070 action='store_true', dest='show_version_info',
1071 help='Display the version sections (if present)')
eliben0fc47af2011-10-02 13:47:12 +02001072 optparser.add_option('--debug-dump',
Eli Bendersky1a516a32011-12-22 15:22:00 +02001073 action='store', dest='debug_dump_what', metavar='<what>',
1074 help=(
1075 'Display the contents of DWARF debug sections. <what> can ' +
1076 'one of {info,decodedline,frames,frames-interp}'))
Eli Bendersky53e86db2011-09-18 06:04:30 +03001077
Eli Bendersky933f6992011-09-09 08:11:06 +03001078 options, args = optparser.parse_args()
1079
Eli Bendersky40eb1702011-09-16 16:59:52 +03001080 if options.help or len(args) == 0:
1081 optparser.print_help()
1082 sys.exit(0)
1083
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001084 if options.show_all_headers:
1085 do_file_header = do_section_header = do_program_header = True
1086 else:
1087 do_file_header = options.show_file_header
1088 do_section_header = options.show_section_header
1089 do_program_header = options.show_program_header
1090
Eli Bendersky933f6992011-09-09 08:11:06 +03001091 with open(args[0], 'rb') as file:
1092 try:
Eli Bendersky0193fb82011-11-26 16:16:16 +02001093 readelf = ReadElf(file, stream or sys.stdout)
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001094 if do_file_header:
1095 readelf.display_file_header()
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001096 if do_section_header:
1097 readelf.display_section_headers(
1098 show_heading=not do_file_header)
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +03001099 if do_program_header:
1100 readelf.display_program_headers(
1101 show_heading=not do_file_header)
Mike Frysinger5699e182013-03-23 02:47:32 -04001102 if options.show_dynamic_tags:
1103 readelf.display_dynamic_tags()
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001104 if options.show_symbols:
1105 readelf.display_symbol_tables()
Eli Bendersky84066b22011-09-20 06:48:52 +03001106 if options.show_relocs:
1107 readelf.display_relocations()
Yann Rouillard7b246702013-05-27 22:44:28 +02001108 if options.show_version_info:
1109 readelf.display_version_info()
Eli Benderskyc4a4c072011-09-17 15:28:28 +03001110 if options.show_hex_dump:
1111 readelf.display_hex_dump(options.show_hex_dump)
Eli Bendersky53e86db2011-09-18 06:04:30 +03001112 if options.show_string_dump:
1113 readelf.display_string_dump(options.show_string_dump)
Eli Bendersky5ec2dde2011-12-04 07:05:31 +02001114 if options.debug_dump_what:
1115 readelf.display_debug_dump(options.debug_dump_what)
Eli Bendersky933f6992011-09-09 08:11:06 +03001116 except ELFError as ex:
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001117 sys.stderr.write('ELF error: %s\n' % ex)
Eli Bendersky933f6992011-09-09 08:11:06 +03001118 sys.exit(1)
1119
1120
Eli Bendersky0193fb82011-11-26 16:16:16 +02001121def profile_main():
1122 # Run 'main' redirecting its output to readelfout.txt
1123 # Saves profiling information in readelf.profile
1124 PROFFILE = 'readelf.profile'
1125 import cProfile
1126 cProfile.run('main(open("readelfout.txt", "w"))', PROFFILE)
1127
1128 # Dig in some profiling stats
1129 import pstats
1130 p = pstats.Stats(PROFFILE)
1131 p.sort_stats('cumulative').print_stats(25)
1132
1133
Eli Bendersky933f6992011-09-09 08:11:06 +03001134#-------------------------------------------------------------------------------
1135if __name__ == '__main__':
Eli Bendersky4f4d80c2011-11-26 16:49:27 +02001136 main()
1137 #profile_main()
Eli Bendersky0193fb82011-11-26 16:16:16 +02001138
Eli Bendersky933f6992011-09-09 08:11:06 +03001139