#!/bin/bash # # Copyright 2016 Google Inc. All Rights Reserved. # # This is an example script to show users the steps for bisecting an NDK # application for Android. Our example is the Teapot app that comes bundled with # the NDK as a sample app. # # Our Teapot app only has 12 or so object files generated per build. Bisection # for just 12 object files is overkill, but this bisection process easily scales # to thousands of object files (as seen with the Android source). # # Setup: # 1. Install NDK (make sure it is in your PATH) # 2. Install compiler_wrapper.py # 3. Connect an arm7 device (tested with Nexus 5X) # a. See README for supporting other device archs # # Tested in bash on Linux. # Set CWD to where this script lives pushd "$(dirname "$0")" # If Teapot dir already exists remove it. if [[ -d Teapot ]]; then rm -rf Teapot fi # Unzip our repository we'll be testing with. tar -xzf Teapot.tar.gz # Apply small setup patch. This patch makes a small change to the build system # to make this bisecting example a little easier. It inserts the option to only # build for an arm7. See the patch file for details. # (This patch file was generated with git, -p1 will remove the a/ and b/) patch -p1 -i PATCH1 # We want all of our cached files to be stored in ~/NDK_EXAMPLE_BISECT # Remove directory if already exists export BISECT_DIR=~/NDK_EXAMPLE_BISECT if [[ -d ${BISECT_DIR} ]]; then rm -rf ${BISECT_DIR} fi # We will now take our normal "good compiler" and do a full build of the app. We # need to clean before building. This ensures that all objects are generated and # can be cached. pushd Teapot export BISECT_STAGE=POPULATE_GOOD ./gradlew clean ./gradlew installArm7Debug popd # Inserting "compiler error". Really this is just a patch that inserts a simple # error in the code, but this is used to simulate our compiler error. This patch # will simply cause the app to crash as soon as it starts. See the patch file # for details. # (This patch file was generated with git, -p1 will remove the a/ and b/) patch -p1 -i PATCH2 # Now that we have installed our bad compiler (i.e. applied the above patch that # acts like a compiler error), we want to enumerate and cache all objects # generated by this "bad compiler". So again, we clean the build tree so that # all objects are regenerated and can be cached. pushd Teapot export BISECT_STAGE=POPULATE_BAD ./gradlew clean ./gradlew installArm7Debug popd # Now ~/NDK_EXAMPLE_BISECT holds the caches for both good and bad compiler # outputs. We will now use these to bisect our problem. We should find that # TeapotRenderer.o is the bad file (because this is where PATCH2 inserted the # "compiler error"). # Tell the compiler wrapper to not cache outputs, and instead begin bisecting. export BISECT_STAGE=TRIAGE # Run the actual bisection tool. This will automatically narrow down which # object file has the error. The test_setup.sh script will rebuild our app # with gradle, and boot_test.sh will ping the device to see if the app crashed # or not. cd .. ./binary_search_state.py \ --get_initial_items=ndk/get_initial_items.sh \ --switch_to_good=ndk/switch_to_good.sh \ --switch_to_bad=ndk/switch_to_bad.sh \ --test_setup_script=ndk/test_setup.sh \ --test_script=ndk/boot_test.sh \ --file_args popd