Implementing reading the INTERP path in segments
authorEli Bendersky <eliben@gmail.com>
Wed, 14 Sep 2011 02:58:06 +0000 (05:58 +0300)
committerEli Bendersky <eliben@gmail.com>
Wed, 14 Sep 2011 02:58:06 +0000 (05:58 +0300)
elftools/common/utils.py
elftools/elf/elffile.py
elftools/elf/segments.py
scripts/readelf.py
z.py

index 666176f6b8c71d13c6b7eccb89f4b6535f065d5e..477d7ee52905f7640f8bf734d503412ac81b29dd 100644 (file)
@@ -10,11 +10,11 @@ from .exceptions import ELFParseError, ELFError
 
 
 def struct_parse(struct, stream, stream_pos=None):
-    """ Convenience function for using the given struct to parse a stream (at
-        its current location).
+    """ Convenience function for using the given struct to parse a stream.
         If stream_pos is provided, the stream is seeked to this position before
-        the parsing is done.
-        Wraps the error thrown by construct with our own error.
+        the parsing is done. Otherwise, the current position of the stream is
+        used.
+        Wraps the error thrown by construct with ELFParseError.
     """
     try:
         if stream_pos is not None:
index aee1b5434097008329bde7d645ef1a9f960d9fd1..32373e9760a711cef4ef69dc197a5dbf123d6ec1 100644 (file)
@@ -11,7 +11,7 @@ from ..common.utils import struct_parse, elf_assert
 from ..construct import ConstructError
 from .structs import ELFStructs
 from .sections import Section, StringTableSection, SymbolTableSection
-from .segments import Segment
+from .segments import Segment, InterpSegment
 
 
 class ELFFile(object):
@@ -69,7 +69,7 @@ class ELFFile(object):
         """ Get the segment at index #n from the file (Segment object)
         """
         segment_header = self._get_segment_header(n)
-        return Segment(segment_header, self.stream)
+        return self._make_segment(segment_header)
     
     def iter_segments(self):
         """ Yield all the segments in the file
@@ -121,6 +121,15 @@ class ELFFile(object):
         """
         return self['e_phoff'] + n * self['e_phentsize']
     
+    def _make_segment(self, segment_header):
+        """ Create a Segment object of the appropriate type
+        """
+        segtype = segment_header['p_type']
+        if segtype == 'PT_INTERP':
+            return InterpSegment(segment_header, self.stream)
+        else:
+            return Segment(segment_header, self.stream)
+
     def _get_section_header(self, n):
         """ Find the header of section #n, parse it and return the struct 
         """
index a583de0fe943318648244335fca8b1d81ecacbdc..5e61b2870d21ca7dd9bf189f8351b0d2e1467a2a 100644 (file)
@@ -6,6 +6,9 @@
 # Eli Bendersky (eliben@gmail.com)
 # This code is in the public domain
 #-------------------------------------------------------------------------------
+from ..construct import CString
+from ..common.utils import struct_parse
+
 
 class Segment(object):
     def __init__(self, header, stream):
@@ -23,3 +26,21 @@ class Segment(object):
         """
         return self.header[name]
 
+
+class InterpSegment(Segment):
+    """ INTERP segment. Knows how to obtain the path to the interpreter used
+        for this ELF file.
+    """
+    def __init__(self, header, stream):
+        super(InterpSegment, self).__init__(header, stream)
+
+    def get_interp_name(self):
+        """ Obtain the interpreter path used for this ELF file.
+        """
+        path_offset = self['p_offset']
+        return struct_parse(
+            CString(''),
+            self.stream,
+            stream_pos=path_offset)
+
+
index 382f943809707097d03650986e89706b86dec58a..982add47974e53d3bc148f7ef55c3d8f1d7b0a1b 100644 (file)
@@ -19,6 +19,7 @@ except ImportError:
 
 from elftools.common.exceptions import ELFError
 from elftools.elf.elffile import ELFFile
+from elftools.elf.segments import InterpSegment
 from elftools.elf.descriptions import (
     describe_ei_class, describe_ei_data, describe_ei_version,
     describe_ei_osabi, describe_e_type, describe_e_machine,
@@ -129,6 +130,10 @@ class ReadElf(object):
                     describe_p_flags(segment['p_flags']),
                     self._format_hex(segment['p_align'])))
 
+            if isinstance(segment, InterpSegment):
+                self._emitline('      [Requesting program interpreter: %s]' % 
+                    segment.get_interp_name())
+
 
 
         
diff --git a/z.py b/z.py
index dd2ab54fd09876b3b3d22995d5116a0e11fb01b4..39e569aa739e95030544518cec9cb23dffea0d52 100644 (file)
--- a/z.py
+++ b/z.py
@@ -20,7 +20,7 @@ for sec in efile.iter_sections():
         print '   linked string table:', sec.stringtable.name
 
 for seg in efile.iter_segments():
-    print seg['p_type'], seg['p_offset']
+    print type(seg), seg['p_type'], seg['p_offset']
 
 for sec in efile.iter_sections():
     if isinstance(sec, SymbolTableSection):