1#!/usr/bin/env bash 2 3# List of hardcoded paths that should be ignored, as they may 4# contain binaries for an architecture different from the 5# architecture of the target. 6declare -a IGNORES=( 7 # Skip firmware files, they could be ELF files for other 8 # architectures 9 "/lib/firmware" 10 "/usr/lib/firmware" 11 12 # Skip kernel modules 13 # When building a 32-bit userland on 64-bit architectures, the kernel 14 # and its modules may still be 64-bit. To keep the basic 15 # check-bin-arch logic simple, just skip this directory. 16 "/lib/modules" 17 "/usr/lib/modules" 18 19 # Skip files in /usr/share, several packages (qemu, 20 # pru-software-support) legitimately install ELF binaries that 21 # are not for the target architecture 22 "/usr/share" 23 24 # Skip files in {/usr,}/lib/grub, since it is possible to have 25 # it for a different architecture (e.g. i386 grub on x86_64). 26 "/lib/grub" 27 "/usr/lib/grub" 28 29 # Guile modules are ELF files, with a "None" machine 30 "/usr/lib/guile" 31) 32 33while getopts p:l:r:a:i: OPT ; do 34 case "${OPT}" in 35 p) package="${OPTARG}";; 36 l) pkg_list="${OPTARG}";; 37 r) readelf="${OPTARG}";; 38 a) arch_name="${OPTARG}";; 39 i) 40 # Ensure we do have single '/' as separators, 41 # and that we have a leading and a trailing one. 42 pattern="$(sed -r -e 's:/+:/:g; s:^/*:/:; s:/*$:/:;' <<<"${OPTARG}")" 43 IGNORES+=("${pattern}") 44 ;; 45 :) error "option '%s' expects a mandatory argument\n" "${OPTARG}";; 46 \?) error "unknown option '%s'\n" "${OPTARG}";; 47 esac 48done 49 50if test -z "${package}" -o -z "${pkg_list}" -o -z "${readelf}" -o -z "${arch_name}" ; then 51 echo "Usage: $0 -p <pkg> -l <pkg-file-list> -r <readelf> -a <arch name> [-i PATH ...]" 52 exit 1 53fi 54 55exitcode=0 56 57# Only split on new lines, for filenames-with-spaces 58IFS=" 59" 60 61while read f; do 62 for ignore in "${IGNORES[@]}"; do 63 if [[ "${f}" =~ ^"${ignore}" ]]; then 64 continue 2 65 fi 66 done 67 68 # Skip symlinks. Some symlinks may have absolute paths as 69 # target, pointing to host binaries while we're building. 70 if [[ -L "${TARGET_DIR}/${f}" ]]; then 71 continue 72 fi 73 74 # Get architecture using readelf. We pipe through 'head -1' so 75 # that when the file is a static library (.a), we only take 76 # into account the architecture of the first object file. 77 arch=$(LC_ALL=C ${readelf} -h "${TARGET_DIR}/${f}" 2>&1 | \ 78 sed -r -e '/^ Machine: +(.+)/!d; s//\1/;' | head -1) 79 80 # If no architecture found, assume it was not an ELF file 81 if test "${arch}" = "" ; then 82 continue 83 fi 84 85 # Architecture is correct 86 if test "${arch}" = "${arch_name}" ; then 87 continue 88 fi 89 90 printf 'ERROR: architecture for "%s" is "%s", should be "%s"\n' \ 91 "${f}" "${arch}" "${arch_name}" 92 93 exitcode=1 94done < <( sed -r -e "/^${package},\.(.+)$/!d; s//\1/;" ${pkg_list} ) 95 96exit ${exitcode} 97