blob: 06a6edd0c62744bd5e1245164eb1da717da32477 [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 Bendersky149315a2011-11-24 08:12:37 +020042from elftools.dwarf.dwarfinfo import DWARFInfo
Eli Bendersky3501f9f2011-12-09 12:29:06 +020043from elftools.dwarf.descriptions import (
Eli Bendersky4682c962011-12-16 06:39:49 +020044 describe_reg_name, describe_attr_value, set_global_machine_arch,
45 describe_CFI_instructions, describe_CFI_register_rule,
46 describe_CFI_CFA_rule,
47 )
Eli Benderskybf83b1b2011-12-06 06:48:10 +020048from elftools.dwarf.constants import (
49 DW_LNS_copy, DW_LNS_set_file, DW_LNE_define_file)
Eli Bendersky7241ff02011-12-12 06:40:34 +020050from elftools.dwarf.callframe import CIE, FDE
Eli Bendersky933f6992011-09-09 08:11:06 +030051
52
53class ReadElf(object):
54 """ display_* methods are used to emit output into the output stream
55 """
56 def __init__(self, file, output):
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080057 """ file:
Eli Bendersky933f6992011-09-09 08:11:06 +030058 stream object with the ELF file to read
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080059
Eli Bendersky933f6992011-09-09 08:11:06 +030060 output:
61 output stream to write to
62 """
63 self.elffile = ELFFile(file)
64 self.output = output
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080065
eliben0fc47af2011-10-02 13:47:12 +020066 # Lazily initialized if a debug dump is requested
67 self._dwarfinfo = None
Eli Bendersky933f6992011-09-09 08:11:06 +030068
Yann Rouillard7b246702013-05-27 22:44:28 +020069 self._versioninfo = None
70
Eli Bendersky933f6992011-09-09 08:11:06 +030071 def display_file_header(self):
72 """ Display the ELF file header
73 """
74 self._emitline('ELF Header:')
75 self._emit(' Magic: ')
Eli Bendersky79271e92012-01-27 10:25:47 +020076 self._emitline(' '.join('%2.2x' % byte2int(b)
Eli Bendersky933f6992011-09-09 08:11:06 +030077 for b in self.elffile.e_ident_raw))
78 header = self.elffile.header
79 e_ident = header['e_ident']
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080080 self._emitline(' Class: %s' %
Eli Bendersky933f6992011-09-09 08:11:06 +030081 describe_ei_class(e_ident['EI_CLASS']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080082 self._emitline(' Data: %s' %
Eli Bendersky933f6992011-09-09 08:11:06 +030083 describe_ei_data(e_ident['EI_DATA']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080084 self._emitline(' Version: %s' %
Eli Bendersky933f6992011-09-09 08:11:06 +030085 describe_ei_version(e_ident['EI_VERSION']))
86 self._emitline(' OS/ABI: %s' %
87 describe_ei_osabi(e_ident['EI_OSABI']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080088 self._emitline(' ABI Version: %d' %
Eli Bendersky933f6992011-09-09 08:11:06 +030089 e_ident['EI_ABIVERSION'])
90 self._emitline(' Type: %s' %
91 describe_e_type(header['e_type']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080092 self._emitline(' Machine: %s' %
Eli Benderskyde8d71e2011-09-09 08:22:35 +030093 describe_e_machine(header['e_machine']))
94 self._emitline(' Version: %s' %
95 describe_e_version_numeric(header['e_version']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080096 self._emitline(' Entry point address: %s' %
Eli Bendersky26de2ac2011-09-13 06:50:28 +030097 self._format_hex(header['e_entry']))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080098 self._emit(' Start of program headers: %s' %
Eli Benderskyd62928d2011-09-09 10:05:57 +030099 header['e_phoff'])
100 self._emitline(' (bytes into file)')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800101 self._emit(' Start of section headers: %s' %
Eli Benderskyd62928d2011-09-09 10:05:57 +0300102 header['e_shoff'])
103 self._emitline(' (bytes into file)')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800104 self._emitline(' Flags: %s' %
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300105 self._format_hex(header['e_flags']))
Eli Benderskyd62928d2011-09-09 10:05:57 +0300106 self._emitline(' Size of this header: %s (bytes)' %
107 header['e_ehsize'])
108 self._emitline(' Size of program headers: %s (bytes)' %
109 header['e_phentsize'])
110 self._emitline(' Number of program headers: %s' %
111 header['e_phnum'])
112 self._emitline(' Size of section headers: %s (bytes)' %
113 header['e_shentsize'])
114 self._emitline(' Number of section headers: %s' %
115 header['e_shnum'])
116 self._emitline(' Section header string table index: %s' %
117 header['e_shstrndx'])
Eli Bendersky933f6992011-09-09 08:11:06 +0300118
Eli Bendersky0b27ba42011-09-17 06:44:02 +0300119 def display_program_headers(self, show_heading=True):
120 """ Display the ELF program headers.
121 If show_heading is True, displays the heading for this information
122 (Elf file type is...)
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300123 """
124 self._emitline()
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +0300125 if self.elffile.num_segments() == 0:
126 self._emitline('There are no program headers in this file.')
127 return
128
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300129 elfheader = self.elffile.header
Eli Bendersky0b27ba42011-09-17 06:44:02 +0300130 if show_heading:
131 self._emitline('Elf file type is %s' %
132 describe_e_type(elfheader['e_type']))
133 self._emitline('Entry point is %s' %
134 self._format_hex(elfheader['e_entry']))
135 # readelf weirness - why isn't e_phoff printed as hex? (for section
136 # headers, it is...)
137 self._emitline('There are %s program headers, starting at offset %s' % (
138 elfheader['e_phnum'], elfheader['e_phoff']))
139 self._emitline()
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300140
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +0300141 self._emitline('Program Headers:')
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300142
143 # Now comes the table of program headers with their attributes. Note
144 # that due to different formatting constraints of 32-bit and 64-bit
145 # addresses, there are some conditions on elfclass here.
146 #
147 # First comes the table heading
148 #
149 if self.elffile.elfclass == 32:
150 self._emitline(' Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align')
151 else:
152 self._emitline(' Type Offset VirtAddr PhysAddr')
153 self._emitline(' FileSiz MemSiz Flags Align')
154
155 # Now the entries
156 #
157 for segment in self.elffile.iter_segments():
158 self._emit(' %-14s ' % describe_p_type(segment['p_type']))
159
160 if self.elffile.elfclass == 32:
161 self._emitline('%s %s %s %s %s %-3s %s' % (
162 self._format_hex(segment['p_offset'], fieldsize=6),
163 self._format_hex(segment['p_vaddr'], fullhex=True),
164 self._format_hex(segment['p_paddr'], fullhex=True),
165 self._format_hex(segment['p_filesz'], fieldsize=5),
166 self._format_hex(segment['p_memsz'], fieldsize=5),
167 describe_p_flags(segment['p_flags']),
168 self._format_hex(segment['p_align'])))
Eli Benderskya41c3c02011-09-14 06:18:28 +0300169 else: # 64
170 self._emitline('%s %s %s' % (
171 self._format_hex(segment['p_offset'], fullhex=True),
172 self._format_hex(segment['p_vaddr'], fullhex=True),
173 self._format_hex(segment['p_paddr'], fullhex=True)))
174 self._emitline(' %s %s %-3s %s' % (
175 self._format_hex(segment['p_filesz'], fullhex=True),
176 self._format_hex(segment['p_memsz'], fullhex=True),
177 describe_p_flags(segment['p_flags']),
178 # lead0x set to False for p_align, to mimic readelf.
179 # No idea why the difference from 32-bit mode :-|
180 self._format_hex(segment['p_align'], lead0x=False)))
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300181
Eli Bendersky3f4de3e2011-09-14 05:58:06 +0300182 if isinstance(segment, InterpSegment):
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800183 self._emitline(' [Requesting program interpreter: %s]' %
Eli Bendersky79271e92012-01-27 10:25:47 +0200184 bytes2str(segment.get_interp_name()))
Eli Bendersky3f4de3e2011-09-14 05:58:06 +0300185
Eli Bendersky58585b02011-09-15 07:07:54 +0300186 # Sections to segments mapping
187 #
188 if self.elffile.num_sections() == 0:
189 # No sections? We're done
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800190 return
Eli Bendersky58585b02011-09-15 07:07:54 +0300191
192 self._emitline('\n Section to Segment mapping:')
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +0300193 self._emitline(' Segment Sections...')
Eli Bendersky58585b02011-09-15 07:07:54 +0300194
195 for nseg, segment in enumerate(self.elffile.iter_segments()):
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +0300196 self._emit(' %2.2d ' % nseg)
Eli Bendersky58585b02011-09-15 07:07:54 +0300197
198 for section in self.elffile.iter_sections():
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800199 if ( not section.is_null() and
Eli Bendersky58585b02011-09-15 07:07:54 +0300200 segment.section_in_segment(section)):
Eli Bendersky79271e92012-01-27 10:25:47 +0200201 self._emit('%s ' % bytes2str(section.name))
Eli Bendersky58585b02011-09-15 07:07:54 +0300202
203 self._emitline('')
204
Eli Bendersky0b27ba42011-09-17 06:44:02 +0300205 def display_section_headers(self, show_heading=True):
Eli Bendersky377bd862011-09-16 11:10:44 +0300206 """ Display the ELF section headers
207 """
208 elfheader = self.elffile.header
Eli Bendersky0b27ba42011-09-17 06:44:02 +0300209 if show_heading:
210 self._emitline('There are %s section headers, starting at offset %s' % (
211 elfheader['e_shnum'], self._format_hex(elfheader['e_shoff'])))
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300212
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +0300213 self._emitline('\nSection Header%s:' % (
Eli Bendersky377bd862011-09-16 11:10:44 +0300214 's' if elfheader['e_shnum'] > 1 else ''))
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300215
Eli Bendersky377bd862011-09-16 11:10:44 +0300216 # Different formatting constraints of 32-bit and 64-bit addresses
217 #
218 if self.elffile.elfclass == 32:
219 self._emitline(' [Nr] Name Type Addr Off Size ES Flg Lk Inf Al')
220 else:
221 self._emitline(' [Nr] Name Type Address Offset')
222 self._emitline(' Size EntSize Flags Link Info Align')
223
224 # Now the entries
225 #
226 for nsec, section in enumerate(self.elffile.iter_sections()):
227 self._emit(' [%2u] %-17.17s %-15.15s ' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200228 nsec, bytes2str(section.name), describe_sh_type(section['sh_type'])))
Eli Bendersky377bd862011-09-16 11:10:44 +0300229
230 if self.elffile.elfclass == 32:
231 self._emitline('%s %s %s %s %3s %2s %3s %2s' % (
232 self._format_hex(section['sh_addr'], fieldsize=8, lead0x=False),
233 self._format_hex(section['sh_offset'], fieldsize=6, lead0x=False),
234 self._format_hex(section['sh_size'], fieldsize=6, lead0x=False),
235 self._format_hex(section['sh_entsize'], fieldsize=2, lead0x=False),
236 describe_sh_flags(section['sh_flags']),
237 section['sh_link'], section['sh_info'],
238 section['sh_addralign']))
239 else: # 64
240 self._emitline(' %s %s' % (
241 self._format_hex(section['sh_addr'], fullhex=True, lead0x=False),
242 self._format_hex(section['sh_offset'],
243 fieldsize=16 if section['sh_offset'] > 0xffffffff else 8,
244 lead0x=False)))
245 self._emitline(' %s %s %3s %2s %3s %s' % (
246 self._format_hex(section['sh_size'], fullhex=True, lead0x=False),
247 self._format_hex(section['sh_entsize'], fullhex=True, lead0x=False),
248 describe_sh_flags(section['sh_flags']),
249 section['sh_link'], section['sh_info'],
250 section['sh_addralign']))
251
252 self._emitline('Key to Flags:')
Eli Bendersky93e630d2011-11-16 07:22:57 +0200253 self._emit(' W (write), A (alloc), X (execute), M (merge), S (strings)')
254 if self.elffile['e_machine'] in ('EM_X86_64', 'EM_L10M'):
255 self._emitline(', l (large)')
256 else:
257 self._emitline()
258 self._emitline(' I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)')
Eli Bendersky377bd862011-09-16 11:10:44 +0300259 self._emitline(' O (extra OS processing required) o (OS specific), p (processor specific)')
260
Eli Bendersky3edefab2011-09-16 14:52:54 +0300261 def display_symbol_tables(self):
262 """ Display the symbol tables contained in the file
263 """
Yann Rouillard7b246702013-05-27 22:44:28 +0200264 self._init_versioninfo()
265
Eli Bendersky3edefab2011-09-16 14:52:54 +0300266 for section in self.elffile.iter_sections():
267 if not isinstance(section, SymbolTableSection):
268 continue
269
270 if section['sh_entsize'] == 0:
271 self._emitline("\nSymbol table '%s' has a sh_entsize of zero!" % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200272 bytes2str(section.name)))
Eli Bendersky3edefab2011-09-16 14:52:54 +0300273 continue
274
275 self._emitline("\nSymbol table '%s' contains %s entries:" % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200276 bytes2str(section.name), section.num_symbols()))
Eli Bendersky3edefab2011-09-16 14:52:54 +0300277
278 if self.elffile.elfclass == 32:
279 self._emitline(' Num: Value Size Type Bind Vis Ndx Name')
280 else: # 64
281 self._emitline(' Num: Value Size Type Bind Vis Ndx Name')
282
283 for nsym, symbol in enumerate(section.iter_symbols()):
Yann Rouillard7b246702013-05-27 22:44:28 +0200284
285 version_info = ''
286 # readelf doesn't display version info for Solaris versioning
287 if (section['sh_type'] == 'SHT_DYNSYM' and
288 self._versioninfo['type'] == 'GNU'):
289 version = self._symbol_version(nsym)
Yann Rouillardde179382013-05-29 23:47:50 +0200290 if (version['name'] != bytes2str(symbol.name) and
Yann Rouillard7b246702013-05-27 22:44:28 +0200291 version['index'] not in ('VER_NDX_LOCAL',
292 'VER_NDX_GLOBAL')):
293 if version['filename']:
294 # external symbol
295 version_info = '@%(name)s (%(index)i)' % version
296 else:
297 # internal symbol
298 if version['hidden']:
299 version_info = '@%(name)s' % version
300 else:
301 version_info = '@@%(name)s' % version
302
Eli Benderskyb6fa3652011-09-16 15:20:20 +0300303 # symbol names are truncated to 25 chars, similarly to readelf
Yann Rouillard7b246702013-05-27 22:44:28 +0200304 self._emitline('%6d: %s %5d %-7s %-6s %-7s %4s %.25s%s' % (
Eli Bendersky3edefab2011-09-16 14:52:54 +0300305 nsym,
Yann Rouillardde179382013-05-29 23:47:50 +0200306 self._format_hex(
307 symbol['st_value'], fullhex=True, lead0x=False),
Eli Bendersky3edefab2011-09-16 14:52:54 +0300308 symbol['st_size'],
309 describe_symbol_type(symbol['st_info']['type']),
310 describe_symbol_bind(symbol['st_info']['bind']),
311 describe_symbol_visibility(symbol['st_other']['visibility']),
312 describe_symbol_shndx(symbol['st_shndx']),
Yann Rouillard7b246702013-05-27 22:44:28 +0200313 bytes2str(symbol.name),
314 version_info))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800315
Mike Frysinger5699e182013-03-23 02:47:32 -0400316 def display_dynamic_tags(self):
317 """ Display the dynamic tags contained in the file
318 """
Mike Frysinger5699e182013-03-23 02:47:32 -0400319 for section in self.elffile.iter_sections():
320 if not isinstance(section, DynamicSection):
321 continue
322
Mike Frysinger5699e182013-03-23 02:47:32 -0400323 self._emitline("\nDynamic section at offset %s contains %s entries:" % (
324 self._format_hex(section['sh_offset']),
325 section.num_tags()))
326 self._emitline(" Tag Type Name/Value")
327
Mike Frysinger5699e182013-03-23 02:47:32 -0400328 padding = 20 + (8 if self.elffile.elfclass == 32 else 0)
329 for tag in section.iter_tags():
330 if tag.entry.d_tag == 'DT_NEEDED':
Eli Benderskyccdb5542013-03-31 14:19:21 -0700331 parsed = 'Shared library: [%s]' % bytes2str(tag.needed)
Mike Frysinger5699e182013-03-23 02:47:32 -0400332 elif tag.entry.d_tag == 'DT_RPATH':
Eli Benderskyccdb5542013-03-31 14:19:21 -0700333 parsed = 'Library rpath: [%s]' % bytes2str(tag.rpath)
Mike Frysinger5699e182013-03-23 02:47:32 -0400334 elif tag.entry.d_tag == 'DT_RUNPATH':
Eli Benderskyccdb5542013-03-31 14:19:21 -0700335 parsed = 'Library runpath: [%s]' % bytes2str(tag.runpath)
Eli Benderskyf8d2cf72013-03-31 06:56:56 -0700336 elif tag.entry.d_tag == 'DT_SONAME':
Eli Benderskyccdb5542013-03-31 14:19:21 -0700337 parsed = 'Library soname: [%s]' % bytes2str(tag.soname)
Mike Frysinger5699e182013-03-23 02:47:32 -0400338 elif (tag.entry.d_tag.endswith('SZ') or
339 tag.entry.d_tag.endswith('ENT')):
340 parsed = '%i (bytes)' % tag['d_val']
Eli Benderskybfb1bf52013-03-31 07:58:21 -0700341 elif (tag.entry.d_tag.endswith('NUM') or
342 tag.entry.d_tag.endswith('COUNT')):
Mike Frysinger5699e182013-03-23 02:47:32 -0400343 parsed = '%i' % tag['d_val']
344 elif tag.entry.d_tag == 'DT_PLTREL':
345 s = describe_dyn_tag(tag.entry.d_val)
346 if s.startswith('DT_'):
347 s = s[3:]
348 parsed = '%s' % s
349 else:
350 parsed = '%#x' % tag['d_val']
351
352 self._emitline(" %s %-*s %s" % (
353 self._format_hex(ENUM_D_TAG.get(tag.entry.d_tag, tag.entry.d_tag),
Eli Benderskyf8d2cf72013-03-31 06:56:56 -0700354 fullhex=True, lead0x=True),
Mike Frysinger5699e182013-03-23 02:47:32 -0400355 padding,
356 '(%s)' % (tag.entry.d_tag[3:],),
357 parsed))
358
Eli Bendersky84066b22011-09-20 06:48:52 +0300359 def display_relocations(self):
360 """ Display the relocations contained in the file
361 """
362 has_relocation_sections = False
363 for section in self.elffile.iter_sections():
364 if not isinstance(section, RelocationSection):
365 continue
366
367 has_relocation_sections = True
368 self._emitline("\nRelocation section '%s' at offset %s contains %s entries:" % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200369 bytes2str(section.name),
Eli Bendersky7c1ffa62011-09-22 06:37:07 +0300370 self._format_hex(section['sh_offset']),
371 section.num_relocations()))
Eli Bendersky89a824f2011-09-23 10:59:59 +0300372 if section.is_RELA():
373 self._emitline(" Offset Info Type Sym. Value Sym. Name + Addend")
374 else:
375 self._emitline(" Offset Info Type Sym.Value Sym. Name")
376
377 # The symbol table section pointed to in sh_link
378 symtable = self.elffile.get_section(section['sh_link'])
379
Eli Bendersky84066b22011-09-20 06:48:52 +0300380 for rel in section.iter_relocations():
Eli Bendersky89a824f2011-09-23 10:59:59 +0300381 hexwidth = 8 if self.elffile.elfclass == 32 else 12
Eli Bendersky099d48f2011-09-23 12:03:48 +0300382 self._emit('%s %s %-17.17s' % (
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800383 self._format_hex(rel['r_offset'],
Eli Bendersky89a824f2011-09-23 10:59:59 +0300384 fieldsize=hexwidth, lead0x=False),
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800385 self._format_hex(rel['r_info'],
Eli Bendersky89a824f2011-09-23 10:59:59 +0300386 fieldsize=hexwidth, lead0x=False),
387 describe_reloc_type(
Eli Bendersky067b3fd2011-11-18 12:02:57 +0200388 rel['r_info_type'], self.elffile)))
Eli Bendersky099d48f2011-09-23 12:03:48 +0300389
390 if rel['r_info_sym'] == 0:
391 self._emitline()
392 continue
393
394 symbol = symtable.get_symbol(rel['r_info_sym'])
Eli Benderskyadf707a2011-09-23 15:23:41 +0300395 # Some symbols have zero 'st_name', so instead what's used is
396 # the name of the section they point at
397 if symbol['st_name'] == 0:
398 symsec = self.elffile.get_section(symbol['st_shndx'])
399 symbol_name = symsec.name
400 else:
401 symbol_name = symbol.name
Eli Bendersky6434a962011-09-23 17:14:08 +0300402 self._emit(' %s %s%22.22s' % (
Eli Bendersky89a824f2011-09-23 10:59:59 +0300403 self._format_hex(
404 symbol['st_value'],
405 fullhex=True, lead0x=False),
406 ' ' if self.elffile.elfclass == 32 else '',
Eli Bendersky79271e92012-01-27 10:25:47 +0200407 bytes2str(symbol_name)))
Eli Bendersky89a824f2011-09-23 10:59:59 +0300408 if section.is_RELA():
409 self._emit(' %s %x' % (
410 '+' if rel['r_addend'] >= 0 else '-',
411 abs(rel['r_addend'])))
412 self._emitline()
Eli Bendersky84066b22011-09-20 06:48:52 +0300413
414 if not has_relocation_sections:
415 self._emitline('\nThere are no relocations in this file.')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800416
Yann Rouillard7b246702013-05-27 22:44:28 +0200417 def display_version_info(self):
418 """ Display the version info contained in the file
419 """
420 self._init_versioninfo()
421
422 if not self._versioninfo['type']:
423 self._emitline("\nNo version information found in this file.")
424 return
425
426 for section in self.elffile.iter_sections():
Yann Rouillard478a4592013-05-31 21:01:25 +0200427 if isinstance(section, GNUVerSymSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200428 self._print_version_section_header(
429 section, 'Version symbols', lead0x=False)
430
431 num_symbols = section.num_symbols()
432
433 # Symbol version info are printed four by four entries
434 for idx_by_4 in range(0, num_symbols, 4):
435
436 self._emit(' %03x:' % idx_by_4)
437
438 for idx in range(idx_by_4, min(idx_by_4 + 4, num_symbols)):
439
440 symbol_version = self._symbol_version(idx)
441 if symbol_version['index'] == 'VER_NDX_LOCAL':
442 version_index = 0
443 version_name = '(*local*)'
444 elif symbol_version['index'] == 'VER_NDX_GLOBAL':
445 version_index = 1
446 version_name = '(*global*)'
447 else:
448 version_index = symbol_version['index']
449 version_name = '(%(name)s)' % symbol_version
450
451 visibility = 'h' if symbol_version['hidden'] else ' '
452
453 self._emit('%4x%s%-13s' % (
454 version_index, visibility, version_name))
455
456 self._emitline()
457
Yann Rouillard478a4592013-05-31 21:01:25 +0200458 elif isinstance(section, GNUVerDefSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200459 self._print_version_section_header(
460 section, 'Version definition', indent=2)
461
462 offset = 0
463 for verdef, verdaux_iter in section.iter_versions():
464 verdaux = next(verdaux_iter)
465
466 name = verdaux.name
467 if verdef['vd_flags']:
468 flags = describe_ver_flags(verdef['vd_flags'])
469 # Mimic exactly the readelf output
470 flags += ' '
471 else:
472 flags = 'none'
473
474 self._emitline(' %s: Rev: %i Flags: %s Index: %i'
475 ' Cnt: %i Name: %s' % (
476 self._format_hex(offset, fieldsize=6,
477 alternate=True),
478 verdef['vd_version'], flags, verdef['vd_ndx'],
479 verdef['vd_cnt'], bytes2str(name)))
480
481 verdaux_offset = (
482 offset + verdef['vd_aux'] + verdaux['vda_next'])
483 for idx, verdaux in enumerate(verdaux_iter, start=1):
484 self._emitline(' %s: Parent %i: %s' %
485 (self._format_hex(verdaux_offset, fieldsize=4),
486 idx, bytes2str(verdaux.name)))
487 verdaux_offset += verdaux['vda_next']
488
489 offset += verdef['vd_next']
490
Yann Rouillard478a4592013-05-31 21:01:25 +0200491 elif isinstance(section, GNUVerNeedSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200492 self._print_version_section_header(section, 'Version needs')
493
494 offset = 0
495 for verneed, verneed_iter in section.iter_versions():
496
497 self._emitline(' %s: Version: %i File: %s Cnt: %i' % (
498 self._format_hex(offset, fieldsize=6,
499 alternate=True),
500 verneed['vn_version'], bytes2str(verneed.name),
501 verneed['vn_cnt']))
502
503 vernaux_offset = offset + verneed['vn_aux']
504 for idx, vernaux in enumerate(verneed_iter, start=1):
505 if vernaux['vna_flags']:
506 flags = describe_ver_flags(vernaux['vna_flags'])
507 # Mimic exactly the readelf output
508 flags += ' '
509 else:
510 flags = 'none'
511
512 self._emitline(
513 ' %s: Name: %s Flags: %s Version: %i' % (
514 self._format_hex(vernaux_offset, fieldsize=4),
515 bytes2str(vernaux.name), flags,
516 vernaux['vna_other']))
517
518 vernaux_offset += vernaux['vna_next']
519
520 offset += verneed['vn_next']
521
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300522 def display_hex_dump(self, section_spec):
523 """ Display a hex dump of a section. section_spec is either a section
524 number or a name.
525 """
eliben54e39b22011-09-19 13:10:57 +0300526 section = self._section_from_spec(section_spec)
527 if section is None:
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300528 self._emitline("Section '%s' does not exist in the file!" % (
529 section_spec))
530 return
531
Eli Bendersky79271e92012-01-27 10:25:47 +0200532 self._emitline("\nHex dump of section '%s':" % bytes2str(section.name))
Eli Benderskyadf707a2011-09-23 15:23:41 +0300533 self._note_relocs_for_section(section)
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300534 addr = section['sh_addr']
535 data = section.data()
536 dataptr = 0
537
538 while dataptr < len(data):
539 bytesleft = len(data) - dataptr
540 # chunks of 16 bytes per line
541 linebytes = 16 if bytesleft > 16 else bytesleft
542
543 self._emit(' %s ' % self._format_hex(addr, fieldsize=8))
544 for i in range(16):
545 if i < linebytes:
Eli Bendersky79271e92012-01-27 10:25:47 +0200546 self._emit('%2.2x' % byte2int(data[dataptr + i]))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300547 else:
548 self._emit(' ')
549 if i % 4 == 3:
550 self._emit(' ')
551
552 for i in range(linebytes):
Eli Bendersky79271e92012-01-27 10:25:47 +0200553 c = data[dataptr + i : dataptr + i + 1]
554 if byte2int(c[0]) >= 32 and byte2int(c[0]) < 0x7f:
555 self._emit(bytes2str(c))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300556 else:
Eli Bendersky79271e92012-01-27 10:25:47 +0200557 self._emit(bytes2str(b'.'))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300558
559 self._emitline()
560 addr += linebytes
561 dataptr += linebytes
562
563 self._emitline()
564
Eli Bendersky53e86db2011-09-18 06:04:30 +0300565 def display_string_dump(self, section_spec):
566 """ Display a strings dump of a section. section_spec is either a
567 section number or a name.
568 """
eliben54e39b22011-09-19 13:10:57 +0300569 section = self._section_from_spec(section_spec)
570 if section is None:
Eli Bendersky53e86db2011-09-18 06:04:30 +0300571 self._emitline("Section '%s' does not exist in the file!" % (
572 section_spec))
573 return
574
Eli Bendersky79271e92012-01-27 10:25:47 +0200575 self._emitline("\nString dump of section '%s':" % bytes2str(section.name))
Eli Bendersky53e86db2011-09-18 06:04:30 +0300576
577 found = False
578 data = section.data()
579 dataptr = 0
580
581 while dataptr < len(data):
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800582 while ( dataptr < len(data) and
Eli Bendersky79271e92012-01-27 10:25:47 +0200583 not (32 <= byte2int(data[dataptr]) <= 127)):
Eli Bendersky53e86db2011-09-18 06:04:30 +0300584 dataptr += 1
585
586 if dataptr >= len(data):
587 break
588
589 endptr = dataptr
Eli Bendersky79271e92012-01-27 10:25:47 +0200590 while endptr < len(data) and byte2int(data[endptr]) != 0:
Eli Bendersky53e86db2011-09-18 06:04:30 +0300591 endptr += 1
592
593 found = True
594 self._emitline(' [%6x] %s' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200595 dataptr, bytes2str(data[dataptr:endptr])))
Eli Bendersky53e86db2011-09-18 06:04:30 +0300596
597 dataptr = endptr
598
599 if not found:
600 self._emitline(' No strings found in this section.')
601 else:
602 self._emitline()
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300603
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200604 def display_debug_dump(self, dump_what):
eliben0fc47af2011-10-02 13:47:12 +0200605 """ Dump a DWARF section
606 """
607 self._init_dwarfinfo()
608 if self._dwarfinfo is None:
609 return
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800610
Eli Bendersky3501f9f2011-12-09 12:29:06 +0200611 set_global_machine_arch(self.elffile.get_machine_arch())
612
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200613 if dump_what == 'info':
eliben0fc47af2011-10-02 13:47:12 +0200614 self._dump_debug_info()
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200615 elif dump_what == 'decodedline':
616 self._dump_debug_line_programs()
Eli Bendersky7241ff02011-12-12 06:40:34 +0200617 elif dump_what == 'frames':
618 self._dump_debug_frames()
Eli Bendersky8670bb32011-12-15 16:11:06 +0200619 elif dump_what == 'frames-interp':
620 self._dump_debug_frames_interp()
eliben0fc47af2011-10-02 13:47:12 +0200621 else:
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200622 self._emitline('debug dump not yet supported for "%s"' % dump_what)
eliben0fc47af2011-10-02 13:47:12 +0200623
Yann Rouillard7b246702013-05-27 22:44:28 +0200624 def _format_hex(self, addr, fieldsize=None, fullhex=False, lead0x=True,
625 alternate=False):
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300626 """ Format an address into a hexadecimal string.
Eli Benderskyd62928d2011-09-09 10:05:57 +0300627
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300628 fieldsize:
629 Size of the hexadecimal field (with leading zeros to fit the
630 address into. For example with fieldsize=8, the format will
631 be %08x
632 If None, the minimal required field size will be used.
633
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300634 fullhex:
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800635 If True, override fieldsize to set it to the maximal size
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300636 needed for the elfclass
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300637
638 lead0x:
639 If True, leading 0x is added
Yann Rouillard7b246702013-05-27 22:44:28 +0200640
641 alternate:
642 If True, override lead0x to emulate the alternate
Yann Rouillardde179382013-05-29 23:47:50 +0200643 hexadecimal form specified in format string with the #
Yann Rouillard7b246702013-05-27 22:44:28 +0200644 character: only non-zero values are prefixed with 0x.
645 This form is used by readelf.
Eli Benderskyd62928d2011-09-09 10:05:57 +0300646 """
Yann Rouillard7b246702013-05-27 22:44:28 +0200647 if alternate:
648 if addr == 0:
649 lead0x = False
650 else:
651 lead0x = True
652 fieldsize -= 2
653
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300654 s = '0x' if lead0x else ''
655 if fullhex:
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300656 fieldsize = 8 if self.elffile.elfclass == 32 else 16
657 if fieldsize is None:
658 field = '%x'
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300659 else:
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300660 field = '%' + '0%sx' % fieldsize
661 return s + field % addr
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800662
Yann Rouillardde179382013-05-29 23:47:50 +0200663 def _print_version_section_header(self, version_section, name, lead0x=True,
664 indent=1):
665 """ Print a section header of one version related section (versym,
666 verneed or verdef) with some options to accomodate readelf
667 little differences between each header (e.g. indentation
668 and 0x prefixing).
Yann Rouillard7b246702013-05-27 22:44:28 +0200669 """
670 if hasattr(version_section, 'num_versions'):
671 num_entries = version_section.num_versions()
672 else:
673 num_entries = version_section.num_symbols()
674
675 self._emitline("\n%s section '%s' contains %s entries:" %
676 (name, bytes2str(version_section.name), num_entries))
Yann Rouillardde179382013-05-29 23:47:50 +0200677 self._emitline('%sAddr: %s Offset: %s Link: %i (%s)' % (
678 ' ' * indent,
679 self._format_hex(
680 version_section['sh_addr'], fieldsize=16, lead0x=lead0x),
681 self._format_hex(
682 version_section['sh_offset'], fieldsize=6, lead0x=True),
683 version_section['sh_link'],
684 bytes2str(
685 self.elffile.get_section(version_section['sh_link']).name)
686 )
687 )
Yann Rouillard7b246702013-05-27 22:44:28 +0200688
689 def _init_versioninfo(self):
690 """ Search and initialize informations about version related sections
691 and the kind of versioning used (GNU or Solaris).
692 """
693 if self._versioninfo is not None:
694 return
695
Yann Rouillardde179382013-05-29 23:47:50 +0200696 self._versioninfo = {'versym': None, 'verdef': None,
697 'verneed': None, 'type': None}
Yann Rouillard7b246702013-05-27 22:44:28 +0200698
699 for section in self.elffile.iter_sections():
Yann Rouillard478a4592013-05-31 21:01:25 +0200700 if isinstance(section, GNUVerSymSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200701 self._versioninfo['versym'] = section
Yann Rouillard478a4592013-05-31 21:01:25 +0200702 elif isinstance(section, GNUVerDefSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200703 self._versioninfo['verdef'] = section
Yann Rouillard478a4592013-05-31 21:01:25 +0200704 elif isinstance(section, GNUVerNeedSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200705 self._versioninfo['verneed'] = section
706 elif isinstance(section, DynamicSection):
707 for tag in section.iter_tags():
708 if tag['d_tag'] == 'DT_VERSYM':
709 self._versioninfo['type'] = 'GNU'
Yann Rouillardde179382013-05-29 23:47:50 +0200710 break
Yann Rouillard7b246702013-05-27 22:44:28 +0200711
712 if not self._versioninfo['type'] and (
713 self._versioninfo['verneed'] or self._versioninfo['verdef']):
714 self._versioninfo['type'] = 'Solaris'
715
Yann Rouillard7b246702013-05-27 22:44:28 +0200716 def _symbol_version(self, nsym):
Yann Rouillardde179382013-05-29 23:47:50 +0200717 """ Return a dict containing information on the
Yann Rouillard7b246702013-05-27 22:44:28 +0200718 or None if no version information is available
719 """
720 self._init_versioninfo()
Yann Rouillardde179382013-05-29 23:47:50 +0200721
Yann Rouillard7b246702013-05-27 22:44:28 +0200722 symbol_version = dict.fromkeys(('index', 'name', 'filename', 'hidden'))
723
724 if (not self._versioninfo['versym'] or
725 nsym >= self._versioninfo['versym'].num_symbols()):
726 return None
727
728 symbol = self._versioninfo['versym'].get_symbol(nsym)
729 index = symbol.entry['ndx']
730 if not index in ('VER_NDX_LOCAL', 'VER_NDX_GLOBAL'):
731 index = int(index)
732
733 if self._versioninfo['type'] == 'GNU':
Yann Rouillardde179382013-05-29 23:47:50 +0200734 # In GNU versioning mode, the highest bit is used to
Yann Rouillard7b246702013-05-27 22:44:28 +0200735 # store wether the symbol is hidden or not
736 if index & 0x8000:
Yann Rouillardde179382013-05-29 23:47:50 +0200737 index &= ~0x8000
Yann Rouillard7b246702013-05-27 22:44:28 +0200738 symbol_version['hidden'] = True
739
Yann Rouillardde179382013-05-29 23:47:50 +0200740 if (self._versioninfo['verdef'] and
Yann Rouillard7b246702013-05-27 22:44:28 +0200741 index <= self._versioninfo['verdef'].num_versions()):
742 _, verdaux_iter = \
743 self._versioninfo['verdef'].get_version(index)
744 symbol_version['name'] = bytes2str(next(verdaux_iter).name)
745 else:
746 verneed, vernaux = \
747 self._versioninfo['verneed'].get_version(index)
748 symbol_version['name'] = bytes2str(vernaux.name)
749 symbol_version['filename'] = bytes2str(verneed.name)
750
751 symbol_version['index'] = index
752 return symbol_version
753
eliben54e39b22011-09-19 13:10:57 +0300754 def _section_from_spec(self, spec):
755 """ Retrieve a section given a "spec" (either number or name).
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300756 Return None if no such section exists in the file.
757 """
758 try:
759 num = int(spec)
eliben54e39b22011-09-19 13:10:57 +0300760 if num < self.elffile.num_sections():
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800761 return self.elffile.get_section(num)
eliben54e39b22011-09-19 13:10:57 +0300762 else:
763 return None
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300764 except ValueError:
765 # Not a number. Must be a name then
Eli Bendersky79271e92012-01-27 10:25:47 +0200766 return self.elffile.get_section_by_name(str2bytes(spec))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300767
Eli Benderskyadf707a2011-09-23 15:23:41 +0300768 def _note_relocs_for_section(self, section):
769 """ If there are relocation sections pointing to the givne section,
770 emit a note about it.
771 """
772 for relsec in self.elffile.iter_sections():
773 if isinstance(relsec, RelocationSection):
774 info_idx = relsec['sh_info']
775 if self.elffile.get_section(info_idx) == section:
776 self._emitline(' Note: This section has relocations against it, but these have NOT been applied to this dump.')
777 return
778
eliben0fc47af2011-10-02 13:47:12 +0200779 def _init_dwarfinfo(self):
780 """ Initialize the DWARF info contained in the file and assign it to
781 self._dwarfinfo.
782 Leave self._dwarfinfo at None if no DWARF info was found in the file
783 """
784 if self._dwarfinfo is not None:
785 return
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800786
eliben0fc47af2011-10-02 13:47:12 +0200787 if self.elffile.has_dwarf_info():
788 self._dwarfinfo = self.elffile.get_dwarf_info()
789 else:
790 self._dwarfinfo = None
791
792 def _dump_debug_info(self):
793 """ Dump the debugging info section.
794 """
eliben985c2c12011-11-14 17:53:23 +0200795 self._emitline('Contents of the .debug_info section:\n')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800796
eliben0fc47af2011-10-02 13:47:12 +0200797 # Offset of the .debug_info section in the stream
Eli Bendersky149315a2011-11-24 08:12:37 +0200798 section_offset = self._dwarfinfo.debug_info_sec.global_offset
Eli Bendersky6062bf72011-11-23 06:54:40 +0200799
eliben0fc47af2011-10-02 13:47:12 +0200800 for cu in self._dwarfinfo.iter_CUs():
eliben985c2c12011-11-14 17:53:23 +0200801 self._emitline(' Compilation Unit @ offset %s:' %
Eli Bendersky149315a2011-11-24 08:12:37 +0200802 self._format_hex(cu.cu_offset))
eliben0fc47af2011-10-02 13:47:12 +0200803 self._emitline(' Length: %s (%s)' % (
804 self._format_hex(cu['unit_length']),
805 '%s-bit' % cu.dwarf_format()))
806 self._emitline(' Version: %s' % cu['version']),
Eli Bendersky7eba7182013-03-30 17:23:36 -0700807 self._emitline(' Abbrev Offset: %s' % (
808 self._format_hex(cu['debug_abbrev_offset']))),
eliben0fc47af2011-10-02 13:47:12 +0200809 self._emitline(' Pointer Size: %s' % cu['address_size'])
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800810
811 # The nesting depth of each DIE within the tree of DIEs must be
eliben0fc47af2011-10-02 13:47:12 +0200812 # displayed. To implement this, a counter is incremented each time
813 # the current DIE has children, and decremented when a null die is
814 # encountered. Due to the way the DIE tree is serialized, this will
815 # correctly reflect the nesting depth
816 #
817 die_depth = 0
818 for die in cu.iter_DIEs():
Eli Bendersky9aec9d82013-03-30 16:39:30 -0700819 self._emitline(' <%s><%x>: Abbrev Number: %s%s' % (
elibenaee11d22011-10-26 10:42:34 +0200820 die_depth,
Eli Bendersky149315a2011-11-24 08:12:37 +0200821 die.offset,
elibenaee11d22011-10-26 10:42:34 +0200822 die.abbrev_code,
Eli Bendersky9aec9d82013-03-30 16:39:30 -0700823 (' (%s)' % die.tag) if not die.is_null() else ''))
824 if die.is_null():
825 die_depth -= 1
826 continue
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800827
Eli Bendersky79271e92012-01-27 10:25:47 +0200828 for attr in itervalues(die.attributes):
Eli Bendersky871ad0c2011-12-16 08:13:48 +0200829 name = attr.name
830 # Unknown attribute values are passed-through as integers
831 if isinstance(name, int):
832 name = 'Unknown AT value: %x' % name
elibenaee11d22011-10-26 10:42:34 +0200833 self._emitline(' <%2x> %-18s: %s' % (
Eli Bendersky149315a2011-11-24 08:12:37 +0200834 attr.offset,
Eli Bendersky871ad0c2011-12-16 08:13:48 +0200835 name,
eliben3bc9c342011-10-26 13:10:58 +0200836 describe_attr_value(
Eli Bendersky5be3be82011-10-27 14:28:12 +0200837 attr, die, section_offset)))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800838
eliben0fc47af2011-10-02 13:47:12 +0200839 if die.has_children:
840 die_depth += 1
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800841
Eli Benderskyf5670e82011-11-24 09:05:44 +0200842 self._emitline()
eliben0fc47af2011-10-02 13:47:12 +0200843
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200844 def _dump_debug_line_programs(self):
845 """ Dump the (decoded) line programs from .debug_line
846 The programs are dumped in the order of the CUs they belong to.
847 """
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200848 self._emitline('Decoded dump of debug contents of section .debug_line:\n')
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200849
850 for cu in self._dwarfinfo.iter_CUs():
851 lineprogram = self._dwarfinfo.line_program_for_CU(cu)
852
Eli Bendersky7eba7182013-03-30 17:23:36 -0700853 cu_filename = bytes2str(lineprogram['file_entry'][0].name)
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200854 if len(lineprogram['include_directory']) > 0:
Eli Bendersky7eba7182013-03-30 17:23:36 -0700855 dir_index = lineprogram['file_entry'][0].dir_index
856 if dir_index > 0:
857 dir = lineprogram['include_directory'][dir_index - 1]
858 else:
Eli Benderskyccdb5542013-03-31 14:19:21 -0700859 dir = b'.'
Eli Bendersky7eba7182013-03-30 17:23:36 -0700860 cu_filename = '%s/%s' % (bytes2str(dir), cu_filename)
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200861
862 self._emitline('CU: %s:' % cu_filename)
863 self._emitline('File name Line number Starting address')
864
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200865 # Print each state's file, line and address information. For some
866 # instructions other output is needed to be compatible with
867 # readelf.
868 for entry in lineprogram.get_entries():
869 state = entry.state
870 if state is None:
871 # Special handling for commands that don't set a new state
872 if entry.command == DW_LNS_set_file:
873 file_entry = lineprogram['file_entry'][entry.args[0] - 1]
874 if file_entry.dir_index == 0:
875 # current directory
876 self._emitline('\n./%s:[++]' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200877 bytes2str(file_entry.name)))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200878 else:
879 self._emitline('\n%s/%s:' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200880 bytes2str(lineprogram['include_directory'][file_entry.dir_index - 1]),
881 bytes2str(file_entry.name)))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200882 elif entry.command == DW_LNE_define_file:
883 self._emitline('%s:' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200884 bytes2str(lineprogram['include_directory'][entry.args[0].dir_index])))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200885 elif not state.end_sequence:
886 # readelf doesn't print the state after end_sequence
887 # instructions. I think it's a bug but to be compatible
888 # I don't print them too.
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200889 self._emitline('%-35s %11d %18s' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200890 bytes2str(lineprogram['file_entry'][state.file - 1].name),
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200891 state.line,
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800892 '0' if state.address == 0 else
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200893 self._format_hex(state.address)))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200894 if entry.command == DW_LNS_copy:
895 # Another readelf oddity...
896 self._emitline()
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200897
Eli Bendersky7241ff02011-12-12 06:40:34 +0200898 def _dump_debug_frames(self):
899 """ Dump the raw frame information from .debug_frame
900 """
Eli Bendersky47a47112011-12-14 06:54:09 +0200901 if not self._dwarfinfo.has_CFI():
902 return
Eli Bendersky7241ff02011-12-12 06:40:34 +0200903 self._emitline('Contents of the .debug_frame section:')
904
905 for entry in self._dwarfinfo.CFI_entries():
906 if isinstance(entry, CIE):
907 self._emitline('\n%08x %08x %08x CIE' % (
908 entry.offset, entry['length'], entry['CIE_id']))
909 self._emitline(' Version: %d' % entry['version'])
Eli Bendersky79271e92012-01-27 10:25:47 +0200910 self._emitline(' Augmentation: "%s"' % bytes2str(entry['augmentation']))
Eli Bendersky7241ff02011-12-12 06:40:34 +0200911 self._emitline(' Code alignment factor: %u' % entry['code_alignment_factor'])
912 self._emitline(' Data alignment factor: %d' % entry['data_alignment_factor'])
913 self._emitline(' Return address column: %d' % entry['return_address_register'])
Eli Bendersky47a47112011-12-14 06:54:09 +0200914 self._emitline()
Eli Bendersky7241ff02011-12-12 06:40:34 +0200915 else: # FDE
916 self._emitline('\n%08x %08x %08x FDE cie=%08x pc=%08x..%08x' % (
917 entry.offset,
918 entry['length'],
919 entry['CIE_pointer'],
920 entry.cie.offset,
921 entry['initial_location'],
922 entry['initial_location'] + entry['address_range']))
923
Eli Bendersky47a47112011-12-14 06:54:09 +0200924 self._emit(describe_CFI_instructions(entry))
925 self._emitline()
Eli Bendersky7241ff02011-12-12 06:40:34 +0200926
Eli Bendersky8670bb32011-12-15 16:11:06 +0200927 def _dump_debug_frames_interp(self):
928 """ Dump the interpreted (decoded) frame information from .debug_frame
929 """
930 if not self._dwarfinfo.has_CFI():
931 return
932
933 self._emitline('Contents of the .debug_frame section:')
934
935 for entry in self._dwarfinfo.CFI_entries():
936 if isinstance(entry, CIE):
937 self._emitline('\n%08x %08x %08x CIE "%s" cf=%d df=%d ra=%d' % (
938 entry.offset,
939 entry['length'],
940 entry['CIE_id'],
Eli Bendersky79271e92012-01-27 10:25:47 +0200941 bytes2str(entry['augmentation']),
Eli Bendersky8670bb32011-12-15 16:11:06 +0200942 entry['code_alignment_factor'],
943 entry['data_alignment_factor'],
944 entry['return_address_register']))
Eli Bendersky4682c962011-12-16 06:39:49 +0200945 ra_regnum = entry['return_address_register']
Eli Bendersky8670bb32011-12-15 16:11:06 +0200946 else: # FDE
947 self._emitline('\n%08x %08x %08x FDE cie=%08x pc=%08x..%08x' % (
948 entry.offset,
949 entry['length'],
950 entry['CIE_pointer'],
951 entry.cie.offset,
952 entry['initial_location'],
953 entry['initial_location'] + entry['address_range']))
Eli Bendersky4682c962011-12-16 06:39:49 +0200954 ra_regnum = entry.cie['return_address_register']
Eli Bendersky8670bb32011-12-15 16:11:06 +0200955
956 # Print the heading row for the decoded table
957 self._emit(' LOC')
958 self._emit(' ' if entry.structs.address_size == 4 else ' ')
Eli Bendersky4682c962011-12-16 06:39:49 +0200959 self._emit(' CFA ')
Eli Bendersky8670bb32011-12-15 16:11:06 +0200960
Eli Bendersky4682c962011-12-16 06:39:49 +0200961 # Decode the table nad look at the registers it describes.
962 # We build reg_order here to match readelf's order. In particular,
963 # registers are sorted by their number, and the register matching
964 # ra_regnum is always listed last with a special heading.
Eli Bendersky8670bb32011-12-15 16:11:06 +0200965 decoded_table = entry.get_decoded()
Eli Bendersky4682c962011-12-16 06:39:49 +0200966 reg_order = sorted(ifilter(
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800967 lambda r: r != ra_regnum,
Eli Bendersky4682c962011-12-16 06:39:49 +0200968 decoded_table.reg_order))
969
970 # Headings for the registers
971 for regnum in reg_order:
Eli Bendersky8670bb32011-12-15 16:11:06 +0200972 self._emit('%-6s' % describe_reg_name(regnum))
973 self._emitline('ra ')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800974
Eli Bendersky4682c962011-12-16 06:39:49 +0200975 # Now include ra_regnum in reg_order to print its values similarly
976 # to the other registers.
977 reg_order.append(ra_regnum)
978 for line in decoded_table.table:
979 self._emit(self._format_hex(
980 line['pc'], fullhex=True, lead0x=False))
981 self._emit(' %-9s' % describe_CFI_CFA_rule(line['cfa']))
Eli Bendersky8670bb32011-12-15 16:11:06 +0200982
Eli Bendersky4682c962011-12-16 06:39:49 +0200983 for regnum in reg_order:
984 if regnum in line:
985 s = describe_CFI_register_rule(line[regnum])
986 else:
987 s = 'u'
988 self._emit('%-6s' % s)
989 self._emitline()
990 self._emitline()
Eli Bendersky8670bb32011-12-15 16:11:06 +0200991
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300992 def _emit(self, s=''):
Eli Bendersky933f6992011-09-09 08:11:06 +0300993 """ Emit an object to output
994 """
995 self.output.write(str(s))
Eli Benderskyd62928d2011-09-09 10:05:57 +0300996
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300997 def _emitline(self, s=''):
Eli Bendersky933f6992011-09-09 08:11:06 +0300998 """ Emit an object to output, followed by a newline
999 """
1000 self.output.write(str(s) + '\n')
1001
1002
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001003SCRIPT_DESCRIPTION = 'Display information about the contents of ELF format files'
1004VERSION_STRING = '%%prog: based on pyelftools %s' % __version__
1005
1006
Eli Bendersky0193fb82011-11-26 16:16:16 +02001007def main(stream=None):
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001008 # parse the command-line arguments and invoke ReadElf
Eli Bendersky40eb1702011-09-16 16:59:52 +03001009 optparser = OptionParser(
Eli Benderskyecde41b2011-09-16 17:16:20 +03001010 usage='usage: %prog [options] <elf-file>',
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001011 description=SCRIPT_DESCRIPTION,
Eli Bendersky40eb1702011-09-16 16:59:52 +03001012 add_help_option=False, # -h is a real option of readelf
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001013 prog='readelf.py',
1014 version=VERSION_STRING)
Mike Frysinger5699e182013-03-23 02:47:32 -04001015 optparser.add_option('-d', '--dynamic',
1016 action='store_true', dest='show_dynamic_tags',
1017 help='Display the dynamic section')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001018 optparser.add_option('-H', '--help',
1019 action='store_true', dest='help',
1020 help='Display this information')
1021 optparser.add_option('-h', '--file-header',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001022 action='store_true', dest='show_file_header',
1023 help='Display the ELF file header')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001024 optparser.add_option('-l', '--program-headers', '--segments',
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001025 action='store_true', dest='show_program_header',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001026 help='Display the program headers')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001027 optparser.add_option('-S', '--section-headers', '--sections',
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001028 action='store_true', dest='show_section_header',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001029 help="Display the sections' headers")
Eli Bendersky40eb1702011-09-16 16:59:52 +03001030 optparser.add_option('-e', '--headers',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001031 action='store_true', dest='show_all_headers',
1032 help='Equivalent to: -h -l -S')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001033 optparser.add_option('-s', '--symbols', '--syms',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001034 action='store_true', dest='show_symbols',
1035 help='Display the symbol table')
Eli Bendersky84066b22011-09-20 06:48:52 +03001036 optparser.add_option('-r', '--relocs',
1037 action='store_true', dest='show_relocs',
1038 help='Display the relocations (if present)')
Eli Benderskyc4a4c072011-09-17 15:28:28 +03001039 optparser.add_option('-x', '--hex-dump',
1040 action='store', dest='show_hex_dump', metavar='<number|name>',
1041 help='Dump the contents of section <number|name> as bytes')
Eli Bendersky53e86db2011-09-18 06:04:30 +03001042 optparser.add_option('-p', '--string-dump',
1043 action='store', dest='show_string_dump', metavar='<number|name>',
1044 help='Dump the contents of section <number|name> as strings')
Yann Rouillard7b246702013-05-27 22:44:28 +02001045 optparser.add_option('-V', '--version-info',
1046 action='store_true', dest='show_version_info',
1047 help='Display the version sections (if present)')
eliben0fc47af2011-10-02 13:47:12 +02001048 optparser.add_option('--debug-dump',
Eli Bendersky1a516a32011-12-22 15:22:00 +02001049 action='store', dest='debug_dump_what', metavar='<what>',
1050 help=(
1051 'Display the contents of DWARF debug sections. <what> can ' +
1052 'one of {info,decodedline,frames,frames-interp}'))
Eli Bendersky53e86db2011-09-18 06:04:30 +03001053
Eli Bendersky933f6992011-09-09 08:11:06 +03001054 options, args = optparser.parse_args()
1055
Eli Bendersky40eb1702011-09-16 16:59:52 +03001056 if options.help or len(args) == 0:
1057 optparser.print_help()
1058 sys.exit(0)
1059
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001060 if options.show_all_headers:
1061 do_file_header = do_section_header = do_program_header = True
1062 else:
1063 do_file_header = options.show_file_header
1064 do_section_header = options.show_section_header
1065 do_program_header = options.show_program_header
1066
Eli Bendersky933f6992011-09-09 08:11:06 +03001067 with open(args[0], 'rb') as file:
1068 try:
Eli Bendersky0193fb82011-11-26 16:16:16 +02001069 readelf = ReadElf(file, stream or sys.stdout)
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001070 if do_file_header:
1071 readelf.display_file_header()
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001072 if do_section_header:
1073 readelf.display_section_headers(
1074 show_heading=not do_file_header)
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +03001075 if do_program_header:
1076 readelf.display_program_headers(
1077 show_heading=not do_file_header)
Mike Frysinger5699e182013-03-23 02:47:32 -04001078 if options.show_dynamic_tags:
1079 readelf.display_dynamic_tags()
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001080 if options.show_symbols:
1081 readelf.display_symbol_tables()
Eli Bendersky84066b22011-09-20 06:48:52 +03001082 if options.show_relocs:
1083 readelf.display_relocations()
Yann Rouillard7b246702013-05-27 22:44:28 +02001084 if options.show_version_info:
1085 readelf.display_version_info()
Eli Benderskyc4a4c072011-09-17 15:28:28 +03001086 if options.show_hex_dump:
1087 readelf.display_hex_dump(options.show_hex_dump)
Eli Bendersky53e86db2011-09-18 06:04:30 +03001088 if options.show_string_dump:
1089 readelf.display_string_dump(options.show_string_dump)
Eli Bendersky5ec2dde2011-12-04 07:05:31 +02001090 if options.debug_dump_what:
1091 readelf.display_debug_dump(options.debug_dump_what)
Eli Bendersky933f6992011-09-09 08:11:06 +03001092 except ELFError as ex:
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001093 sys.stderr.write('ELF error: %s\n' % ex)
Eli Bendersky933f6992011-09-09 08:11:06 +03001094 sys.exit(1)
1095
1096
Eli Bendersky0193fb82011-11-26 16:16:16 +02001097def profile_main():
1098 # Run 'main' redirecting its output to readelfout.txt
1099 # Saves profiling information in readelf.profile
1100 PROFFILE = 'readelf.profile'
1101 import cProfile
1102 cProfile.run('main(open("readelfout.txt", "w"))', PROFFILE)
1103
1104 # Dig in some profiling stats
1105 import pstats
1106 p = pstats.Stats(PROFFILE)
1107 p.sort_stats('cumulative').print_stats(25)
1108
1109
Eli Bendersky933f6992011-09-09 08:11:06 +03001110#-------------------------------------------------------------------------------
1111if __name__ == '__main__':
Eli Bendersky4f4d80c2011-11-26 16:49:27 +02001112 main()
1113 #profile_main()
Eli Bendersky0193fb82011-11-26 16:16:16 +02001114
Eli Bendersky933f6992011-09-09 08:11:06 +03001115