forked from eden-emu/eden
		
	
		
			
	
	
		
			555 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
		
		
			
		
	
	
			555 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
|  | #!/bin/sh
 | ||
|  | # Copyright 2012 Google LLC | ||
|  | # | ||
|  | # Redistribution and use in source and binary forms, with or without | ||
|  | # modification, are permitted provided that the following conditions are | ||
|  | # met: | ||
|  | # | ||
|  | #     * Redistributions of source code must retain the above copyright | ||
|  | # notice, this list of conditions and the following disclaimer. | ||
|  | #     * Redistributions in binary form must reproduce the above | ||
|  | # copyright notice, this list of conditions and the following disclaimer | ||
|  | # in the documentation and/or other materials provided with the | ||
|  | # distribution. | ||
|  | #     * Neither the name of Google LLC nor the names of its | ||
|  | # contributors may be used to endorse or promote products derived from | ||
|  | # this software without specific prior written permission. | ||
|  | # | ||
|  | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
|  | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
|  | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
|  | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
|  | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
|  | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
|  | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
|  | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
|  | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
|  | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
|  | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
|  | 
 | ||
|  | # Sanitize the environment | ||
|  | export LANG=C | ||
|  | export LC_ALL=C | ||
|  | 
 | ||
|  | if [ "$BASH_VERSION" ]; then | ||
|  |   set -o posix | ||
|  | fi | ||
|  | 
 | ||
|  | PROGDIR=$(dirname "$0") | ||
|  | PROGDIR=$(cd "$PROGDIR" && pwd) | ||
|  | PROGNAME=$(basename "$0") | ||
|  | 
 | ||
|  | . $PROGDIR/common-functions.sh | ||
|  | 
 | ||
|  | DEFAULT_ABI="armeabi" | ||
|  | VALID_ABIS="armeabi armeabi-v7a x86 mips" | ||
|  | 
 | ||
|  | ABI= | ||
|  | ADB= | ||
|  | ALL_TESTS= | ||
|  | ENABLE_M32= | ||
|  | HELP= | ||
|  | HELP_ALL= | ||
|  | NDK_DIR= | ||
|  | NO_CLEANUP= | ||
|  | NO_DEVICE= | ||
|  | NUM_JOBS=$(get_core_count) | ||
|  | TMPDIR= | ||
|  | 
 | ||
|  | for opt do | ||
|  |   # The following extracts the value if the option is like --name=<value>. | ||
|  |   optarg=$(expr -- $opt : '^--[^=]*=\(.*\)$') | ||
|  |   case $opt in | ||
|  |     --abi=*) ABI=$optarg;; | ||
|  |     --adb=*) ADB=$optarg;; | ||
|  |     --all-tests) ALL_TESTS=true;; | ||
|  |     --enable-m32) ENABLE_M32=true;; | ||
|  |     --help|-h|-?) HELP=TRUE;; | ||
|  |     --help-all) HELP_ALL=true;; | ||
|  |     --jobs=*) NUM_JOBS=$optarg;; | ||
|  |     --ndk-dir=*) NDK_DIR=$optarg;; | ||
|  |     --tmp-dir=*) TMPDIR=$optarg;; | ||
|  |     --no-cleanup) NO_CLEANUP=true;; | ||
|  |     --no-device) NO_DEVICE=true;; | ||
|  |     --quiet) decrease_verbosity;; | ||
|  |     --verbose) increase_verbosity;; | ||
|  |     -*) panic "Invalid option '$opt', see --help for details.";; | ||
|  |     *) panic "This script doesn't take any parameters. See --help for details." | ||
|  |        ;; | ||
|  |   esac | ||
|  | done | ||
|  | 
 | ||
|  | if [ "$HELP" -o "$HELP_ALL" ]; then | ||
|  |   echo "\
 | ||
|  |   Usage: $PROGNAME [options] | ||
|  | 
 | ||
|  |   This script is used to check that your Google Breakpad source tree can | ||
|  |   be properly built for Android, and that the client library and host tools | ||
|  |   work properly together. | ||
|  | "
 | ||
|  |   if [ "$HELP_ALL" ]; then | ||
|  |     echo "\
 | ||
|  |   In more details, this script will: | ||
|  | 
 | ||
