blob: 104e07b722caa61c0192f4f0140327c5fb75ed61 [file] [log] [blame]
Stephen Hines6d186232014-11-26 17:56:19 -08001#!/bin/bash
Stephen Hines2d1fdb22014-05-28 23:58:16 -07002#===- 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
Stephen Hines6d186232014-11-26 17:56:19 -080013set -e
Stephen Hines2d1fdb22014-05-28 23:58:16 -070014
15HERE="$(cd "$(dirname "$0")" && pwd)"
16
17revert=no
18extra_options=
19device=
20lib=
Stephen Hines86277eb2015-03-23 12:06:32 -070021use_su=0
Stephen Hines2d1fdb22014-05-28 23:58:16 -070022
23function usage {
24 echo "usage: $0 [--revert] [--device device-id] [--lib path] [--extra-options options]"
25 echo " --revert: Uninstall ASan from the device."
26 echo " --lib: Path to ASan runtime library."
27 echo " --extra-options: Extra ASAN_OPTIONS."
28 echo " --device: Install to the given device. Use 'adb devices' to find"
29 echo " device-id."
Stephen Hines86277eb2015-03-23 12:06:32 -070030 echo " --use-su: Use 'su -c' prefix for every adb command instead of using"
31 echo " 'adb root' once."
Stephen Hines2d1fdb22014-05-28 23:58:16 -070032 echo
33 exit 1
34}
35
Stephen Hines86277eb2015-03-23 12:06:32 -070036function adb_push {
37 if [ $use_su -eq 0 ]; then
38 $ADB push "$1" "$2"
39 else
40 local FILENAME=$(basename $1)
41 $ADB push "$1" "/data/local/tmp/$FILENAME"
42 $ADB shell su -c "rm \\\"$2/$FILENAME\\\"" >&/dev/null
43 $ADB shell su -c "cat \\\"/data/local/tmp/$FILENAME\\\" > \\\"$2/$FILENAME\\\""
44 $ADB shell su -c "rm \\\"/data/local/tmp/$FILENAME\\\""
45 fi
46}
47
48function adb_remount {
49 if [ $use_su -eq 0 ]; then
50 $ADB remount
51 else
52 local STORAGE=`$ADB shell mount | grep /system | cut -d ' ' -f1`
53 if [ "$STORAGE" != "" ]; then
54 echo Remounting $STORAGE at /system
55 $ADB shell su -c "mount -o remount,rw $STORAGE /system"
56 else
57 echo Failed to get storage device name for "/system" mount point
58 fi
59 fi
60}
61
62function adb_shell {
63 if [ $use_su -eq 0 ]; then
64 $ADB shell $@
65 else
66 $ADB shell su -c "$*"
67 fi
68}
69
70function adb_root {
71 if [ $use_su -eq 0 ]; then
72 $ADB root
73 fi
74}
75
76function adb_wait_for_device {
77 $ADB wait-for-device
78}
79
80function adb_pull {
81 if [ $use_su -eq 0 ]; then
82 $ADB pull "$1" "$2"
83 else
84 local FILENAME=$(basename $1)
85 $ADB shell rm "/data/local/tmp/$FILENAME" >&/dev/null
86 $ADB shell su -c "[ -f \\\"$1\\\" ] && cat \\\"$1\\\" > \\\"/data/local/tmp/$FILENAME\\\" && chown root.shell \\\"/data/local/tmp/$FILENAME\\\" && chmod 755 \\\"/data/local/tmp/$FILENAME\\\"" &&
87 $ADB pull "/data/local/tmp/$FILENAME" "$2" >&/dev/null && $ADB shell "rm \"/data/local/tmp/$FILENAME\""
88 fi
89}
90
Stephen Hines6d186232014-11-26 17:56:19 -080091function get_device_arch { # OUTVAR
92 local _outvar=$1
Stephen Hines86277eb2015-03-23 12:06:32 -070093 local _ABI=$(adb_shell getprop ro.product.cpu.abi)
Stephen Hines6d186232014-11-26 17:56:19 -080094 local _ARCH=
95 if [[ $_ABI == x86* ]]; then
96 _ARCH=i686
97 elif [[ $_ABI == armeabi* ]]; then
98 _ARCH=arm
99 else
100 echo "Unrecognized device ABI: $_ABI"
101 exit 1
102 fi
103 eval $_outvar=\$_ARCH
104}
105
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700106while [[ $# > 0 ]]; do
107 case $1 in
108 --revert)
109 revert=yes
110 ;;
111 --extra-options)
112 shift
113 if [[ $# == 0 ]]; then
114 echo "--extra-options requires an argument."
115 exit 1
116 fi
117 extra_options="$1"
118 ;;
119 --lib)
120 shift
121 if [[ $# == 0 ]]; then
122 echo "--lib requires an argument."
123 exit 1
124 fi
125 lib="$1"
126 ;;
127 --device)
128 shift
129 if [[ $# == 0 ]]; then
130 echo "--device requires an argument."
131 exit 1
132 fi
133 device="$1"
134 ;;
Stephen Hines86277eb2015-03-23 12:06:32 -0700135 --use-su)
136 use_su=1
137 ;;
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700138 *)
139 usage
140 ;;
141 esac
142 shift
143done
144
145ADB=${ADB:-adb}
146if [[ x$device != x ]]; then
147 ADB="$ADB -s $device"
148fi
149
Stephen Hines86277eb2015-03-23 12:06:32 -0700150if [ $use_su -eq 1 ]; then
151 # Test if 'su' is present on the device
152 SU_TEST_OUT=`$ADB shell su -c "echo foo" 2>&1 | sed 's/\r$//'`
153 if [ $? != 0 -o "$SU_TEST_OUT" != "foo" ]; then
154 echo "ERROR: Cannot use 'su -c':"
155 echo "$ adb shell su -c \"echo foo\""
156 echo $SU_TEST_OUT
157 echo "Check that 'su' binary is correctly installed on the device or omit"
158 echo " --use-su flag"
159 exit 1
160 fi
161fi
162
Stephen Hines6d186232014-11-26 17:56:19 -0800163echo '>> Remounting /system rw'
Stephen Hines86277eb2015-03-23 12:06:32 -0700164adb_wait_for_device
165adb_root
166adb_wait_for_device
167adb_remount
168adb_wait_for_device
Stephen Hines6d186232014-11-26 17:56:19 -0800169
170get_device_arch ARCH
171echo "Target architecture: $ARCH"
172ASAN_RT="libclang_rt.asan-$ARCH-android.so"
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700173
174if [[ x$revert == xyes ]]; then
175 echo '>> Uninstalling ASan'
Stephen Hines6d186232014-11-26 17:56:19 -0800176
Stephen Hines86277eb2015-03-23 12:06:32 -0700177 if ! adb_shell ls -l /system/bin/app_process | grep -o '\->.*app_process' >&/dev/null; then
Stephen Hines6d186232014-11-26 17:56:19 -0800178 echo '>> Pre-L device detected.'
Stephen Hines86277eb2015-03-23 12:06:32 -0700179 adb_shell mv /system/bin/app_process.real /system/bin/app_process
180 adb_shell rm /system/bin/asanwrapper
Stephen Hines6d186232014-11-26 17:56:19 -0800181 else
Stephen Hines86277eb2015-03-23 12:06:32 -0700182 adb_shell rm /system/bin/app_process.wrap
183 adb_shell rm /system/bin/asanwrapper
184 adb_shell rm /system/bin/app_process
185 adb_shell ln -s /system/bin/app_process32 /system/bin/app_process
Stephen Hines6d186232014-11-26 17:56:19 -0800186 fi
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700187
188 echo '>> Restarting shell'
Stephen Hines86277eb2015-03-23 12:06:32 -0700189 adb_shell stop
190 adb_shell start
191
192 # Remove the library on the last step to give a chance to the 'su' binary to
193 # be executed without problem.
194 adb_shell rm /system/lib/$ASAN_RT
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700195
196 echo '>> Done'
197 exit 0
198fi
199
200if [[ -d "$lib" ]]; then
201 ASAN_RT_PATH="$lib"
202elif [[ -f "$lib" && "$lib" == *"$ASAN_RT" ]]; then
203 ASAN_RT_PATH=$(dirname "$lib")
204elif [[ -f "$HERE/$ASAN_RT" ]]; then
205 ASAN_RT_PATH="$HERE"
206elif [[ $(basename "$HERE") == "bin" ]]; then
207 # We could be in the toolchain's base directory.
Stephen Hines6d186232014-11-26 17:56:19 -0800208 # Consider ../lib, ../lib/asan, ../lib/linux and ../lib/clang/$VERSION/lib/linux.
209 P=$(ls "$HERE"/../lib/"$ASAN_RT" "$HERE"/../lib/asan/"$ASAN_RT" "$HERE"/../lib/linux/"$ASAN_RT" "$HERE"/../lib/clang/*/lib/linux/"$ASAN_RT" 2>/dev/null | sort | tail -1)
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700210 if [[ -n "$P" ]]; then
211 ASAN_RT_PATH="$(dirname "$P")"
212 fi
213fi
214
215if [[ -z "$ASAN_RT_PATH" || ! -f "$ASAN_RT_PATH/$ASAN_RT" ]]; then
Stephen Hines6d186232014-11-26 17:56:19 -0800216 echo ">> ASan runtime library not found"
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700217 exit 1
218fi
219
220TMPDIRBASE=$(mktemp -d)
221TMPDIROLD="$TMPDIRBASE/old"
222TMPDIR="$TMPDIRBASE/new"
223mkdir "$TMPDIROLD"
224
Stephen Hines86277eb2015-03-23 12:06:32 -0700225RELEASE=$(adb_shell getprop ro.build.version.release)
Stephen Hines6d186232014-11-26 17:56:19 -0800226PRE_L=0
227if echo "$RELEASE" | grep '^4\.' >&/dev/null; then
228 PRE_L=1
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700229fi
230
Stephen Hines86277eb2015-03-23 12:06:32 -0700231if ! adb_shell ls -l /system/bin/app_process | grep -o '\->.*app_process' >&/dev/null; then
Stephen Hines6d186232014-11-26 17:56:19 -0800232
Stephen Hines86277eb2015-03-23 12:06:32 -0700233 if adb_pull /system/bin/app_process.real /dev/null >&/dev/null; then
Stephen Hines6d186232014-11-26 17:56:19 -0800234 echo '>> Old-style ASan installation detected. Reverting.'
Stephen Hines86277eb2015-03-23 12:06:32 -0700235 adb_shell mv /system/bin/app_process.real /system/bin/app_process
Stephen Hines6d186232014-11-26 17:56:19 -0800236 fi
237
238 echo '>> Pre-L device detected. Setting up app_process symlink.'
Stephen Hines86277eb2015-03-23 12:06:32 -0700239 adb_shell mv /system/bin/app_process /system/bin/app_process32
240 adb_shell ln -s /system/bin/app_process32 /system/bin/app_process
Stephen Hines6d186232014-11-26 17:56:19 -0800241fi
242
243echo '>> Copying files from the device'
Stephen Hines86277eb2015-03-23 12:06:32 -0700244adb_pull /system/bin/app_process.wrap "$TMPDIROLD" || true
245adb_pull /system/bin/asanwrapper "$TMPDIROLD" || true
246adb_pull /system/lib/"$ASAN_RT" "$TMPDIROLD" || true
Stephen Hines6d186232014-11-26 17:56:19 -0800247cp -r "$TMPDIROLD" "$TMPDIR"
248
249if [[ -f "$TMPDIR/app_process.wrap" ]]; then
250 echo ">> Previous installation detected"
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700251else
Stephen Hines6d186232014-11-26 17:56:19 -0800252 echo ">> New installation"
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700253fi
254
255echo '>> Generating wrappers'
256
257cp "$ASAN_RT_PATH/$ASAN_RT" "$TMPDIR/"
258
259# FIXME: alloc_dealloc_mismatch=0 prevents a failure in libdvm startup,
260# which may or may not be a real bug (probably not).
261ASAN_OPTIONS=start_deactivated=1,alloc_dealloc_mismatch=0
Stephen Hines6d186232014-11-26 17:56:19 -0800262
263# On Android-L not allowing user segv handler breaks some applications.
Stephen Hines86277eb2015-03-23 12:06:32 -0700264if [[ PRE_L -eq 0 ]]; then
Stephen Hines6d186232014-11-26 17:56:19 -0800265 ASAN_OPTIONS="$ASAN_OPTIONS,allow_user_segv_handler=1"
266fi
267
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700268if [[ x$extra_options != x ]] ; then
269 ASAN_OPTIONS="$ASAN_OPTIONS,$extra_options"
270fi
271
272# Zygote wrapper.
Stephen Hines6d186232014-11-26 17:56:19 -0800273cat <<EOF >"$TMPDIR/app_process.wrap"
274#!/system/bin/sh-from-zygote
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700275ASAN_OPTIONS=$ASAN_OPTIONS \\
Stephen Hines6d186232014-11-26 17:56:19 -0800276LD_PRELOAD=\$LD_PRELOAD:$ASAN_RT \\
277exec /system/bin/app_process32 \$@
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700278
279EOF
280
281# General command-line tool wrapper (use for anything that's not started as
282# zygote).
283cat <<EOF >"$TMPDIR/asanwrapper"
284#!/system/bin/sh
Stephen Hines6d186232014-11-26 17:56:19 -0800285LD_PRELOAD=$ASAN_RT \\
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700286exec \$@
287
288EOF
289
290if ! ( cd "$TMPDIRBASE" && diff -qr old/ new/ ) ; then
291 echo '>> Pushing files to the device'
Stephen Hines86277eb2015-03-23 12:06:32 -0700292 adb_push "$TMPDIR/$ASAN_RT" /system/lib/
293 adb_push "$TMPDIR/app_process.wrap" /system/bin
294 adb_push "$TMPDIR/asanwrapper" /system/bin
Stephen Hines6d186232014-11-26 17:56:19 -0800295
Stephen Hines86277eb2015-03-23 12:06:32 -0700296 adb_shell rm /system/bin/app_process
297 adb_shell ln -s /system/bin/app_process.wrap /system/bin/app_process
Stephen Hines6d186232014-11-26 17:56:19 -0800298
Stephen Hines86277eb2015-03-23 12:06:32 -0700299 adb_shell chown root.shell \
Stephen Hines6d186232014-11-26 17:56:19 -0800300 /system/lib/"$ASAN_RT" \
301 /system/bin/app_process.wrap \
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700302 /system/bin/asanwrapper
Stephen Hines86277eb2015-03-23 12:06:32 -0700303 adb_shell chmod 644 \
Stephen Hines6d186232014-11-26 17:56:19 -0800304 /system/lib/"$ASAN_RT"
Stephen Hines86277eb2015-03-23 12:06:32 -0700305 adb_shell chmod 755 \
Stephen Hines6d186232014-11-26 17:56:19 -0800306 /system/bin/app_process.wrap \
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700307 /system/bin/asanwrapper
308
Stephen Hines6d186232014-11-26 17:56:19 -0800309 # Make SELinux happy by keeping app_process wrapper and the shell
310 # it runs on in zygote domain.
311 ENFORCING=0
Stephen Hines86277eb2015-03-23 12:06:32 -0700312 if adb_shell getenforce | grep Enforcing >/dev/null; then
Stephen Hines6d186232014-11-26 17:56:19 -0800313 # Sometimes shell is not allowed to change file contexts.
314 # Temporarily switch to permissive.
315 ENFORCING=1
Stephen Hines86277eb2015-03-23 12:06:32 -0700316 adb_shell setenforce 0
Stephen Hines6d186232014-11-26 17:56:19 -0800317 fi
318
Stephen Hines86277eb2015-03-23 12:06:32 -0700319 adb_shell cp /system/bin/sh /system/bin/sh-from-zygote
Stephen Hines6d186232014-11-26 17:56:19 -0800320
321 if [[ PRE_L -eq 1 ]]; then
322 CTX=u:object_r:system_file:s0
323 else
324 CTX=u:object_r:zygote_exec:s0
325 fi
Stephen Hines86277eb2015-03-23 12:06:32 -0700326 adb_shell chcon $CTX \
Stephen Hines6d186232014-11-26 17:56:19 -0800327 /system/bin/sh-from-zygote \
328 /system/bin/app_process.wrap \
329 /system/bin/app_process32
330
331 if [ $ENFORCING == 1 ]; then
Stephen Hines86277eb2015-03-23 12:06:32 -0700332 adb_shell setenforce 1
Stephen Hines6d186232014-11-26 17:56:19 -0800333 fi
334
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700335 echo '>> Restarting shell (asynchronous)'
Stephen Hines86277eb2015-03-23 12:06:32 -0700336 adb_shell stop
337 adb_shell start
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700338
339 echo '>> Please wait until the device restarts'
340else
341 echo '>> Device is up to date'
342fi
343
344rm -r "$TMPDIRBASE"