Index: upload_symbols |
diff --git a/upload_symbols b/upload_symbols |
new file mode 100755 |
index 0000000000000000000000000000000000000000..84de9ca561369d1b2125894dc74c94f2c60edb97 |
--- /dev/null |
+++ b/upload_symbols |
@@ -0,0 +1,242 @@ |
+#!/bin/bash |
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+# Script to upload all debug symbols required for crash reporting |
+# purposes. This script need only be used to upload release builds |
+# symbols or to debug crashes on non-release builds (in which case try |
+# to only upload the symbols for those executables involved). |
+# |
+# NOTE: This script must be run from the chromeos build chroot environment. |
+# |
+ |
+# Load common constants. This should be the first executable line. |
+# The path to common.sh should be relative to your script's location. |
+. "$(dirname "$0")/common.sh" |
+ |
+# Script must be run inside the chroot |
+restart_in_chroot_if_needed $* |
+ |
+get_default_board |
+ |
+# Flags |
+DEFINE_string board "$DEFAULT_BOARD" "The board to build packages for." |
+DEFINE_boolean dryrun ${FLAGS_FALSE} "Run without actually uploading." |
+DEFINE_boolean verbose ${FLAGS_FALSE} "Be verbose." |
+DEFINE_boolean yes ${FLAGS_FALSE} "Answer yes to all prompts." |
+ |
+DUMP_SYMS="dump_syms.i386" |
+SYM_UPLOAD="sym_upload.i386" |
+ |
+CUMULATIVE_SIZE=0 |
+ |
+SYM_FILE=$(mktemp "/tmp/sym.XXXX") |
+ERR_FILE=$(mktemp "/tmp/err.XXXX") |
+ |
+function cleanup() { |
+ rm -f "${SYM_FILE}" "${ERR_FILE}" |
+} |
+ |
+function is_official() { |
+ if [ ${CHROMEOS_OFFICIAL:-0} = 1 ]; then |
+ return 0 |
+ else |
+ return 1 |
+ fi |
+} |
+ |
+# Given path to a debug file, return its text file |
+function get_text_for_debug { |
+ local debug_file=$1 |
+ local text_dir=$(dirname ${debug_file#$DEBUG_ROOT}) |
+ local text_path=${SYSROOT}${text_dir}/$(basename "${debug_file}" .debug) |
+ echo ${text_path} |
+} |
+ |
+# Given path to a text file, return its debug file |
+function get_debug_for_text { |
+ local text_file=$1 |
+ local text_path=${text_file#${SYSROOT}} |
+ local debug_path=${DEBUG_ROOT}${text_path}.debug |
+ echo ${debug_path} |
+} |
+ |
+function really_upload { |
+ if [ ${FLAGS_yes} -eq ${FLAGS_TRUE} ]; then |
+ return 0 |
+ fi |
+ echo "Uploading symbols for an entire Chromium OS build is really only " |
+ echo "necessary for release builds and in a few cases for developers " |
+ echo "to debug problems. It will take considerable time to run. For " |
+ echo "developer debugging purposes, consider instead passing specific files " |
+ echo "to upload." |
+ read -p "Are you sure you want to upload all build symbols (y/N)? " SURE |
+ SURE="${SURE:0:1}" # Get just the first character |
+ if [ "${SURE}" != "y" ]; then |
+ echo "Ok, better safe than sorry." |
+ return 1 |
+ fi |
+ return 0 |
+} |
+ |
+function dump_file { |
+ local debug_file="$1" |
+ local text_file="$2" |
+ # Dump symbols as root in order to read all files. |
+ if ! sudo "${DUMP_SYMS}" "${debug_file}" "${text_file}" > "${SYM_FILE}" \ |
+ 2> "${ERR_FILE}"; then |
+ # A lot of files (like kernel files) contain no debug information, do |
+ # not consider such occurrences as errors. |
+ if grep -q "file contains no debugging information" "${ERR_FILE}"; then |
+ warn "No symbols found for ${text_file}" |
+ return 0 |
+ fi |
+ error "Unable to dump symbols for ${text_file}:" |
+ cat "${ERR_FILE}" |
+ return 1 |
+ fi |
+ if [ ${FLAGS_verbose} -eq ${FLAGS_TRUE} ]; then |
+ local file_id=$(head -1 ${SYM_FILE} | cut -d' ' -f4) |
+ local module_name=$(head -1 ${SYM_FILE} | cut -d' ' -f5) |
+ # Show file upload success and symbol info for easier lookup |
+ info "Dumped symbols from ${text_file} for ${module_name}|${file_id}." |
+ fi |
+ # Sanity check: if we've created the same named file in the /usr/lib/debug |
+ # directory during the src_compile stage of an ebuild, verify our sym file |
+ # is the same. |
+ local installed_sym="${DEBUG_ROOT}"/$(basename "${text_file}").sym |
+ if [ -e "${installed_sym}" ]; then |
+ if ! diff "${installed_sym}" "${SYM_FILE}"; then |
+ error "${installed_sym} differ from current sym file:" |
+ diff "${installed_sym}" "${SYM_FILE}" |
+ return 1 |
+ fi |
+ fi |
+ size=$(wc -c "${SYM_FILE}" | cut -d' ' -f1) |
+ CUMULATIVE_SIZE=$((CUMULATIVE_SIZE + $size)) |
+ return 0 |
+} |
+ |
+# Upload the current symbol file to given URL. |
+function upload_file { |
+ local upload_url="$1" |
+ if ! "${SYM_UPLOAD}" "${SYM_FILE}" "${upload_url}" > /dev/null \ |
+ 2> "${ERR_FILE}"; then |
+ error "Unable to upload symbols in ${SYM_FILE}:" |
+ cat "${ERR_FILE}" |
+ return 1 |
+ fi |
+ if [ ${FLAGS_verbose} -eq ${FLAGS_TRUE} ]; then |
+ size=$(wc -c "${SYM_FILE}" | cut -d' ' -f1) |
+ info "Successfully uploaded ${size}B." |
+ fi |
+ return 0 |
+} |
+ |
+# Convert and then upload the given debug file to the given URL. |
+function process_file { |
+ local debug_file="$1" |
+ local upload_url="$2" |
+ local text_file="$(get_text_for_debug ${debug_file})" |
+ if [ "${text_file##*.}" == "ko" ]; then |
+ # Skip kernel objects. We can't use their symbols and they sometimes |
+ # have objects with empty text sections which trigger errors in dump_sym. |
+ if [ ${FLAGS_verbose} -eq ${FLAGS_TRUE} ]; then |
+ info "Skipping kernel object: ${text_file}" |
+ fi |
+ return 0 |
+ fi |
+ if [ "${text_file#${AUTOTEST_ROOT}}" != "${text_file}" ]; then |
+ # Skip autotest files, they are not part of the image to debug |
+ # and some cause trouble to dump_syms because they are built |
+ # externally (with different build options). |
+ if [ ${FLAGS_verbose} -eq ${FLAGS_TRUE} ]; then |
+ info "Skipping autotest file: ${text_file}" |
+ fi |
+ return 0 |
+ fi |
+ if [ ! -f "${text_file}" ]; then |
+ # Allow files to not exist, for instance if they are in the INSTALL_MASK. |
+ warn "Binary does not exist: ${text_file}" |
+ return 0 |
+ fi |
+ |
+ dump_file "${debug_file}" "${text_file}" || return 1 |
+ |
+ [ ${FLAGS_dryrun} -eq ${FLAGS_TRUE} ] && return 0 |
+ |
+ upload_file "${upload_url}" |
+} |
+ |
+function main() { |
+ trap cleanup EXIT |
+ |
+ # Parse command line |
+ FLAGS_HELP="usage: $0 [flags] [<files...>]" |
+ FLAGS "$@" || exit 1 |
+ eval set -- "${FLAGS_ARGV}" |
+ |
+ set -e |
+ |
+ [ -n "$FLAGS_board" ] || die "--board is required." |
+ |
+ SYSROOT="/build/${FLAGS_board}" |
+ |
+ local upload_url="" |
+ if [ ${FLAGS_dryrun} -eq ${FLAGS_FALSE} ]; then |
+ if is_official; then |
+ upload_url="http://clients2.google.com/cr/symbol" |
+ else |
+ upload_url="http://clients2.google.com/cr/staging_symbol" |
+ warn "This is an unofficial build, uploading to staging server." |
+ fi |
+ info "Uploading symbols to ${upload_url} from ${SYSROOT}." |
+ else |
+ warn "Will not upload symbols due to --nodryrun." |
+ fi |
+ |
+ DEBUG_ROOT="${SYSROOT}/usr/lib/debug" |
+ AUTOTEST_ROOT="${SYSROOT}/usr/local/autotest" |
+ CUMULATIVE_SIZE=0 |
+ |
+ local any_errors=0 |
+ if [ -z "${FLAGS_ARGV}" ]; then |
+ if [ ${FLAGS_dryrun} -eq ${FLAGS_FALSE} ]; then |
+ really_upload || exit 1 |
+ fi |
+ for debug_file in $(find "${DEBUG_ROOT}" -name \*.debug); do |
+ if ! process_file "${debug_file}" "${upload_url}"; then |
+ any_errors=1 |
+ fi |
+ done |
+ else |
+ for either_file in ${FLAGS_ARGV}; do |
+ either_file=${either_file#\'} |
+ either_file=${either_file%\'} |
+ if [ ! -f "${either_file}" ]; then |
+ error "Specified file ${either_file} does not exist" |
+ any_errors=1 |
+ continue |
+ fi |
+ if [ "${either_file##*.}" == "debug" ]; then |
+ debug_file="${either_file}" |
+ else |
+ debug_file="$(get_debug_for_text ${either_file})" |
+ fi |
+ if ! process_file "${debug_file}" "${upload_url}"; then |
+ any_errors=1 |
+ fi |
+ done |
+ fi |
+ |
+ if [ ${FLAGS_dryrun} -eq ${FLAGS_TRUE} ]; then |
+ warn "Did not actually upload, pass --nodryrun to upload" |
+ info "Would have uploaded ${CUMULATIVE_SIZE}B of debug information" |
+ else |
+ info "Uploaded ${CUMULATIVE_SIZE}B of debug information" |
+ fi |
+ [ ${any_errors} -ne 0 ] && die "Encountered problems" |
+} |
+ |
+main "$@" |