|  |   - Rebuild the host version of Google Breakpad in a temporary | ||
|  |     directory (with the Auto-tools based build system). | ||
|  | 
 | ||
|  |   - Rebuild the Android client library with the Google Breakpad build | ||
|  |     system (using autotools/configure). This requires that you define | ||
|  |     ANDROID_NDK_ROOT in your environment to point to a valid Android NDK | ||
|  |     installation directory, or use the --ndk-dir=<path> option. | ||
|  | 
 | ||
|  |   - Rebuild the Android client library and a test crashing program with the | ||
|  |     Android NDK build system (ndk-build). | ||
|  | 
 | ||
|  |   - Require an Android device connected to your machine, and the 'adb' | ||
|  |     tool in your path. They are used to: | ||
|  | 
 | ||
|  |       - Install and  run a test crashing program. | ||
|  |       - Extract the corresponding minidump from the device. | ||
|  |       - Dump the symbols from the test program on the host with 'dump_syms' | ||
|  |       - Generate a stack trace with 'minidump_stackwalk' | ||
|  |       - Check the stack trace content for valid source file locations. | ||
|  | 
 | ||
|  |     You can however skip this requirement and only test the builds by using | ||
|  |     the --no-device flag. | ||
|  | 
 | ||
|  |     By default, all generated files will be created in a temporary directory | ||
|  |     that is removed when the script completion. If you want to inspect the | ||
|  |     files, use the --no-cleanup option. | ||
|  | 
 | ||
|  |     Finally, use --verbose to increase the verbosity level, this will help | ||
|  |     you see which exact commands are being issues and their result. Use the | ||
|  |     flag twice for even more output. Use --quiet to decrease verbosity | ||
|  |     instead and run the script silently. | ||
|  | 
 | ||
|  |     If you have a device connected, the script will probe it to determine | ||
|  |     its primary CPU ABI, and build the test program for it. You can however | ||
|  |     use the --abi=<name> option to override this (this can be useful to check | ||
|  |     the secondary ABI, e.g. using --abi=armeabi to check that such a program | ||
|  |     works correctly on an ARMv7-A device). | ||
|  | 
 | ||
|  |     If you don't have a device connected, the test program will be built (but | ||
|  |     not run) with the default '$DEFAULT_ABI' ABI. Again, you can use | ||
|  |     --abi=<name> to override this. Valid ABI names are: | ||
|  | 
 | ||
|  |         $VALID_ABIS | ||
|  | 
 | ||
|  |     The script will only run the client library unit test on the device | ||
|  |     by default. You can use --all-tests to also build and run the unit | ||
|  |     tests for the Breakpad tools and processor, but be warned that this | ||
|  |     adds several minutes of testing time. --all-tests will also run the | ||
|  |     host unit tests suite. | ||
|  | "
 | ||
|  | 
 | ||
|  |   fi  # HELP_ALL | ||
|  | 
 | ||
|  |   echo "\
 | ||
|  |   Valid options: | ||
|  | 
 | ||
|  |       --help|-h|-?     Display this message. | ||
|  |       --help-all       Display extended help. | ||
|  |       --enable-m32     Build 32-bit version of host tools. | ||
|  |       --abi=<name>     Specify target CPU ABI [auto-detected]. | ||
|  |       --jobs=<count>   Run <count> build tasks in parallel [$NUM_JOBS]. | ||
|  |       --ndk-dir=<path> Specify NDK installation directory. | ||
|  |       --tmp-dir=<path> Specify temporary directory (will be wiped-out). | ||
|  |       --adb=<path>     Specify adb program path. | ||
|  |       --no-cleanup     Don't remove temporary directory after completion. | ||
|  |       --no-device      Do not try to detect devices, nor run crash test. | ||
|  |       --all-tests      Run all unit tests (i.e. tools and processor ones too). | ||
|  |       --verbose        Increase verbosity. | ||
|  |       --quiet          Decrease verbosity."
 | ||
|  | 
 | ||
|  |   exit 0 | ||
|  | fi | ||
|  | 
 | ||
|  | TESTAPP_DIR=$PROGDIR/sample_app | ||
|  | 
 | ||
|  | # Select NDK install directory. | ||
|  | if [ -z "$NDK_DIR" ]; then | ||
|  |   if [ -z "$ANDROID_NDK_ROOT" ]; then | ||
|  |     panic "Please define ANDROID_NDK_ROOT in your environment, or use \
 | ||
