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