118
|
1 import struct
|
126
|
2 import collections
|
118
|
3
|
|
4 class ElfFile:
|
|
5 def __init__(self, f):
|
|
6 self.f = f
|
|
7 self.parse()
|
|
8 def parse(self):
|
|
9 self.parseHeader()
|
|
10 @property
|
|
11 def ElfClass(self):
|
|
12 return classes[self.ei_class]
|
|
13 def parseHeader(self):
|
|
14 # Parse identifier
|
|
15 e_ident = self.f.read(16)
|
|
16 ELFMAGIC = bytes([0x7f]) + b'ELF'
|
|
17 assert e_ident[0:4] == ELFMAGIC
|
|
18 self.ei_class = e_ident[4]
|
126
|
19 # Change the class of this object in some strange way:
|
|
20 self.__class__ = classes[self.ei_class]
|
118
|
21 print('ELF class: ', self.ElfClass)
|
|
22 assert self.ei_class in classes.keys()
|
|
23 self.ei_data = e_ident[5]
|
|
24 print('ei_data:', self.ei_data)
|
|
25 ei_version = e_ident[6]
|
|
26 assert ei_version == 1
|
|
27
|
|
28 # rest of the ELF header:
|
|
29 e_type = self.readHalf()
|
|
30 e_machine = self.readHalf()
|
|
31 e_version = self.readWord()
|
|
32 e_entry = self.readAddr()
|
126
|
33 self.e_phoff = self.readOff()
|
|
34 self.e_shoff = self.readOff()
|
|
35 self.e_flags = self.readWord()
|
118
|
36 e_ehsize = self.readHalf()
|
126
|
37 self.e_phentsize = self.readHalf()
|
|
38 self.e_phnum = self.readHalf()
|
|
39 self.e_shentsize = self.readHalf()
|
|
40 self.e_shnum = self.readHalf()
|
|
41 self.e_shstrndx = self.readHalf()
|
118
|
42
|
126
|
43 assert e_ehsize == self.HEADERSIZE
|
|
44 print('program header size', self.e_phentsize, self.e_phnum)
|
|
45 print('section header size', self.e_shentsize, self.e_shnum)
|
|
46 print('string index:', self.e_shstrndx)
|
118
|
47 def readFmt(self, fmt):
|
|
48 size = struct.calcsize(fmt)
|
|
49 return struct.unpack(fmt, self.f.read(size))
|
|
50 def readHalf(self):
|
|
51 return self.readFmt('<H')[0]
|
|
52 def readWord(self):
|
|
53 return self.readFmt('<I')[0]
|
126
|
54 def parsePrograms(self):
|
|
55 # Skip to start of program headers:
|
|
56 self.f.seek(self.e_phoff)
|
|
57 pheaders = []
|
|
58 for i in range(self.e_phnum):
|
|
59 pheaders.append(self.parseProgramHeader())
|
|
60 return pheaders
|
|
61
|
|
62 ProgramHeader = collections.namedtuple('ProgramHeader', ['p_type',
|
|
63 'p_flags', 'p_offset', 'p_vaddr', 'p_paddr', 'p_filesz', 'p_memsz'])
|
|
64
|
|
65 class Elf32File(ElfFile):
|
|
66 HEADERSIZE=52
|
118
|
67 def readAddr(self):
|
126
|
68 return self.readFmt('<I')[0]
|
118
|
69 readOff = readAddr
|
126
|
70 def parseProgramHeader(self):
|
|
71 p_type = self.readWord()
|
|
72 p_offset = self.readOff()
|
|
73 p_vaddr = self.readAddr()
|
|
74 p_paddr = self.readAddr()
|
|
75 p_filesz = self.readWord()
|
|
76 p_memsz = self.readWord()
|
|
77 p_flags = self.readWord()
|
|
78 p_align = self.readWord()
|
|
79 return ProgramHeader(p_type, p_flags, p_offset, p_vaddr, p_paddr, p_filesz, p_memsz)
|
|
80
|
|
81 class Elf64File(ElfFile):
|
|
82 HEADERSIZE=64
|
|
83 def readAddr(self):
|
|
84 return self.readFmt('<Q')[0]
|
|
85 readOff = readAddr
|
|
86 readXword = readAddr
|
|
87 def parseProgramHeader(self):
|
|
88 p_type = self.readWord()
|
|
89 p_flags = self.readWord()
|
|
90 p_offset = self.readOff()
|
|
91 p_vaddr = self.readAddr()
|
|
92 p_paddr = self.readAddr()
|
|
93 p_filesz = self.readXword()
|
|
94 p_memsz = self.readXword()
|
|
95 p_align = self.readXword()
|
|
96 return ProgramHeader(p_type, p_flags, p_offset, p_vaddr, p_paddr)
|
118
|
97
|
126
|
98 classes = {1:Elf32File, 2:Elf64File}
|
|
99
|