class NotELFFileError(Exception): pass class ELFFile: EI_NIDENT = 16 EI_CLASS = 4 EI_DATA = 5 EI_VERSION = 6 EI_OSABI = 7 EI_ABIVERSION = 8 # possible values for EI_CLASS ELFCLASSNONE = 0 ELFCLASS32 = 1 ELFCLASS64 = 2 # possible value for EI_VERSION EV_CURRENT = 1 # possible values for EI_DATA ELFDATANONE = 0 ELFDATA2LSB = 1 ELFDATA2MSB = 2 def my_assert(self, expectation, result): if not expectation == result: #print "'%x','%x' %s" % (ord(expectation), ord(result), self.name) raise NotELFFileError("%s is not an ELF" % self.name) def __init__(self, name, bits = 0): self.name = name self.bits = bits self.objdump_output = {} def open(self): if not os.path.isfile(self.name): raise NotELFFileError("%s is not a normal file" % self.name) self.file = file(self.name, "r") self.data = self.file.read(ELFFile.EI_NIDENT+4) self.my_assert(len(self.data), ELFFile.EI_NIDENT+4) self.my_assert(self.data[0], chr(0x7f) ) self.my_assert(self.data[1], 'E') self.my_assert(self.data[2], 'L') self.my_assert(self.data[3], 'F') if self.bits == 0: if self.data[ELFFile.EI_CLASS] == chr(ELFFile.ELFCLASS32): self.bits = 32 elif self.data[ELFFile.EI_CLASS] == chr(ELFFile.ELFCLASS64): self.bits = 64 else: # Not 32-bit or 64.. lets assert raise NotELFFileError("ELF but not 32 or 64 bit.") elif self.bits == 32: self.my_assert(self.data[ELFFile.EI_CLASS], chr(ELFFile.ELFCLASS32)) elif self.bits == 64: self.my_assert(self.data[ELFFile.EI_CLASS], chr(ELFFile.ELFCLASS64)) else: raise NotELFFileError("Must specify unknown, 32 or 64 bit size.") self.my_assert(self.data[ELFFile.EI_VERSION], chr(ELFFile.EV_CURRENT) ) self.sex = self.data[ELFFile.EI_DATA] if self.sex == chr(ELFFile.ELFDATANONE): raise NotELFFileError("self.sex == ELFDATANONE") elif self.sex == chr(ELFFile.ELFDATA2LSB): self.sex = "<" elif self.sex == chr(ELFFile.ELFDATA2MSB): self.sex = ">" else: raise NotELFFileError("Unknown self.sex") def osAbi(self): return ord(self.data[ELFFile.EI_OSABI]) def abiVersion(self): return ord(self.data[ELFFile.EI_ABIVERSION]) def abiSize(self): return self.bits def isLittleEndian(self): return self.sex == "<" def isBigEndian(self): return self.sex == ">" def machine(self): """ We know the sex stored in self.sex and we know the position """ import struct (a,) = struct.unpack(self.sex+"H", self.data[18:20]) return a def run_objdump(self, cmd, d): import bb.process import sys if cmd in self.objdump_output: return self.objdump_output[cmd] objdump = d.getVar('OBJDUMP', True) env = os.environ.copy() env["LC_ALL"] = "C" env["PATH"] = d.getVar('PATH', True) try: bb.note("%s %s %s" % (objdump, cmd, self.name)) self.objdump_output[cmd] = bb.process.run([objdump, cmd, self.name], env=env, shell=False)[0] return self.objdump_output[cmd] except Exception as e: bb.note("%s %s %s failed: %s" % (objdump, cmd, self.name, e)) return ""