OLD | NEW |
(Empty) | |
| 1 #!/bin/bash |
| 2 #===- lib/asan/scripts/asan_device_setup -----------------------------------===# |
| 3 # |
| 4 # The LLVM Compiler Infrastructure |
| 5 # |
| 6 # This file is distributed under the University of Illinois Open Source |
| 7 # License. See LICENSE.TXT for details. |
| 8 # |
| 9 # Prepare Android device to run ASan applications. |
| 10 # |
| 11 #===------------------------------------------------------------------------===# |
| 12 |
| 13 set -e |
| 14 |
| 15 HERE="$(cd "$(dirname "$0")" && pwd)" |
| 16 |
| 17 revert=no |
| 18 extra_options= |
| 19 device= |
| 20 lib= |
| 21 |
| 22 function usage { |
| 23 echo "usage: $0 [--revert] [--device device-id] [--lib path] [--extra-option
s options]" |
| 24 echo " --revert: Uninstall ASan from the device." |
| 25 echo " --lib: Path to ASan runtime library." |
| 26 echo " --extra-options: Extra ASAN_OPTIONS." |
| 27 echo " --device: Install to the given device. Use 'adb devices' to find" |
| 28 echo " device-id." |
| 29 echo |
| 30 exit 1 |
| 31 } |
| 32 |
| 33 function get_device_arch { # OUTVAR |
| 34 local _outvar=$1 |
| 35 local _ABI=$($ADB shell getprop ro.product.cpu.abi) |
| 36 local _ARCH= |
| 37 if [[ $_ABI == x86* ]]; then |
| 38 _ARCH=i686 |
| 39 elif [[ $_ABI == armeabi* ]]; then |
| 40 _ARCH=arm |
| 41 else |
| 42 echo "Unrecognized device ABI: $_ABI" |
| 43 exit 1 |
| 44 fi |
| 45 eval $_outvar=\$_ARCH |
| 46 } |
| 47 |
| 48 while [[ $# > 0 ]]; do |
| 49 case $1 in |
| 50 --revert) |
| 51 revert=yes |
| 52 ;; |
| 53 --extra-options) |
| 54 shift |
| 55 if [[ $# == 0 ]]; then |
| 56 echo "--extra-options requires an argument." |
| 57 exit 1 |
| 58 fi |
| 59 extra_options="$1" |
| 60 ;; |
| 61 --lib) |
| 62 shift |
| 63 if [[ $# == 0 ]]; then |
| 64 echo "--lib requires an argument." |
| 65 exit 1 |
| 66 fi |
| 67 lib="$1" |
| 68 ;; |
| 69 --device) |
| 70 shift |
| 71 if [[ $# == 0 ]]; then |
| 72 echo "--device requires an argument." |
| 73 exit 1 |
| 74 fi |
| 75 device="$1" |
| 76 ;; |
| 77 *) |
| 78 usage |
| 79 ;; |
| 80 esac |
| 81 shift |
| 82 done |
| 83 |
| 84 ADB=${ADB:-adb} |
| 85 if [[ x$device != x ]]; then |
| 86 ADB="$ADB -s $device" |
| 87 fi |
| 88 |
| 89 echo '>> Remounting /system rw' |
| 90 $ADB root |
| 91 $ADB wait-for-device |
| 92 $ADB remount |
| 93 $ADB wait-for-device |
| 94 |
| 95 get_device_arch ARCH |
| 96 echo "Target architecture: $ARCH" |
| 97 ASAN_RT="libclang_rt.asan-$ARCH-android.so" |
| 98 |
| 99 if [[ x$revert == xyes ]]; then |
| 100 echo '>> Uninstalling ASan' |
| 101 |
| 102 if ! $ADB shell readlink /system/bin/app_process | grep 'app_process' >&/dev
/null; then |
| 103 echo '>> Pre-L device detected.' |
| 104 $ADB shell mv /system/bin/app_process.real /system/bin/app_process |
| 105 $ADB shell rm /system/bin/asanwrapper |
| 106 $ADB shell rm /system/lib/$ASAN_RT |
| 107 else |
| 108 $ADB shell rm /system/bin/app_process.wrap |
| 109 $ADB shell rm /system/bin/asanwrapper |
| 110 $ADB shell rm /system/lib/$ASAN_RT |
| 111 $ADB shell rm /system/bin/app_process |
| 112 $ADB shell ln -s /system/bin/app_process32 /system/bin/app_process |
| 113 fi |
| 114 |
| 115 echo '>> Restarting shell' |
| 116 $ADB shell stop |
| 117 $ADB shell start |
| 118 |
| 119 echo '>> Done' |
| 120 exit 0 |
| 121 fi |
| 122 |
| 123 if [[ -d "$lib" ]]; then |
| 124 ASAN_RT_PATH="$lib" |
| 125 elif [[ -f "$lib" && "$lib" == *"$ASAN_RT" ]]; then |
| 126 ASAN_RT_PATH=$(dirname "$lib") |
| 127 elif [[ -f "$HERE/$ASAN_RT" ]]; then |
| 128 ASAN_RT_PATH="$HERE" |
| 129 elif [[ $(basename "$HERE") == "bin" ]]; then |
| 130 # We could be in the toolchain's base directory. |
| 131 # Consider ../lib, ../lib/asan, ../lib/linux and ../lib/clang/$VERSION/lib/l
inux. |
| 132 P=$(ls "$HERE"/../lib/"$ASAN_RT" "$HERE"/../lib/asan/"$ASAN_RT" "$HERE"/../l
ib/linux/"$ASAN_RT" "$HERE"/../lib/clang/*/lib/linux/"$ASAN_RT" 2>/dev/null | so
rt | tail -1) |
| 133 if [[ -n "$P" ]]; then |
| 134 ASAN_RT_PATH="$(dirname "$P")" |
| 135 fi |
| 136 fi |
| 137 |
| 138 if [[ -z "$ASAN_RT_PATH" || ! -f "$ASAN_RT_PATH/$ASAN_RT" ]]; then |
| 139 echo ">> ASan runtime library not found" |
| 140 exit 1 |
| 141 fi |
| 142 |
| 143 TMPDIRBASE=$(mktemp -d) |
| 144 TMPDIROLD="$TMPDIRBASE/old" |
| 145 TMPDIR="$TMPDIRBASE/new" |
| 146 mkdir "$TMPDIROLD" |
| 147 |
| 148 RELEASE=$($ADB shell getprop ro.build.version.release) |
| 149 PRE_L=0 |
| 150 if echo "$RELEASE" | grep '^4\.' >&/dev/null; then |
| 151 PRE_L=1 |
| 152 fi |
| 153 |
| 154 if ! $ADB shell readlink /system/bin/app_process | grep 'app_process' >&/dev/nul
l; then |
| 155 |
| 156 if $ADB pull /system/bin/app_process.real /dev/null >&/dev/null; then |
| 157 echo '>> Old-style ASan installation detected. Reverting.' |
| 158 $ADB shell mv /system/bin/app_process.real /system/bin/app_process |
| 159 fi |
| 160 |
| 161 echo '>> Pre-L device detected. Setting up app_process symlink.' |
| 162 $ADB shell mv /system/bin/app_process /system/bin/app_process32 |
| 163 $ADB shell ln -s /system/bin/app_process32 /system/bin/app_process |
| 164 fi |
| 165 |
| 166 echo '>> Copying files from the device' |
| 167 $ADB pull /system/bin/app_process.wrap "$TMPDIROLD" || true |
| 168 $ADB pull /system/bin/asanwrapper "$TMPDIROLD" || true |
| 169 $ADB pull /system/lib/"$ASAN_RT" "$TMPDIROLD" || true |
| 170 cp -r "$TMPDIROLD" "$TMPDIR" |
| 171 |
| 172 if [[ -f "$TMPDIR/app_process.wrap" ]]; then |
| 173 echo ">> Previous installation detected" |
| 174 else |
| 175 echo ">> New installation" |
| 176 fi |
| 177 |
| 178 echo '>> Generating wrappers' |
| 179 |
| 180 cp "$ASAN_RT_PATH/$ASAN_RT" "$TMPDIR/" |
| 181 |
| 182 # FIXME: alloc_dealloc_mismatch=0 prevents a failure in libdvm startup, |
| 183 # which may or may not be a real bug (probably not). |
| 184 ASAN_OPTIONS=start_deactivated=1,alloc_dealloc_mismatch=0 |
| 185 |
| 186 # On Android-L not allowing user segv handler breaks some applications. |
| 187 if [[ PRE_L -eq 0 ]]; then |
| 188 ASAN_OPTIONS="$ASAN_OPTIONS,allow_user_segv_handler=1" |
| 189 fi |
| 190 |
| 191 if [[ x$extra_options != x ]] ; then |
| 192 ASAN_OPTIONS="$ASAN_OPTIONS,$extra_options" |
| 193 fi |
| 194 |
| 195 # Zygote wrapper. |
| 196 cat <<EOF >"$TMPDIR/app_process.wrap" |
| 197 #!/system/bin/sh-from-zygote |
| 198 ASAN_OPTIONS=$ASAN_OPTIONS \\ |
| 199 LD_PRELOAD=\$LD_PRELOAD:$ASAN_RT \\ |
| 200 exec /system/bin/app_process32 \$@ |
| 201 |
| 202 EOF |
| 203 |
| 204 # General command-line tool wrapper (use for anything that's not started as |
| 205 # zygote). |
| 206 cat <<EOF >"$TMPDIR/asanwrapper" |
| 207 #!/system/bin/sh |
| 208 LD_PRELOAD=$ASAN_RT \\ |
| 209 exec \$@ |
| 210 |
| 211 EOF |
| 212 |
| 213 if ! ( cd "$TMPDIRBASE" && diff -qr old/ new/ ) ; then |
| 214 echo '>> Pushing files to the device' |
| 215 $ADB push "$TMPDIR/$ASAN_RT" /system/lib/ |
| 216 $ADB push "$TMPDIR/app_process.wrap" /system/bin/app_process.wrap |
| 217 $ADB push "$TMPDIR/asanwrapper" /system/bin/asanwrapper |
| 218 |
| 219 $ADB shell rm /system/bin/app_process |
| 220 $ADB shell ln -s /system/bin/app_process.wrap /system/bin/app_process |
| 221 |
| 222 $ADB shell chown root.shell \ |
| 223 /system/lib/"$ASAN_RT" \ |
| 224 /system/bin/app_process.wrap \ |
| 225 /system/bin/asanwrapper |
| 226 $ADB shell chmod 644 \ |
| 227 /system/lib/"$ASAN_RT" |
| 228 $ADB shell chmod 755 \ |
| 229 /system/bin/app_process.wrap \ |
| 230 /system/bin/asanwrapper |
| 231 |
| 232 # Make SELinux happy by keeping app_process wrapper and the shell |
| 233 # it runs on in zygote domain. |
| 234 ENFORCING=0 |
| 235 if $ADB shell getenforce | grep Enforcing >/dev/null; then |
| 236 # Sometimes shell is not allowed to change file contexts. |
| 237 # Temporarily switch to permissive. |
| 238 ENFORCING=1 |
| 239 $ADB shell setenforce 0 |
| 240 fi |
| 241 |
| 242 $ADB shell cp /system/bin/sh /system/bin/sh-from-zygote |
| 243 |
| 244 if [[ PRE_L -eq 1 ]]; then |
| 245 CTX=u:object_r:system_file:s0 |
| 246 else |
| 247 CTX=u:object_r:zygote_exec:s0 |
| 248 fi |
| 249 $ADB shell chcon $CTX \ |
| 250 /system/bin/sh-from-zygote \ |
| 251 /system/bin/app_process.wrap \ |
| 252 /system/bin/app_process32 |
| 253 |
| 254 if [ $ENFORCING == 1 ]; then |
| 255 $ADB shell setenforce 1 |
| 256 fi |
| 257 |
| 258 echo '>> Restarting shell (asynchronous)' |
| 259 $ADB shell stop |
| 260 $ADB shell start |
| 261 |
| 262 echo '>> Please wait until the device restarts' |
| 263 else |
| 264 echo '>> Device is up to date' |
| 265 fi |
| 266 |
| 267 rm -r "$TMPDIRBASE" |
OLD | NEW |