blob: 8179c013a54cf5ca7a369c386bf3b571fd894823 [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)
Martin Panter133ac3f2014-02-12 00:09:01 +0000353 elif tag.entry.d_tag.endswith(('SZ', 'ENT')):
Mike Frysinger5699e182013-03-23 02:47:32 -0400354 parsed = '%i (bytes)' % tag['d_val']
Martin Panter133ac3f2014-02-12 00:09:01 +0000355 elif tag.entry.d_tag.endswith(('NUM', 'COUNT')):
Mike Frysinger5699e182013-03-23 02:47:32 -0400356 parsed = '%i' % tag['d_val']
357 elif tag.entry.d_tag == 'DT_PLTREL':
358 s = describe_dyn_tag(tag.entry.d_val)
359 if s.startswith('DT_'):
360 s = s[3:]
361 parsed = '%s' % s
362 else:
363 parsed = '%#x' % tag['d_val']
364
365 self._emitline(" %s %-*s %s" % (
366 self._format_hex(ENUM_D_TAG.get(tag.entry.d_tag, tag.entry.d_tag),
Eli Benderskyf8d2cf72013-03-31 06:56:56 -0700367 fullhex=True, lead0x=True),
Mike Frysinger5699e182013-03-23 02:47:32 -0400368 padding,
369 '(%s)' % (tag.entry.d_tag[3:],),
370 parsed))
Eli Bendersky6fdebd92013-06-08 09:40:41 -0700371 if not has_dynamic_sections:
372 # readelf only prints this if there is at least one segment
373 if self.elffile.num_segments():
374 self._emitline("\nThere is no dynamic section in this file.")
Mike Frysinger5699e182013-03-23 02:47:32 -0400375
Eli Bendersky84066b22011-09-20 06:48:52 +0300376 def display_relocations(self):
377 """ Display the relocations contained in the file
378 """
379 has_relocation_sections = False
380 for section in self.elffile.iter_sections():
381 if not isinstance(section, RelocationSection):
382 continue
383
384 has_relocation_sections = True
385 self._emitline("\nRelocation section '%s' at offset %s contains %s entries:" % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200386 bytes2str(section.name),
Eli Bendersky7c1ffa62011-09-22 06:37:07 +0300387 self._format_hex(section['sh_offset']),
388 section.num_relocations()))
Eli Bendersky89a824f2011-09-23 10:59:59 +0300389 if section.is_RELA():
390 self._emitline(" Offset Info Type Sym. Value Sym. Name + Addend")
391 else:
392 self._emitline(" Offset Info Type Sym.Value Sym. Name")
393
394 # The symbol table section pointed to in sh_link
395 symtable = self.elffile.get_section(section['sh_link'])
396
Eli Bendersky84066b22011-09-20 06:48:52 +0300397 for rel in section.iter_relocations():
Eli Bendersky89a824f2011-09-23 10:59:59 +0300398 hexwidth = 8 if self.elffile.elfclass == 32 else 12
Eli Bendersky099d48f2011-09-23 12:03:48 +0300399 self._emit('%s %s %-17.17s' % (
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800400 self._format_hex(rel['r_offset'],
Eli Bendersky89a824f2011-09-23 10:59:59 +0300401 fieldsize=hexwidth, lead0x=False),
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800402 self._format_hex(rel['r_info'],
Eli Bendersky89a824f2011-09-23 10:59:59 +0300403 fieldsize=hexwidth, lead0x=False),
404 describe_reloc_type(
Eli Bendersky067b3fd2011-11-18 12:02:57 +0200405 rel['r_info_type'], self.elffile)))
Eli Bendersky099d48f2011-09-23 12:03:48 +0300406
407 if rel['r_info_sym'] == 0:
408 self._emitline()
409 continue
410
411 symbol = symtable.get_symbol(rel['r_info_sym'])
Eli Benderskyadf707a2011-09-23 15:23:41 +0300412 # Some symbols have zero 'st_name', so instead what's used is
413 # the name of the section they point at
414 if symbol['st_name'] == 0:
415 symsec = self.elffile.get_section(symbol['st_shndx'])
416 symbol_name = symsec.name
417 else:
418 symbol_name = symbol.name
Eli Bendersky6434a962011-09-23 17:14:08 +0300419 self._emit(' %s %s%22.22s' % (
Eli Bendersky89a824f2011-09-23 10:59:59 +0300420 self._format_hex(
421 symbol['st_value'],
422 fullhex=True, lead0x=False),
423 ' ' if self.elffile.elfclass == 32 else '',
Eli Bendersky79271e92012-01-27 10:25:47 +0200424 bytes2str(symbol_name)))
Eli Bendersky89a824f2011-09-23 10:59:59 +0300425 if section.is_RELA():
426 self._emit(' %s %x' % (
427 '+' if rel['r_addend'] >= 0 else '-',
428 abs(rel['r_addend'])))
429 self._emitline()
Eli Bendersky84066b22011-09-20 06:48:52 +0300430
431 if not has_relocation_sections:
432 self._emitline('\nThere are no relocations in this file.')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800433
Yann Rouillard7b246702013-05-27 22:44:28 +0200434 def display_version_info(self):
435 """ Display the version info contained in the file
436 """
437 self._init_versioninfo()
438
439 if not self._versioninfo['type']:
440 self._emitline("\nNo version information found in this file.")
441 return
442
443 for section in self.elffile.iter_sections():
Yann Rouillard478a4592013-05-31 21:01:25 +0200444 if isinstance(section, GNUVerSymSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200445 self._print_version_section_header(
446 section, 'Version symbols', lead0x=False)
447
448 num_symbols = section.num_symbols()
449
450 # Symbol version info are printed four by four entries
451 for idx_by_4 in range(0, num_symbols, 4):
452
453 self._emit(' %03x:' % idx_by_4)
454
455 for idx in range(idx_by_4, min(idx_by_4 + 4, num_symbols)):
456
457 symbol_version = self._symbol_version(idx)
458 if symbol_version['index'] == 'VER_NDX_LOCAL':
459 version_index = 0
460 version_name = '(*local*)'
461 elif symbol_version['index'] == 'VER_NDX_GLOBAL':
462 version_index = 1
463 version_name = '(*global*)'
464 else:
465 version_index = symbol_version['index']
466 version_name = '(%(name)s)' % symbol_version
467
468 visibility = 'h' if symbol_version['hidden'] else ' '
469
470 self._emit('%4x%s%-13s' % (
471 version_index, visibility, version_name))
472
473 self._emitline()
474
Yann Rouillard478a4592013-05-31 21:01:25 +0200475 elif isinstance(section, GNUVerDefSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200476 self._print_version_section_header(
477 section, 'Version definition', indent=2)
478
479 offset = 0
480 for verdef, verdaux_iter in section.iter_versions():
481 verdaux = next(verdaux_iter)
482
483 name = verdaux.name
484 if verdef['vd_flags']:
485 flags = describe_ver_flags(verdef['vd_flags'])
486 # Mimic exactly the readelf output
487 flags += ' '
488 else:
489 flags = 'none'
490
491 self._emitline(' %s: Rev: %i Flags: %s Index: %i'
492 ' Cnt: %i Name: %s' % (
493 self._format_hex(offset, fieldsize=6,
494 alternate=True),
495 verdef['vd_version'], flags, verdef['vd_ndx'],
496 verdef['vd_cnt'], bytes2str(name)))
497
498 verdaux_offset = (
499 offset + verdef['vd_aux'] + verdaux['vda_next'])
500 for idx, verdaux in enumerate(verdaux_iter, start=1):
501 self._emitline(' %s: Parent %i: %s' %
502 (self._format_hex(verdaux_offset, fieldsize=4),
503 idx, bytes2str(verdaux.name)))
504 verdaux_offset += verdaux['vda_next']
505
506 offset += verdef['vd_next']
507
Yann Rouillard478a4592013-05-31 21:01:25 +0200508 elif isinstance(section, GNUVerNeedSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200509 self._print_version_section_header(section, 'Version needs')
510
511 offset = 0
512 for verneed, verneed_iter in section.iter_versions():
513
514 self._emitline(' %s: Version: %i File: %s Cnt: %i' % (
515 self._format_hex(offset, fieldsize=6,
516 alternate=True),
517 verneed['vn_version'], bytes2str(verneed.name),
518 verneed['vn_cnt']))
519
520 vernaux_offset = offset + verneed['vn_aux']
521 for idx, vernaux in enumerate(verneed_iter, start=1):
522 if vernaux['vna_flags']:
523 flags = describe_ver_flags(vernaux['vna_flags'])
524 # Mimic exactly the readelf output
525 flags += ' '
526 else:
527 flags = 'none'
528
529 self._emitline(
530 ' %s: Name: %s Flags: %s Version: %i' % (
531 self._format_hex(vernaux_offset, fieldsize=4),
532 bytes2str(vernaux.name), flags,
533 vernaux['vna_other']))
534
535 vernaux_offset += vernaux['vna_next']
536
537 offset += verneed['vn_next']
538
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300539 def display_hex_dump(self, section_spec):
540 """ Display a hex dump of a section. section_spec is either a section
541 number or a name.
542 """
eliben54e39b22011-09-19 13:10:57 +0300543 section = self._section_from_spec(section_spec)
544 if section is None:
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300545 self._emitline("Section '%s' does not exist in the file!" % (
546 section_spec))
547 return
548
Eli Bendersky79271e92012-01-27 10:25:47 +0200549 self._emitline("\nHex dump of section '%s':" % bytes2str(section.name))
Eli Benderskyadf707a2011-09-23 15:23:41 +0300550 self._note_relocs_for_section(section)
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300551 addr = section['sh_addr']
552 data = section.data()
553 dataptr = 0
554
555 while dataptr < len(data):
556 bytesleft = len(data) - dataptr
557 # chunks of 16 bytes per line
558 linebytes = 16 if bytesleft > 16 else bytesleft
559
560 self._emit(' %s ' % self._format_hex(addr, fieldsize=8))
561 for i in range(16):
562 if i < linebytes:
Eli Bendersky79271e92012-01-27 10:25:47 +0200563 self._emit('%2.2x' % byte2int(data[dataptr + i]))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300564 else:
565 self._emit(' ')
566 if i % 4 == 3:
567 self._emit(' ')
568
569 for i in range(linebytes):
Eli Bendersky79271e92012-01-27 10:25:47 +0200570 c = data[dataptr + i : dataptr + i + 1]
571 if byte2int(c[0]) >= 32 and byte2int(c[0]) < 0x7f:
572 self._emit(bytes2str(c))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300573 else:
Eli Bendersky79271e92012-01-27 10:25:47 +0200574 self._emit(bytes2str(b'.'))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300575
576 self._emitline()
577 addr += linebytes
578 dataptr += linebytes
579
580 self._emitline()
581
Eli Bendersky53e86db2011-09-18 06:04:30 +0300582 def display_string_dump(self, section_spec):
583 """ Display a strings dump of a section. section_spec is either a
584 section number or a name.
585 """
eliben54e39b22011-09-19 13:10:57 +0300586 section = self._section_from_spec(section_spec)
587 if section is None:
Eli Bendersky53e86db2011-09-18 06:04:30 +0300588 self._emitline("Section '%s' does not exist in the file!" % (
589 section_spec))
590 return
591
Eli Bendersky79271e92012-01-27 10:25:47 +0200592 self._emitline("\nString dump of section '%s':" % bytes2str(section.name))
Eli Bendersky53e86db2011-09-18 06:04:30 +0300593
594 found = False
595 data = section.data()
596 dataptr = 0
597
598 while dataptr < len(data):
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800599 while ( dataptr < len(data) and
Eli Bendersky79271e92012-01-27 10:25:47 +0200600 not (32 <= byte2int(data[dataptr]) <= 127)):
Eli Bendersky53e86db2011-09-18 06:04:30 +0300601 dataptr += 1
602
603 if dataptr >= len(data):
604 break
605
606 endptr = dataptr
Eli Bendersky79271e92012-01-27 10:25:47 +0200607 while endptr < len(data) and byte2int(data[endptr]) != 0:
Eli Bendersky53e86db2011-09-18 06:04:30 +0300608 endptr += 1
609
610 found = True
611 self._emitline(' [%6x] %s' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200612 dataptr, bytes2str(data[dataptr:endptr])))
Eli Bendersky53e86db2011-09-18 06:04:30 +0300613
614 dataptr = endptr
615
616 if not found:
617 self._emitline(' No strings found in this section.')
618 else:
619 self._emitline()
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300620
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200621 def display_debug_dump(self, dump_what):
eliben0fc47af2011-10-02 13:47:12 +0200622 """ Dump a DWARF section
623 """
624 self._init_dwarfinfo()
625 if self._dwarfinfo is None:
626 return
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800627
Eli Bendersky3501f9f2011-12-09 12:29:06 +0200628 set_global_machine_arch(self.elffile.get_machine_arch())
629
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200630 if dump_what == 'info':
eliben0fc47af2011-10-02 13:47:12 +0200631 self._dump_debug_info()
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200632 elif dump_what == 'decodedline':
633 self._dump_debug_line_programs()
Eli Bendersky7241ff02011-12-12 06:40:34 +0200634 elif dump_what == 'frames':
635 self._dump_debug_frames()
Eli Bendersky8670bb32011-12-15 16:11:06 +0200636 elif dump_what == 'frames-interp':
637 self._dump_debug_frames_interp()
eliben0fc47af2011-10-02 13:47:12 +0200638 else:
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200639 self._emitline('debug dump not yet supported for "%s"' % dump_what)
eliben0fc47af2011-10-02 13:47:12 +0200640
Yann Rouillard7b246702013-05-27 22:44:28 +0200641 def _format_hex(self, addr, fieldsize=None, fullhex=False, lead0x=True,
642 alternate=False):
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300643 """ Format an address into a hexadecimal string.
Eli Benderskyd62928d2011-09-09 10:05:57 +0300644
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300645 fieldsize:
646 Size of the hexadecimal field (with leading zeros to fit the
647 address into. For example with fieldsize=8, the format will
648 be %08x
649 If None, the minimal required field size will be used.
650
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300651 fullhex:
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800652 If True, override fieldsize to set it to the maximal size
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300653 needed for the elfclass
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300654
655 lead0x:
656 If True, leading 0x is added
Yann Rouillard7b246702013-05-27 22:44:28 +0200657
658 alternate:
659 If True, override lead0x to emulate the alternate
Yann Rouillardde179382013-05-29 23:47:50 +0200660 hexadecimal form specified in format string with the #
Yann Rouillard7b246702013-05-27 22:44:28 +0200661 character: only non-zero values are prefixed with 0x.
662 This form is used by readelf.
Eli Benderskyd62928d2011-09-09 10:05:57 +0300663 """
Yann Rouillard7b246702013-05-27 22:44:28 +0200664 if alternate:
665 if addr == 0:
666 lead0x = False
667 else:
668 lead0x = True
669 fieldsize -= 2
670
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300671 s = '0x' if lead0x else ''
672 if fullhex:
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300673 fieldsize = 8 if self.elffile.elfclass == 32 else 16
674 if fieldsize is None:
675 field = '%x'
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300676 else:
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300677 field = '%' + '0%sx' % fieldsize
678 return s + field % addr
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800679
Yann Rouillardde179382013-05-29 23:47:50 +0200680 def _print_version_section_header(self, version_section, name, lead0x=True,
681 indent=1):
682 """ Print a section header of one version related section (versym,
683 verneed or verdef) with some options to accomodate readelf
684 little differences between each header (e.g. indentation
685 and 0x prefixing).
Yann Rouillard7b246702013-05-27 22:44:28 +0200686 """
687 if hasattr(version_section, 'num_versions'):
688 num_entries = version_section.num_versions()
689 else:
690 num_entries = version_section.num_symbols()
691
692 self._emitline("\n%s section '%s' contains %s entries:" %
693 (name, bytes2str(version_section.name), num_entries))
Yann Rouillardde179382013-05-29 23:47:50 +0200694 self._emitline('%sAddr: %s Offset: %s Link: %i (%s)' % (
695 ' ' * indent,
696 self._format_hex(
697 version_section['sh_addr'], fieldsize=16, lead0x=lead0x),
698 self._format_hex(
699 version_section['sh_offset'], fieldsize=6, lead0x=True),
700 version_section['sh_link'],
701 bytes2str(
702 self.elffile.get_section(version_section['sh_link']).name)
703 )
704 )
Yann Rouillard7b246702013-05-27 22:44:28 +0200705
706 def _init_versioninfo(self):
707 """ Search and initialize informations about version related sections
708 and the kind of versioning used (GNU or Solaris).
709 """
710 if self._versioninfo is not None:
711 return
712
Yann Rouillardde179382013-05-29 23:47:50 +0200713 self._versioninfo = {'versym': None, 'verdef': None,
714 'verneed': None, 'type': None}
Yann Rouillard7b246702013-05-27 22:44:28 +0200715
716 for section in self.elffile.iter_sections():
Yann Rouillard478a4592013-05-31 21:01:25 +0200717 if isinstance(section, GNUVerSymSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200718 self._versioninfo['versym'] = section
Yann Rouillard478a4592013-05-31 21:01:25 +0200719 elif isinstance(section, GNUVerDefSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200720 self._versioninfo['verdef'] = section
Yann Rouillard478a4592013-05-31 21:01:25 +0200721 elif isinstance(section, GNUVerNeedSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200722 self._versioninfo['verneed'] = section
723 elif isinstance(section, DynamicSection):
724 for tag in section.iter_tags():
725 if tag['d_tag'] == 'DT_VERSYM':
726 self._versioninfo['type'] = 'GNU'
Yann Rouillardde179382013-05-29 23:47:50 +0200727 break
Yann Rouillard7b246702013-05-27 22:44:28 +0200728
729 if not self._versioninfo['type'] and (
730 self._versioninfo['verneed'] or self._versioninfo['verdef']):
731 self._versioninfo['type'] = 'Solaris'
732
Yann Rouillard7b246702013-05-27 22:44:28 +0200733 def _symbol_version(self, nsym):
Yann Rouillardde179382013-05-29 23:47:50 +0200734 """ Return a dict containing information on the
Yann Rouillard7b246702013-05-27 22:44:28 +0200735 or None if no version information is available
736 """
737 self._init_versioninfo()
Yann Rouillardde179382013-05-29 23:47:50 +0200738
Yann Rouillard7b246702013-05-27 22:44:28 +0200739 symbol_version = dict.fromkeys(('index', 'name', 'filename', 'hidden'))
740
741 if (not self._versioninfo['versym'] or
742 nsym >= self._versioninfo['versym'].num_symbols()):
743 return None
744
745 symbol = self._versioninfo['versym'].get_symbol(nsym)
746 index = symbol.entry['ndx']
747 if not index in ('VER_NDX_LOCAL', 'VER_NDX_GLOBAL'):
748 index = int(index)
749
750 if self._versioninfo['type'] == 'GNU':
Yann Rouillardde179382013-05-29 23:47:50 +0200751 # In GNU versioning mode, the highest bit is used to
Yann Rouillard7b246702013-05-27 22:44:28 +0200752 # store wether the symbol is hidden or not
753 if index & 0x8000:
Yann Rouillardde179382013-05-29 23:47:50 +0200754 index &= ~0x8000
Yann Rouillard7b246702013-05-27 22:44:28 +0200755 symbol_version['hidden'] = True
756
Yann Rouillardde179382013-05-29 23:47:50 +0200757 if (self._versioninfo['verdef'] and
Yann Rouillard7b246702013-05-27 22:44:28 +0200758 index <= self._versioninfo['verdef'].num_versions()):
759 _, verdaux_iter = \
760 self._versioninfo['verdef'].get_version(index)
761 symbol_version['name'] = bytes2str(next(verdaux_iter).name)
762 else:
763 verneed, vernaux = \
764 self._versioninfo['verneed'].get_version(index)
765 symbol_version['name'] = bytes2str(vernaux.name)
766 symbol_version['filename'] = bytes2str(verneed.name)
767
768 symbol_version['index'] = index
769 return symbol_version
770
eliben54e39b22011-09-19 13:10:57 +0300771 def _section_from_spec(self, spec):
772 """ Retrieve a section given a "spec" (either number or name).
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300773 Return None if no such section exists in the file.
774 """
775 try:
776 num = int(spec)
eliben54e39b22011-09-19 13:10:57 +0300777 if num < self.elffile.num_sections():
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800778 return self.elffile.get_section(num)
eliben54e39b22011-09-19 13:10:57 +0300779 else:
780 return None
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300781 except ValueError:
782 # Not a number. Must be a name then
Eli Bendersky79271e92012-01-27 10:25:47 +0200783 return self.elffile.get_section_by_name(str2bytes(spec))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300784
Eli Benderskyadf707a2011-09-23 15:23:41 +0300785 def _note_relocs_for_section(self, section):
786 """ If there are relocation sections pointing to the givne section,
787 emit a note about it.
788 """
789 for relsec in self.elffile.iter_sections():
790 if isinstance(relsec, RelocationSection):
791 info_idx = relsec['sh_info']
792 if self.elffile.get_section(info_idx) == section:
793 self._emitline(' Note: This section has relocations against it, but these have NOT been applied to this dump.')
794 return
795
eliben0fc47af2011-10-02 13:47:12 +0200796 def _init_dwarfinfo(self):
797 """ Initialize the DWARF info contained in the file and assign it to
798 self._dwarfinfo.
799 Leave self._dwarfinfo at None if no DWARF info was found in the file
800 """
801 if self._dwarfinfo is not None:
802 return
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800803
eliben0fc47af2011-10-02 13:47:12 +0200804 if self.elffile.has_dwarf_info():
805 self._dwarfinfo = self.elffile.get_dwarf_info()
806 else:
807 self._dwarfinfo = None
808
809 def _dump_debug_info(self):
810 """ Dump the debugging info section.
811 """
eliben985c2c12011-11-14 17:53:23 +0200812 self._emitline('Contents of the .debug_info section:\n')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800813
eliben0fc47af2011-10-02 13:47:12 +0200814 # Offset of the .debug_info section in the stream
Eli Bendersky149315a2011-11-24 08:12:37 +0200815 section_offset = self._dwarfinfo.debug_info_sec.global_offset
Eli Bendersky6062bf72011-11-23 06:54:40 +0200816
eliben0fc47af2011-10-02 13:47:12 +0200817 for cu in self._dwarfinfo.iter_CUs():
eliben985c2c12011-11-14 17:53:23 +0200818 self._emitline(' Compilation Unit @ offset %s:' %
Eli Bendersky149315a2011-11-24 08:12:37 +0200819 self._format_hex(cu.cu_offset))
eliben0fc47af2011-10-02 13:47:12 +0200820 self._emitline(' Length: %s (%s)' % (
821 self._format_hex(cu['unit_length']),
822 '%s-bit' % cu.dwarf_format()))
823 self._emitline(' Version: %s' % cu['version']),
Eli Bendersky7eba7182013-03-30 17:23:36 -0700824 self._emitline(' Abbrev Offset: %s' % (
825 self._format_hex(cu['debug_abbrev_offset']))),
eliben0fc47af2011-10-02 13:47:12 +0200826 self._emitline(' Pointer Size: %s' % cu['address_size'])
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800827
828 # The nesting depth of each DIE within the tree of DIEs must be
eliben0fc47af2011-10-02 13:47:12 +0200829 # displayed. To implement this, a counter is incremented each time
830 # the current DIE has children, and decremented when a null die is
831 # encountered. Due to the way the DIE tree is serialized, this will
832 # correctly reflect the nesting depth
833 #
834 die_depth = 0
835 for die in cu.iter_DIEs():
Eli Bendersky9aec9d82013-03-30 16:39:30 -0700836 self._emitline(' <%s><%x>: Abbrev Number: %s%s' % (
elibenaee11d22011-10-26 10:42:34 +0200837 die_depth,
Eli Bendersky149315a2011-11-24 08:12:37 +0200838 die.offset,
elibenaee11d22011-10-26 10:42:34 +0200839 die.abbrev_code,
Eli Bendersky9aec9d82013-03-30 16:39:30 -0700840 (' (%s)' % die.tag) if not die.is_null() else ''))
841 if die.is_null():
842 die_depth -= 1
843 continue
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800844
Eli Bendersky79271e92012-01-27 10:25:47 +0200845 for attr in itervalues(die.attributes):
Eli Bendersky871ad0c2011-12-16 08:13:48 +0200846 name = attr.name
847 # Unknown attribute values are passed-through as integers
848 if isinstance(name, int):
849 name = 'Unknown AT value: %x' % name
elibenaee11d22011-10-26 10:42:34 +0200850 self._emitline(' <%2x> %-18s: %s' % (
Eli Bendersky149315a2011-11-24 08:12:37 +0200851 attr.offset,
Eli Bendersky871ad0c2011-12-16 08:13:48 +0200852 name,
eliben3bc9c342011-10-26 13:10:58 +0200853 describe_attr_value(
Eli Bendersky5be3be82011-10-27 14:28:12 +0200854 attr, die, section_offset)))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800855
eliben0fc47af2011-10-02 13:47:12 +0200856 if die.has_children:
857 die_depth += 1
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800858
Eli Benderskyf5670e82011-11-24 09:05:44 +0200859 self._emitline()
eliben0fc47af2011-10-02 13:47:12 +0200860
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200861 def _dump_debug_line_programs(self):
862 """ Dump the (decoded) line programs from .debug_line
863 The programs are dumped in the order of the CUs they belong to.
864 """
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200865 self._emitline('Decoded dump of debug contents of section .debug_line:\n')
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200866
867 for cu in self._dwarfinfo.iter_CUs():
868 lineprogram = self._dwarfinfo.line_program_for_CU(cu)
869
Eli Bendersky7eba7182013-03-30 17:23:36 -0700870 cu_filename = bytes2str(lineprogram['file_entry'][0].name)
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200871 if len(lineprogram['include_directory']) > 0:
Eli Bendersky7eba7182013-03-30 17:23:36 -0700872 dir_index = lineprogram['file_entry'][0].dir_index
873 if dir_index > 0:
874 dir = lineprogram['include_directory'][dir_index - 1]
875 else:
Eli Benderskyccdb5542013-03-31 14:19:21 -0700876 dir = b'.'
Eli Bendersky7eba7182013-03-30 17:23:36 -0700877 cu_filename = '%s/%s' % (bytes2str(dir), cu_filename)
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200878
879 self._emitline('CU: %s:' % cu_filename)
880 self._emitline('File name Line number Starting address')
881
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200882 # Print each state's file, line and address information. For some
883 # instructions other output is needed to be compatible with
884 # readelf.
885 for entry in lineprogram.get_entries():
886 state = entry.state
887 if state is None:
888 # Special handling for commands that don't set a new state
889 if entry.command == DW_LNS_set_file:
890 file_entry = lineprogram['file_entry'][entry.args[0] - 1]
891 if file_entry.dir_index == 0:
892 # current directory
893 self._emitline('\n./%s:[++]' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200894 bytes2str(file_entry.name)))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200895 else:
896 self._emitline('\n%s/%s:' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200897 bytes2str(lineprogram['include_directory'][file_entry.dir_index - 1]),
898 bytes2str(file_entry.name)))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200899 elif entry.command == DW_LNE_define_file:
900 self._emitline('%s:' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200901 bytes2str(lineprogram['include_directory'][entry.args[0].dir_index])))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200902 elif not state.end_sequence:
903 # readelf doesn't print the state after end_sequence
904 # instructions. I think it's a bug but to be compatible
905 # I don't print them too.
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200906 self._emitline('%-35s %11d %18s' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200907 bytes2str(lineprogram['file_entry'][state.file - 1].name),
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200908 state.line,
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800909 '0' if state.address == 0 else
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200910 self._format_hex(state.address)))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200911 if entry.command == DW_LNS_copy:
912 # Another readelf oddity...
913 self._emitline()
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200914
Eli Bendersky7241ff02011-12-12 06:40:34 +0200915 def _dump_debug_frames(self):
916 """ Dump the raw frame information from .debug_frame
917 """
Eli Bendersky47a47112011-12-14 06:54:09 +0200918 if not self._dwarfinfo.has_CFI():
919 return
Eli Bendersky7241ff02011-12-12 06:40:34 +0200920 self._emitline('Contents of the .debug_frame section:')
921
922 for entry in self._dwarfinfo.CFI_entries():
923 if isinstance(entry, CIE):
Eli Benderskycb4eb992013-11-28 09:54:41 -0800924 self._emitline('\n%08x %s %s CIE' % (
925 entry.offset,
926 self._format_hex(entry['length'], fullhex=True, lead0x=False),
927 self._format_hex(entry['CIE_id'], fullhex=True, lead0x=False)))
Eli Bendersky7241ff02011-12-12 06:40:34 +0200928 self._emitline(' Version: %d' % entry['version'])
Eli Bendersky79271e92012-01-27 10:25:47 +0200929 self._emitline(' Augmentation: "%s"' % bytes2str(entry['augmentation']))
Eli Bendersky7241ff02011-12-12 06:40:34 +0200930 self._emitline(' Code alignment factor: %u' % entry['code_alignment_factor'])
931 self._emitline(' Data alignment factor: %d' % entry['data_alignment_factor'])
932 self._emitline(' Return address column: %d' % entry['return_address_register'])
Eli Bendersky47a47112011-12-14 06:54:09 +0200933 self._emitline()
Eli Bendersky7241ff02011-12-12 06:40:34 +0200934 else: # FDE
Eli Benderskycb4eb992013-11-28 09:54:41 -0800935 self._emitline('\n%08x %s %s FDE cie=%08x pc=%s..%s' % (
Eli Bendersky7241ff02011-12-12 06:40:34 +0200936 entry.offset,
Eli Benderskycb4eb992013-11-28 09:54:41 -0800937 self._format_hex(entry['length'], fullhex=True, lead0x=False),
938 self._format_hex(entry['CIE_pointer'], fullhex=True, lead0x=False),
Eli Bendersky7241ff02011-12-12 06:40:34 +0200939 entry.cie.offset,
Eli Benderskycb4eb992013-11-28 09:54:41 -0800940 self._format_hex(entry['initial_location'], fullhex=True, lead0x=False),
941 self._format_hex(
942 entry['initial_location'] + entry['address_range'],
943 fullhex=True, lead0x=False)))
Eli Bendersky7241ff02011-12-12 06:40:34 +0200944
Eli Bendersky47a47112011-12-14 06:54:09 +0200945 self._emit(describe_CFI_instructions(entry))
946 self._emitline()
Eli Bendersky7241ff02011-12-12 06:40:34 +0200947
Eli Bendersky8670bb32011-12-15 16:11:06 +0200948 def _dump_debug_frames_interp(self):
949 """ Dump the interpreted (decoded) frame information from .debug_frame
950 """
951 if not self._dwarfinfo.has_CFI():
952 return
953
954 self._emitline('Contents of the .debug_frame section:')
955
956 for entry in self._dwarfinfo.CFI_entries():
957 if isinstance(entry, CIE):
Eli Benderskycb4eb992013-11-28 09:54:41 -0800958 self._emitline('\n%08x %s %s CIE "%s" cf=%d df=%d ra=%d' % (
Eli Bendersky8670bb32011-12-15 16:11:06 +0200959 entry.offset,
Eli Benderskycb4eb992013-11-28 09:54:41 -0800960 self._format_hex(entry['length'], fullhex=True, lead0x=False),
961 self._format_hex(entry['CIE_id'], fullhex=True, lead0x=False),
Eli Bendersky79271e92012-01-27 10:25:47 +0200962 bytes2str(entry['augmentation']),
Eli Bendersky8670bb32011-12-15 16:11:06 +0200963 entry['code_alignment_factor'],
964 entry['data_alignment_factor'],
965 entry['return_address_register']))
Eli Bendersky4682c962011-12-16 06:39:49 +0200966 ra_regnum = entry['return_address_register']
Eli Bendersky8670bb32011-12-15 16:11:06 +0200967 else: # FDE
Eli Benderskycb4eb992013-11-28 09:54:41 -0800968 self._emitline('\n%08x %s %s FDE cie=%08x pc=%s..%s' % (
Eli Bendersky8670bb32011-12-15 16:11:06 +0200969 entry.offset,
Eli Benderskycb4eb992013-11-28 09:54:41 -0800970 self._format_hex(entry['length'], fullhex=True, lead0x=False),
971 self._format_hex(entry['CIE_pointer'], fullhex=True, lead0x=False),
Eli Bendersky8670bb32011-12-15 16:11:06 +0200972 entry.cie.offset,
Eli Benderskycb4eb992013-11-28 09:54:41 -0800973 self._format_hex(entry['initial_location'], fullhex=True, lead0x=False),
974 self._format_hex(entry['initial_location'] + entry['address_range'],
975 fullhex=True, lead0x=False)))
Eli Bendersky4682c962011-12-16 06:39:49 +0200976 ra_regnum = entry.cie['return_address_register']
Eli Bendersky8670bb32011-12-15 16:11:06 +0200977
978 # Print the heading row for the decoded table
979 self._emit(' LOC')
980 self._emit(' ' if entry.structs.address_size == 4 else ' ')
Eli Bendersky4682c962011-12-16 06:39:49 +0200981 self._emit(' CFA ')
Eli Bendersky8670bb32011-12-15 16:11:06 +0200982
Eli Bendersky4682c962011-12-16 06:39:49 +0200983 # Decode the table nad look at the registers it describes.
984 # We build reg_order here to match readelf's order. In particular,
985 # registers are sorted by their number, and the register matching
986 # ra_regnum is always listed last with a special heading.
Eli Bendersky8670bb32011-12-15 16:11:06 +0200987 decoded_table = entry.get_decoded()
Eli Bendersky4682c962011-12-16 06:39:49 +0200988 reg_order = sorted(ifilter(
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800989 lambda r: r != ra_regnum,
Eli Bendersky4682c962011-12-16 06:39:49 +0200990 decoded_table.reg_order))
991
992 # Headings for the registers
993 for regnum in reg_order:
Eli Bendersky8670bb32011-12-15 16:11:06 +0200994 self._emit('%-6s' % describe_reg_name(regnum))
995 self._emitline('ra ')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800996
Eli Bendersky4682c962011-12-16 06:39:49 +0200997 # Now include ra_regnum in reg_order to print its values similarly
998 # to the other registers.
999 reg_order.append(ra_regnum)
1000 for line in decoded_table.table:
1001 self._emit(self._format_hex(
1002 line['pc'], fullhex=True, lead0x=False))
1003 self._emit(' %-9s' % describe_CFI_CFA_rule(line['cfa']))
Eli Bendersky8670bb32011-12-15 16:11:06 +02001004
Eli Bendersky4682c962011-12-16 06:39:49 +02001005 for regnum in reg_order:
1006 if regnum in line:
1007 s = describe_CFI_register_rule(line[regnum])
1008 else:
1009 s = 'u'
1010 self._emit('%-6s' % s)
1011 self._emitline()
1012 self._emitline()
Eli Bendersky8670bb32011-12-15 16:11:06 +02001013
Eli Bendersky26de2ac2011-09-13 06:50:28 +03001014 def _emit(self, s=''):
Eli Bendersky933f6992011-09-09 08:11:06 +03001015 """ Emit an object to output
1016 """
1017 self.output.write(str(s))
Eli Benderskyd62928d2011-09-09 10:05:57 +03001018
Eli Bendersky26de2ac2011-09-13 06:50:28 +03001019 def _emitline(self, s=''):
Eli Bendersky933f6992011-09-09 08:11:06 +03001020 """ Emit an object to output, followed by a newline
1021 """
1022 self.output.write(str(s) + '\n')
1023
1024
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001025SCRIPT_DESCRIPTION = 'Display information about the contents of ELF format files'
1026VERSION_STRING = '%%prog: based on pyelftools %s' % __version__
1027
1028
Eli Bendersky0193fb82011-11-26 16:16:16 +02001029def main(stream=None):
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001030 # parse the command-line arguments and invoke ReadElf
Eli Bendersky40eb1702011-09-16 16:59:52 +03001031 optparser = OptionParser(
Eli Benderskyecde41b2011-09-16 17:16:20 +03001032 usage='usage: %prog [options] <elf-file>',
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001033 description=SCRIPT_DESCRIPTION,
Eli Bendersky40eb1702011-09-16 16:59:52 +03001034 add_help_option=False, # -h is a real option of readelf
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001035 prog='readelf.py',
1036 version=VERSION_STRING)
Mike Frysinger5699e182013-03-23 02:47:32 -04001037 optparser.add_option('-d', '--dynamic',
1038 action='store_true', dest='show_dynamic_tags',
1039 help='Display the dynamic section')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001040 optparser.add_option('-H', '--help',
1041 action='store_true', dest='help',
1042 help='Display this information')
1043 optparser.add_option('-h', '--file-header',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001044 action='store_true', dest='show_file_header',
1045 help='Display the ELF file header')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001046 optparser.add_option('-l', '--program-headers', '--segments',
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001047 action='store_true', dest='show_program_header',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001048 help='Display the program headers')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001049 optparser.add_option('-S', '--section-headers', '--sections',
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001050 action='store_true', dest='show_section_header',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001051 help="Display the sections' headers")
Eli Bendersky40eb1702011-09-16 16:59:52 +03001052 optparser.add_option('-e', '--headers',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001053 action='store_true', dest='show_all_headers',
1054 help='Equivalent to: -h -l -S')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001055 optparser.add_option('-s', '--symbols', '--syms',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001056 action='store_true', dest='show_symbols',
1057 help='Display the symbol table')
Eli Bendersky84066b22011-09-20 06:48:52 +03001058 optparser.add_option('-r', '--relocs',
1059 action='store_true', dest='show_relocs',
1060 help='Display the relocations (if present)')
Eli Benderskyc4a4c072011-09-17 15:28:28 +03001061 optparser.add_option('-x', '--hex-dump',
1062 action='store', dest='show_hex_dump', metavar='<number|name>',
1063 help='Dump the contents of section <number|name> as bytes')
Eli Bendersky53e86db2011-09-18 06:04:30 +03001064 optparser.add_option('-p', '--string-dump',
1065 action='store', dest='show_string_dump', metavar='<number|name>',
1066 help='Dump the contents of section <number|name> as strings')
Yann Rouillard7b246702013-05-27 22:44:28 +02001067 optparser.add_option('-V', '--version-info',
1068 action='store_true', dest='show_version_info',
1069 help='Display the version sections (if present)')
eliben0fc47af2011-10-02 13:47:12 +02001070 optparser.add_option('--debug-dump',
Eli Bendersky1a516a32011-12-22 15:22:00 +02001071 action='store', dest='debug_dump_what', metavar='<what>',
1072 help=(
1073 'Display the contents of DWARF debug sections. <what> can ' +
1074 'one of {info,decodedline,frames,frames-interp}'))
Eli Bendersky53e86db2011-09-18 06:04:30 +03001075
Eli Bendersky933f6992011-09-09 08:11:06 +03001076 options, args = optparser.parse_args()
1077
Eli Bendersky40eb1702011-09-16 16:59:52 +03001078 if options.help or len(args) == 0:
1079 optparser.print_help()
1080 sys.exit(0)
1081
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001082 if options.show_all_headers:
1083 do_file_header = do_section_header = do_program_header = True
1084 else:
1085 do_file_header = options.show_file_header
1086 do_section_header = options.show_section_header
1087 do_program_header = options.show_program_header
1088
Eli Bendersky933f6992011-09-09 08:11:06 +03001089 with open(args[0], 'rb') as file:
1090 try:
Eli Bendersky0193fb82011-11-26 16:16:16 +02001091 readelf = ReadElf(file, stream or sys.stdout)
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001092 if do_file_header:
1093 readelf.display_file_header()
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001094 if do_section_header:
1095 readelf.display_section_headers(
1096 show_heading=not do_file_header)
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +03001097 if do_program_header:
1098 readelf.display_program_headers(
1099 show_heading=not do_file_header)
Mike Frysinger5699e182013-03-23 02:47:32 -04001100 if options.show_dynamic_tags:
1101 readelf.display_dynamic_tags()
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001102 if options.show_symbols:
1103 readelf.display_symbol_tables()
Eli Bendersky84066b22011-09-20 06:48:52 +03001104 if options.show_relocs:
1105 readelf.display_relocations()
Yann Rouillard7b246702013-05-27 22:44:28 +02001106 if options.show_version_info:
1107 readelf.display_version_info()
Eli Benderskyc4a4c072011-09-17 15:28:28 +03001108 if options.show_hex_dump:
1109 readelf.display_hex_dump(options.show_hex_dump)
Eli Bendersky53e86db2011-09-18 06:04:30 +03001110 if options.show_string_dump:
1111 readelf.display_string_dump(options.show_string_dump)
Eli Bendersky5ec2dde2011-12-04 07:05:31 +02001112 if options.debug_dump_what:
1113 readelf.display_debug_dump(options.debug_dump_what)
Eli Bendersky933f6992011-09-09 08:11:06 +03001114 except ELFError as ex:
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001115 sys.stderr.write('ELF error: %s\n' % ex)
Eli Bendersky933f6992011-09-09 08:11:06 +03001116 sys.exit(1)
1117
1118
Eli Bendersky0193fb82011-11-26 16:16:16 +02001119def profile_main():
1120 # Run 'main' redirecting its output to readelfout.txt
1121 # Saves profiling information in readelf.profile
1122 PROFFILE = 'readelf.profile'
1123 import cProfile
1124 cProfile.run('main(open("readelfout.txt", "w"))', PROFFILE)
1125
1126 # Dig in some profiling stats
1127 import pstats
1128 p = pstats.Stats(PROFFILE)
1129 p.sort_stats('cumulative').print_stats(25)
1130
1131
Eli Bendersky933f6992011-09-09 08:11:06 +03001132#-------------------------------------------------------------------------------
1133if __name__ == '__main__':
Eli Bendersky4f4d80c2011-11-26 16:49:27 +02001134 main()
1135 #profile_main()
Eli Bendersky0193fb82011-11-26 16:16:16 +02001136
Eli Bendersky933f6992011-09-09 08:11:06 +03001137