diff --git a/upload_debug_syms.py b/upload_debug_syms.py deleted file mode 100755 index 76aed6a4a6..0000000000 --- a/upload_debug_syms.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/python - -''' Utility to upload debug symbols to the Google Breakpad Server ''' - -import os -import subprocess -import sys - -# Common Global Variables -DEBUG_BASE_PATH='/build' -DEBUG_SUBPATH='/usr/lib/debug' -DEBUG_EXT='.sym' -BP_UPLOAD=('../third_party/google-breakpad/' -'files/src/tools/linux/symupload/symupload') - -def CheckBinaryExists(): - if os.path.exists(BP_UPLOAD): - return True - return False - -def FindDebugFiles(): - - curdir = os.curdir - if not os.path.exists("/etc/debian_chroot"): - DEBUG_BASE_PATH= sys.argv[0] + '/../../chroot/build' - - files = [] - for dirpath, dirnames, filenames in os.walk(DEBUG_BASE_PATH): - filenames[:] = [os.path.join(dirpath, fname) - for fname in filenames if fname.endswith(DEBUG_EXT)] - files.extend(filenames) - return files - -def Upload(filenames=[]): - - for filename in filenames: - print 'executing..' + BP_UPLOAD + ' ' + filename - retval = subprocess.call([BPUPLOAD, filename]) - print retval - print 'done.' - -def Main(): - if not CheckBinaryExists(): - print "Could not find Breakpad Upload Binary at : %s " % BP_UPLOAD - return - - filenames = FindDebugFiles() - Upload(filenames) - -if __name__ == '__main__': - Main() diff --git a/upload_symbols b/upload_symbols new file mode 100755 index 0000000000..84de9ca561 --- /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] []" + 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 "$@"