Files
poky/meta/lib/oe/qa.py
Phil Blundell f8c90bce73 insane: Rationalise phdrs-based QA checks
Various different QA checks are based on essentially the same data from
the ELF program headers.  Calling objdump to extract it repeatedly is
inefficient, particularly if the shell is involved.  Instead, let's
cache the output from objdump inside the qa.elf object and allow it to
be reused by multiple tests.

Also, using objdump instead of scanelf to check for bad RPATHs (in the
same way that the useless-rpaths check was doing already) allows the
dependency on pax-utils-native to be dropped.

(From OE-Core rev: bf19eeb9f65e91bf2b5d89e7c0b099c55d7c15ff)

Signed-off-by: Phil Blundell <philb@gnu.org>
Signed-off-by: Saul Wold <sgw@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2012-10-18 12:13:49 +01:00

107 lines
3.2 KiB
Python

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 Exception("This does not work as expected")
def __init__(self, name, bits = 0):
self.name = name
self.bits = bits
self.objdump_output = {}
def open(self):
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 Exception("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 Exception("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 Exception("self.sex == ELFDATANONE")
elif self.sex == chr(ELFFile.ELFDATA2LSB):
self.sex = "<"
elif self.sex == chr(ELFFile.ELFDATA2MSB):
self.sex = ">"
else:
raise Exception("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 isBigEngian(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 self.objdump_output.has_key(cmd):
return self.objdump_output[cmd]
objdump = d.getVar('OBJDUMP', True)
staging_dir = d.getVar('STAGING_BINDIR_TOOLCHAIN', True)
env = os.environ
env["LC_ALL"] = "C"
self.objdump_output[cmd] = bb.process.run([ os.path.join(staging_dir, objdump), cmd, self.name ], env=env, shell=False)[0]
return self.objdump_output[cmd]