12d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#!/bin/bash -e
22d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#===- lib/asan/scripts/asan_device_setup -----------------------------------===#
32d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#
42d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#                     The LLVM Compiler Infrastructure
52d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#
62d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# This file is distributed under the University of Illinois Open Source
72d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# License. See LICENSE.TXT for details.
82d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#
92d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# Prepare Android device to run ASan applications.
102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#
112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#===------------------------------------------------------------------------===#
122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesHERE="$(cd "$(dirname "$0")" && pwd)"
152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesrevert=no
172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesextra_options=
182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesdevice=
192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hineslib=
202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesfunction usage {
222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo "usage: $0 [--revert] [--device device-id] [--lib path] [--extra-options options]"
232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo "  --revert: Uninstall ASan from the device."
242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo "  --lib: Path to ASan runtime library."
252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo "  --extra-options: Extra ASAN_OPTIONS."
262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo "  --device: Install to the given device. Use 'adb devices' to find"
272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo "            device-id."
282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo
292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    exit 1
302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hineswhile [[ $# > 0 ]]; do
332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  case $1 in
342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    --revert)
352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      revert=yes
362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      ;;
372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    --extra-options)
382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      shift
392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      if [[ $# == 0 ]]; then
402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        echo "--extra-options requires an argument."
412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        exit 1
422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      fi
432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      extra_options="$1"
442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      ;;
452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    --lib)
462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      shift
472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      if [[ $# == 0 ]]; then
482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        echo "--lib requires an argument."
492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        exit 1
502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      fi
512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      lib="$1"
522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      ;;
532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    --device)
542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      shift
552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      if [[ $# == 0 ]]; then
562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        echo "--device requires an argument."
572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        exit 1
582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      fi
592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      device="$1"
602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      ;;
612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    *)
622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      usage
632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      ;;
642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  esac
652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  shift
662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesdone
672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesADB=${ADB:-adb}
692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesif [[ x$device != x ]]; then
702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    ADB="$ADB -s $device"
712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesfi
722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesASAN_RT="libclang_rt.asan-arm-android.so"
742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesif [[ x$revert == xyes ]]; then
762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo '>> Uninstalling ASan'
772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    $ADB root
782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    $ADB wait-for-device
792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    $ADB remount
802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    $ADB shell mv /system/bin/app_process.real /system/bin/app_process
812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    $ADB shell rm /system/bin/asanwrapper
822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    $ADB shell rm /system/lib/$ASAN_RT
832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo '>> Restarting shell'
852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    $ADB shell stop
862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    $ADB shell start
872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo '>> Done'
892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    exit 0
902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesfi
912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesif [[ -d "$lib" ]]; then
932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    ASAN_RT_PATH="$lib"
942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hineselif [[ -f "$lib" && "$lib" == *"$ASAN_RT" ]]; then
952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    ASAN_RT_PATH=$(dirname "$lib")
962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hineselif [[ -f "$HERE/$ASAN_RT" ]]; then
972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    ASAN_RT_PATH="$HERE"
982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hineselif [[ $(basename "$HERE") == "bin" ]]; then
992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    # We could be in the toolchain's base directory.
1005d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    # Consider ../lib, ../lib/asan and ../lib/clang/$VERSION/lib/linux.
1015d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    P=$(ls "$HERE"/../lib/"$ASAN_RT" "$HERE"/../lib/asan/"$ASAN_RT" "$HERE"/../lib/clang/*/lib/linux/"$ASAN_RT" 2>/dev/null | sort | tail -1)
1022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if [[ -n "$P" ]]; then
1032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        ASAN_RT_PATH="$(dirname "$P")"
1042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    fi
1052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesfi
1062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesif [[ -z "$ASAN_RT_PATH" || ! -f "$ASAN_RT_PATH/$ASAN_RT" ]]; then
1082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo "ASan runtime library not found"
1092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    exit 1
1102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesfi
1112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesTMPDIRBASE=$(mktemp -d)
1132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesTMPDIROLD="$TMPDIRBASE/old"
1142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesTMPDIR="$TMPDIRBASE/new"
1152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesmkdir "$TMPDIROLD"
1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesecho '>> Remounting /system rw'
1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines$ADB root
1192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines$ADB wait-for-device
1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines$ADB remount
1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesecho '>> Copying files from the device'
1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines$ADB pull /system/bin/app_process "$TMPDIROLD"
1242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines$ADB pull /system/bin/app_process.real "$TMPDIROLD" || true
1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines$ADB pull /system/bin/asanwrapper "$TMPDIROLD" || true
1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines$ADB pull /system/lib/libclang_rt.asan-arm-android.so "$TMPDIROLD" || true
1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinescp -r "$TMPDIROLD" "$TMPDIR"
1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesif ! [[ -f "$TMPDIR/app_process" ]]; then
1302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo "app_process missing???"
1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    exit 1
1322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesfi
1332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesif [[ -f "$TMPDIR/app_process.real" ]]; then
1352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo "app_process.real exists, updating the wrapper"
1362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hineselse
1372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo "app_process.real missing, new installation"
1382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    mv "$TMPDIR/app_process" "$TMPDIR/app_process.real"
1392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesfi
1402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesecho '>> Generating wrappers'
1422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinescp "$ASAN_RT_PATH/$ASAN_RT" "$TMPDIR/"
1442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# FIXME: alloc_dealloc_mismatch=0 prevents a failure in libdvm startup,
1462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# which may or may not be a real bug (probably not).
1472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesASAN_OPTIONS=start_deactivated=1,alloc_dealloc_mismatch=0
1482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesif [[ x$extra_options != x ]] ; then
1492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    ASAN_OPTIONS="$ASAN_OPTIONS,$extra_options"
1502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesfi
1512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# Zygote wrapper.
1532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinescat <<EOF >"$TMPDIR/app_process"
1542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#!/system/bin/sh
1552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesASAN_OPTIONS=$ASAN_OPTIONS \\
1562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesLD_PRELOAD=libclang_rt.asan-arm-android.so \\
1572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesexec /system/bin/app_process.real \$@
1582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesEOF
1602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# General command-line tool wrapper (use for anything that's not started as
1622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# zygote).
1632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinescat <<EOF >"$TMPDIR/asanwrapper"
1642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#!/system/bin/sh
1652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesLD_PRELOAD=libclang_rt.asan-arm-android.so \\
1662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesexec \$@
1672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesEOF
1692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesif ! ( cd "$TMPDIRBASE" && diff -qr old/ new/ ) ; then
1712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo '>> Pushing files to the device'
1722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    $ADB push "$TMPDIR/$ASAN_RT" /system/lib/
1732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    $ADB push "$TMPDIR/app_process" /system/bin/app_process
1742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    $ADB push "$TMPDIR/app_process.real" /system/bin/app_process.real
1752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    $ADB push "$TMPDIR/asanwrapper" /system/bin/asanwrapper
1762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    $ADB shell chown root.shell \
1772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        /system/bin/app_process \
1782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        /system/bin/app_process.real \
1792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        /system/bin/asanwrapper
1802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    $ADB shell chmod 755 \
1812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        /system/bin/app_process \
1822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        /system/bin/app_process.real \
1832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        /system/bin/asanwrapper
1842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo '>> Restarting shell (asynchronous)'
1862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    $ADB shell stop
1872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    $ADB shell start
1882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo '>> Please wait until the device restarts'
1902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hineselse
1912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    echo '>> Device is up to date'
1922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesfi
1932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesrm -r "$TMPDIRBASE"
195