| # Copyright 2015 Gentoo Foundation |
| # Distributed under the terms of the GNU General Public License v2 |
| |
| from portage.util.endian.decode import (decode_uint16_le, |
| decode_uint32_le, decode_uint16_be, decode_uint32_be) |
| from portage.util.elf.constants import (E_ENTRY, E_MACHINE, E_TYPE, |
| EI_CLASS, ELFCLASS32, ELFCLASS64, ELFDATA2LSB, ELFDATA2MSB) |
| |
| class ELFHeader(object): |
| |
| __slots__ = ('e_flags', 'e_machine', 'e_type', 'ei_class', |
| 'ei_data') |
| |
| @classmethod |
| def read(cls, f): |
| """ |
| @param f: an open ELF file |
| @type f: file |
| @rtype: ELFHeader |
| @return: A new ELFHeader instance containing data from f |
| """ |
| f.seek(EI_CLASS) |
| ei_class = ord(f.read(1)) |
| ei_data = ord(f.read(1)) |
| |
| if ei_class == ELFCLASS32: |
| width = 32 |
| elif ei_class == ELFCLASS64: |
| width = 64 |
| else: |
| width = None |
| |
| if ei_data == ELFDATA2LSB: |
| uint16 = decode_uint16_le |
| uint32 = decode_uint32_le |
| elif ei_data == ELFDATA2MSB: |
| uint16 = decode_uint16_be |
| uint32 = decode_uint32_be |
| else: |
| uint16 = None |
| uint32 = None |
| |
| if width is None or uint16 is None: |
| e_flags = None |
| e_machine = None |
| e_type = None |
| else: |
| f.seek(E_TYPE) |
| e_type = uint16(f.read(2)) |
| f.seek(E_MACHINE) |
| e_machine = uint16(f.read(2)) |
| |
| # E_ENTRY + 3 * sizeof(uintN) |
| e_flags_offset = E_ENTRY + 3 * width // 8 |
| f.seek(e_flags_offset) |
| e_flags = uint32(f.read(4)) |
| |
| obj = cls() |
| obj.e_flags = e_flags |
| obj.e_machine = e_machine |
| obj.e_type = e_type |
| obj.ei_class = ei_class |
| obj.ei_data = ei_data |
| |
| return obj |