|  | --ndk-dir=<path>."
 | ||
|  |   fi | ||
|  |   NDK_DIR="$ANDROID_NDK_ROOT" | ||
|  |   log "Found NDK directory: $NDK_DIR" | ||
|  | else | ||
|  |   log "Using NDK directory: $NDK_DIR" | ||
|  | fi | ||
|  | # Small sanity check. | ||
|  | NDK_BUILD="$NDK_DIR/ndk-build" | ||
|  | if [ ! -f "$NDK_BUILD" ]; then | ||
|  |   panic "Your NDK directory is not valid (missing ndk-build): $NDK_DIR" | ||
|  | fi | ||
|  | 
 | ||
|  | # Ensure the temporary directory is deleted on exit, except if the --no-cleanup | ||
|  | # option is used. | ||
|  | 
 | ||
|  | clean_tmpdir () { | ||
|  |   if [ "$TMPDIR" ]; then | ||
|  |     if [ -z "$NO_CLEANUP" ]; then | ||
|  |       log "Cleaning up: $TMPDIR" | ||
|  |       rm -rf "$TMPDIR" | ||
|  |     else | ||
|  |       dump "Temporary directory contents preserved: $TMPDIR" | ||
|  |     fi | ||
|  |   fi | ||
|  |   exit "$@" | ||
|  | } | ||
|  | 
 | ||
|  | atexit clean_tmpdir | ||
|  | 
 | ||
