--- /dev/null
+#-------------------------------------------------------------------------------\r
+# elftools: common/utils.py\r
+#\r
+# Miscellaneous utilities for elftools\r
+#\r
+# Eli Bendersky (eliben@gmail.com)\r
+# This code is in the public domain\r
+#-------------------------------------------------------------------------------\r
+from .exceptions import ELFParseError\r
+\r
+\r
+def struct_parse(struct, stream, stream_pos=None):\r
+ """ Convenience function for using the given struct to parse a stream (at\r
+ its current location).\r
+ If stream_pos is provided, the stream is seeked to this position before\r
+ the parsing is done.\r
+ Wraps the error thrown by construct with our own error.\r
+ """\r
+ try:\r
+ if stream_pos is not None:\r
+ stream.seek(stream_pos)\r
+ return struct.parse_stream(stream)\r
+ except ConstructError as e:\r
+ raise ELFParseError(e.message)\r
+ \r
# Eli Bendersky (eliben@gmail.com)\r
# This code is in the public domain\r
#-------------------------------------------------------------------------------\r
-\r
-from cStringIO import StringIO\r
-\r
-from ..exceptions import ELFError, ELFParseError\r
-from ..construct import ConstructError, CString\r
+from ..common.exceptions import ELFError\r
+from ..common.utils import struct_parse\r
+from ..construct import ConstructError\r
from .structs import ELFStructs\r
-from .sections import Section\r
+from .sections import Section, StringTableSection\r
from .segments import Segment\r
\r
\r
little_endian=self.little_endian,\r
elfclass=self.elfclass)\r
self.header = self._parse_elf_header()\r
- self._stringtable = self._get_stringtable()\r
+ \r
+ self._file_stringtable_section = self._get_file_stringtable()\r
\r
def num_sections(self):
""" Number of sections in the file
def _get_section_header(self, n):
""" Find the header of section #n, parse it and return the struct
"""\r
- self.stream.seek(self._section_offset(n))\r
- return self._struct_parse(self.structs.Elf_Shdr)\r
+ return struct_parse(\r
+ self.structs.Elf_Shdr,\r
+ self.stream,\r
+ stream_pos=self._section_offset(n))\r
\r
+ def _get_section_name(self, section_header):\r
+ """ Given a section header, find this section's name in the file's\r
+ string table\r
+ """\r
+ name_offset = section_header['sh_name']\r
+ return self._file_stringtable_section.get_string(name_offset)\r
+\r
def _get_segment_header(self, n):
""" Find the header of segment #n, parse it and return the struct
"""\r
- self.stream.seek(self._segment_offset(n))\r
- return self._struct_parse(self.structs.Elf_Phdr)\r
+ return struct_parse(\r
+ self.structs.Elf_Phdr,\r
+ self.stream,\r
+ stream_pos=self._segment_offset(n))\r
\r
- def _get_section_name(self, section_header):
- """ Given a section header, find this section's name in the file's\r
- string table, and return it as a normal Python string.
- """\r
- offset = section_header['sh_name']\r
- self._stringtable.seek(offset)\r
- return CString('').parse_stream(self._stringtable)\r
- \r
- def _get_stringtable(self):
- """ Find the file's string table section, read it and return the string\r
- table as a StringIO object pointing to the section's contents.
+ def _get_file_stringtable(self):
+ """ Find the file's string table section
"""\r
- # Find the section header for the stringtable header, and read the \r
- # section's contents from it\r
- #\r
stringtable_section_num = self['e_shstrndx']\r
- stringtable_header = self._get_section_header(stringtable_section_num)\r
- self.stream.seek(stringtable_header['sh_offset'])\r
- return StringIO(self.stream.read(stringtable_header['sh_size']))\r
+ return StringTableSection(\r
+ header=self._get_section_header(stringtable_section_num),\r
+ name='',\r
+ stream=self.stream)\r
\r
def _parse_elf_header(self):
""" Parses the ELF file header and assigns the result to attributes\r
of this object.
"""\r
- self.stream.seek(0)\r
- return self._struct_parse(self.structs.Elf_Ehdr)\r
- \r
- def _struct_parse(self, struct):
- """ Convenience method for parsing at the current stream location with\r
- the given struct. Also wraps the error thrown by construct with our\r
- own error.
- """\r
- try:\r
- return struct.parse_stream(self.stream)\r
- except ConstructError as e:\r
- raise ELFParseError(e.message)\r
+ return struct_parse(self.structs.Elf_Ehdr, self.stream, stream_pos=0)\r
\r
def _assert(self, cond, msg=''):
""" Assert that cond is True, otherwise raise ELFError(msg)
# Eli Bendersky (eliben@gmail.com)\r
# This code is in the public domain\r
#-------------------------------------------------------------------------------\r
+from ..construct import CString\r
+\r
\r
class Section(object):
def __init__(self, header, name, stream):
"""\r
return self.header[name]\r
\r
+\r
+class StringTableSection(Section):
+ def __init__(self, header, name, stream):
+ super(StringTableSection, self).__init__(header, name, stream)\r
+ \r
+ def get_string(self, offset):\r
+ """ Get the string stored at the given offset in this string table.
+ """\r
+ table_offset = self['sh_offset']\r
+ self.stream.seek(table_offset + offset)\r
+ return CString('').parse_stream(self.stream)
+\r
+\r
+ \r
+