blob: 6cb7b94c21978924e750d6c36f5f56b84b7cefbe [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
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080091function get_device_arch { # OUT OUT64
Stephen Hines6d186232014-11-26 17:56:19 -080092 local _outvar=$1
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080093 local _outvar64=$2
Stephen Hines86277eb2015-03-23 12:06:32 -070094 local _ABI=$(adb_shell getprop ro.product.cpu.abi)
Stephen Hines6d186232014-11-26 17:56:19 -080095 local _ARCH=
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080096 local _ARCH64=
Stephen Hines6d186232014-11-26 17:56:19 -080097 if [[ $_ABI == x86* ]]; then
98 _ARCH=i686
99 elif [[ $_ABI == armeabi* ]]; then
100 _ARCH=arm
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800101 elif [[ $_ABI == arm64-v8a* ]]; then
102 _ARCH=arm
103 _ARCH64=aarch64
Stephen Hines6d186232014-11-26 17:56:19 -0800104 else
105 echo "Unrecognized device ABI: $_ABI"
106 exit 1
107 fi
108 eval $_outvar=\$_ARCH
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800109 eval $_outvar64=\$_ARCH64
Stephen Hines6d186232014-11-26 17:56:19 -0800110}
111
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700112while [[ $# > 0 ]]; do
113 case $1 in
114 --revert)
115 revert=yes
116 ;;
117 --extra-options)
118 shift
119 if [[ $# == 0 ]]; then
120 echo "--extra-options requires an argument."
121 exit 1
122 fi
123 extra_options="$1"
124 ;;
125 --lib)
126 shift
127 if [[ $# == 0 ]]; then
128 echo "--lib requires an argument."
129 exit 1
130 fi
131 lib="$1"
132 ;;
133 --device)
134 shift
135 if [[ $# == 0 ]]; then
136 echo "--device requires an argument."
137 exit 1
138 fi
139 device="$1"
140 ;;
Stephen Hines86277eb2015-03-23 12:06:32 -0700141 --use-su)
142 use_su=1
143 ;;
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700144 *)
145 usage
146 ;;
147 esac
148 shift
149done
150
151ADB=${ADB:-adb}
152if [[ x$device != x ]]; then
153 ADB="$ADB -s $device"
154fi
155
Stephen Hines86277eb2015-03-23 12:06:32 -0700156if [ $use_su -eq 1 ]; then
157 # Test if 'su' is present on the device
158 SU_TEST_OUT=`$ADB shell su -c "echo foo" 2>&1 | sed 's/\r$//'`
159 if [ $? != 0 -o "$SU_TEST_OUT" != "foo" ]; then
160 echo "ERROR: Cannot use 'su -c':"
161 echo "$ adb shell su -c \"echo foo\""
162 echo $SU_TEST_OUT
163 echo "Check that 'su' binary is correctly installed on the device or omit"
164 echo " --use-su flag"
165 exit 1
166 fi
167fi
168
Stephen Hines6d186232014-11-26 17:56:19 -0800169echo '>> Remounting /system rw'
Stephen Hines86277eb2015-03-23 12:06:32 -0700170adb_wait_for_device
171adb_root
172adb_wait_for_device
173adb_remount
174adb_wait_for_device
Stephen Hines6d186232014-11-26 17:56:19 -0800175
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800176get_device_arch ARCH ARCH64
Stephen Hines6d186232014-11-26 17:56:19 -0800177echo "Target architecture: $ARCH"
178ASAN_RT="libclang_rt.asan-$ARCH-android.so"
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800179if [[ -n $ARCH64 ]]; then
180 echo "Target architecture: $ARCH64"
181 ASAN_RT64="libclang_rt.asan-$ARCH64-android.so"
182fi
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700183
184if [[ x$revert == xyes ]]; then
185 echo '>> Uninstalling ASan'
Stephen Hines6d186232014-11-26 17:56:19 -0800186
Stephen Hines86277eb2015-03-23 12:06:32 -0700187 if ! adb_shell ls -l /system/bin/app_process | grep -o '\->.*app_process' >&/dev/null; then
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800188 echo '>> Pre-L device detected.'
189 adb_shell mv /system/bin/app_process.real /system/bin/app_process
190 adb_shell rm /system/bin/asanwrapper
191 elif ! adb_shell ls -l /system/bin/app_process64.real | grep -o 'No such file or directory' >&/dev/null; then
192 # 64-bit installation.
193 adb_shell mv /system/bin/app_process32.real /system/bin/app_process32
194 adb_shell mv /system/bin/app_process64.real /system/bin/app_process64
195 adb_shell rm /system/bin/asanwrapper
196 adb_shell rm /system/bin/asanwrapper64
Stephen Hines6d186232014-11-26 17:56:19 -0800197 else
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800198 # 32-bit installation.
199 adb_shell rm /system/bin/app_process.wrap
200 adb_shell rm /system/bin/asanwrapper
201 adb_shell rm /system/bin/app_process
202 adb_shell ln -s /system/bin/app_process32 /system/bin/app_process
Stephen Hines6d186232014-11-26 17:56:19 -0800203 fi
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700204
205 echo '>> Restarting shell'
Stephen Hines86277eb2015-03-23 12:06:32 -0700206 adb_shell stop
207 adb_shell start
208
209 # Remove the library on the last step to give a chance to the 'su' binary to
210 # be executed without problem.
211 adb_shell rm /system/lib/$ASAN_RT
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700212
213 echo '>> Done'
214 exit 0
215fi
216
217if [[ -d "$lib" ]]; then
218 ASAN_RT_PATH="$lib"
219elif [[ -f "$lib" && "$lib" == *"$ASAN_RT" ]]; then
220 ASAN_RT_PATH=$(dirname "$lib")
221elif [[ -f "$HERE/$ASAN_RT" ]]; then
222 ASAN_RT_PATH="$HERE"
223elif [[ $(basename "$HERE") == "bin" ]]; then
224 # We could be in the toolchain's base directory.
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800225 # Consider ../lib, ../lib/asan, ../lib/linux,
226 # ../lib/clang/$VERSION/lib/linux, and ../lib64/clang/$VERSION/lib/linux.
227 P=$(ls "$HERE"/../lib/"$ASAN_RT" \
228 "$HERE"/../lib/asan/"$ASAN_RT" \
229 "$HERE"/../lib/linux/"$ASAN_RT" \
230 "$HERE"/../lib/clang/*/lib/linux/"$ASAN_RT" \
231 "$HERE"/../lib64/clang/*/lib/linux/"$ASAN_RT" 2>/dev/null | sort | tail -1)
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700232 if [[ -n "$P" ]]; then
233 ASAN_RT_PATH="$(dirname "$P")"
234 fi
235fi
236
237if [[ -z "$ASAN_RT_PATH" || ! -f "$ASAN_RT_PATH/$ASAN_RT" ]]; then
Stephen Hines6d186232014-11-26 17:56:19 -0800238 echo ">> ASan runtime library not found"
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700239 exit 1
240fi
241
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800242if [[ -n "$ASAN_RT64" ]]; then
243 if [[ -z "$ASAN_RT_PATH" || ! -f "$ASAN_RT_PATH/$ASAN_RT64" ]]; then
244 echo ">> ASan runtime library not found"
245 exit 1
246 fi
247fi
248
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700249TMPDIRBASE=$(mktemp -d)
250TMPDIROLD="$TMPDIRBASE/old"
251TMPDIR="$TMPDIRBASE/new"
252mkdir "$TMPDIROLD"
253
Stephen Hines86277eb2015-03-23 12:06:32 -0700254RELEASE=$(adb_shell getprop ro.build.version.release)
Stephen Hines6d186232014-11-26 17:56:19 -0800255PRE_L=0
256if echo "$RELEASE" | grep '^4\.' >&/dev/null; then
257 PRE_L=1
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700258fi
259
Stephen Hines86277eb2015-03-23 12:06:32 -0700260if ! adb_shell ls -l /system/bin/app_process | grep -o '\->.*app_process' >&/dev/null; then
Stephen Hines6d186232014-11-26 17:56:19 -0800261
Stephen Hines86277eb2015-03-23 12:06:32 -0700262 if adb_pull /system/bin/app_process.real /dev/null >&/dev/null; then
Stephen Hines6d186232014-11-26 17:56:19 -0800263 echo '>> Old-style ASan installation detected. Reverting.'
Stephen Hines86277eb2015-03-23 12:06:32 -0700264 adb_shell mv /system/bin/app_process.real /system/bin/app_process
Stephen Hines6d186232014-11-26 17:56:19 -0800265 fi
266
267 echo '>> Pre-L device detected. Setting up app_process symlink.'
Stephen Hines86277eb2015-03-23 12:06:32 -0700268 adb_shell mv /system/bin/app_process /system/bin/app_process32
269 adb_shell ln -s /system/bin/app_process32 /system/bin/app_process
Stephen Hines6d186232014-11-26 17:56:19 -0800270fi
271
272echo '>> Copying files from the device'
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800273if [[ -n "$ASAN_RT64" ]]; then
274 adb_pull /system/lib/"$ASAN_RT" "$TMPDIROLD" || true
275 adb_pull /system/lib64/"$ASAN_RT64" "$TMPDIROLD" || true
276 adb_pull /system/bin/app_process32 "$TMPDIROLD" || true
277 adb_pull /system/bin/app_process32.real "$TMPDIROLD" || true
278 adb_pull /system/bin/app_process64 "$TMPDIROLD" || true
279 adb_pull /system/bin/app_process64.real "$TMPDIROLD" || true
280 adb_pull /system/bin/asanwrapper "$TMPDIROLD" || true
281 adb_pull /system/bin/asanwrapper64 "$TMPDIROLD" || true
282else
283 adb_pull /system/lib/"$ASAN_RT" "$TMPDIROLD" || true
284 adb_pull /system/bin/app_process32 "$TMPDIROLD" || true
285 adb_pull /system/bin/app_process.wrap "$TMPDIROLD" || true
286 adb_pull /system/bin/asanwrapper "$TMPDIROLD" || true
287fi
Stephen Hines6d186232014-11-26 17:56:19 -0800288cp -r "$TMPDIROLD" "$TMPDIR"
289
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800290if [[ -f "$TMPDIR/app_process.wrap" || -f "$TMPDIR/app_process64.real" ]]; then
Stephen Hines6d186232014-11-26 17:56:19 -0800291 echo ">> Previous installation detected"
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700292else
Stephen Hines6d186232014-11-26 17:56:19 -0800293 echo ">> New installation"
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700294fi
295
296echo '>> Generating wrappers'
297
298cp "$ASAN_RT_PATH/$ASAN_RT" "$TMPDIR/"
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800299if [[ -n "$ASAN_RT64" ]]; then
300 cp "$ASAN_RT_PATH/$ASAN_RT64" "$TMPDIR/"
301fi
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700302
303# FIXME: alloc_dealloc_mismatch=0 prevents a failure in libdvm startup,
304# which may or may not be a real bug (probably not).
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800305ASAN_OPTIONS=start_deactivated=1,alloc_dealloc_mismatch=0,malloc_context_size=0
306
307function generate_zygote_wrapper { # from, to, asan_rt
308 local _from=$1
309 local _to=$2
310 local _asan_rt=$3
311 cat <<EOF >"$TMPDIR/$_from"
312#!/system/bin/sh-from-zygote
313ASAN_OPTIONS=$ASAN_OPTIONS \\
314ASAN_ACTIVATION_OPTIONS=include_if_exists=/data/local/tmp/asan.options.%b \\
315LD_PRELOAD=\$LD_PRELOAD:$_asan_rt \\
316exec $_to \$@
317
318EOF
319}
Stephen Hines6d186232014-11-26 17:56:19 -0800320
321# On Android-L not allowing user segv handler breaks some applications.
Stephen Hines86277eb2015-03-23 12:06:32 -0700322if [[ PRE_L -eq 0 ]]; then
Stephen Hines6d186232014-11-26 17:56:19 -0800323 ASAN_OPTIONS="$ASAN_OPTIONS,allow_user_segv_handler=1"
324fi
325
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700326if [[ x$extra_options != x ]] ; then
327 ASAN_OPTIONS="$ASAN_OPTIONS,$extra_options"
328fi
329
330# Zygote wrapper.
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800331if [[ -f "$TMPDIR/app_process64" ]]; then
332 # A 64-bit device.
333 if [[ ! -f "$TMPDIR/app_process64.real" ]]; then
334 # New installation.
335 mv "$TMPDIR/app_process32" "$TMPDIR/app_process32.real"
336 mv "$TMPDIR/app_process64" "$TMPDIR/app_process64.real"
337 fi
338 generate_zygote_wrapper "app_process32" "/system/bin/app_process32.real" "$ASAN_RT"
339 generate_zygote_wrapper "app_process64" "/system/bin/app_process64.real" "$ASAN_RT64"
340else
341 # A 32-bit device.
342 generate_zygote_wrapper "app_process.wrap" "/system/bin/app_process32" "$ASAN_RT"
343fi
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700344
345# General command-line tool wrapper (use for anything that's not started as
346# zygote).
347cat <<EOF >"$TMPDIR/asanwrapper"
348#!/system/bin/sh
Stephen Hines6d186232014-11-26 17:56:19 -0800349LD_PRELOAD=$ASAN_RT \\
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700350exec \$@
351
352EOF
353
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800354if [[ -n "$ASAN_RT64" ]]; then
355 cat <<EOF >"$TMPDIR/asanwrapper64"
356#!/system/bin/sh
357LD_PRELOAD=$ASAN_RT64 \\
358exec \$@
359
360EOF
361fi
362
363function install { # from, to, chmod, chcon
364 local _from=$1
365 local _to=$2
366 local _mode=$3
367 local _context=$4
368 local _basename="$(basename "$_from")"
369 echo "Installing $_to/$_basename $_mode $_context"
370 adb_push "$_from" "$_to/$_basename"
371 adb_shell chown root.shell "$_to/$_basename"
372 if [[ -n "$_mode" ]]; then
373 adb_shell chmod "$_mode" "$_to/$_basename"
374 fi
375 if [[ -n "$_context" ]]; then
376 adb_shell chcon "$_context" "$_to/$_basename"
377 fi
378}
379
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700380if ! ( cd "$TMPDIRBASE" && diff -qr old/ new/ ) ; then
Stephen Hines6d186232014-11-26 17:56:19 -0800381 # Make SELinux happy by keeping app_process wrapper and the shell
382 # it runs on in zygote domain.
383 ENFORCING=0
Stephen Hines86277eb2015-03-23 12:06:32 -0700384 if adb_shell getenforce | grep Enforcing >/dev/null; then
Stephen Hines6d186232014-11-26 17:56:19 -0800385 # Sometimes shell is not allowed to change file contexts.
386 # Temporarily switch to permissive.
387 ENFORCING=1
Stephen Hines86277eb2015-03-23 12:06:32 -0700388 adb_shell setenforce 0
Stephen Hines6d186232014-11-26 17:56:19 -0800389 fi
390
Stephen Hines6d186232014-11-26 17:56:19 -0800391 if [[ PRE_L -eq 1 ]]; then
392 CTX=u:object_r:system_file:s0
393 else
394 CTX=u:object_r:zygote_exec:s0
395 fi
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800396
397 echo '>> Pushing files to the device'
398
399 if [[ -n "$ASAN_RT64" ]]; then
400 install "$TMPDIR/$ASAN_RT" /system/lib 644
401 install "$TMPDIR/$ASAN_RT64" /system/lib64 644
402 install "$TMPDIR/app_process32" /system/bin 755 $CTX
403 install "$TMPDIR/app_process32.real" /system/bin 755 $CTX
404 install "$TMPDIR/app_process64" /system/bin 755 $CTX
405 install "$TMPDIR/app_process64.real" /system/bin 755 $CTX
406 install "$TMPDIR/asanwrapper" /system/bin 755
407 install "$TMPDIR/asanwrapper64" /system/bin 755
408 else
409 install "$TMPDIR/$ASAN_RT" /system/lib 644
410 install "$TMPDIR/app_process32" /system/bin 755 $CTX
411 install "$TMPDIR/app_process.wrap" /system/bin 755 $CTX
412 install "$TMPDIR/asanwrapper" /system/bin 755 $CTX
413
414 adb_shell rm /system/bin/app_process
415 adb_shell ln -s /system/bin/app_process.wrap /system/bin/app_process
416 fi
417
418 adb_shell cp /system/bin/sh /system/bin/sh-from-zygote
419 adb_shell chcon $CTX /system/bin/sh-from-zygote
Stephen Hines6d186232014-11-26 17:56:19 -0800420
421 if [ $ENFORCING == 1 ]; then
Stephen Hines86277eb2015-03-23 12:06:32 -0700422 adb_shell setenforce 1
Stephen Hines6d186232014-11-26 17:56:19 -0800423 fi
424
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700425 echo '>> Restarting shell (asynchronous)'
Stephen Hines86277eb2015-03-23 12:06:32 -0700426 adb_shell stop
427 adb_shell start
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700428
429 echo '>> Please wait until the device restarts'
430else
431 echo '>> Device is up to date'
432fi
433
434rm -r "$TMPDIRBASE"