#!/usr/bin/env python3 """Name and check the ELF files of a Linux package. `arch EXECUTABLE` prints the package architecture names of the executable being packaged: its machine name (AppImage and RPM), Debian architecture and PDFium archive, for example `aarch64 arm64 linux-arm64`. Packages describe the executable they contain rather than the build machine, because a 64-bit kernel can run a 32-bit userland. `verify PATH...` checks every ELF file at or below the paths. They must all be built for one machine, and every load segment must be aligned for the largest page size that machine's kernels use. Arm64 kernels use 4, 16 or 64 KiB pages (the Raspberry Pi 5 kernel uses 16 KiB), and they cannot load a segment that is aligned only for 4 KiB pages. """ import argparse import os import struct from pathlib import Path PT_LOAD = 1 # ELF e_machine: machine name, Debian architecture, PDFium archive and the # largest page size its Linux kernels use. MACHINES = { 62: ("x86_64", "amd64", "linux-x64", 4096), 183: ("aarch64", "arm64", "linux-arm64", 65536), } def read_elf(path): """Return the machine and load segments of an ELF file, or None for other files.""" with open(path, "rb") as stream: header = stream.read(64) if header[:4] != b"\x7fELF": return None if len(header) < 64 or header[4:6] != b"\x02\x01": raise ValueError(f"{path}: expected a little-endian 64-bit ELF file") machine = struct.unpack_from("