#!/bin/bash -e #===- 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. # #===------------------------------------------------------------------------===# 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 } 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 ASAN_RT="libclang_rt.asan-arm-android.so" if [[ x$revert == xyes ]]; then echo '>> Uninstalling ASan' $ADB root $ADB wait-for-device $ADB remount $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 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 and ../lib/clang/$VERSION/lib/linux. P=$(ls "$HERE"/../lib/"$ASAN_RT" "$HERE"/../lib/asan/"$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" echo '>> Remounting /system rw' $ADB root $ADB wait-for-device $ADB remount echo '>> Copying files from the device' $ADB pull /system/bin/app_process "$TMPDIROLD" $ADB pull /system/bin/app_process.real "$TMPDIROLD" || true $ADB pull /system/bin/asanwrapper "$TMPDIROLD" || true $ADB pull /system/lib/libclang_rt.asan-arm-android.so "$TMPDIROLD" || true cp -r "$TMPDIROLD" "$TMPDIR" if ! [[ -f "$TMPDIR/app_process" ]]; then echo "app_process missing???" exit 1 fi if [[ -f "$TMPDIR/app_process.real" ]]; then echo "app_process.real exists, updating the wrapper" else echo "app_process.real missing, new installation" mv "$TMPDIR/app_process" "$TMPDIR/app_process.real" 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 if [[ x$extra_options != x ]] ; then ASAN_OPTIONS="$ASAN_OPTIONS,$extra_options" fi # Zygote wrapper. cat <<EOF >"$TMPDIR/app_process" #!/system/bin/sh ASAN_OPTIONS=$ASAN_OPTIONS \\ LD_PRELOAD=libclang_rt.asan-arm-android.so \\ exec /system/bin/app_process.real \$@ EOF # General command-line tool wrapper (use for anything that's not started as # zygote). cat <<EOF >"$TMPDIR/asanwrapper" #!/system/bin/sh LD_PRELOAD=libclang_rt.asan-arm-android.so \\ 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" /system/bin/app_process $ADB push "$TMPDIR/app_process.real" /system/bin/app_process.real $ADB push "$TMPDIR/asanwrapper" /system/bin/asanwrapper $ADB shell chown root.shell \ /system/bin/app_process \ /system/bin/app_process.real \ /system/bin/asanwrapper $ADB shell chmod 755 \ /system/bin/app_process \ /system/bin/app_process.real \ /system/bin/asanwrapper 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"