Tools for building 32-bit archlinux packages from archlinux.org's official, 64-bit tested PKGBUILDs et al.

check-opcodes 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. #!/bin/sh
  2. # shellcheck disable=SC2086,SC2119,SC2120
  3. # shellcheck source=../lib/load-configuration
  4. . "${0%/*}/../lib/load-configuration"
  5. usage( ) {
  6. >&2 cat <<EOF
  7. check_opcodes: [options] [ -a <arch> ] <package>
  8. possible optons:
  9. -h|--help: Show this help page
  10. -a|--architecture: architecture family to check against, one of
  11. i486, i686, pentium3 (meaning target architecture
  12. the package should be runnable on)
  13. -v|--verbose: Verbose output, print result of check for logs
  14. -d|--debug: Debug output, used for development and testing
  15. EOF
  16. exit 1
  17. }
  18. VERBOSE=0
  19. DEBUG=0
  20. EXIT_CODE=0
  21. verbose( ) {
  22. if test $VERBOSE = 1; then
  23. echo "$@"
  24. fi
  25. }
  26. debug( ) {
  27. if test $DEBUG = 1; then
  28. echo "$@"
  29. fi
  30. }
  31. err( ) {
  32. echo "ERROR: $*"
  33. EXIT_CODE=1
  34. }
  35. tmp_dir=$(mktemp -d "${work_dir}/tmp.check-opcodes.XXXXXX")
  36. trap 'rm -rf --one-file-system "${tmp_dir:?}"' EXIT
  37. ARCH=i686
  38. while getopts ":vda:h-:" opt; do
  39. case $opt in
  40. -)
  41. case "$OPTARG" in
  42. help)
  43. usage
  44. ;;
  45. verbose)
  46. VERBOSE=1
  47. ;;
  48. debug)
  49. DEBUG=1
  50. ;;
  51. *)
  52. echo "ERROR: Invalid option: --$OPTARG" >&2
  53. usage
  54. ;;
  55. esac
  56. ;;
  57. h)
  58. usage
  59. ;;
  60. v)
  61. VERBOSE=1
  62. ;;
  63. d)
  64. DEBUG=1
  65. ;;
  66. a)
  67. ARCH=$OPTARG
  68. ;;
  69. \?)
  70. echo "ERROR: Invalid option: -$OPTARG" >&2
  71. usage
  72. ;;
  73. esac
  74. done
  75. shift $((OPTIND-1))
  76. PACKAGE=$1
  77. if test "x$PACKAGE" = "x"; then
  78. echo "ERROR: Filename of a package required as argument" >&2
  79. usage
  80. exit 1
  81. fi
  82. OPCODE_ARGS=""
  83. case $ARCH in
  84. i486)
  85. OPCODE_ARGS='-r -a 386 -v'
  86. ;;
  87. i686)
  88. OPCODE_ARGS='-s MMX -s SSE'
  89. ;;
  90. # TODO: pentium4
  91. pentium3)
  92. OPCODE_ARGS='-s SSE2 -s SSE3'
  93. ;;
  94. *)
  95. echo "ERROR: architecture must currently be one of i486, i686 and pentium3" >&2
  96. usage
  97. exit 1
  98. esac
  99. debug "Unpacking $PACKAGE to $tmp_dir.."
  100. bsdtar --no-fflags -x -C $tmp_dir -f $PACKAGE
  101. debug "Checking for architecture: $ARCH ($OPCODE_ARGS).."
  102. # shellcheck disable=SC2044
  103. for absfile in $(find $tmp_dir \( -regextype grep -regex '.*\.so\(\.[0-9.]\+\)\?' -type f \) -o \( -executable -type f \) ); do
  104. file=$(basename $absfile)
  105. relfile=${absfile#$tmp_dir}
  106. debug "Checking file: $relfile"
  107. if ! readelf -a $absfile > $tmp_dir/$file.elf 2>/dev/null; then
  108. debug "readelf failed, ignoring file"
  109. continue
  110. fi
  111. if ! objdump -f $absfile > $tmp_dir/$file.objdump 2>/dev/null; then
  112. debug "objdump failed, ignoring file"
  113. continue
  114. fi
  115. file $absfile > $tmp_dir/$file.file
  116. arch=$(grep ^architecture $tmp_dir/$file.objdump | sed 's/^architecture: //g' | cut -f 1 -d ,)
  117. case $arch in
  118. i386:x86-64)
  119. arch='x86_64'
  120. ;;
  121. i386)
  122. arch='x86'
  123. ;;
  124. *)
  125. arch='unknown'
  126. ;;
  127. esac
  128. debug " Objdump architecture: $arch"
  129. archelf=$(grep '^ \+Class' $tmp_dir/$file.elf | cut -f 2 -d : | tr -d ' ')
  130. case $archelf in
  131. ELF64)
  132. archelf='x86_64'
  133. ;;
  134. ELF32)
  135. archelf='x86'
  136. ;;
  137. *)
  138. archelf='unknown'
  139. ;;
  140. esac
  141. debug " Readelf architecture: $archelf"
  142. if test $arch != $archelf; then
  143. err "ERROR: $file ambigous architecture information (objdump: $arch, ELF: $archelf)"
  144. fi
  145. if test $arch = "x86_64"; then
  146. err "ERROR: $file is a 64-bit library!"
  147. continue
  148. fi
  149. objdump -M intel -d $absfile > $tmp_dir/$file.asm
  150. bad_opcodes=$(${base_dir}/bin/opcode $OPCODE_ARGS -m 1 < $tmp_dir/$file.asm | wc -l)
  151. if test $bad_opcodes != 0; then
  152. case $ARCH in
  153. i486)
  154. err "$relfile is not built for plain i486 opcodes"
  155. ;;
  156. i686)
  157. err "$relfile contains MMX, SSE or newer opcodes"
  158. ;;
  159. pentium3)
  160. err "$relfile contains SSE2 or newer opcodes"
  161. ;;
  162. esac
  163. if test $DEBUG = 1; then
  164. ${base_dir}/bin/opcode $OPCODE_ARGS -B 2 -A 2 < $tmp_dir/$file.asm
  165. fi
  166. else
  167. if test $VERBOSE = 1; then
  168. verbose "OK: $relfile fullfills architecture constraint for $ARCH"
  169. fi
  170. fi
  171. done
  172. exit $EXIT_CODE