| 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"
 | 
| 
 |