#!/bin/sh . "${0%/*}/../conf/default.conf" usage( ) { >&2 cat < ] possible optons: -h|--help: show this help page -v|--verbose: verbose output -d|--debug: enable debug output -a|--architecture: architecture family to check against, one of i486, i686, pentium4 EOF exit 1 } VERBOSE=0 log( ) { if test $VERBOSE = 1; then echo $* fi } DEBUG=0 debug( ) { if test $DEBUG = 1; then echo $* fi } EXIT_CODE=0 err( ) { echo "ERROR: $*" EXIT_CODE=1 } tmp_dir=$(mktemp -d "${work_dir}/tmp.check-opcodes.XXXXXX") trap "rm -rf --one-file-system '${tmp_dir:?}'" EXIT ARCH=i686 while getopts ":va:d-h-:" opt; do case $opt in -) case "$OPTARG" in help) usage ;; verbose) VERBOSE=1 ;; debug) DEBUG=1 ;; *) echo "ERROR: Invalid option: --$OPTARG" >&2 usage ;; esac ;; h) usage ;; v) VERBOSE=1 ;; d) DEBUG=1 ;; a) ARCH=$OPTARG ;; \?) echo "ERROR: Invalid option: -$OPTARG" >&2 usage ;; esac done shift $((OPTIND-1)) PACKAGE=$1 if test "x$PACKAGE" = "x"; then echo "ERROR: Filename of a package required as argument" >&2 usage exit 1 fi OPCODE_ARGS="" case $ARCH in i486) OPCODE_ARGS='-r -a 486 -v' ;; i686) OPCODE_ARGS='-s MMX -s SSE -s SSE2' ;; pentium4) OPCODE_ARGS='-s SSE3 -s SSSE3 -s AVX' ;; *) echo "ERROR: architecture must currently be one of i486 and i686" >&2 usage exit 1 esac log "Checking package $PACKAGE" log "Checking for architecture constraint: $ARCH ($OPCODE_ARGS)" bsdtar --no-fflags -x -C $tmp_dir -f $PACKAGE for absfile in `find $tmp_dir -type f`; do file=`basename $absfile` ext=`echo $absfile | rev | cut -f 1 -d . | rev` case "$file" in .PKGINFO|.BUILDINFO|.MTREE) debug "Skipping $file (internal Archlinux file)" continue ;; *.hpp|*.h|*.c|*.cpp|*.html|*.mo|*.po|*.svg|*.png|*.pl|*.pod|*.vim|*.js|*.cmake|*.xml|*.txt|*.rst|*.in|*.conf|*.[0123456789]) debug "Skipping $file (extension is .$ext)" continue ;; *) # we cannot really ignore the file by extension esac mimetype=`file -i $absfile | cut -f 2- -d : | cut -f 1 -d ';' | tr -d ' '` case "$mimetype" in application/x-sharedlib) debug "Checking library/binary: $file" ;; *) debug "Skipping $file (MIME type is $mimetype)" continue ;; esac objdump -f $absfile > $tmp_dir/$file.objdump arch=`grep ^architecture $tmp_dir/$file.objdump | sed 's/^architecture: //g' | cut -f 1 -d ,` case $arch in i386:x86-64) arch='x86_64' ;; i386) arch='x86' ;; *) arch='unknown' ;; esac debug " Objdump architecture: $arch" readelf -a $absfile > $tmp_dir/$file.elf 2> $tmp_dir/$file.elferr archelf=`grep '^ \+Class' $tmp_dir/$file.elf | cut -f 2 -d : | tr -d ' '` case $archelf in ELF64) archelf='x86_64' ;; ELF32) archelf='x86' ;; *) archelf='unknown' ;; esac debug " Readelf architecture: $archelf" if test $arch != $archelf; then err "$file ambigous architecture information (objdump: $arch, ELF: $archelf)" fi if test $arch = "x86_64"; then err "$file is a 64-bit library!" continue fi objdump -M intel -d $absfile > $tmp_dir/$file.asm bad_opcodes=`cat $tmp_dir/$file.asm | ${base_dir}/bin/opcode $OPCODE_ARGS -m 1 | wc -l` if test $bad_opcodes != 0; then case $ARCH in i486) err "$file is not built for plain i486 opcodes" ;; i686) err "$file contains MMX, SSE or SSE2 opcodes" ;; pentium4) err "$file contains SSE3 or newer opcodes" ;; esac else if test $VERBOSE = 1; then log "$file fullfills architecture constraint for $ARCH" fi fi done exit $EXIT_CODE