implemented some of program header display
authorEli Bendersky <eliben@gmail.com>
Tue, 13 Sep 2011 03:50:28 +0000 (06:50 +0300)
committerEli Bendersky <eliben@gmail.com>
Tue, 13 Sep 2011 03:50:28 +0000 (06:50 +0300)
elftools/elf/descriptions.py
scripts/readelf.py

index ff149a528c8ea726dda2031bdabc79b8b043d54b..258fc672b7567c6aca2b4a03b031c4e11e4a6478 100644 (file)
@@ -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',
+}
+
+
index 427ee8f80abd9346a72f52f48d2334c0347c2b3d..382f943809707097d03650986e89706b86dec58a 100644 (file)
@@ -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)