diff options
Diffstat (limited to 'binary_search_tool/android')
-rw-r--r-- | binary_search_tool/android/README.android | 186 | ||||
-rwxr-xr-x | binary_search_tool/android/boot_test.sh | 61 | ||||
-rwxr-xr-x | binary_search_tool/android/cleanup.sh | 11 | ||||
-rwxr-xr-x | binary_search_tool/android/get_initial_items.sh | 14 | ||||
-rwxr-xr-x | binary_search_tool/android/interactive_test.sh | 39 | ||||
-rwxr-xr-x | binary_search_tool/android/setup.sh | 147 | ||||
-rwxr-xr-x | binary_search_tool/android/switch_to_bad.sh | 42 | ||||
-rwxr-xr-x | binary_search_tool/android/switch_to_good.sh | 41 | ||||
-rwxr-xr-x | binary_search_tool/android/test_setup.sh | 130 |
9 files changed, 671 insertions, 0 deletions
diff --git a/binary_search_tool/android/README.android b/binary_search_tool/android/README.android new file mode 100644 index 00000000..9e518f60 --- /dev/null +++ b/binary_search_tool/android/README.android @@ -0,0 +1,186 @@ + +binary_search_state.py is a general binary search triage tool that +performs a binary search on a set of things to try to identify which +thing or thing(s) in the set is 'bad'. binary_search_state.py assumes +that the user has two sets, one where everything is known to be good, +and one which contains at least one bad item. binary_search_state.py +then copies items from the good and bad sets into a working set and +tests the result (good or bad). binary_search_state.py requires that +a set of scripts be supplied to it for any particular job. For more +information on binary_search_state.py, see + +https://sites.google.com/a/google.com/chromeos-toolchain-team-home2/home/team-tools-and-scripts/binary-searcher-tool-for-triage + +This particular set of scripts is designed to work wtih +binary_search_state.py in order to find the bad object or set of +bad objects in an Android build. + + +QUICKSTART: + +After setting up your 2 build trees (see Prerequisites section), do the +following: + + - Decide which test script to use (boot_test.sh or + interactive_test.sh) + - Get the serial number for the Android device you will use for testing. + - Run the following: + + $ cd <android_src> + $ source build/envsetup.sh + $ lunch <android_device_lunch_combo> + $ cd <path_to_toolchain_utils>/binary_search_tool/ + $ NUM_JOBS=10 ANDROID_SERIAL=<device_serial> \ + ./android/setup.sh <android_src> + + If you chose the boot test, then: + TEST_SCRIPT=android/boot_test.sh + + If you chose the interactive test, then: + TEST_SCRIPT=android/interactive_test.sh + + Finally, run the binary search tool: + + $ python ./binary_search_state.py \ + --get_initial_items=android/get_initial_items.sh \ + --switch_to_good=android/switch_to_good.sh \ + --switch_to_bad=android/switch_to_bad.sh \ + --test_setup_script=android/test_setup.sh \ + --test_script=$TEST_SCRIPT \ + --file_args \ + --prune + + Once you have completely finished doing the binary search/triage, + run the cleanup script: + + $ android/cleanup.sh + + + +FILES AND SCRIPTS: + + Check the header comments for each script for more in depth documentation. + + boot_test.sh - One of two possible test scripts used to determine + if the Android image built from the objects is good + or bad. This script tests to see if the image + booted, and requires no user intervention. + + cleanup.sh - This is called after the binary search tool completes. This + script will clean up the common.sh file generated by setup.sh + + get_initial_items.sh - This script is used to determine all Android objects + that will be bisected. + + test_setup.sh - This script will build and flash your image to the + Android device. If the flash fails, this script will + help the user troubleshoot by trying to flash again or + by asking the user to manually flash it. + + interactive_test.sh - One of two possible scripts used to determine + if the Android image built from the objects + is good or bad. This script requires user + interaction to determine if the image is + good or bad. + + setup.sh - This is the first script the user should call, after + taking care of the prerequisites. It sets up the + environment appropriately for running the Android + object binary search triage, and it generates the + necessary common script (see below). + + switch_to_bad.sh - This script is used to link objects from the + 'bad' build tree into the work area. + + switch_to_good.sh - This script is used to link objects from the + 'good' build tree into the work area. + + +GENERATED SCRIPTS: + + common.sh - contains basic environment variable definitions for + this binary search triage session. + +ASSUMPTIONS: + +- There are two different Android builds, for the same board/lunch combo with + the same set of generated object files. One build creates a good working + Android image and the other does not. + +- The toolchain bug you are tracking down is not related to the linker. If the + linker is broken or generates bad code, this tool is unlikely to help you. + + +PREREQUISITES FOR USING THESE SCRIPTS: + + Step 1: Decide where to store each build tree + By default, each build tree is stored in "~/ANDROID_BISECT". However you + can override this by exporting BISECT_DIR set to whatever directory you + please. Keep in mind these build trees take dozens of gigabytes each. + + Step 2: Setup your android build environment + 1. `cd <android_src>` + 2. `source build/envsetup.sh` + 3. `lunch <android_device_lunch_combo>` + + Step 3: Populate the good build tree + 1. `make clean` + 2. `export BISECT_STAGE=POPULATE_GOOD` + 3. Install your "good" toolchain in Android, this will most likely be + the toolchain that comes preinstalled with the Android source. + 4. Build all of Android: `make -j10`. The "-j" parameter depends on how + many cores your machine has. See Android documentation for more details. + + Step 4: Populate the bad build tree + 1. `make clean` + 2. `export BISECT_STAGE=POPULATE_BAD` + 3. Install your "bad" toolchain in Android. + 4. Build all of Android again. + + Step 5: Run the android setup script + 1. `cd <path_to_toolchain_utils>/binary_search_tool/` + 2. `NUM_JOBS=<jobs> ANDROID_SERIAL=<android_serial_num> \ + android/setup.sh <android_src>` + + WARNING: It's important that you leave the full "out/" directory in your + Android source alone after Step 4. The binary search tool will + use this directory as a skeleton to build each test image while + triaging. + +USING THESE SCRIPTS FOR BINARY TRIAGE OF OBJECTS: + +To use these scripts, you must first run setup.sh, passing it the path to your +Android source directory. setup.sh will do the following: + + - Verify that your build trees are set up correctly (with good, bad). + - Verify that each build tree has the same contents. + - Verify that the android build environment (lunch, etc.) are setup in your + current shell. + - Create the common.sh file that the other scripts passed to the + binary triage tool will need. + + +This set of scripts comes with two alternate test scripts. One test +script, boot_test.sh, just checks to make sure that the image +booted (wait for device to boot to home screen) and assumes that is enough. +The other test script, interactive_test.sh, is interactive and asks YOU +to tell it whether the image on the android device is ok or not (it +prompts you and waits for a response). + + +Once you have run setup.sh (and decided which test script you +want to use) run the binary triage tool using these scripts to +isolate/identify the bad object: + +./binary_search_state.py \ + --get_initial_items=android/get_initial_items.sh \ + --switch_to_good=android/switch_to_good.sh \ + --switch_to_bad=android/switch_to_bad.sh \ + --test_setup_script=android/test_setup.sh \ + --test_script=android/boot_test.sh \ # could use interactive_test.sh instead + --prune + + +After you have finished running the tool and have identified the bad +object(s), you will want to run the cleanup script (android/cleanup.sh). + diff --git a/binary_search_tool/android/boot_test.sh b/binary_search_tool/android/boot_test.sh new file mode 100755 index 00000000..dc871601 --- /dev/null +++ b/binary_search_tool/android/boot_test.sh @@ -0,0 +1,61 @@ +#!/bin/bash -u +# +# Copyright 2016 Google Inc. All Rights Reserved. +# +# This script pings the android device to determine if it successfully booted. +# +# This script is intended to be used by binary_search_state.py, as +# part of the binary search triage on the Android source tree. It +# waits for the test setup script to build and install the image, then checks +# if image boots or not. It should return '0' if the test succeeds +# (the image is 'good'); '1' if the test fails (the image is 'bad'); and '125' +# if it could not determine (does not apply in this case). +# + +source android/common.sh + +# Check if boot animation has stopped and trim whitespace +is_booted() +{ + # Wait for boot animation to stop and trim whitespace + status=`adb shell getprop init.svc.bootanim | tr -d '[:space:]'` + [[ "$status" == "stopped" ]] + return $? +} + +# Wait for device to boot, retry every 1s +# WARNING: Do not run without timeout command, could run forever +wait_for_boot() +{ + while ! is_booted + do + sleep 1 + done +} + +echo "Waiting 60 seconds for device to come online..." +timeout 60 adb wait-for-device +retval=$? + +if [[ ${retval} -eq 0 ]]; then + echo "Android image has been built and installed." +else + echo "Device failed to reboot within 60 seconds." + exit 1 +fi + +echo "Waiting 60 seconds for device to finish boot..." +# Spawn subshell that will timeout in 60 seconds +# Feed to cat so that timeout will recognize it as a command +# (timeout only works for commands/programs, not functions) +timeout 60 cat <(wait_for_boot) +retval=$? + +if [[ ${retval} -eq 0 ]]; then + echo "Android device fully booted!" +else + echo "Device failed to fully boot within 60 seconds." + exit 1 +fi + +exit ${retval} diff --git a/binary_search_tool/android/cleanup.sh b/binary_search_tool/android/cleanup.sh new file mode 100755 index 00000000..c89c337d --- /dev/null +++ b/binary_search_tool/android/cleanup.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# +# Copyright 2016 Google Inc. All Rights Reserved. +# +# This script is part of the Android binary search triage process. +# It should be the last script called by the user, after the user has +# successfully run the bisection tool and found their bad items. This script +# will perform all necessary cleanup for the bisection tool. +# + +rm android/common.sh diff --git a/binary_search_tool/android/get_initial_items.sh b/binary_search_tool/android/get_initial_items.sh new file mode 100755 index 00000000..2a1eda3a --- /dev/null +++ b/binary_search_tool/android/get_initial_items.sh @@ -0,0 +1,14 @@ +#!/bin/bash -u +# +# Copyright 2016 Google Inc. All Rights Reserved. +# +# This script is intended to be used by binary_search_state.py, as +# part of the binary search triage on the Android source tree. This script +# generates the list of current Android object files, that is then used +# for doing the binary search. +# + +source android/common.sh + +cat ${BISECT_GOOD_BUILD}/_LIST + diff --git a/binary_search_tool/android/interactive_test.sh b/binary_search_tool/android/interactive_test.sh new file mode 100755 index 00000000..e506b236 --- /dev/null +++ b/binary_search_tool/android/interactive_test.sh @@ -0,0 +1,39 @@ +#!/bin/bash -u +# +# Copyright 2016 Google Inc. All Rights Reserved. +# +# This script pings the android device to determine if it successfully booted. +# It then asks the user if the image is good or not, allowing the user to +# conduct whatever tests the user wishes, and waiting for a response. +# +# This script is intended to be used by binary_search_state.py, as +# part of the binary search triage on the Android source tree. It +# waits for the test setup script to build and install the image, then asks the +# user if the image is good or not. It should return '0' if the test succeeds +# (the image is 'good'); '1' if the test fails (the image is 'bad'); and '125' +# if it could not determine (does not apply in this case). +# + +source android/common.sh + +echo "Waiting 60 seconds for device to boot..." +timeout 60 adb wait-for-device +retval=$? + +if [[ ${retval} -eq 0 ]]; then + echo "Android image has been built and installed." +else + echo "Device failed to reboot within 60 seconds." + exit 1 +fi + +while true; do + read -p "Is this a good Android image?" yn + case $yn in + [Yy]* ) exit 0;; + [Nn]* ) exit 1;; + * ) echo "Please answer yes or no.";; + esac +done + +exit 125 diff --git a/binary_search_tool/android/setup.sh b/binary_search_tool/android/setup.sh new file mode 100755 index 00000000..7f8ba0e9 --- /dev/null +++ b/binary_search_tool/android/setup.sh @@ -0,0 +1,147 @@ +#!/bin/bash -u +# +# Copyright 2016 Google Inc. All Rights Reserved. +# +# This script is part of the Android binary search triage process. +# It should be the first script called by the user, after the user has set up +# the two necessary build tree directories (see the prerequisites section of +# README.android). +# +# WARNING: +# Before running this script make sure you have setup the Android build +# environment in this shell (i.e. successfully run 'lunch'). +# +# This script takes three arguments. The first argument must be the path of +# the android source tree being tested. The second (optional) argument is the +# device ID for fastboot/adb so the test device can be uniquely indentified in +# case multiple phones are plugged in. The final (optional) argument is the +# number of jobs that various programs can use for parallelism +# (make, xargs, etc.). There is also the argument for bisection directory, but +# this is not strictly an argument for just this script (as it should be set +# during the POPULATE_GOOD and POPULATE_BAD steps, see README.android for +# details). +# +# Example call: +# ANDROID_SERIAL=002ee16b1558a3d3 NUM_JOBS=10 android/setup.sh ~/android +# +# This will setup the bisector for Nexus5X, using 10 jobs, where the android +# source lives at ~/android. +# +# NOTE: ANDROID_SERIAL is actually an option used by ADB. You can also simply +# do 'export ANDROID_SERIAL=<device_id>' and the bisector will still work. +# Furthermore, if your device is the only Android device plugged in you can +# ignore ANDROID_SERIAL. +# +# This script sets all necessary environment variables, and ensures the +# environment for the binary search triage process is setup properly. In +# addition, this script generates common.sh, which generates enviroment +# variables used by the other scripts in the package binary search triage process. +# + +# +# Positional arguments +# + +ANDROID_SRC=$1 + +# +# Optional arguments +# + +# If DEVICE_ID is not null export this as ANDROID_SERIAL for use by adb +# If DEVICE_ID is null then leave null +DEVICE_ID=${ANDROID_SERIAL:+"export ANDROID_SERIAL=${ANDROID_SERIAL} "} + +NUM_JOBS=${NUM_JOBS:-"1"} +BISECT_ANDROID_DIR=${BISECT_DIR:-~/ANDROID_BISECT} + +# +# Set up basic variables. +# + +GOOD_BUILD=${BISECT_ANDROID_DIR}/good +BAD_BUILD=${BISECT_ANDROID_DIR}/bad +WORK_BUILD=${ANDROID_SRC} + +# +# Verify that the necessary directories exist. +# + +if [[ ! -d ${GOOD_BUILD} ]] ; then + echo "Error: ${GOOD_BUILD} does not exist." + exit 1 +fi + +if [[ ! -d ${BAD_BUILD} ]] ; then + echo "Error: ${BAD_BUILD} does not exist." + exit 1 +fi + +if [[ ! -d ${WORK_BUILD} ]] ; then + echo "Error: ${WORK_BUILD} does not exist." + exit 1 +fi + +# +# Verify that good/bad object lists are the same +# + +good_list=`mktemp` +bad_list=`mktemp` +sort ${GOOD_BUILD}/_LIST > good_list +sort ${BAD_BUILD}/_LIST > bad_list + +diff good_list bad_list +diff_result=$? +rm good_list bad_list + +if [ ${diff_result} -ne 0 ]; then + echo "Error: good and bad object lists differ." + echo "diff exited with non-zero status: ${diff_result}" + exit 1 +fi + +# +# Ensure android build environment is setup +# +# ANDROID_PRODUCT_OUT is only set once lunch is successfully executed. Fail if +# ANDROID_PRODUCT_OUT is unset. +# + +if [ -z ${ANDROID_PRODUCT_OUT+0} ]; then + echo "Error: Android build environment is not setup." + echo "cd to ${ANDROID_SRC} and do the following:" + echo " source build/envsetup.sh" + echo " lunch <device_lunch_combo>" + exit 1 +fi + +# +# Create common.sh file, containing appropriate environment variables. +# + +COMMON_FILE="android/common.sh" + +cat <<-EOF > ${COMMON_FILE} + +BISECT_ANDROID_DIR=${BISECT_ANDROID_DIR} + +BISECT_ANDROID_SRC=${ANDROID_SRC} +BISECT_NUM_JOBS=${NUM_JOBS} + +BISECT_GOOD_BUILD=${GOOD_BUILD} +BISECT_BAD_BUILD=${BAD_BUILD} +BISECT_WORK_BUILD=${WORK_BUILD} + +BISECT_GOOD_SET=${GOOD_BUILD}/_LIST +BISECT_BAD_SET=${BAD_BUILD}/_LIST + +${DEVICE_ID} + +export BISECT_STAGE="TRIAGE" + +EOF + +chmod 755 ${COMMON_FILE} + +exit 0 diff --git a/binary_search_tool/android/switch_to_bad.sh b/binary_search_tool/android/switch_to_bad.sh new file mode 100755 index 00000000..f746b628 --- /dev/null +++ b/binary_search_tool/android/switch_to_bad.sh @@ -0,0 +1,42 @@ +#!/bin/bash -u +# +# Copyright 2016 Google Inc. All Rights Reserved. +# +# This script is intended to be used by binary_search_state.py, as +# part of the binary search triage on the Android source tree. This script +# symlinks a list of object files from the 'bad' build tree into the working +# build tree, for testing. +# +# It is highly recommended to not use --noincremental with these scripts. If the +# switch scripts are given non incremental sets of GOOD/BAD objects, make will +# not be able to do an incremental build and will take much longer to build. +# + + +source android/common.sh + +OBJ_LIST_FILE=$1 + +# Symlink from BAD obj to working tree. +SWITCH_CMD="ln -f ${BISECT_BAD_BUILD}/{} {}; touch {};" + +overall_status=0 + +# Check that number of arguments == 1 +if [ $# -eq 1 ] ; then + # Run symlink once per input line, ignore empty lines. + # Have ${BISECT_NUM_JOBS} processes running concurrently. + # Pass to "sh" to allow multiple commands to be executed. + xargs -P ${BISECT_NUM_JOBS} -a ${OBJ_LIST_FILE} -r -l -I '{}' \ + sh -c "${SWITCH_CMD}" +else + echo "ERROR:" + echo "Please run the binary search tool with --file_args" + echo "Android has too many files to be passed as command line arguments" + echo "The binary search tool will now exit..." + exit 1 +fi +overall_status=$? + + +exit ${overall_status} diff --git a/binary_search_tool/android/switch_to_good.sh b/binary_search_tool/android/switch_to_good.sh new file mode 100755 index 00000000..1c046c3f --- /dev/null +++ b/binary_search_tool/android/switch_to_good.sh @@ -0,0 +1,41 @@ +#!/bin/bash -u +# +# Copyright 2016 Google Inc. All Rights Reserved. +# +# This script is intended to be used by binary_search_state.py, as +# part of the binary search triage on the Android source tree. This script +# symlinks a list of object files from the 'good' build tree into the working +# build tree, for testing. +# +# It is highly recommended to not use --noincremental with these scripts. If the +# switch scripts are given non incremental sets of GOOD/BAD objects, make will +# not be able to do an incremental build and will take much longer to build. +# + +source android/common.sh + +OBJ_LIST_FILE=$1 + +# Symlink from GOOD obj to working tree. +SWITCH_CMD="ln -f ${BISECT_GOOD_BUILD}/{} {}; touch {};" + +overall_status=0 + +# Check that number of arguments == 1 +if [ $# -eq 1 ] ; then + # Run symlink once per input line, ignore empty lines. + # Have ${BISECT_NUM_JOBS} processes running concurrently. + # Pass to "sh" to allow multiple commands to be executed. + xargs -P ${BISECT_NUM_JOBS} -a ${OBJ_LIST_FILE} -r -l -I '{}' \ + sh -c "${SWITCH_CMD}" +else + echo "ERROR:" + echo "Please run the binary search tool with --file_args" + echo "Android has too many files to be passed as command line arguments" + echo "The binary search tool will now exit..." + exit 1 +fi +overall_status=$? + + +exit ${overall_status} diff --git a/binary_search_tool/android/test_setup.sh b/binary_search_tool/android/test_setup.sh new file mode 100755 index 00000000..26f8ec22 --- /dev/null +++ b/binary_search_tool/android/test_setup.sh @@ -0,0 +1,130 @@ +#!/bin/bash +# +# Copyright 2016 Google Inc. All Rights Reserved. +# +# This is the test setup script for generating an Android image based off the +# current working build tree. make is called to relink the object files and +# generate the new Android image to be flashed. The device is then rebooted into +# bootloader mode and fastboot is used to flash the new image. The device is +# then rebooted so the user's test script can run. +# +# This script is intended to be used by binary_search_state.py, as +# part of the binary search triage on the Android source tree. It should +# return '0' if the setup succeeds; and '1' if the setup fails (the image +# could not build or be flashed). +# + +source android/common.sh + +manual_flash() +{ + echo + echo "Please manually flash the built image to your device." + echo "To do so follow these steps:" + echo " 1. Boot your device into fastboot mode." + echo " 2. cd to '${BISECT_ANDROID_SRC}'" + echo " 2. Run 'source build/envsetup.sh'" + echo " 3. Run 'lunch'" + echo " 4. Run '${ADB_DEVICE}fastboot flashall -w'" + echo "Or see the following link for more in depth steps:" + echo "https://source.android.com/source/running.html" + echo + while true; do + sleep 1 + read -p "Was the flashing of the image successful? " choice + case $choice in + [Yy]*) return 0;; + [Nn]*) return 1;; + *) echo "Please answer y or n.";; + esac + done +} + +auto_flash() +{ + echo + echo "Please ensure your Android device is on and in fastboot mode so" + echo "fastboot flash may run." + echo + sleep 1 + read -p $'Press enter to continue and retry the flashing' notused + + echo " ${ADB_DEVICE}fastboot flashall -w" + fastboot flashall -w +} + +flash() +{ + echo + echo "FLASHING" + echo "Rebooting device into fastboot mode." + echo " ${ADB_DEVICE}adb reboot bootloader" + adb reboot bootloader + + echo + echo "Waiting for device to reach fastboot mode." + echo "(will timeout after 60 seconds)" + # fastboot will block indefinitely until device comes online. + # Grab random variable to test if device is online. + # If takes >60s then we error out and ask the user for help. + timeout 60 fastboot getvar 0 2>/dev/null + fastboot_flash_status=$? + + if [[ ${fastboot_flash_status} -eq 0 ]]; then + echo + echo "Flashing image." + echo " ${ADB_DEVICE}fastboot flashall -w" + fastboot flashall -w + fastboot_flash_status=$? + fi + + while [[ ${fastboot_flash_status} -ne 0 ]] ; do + echo + echo "fastboot flash has failed! From here you can:" + echo "1. Debug and/or flash manually" + echo "2. Retry flashing automatically" + echo "3. Abort this installation and skip this image" + echo "4. Abort this installation and mark test as failed" + sleep 1 + read -p "Which method would you like to do? " choice + case $choice in + 1) manual_flash && break;; + 2) auto_flash && break;; + 3) return 125;; + 4) return 1;; + *) echo "Please answer 1, 2, 3, or 4.";; + esac + done +} + +# Number of jobs make will use. Can be customized and played with. +MAKE_JOBS=${BISECT_NUM_JOBS} + +# Set ADB_DEVICE to "ANDROID_SERIAL=${ANDROID_SERIAL}" or "" if device id not +# set. This is used for debugging info so users can confirm which device +# commands are being sent to. +ADB_DEVICE=${ANDROID_SERIAL:+"ANDROID_SERIAL=${ANDROID_SERIAL} "} + +echo +echo "INSTALLATION BEGIN" +echo + +cd ${BISECT_ANDROID_SRC} + +echo "BUILDING IMAGE" + +make -j ${MAKE_JOBS} +make_status=$? + +exit_val=0 +if [[ ${make_status} -eq 0 ]]; then + flash + exit_val=$? +else + echo "ERROR:" + echo "make returned a non-zero status: ${make_status}. Skipping image..." + exit_val=1 +fi + + +exit ${exit_val} |