1#!/bin/sh 2 3# The purpose of this dummy build test is to ensure that all the 4# armeabi-v7a prebuilt binaries distributed with the NDK were 5# properly built targetting VFPv3-D16, as per the ABI spec. 6# 7# For a related bug, see http://code.google.com/p/android/issues/detail?id=26199 8# 9 10# 11# $1: ELF binary 12# $2: Tag name (e.g. Tag_CPU_name) 13# 14extract_arch_tag () 15{ 16 echo $($ARM_READELF -A "$1" | awk '$1 == "'$2':" { print $2; }' | sort -u | tr '\n' ' ') 17} 18 19# Returns success only if a file is a static object or library. 20# We simply check the suffix, which must be either .a or .o 21# $1: file name 22is_static_file () 23{ 24 case $1 in 25 *.o|*.a) 26 return 0 27 ;; 28 esac 29 return 1 30} 31 32 33# 34# WARNING: VERY IMPORTANT TECHNICAL NOTE: 35# 36# The function below works by inspecting the architecture-specific 37# attributes in an ELF file. Please be aware that the behaviour of 38# binutils-2.19 and binutils-2.21 is different when generating these 39# tags. 40# 41# 1/ When compiling for ARMv7-A targets, one can use any of the following 42# labels for the -mfpu=<name> option: 43# 44# vfp 45# vfpv3 46# vfpv3-d16 47# neon 48# 49# 2/ There are two VFPv3 architectures defined by ARM: 50# 51# VFPv3-D16 -> Mandates only 16 double FPU registers (d0-d15) 52# VFPv3-D32 -> Mandates 32 double FPU registers (d0-d31) 53# 54# In addition, NEON requires VFPv3-D32 55# 56# There is also VFPv2, which is an earlier version of VFPv3. Technically 57# speaking, VFPv3 is not completely backwards compatible with VFPv2 because 58# there are a few VFPv2 instructions it doesn't support. 59# 60# 3/ The table below indicates, for each -mfpu label, the following: 61# 62# - The value of the 'Tag_VFP_arch' attribute that will be placed in 63# the generated object files or binaries (you can list them with 64# 'readelf -A <file>') 65# 66# - Whether the generated code uses 16 or 32 FPU double registers 67# (this is checked by looking at the disassembly of libgnustl_shared.so, 68# more specifically functions like 'cosf' or 'sinf' inside it). 69# 70# First, for binutils-2.19: 71# 72# fpu value EABI tag FPU reg count 73# ----------------------------------------------------- 74# vfp VFPv2 16 75# vfpv3 VFPv3-D16 32 (*) 76# vfpv3-d16 VFPv3 16 (*) 77# neon VFPv3 32 78# 79# And now for binutils-2.21 80# 81# fpu value EABI tag FPU reg count 82# ----------------------------------------------------- 83# vfp VFPv2 16 84# vfpv3 VFPv3 32 85# vfpv3-d16 VFPv3-D16 16 86# neon VFPv3 32 87# 88# This shows that: 89# 90# - The 'VFPv3' tag seems to match VFPv3-D32 exclusively on 2.21, 91# but is a mess with 2.19 92# 93# - Similarly, the 'vfpv3' value seems to match VFPv3-D32 as well, 94# with the exception that binutils-2.19 is buggy and will put an 95# invalid tag (VFPv3-D16, instead of VFPv3) in the generate ELF file. 96# 97# - binutils 2.19 puts the wrong tag in the executable for vfpv3 and 98# vfpv3-d16, then should probably be inverted! 99# 100# The end result is that we can't use the EABI tag to determine the number 101# of hardware FPU registers that are really used by the machine code with 102# binutils 2.19 :-( 103# 104# BONUS: 105# 106# - When using 'neon', binutils-2.21 will also add a new tag named 107# 'Tag_Advanced_SIMD_arch' with value 'NEONv1'. Sadly, binutils-2.19 108# doesn't do any of this. 109# 110 111# Check that an ELF binary is compatible with our armeabi-v7a ABI 112# (i.e. no NEON, and only 16 hardware registers being used). 113# 114# See technical note above to understand how this currently works. 115# We're still assuming the toolchain is built with the buggy binutils-2.19. 116# 117# $1: path to an ARMv7-A ELF binary (static lib, shared lib or executable) 118# 119check_armv7_elf_binary () 120{ 121 # We use a small awk script to parse the output of 'readelf -A' 122 # Which typically looks like: 123 # 124 # Attribute Section: aeabi 125 # File Attributes 126 # Tag_CPU_name: "7-A" 127 # Tag_CPU_arch: v7 128 # Tag_CPU_arch_profile: Application 129 # Tag_ARM_ISA_use: Yes 130 # Tag_THUMB_ISA_use: Thumb-2 131 # Tag_VFP_arch: VFPv3-D16 132 # Tag_ABI_PCS_wchar_t: 4 133 # Tag_ABI_FP_denormal: Needed 134 # Tag_ABI_FP_exceptions: Needed 135 # Tag_ABI_FP_number_model: IEEE 754 136 # Tag_ABI_align8_needed: Yes 137 # Tag_ABI_align8_preserved: Yes, except leaf SP 138 # Tag_ABI_enum_size: int 139 # Tag_ABI_HardFP_use: SP and DP 140 # Tag_ABI_optimization_goals: Aggressive Speed 141 # Tag_unknown_44: 1 (0x1) 142 # 143 # Note that for static libraries, these sections will appear multiple 144 # time in the output of 'readelf -A'. 145 146 echo "Checking: $(basename $1)" 147 if [ ! -f "$1" ]; then 148 1>&2 echo "PANIC: Missing binary: $1" 149 exit 1 150 fi 151 152 # We want to check the values of Tag_CPU_name 153 CPU_NAMES=$(extract_arch_tag "$1" Tag_CPU_name) 154 VFP_ARCHS=$(extract_arch_tag "$1" Tag_VFP_arch) 155 NEON_ARCHS=$(extract_arch_tag "$1" Tag_Advanced_SIMD_arch) 156 157 # IMPORTANT NOTE: Even when using -march=armv7-a, the compiler may not 158 # necessarily use ARMv7-A specific instruction and will tag an object file 159 # with the following attributes: 160 # 161 # Attribute Section: aeabi 162 # File Attributes 163 # Tag_CPU_name: "5TE" 164 # Tag_CPU_arch: v5TE 165 # Tag_ARM_ISA_use: Yes 166 # Tag_THUMB_ISA_use: Thumb-1 167 # Tag_ABI_PCS_wchar_t: 4 168 # Tag_ABI_FP_denormal: Needed 169 # Tag_ABI_FP_exceptions: Needed 170 # Tag_ABI_FP_number_model: IEEE 754 171 # Tag_ABI_align8_needed: Yes 172 # Tag_ABI_align8_preserved: Yes, except leaf SP 173 # Tag_ABI_enum_size: int 174 # Tag_ABI_optimization_goals: Aggressive Speed 175 # Tag_unknown_44: 1 (0x1) 176 # 177 # This means that in static libraries, you can have both 178 # '5TE' and '7-A' CPU name tags at the same time, or only 179 # '5TE' or only '7-A', deal with all these cases properly. 180 181 echo " found tags: CPU names:'$CPU_NAMES' VFP:'$VFP_ARCHS' NEON:'$NEON_ARCHS'" 182 183 # Clearly, any trace of NEON is a deal-breaker! 184 if [ "$NEON_ARCHS" ]; then 185 1>&2 echo "PANIC: Binary file should not contain NEON instructions: $1" 186 exit 1 187 fi 188 189 if is_static_file "$1"; then 190 # For static libraries / object files, it's ok to contain ARMv5TE binaries 191 if [ "$CPU_NAMES" == "\"5TE\"" -a "$CPU_NAMES" != "\"7-A\"" -a "$CPU_NAMES" != "\"5TE\" \"7-A\"" ]; then 192 # Neither ARMv7-A or ARMv5TE+ARMv7-A, something's fishy 193 1>&2 echo "PANIC: File is neither ARMv5TE or ARMv7-A binary: $1" 194 exit 1 195 fi 196 197 # exit here because some static libraries can have a mix of several 198 # VFP tags that make them difficult to check (e.g. libgnustl_static.a 199 # can have 'VFPv1 VFPv2 VFPv3' at the same time :-( 200 return 201 fi 202 203 # If we reach this point, we only contain ARMv7-A machine code, so look 204 # at the VFP arch tag(s) 205 206 # Sometimes no VFP_arch tag is placed in the final binary, this happens 207 # with libgabi++_shared.so for example, because the code doesn't have 208 # any floating point instructions. 209 # 210 211 # XXX: FOR NOW, ASSUME BROKEN binutils-2.19, AND THUS THAT 'VFPv3' IS VALID 212 213 if [ "$VFP_ARCHS" != "VFPv3" -a "$VFP_ARCHS" != "VFPv3-D16" -a "$VFP_ARCHS" != "" ]; then 214 1>&2 echo "PANIC: File is not a VFPv3-D16 binary: $1" 215 exit 1 216 fi 217} 218 219. $NDK/build/tools/dev-defaults.sh 220 221ARM_TOOLCHAIN_NAME=$(get_default_toolchain_name_for_arch arm) 222ARM_TOOLCHAIN_PREFIX=$(get_default_toolchain_prefix_for_arch arm) 223 224case $(uname -s) in 225 Darwin) 226 HOST_ARCH=`uname -m` 227 case "$HOST_ARCH" in 228 i?86) HOST_ARCH=x86 229 if ! echo __LP64__ | (CCOPTS= gcc -E - 2>/dev/null) | grep -q __LP64__ ; then 230 HOST_ARCH=x86_64 231 fi 232 ;; 233 esac 234 HOST_TAG=darwin-$HOST_ARCH 235 ;; 236 Linux) 237 HOST_TAG=linux-$(uname -p) 238 ;; 239 *) 240 echo "WARNING: This test cannot run on this machine!" >&2 241 exit 0 242 ;; 243esac 244 245ARM_READELF=$NDK/toolchains/$ARM_TOOLCHAIN_NAME/prebuilt/$HOST_TAG/bin/${ARM_TOOLCHAIN_PREFIX}-readelf 246if [ ! -f "$ARM_READELF" ]; then 247 echo "ERROR: Missing binary: $ARM_READELF" >&2 248 exit 1 249fi 250 251ARMv7_ABIS="armeabi-v7a armeabi-v7a-hard" 252for ABI in $ARMv7_ABIS; do 253 254 GABIXX_LIBS=$NDK/sources/cxx-stl/gabi++/libs/$ABI 255 check_armv7_elf_binary $GABIXX_LIBS/libgabi++_shared.so 256 check_armv7_elf_binary $GABIXX_LIBS/libgabi++_static.a 257 258 STLPORT_LIBS=$NDK/sources/cxx-stl/stlport/libs/$ABI 259 check_armv7_elf_binary $STLPORT_LIBS/libstlport_shared.so 260 check_armv7_elf_binary $STLPORT_LIBS/libstlport_static.a 261 262 263 for VERSION in $DEFAULT_GCC_VERSION_LIST; do 264 GNUSTL_LIBS=$NDK/sources/cxx-stl/gnu-libstdc++/$VERSION/libs/$ABI 265 check_armv7_elf_binary $GNUSTL_LIBS/libsupc++.a 266 check_armv7_elf_binary $GNUSTL_LIBS/libgnustl_shared.so 267 check_armv7_elf_binary $GNUSTL_LIBS/libgnustl_static.a 268 done 269done 270 271echo "Done!" 272