Some code reorg:
authoreliben <devnull@localhost>
Thu, 8 Sep 2011 13:24:49 +0000 (16:24 +0300)
committereliben <devnull@localhost>
Thu, 8 Sep 2011 13:24:49 +0000 (16:24 +0300)
* created common/ dir and moved exceptions there (along with utils)
* moved struct_parse from elffile to utils
* moved string table functionality to its own section class

elftools/common/__init__.py [new file with mode: 0644]
elftools/common/exceptions.py [new file with mode: 0644]
elftools/common/utils.py [new file with mode: 0644]
elftools/elf/elffile.py
elftools/elf/sections.py
elftools/exceptions.py [deleted file]
z.py

diff --git a/elftools/common/__init__.py b/elftools/common/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/elftools/common/exceptions.py b/elftools/common/exceptions.py
new file mode 100644 (file)
index 0000000..05fa602
--- /dev/null
@@ -0,0 +1,15 @@
+#-------------------------------------------------------------------------------\r
+# elftools: common/exceptions.py\r
+#\r
+# Exception classes for elftools\r
+#\r
+# Eli Bendersky (eliben@gmail.com)\r
+# This code is in the public domain\r
+#-------------------------------------------------------------------------------\r
+\r
+class ELFError(Exception): \r
+    pass
+\r
+class ELFParseError(ELFError):\r
+    pass\r
+\r
diff --git a/elftools/common/utils.py b/elftools/common/utils.py
new file mode 100644 (file)
index 0000000..716bebd
--- /dev/null
@@ -0,0 +1,25 @@
+#-------------------------------------------------------------------------------\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
index 01be519d33118cdb8b9573749f120c9e7ab12bfb..7d134b971b5c8b74ba88d9181b7568b3c4e7a6e3 100644 (file)
@@ -6,13 +6,11 @@
 # 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
@@ -35,7 +33,8 @@ class ELFFile(object):
             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
@@ -119,51 +118,40 @@ class ELFFile(object):
     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)
index 4fb4249990407a37d0545449802df461514dd407..502b69f64da0f41e9aa31af76395002d89a8abae 100644 (file)
@@ -6,6 +6,8 @@
 # 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):
@@ -24,3 +26,18 @@ class Section(object):
         """\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
+    
diff --git a/elftools/exceptions.py b/elftools/exceptions.py
deleted file mode 100644 (file)
index b61b463..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#-------------------------------------------------------------------------------\r
-# elftools: exceptions.py\r
-#\r
-# Exception classes for elftools\r
-#\r
-# Eli Bendersky (eliben@gmail.com)\r
-# This code is in the public domain\r
-#-------------------------------------------------------------------------------\r
-\r
-class ELFError(Exception): \r
-    pass
-\r
-class ELFParseError(ELFError):\r
-    pass\r
-\r
diff --git a/z.py b/z.py
index 9f208d3ba9c6660d67a6274223022fafdae345f5..adcfd6c39fc6a4229f7dd679c0600f48444988ca 100644 (file)
--- a/z.py
+++ b/z.py
@@ -9,6 +9,9 @@ stream = open('binfiles/z.elf', 'rb')
 \r
 efile = ELFFile(stream)\r
 \r
+print '===> %s sections!' % efile.num_sections() \r
+print '===> %s segments!' % efile.num_segments()\r
+\r
 for sec in efile.iter_sections():\r
     print sec.name\r
 \r