# This code is in the public domain\r
#-------------------------------------------------------------------------------\r
\r
-from .structs import ELFStructs\r
+from cStringIO import StringIO\r
+\r
from ..exceptions import ELFError, ELFParseError\r
-from ..construct import ConstructError\r
+from ..construct import ConstructError, CString\r
+from .structs import ELFStructs\r
+from .sections import Section\r
\r
\r
class ELFFile(object):\r
boolean - specifies the target machine's endianness \r
\r
header:\r
- the complete ELF file header
+ the complete ELF file header\r
"""
def __init__(self, stream):
self.stream = stream\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
+ def num_sections(self):
+ """ Get the number of sections in the file
+ """\r
+ return self['e_shnum']\r
+ \r
+ def get_section(self, n):
+ """ Get the section at index #n from the file (Section object)
+ """\r
+ section_header = self._get_section_header(n)\r
+ name = self._get_section_name(section_header)\r
+ return Section(section_header, name, self.stream)\r
+ \r
+ #-------------------------------- PRIVATE --------------------------------#\r
\r
def __getitem__(self, name):
""" Implement dict-like access to header entries
else:\r
raise ELFError('Invalid EI_DATA %s' % repr(ei_data))\r
\r
+ def _section_offset(self, n):
+ """ Compute the offset of section #n in the file
+ """\r
+ return self['e_shoff'] + n * self['e_shentsize']\r
+ \r
+ 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
+ \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.
+ """\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
+ \r
def _parse_elf_header(self):
""" Parses the ELF file header and assigns the result to attributes\r
of this object.
--- /dev/null
+#-------------------------------------------------------------------------------\r
+# elftools: elf/sections.py\r
+#\r
+# ELF sections\r
+#\r
+# Eli Bendersky (eliben@gmail.com)\r
+# This code is in the public domain\r
+#-------------------------------------------------------------------------------\r
+\r
+class Section(object):
+ def __init__(self, header, name, stream):
+ self.header = header\r
+ self.name = name\r
+ self.stream = stream\r
+ \r
+ def data(self):
+ """ The section data from the file.
+ """\r
+ self.stream.seek(self['sh_offset'])\r
+ return self.stream.read(self['sh_size'])
+\r
+ def __getitem__(self, name):\r
+ """ Implement dict-like access to header entries\r
+ """\r
+ return self.header[name]\r
+\r
\r
efile = ELFFile(stream)\r
\r
+print 'num', efile.num_sections()\r
+sec = efile.get_section(39)\r
+#~ print sec.header\r
+print sec.name\r
+print sec['sh_type']\r
+print map(ord, sec.data())\r
+\r
+#~ print sec.stream\r
+#~ print map(ord, efile._stringtable)\r
+\r
#~ print efile.header\r
#~ print dir(efile)\r
#~ print efile['e_type']\r
\r
-shtable_offset = efile['e_shoff']\r
-strtable_section_offset = shtable_offset + efile['e_shstrndx'] * efile['e_shentsize']\r
+#~ shtable_offset = efile['e_shoff']\r
+#~ strtable_section_offset = shtable_offset + efile['e_shstrndx'] * efile['e_shentsize']\r
\r
-# get to the section header for the sh string table\r
-print strtable_section_offset\r
-stream.seek(strtable_section_offset)\r
-sheader = es.Elf_Shdr.parse_stream(stream)\r
-print sheader\r
+#~ # get to the section header for the sh string table\r
+#~ print strtable_section_offset\r
+#~ stream.seek(strtable_section_offset)\r
+#~ sheader = es.Elf_Shdr.parse_stream(stream)\r
+#~ print sheader\r
\r
-# yay, looks correct!!\r
-stream.seek(sheader.sh_offset)\r
-buf = stream.read(sheader.sh_size)\r
-for c in buf:\r
- sys.stdout.write('%02X' % ord(c))\r
+#~ # yay, looks correct!!\r
+#~ stream.seek(sheader.sh_offset)\r
+#~ buf = stream.read(sheader.sh_size)\r
+#~ for c in buf:\r
+ #~ sys.stdout.write('%02X' % ord(c))\r
\r
\r
\r