# This code is in the public domain
#-------------------------------------------------------------------------------
from .enums import ENUM_E_VERSION
+from .constants import P_FLAGS
def describe_ei_class(x):
def describe_e_version_numeric(x):
return '0x%x' % ENUM_E_VERSION[x]
+def describe_p_type(x):
+ return _DESCR_P_TYPE.get(x, _unknown())
+
+def describe_p_flags(x):
+ s = ''
+ for flag in (P_FLAGS.PF_R, P_FLAGS.PF_W, P_FLAGS.PF_X):
+ s += _DESCR_P_FLAGS[flag] if (x & flag) else ' '
+ return s
+
#-------------------------------------------------------------------------------
def _unknown():
EM_AVR='Atmel AVR 8-bit microcontroller',
RESERVED='RESERVED',
)
+
+_DESCR_P_TYPE = dict(
+ PT_NULL='NULL',
+ PT_LOAD='LOAD',
+ PT_DYNAMIC='DYNAMIC',
+ PT_INTERP='INTERP',
+ PT_NOTE='NOTE',
+ PT_SHLIB='SHLIB',
+ PT_PHDR='PHDR',
+ PT_GNU_EH_FRAME='GNU_EH_FRAME',
+ PT_GNU_STACK='GNU_STACK',
+ PT_GNU_RELRO='GNU_RELR0',
+)
+
+_DESCR_P_FLAGS = {
+ P_FLAGS.PF_X: 'E',
+ P_FLAGS.PF_R: 'R',
+ P_FLAGS.PF_W: 'W',
+}
+
+
from elftools.elf.descriptions import (
describe_ei_class, describe_ei_data, describe_ei_version,
describe_ei_osabi, describe_e_type, describe_e_machine,
- describe_e_version_numeric,
+ describe_e_version_numeric, describe_p_type, describe_p_flags,
+
)
self._emitline(' Version: %s' %
describe_e_version_numeric(header['e_version']))
self._emitline(' Entry point address: %s' %
- self._format_addr(header['e_entry']))
+ self._format_hex(header['e_entry']))
self._emit(' Start of program headers %s' %
header['e_phoff'])
self._emitline(' (bytes into file)')
header['e_shoff'])
self._emitline(' (bytes into file)')
self._emitline(' Flags: %s' %
- self._format_addr(header['e_flags']))
+ self._format_hex(header['e_flags']))
self._emitline(' Size of this header: %s (bytes)' %
header['e_ehsize'])
self._emitline(' Size of program headers: %s (bytes)' %
self._emitline(' Section header string table index: %s' %
header['e_shstrndx'])
- def _format_addr(self, addr, fullhex=False, lead0x=True):
+ def display_program_headers(self):
+ """ Display the ELF program headers
+ """
+ self._emitline()
+ elfheader = self.elffile.header
+ self._emitline('Elf file type is %s' %
+ describe_e_type(elfheader['e_type']))
+ self._emitline('Entry point is %s' %
+ self._format_hex(elfheader['e_entry']))
+ self._emitline('There are %s program headers, starting at offset %s' % (
+ elfheader['e_phnum'], elfheader['e_phoff']))
+
+ self._emitline('\nProgram headers:')
+
+ # Now comes the table of program headers with their attributes. Note
+ # that due to different formatting constraints of 32-bit and 64-bit
+ # addresses, there are some conditions on elfclass here.
+ #
+ # First comes the table heading
+ #
+ if self.elffile.elfclass == 32:
+ self._emitline(' Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align')
+ else:
+ self._emitline(' Type Offset VirtAddr PhysAddr')
+ self._emitline(' FileSiz MemSiz Flags Align')
+
+ # Now the entries
+ #
+ for segment in self.elffile.iter_segments():
+ self._emit(' %-14s ' % describe_p_type(segment['p_type']))
+
+ if self.elffile.elfclass == 32:
+ self._emitline('%s %s %s %s %s %-3s %s' % (
+ self._format_hex(segment['p_offset'], fieldsize=6),
+ self._format_hex(segment['p_vaddr'], fullhex=True),
+ self._format_hex(segment['p_paddr'], fullhex=True),
+ self._format_hex(segment['p_filesz'], fieldsize=5),
+ self._format_hex(segment['p_memsz'], fieldsize=5),
+ describe_p_flags(segment['p_flags']),
+ self._format_hex(segment['p_align'])))
+
+
+
+
+ def _format_hex(self, addr, fieldsize=None, fullhex=False, lead0x=True):
""" Format an address into a hexadecimal string.
+ fieldsize:
+ Size of the hexadecimal field (with leading zeros to fit the
+ address into. For example with fieldsize=8, the format will
+ be %08x
+ If None, the minimal required field size will be used.
+
fullhex:
- If True, include leading zeros in the address, adjusted for
- the elfclass.
+ If True, override fieldsize to set it to the maximal size
+ needed for the elfclass
lead0x:
If True, leading 0x is added
"""
s = '0x' if lead0x else ''
if fullhex:
- if self.elffile.elfclass == 32:
- return s + '%08x' % addr
- else:
- return s + '%016x' % addr
+ fieldsize = 8 if self.elffile.elfclass == 32 else 16
+ if fieldsize is None:
+ field = '%x'
else:
- return s + '%x' % addr
+ field = '%' + '0%sx' % fieldsize
+ return s + field % addr
- def _emit(self, s):
+ def _emit(self, s=''):
""" Emit an object to output
"""
self.output.write(str(s))
- def _emitline(self, s):
+ def _emitline(self, s=''):
""" Emit an object to output, followed by a newline
"""
self.output.write(str(s) + '\n')
try:
readelf = ReadElf(file, sys.stdout)
readelf.display_file_header()
+ print '----'
+ readelf.display_program_headers()
except ELFError as ex:
sys.stderr.write('ELF read error: %s\n' % ex)
sys.exit(1)