changeset 126:bbf4c9b138d4

Changes to elf reading
author Windel Bouwman
date Sun, 13 Jan 2013 12:14:27 +0100
parents 1ee5f36b34ed
children ec1f2cc04d95
files python/elffile.py python/readelf.py
diffstat 2 files changed, 62 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/python/elffile.py	Sun Jan 13 10:42:03 2013 +0100
+++ b/python/elffile.py	Sun Jan 13 12:14:27 2013 +0100
@@ -1,6 +1,5 @@
 import struct
-
-classes = {1:'ELF32', 2:'ELF64'}
+import collections
 
 class ElfFile:
    def __init__(self, f):
@@ -8,8 +7,6 @@
       self.parse()
    def parse(self):
       self.parseHeader()
-      self.parseSections()
-      self.parsePrograms()
    @property
    def ElfClass(self):
       return classes[self.ei_class]
@@ -19,6 +16,8 @@
       ELFMAGIC = bytes([0x7f]) + b'ELF'
       assert e_ident[0:4] == ELFMAGIC
       self.ei_class = e_ident[4]
+      # Change the class of this object in some strange way:
+      self.__class__ = classes[self.ei_class] 
       print('ELF class: ', self.ElfClass)
       assert self.ei_class in classes.keys()
       self.ei_data = e_ident[5]
@@ -31,22 +30,20 @@
       e_machine = self.readHalf()
       e_version = self.readWord()
       e_entry = self.readAddr()
-      e_phoff = self.readOff()
-      e_shoff = self.readOff()
-      e_flags = self.readWord()
+      self.e_phoff = self.readOff()
+      self.e_shoff = self.readOff()
+      self.e_flags = self.readWord()
       e_ehsize = self.readHalf()
-      e_phentsize = self.readHalf()
-      e_phnum = self.readHalf()
-      e_shentsize = self.readHalf()
-      e_shnum = self.readHalf()
-      e_shstrndx = self.readHalf()
+      self.e_phentsize = self.readHalf()
+      self.e_phnum = self.readHalf()
+      self.e_shentsize = self.readHalf()
+      self.e_shnum = self.readHalf()
+      self.e_shstrndx = self.readHalf()
       
-      if self.ei_class == 1:
-         assert e_ehsize == 52
-      elif self.ei_class == 2:
-         assert e_ehsize == 64
-      print('program header size', e_phentsize, e_phnum)
-      print('section header size', e_shentsize, e_shnum, e_shstrndx)
+      assert e_ehsize == self.HEADERSIZE
+      print('program header size', self.e_phentsize, self.e_phnum)
+      print('section header size', self.e_shentsize, self.e_shnum)
+      print('string index:', self.e_shstrndx)
    def readFmt(self, fmt):
       size = struct.calcsize(fmt)
       return struct.unpack(fmt, self.f.read(size))
@@ -54,15 +51,49 @@
       return self.readFmt('<H')[0]
    def readWord(self):
       return self.readFmt('<I')[0]
+   def parsePrograms(self):
+      # Skip to start of program headers:
+      self.f.seek(self.e_phoff)
+      pheaders = []
+      for i in range(self.e_phnum):
+         pheaders.append(self.parseProgramHeader())
+      return pheaders
+
+ProgramHeader = collections.namedtuple('ProgramHeader', ['p_type', 
+   'p_flags', 'p_offset', 'p_vaddr', 'p_paddr', 'p_filesz', 'p_memsz'])
+      
+class Elf32File(ElfFile):
+   HEADERSIZE=52
    def readAddr(self):
-      if self.ei_class == 1:
-         fmt = '<I'
-      elif self.ei_class == 2:
-         fmt = '<Q'
-      else:
-         raise Exception()
-      return self.readFmt(fmt)[0]
+      return self.readFmt('<I')[0]
    readOff = readAddr
+   def parseProgramHeader(self):
+      p_type = self.readWord()
+      p_offset = self.readOff()
+      p_vaddr = self.readAddr()
+      p_paddr = self.readAddr()
+      p_filesz = self.readWord()
+      p_memsz = self.readWord()
+      p_flags = self.readWord()
+      p_align = self.readWord()
+      return ProgramHeader(p_type, p_flags, p_offset, p_vaddr, p_paddr, p_filesz, p_memsz)
+      
+class Elf64File(ElfFile):
+   HEADERSIZE=64
+   def readAddr(self):
+      return self.readFmt('<Q')[0]
+   readOff = readAddr
+   readXword = readAddr
+   def parseProgramHeader(self):
+      p_type = self.readWord()
+      p_flags = self.readWord()
+      p_offset = self.readOff()
+      p_vaddr = self.readAddr()
+      p_paddr = self.readAddr()
+      p_filesz = self.readXword()
+      p_memsz = self.readXword()
+      p_align = self.readXword()
+      return ProgramHeader(p_type, p_flags, p_offset, p_vaddr, p_paddr)
 
-   def printProgramHeaders(self):
-      pass
+classes = {1:Elf32File, 2:Elf64File}
+
--- a/python/readelf.py	Sun Jan 13 10:42:03 2013 +0100
+++ b/python/readelf.py	Sun Jan 13 12:14:27 2013 +0100
@@ -13,5 +13,8 @@
 
 if args.list_program_headers:
    print('program headers')
-   ef.printProgramHeaders()
+   phs = ef.parsePrograms()
+   print(phs)
+   for ph in phs:
+      print('type=0x{0:X} vaddr=0x{1:X} filesz=0x{2:X}'.format(ph.p_type, ph.p_vaddr, ph.p_filesz))