]> git.proxmox.com Git - rustc.git/blame - src/compiler-rt/lib/asan/scripts/asan_device_setup
Imported Upstream version 1.6.0+dfsg1
[rustc.git] / src / compiler-rt / lib / asan / scripts / asan_device_setup
CommitLineData
92a42be0 1#!/bin/bash
1a4d82fc
JJ
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
92a42be0 13set -e
1a4d82fc
JJ
14
15HERE="$(cd "$(dirname "$0")" && pwd)"
16
17revert=no
18extra_options=
19device=
20lib=
92a42be0 21use_su=0
1a4d82fc
JJ
22
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."
92a42be0
SL
30 echo " --use-su: Use 'su -c' prefix for every adb command instead of using"
31 echo " 'adb root' once."
1a4d82fc
JJ
32 echo
33 exit 1
34}
35
92a42be0
SL
36function 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
91function get_device_arch { # OUT OUT64
92 local _outvar=$1
93 local _outvar64=$2
94 local _ABI=$(adb_shell getprop ro.product.cpu.abi)
95 local _ARCH=
96 local _ARCH64=
97 if [[ $_ABI == x86* ]]; then
98 _ARCH=i686
99 elif [[ $_ABI == armeabi* ]]; then
100 _ARCH=arm
101 elif [[ $_ABI == arm64-v8a* ]]; then
102 _ARCH=arm
103 _ARCH64=aarch64
104 else
105 echo "Unrecognized device ABI: $_ABI"
106 exit 1
107 fi
108 eval $_outvar=\$_ARCH
109 eval $_outvar64=\$_ARCH64
110}
111
1a4d82fc
JJ
112while [[ $# > 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 ;;
92a42be0
SL
141 --use-su)
142 use_su=1
143 ;;
1a4d82fc
JJ
144 *)
145 usage
146 ;;
147 esac
148 shift
149done
150
151ADB=${ADB:-adb}
152if [[ x$device != x ]]; then
153 ADB="$ADB -s $device"
154fi
155
92a42be0
SL
156if [ $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
169echo '>> Remounting /system rw'
170adb_wait_for_device
171adb_root
172adb_wait_for_device
173adb_remount
174adb_wait_for_device
175
176get_device_arch ARCH ARCH64
177echo "Target architecture: $ARCH"
178ASAN_RT="libclang_rt.asan-$ARCH-android.so"
179if [[ -n $ARCH64 ]]; then
180 echo "Target architecture: $ARCH64"
181 ASAN_RT64="libclang_rt.asan-$ARCH64-android.so"
182fi
1a4d82fc
JJ
183
184if [[ x$revert == xyes ]]; then
185 echo '>> Uninstalling ASan'
92a42be0
SL
186
187 if ! adb_shell ls -l /system/bin/app_process | grep -o '\->.*app_process' >&/dev/null; then
188 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
197 else
198 # 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
203 fi
1a4d82fc
JJ
204
205 echo '>> Restarting shell'
92a42be0
SL
206 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
1a4d82fc
JJ
212
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.
92a42be0
SL
225 # Consider ../lib, ../lib/asan, ../lib/linux and ../lib/clang/$VERSION/lib/linux.
226 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)
1a4d82fc
JJ
227 if [[ -n "$P" ]]; then
228 ASAN_RT_PATH="$(dirname "$P")"
229 fi
230fi
231
232if [[ -z "$ASAN_RT_PATH" || ! -f "$ASAN_RT_PATH/$ASAN_RT" ]]; then
92a42be0 233 echo ">> ASan runtime library not found"
1a4d82fc
JJ
234 exit 1
235fi
236
92a42be0
SL
237if [[ -n "$ASAN_RT64" ]]; then
238 if [[ -z "$ASAN_RT_PATH" || ! -f "$ASAN_RT_PATH/$ASAN_RT64" ]]; then
239 echo ">> ASan runtime library not found"
240 exit 1
241 fi
242fi
243
1a4d82fc
JJ
244TMPDIRBASE=$(mktemp -d)
245TMPDIROLD="$TMPDIRBASE/old"
246TMPDIR="$TMPDIRBASE/new"
247mkdir "$TMPDIROLD"
248
92a42be0
SL
249RELEASE=$(adb_shell getprop ro.build.version.release)
250PRE_L=0
251if echo "$RELEASE" | grep '^4\.' >&/dev/null; then
252 PRE_L=1
253fi
1a4d82fc 254
92a42be0 255if ! adb_shell ls -l /system/bin/app_process | grep -o '\->.*app_process' >&/dev/null; then
1a4d82fc 256
92a42be0
SL
257 if adb_pull /system/bin/app_process.real /dev/null >&/dev/null; then
258 echo '>> Old-style ASan installation detected. Reverting.'
259 adb_shell mv /system/bin/app_process.real /system/bin/app_process
260 fi
261
262 echo '>> Pre-L device detected. Setting up app_process symlink.'
263 adb_shell mv /system/bin/app_process /system/bin/app_process32
264 adb_shell ln -s /system/bin/app_process32 /system/bin/app_process
265fi
266
267echo '>> Copying files from the device'
268if [[ -n "$ASAN_RT64" ]]; then
269 adb_pull /system/lib/"$ASAN_RT" "$TMPDIROLD" || true
270 adb_pull /system/lib64/"$ASAN_RT64" "$TMPDIROLD" || true
271 adb_pull /system/bin/app_process32 "$TMPDIROLD" || true
272 adb_pull /system/bin/app_process32.real "$TMPDIROLD" || true
273 adb_pull /system/bin/app_process64 "$TMPDIROLD" || true
274 adb_pull /system/bin/app_process64.real "$TMPDIROLD" || true
275 adb_pull /system/bin/asanwrapper "$TMPDIROLD" || true
276 adb_pull /system/bin/asanwrapper64 "$TMPDIROLD" || true
277else
278 adb_pull /system/lib/"$ASAN_RT" "$TMPDIROLD" || true
279 adb_pull /system/bin/app_process32 "$TMPDIROLD" || true
280 adb_pull /system/bin/app_process.wrap "$TMPDIROLD" || true
281 adb_pull /system/bin/asanwrapper "$TMPDIROLD" || true
1a4d82fc 282fi
92a42be0 283cp -r "$TMPDIROLD" "$TMPDIR"
1a4d82fc 284
92a42be0
SL
285if [[ -f "$TMPDIR/app_process.wrap" || -f "$TMPDIR/app_process64.real" ]]; then
286 echo ">> Previous installation detected"
1a4d82fc 287else
92a42be0 288 echo ">> New installation"
1a4d82fc
JJ
289fi
290
291echo '>> Generating wrappers'
292
293cp "$ASAN_RT_PATH/$ASAN_RT" "$TMPDIR/"
92a42be0
SL
294if [[ -n "$ASAN_RT64" ]]; then
295 cp "$ASAN_RT_PATH/$ASAN_RT64" "$TMPDIR/"
296fi
1a4d82fc
JJ
297
298# FIXME: alloc_dealloc_mismatch=0 prevents a failure in libdvm startup,
299# which may or may not be a real bug (probably not).
92a42be0
SL
300ASAN_OPTIONS=start_deactivated=1,alloc_dealloc_mismatch=0,malloc_context_size=0
301
302function generate_zygote_wrapper { # from, to, asan_rt
303 local _from=$1
304 local _to=$2
305 local _asan_rt=$3
306 cat <<EOF >"$TMPDIR/$_from"
307#!/system/bin/sh-from-zygote
308ASAN_OPTIONS=$ASAN_OPTIONS \\
309ASAN_ACTIVATION_OPTIONS=include_if_exists=/data/local/tmp/asan.options.%b \\
310LD_PRELOAD=\$LD_PRELOAD:$_asan_rt \\
311exec $_to \$@
312
313EOF
314}
315
316# On Android-L not allowing user segv handler breaks some applications.
317if [[ PRE_L -eq 0 ]]; then
318 ASAN_OPTIONS="$ASAN_OPTIONS,allow_user_segv_handler=1"
319fi
320
1a4d82fc
JJ
321if [[ x$extra_options != x ]] ; then
322 ASAN_OPTIONS="$ASAN_OPTIONS,$extra_options"
323fi
324
325# Zygote wrapper.
92a42be0
SL
326if [[ -f "$TMPDIR/app_process64" ]]; then
327 # A 64-bit device.
328 if [[ ! -f "$TMPDIR/app_process64.real" ]]; then
329 # New installation.
330 mv "$TMPDIR/app_process32" "$TMPDIR/app_process32.real"
331 mv "$TMPDIR/app_process64" "$TMPDIR/app_process64.real"
332 fi
333 generate_zygote_wrapper "app_process32" "/system/bin/app_process32.real" "$ASAN_RT"
334 generate_zygote_wrapper "app_process64" "/system/bin/app_process64.real" "$ASAN_RT64"
335else
336 # A 32-bit device.
337 generate_zygote_wrapper "app_process.wrap" "/system/bin/app_process32" "$ASAN_RT"
338fi
1a4d82fc
JJ
339
340# General command-line tool wrapper (use for anything that's not started as
341# zygote).
342cat <<EOF >"$TMPDIR/asanwrapper"
343#!/system/bin/sh
92a42be0
SL
344LD_PRELOAD=$ASAN_RT \\
345exec \$@
346
347EOF
348
349if [[ -n "$ASAN_RT64" ]]; then
350 cat <<EOF >"$TMPDIR/asanwrapper64"
351#!/system/bin/sh
352LD_PRELOAD=$ASAN_RT64 \\
1a4d82fc
JJ
353exec \$@
354
355EOF
92a42be0
SL
356fi
357
358function install { # from, to, chmod, chcon
359 local _from=$1
360 local _to=$2
361 local _mode=$3
362 local _context=$4
363 local _basename="$(basename "$_from")"
364 echo "Installing $_to/$_basename $_mode $_context"
365 adb_push "$_from" "$_to/$_basename"
366 adb_shell chown root.shell "$_to/$_basename"
367 if [[ -n "$_mode" ]]; then
368 adb_shell chmod "$_mode" "$_to/$_basename"
369 fi
370 if [[ -n "$_context" ]]; then
371 adb_shell chcon "$_context" "$_to/$_basename"
372 fi
373}
1a4d82fc
JJ
374
375if ! ( cd "$TMPDIRBASE" && diff -qr old/ new/ ) ; then
92a42be0
SL
376 # Make SELinux happy by keeping app_process wrapper and the shell
377 # it runs on in zygote domain.
378 ENFORCING=0
379 if adb_shell getenforce | grep Enforcing >/dev/null; then
380 # Sometimes shell is not allowed to change file contexts.
381 # Temporarily switch to permissive.
382 ENFORCING=1
383 adb_shell setenforce 0
384 fi
385
386 if [[ PRE_L -eq 1 ]]; then
387 CTX=u:object_r:system_file:s0
388 else
389 CTX=u:object_r:zygote_exec:s0
390 fi
391
1a4d82fc 392 echo '>> Pushing files to the device'
92a42be0
SL
393
394 if [[ -n "$ASAN_RT64" ]]; then
395 install "$TMPDIR/$ASAN_RT" /system/lib 644
396 install "$TMPDIR/$ASAN_RT64" /system/lib64 644
397 install "$TMPDIR/app_process32" /system/bin 755 $CTX
398 install "$TMPDIR/app_process32.real" /system/bin 755 $CTX
399 install "$TMPDIR/app_process64" /system/bin 755 $CTX
400 install "$TMPDIR/app_process64.real" /system/bin 755 $CTX
401 install "$TMPDIR/asanwrapper" /system/bin 755
402 install "$TMPDIR/asanwrapper64" /system/bin 755
403 else
404 install "$TMPDIR/$ASAN_RT" /system/lib 644
405 install "$TMPDIR/app_process32" /system/bin 755 $CTX
406 install "$TMPDIR/app_process.wrap" /system/bin 755 $CTX
407 install "$TMPDIR/asanwrapper" /system/bin 755 $CTX
408
409 adb_shell rm /system/bin/app_process
410 adb_shell ln -s /system/bin/app_process.wrap /system/bin/app_process
411 fi
412
413 adb_shell cp /system/bin/sh /system/bin/sh-from-zygote
414 adb_shell chcon $CTX /system/bin/sh-from-zygote
415
416 if [ $ENFORCING == 1 ]; then
417 adb_shell setenforce 1
418 fi
1a4d82fc
JJ
419
420 echo '>> Restarting shell (asynchronous)'
92a42be0
SL
421 adb_shell stop
422 adb_shell start
1a4d82fc
JJ
423
424 echo '>> Please wait until the device restarts'
425else
426 echo '>> Device is up to date'
427fi
428
429rm -r "$TMPDIRBASE"