"""Verify a freshly built ARM binary against the device, then install it. Building inside the chroot is not proof that a binary will run: the chroot carries gtk 2.8/glib 2.12 headers while the netBook Pro runs gtk 2.6/glib 2.6, and several /usr/include/gpe headers were staged from later releases than the libraries the device actually has. A binary that links in the chroot can still reference a symbol no device library defines. So every binary is checked three ways before it is allowed in: 1. ARM OABI -- e_flags must be 0x2, or the device's loader rejects it 2. every DT_NEEDED library exists in the image 3. every undefined dynamic symbol is defined by one of those libraries Anything that fails is reported and not installed. What passes replaces the existing file, with the original kept alongside as .gpe-orig so the stock GPE binary can be put back. python3 scripts/install-built.py = [...] """ import os import struct import sys sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from elfdeps import needed # noqa: E402 from elfsyms import symbols # noqa: E402 ROOT = os.path.expanduser( '~/Downloads/PsionLinux-netBookPro/workspace/card/root') LIBDIRS = ('lib', 'usr/lib', 'usr/lib/gtk-2.0/2.4.0/loaders', 'usr/lib/gtk-2.0/2.4.0/modules') def oabi(path): with open(path, 'rb') as fh: head = fh.read(64) if head[:4] != b'\x7fELF': return None return struct.unpack_from(' 12: problems.append(f'... and {len(unresolved) - 12} more unresolved') return problems def main(): ok = bad = 0 for arg in sys.argv[1:]: dest, src = arg.split('=', 1) if not os.path.isfile(src): print(f' {dest:28s} SOURCE MISSING {src}') bad += 1 continue problems = check(src) if problems: print(f' {dest:28s} REJECTED') for p in problems: print(f' {p}') bad += 1 continue target = os.path.join(ROOT, dest.lstrip('/')) os.makedirs(os.path.dirname(target), exist_ok=True) keep = target + '.gpe-orig' mode = 0o755 if os.path.exists(keep): # a previous run already set the original aside; its mode is # still the authority for what this file should be mode = os.stat(keep).st_mode & 0o7777 note = '' elif os.path.exists(target): mode = os.stat(target).st_mode & 0o7777 os.rename(target, keep) note = ' (stock kept as .gpe-orig)' else: note = '' with open(src, 'rb') as a, open(target, 'wb') as b: b.write(a.read()) # carry the stock permissions over: gpe-conf is setuid root and # loses its privileged applets without it os.chmod(target, mode) if mode & 0o4000: note += ' setuid' print(f' {dest:28s} installed {os.path.getsize(target):>8} B{note}') ok += 1 print(f'\n {ok} installed, {bad} rejected') return 0 if bad == 0 else 1 if __name__ == '__main__': sys.exit(main())