From 26de2ac0a89bb35b522f445cc6cd52c094bceef6 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Tue, 13 Sep 2011 06:50:28 +0300 Subject: [PATCH] implemented some of program header display --- elftools/elf/descriptions.py | 31 ++++++++++++++ scripts/readelf.py | 79 ++++++++++++++++++++++++++++++------ 2 files changed, 97 insertions(+), 13 deletions(-) diff --git a/elftools/elf/descriptions.py b/elftools/elf/descriptions.py index ff149a5..258fc67 100644 --- a/elftools/elf/descriptions.py +++ b/elftools/elf/descriptions.py @@ -7,6 +7,7 @@ # This code is in the public domain #------------------------------------------------------------------------------- from .enums import ENUM_E_VERSION +from .constants import P_FLAGS def describe_ei_class(x): @@ -33,6 +34,15 @@ def describe_e_machine(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(): @@ -96,3 +106,24 @@ _DESCR_E_MACHINE = dict( 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', +} + + diff --git a/scripts/readelf.py b/scripts/readelf.py index 427ee8f..382f943 100644 --- a/scripts/readelf.py +++ b/scripts/readelf.py @@ -22,7 +22,8 @@ from elftools.elf.elffile import ELFFile 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, + ) @@ -65,7 +66,7 @@ class ReadElf(object): 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)') @@ -73,7 +74,7 @@ class ReadElf(object): 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)' % @@ -87,31 +88,81 @@ class ReadElf(object): 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') @@ -125,6 +176,8 @@ def main(): 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) -- 2.30.2