|  | # If --tmp-dir=<path> is not used, create a temporary directory. | ||
|  | # Otherwise, start by cleaning up the user-provided path. | ||
|  | if [ -z "$TMPDIR" ]; then | ||
|  |   TMPDIR=$(mktemp -d /tmp/$PROGNAME.XXXXXXXX) | ||
|  |   fail_panic "Can't create temporary directory!" | ||
|  |   log "Using temporary directory: $TMPDIR" | ||
|  | else | ||
|  |   if [ ! -d "$TMPDIR" ]; then | ||
|  |     mkdir -p "$TMPDIR" | ||
|  |     fail_panic "Can't create temporary directory: $TMPDIR" | ||
|  |   else | ||
|  |     log "Cleaning up temporary directory: $TMPDIR" | ||
|  |     rm -rf "$TMPDIR"/* | ||
|  |     fail_panic "Cannot cleanup temporary directory!" | ||
|  |   fi | ||
|  | fi | ||
|  | 
 | ||
|  | if [ -z "$NO_DEVICE" ]; then | ||
|  |   if ! adb_check_device $ADB; then | ||
|  |     echo "$(adb_get_error)" | ||
|  |     echo "Use --no-device to build the code without running any tests." | ||
|  |     exit 1 | ||
|  |   fi | ||
|  | fi | ||
|  | 
 | ||
|  | BUILD_LOG="$TMPDIR/build.log" | ||
|  | RUN_LOG="$TMPDIR/run.log" | ||
|  | CRASH_LOG="$TMPDIR/crash.log" | ||
|  | 
 | ||
|  | set_run_log "$RUN_LOG" | ||
|  | 
 | ||
|  | TMPHOST="$TMPDIR/host-local" | ||
|  | 
 | ||
|  | cd "$TMPDIR" | ||
|  | 
 | ||
|  | # Build host version of the tools | ||
|  | dump "Building host binaries." | ||
|  | CONFIGURE_FLAGS= | ||
|  | if [ "$ENABLE_M32" ]; then | ||
|  |   CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-m32" | ||
|  | fi | ||
|  | ( | ||
|  |   run mkdir "$TMPDIR/build-host" && | ||
|  |   run cd "$TMPDIR/build-host" && | ||
|  |   run2 "$PROGDIR/../configure" --prefix="$TMPHOST" $CONFIGURE_FLAGS && | ||
|  |   run2 make -j$NUM_JOBS install | ||
|  | ) | ||
|  | fail_panic "Can't build host binaries!" | ||
|  | 
 | ||
|  | if [ "$ALL_TESTS" ]; then | ||
|  |   dump "Running host unit tests." | ||
|  |   ( | ||
|  |     run cd "$TMPDIR/build-host" && | ||
|  |     run2 make -j$NUM_JOBS check | ||
|  |   ) | ||
|  |   fail_panic "Host unit tests failed!!" | ||
|  | fi | ||
|  | 
 | ||
|  | TMPBIN=$TMPHOST/bin | ||
|  | 
 | ||
|  | # Generate a stand-alone NDK toolchain | ||
|  | 
 | ||
|  | # Extract CPU ABI and architecture from device, if any. | ||
|  | if adb_check_device; then | ||
|  |   DEVICE_ABI=$(adb_shell getprop ro.product.cpu.abi) | ||
|  |   DEVICE_ABI2=$(adb_shell getprop ro.product.cpu.abi2) | ||
|  |   if [ -z "$DEVICE_ABI" ]; then | ||
|  |     panic "Can't extract ABI from connected device!" | ||
|  |   fi | ||
|  |   if [ "$DEVICE_ABI2" ]; then | ||
|  |     dump "Found device ABIs: $DEVICE_ABI $DEVICE_ABI2" | ||
|  |   else | ||
|  |     dump "Found device ABI: $DEVICE_ABI" | ||
|  |     DEVICE_ABI2=$DEVICE_ABI | ||
|  |   fi | ||
|  | 
 | ||
|  |   # If --abi=<name> is used, check that the device supports it. | ||
|  |   if [ "$ABI" -a "$DEVICE_ABI" != "$ABI" -a "$DEVICE_ABI2" != "$ABI" ]; then | ||
|  |     dump  "ERROR: Device ABI(s) do not match --abi command-line value ($ABI)!" | ||
|  |     panic "Please use --no-device to skip device tests." | ||
|  |   fi | ||
|  | 
 | ||
|  |   if [ -z "$ABI" ]; then | ||
|  |     ABI=$DEVICE_ABI | ||
|  |     dump "Using CPU ABI: $ABI (device)" | ||
|  |   else | ||
|  |     dump "Using CPU ABI: $ABI (command-line)" | ||
|  |   fi | ||
|  | else | ||
|  |   if [ -z "$ABI" ]; then | ||
|  |     # No device connected, choose default ABI | ||
|  |     ABI=$DEFAULT_ABI | ||
|  |     dump "Using CPU ABI: $ABI (default)" | ||
|  |   else | ||
|  |     dump "Using CPU ABI: $ABI (command-line)" | ||
|  |   fi | ||
|  | fi | ||
|  | 
 | ||
|  | # Check the ABI value | ||
|  | VALID= | ||
|  | for VALID_ABI in $VALID_ABIS; do | ||
|  |   if [ "$ABI" = "$VALID_ABI" ]; then | ||
|  |     VALID=true | ||
|  |     break | ||
|  |   fi | ||
|  | done | ||
|  | 
 | ||
|  | if [ -z "$VALID" ]; then | ||
|  |   panic "Unknown CPU ABI '$ABI'. Valid values are: $VALID_ABIS" | ||
|  | fi | ||
|  | 
 | ||
|  | # Extract architecture name from ABI | ||
|  | case $ABI in | ||
|  |   armeabi*) ARCH=arm;; | ||
|  |   *) ARCH=$ABI;; | ||
|  | esac | ||
|  | 
 | ||
|  | # Extract GNU configuration name | ||
|  | case $ARCH in | ||
|  |   arm) | ||
|  |     GNU_CONFIG=arm-linux-androideabi | ||
|  |     ;; | ||
|  |   x86) | ||
|  |     GNU_CONFIG=i686-linux-android | ||
|  |     ;; | ||
|  |   mips) | ||
|  |     GNU_CONFIG=mipsel-linux-android | ||
|  |     ;; | ||
|  |   *) | ||
|  |     GNU_CONFIG="$ARCH-linux-android" | ||
|  |     ;; | ||
|  | esac | ||
|  | 
 | ||
|  | # Generate standalone NDK toolchain installation | ||
|  | NDK_STANDALONE="$TMPDIR/ndk-$ARCH-toolchain" | ||
|  | echo "Generating NDK standalone toolchain installation" | ||
|  | mkdir -p "$NDK_STANDALONE" | ||
|  | # NOTE: The --platform=android-9 is required to provide <regex.h> for GTest. | ||
|  | run "$NDK_DIR/build/tools/make-standalone-toolchain.sh" \
 | ||
|  |       --arch="$ARCH" \
 | ||
|  |       --platform=android-9 \
 | ||
|  |       --install-dir="$NDK_STANDALONE" | ||
|  | fail_panic "Can't generate standalone NDK toolchain installation!" | ||
|  | 
 | ||
|  | # Rebuild the client library, processor and tools with the auto-tools based | ||
|  | # build system. Even though it's not going to be used, this checks that this | ||
|  | # still works correctly. | ||
|  | echo "Building full Android binaries with configure/make" | ||
|  | TMPTARGET="$TMPDIR/target-local" | ||
|  | ( | ||
|  |   PATH="$NDK_STANDALONE/bin:$PATH" | ||
|  |   run mkdir "$TMPTARGET" && | ||
|  |   run mkdir "$TMPDIR"/build-target && | ||
|  |   run cd "$TMPDIR"/build-target && | ||
|  |   run2 "$PROGDIR"/../configure --prefix="$TMPTARGET" \
 | ||
|  |                                --host="$GNU_CONFIG" && | ||
|  |   run2 make -j$NUM_JOBS install | ||
|  | ) | ||
|  | fail_panic "Could not rebuild Android binaries!" | ||
|  | 
 | ||
|  | # Build and/or run unit test suite. | ||
|  | # If --no-device is used, only rebuild it, otherwise, run in on the | ||
|  | # connected device. | ||
|  | if [ "$NO_DEVICE" ]; then | ||
|  |   ACTION="Building" | ||
|  |   # This is a trick to force the Makefile to ignore running the scripts. | ||
|  |   TESTS_ENVIRONMENT="TESTS_ENVIRONMENT=true" | ||
|  | else | ||
|  |   ACTION="Running" | ||
|  |   TESTS_ENVIRONMENT= | ||
|  | fi | ||
|  | 
 | ||
|  | ( | ||
|  |   PATH="$NDK_STANDALONE/bin:$PATH" | ||
|  |   run cd "$TMPDIR"/build-target && | ||
|  |   # Reconfigure to only run the client unit test suite. | ||
|  |   # This one should _never_ fail. | ||
|  |   dump "$ACTION Android client library unit tests." | ||
|  |   run2 "$PROGDIR"/../configure --prefix="$TMPTARGET" \
 | ||
|  |                                --host="$GNU_CONFIG" \
 | ||
|  |                                --disable-tools \
 | ||
|  |                                --disable-processor && | ||
|  |   run make -j$NUM_JOBS check $TESTS_ENVIRONMENT || exit $? | ||
|  | 
 | ||
|  |   if [ "$ALL_TESTS" ]; then | ||
|  |     dump "$ACTION Tools and processor unit tests." | ||
|  |     # Reconfigure to run the processor and tools tests. | ||
|  |     # Most of these fail for now, so do not worry about it. | ||
|  |     run2 "$PROGDIR"/../configure --prefix="$TMPTARGET" \
 | ||
|  |                                  --host="$GNU_CONFIG" && | ||
|  |     run make -j$NUM_JOBS check $TESTS_ENVIRONMENT | ||
|  |     if [ $? != 0 ]; then | ||
|  |       dump "Tools and processor unit tests failed as expected. \
 | ||
|  | Use --verbose for results."
 | ||
|  |     fi                            | ||
|  |   fi | ||
|  | ) | ||
|  | fail_panic "Client library unit test suite failed!" | ||
|  | 
 | ||
|  | # Copy sources to temporary directory | ||
|  | PROJECT_DIR=$TMPDIR/project | ||
|  | dump "Copying test program sources to: $PROJECT_DIR" | ||
|  | run cp -r "$TESTAPP_DIR" "$PROJECT_DIR" && | ||
|  | run rm -rf "$PROJECT_DIR/obj" && | ||
|  | run rm -rf "$PROJECT_DIR/libs" | ||
|  | fail_panic "Could not copy test program sources to: $PROJECT_DIR" | ||
|  | 
 | ||
|  | # Build the test program with ndk-build. | ||
|  | dump "Building test program with ndk-build" | ||
|  | export NDK_MODULE_PATH="$PROGDIR" | ||
|  | NDK_BUILD_FLAGS="-j$NUM_JOBS" | ||
|  | if verbosity_is_higher_than 1; then | ||
|  |   NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS NDK_LOG=1 V=1" | ||
|  | fi | ||
|  | run "$NDK_DIR/ndk-build" -C "$PROJECT_DIR" $NDK_BUILD_FLAGS APP_ABI=$ABI | ||
|  | fail_panic "Can't build test program!" | ||
|  | 
 | ||
|  | # Unless --no-device was used, stop right here if ADB isn't in the path, | ||
|  | # or there is no connected device. | ||
|  | if [ "$NO_DEVICE" ]; then | ||
|  |   dump "Done. Please connect a device to run all tests!" | ||
|  |   clean_exit 0 | ||
|  | fi | ||
|  | 
 | ||
|  | # Push the program to the device. | ||
|  | TESTAPP=test_google_breakpad | ||
|  | TESTAPP_FILE="$PROJECT_DIR/libs/$ABI/test_google_breakpad" | ||
|  | if [ ! -f "$TESTAPP_FILE" ]; then | ||
|  |   panic "Device requires '$ABI' binaries. None found!" | ||
|  | fi | ||
|  | 
 | ||
|  | # Run the program there | ||
|  | dump "Installing test program on device" | ||
|  | DEVICE_TMP=/data/local/tmp | ||
|  | adb_push "$TESTAPP_FILE" "$DEVICE_TMP/" | ||
|  | fail_panic "Cannot push test program to device!" | ||
|  | 
 | ||
|  | dump "Running test program on device" | ||
|  | adb_shell cd "$DEVICE_TMP" "&&" ./$TESTAPP > "$CRASH_LOG" 2>/dev/null | ||
|  | if [ $? = 0 ]; then | ||
|  |   panic "Test program did *not* crash as expected!" | ||
|  | fi | ||
|  | if verbosity_is_higher_than 0; then | ||
|  |   echo -n "Crash log: " | ||
|  |   cat "$CRASH_LOG" | ||
|  | fi | ||
|  | 
 | ||
|  | # Extract minidump from device | ||
|  | MINIDUMP_NAME=$(awk '$1 == "Dump" && $2 == "path:" { print $3; }' "$CRASH_LOG") | ||
|  | MINIDUMP_NAME=$(basename "$MINIDUMP_NAME") | ||
|  | if [ -z "$MINIDUMP_NAME" ]; then | ||
|  |   panic "Test program didn't write minidump properly!" | ||
|  | fi | ||
|  | 
 | ||
|  | dump "Extracting minidump: $MINIDUMP_NAME" | ||
|  | adb_pull "$DEVICE_TMP/$MINIDUMP_NAME" . | ||
|  | fail_panic "Can't extract minidump!" | ||
|  | 
 | ||
|  | dump "Parsing test program symbols" | ||
|  | if verbosity_is_higher_than 1; then | ||
|  |   log "COMMAND: $TMPBIN/dump_syms \
 | ||
|  |                 $PROJECT_DIR/obj/local/$ABI/$TESTAPP >$TESTAPP.sym"
 | ||
|  | fi | ||
|  | "$TMPBIN/dump_syms" "$PROJECT_DIR/obj/local/$ABI/$TESTAPP" > $TESTAPP.sym | ||
|  | fail_panic "dump_syms doesn't work!" | ||
|  | 
 | ||
|  | VERSION=$(awk '$1 == "MODULE" { print $4; }' $TESTAPP.sym) | ||
|  | dump "Found module version: $VERSION" | ||
|  | if [ -z "$VERSION" ]; then | ||
|  |   echo "ERROR: Can't find proper module version from symbol dump!" | ||
|  |   head -n5 $TESTAPP.sym | ||
|  |   clean_exit 1 | ||
|  | fi | ||
|  | 
 | ||
|  | run mkdir -p "$TMPDIR/symbols/$TESTAPP/$VERSION" | ||
|  | run mv $TESTAPP.sym "$TMPDIR/symbols/$TESTAPP/$VERSION/" | ||
|  | 
 | ||
|  | dump "Generating stack trace" | ||
|  | # Don't use 'run' to be able to send stdout and stderr to two different files. | ||
|  | log "COMMAND: $TMPBIN/minidump_stackwalk $MINIDUMP_NAME symbols" | ||
|  | "$TMPBIN/minidump_stackwalk" $MINIDUMP_NAME \
 | ||
|  |                              "$TMPDIR/symbols" \
 | ||
|  |                              > "$BUILD_LOG" 2>>"$RUN_LOG" | ||
|  | fail_panic "minidump_stackwalk doesn't work!" | ||
|  | 
 | ||
|  | dump "Checking stack trace content" | ||
|  | 
 | ||
|  | if verbosity_is_higher_than 1; then | ||
|  |   cat "$BUILD_LOG" | ||
|  | fi | ||
|  | 
 | ||
|  | # The generated stack trace should look like the following: | ||
|  | # | ||
|  | # Thread 0 (crashed) | ||
|  | #  0  test_google_breakpad!crash [test_breakpad.cpp : 17 + 0x4] | ||
|  | #      r4 = 0x00015530    r5 = 0xbea2cbe4    r6 = 0xffffff38    r7 = 0xbea2cb5c | ||
|  | #      r8 = 0x00000000    r9 = 0x00000000   r10 = 0x00000000    fp = 0x00000000 | ||
|  | #      sp = 0xbea2cb50    lr = 0x00009025    pc = 0x00008f84 | ||
|  | #     Found by: given as instruction pointer in context | ||
|  | #  1  test_google_breakpad!main [test_breakpad.cpp : 25 + 0x3] | ||
|  | #      r4 = 0x00015530    r5 = 0xbea2cbe4    r6 = 0xffffff38    r7 = 0xbea2cb5c | ||
|  | #      r8 = 0x00000000    r9 = 0x00000000   r10 = 0x00000000    fp = 0x00000000 | ||
|  | #      sp = 0xbea2cb50    pc = 0x00009025 | ||
|  | #     Found by: call frame info | ||
|  | #  2  libc.so + 0x164e5 | ||
|  | #      r4 = 0x00008f64    r5 = 0xbea2cc34    r6 = 0x00000001    r7 = 0xbea2cc3c | ||
|  | #      r8 = 0x00000000    r9 = 0x00000000   r10 = 0x00000000    fp = 0x00000000 | ||
|  | #      sp = 0xbea2cc18    pc = 0x400c34e7 | ||
|  | #     Found by: call frame info | ||
|  | # ... | ||
|  | # | ||
|  | # The most important part for us is ensuring that the source location could | ||
|  | # be extracted, so look at the 'test_breakpad.cpp' references here. | ||
|  | # | ||
|  | # First, extract all the lines with test_google_breakpad! in them, and | ||
|  | # dump the corresponding crash location. | ||
|  | # | ||
|  | # Note that if the source location can't be extracted, the second field | ||
|  | # will only be 'test_google_breakpad' without the exclamation mark. | ||
|  | # | ||
|  | LOCATIONS=$(awk '$2 ~ "^test_google_breakpad!.*" { print $3; }' "$BUILD_LOG") | ||
|  | 
 | ||
|  | if [ -z "$LOCATIONS" ]; then | ||
|  |   if verbosity_is_lower_than 1; then | ||
|  |     cat "$BUILD_LOG" | ||
|  |   fi | ||
|  |   panic "No source location found in stack trace!" | ||
|  | fi | ||
|  | 
 | ||
|  | # Now check that they all match "[<source file>" | ||
|  | BAD_LOCATIONS= | ||
|  | for LOCATION in $LOCATIONS; do | ||
|  |   case $LOCATION in | ||
|  |     # Escape the opening bracket, or some shells like Dash will not | ||
|  |     # match them properly. | ||
|  |     \[*.cpp|\[*.cc|\[*.h) # These are valid source locations in our executable | ||
|  |       ;; | ||
|  |     *) # Everything else is not! | ||
|  |       BAD_LOCATIONS="$BAD_LOCATIONS $LOCATION" | ||
|  |       ;; | ||
|  |   esac | ||
|  | done | ||
|  | 
 | ||
|  | if [ "$BAD_LOCATIONS" ]; then | ||
|  |   dump "ERROR: Generated stack trace doesn't contain valid source locations:" | ||
|  |   cat "$BUILD_LOG" | ||
|  |   echo "Bad locations are: $BAD_LOCATIONS" | ||
|  |   exit 1 | ||
|  | fi | ||
|  | 
 | ||
|  | echo "All clear! Congratulations." | ||
|  | 
 |