Index: tools/android/asan/third_party/asan_device_setup.sh |
diff --git a/tools/android/asan/third_party/asan_device_setup.sh b/tools/android/asan/third_party/asan_device_setup.sh |
new file mode 100755 |
index 0000000000000000000000000000000000000000..eb50ea4ed1fce89b6cb37fe35b895ef85a4bac58 |
--- /dev/null |
+++ b/tools/android/asan/third_party/asan_device_setup.sh |
@@ -0,0 +1,267 @@ |
+#!/bin/bash |
+#===- lib/asan/scripts/asan_device_setup -----------------------------------===# |
+# |
+# The LLVM Compiler Infrastructure |
+# |
+# This file is distributed under the University of Illinois Open Source |
+# License. See LICENSE.TXT for details. |
+# |
+# Prepare Android device to run ASan applications. |
+# |
+#===------------------------------------------------------------------------===# |
+ |
+set -e |
+ |
+HERE="$(cd "$(dirname "$0")" && pwd)" |
+ |
+revert=no |
+extra_options= |
+device= |
+lib= |
+ |
+function usage { |
+ echo "usage: $0 [--revert] [--device device-id] [--lib path] [--extra-options options]" |
+ echo " --revert: Uninstall ASan from the device." |
+ echo " --lib: Path to ASan runtime library." |
+ echo " --extra-options: Extra ASAN_OPTIONS." |
+ echo " --device: Install to the given device. Use 'adb devices' to find" |
+ echo " device-id." |
+ echo |
+ exit 1 |
+} |
+ |
+function get_device_arch { # OUTVAR |
+ local _outvar=$1 |
+ local _ABI=$($ADB shell getprop ro.product.cpu.abi) |
+ local _ARCH= |
+ if [[ $_ABI == x86* ]]; then |
+ _ARCH=i686 |
+ elif [[ $_ABI == armeabi* ]]; then |
+ _ARCH=arm |
+ else |
+ echo "Unrecognized device ABI: $_ABI" |
+ exit 1 |
+ fi |
+ eval $_outvar=\$_ARCH |
+} |
+ |
+while [[ $# > 0 ]]; do |
+ case $1 in |
+ --revert) |
+ revert=yes |
+ ;; |
+ --extra-options) |
+ shift |
+ if [[ $# == 0 ]]; then |
+ echo "--extra-options requires an argument." |
+ exit 1 |
+ fi |
+ extra_options="$1" |
+ ;; |
+ --lib) |
+ shift |
+ if [[ $# == 0 ]]; then |
+ echo "--lib requires an argument." |
+ exit 1 |
+ fi |
+ lib="$1" |
+ ;; |
+ --device) |
+ shift |
+ if [[ $# == 0 ]]; then |
+ echo "--device requires an argument." |
+ exit 1 |
+ fi |
+ device="$1" |
+ ;; |
+ *) |
+ usage |
+ ;; |
+ esac |
+ shift |
+done |
+ |
+ADB=${ADB:-adb} |
+if [[ x$device != x ]]; then |
+ ADB="$ADB -s $device" |
+fi |
+ |
+echo '>> Remounting /system rw' |
+$ADB root |
+$ADB wait-for-device |
+$ADB remount |
+$ADB wait-for-device |
+ |
+get_device_arch ARCH |
+echo "Target architecture: $ARCH" |
+ASAN_RT="libclang_rt.asan-$ARCH-android.so" |
+ |
+if [[ x$revert == xyes ]]; then |
+ echo '>> Uninstalling ASan' |
+ |
+ if ! $ADB shell readlink /system/bin/app_process | grep 'app_process' >&/dev/null; then |
+ echo '>> Pre-L device detected.' |
+ $ADB shell mv /system/bin/app_process.real /system/bin/app_process |
+ $ADB shell rm /system/bin/asanwrapper |
+ $ADB shell rm /system/lib/$ASAN_RT |
+ else |
+ $ADB shell rm /system/bin/app_process.wrap |
+ $ADB shell rm /system/bin/asanwrapper |
+ $ADB shell rm /system/lib/$ASAN_RT |
+ $ADB shell rm /system/bin/app_process |
+ $ADB shell ln -s /system/bin/app_process32 /system/bin/app_process |
+ fi |
+ |
+ echo '>> Restarting shell' |
+ $ADB shell stop |
+ $ADB shell start |
+ |
+ echo '>> Done' |
+ exit 0 |
+fi |
+ |
+if [[ -d "$lib" ]]; then |
+ ASAN_RT_PATH="$lib" |
+elif [[ -f "$lib" && "$lib" == *"$ASAN_RT" ]]; then |
+ ASAN_RT_PATH=$(dirname "$lib") |
+elif [[ -f "$HERE/$ASAN_RT" ]]; then |
+ ASAN_RT_PATH="$HERE" |
+elif [[ $(basename "$HERE") == "bin" ]]; then |
+ # We could be in the toolchain's base directory. |
+ # Consider ../lib, ../lib/asan, ../lib/linux and ../lib/clang/$VERSION/lib/linux. |
+ 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) |
+ if [[ -n "$P" ]]; then |
+ ASAN_RT_PATH="$(dirname "$P")" |
+ fi |
+fi |
+ |
+if [[ -z "$ASAN_RT_PATH" || ! -f "$ASAN_RT_PATH/$ASAN_RT" ]]; then |
+ echo ">> ASan runtime library not found" |
+ exit 1 |
+fi |
+ |
+TMPDIRBASE=$(mktemp -d) |
+TMPDIROLD="$TMPDIRBASE/old" |
+TMPDIR="$TMPDIRBASE/new" |
+mkdir "$TMPDIROLD" |
+ |
+RELEASE=$($ADB shell getprop ro.build.version.release) |
+PRE_L=0 |
+if echo "$RELEASE" | grep '^4\.' >&/dev/null; then |
+ PRE_L=1 |
+fi |
+ |
+if ! $ADB shell readlink /system/bin/app_process | grep 'app_process' >&/dev/null; then |
+ |
+ if $ADB pull /system/bin/app_process.real /dev/null >&/dev/null; then |
+ echo '>> Old-style ASan installation detected. Reverting.' |
+ $ADB shell mv /system/bin/app_process.real /system/bin/app_process |
+ fi |
+ |
+ echo '>> Pre-L device detected. Setting up app_process symlink.' |
+ $ADB shell mv /system/bin/app_process /system/bin/app_process32 |
+ $ADB shell ln -s /system/bin/app_process32 /system/bin/app_process |
+fi |
+ |
+echo '>> Copying files from the device' |
+$ADB pull /system/bin/app_process.wrap "$TMPDIROLD" || true |
+$ADB pull /system/bin/asanwrapper "$TMPDIROLD" || true |
+$ADB pull /system/lib/"$ASAN_RT" "$TMPDIROLD" || true |
+cp -r "$TMPDIROLD" "$TMPDIR" |
+ |
+if [[ -f "$TMPDIR/app_process.wrap" ]]; then |
+ echo ">> Previous installation detected" |
+else |
+ echo ">> New installation" |
+fi |
+ |
+echo '>> Generating wrappers' |
+ |
+cp "$ASAN_RT_PATH/$ASAN_RT" "$TMPDIR/" |
+ |
+# FIXME: alloc_dealloc_mismatch=0 prevents a failure in libdvm startup, |
+# which may or may not be a real bug (probably not). |
+ASAN_OPTIONS=start_deactivated=1,alloc_dealloc_mismatch=0 |
+ |
+# On Android-L not allowing user segv handler breaks some applications. |
+if [[ PRE_L -eq 0 ]]; then |
+ ASAN_OPTIONS="$ASAN_OPTIONS,allow_user_segv_handler=1" |
+fi |
+ |
+if [[ x$extra_options != x ]] ; then |
+ ASAN_OPTIONS="$ASAN_OPTIONS,$extra_options" |
+fi |
+ |
+# Zygote wrapper. |
+cat <<EOF >"$TMPDIR/app_process.wrap" |
+#!/system/bin/sh-from-zygote |
+ASAN_OPTIONS=$ASAN_OPTIONS \\ |
+LD_PRELOAD=\$LD_PRELOAD:$ASAN_RT \\ |
+exec /system/bin/app_process32 \$@ |
+ |
+EOF |
+ |
+# General command-line tool wrapper (use for anything that's not started as |
+# zygote). |
+cat <<EOF >"$TMPDIR/asanwrapper" |
+#!/system/bin/sh |
+LD_PRELOAD=$ASAN_RT \\ |
+exec \$@ |
+ |
+EOF |
+ |
+if ! ( cd "$TMPDIRBASE" && diff -qr old/ new/ ) ; then |
+ echo '>> Pushing files to the device' |
+ $ADB push "$TMPDIR/$ASAN_RT" /system/lib/ |
+ $ADB push "$TMPDIR/app_process.wrap" /system/bin/app_process.wrap |
+ $ADB push "$TMPDIR/asanwrapper" /system/bin/asanwrapper |
+ |
+ $ADB shell rm /system/bin/app_process |
+ $ADB shell ln -s /system/bin/app_process.wrap /system/bin/app_process |
+ |
+ $ADB shell chown root.shell \ |
+ /system/lib/"$ASAN_RT" \ |
+ /system/bin/app_process.wrap \ |
+ /system/bin/asanwrapper |
+ $ADB shell chmod 644 \ |
+ /system/lib/"$ASAN_RT" |
+ $ADB shell chmod 755 \ |
+ /system/bin/app_process.wrap \ |
+ /system/bin/asanwrapper |
+ |
+ # Make SELinux happy by keeping app_process wrapper and the shell |
+ # it runs on in zygote domain. |
+ ENFORCING=0 |
+ if $ADB shell getenforce | grep Enforcing >/dev/null; then |
+ # Sometimes shell is not allowed to change file contexts. |
+ # Temporarily switch to permissive. |
+ ENFORCING=1 |
+ $ADB shell setenforce 0 |
+ fi |
+ |
+ $ADB shell cp /system/bin/sh /system/bin/sh-from-zygote |
+ |
+ if [[ PRE_L -eq 1 ]]; then |
+ CTX=u:object_r:system_file:s0 |
+ else |
+ CTX=u:object_r:zygote_exec:s0 |
+ fi |
+ $ADB shell chcon $CTX \ |
+ /system/bin/sh-from-zygote \ |
+ /system/bin/app_process.wrap \ |
+ /system/bin/app_process32 |
+ |
+ if [ $ENFORCING == 1 ]; then |
+ $ADB shell setenforce 1 |
+ fi |
+ |
+ echo '>> Restarting shell (asynchronous)' |
+ $ADB shell stop |
+ $ADB shell start |
+ |
+ echo '>> Please wait until the device restarts' |
+else |
+ echo '>> Device is up to date' |
+fi |
+ |
+rm -r "$TMPDIRBASE" |