1 #!/bin/bash 2 # 3 # Copyright 2016 Google Inc. All Rights Reserved. 4 # 5 # This is an example script to show users the steps for bisecting an NDK 6 # application for Android. Our example is the Teapot app that comes bundled with 7 # the NDK as a sample app. 8 # 9 # Our Teapot app only has 12 or so object files generated per build. Bisection 10 # for just 12 object files is overkill, but this bisection process easily scales 11 # to thousands of object files (as seen with the Android source). 12 # 13 # Setup: 14 # 1. Install NDK (make sure it is in your PATH) 15 # 2. Install compiler_wrapper.py 16 # 3. Connect an arm7 device (tested with Nexus 5X) 17 # a. See README for supporting other device archs 18 # 19 # Tested in bash on Linux. 20 21 # Set CWD to where this script lives 22 pushd "$(dirname "$0")" 23 24 # If Teapot dir already exists remove it. 25 if [[ -d Teapot ]]; then 26 rm -rf Teapot 27 fi 28 29 # Unzip our repository we'll be testing with. 30 tar -xzf Teapot.tar.gz 31 32 # Apply small setup patch. This patch makes a small change to the build system 33 # to make this bisecting example a little easier. It inserts the option to only 34 # build for an arm7. See the patch file for details. 35 # (This patch file was generated with git, -p1 will remove the a/ and b/) 36 patch -p1 -i PATCH1 37 38 # We want all of our cached files to be stored in ~/NDK_EXAMPLE_BISECT 39 # Remove directory if already exists 40 export BISECT_DIR=~/NDK_EXAMPLE_BISECT 41 if [[ -d ${BISECT_DIR} ]]; then 42 rm -rf ${BISECT_DIR} 43 fi 44 45 # We will now take our normal "good compiler" and do a full build of the app. We 46 # need to clean before building. This ensures that all objects are generated and 47 # can be cached. 48 pushd Teapot 49 export BISECT_STAGE=POPULATE_GOOD 50 ./gradlew clean 51 ./gradlew installArm7Debug 52 popd 53 54 # Inserting "compiler error". Really this is just a patch that inserts a simple 55 # error in the code, but this is used to simulate our compiler error. This patch 56 # will simply cause the app to crash as soon as it starts. See the patch file 57 # for details. 58 # (This patch file was generated with git, -p1 will remove the a/ and b/) 59 patch -p1 -i PATCH2 60 61 # Now that we have installed our bad compiler (i.e. applied the above patch that 62 # acts like a compiler error), we want to enumerate and cache all objects 63 # generated by this "bad compiler". So again, we clean the build tree so that 64 # all objects are regenerated and can be cached. 65 pushd Teapot 66 export BISECT_STAGE=POPULATE_BAD 67 ./gradlew clean 68 ./gradlew installArm7Debug 69 popd 70 71 # Now ~/NDK_EXAMPLE_BISECT holds the caches for both good and bad compiler 72 # outputs. We will now use these to bisect our problem. We should find that 73 # TeapotRenderer.o is the bad file (because this is where PATCH2 inserted the 74 # "compiler error"). 75 76 # Tell the compiler wrapper to not cache outputs, and instead begin bisecting. 77 export BISECT_STAGE=TRIAGE 78 79 # Run the actual bisection tool. This will automatically narrow down which 80 # object file has the error. The test_setup.sh script will rebuild our app 81 # with gradle, and boot_test.sh will ping the device to see if the app crashed 82 # or not. 83 cd .. 84 ./binary_search_state.py \ 85 --get_initial_items=ndk/get_initial_items.sh \ 86 --switch_to_good=ndk/switch_to_good.sh \ 87 --switch_to_bad=ndk/switch_to_bad.sh \ 88 --test_setup_script=ndk/test_setup.sh \ 89 --test_script=ndk/boot_test.sh \ 90 --file_args 91 92 popd 93