blob: dc0156675c31bd6a417a7131a2600d05df97f707 [file] [log] [blame]
Eli Bendersky3edefab2011-09-16 14:52:54 +03001#!/usr/bin/env python
Eli Bendersky933f6992011-09-09 08:11:06 +03002#-------------------------------------------------------------------------------
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +03003# scripts/readelf.py
Eli Bendersky933f6992011-09-09 08:11:06 +03004#
5# A clone of 'readelf' in Python, based on the pyelftools library
6#
7# Eli Bendersky (eliben@gmail.com)
8# This code is in the public domain
9#-------------------------------------------------------------------------------
Eli Bendersky53e86db2011-09-18 06:04:30 +030010import os, sys
Eli Bendersky933f6992011-09-09 08:11:06 +030011from optparse import OptionParser
Eli Bendersky53e86db2011-09-18 06:04:30 +030012import string
13
Eli Bendersky34d80012013-04-08 06:41:37 -070014# For running from development directory. It should take precedence over the
15# installed pyelftools.
Eli Bendersky8d12cae2013-04-06 07:05:35 -070016sys.path.insert(0, '.')
Eli Bendersky933f6992011-09-09 08:11:06 +030017
Eli Benderskydd71c432013-04-08 06:38:57 -070018
Eli Bendersky0b27ba42011-09-17 06:44:02 +030019from elftools import __version__
Eli Bendersky933f6992011-09-09 08:11:06 +030020from elftools.common.exceptions import ELFError
Eli Bendersky79271e92012-01-27 10:25:47 +020021from elftools.common.py3compat import (
22 ifilter, byte2int, bytes2str, itervalues, str2bytes)
Eli Bendersky933f6992011-09-09 08:11:06 +030023from elftools.elf.elffile import ELFFile
Mike Frysinger5699e182013-03-23 02:47:32 -040024from elftools.elf.dynamic import DynamicSection, DynamicSegment
25from elftools.elf.enums import ENUM_D_TAG
Eli Bendersky3f4de3e2011-09-14 05:58:06 +030026from elftools.elf.segments import InterpSegment
Yann Rouillard7b246702013-05-27 22:44:28 +020027from elftools.elf.sections import (
Yann Rouillardac9b3c82013-05-29 23:23:27 +020028 SymbolTableSection, GNUVerSymTableSection,
29 GNUVerDefTableSection, GNUVerNeedTableSection,
Yann Rouillard7b246702013-05-27 22:44:28 +020030 )
Eli Bendersky149315a2011-11-24 08:12:37 +020031from elftools.elf.relocation import RelocationSection
Eli Bendersky933f6992011-09-09 08:11:06 +030032from elftools.elf.descriptions import (
33 describe_ei_class, describe_ei_data, describe_ei_version,
Eli Benderskyde8d71e2011-09-09 08:22:35 +030034 describe_ei_osabi, describe_e_type, describe_e_machine,
Eli Bendersky26de2ac2011-09-13 06:50:28 +030035 describe_e_version_numeric, describe_p_type, describe_p_flags,
Eli Bendersky377bd862011-09-16 11:10:44 +030036 describe_sh_type, describe_sh_flags,
Eli Bendersky3edefab2011-09-16 14:52:54 +030037 describe_symbol_type, describe_symbol_bind, describe_symbol_visibility,
Mike Frysinger5699e182013-03-23 02:47:32 -040038 describe_symbol_shndx, describe_reloc_type, describe_dyn_tag,
Yann Rouillard7b246702013-05-27 22:44:28 +020039 describe_ver_flags,
Eli Bendersky933f6992011-09-09 08:11:06 +030040 )
Eli Bendersky149315a2011-11-24 08:12:37 +020041from elftools.dwarf.dwarfinfo import DWARFInfo
Eli Bendersky3501f9f2011-12-09 12:29:06 +020042from elftools.dwarf.descriptions import (
Eli Bendersky4682c962011-12-16 06:39:49 +020043 describe_reg_name, describe_attr_value, set_global_machine_arch,
44 describe_CFI_instructions, describe_CFI_register_rule,
45 describe_CFI_CFA_rule,
46 )
Eli Benderskybf83b1b2011-12-06 06:48:10 +020047from elftools.dwarf.constants import (
48 DW_LNS_copy, DW_LNS_set_file, DW_LNE_define_file)
Eli Bendersky7241ff02011-12-12 06:40:34 +020049from elftools.dwarf.callframe import CIE, FDE
Eli Bendersky933f6992011-09-09 08:11:06 +030050
51
52class ReadElf(object):
53 """ display_* methods are used to emit output into the output stream
54 """
55 def __init__(self, file, output):
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080056 """ file:
Eli Bendersky933f6992011-09-09 08:11:06 +030057 stream object with the ELF file to read
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080058
Eli Bendersky933f6992011-09-09 08:11:06 +030059 output:
60 output stream to write to
61 """
62 self.elffile = ELFFile(file)
63 self.output = output
Eli Bendersky0aaa6b02013-01-06 21:10:38 -080064
eliben0fc47af2011-10-02 13:47:12 +020065 # Lazily initialized if a debug dump is requested
66 self._dwarfinfo = None
Eli Bendersky933f6992011-09-09 08:11:06 +030067
Yann Rouillard7b246702013-05-27 22:44:28 +020068 self._versioninfo = None
69
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
Yann Rouillard7b246702013-05-27 22:44:28 +0200275
Eli Bendersky3edefab2011-09-16 14:52:54 +0300276 self._emitline("\nSymbol table '%s' contains %s entries:" % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200277 bytes2str(section.name), section.num_symbols()))
Eli Bendersky3edefab2011-09-16 14:52:54 +0300278
279 if self.elffile.elfclass == 32:
280 self._emitline(' Num: Value Size Type Bind Vis Ndx Name')
281 else: # 64
282 self._emitline(' Num: Value Size Type Bind Vis Ndx Name')
283
284 for nsym, symbol in enumerate(section.iter_symbols()):
Yann Rouillard7b246702013-05-27 22:44:28 +0200285
286 version_info = ''
287 # readelf doesn't display version info for Solaris versioning
288 if (section['sh_type'] == 'SHT_DYNSYM' and
289 self._versioninfo['type'] == 'GNU'):
290 version = self._symbol_version(nsym)
291 if (version['name'] != bytes2str(symbol.name) and
292 version['index'] not in ('VER_NDX_LOCAL',
293 'VER_NDX_GLOBAL')):
294 if version['filename']:
295 # external symbol
296 version_info = '@%(name)s (%(index)i)' % version
297 else:
298 # internal symbol
299 if version['hidden']:
300 version_info = '@%(name)s' % version
301 else:
302 version_info = '@@%(name)s' % version
303
Eli Benderskyb6fa3652011-09-16 15:20:20 +0300304 # symbol names are truncated to 25 chars, similarly to readelf
Yann Rouillard7b246702013-05-27 22:44:28 +0200305 self._emitline('%6d: %s %5d %-7s %-6s %-7s %4s %.25s%s' % (
Eli Bendersky3edefab2011-09-16 14:52:54 +0300306 nsym,
307 self._format_hex(symbol['st_value'], fullhex=True, lead0x=False),
308 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 Rouillardac9b3c82013-05-29 23:23:27 +0200427 if isinstance(section, GNUVerSymTableSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200428
429 self._print_version_section_header(
430 section, 'Version symbols', lead0x=False)
431
432 num_symbols = section.num_symbols()
433
434 # Symbol version info are printed four by four entries
435 for idx_by_4 in range(0, num_symbols, 4):
436
437 self._emit(' %03x:' % idx_by_4)
438
439 for idx in range(idx_by_4, min(idx_by_4 + 4, num_symbols)):
440
441 symbol_version = self._symbol_version(idx)
442 if symbol_version['index'] == 'VER_NDX_LOCAL':
443 version_index = 0
444 version_name = '(*local*)'
445 elif symbol_version['index'] == 'VER_NDX_GLOBAL':
446 version_index = 1
447 version_name = '(*global*)'
448 else:
449 version_index = symbol_version['index']
450 version_name = '(%(name)s)' % symbol_version
451
452 visibility = 'h' if symbol_version['hidden'] else ' '
453
454 self._emit('%4x%s%-13s' % (
455 version_index, visibility, version_name))
456
457 self._emitline()
458
Yann Rouillardac9b3c82013-05-29 23:23:27 +0200459 elif isinstance(section, GNUVerDefTableSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200460
461 self._print_version_section_header(
462 section, 'Version definition', indent=2)
463
464 offset = 0
465 for verdef, verdaux_iter in section.iter_versions():
466 verdaux = next(verdaux_iter)
467
468 name = verdaux.name
469 if verdef['vd_flags']:
470 flags = describe_ver_flags(verdef['vd_flags'])
471 # Mimic exactly the readelf output
472 flags += ' '
473 else:
474 flags = 'none'
475
476 self._emitline(' %s: Rev: %i Flags: %s Index: %i'
477 ' Cnt: %i Name: %s' % (
478 self._format_hex(offset, fieldsize=6,
479 alternate=True),
480 verdef['vd_version'], flags, verdef['vd_ndx'],
481 verdef['vd_cnt'], bytes2str(name)))
482
483 verdaux_offset = (
484 offset + verdef['vd_aux'] + verdaux['vda_next'])
485 for idx, verdaux in enumerate(verdaux_iter, start=1):
486 self._emitline(' %s: Parent %i: %s' %
487 (self._format_hex(verdaux_offset, fieldsize=4),
488 idx, bytes2str(verdaux.name)))
489 verdaux_offset += verdaux['vda_next']
490
491 offset += verdef['vd_next']
492
Yann Rouillardac9b3c82013-05-29 23:23:27 +0200493 elif isinstance(section, GNUVerNeedTableSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200494
495 self._print_version_section_header(section, 'Version needs')
496
497 offset = 0
498 for verneed, verneed_iter in section.iter_versions():
499
500 self._emitline(' %s: Version: %i File: %s Cnt: %i' % (
501 self._format_hex(offset, fieldsize=6,
502 alternate=True),
503 verneed['vn_version'], bytes2str(verneed.name),
504 verneed['vn_cnt']))
505
506 vernaux_offset = offset + verneed['vn_aux']
507 for idx, vernaux in enumerate(verneed_iter, start=1):
508 if vernaux['vna_flags']:
509 flags = describe_ver_flags(vernaux['vna_flags'])
510 # Mimic exactly the readelf output
511 flags += ' '
512 else:
513 flags = 'none'
514
515 self._emitline(
516 ' %s: Name: %s Flags: %s Version: %i' % (
517 self._format_hex(vernaux_offset, fieldsize=4),
518 bytes2str(vernaux.name), flags,
519 vernaux['vna_other']))
520
521 vernaux_offset += vernaux['vna_next']
522
523 offset += verneed['vn_next']
524
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300525 def display_hex_dump(self, section_spec):
526 """ Display a hex dump of a section. section_spec is either a section
527 number or a name.
528 """
eliben54e39b22011-09-19 13:10:57 +0300529 section = self._section_from_spec(section_spec)
530 if section is None:
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300531 self._emitline("Section '%s' does not exist in the file!" % (
532 section_spec))
533 return
534
Eli Bendersky79271e92012-01-27 10:25:47 +0200535 self._emitline("\nHex dump of section '%s':" % bytes2str(section.name))
Eli Benderskyadf707a2011-09-23 15:23:41 +0300536 self._note_relocs_for_section(section)
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300537 addr = section['sh_addr']
538 data = section.data()
539 dataptr = 0
540
541 while dataptr < len(data):
542 bytesleft = len(data) - dataptr
543 # chunks of 16 bytes per line
544 linebytes = 16 if bytesleft > 16 else bytesleft
545
546 self._emit(' %s ' % self._format_hex(addr, fieldsize=8))
547 for i in range(16):
548 if i < linebytes:
Eli Bendersky79271e92012-01-27 10:25:47 +0200549 self._emit('%2.2x' % byte2int(data[dataptr + i]))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300550 else:
551 self._emit(' ')
552 if i % 4 == 3:
553 self._emit(' ')
554
555 for i in range(linebytes):
Eli Bendersky79271e92012-01-27 10:25:47 +0200556 c = data[dataptr + i : dataptr + i + 1]
557 if byte2int(c[0]) >= 32 and byte2int(c[0]) < 0x7f:
558 self._emit(bytes2str(c))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300559 else:
Eli Bendersky79271e92012-01-27 10:25:47 +0200560 self._emit(bytes2str(b'.'))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300561
562 self._emitline()
563 addr += linebytes
564 dataptr += linebytes
565
566 self._emitline()
567
Eli Bendersky53e86db2011-09-18 06:04:30 +0300568 def display_string_dump(self, section_spec):
569 """ Display a strings dump of a section. section_spec is either a
570 section number or a name.
571 """
eliben54e39b22011-09-19 13:10:57 +0300572 section = self._section_from_spec(section_spec)
573 if section is None:
Eli Bendersky53e86db2011-09-18 06:04:30 +0300574 self._emitline("Section '%s' does not exist in the file!" % (
575 section_spec))
576 return
577
Eli Bendersky79271e92012-01-27 10:25:47 +0200578 self._emitline("\nString dump of section '%s':" % bytes2str(section.name))
Eli Bendersky53e86db2011-09-18 06:04:30 +0300579
580 found = False
581 data = section.data()
582 dataptr = 0
583
584 while dataptr < len(data):
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800585 while ( dataptr < len(data) and
Eli Bendersky79271e92012-01-27 10:25:47 +0200586 not (32 <= byte2int(data[dataptr]) <= 127)):
Eli Bendersky53e86db2011-09-18 06:04:30 +0300587 dataptr += 1
588
589 if dataptr >= len(data):
590 break
591
592 endptr = dataptr
Eli Bendersky79271e92012-01-27 10:25:47 +0200593 while endptr < len(data) and byte2int(data[endptr]) != 0:
Eli Bendersky53e86db2011-09-18 06:04:30 +0300594 endptr += 1
595
596 found = True
597 self._emitline(' [%6x] %s' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200598 dataptr, bytes2str(data[dataptr:endptr])))
Eli Bendersky53e86db2011-09-18 06:04:30 +0300599
600 dataptr = endptr
601
602 if not found:
603 self._emitline(' No strings found in this section.')
604 else:
605 self._emitline()
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300606
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200607 def display_debug_dump(self, dump_what):
eliben0fc47af2011-10-02 13:47:12 +0200608 """ Dump a DWARF section
609 """
610 self._init_dwarfinfo()
611 if self._dwarfinfo is None:
612 return
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800613
Eli Bendersky3501f9f2011-12-09 12:29:06 +0200614 set_global_machine_arch(self.elffile.get_machine_arch())
615
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200616 if dump_what == 'info':
eliben0fc47af2011-10-02 13:47:12 +0200617 self._dump_debug_info()
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200618 elif dump_what == 'decodedline':
619 self._dump_debug_line_programs()
Eli Bendersky7241ff02011-12-12 06:40:34 +0200620 elif dump_what == 'frames':
621 self._dump_debug_frames()
Eli Bendersky8670bb32011-12-15 16:11:06 +0200622 elif dump_what == 'frames-interp':
623 self._dump_debug_frames_interp()
eliben0fc47af2011-10-02 13:47:12 +0200624 else:
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200625 self._emitline('debug dump not yet supported for "%s"' % dump_what)
eliben0fc47af2011-10-02 13:47:12 +0200626
Yann Rouillard7b246702013-05-27 22:44:28 +0200627 def _format_hex(self, addr, fieldsize=None, fullhex=False, lead0x=True,
628 alternate=False):
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300629 """ Format an address into a hexadecimal string.
Eli Benderskyd62928d2011-09-09 10:05:57 +0300630
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300631 fieldsize:
632 Size of the hexadecimal field (with leading zeros to fit the
633 address into. For example with fieldsize=8, the format will
634 be %08x
635 If None, the minimal required field size will be used.
636
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300637 fullhex:
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800638 If True, override fieldsize to set it to the maximal size
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300639 needed for the elfclass
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300640
641 lead0x:
642 If True, leading 0x is added
Yann Rouillard7b246702013-05-27 22:44:28 +0200643
644 alternate:
645 If True, override lead0x to emulate the alternate
646 hexadecimal form specified in format string with the #
647 character: only non-zero values are prefixed with 0x.
648 This form is used by readelf.
Eli Benderskyd62928d2011-09-09 10:05:57 +0300649 """
Yann Rouillard7b246702013-05-27 22:44:28 +0200650 if alternate:
651 if addr == 0:
652 lead0x = False
653 else:
654 lead0x = True
655 fieldsize -= 2
656
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300657 s = '0x' if lead0x else ''
658 if fullhex:
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300659 fieldsize = 8 if self.elffile.elfclass == 32 else 16
660 if fieldsize is None:
661 field = '%x'
Eli Bendersky6a12cde2011-09-09 10:23:16 +0300662 else:
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300663 field = '%' + '0%sx' % fieldsize
664 return s + field % addr
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800665
Yann Rouillard7b246702013-05-27 22:44:28 +0200666
667 def _print_version_section_header(self, version_section, name, lead0x=True, indent=1):
668 """ Print a section header of one version related section (versym, verneed or verdef)
669 with some options to accomodate readelf little differences between each header
670 (e.g. indentation and 0x prefixing).
671 """
672 if hasattr(version_section, 'num_versions'):
673 num_entries = version_section.num_versions()
674 else:
675 num_entries = version_section.num_symbols()
676
677 self._emitline("\n%s section '%s' contains %s entries:" %
678 (name, bytes2str(version_section.name), num_entries))
679 self._emitline('%sAddr: %s Offset: %s Link: %i (%s)' %
680 (' ' * indent,
681 self._format_hex(version_section['sh_addr'], fieldsize=16, lead0x=lead0x),
682 self._format_hex(version_section['sh_offset'], fieldsize=6, lead0x=True),
683 version_section['sh_link'],
684 bytes2str(self.elffile.get_section(version_section['sh_link']).name)))
685
686
687
688 def _init_versioninfo(self):
689 """ Search and initialize informations about version related sections
690 and the kind of versioning used (GNU or Solaris).
691 """
692 if self._versioninfo is not None:
693 return
694
695 self._versioninfo = { 'versym': None, 'verdef': None,
696 'verneed': None, 'type': None }
697
698 for section in self.elffile.iter_sections():
Yann Rouillardac9b3c82013-05-29 23:23:27 +0200699 if isinstance(section, GNUVerSymTableSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200700 self._versioninfo['versym'] = section
Yann Rouillardac9b3c82013-05-29 23:23:27 +0200701 elif isinstance(section, GNUVerDefTableSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200702 self._versioninfo['verdef'] = section
Yann Rouillardac9b3c82013-05-29 23:23:27 +0200703 elif isinstance(section, GNUVerNeedTableSection):
Yann Rouillard7b246702013-05-27 22:44:28 +0200704 self._versioninfo['verneed'] = section
705 elif isinstance(section, DynamicSection):
706 for tag in section.iter_tags():
707 if tag['d_tag'] == 'DT_VERSYM':
708 self._versioninfo['type'] = 'GNU'
709 break
710
711 if not self._versioninfo['type'] and (
712 self._versioninfo['verneed'] or self._versioninfo['verdef']):
713 self._versioninfo['type'] = 'Solaris'
714
715
716 def _symbol_version(self, nsym):
717 """ Return a dict containing information on the
718 or None if no version information is available
719 """
720 self._init_versioninfo()
721
722 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':
734 # In GNU versioning mode, the highest bit is used to
735 # store wether the symbol is hidden or not
736 if index & 0x8000:
737 index &= ~0x8000;
738 symbol_version['hidden'] = True
739
740 if (self._versioninfo['verdef'] and
741 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
754
eliben54e39b22011-09-19 13:10:57 +0300755 def _section_from_spec(self, spec):
756 """ Retrieve a section given a "spec" (either number or name).
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300757 Return None if no such section exists in the file.
758 """
759 try:
760 num = int(spec)
eliben54e39b22011-09-19 13:10:57 +0300761 if num < self.elffile.num_sections():
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800762 return self.elffile.get_section(num)
eliben54e39b22011-09-19 13:10:57 +0300763 else:
764 return None
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300765 except ValueError:
766 # Not a number. Must be a name then
Eli Bendersky79271e92012-01-27 10:25:47 +0200767 return self.elffile.get_section_by_name(str2bytes(spec))
Eli Benderskyc4a4c072011-09-17 15:28:28 +0300768
Eli Benderskyadf707a2011-09-23 15:23:41 +0300769 def _note_relocs_for_section(self, section):
770 """ If there are relocation sections pointing to the givne section,
771 emit a note about it.
772 """
773 for relsec in self.elffile.iter_sections():
774 if isinstance(relsec, RelocationSection):
775 info_idx = relsec['sh_info']
776 if self.elffile.get_section(info_idx) == section:
777 self._emitline(' Note: This section has relocations against it, but these have NOT been applied to this dump.')
778 return
779
eliben0fc47af2011-10-02 13:47:12 +0200780 def _init_dwarfinfo(self):
781 """ Initialize the DWARF info contained in the file and assign it to
782 self._dwarfinfo.
783 Leave self._dwarfinfo at None if no DWARF info was found in the file
784 """
785 if self._dwarfinfo is not None:
786 return
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800787
eliben0fc47af2011-10-02 13:47:12 +0200788 if self.elffile.has_dwarf_info():
789 self._dwarfinfo = self.elffile.get_dwarf_info()
790 else:
791 self._dwarfinfo = None
792
793 def _dump_debug_info(self):
794 """ Dump the debugging info section.
795 """
eliben985c2c12011-11-14 17:53:23 +0200796 self._emitline('Contents of the .debug_info section:\n')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800797
eliben0fc47af2011-10-02 13:47:12 +0200798 # Offset of the .debug_info section in the stream
Eli Bendersky149315a2011-11-24 08:12:37 +0200799 section_offset = self._dwarfinfo.debug_info_sec.global_offset
Eli Bendersky6062bf72011-11-23 06:54:40 +0200800
eliben0fc47af2011-10-02 13:47:12 +0200801 for cu in self._dwarfinfo.iter_CUs():
eliben985c2c12011-11-14 17:53:23 +0200802 self._emitline(' Compilation Unit @ offset %s:' %
Eli Bendersky149315a2011-11-24 08:12:37 +0200803 self._format_hex(cu.cu_offset))
eliben0fc47af2011-10-02 13:47:12 +0200804 self._emitline(' Length: %s (%s)' % (
805 self._format_hex(cu['unit_length']),
806 '%s-bit' % cu.dwarf_format()))
807 self._emitline(' Version: %s' % cu['version']),
Eli Bendersky7eba7182013-03-30 17:23:36 -0700808 self._emitline(' Abbrev Offset: %s' % (
809 self._format_hex(cu['debug_abbrev_offset']))),
eliben0fc47af2011-10-02 13:47:12 +0200810 self._emitline(' Pointer Size: %s' % cu['address_size'])
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800811
812 # The nesting depth of each DIE within the tree of DIEs must be
eliben0fc47af2011-10-02 13:47:12 +0200813 # displayed. To implement this, a counter is incremented each time
814 # the current DIE has children, and decremented when a null die is
815 # encountered. Due to the way the DIE tree is serialized, this will
816 # correctly reflect the nesting depth
817 #
818 die_depth = 0
819 for die in cu.iter_DIEs():
Eli Bendersky9aec9d82013-03-30 16:39:30 -0700820 self._emitline(' <%s><%x>: Abbrev Number: %s%s' % (
elibenaee11d22011-10-26 10:42:34 +0200821 die_depth,
Eli Bendersky149315a2011-11-24 08:12:37 +0200822 die.offset,
elibenaee11d22011-10-26 10:42:34 +0200823 die.abbrev_code,
Eli Bendersky9aec9d82013-03-30 16:39:30 -0700824 (' (%s)' % die.tag) if not die.is_null() else ''))
825 if die.is_null():
826 die_depth -= 1
827 continue
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800828
Eli Bendersky79271e92012-01-27 10:25:47 +0200829 for attr in itervalues(die.attributes):
Eli Bendersky871ad0c2011-12-16 08:13:48 +0200830 name = attr.name
831 # Unknown attribute values are passed-through as integers
832 if isinstance(name, int):
833 name = 'Unknown AT value: %x' % name
elibenaee11d22011-10-26 10:42:34 +0200834 self._emitline(' <%2x> %-18s: %s' % (
Eli Bendersky149315a2011-11-24 08:12:37 +0200835 attr.offset,
Eli Bendersky871ad0c2011-12-16 08:13:48 +0200836 name,
eliben3bc9c342011-10-26 13:10:58 +0200837 describe_attr_value(
Eli Bendersky5be3be82011-10-27 14:28:12 +0200838 attr, die, section_offset)))
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800839
eliben0fc47af2011-10-02 13:47:12 +0200840 if die.has_children:
841 die_depth += 1
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800842
Eli Benderskyf5670e82011-11-24 09:05:44 +0200843 self._emitline()
eliben0fc47af2011-10-02 13:47:12 +0200844
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200845 def _dump_debug_line_programs(self):
846 """ Dump the (decoded) line programs from .debug_line
847 The programs are dumped in the order of the CUs they belong to.
848 """
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200849 self._emitline('Decoded dump of debug contents of section .debug_line:\n')
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200850
851 for cu in self._dwarfinfo.iter_CUs():
852 lineprogram = self._dwarfinfo.line_program_for_CU(cu)
853
Eli Bendersky7eba7182013-03-30 17:23:36 -0700854 cu_filename = bytes2str(lineprogram['file_entry'][0].name)
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200855 if len(lineprogram['include_directory']) > 0:
Eli Bendersky7eba7182013-03-30 17:23:36 -0700856 dir_index = lineprogram['file_entry'][0].dir_index
857 if dir_index > 0:
858 dir = lineprogram['include_directory'][dir_index - 1]
859 else:
Eli Benderskyccdb5542013-03-31 14:19:21 -0700860 dir = b'.'
Eli Bendersky7eba7182013-03-30 17:23:36 -0700861 cu_filename = '%s/%s' % (bytes2str(dir), cu_filename)
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200862
863 self._emitline('CU: %s:' % cu_filename)
864 self._emitline('File name Line number Starting address')
865
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200866 # Print each state's file, line and address information. For some
867 # instructions other output is needed to be compatible with
868 # readelf.
869 for entry in lineprogram.get_entries():
870 state = entry.state
871 if state is None:
872 # Special handling for commands that don't set a new state
873 if entry.command == DW_LNS_set_file:
874 file_entry = lineprogram['file_entry'][entry.args[0] - 1]
875 if file_entry.dir_index == 0:
876 # current directory
877 self._emitline('\n./%s:[++]' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200878 bytes2str(file_entry.name)))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200879 else:
880 self._emitline('\n%s/%s:' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200881 bytes2str(lineprogram['include_directory'][file_entry.dir_index - 1]),
882 bytes2str(file_entry.name)))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200883 elif entry.command == DW_LNE_define_file:
884 self._emitline('%s:' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200885 bytes2str(lineprogram['include_directory'][entry.args[0].dir_index])))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200886 elif not state.end_sequence:
887 # readelf doesn't print the state after end_sequence
888 # instructions. I think it's a bug but to be compatible
889 # I don't print them too.
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200890 self._emitline('%-35s %11d %18s' % (
Eli Bendersky79271e92012-01-27 10:25:47 +0200891 bytes2str(lineprogram['file_entry'][state.file - 1].name),
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200892 state.line,
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800893 '0' if state.address == 0 else
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200894 self._format_hex(state.address)))
Eli Benderskybf83b1b2011-12-06 06:48:10 +0200895 if entry.command == DW_LNS_copy:
896 # Another readelf oddity...
897 self._emitline()
Eli Bendersky5ec2dde2011-12-04 07:05:31 +0200898
Eli Bendersky7241ff02011-12-12 06:40:34 +0200899 def _dump_debug_frames(self):
900 """ Dump the raw frame information from .debug_frame
901 """
Eli Bendersky47a47112011-12-14 06:54:09 +0200902 if not self._dwarfinfo.has_CFI():
903 return
Eli Bendersky7241ff02011-12-12 06:40:34 +0200904 self._emitline('Contents of the .debug_frame section:')
905
906 for entry in self._dwarfinfo.CFI_entries():
907 if isinstance(entry, CIE):
908 self._emitline('\n%08x %08x %08x CIE' % (
909 entry.offset, entry['length'], entry['CIE_id']))
910 self._emitline(' Version: %d' % entry['version'])
Eli Bendersky79271e92012-01-27 10:25:47 +0200911 self._emitline(' Augmentation: "%s"' % bytes2str(entry['augmentation']))
Eli Bendersky7241ff02011-12-12 06:40:34 +0200912 self._emitline(' Code alignment factor: %u' % entry['code_alignment_factor'])
913 self._emitline(' Data alignment factor: %d' % entry['data_alignment_factor'])
914 self._emitline(' Return address column: %d' % entry['return_address_register'])
Eli Bendersky47a47112011-12-14 06:54:09 +0200915 self._emitline()
Eli Bendersky7241ff02011-12-12 06:40:34 +0200916 else: # FDE
917 self._emitline('\n%08x %08x %08x FDE cie=%08x pc=%08x..%08x' % (
918 entry.offset,
919 entry['length'],
920 entry['CIE_pointer'],
921 entry.cie.offset,
922 entry['initial_location'],
923 entry['initial_location'] + entry['address_range']))
924
Eli Bendersky47a47112011-12-14 06:54:09 +0200925 self._emit(describe_CFI_instructions(entry))
926 self._emitline()
Eli Bendersky7241ff02011-12-12 06:40:34 +0200927
Eli Bendersky8670bb32011-12-15 16:11:06 +0200928 def _dump_debug_frames_interp(self):
929 """ Dump the interpreted (decoded) frame information from .debug_frame
930 """
931 if not self._dwarfinfo.has_CFI():
932 return
933
934 self._emitline('Contents of the .debug_frame section:')
935
936 for entry in self._dwarfinfo.CFI_entries():
937 if isinstance(entry, CIE):
938 self._emitline('\n%08x %08x %08x CIE "%s" cf=%d df=%d ra=%d' % (
939 entry.offset,
940 entry['length'],
941 entry['CIE_id'],
Eli Bendersky79271e92012-01-27 10:25:47 +0200942 bytes2str(entry['augmentation']),
Eli Bendersky8670bb32011-12-15 16:11:06 +0200943 entry['code_alignment_factor'],
944 entry['data_alignment_factor'],
945 entry['return_address_register']))
Eli Bendersky4682c962011-12-16 06:39:49 +0200946 ra_regnum = entry['return_address_register']
Eli Bendersky8670bb32011-12-15 16:11:06 +0200947 else: # FDE
948 self._emitline('\n%08x %08x %08x FDE cie=%08x pc=%08x..%08x' % (
949 entry.offset,
950 entry['length'],
951 entry['CIE_pointer'],
952 entry.cie.offset,
953 entry['initial_location'],
954 entry['initial_location'] + entry['address_range']))
Eli Bendersky4682c962011-12-16 06:39:49 +0200955 ra_regnum = entry.cie['return_address_register']
Eli Bendersky8670bb32011-12-15 16:11:06 +0200956
957 # Print the heading row for the decoded table
958 self._emit(' LOC')
959 self._emit(' ' if entry.structs.address_size == 4 else ' ')
Eli Bendersky4682c962011-12-16 06:39:49 +0200960 self._emit(' CFA ')
Eli Bendersky8670bb32011-12-15 16:11:06 +0200961
Eli Bendersky4682c962011-12-16 06:39:49 +0200962 # Decode the table nad look at the registers it describes.
963 # We build reg_order here to match readelf's order. In particular,
964 # registers are sorted by their number, and the register matching
965 # ra_regnum is always listed last with a special heading.
Eli Bendersky8670bb32011-12-15 16:11:06 +0200966 decoded_table = entry.get_decoded()
Eli Bendersky4682c962011-12-16 06:39:49 +0200967 reg_order = sorted(ifilter(
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800968 lambda r: r != ra_regnum,
Eli Bendersky4682c962011-12-16 06:39:49 +0200969 decoded_table.reg_order))
970
971 # Headings for the registers
972 for regnum in reg_order:
Eli Bendersky8670bb32011-12-15 16:11:06 +0200973 self._emit('%-6s' % describe_reg_name(regnum))
974 self._emitline('ra ')
Eli Bendersky0aaa6b02013-01-06 21:10:38 -0800975
Eli Bendersky4682c962011-12-16 06:39:49 +0200976 # Now include ra_regnum in reg_order to print its values similarly
977 # to the other registers.
978 reg_order.append(ra_regnum)
979 for line in decoded_table.table:
980 self._emit(self._format_hex(
981 line['pc'], fullhex=True, lead0x=False))
982 self._emit(' %-9s' % describe_CFI_CFA_rule(line['cfa']))
Eli Bendersky8670bb32011-12-15 16:11:06 +0200983
Eli Bendersky4682c962011-12-16 06:39:49 +0200984 for regnum in reg_order:
985 if regnum in line:
986 s = describe_CFI_register_rule(line[regnum])
987 else:
988 s = 'u'
989 self._emit('%-6s' % s)
990 self._emitline()
991 self._emitline()
Eli Bendersky8670bb32011-12-15 16:11:06 +0200992
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300993 def _emit(self, s=''):
Eli Bendersky933f6992011-09-09 08:11:06 +0300994 """ Emit an object to output
995 """
996 self.output.write(str(s))
Eli Benderskyd62928d2011-09-09 10:05:57 +0300997
Eli Bendersky26de2ac2011-09-13 06:50:28 +0300998 def _emitline(self, s=''):
Eli Bendersky933f6992011-09-09 08:11:06 +0300999 """ Emit an object to output, followed by a newline
1000 """
1001 self.output.write(str(s) + '\n')
1002
1003
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001004SCRIPT_DESCRIPTION = 'Display information about the contents of ELF format files'
1005VERSION_STRING = '%%prog: based on pyelftools %s' % __version__
1006
1007
Eli Bendersky0193fb82011-11-26 16:16:16 +02001008def main(stream=None):
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001009 # parse the command-line arguments and invoke ReadElf
Eli Bendersky40eb1702011-09-16 16:59:52 +03001010 optparser = OptionParser(
Eli Benderskyecde41b2011-09-16 17:16:20 +03001011 usage='usage: %prog [options] <elf-file>',
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001012 description=SCRIPT_DESCRIPTION,
Eli Bendersky40eb1702011-09-16 16:59:52 +03001013 add_help_option=False, # -h is a real option of readelf
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001014 prog='readelf.py',
1015 version=VERSION_STRING)
Mike Frysinger5699e182013-03-23 02:47:32 -04001016 optparser.add_option('-d', '--dynamic',
1017 action='store_true', dest='show_dynamic_tags',
1018 help='Display the dynamic section')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001019 optparser.add_option('-H', '--help',
1020 action='store_true', dest='help',
1021 help='Display this information')
1022 optparser.add_option('-h', '--file-header',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001023 action='store_true', dest='show_file_header',
1024 help='Display the ELF file header')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001025 optparser.add_option('-l', '--program-headers', '--segments',
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001026 action='store_true', dest='show_program_header',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001027 help='Display the program headers')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001028 optparser.add_option('-S', '--section-headers', '--sections',
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001029 action='store_true', dest='show_section_header',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001030 help="Display the sections' headers")
Eli Bendersky40eb1702011-09-16 16:59:52 +03001031 optparser.add_option('-e', '--headers',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001032 action='store_true', dest='show_all_headers',
1033 help='Equivalent to: -h -l -S')
Eli Bendersky40eb1702011-09-16 16:59:52 +03001034 optparser.add_option('-s', '--symbols', '--syms',
Eli Benderskyecde41b2011-09-16 17:16:20 +03001035 action='store_true', dest='show_symbols',
1036 help='Display the symbol table')
Eli Bendersky84066b22011-09-20 06:48:52 +03001037 optparser.add_option('-r', '--relocs',
1038 action='store_true', dest='show_relocs',
1039 help='Display the relocations (if present)')
Eli Benderskyc4a4c072011-09-17 15:28:28 +03001040 optparser.add_option('-x', '--hex-dump',
1041 action='store', dest='show_hex_dump', metavar='<number|name>',
1042 help='Dump the contents of section <number|name> as bytes')
Eli Bendersky53e86db2011-09-18 06:04:30 +03001043 optparser.add_option('-p', '--string-dump',
1044 action='store', dest='show_string_dump', metavar='<number|name>',
1045 help='Dump the contents of section <number|name> as strings')
Yann Rouillard7b246702013-05-27 22:44:28 +02001046 optparser.add_option('-V', '--version-info',
1047 action='store_true', dest='show_version_info',
1048 help='Display the version sections (if present)')
eliben0fc47af2011-10-02 13:47:12 +02001049 optparser.add_option('--debug-dump',
Eli Bendersky1a516a32011-12-22 15:22:00 +02001050 action='store', dest='debug_dump_what', metavar='<what>',
1051 help=(
1052 'Display the contents of DWARF debug sections. <what> can ' +
1053 'one of {info,decodedline,frames,frames-interp}'))
Eli Bendersky53e86db2011-09-18 06:04:30 +03001054
Eli Bendersky933f6992011-09-09 08:11:06 +03001055 options, args = optparser.parse_args()
1056
Eli Bendersky40eb1702011-09-16 16:59:52 +03001057 if options.help or len(args) == 0:
1058 optparser.print_help()
1059 sys.exit(0)
1060
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001061 if options.show_all_headers:
1062 do_file_header = do_section_header = do_program_header = True
1063 else:
1064 do_file_header = options.show_file_header
1065 do_section_header = options.show_section_header
1066 do_program_header = options.show_program_header
1067
Eli Bendersky933f6992011-09-09 08:11:06 +03001068 with open(args[0], 'rb') as file:
1069 try:
Eli Bendersky0193fb82011-11-26 16:16:16 +02001070 readelf = ReadElf(file, stream or sys.stdout)
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001071 if do_file_header:
1072 readelf.display_file_header()
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001073 if do_section_header:
1074 readelf.display_section_headers(
1075 show_heading=not do_file_header)
Eli Bendersky2fc0f2a2011-09-17 10:39:29 +03001076 if do_program_header:
1077 readelf.display_program_headers(
1078 show_heading=not do_file_header)
Mike Frysinger5699e182013-03-23 02:47:32 -04001079 if options.show_dynamic_tags:
1080 readelf.display_dynamic_tags()
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001081 if options.show_symbols:
1082 readelf.display_symbol_tables()
Eli Bendersky84066b22011-09-20 06:48:52 +03001083 if options.show_relocs:
1084 readelf.display_relocations()
Yann Rouillard7b246702013-05-27 22:44:28 +02001085 if options.show_version_info:
1086 readelf.display_version_info()
Eli Benderskyc4a4c072011-09-17 15:28:28 +03001087 if options.show_hex_dump:
1088 readelf.display_hex_dump(options.show_hex_dump)
Eli Bendersky53e86db2011-09-18 06:04:30 +03001089 if options.show_string_dump:
1090 readelf.display_string_dump(options.show_string_dump)
Eli Bendersky5ec2dde2011-12-04 07:05:31 +02001091 if options.debug_dump_what:
1092 readelf.display_debug_dump(options.debug_dump_what)
Eli Bendersky933f6992011-09-09 08:11:06 +03001093 except ELFError as ex:
Eli Bendersky0b27ba42011-09-17 06:44:02 +03001094 sys.stderr.write('ELF error: %s\n' % ex)
Eli Bendersky933f6992011-09-09 08:11:06 +03001095 sys.exit(1)
1096
1097
Eli Bendersky0193fb82011-11-26 16:16:16 +02001098def profile_main():
1099 # Run 'main' redirecting its output to readelfout.txt
1100 # Saves profiling information in readelf.profile
1101 PROFFILE = 'readelf.profile'
1102 import cProfile
1103 cProfile.run('main(open("readelfout.txt", "w"))', PROFFILE)
1104
1105 # Dig in some profiling stats
1106 import pstats
1107 p = pstats.Stats(PROFFILE)
1108 p.sort_stats('cumulative').print_stats(25)
1109
1110
Eli Bendersky933f6992011-09-09 08:11:06 +03001111#-------------------------------------------------------------------------------
1112if __name__ == '__main__':
Eli Bendersky4f4d80c2011-11-26 16:49:27 +02001113 main()
1114 #profile_main()
Eli Bendersky0193fb82011-11-26 16:16:16 +02001115
Eli Bendersky933f6992011-09-09 08:11:06 +03001116