1#!/bin/bash -e
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
14HERE="$(cd "$(dirname "$0")" && pwd)"
15
16revert=no
17extra_options=
18device=
19lib=
20
21function usage {
22    echo "usage: $0 [--revert] [--device device-id] [--lib path] [--extra-options options]"
23    echo "  --revert: Uninstall ASan from the device."
24    echo "  --lib: Path to ASan runtime library."
25    echo "  --extra-options: Extra ASAN_OPTIONS."
26    echo "  --device: Install to the given device. Use 'adb devices' to find"
27    echo "            device-id."
28    echo
29    exit 1
30}
31
32while [[ $# > 0 ]]; do
33  case $1 in
34    --revert)
35      revert=yes
36      ;;
37    --extra-options)
38      shift
39      if [[ $# == 0 ]]; then
40        echo "--extra-options requires an argument."
41        exit 1
42      fi
43      extra_options="$1"
44      ;;
45    --lib)
46      shift
47      if [[ $# == 0 ]]; then
48        echo "--lib requires an argument."
49        exit 1
50      fi
51      lib="$1"
52      ;;
53    --device)
54      shift
55      if [[ $# == 0 ]]; then
56        echo "--device requires an argument."
57        exit 1
58      fi
59      device="$1"
60      ;;
61    *)
62      usage
63      ;;
64  esac
65  shift
66done
67
68ADB=${ADB:-adb}
69if [[ x$device != x ]]; then
70    ADB="$ADB -s $device"
71fi
72
73ASAN_RT="libclang_rt.asan-arm-android.so"
74
75if [[ x$revert == xyes ]]; then
76    echo '>> Uninstalling ASan'
77    $ADB root
78    $ADB wait-for-device
79    $ADB remount
80    $ADB shell mv /system/bin/app_process.real /system/bin/app_process
81    $ADB shell rm /system/bin/asanwrapper
82    $ADB shell rm /system/lib/$ASAN_RT
83
84    echo '>> Restarting shell'
85    $ADB shell stop
86    $ADB shell start
87
88    echo '>> Done'
89    exit 0
90fi
91
92if [[ -d "$lib" ]]; then
93    ASAN_RT_PATH="$lib"
94elif [[ -f "$lib" && "$lib" == *"$ASAN_RT" ]]; then
95    ASAN_RT_PATH=$(dirname "$lib")
96elif [[ -f "$HERE/$ASAN_RT" ]]; then
97    ASAN_RT_PATH="$HERE"
98elif [[ $(basename "$HERE") == "bin" ]]; then
99    # We could be in the toolchain's base directory.
100    # Consider ../lib, ../lib/asan and ../lib/clang/$VERSION/lib/linux.
101    P=$(ls "$HERE"/../lib/"$ASAN_RT" "$HERE"/../lib/asan/"$ASAN_RT" "$HERE"/../lib/clang/*/lib/linux/"$ASAN_RT" 2>/dev/null | sort | tail -1)
102    if [[ -n "$P" ]]; then
103        ASAN_RT_PATH="$(dirname "$P")"
104    fi
105fi
106
107if [[ -z "$ASAN_RT_PATH" || ! -f "$ASAN_RT_PATH/$ASAN_RT" ]]; then
108    echo "ASan runtime library not found"
109    exit 1
110fi
111
112TMPDIRBASE=$(mktemp -d)
113TMPDIROLD="$TMPDIRBASE/old"
114TMPDIR="$TMPDIRBASE/new"
115mkdir "$TMPDIROLD"
116
117echo '>> Remounting /system rw'
118$ADB root
119$ADB wait-for-device
120$ADB remount
121
122echo '>> Copying files from the device'
123$ADB pull /system/bin/app_process "$TMPDIROLD"
124$ADB pull /system/bin/app_process.real "$TMPDIROLD" || true
125$ADB pull /system/bin/asanwrapper "$TMPDIROLD" || true
126$ADB pull /system/lib/libclang_rt.asan-arm-android.so "$TMPDIROLD" || true
127cp -r "$TMPDIROLD" "$TMPDIR"
128
129if ! [[ -f "$TMPDIR/app_process" ]]; then
130    echo "app_process missing???"
131    exit 1
132fi
133
134if [[ -f "$TMPDIR/app_process.real" ]]; then
135    echo "app_process.real exists, updating the wrapper"
136else
137    echo "app_process.real missing, new installation"
138    mv "$TMPDIR/app_process" "$TMPDIR/app_process.real"
139fi
140
141echo '>> Generating wrappers'
142
143cp "$ASAN_RT_PATH/$ASAN_RT" "$TMPDIR/"
144
145# FIXME: alloc_dealloc_mismatch=0 prevents a failure in libdvm startup,
146# which may or may not be a real bug (probably not).
147ASAN_OPTIONS=start_deactivated=1,alloc_dealloc_mismatch=0
148if [[ x$extra_options != x ]] ; then
149    ASAN_OPTIONS="$ASAN_OPTIONS,$extra_options"
150fi
151
152# Zygote wrapper.
153cat <<EOF >"$TMPDIR/app_process"
154#!/system/bin/sh
155ASAN_OPTIONS=$ASAN_OPTIONS \\
156LD_PRELOAD=libclang_rt.asan-arm-android.so \\
157exec /system/bin/app_process.real \$@
158
159EOF
160
161# General command-line tool wrapper (use for anything that's not started as
162# zygote).
163cat <<EOF >"$TMPDIR/asanwrapper"
164#!/system/bin/sh
165LD_PRELOAD=libclang_rt.asan-arm-android.so \\
166exec \$@
167
168EOF
169
170if ! ( cd "$TMPDIRBASE" && diff -qr old/ new/ ) ; then
171    echo '>> Pushing files to the device'
172    $ADB push "$TMPDIR/$ASAN_RT" /system/lib/
173    $ADB push "$TMPDIR/app_process" /system/bin/app_process
174    $ADB push "$TMPDIR/app_process.real" /system/bin/app_process.real
175    $ADB push "$TMPDIR/asanwrapper" /system/bin/asanwrapper
176    $ADB shell chown root.shell \
177        /system/bin/app_process \
178        /system/bin/app_process.real \
179        /system/bin/asanwrapper
180    $ADB shell chmod 755 \
181        /system/bin/app_process \
182        /system/bin/app_process.real \
183        /system/bin/asanwrapper
184
185    echo '>> Restarting shell (asynchronous)'
186    $ADB shell stop
187    $ADB shell start
188
189    echo '>> Please wait until the device restarts'
190else
191    echo '>> Device is up to date'
192fi
193
194rm -r "$TMPDIRBASE"
195