From 3f4de3eb7fd7ab9b5b42192676b874278f7804ad Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Wed, 14 Sep 2011 05:58:06 +0300 Subject: [PATCH] Implementing reading the INTERP path in segments --- elftools/common/utils.py | 8 ++++---- elftools/elf/elffile.py | 13 +++++++++++-- elftools/elf/segments.py | 21 +++++++++++++++++++++ scripts/readelf.py | 5 +++++ z.py | 2 +- 5 files changed, 42 insertions(+), 7 deletions(-) diff --git a/elftools/common/utils.py b/elftools/common/utils.py index 666176f..477d7ee 100644 --- a/elftools/common/utils.py +++ b/elftools/common/utils.py @@ -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: diff --git a/elftools/elf/elffile.py b/elftools/elf/elffile.py index aee1b54..32373e9 100644 --- a/elftools/elf/elffile.py +++ b/elftools/elf/elffile.py @@ -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 """ diff --git a/elftools/elf/segments.py b/elftools/elf/segments.py index a583de0..5e61b28 100644 --- a/elftools/elf/segments.py +++ b/elftools/elf/segments.py @@ -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) + + diff --git a/scripts/readelf.py b/scripts/readelf.py index 382f943..982add4 100644 --- a/scripts/readelf.py +++ b/scripts/readelf.py @@ -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 dd2ab54..39e569a 100644 --- 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): -- 2.30.2