mirror of
https://github.com/flatcar/scripts.git
synced 2025-11-28 14:01:43 +01:00
In our build environment, we have lots of symbolic links such as "debug/.build-id/5c/a06545ff3812557dc5fd259db4e905c5dc3484.debug" that just link to another .debug file. In our case, those links don't actually point to the right place, so we've just been seeing lots of "Binary does not exist" warnings. But it would also be undesirable to actually generate symbols for these even if their targets *did* exist. BUG=None TEST=Ran cros_generate_breakpad_symbols Change-Id: I050c349f7fefbdf922d54250379bad9b3db073d7 Reviewed-on: https://gerrit.chromium.org/gerrit/19182 Commit-Ready: Michael Krebs <mkrebs@chromium.org> Tested-by: Michael Krebs <mkrebs@chromium.org> Reviewed-by: David James <davidjames@chromium.org>
207 lines
6.5 KiB
Bash
Executable File
207 lines
6.5 KiB
Bash
Executable File
#!/bin/bash
|
|
# Copyright (c) 2011 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 generate minidump symbols in the format required by
|
|
# minidump_stackwalk to dump stack information.
|
|
#
|
|
# NOTE: This script must be run from the chromeos build chroot environment.
|
|
#
|
|
|
|
SCRIPT_ROOT=$(dirname $(readlink -f "$0"))
|
|
. "${SCRIPT_ROOT}/common.sh" || { echo "Unable to load common.sh"; exit 1; }
|
|
|
|
# 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_string minidump_symbol_root "" \
|
|
"Symbol root (defaults to /usr/lib/debug/breakpad for board)"
|
|
DEFINE_boolean verbose ${FLAGS_FALSE} "Be verbose."
|
|
|
|
DUMP_SYMS="dump_syms"
|
|
DUMP_SYMS32="dump_syms.32"
|
|
|
|
CUMULATIVE_SIZE=0
|
|
ANY_ERRORS=0
|
|
|
|
SYM_FILE=$(mktemp "/tmp/sym.XXXX")
|
|
ERR_FILE=$(mktemp "/tmp/err.XXXX")
|
|
|
|
function cleanup() {
|
|
rm -f "${SYM_FILE}" "${ERR_FILE}"
|
|
}
|
|
|
|
# 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}
|
|
}
|
|
|
|
# Returns true if the file given is a 32-bit ELF file.
|
|
function is_32b_elf() {
|
|
local elf="$1"
|
|
file "${elf}" | grep -q "ELF 32-bit"
|
|
}
|
|
|
|
# Dump given debug and text file. Returns 1 if any errors, even
|
|
# if they can be ignored, but only sets ANY_ERRORS if the error should not
|
|
# be ignored (and we should not proceed to upload).
|
|
function dump_file() {
|
|
local debug_file="$1"
|
|
local text_file="$2"
|
|
local debug_directory="$(dirname "${debug_file}")"
|
|
local dump_syms_prog="${DUMP_SYMS}"
|
|
# 32-bit dump_syms must be used to dump a 32-bit ELF file
|
|
if is_32b_elf "${text_file}"; then
|
|
dump_syms_prog="${DUMP_SYMS32}"
|
|
info "Using ${dump_syms_prog} for 32-bit file ${text_file}"
|
|
fi
|
|
# Dump symbols as root in order to read all files.
|
|
if ! sudo "${dump_syms_prog}" "${text_file}" "${debug_directory}" \
|
|
> "${SYM_FILE}" 2> "${ERR_FILE}"; then
|
|
# Try dumping just the main file to get public-only symbols.
|
|
if ! sudo "${dump_syms_prog}" "${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 1
|
|
fi
|
|
error "Unable to dump symbols for ${text_file}:"
|
|
cat "${ERR_FILE}"
|
|
ANY_ERRORS=1
|
|
return 1
|
|
else
|
|
warn "File ${text_file} did not have debug info, using linkage symbols"
|
|
fi
|
|
fi
|
|
local file_id=$(head -1 ${SYM_FILE} | cut -d' ' -f4)
|
|
local module_name=$(head -1 ${SYM_FILE} | cut -d' ' -f5)
|
|
if [ ${FLAGS_verbose} -eq ${FLAGS_TRUE} ]; then
|
|
# 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}"
|
|
ANY_ERRORS=1
|
|
return 1
|
|
fi
|
|
fi
|
|
size=$(wc -c "${SYM_FILE}" | cut -d' ' -f1)
|
|
CUMULATIVE_SIZE=$((CUMULATIVE_SIZE + $size))
|
|
|
|
local container_dir="${FLAGS_minidump_symbol_root}/${module_name}/${file_id}"
|
|
sudo mkdir -p "${container_dir}"
|
|
sudo mv "${SYM_FILE}" "${container_dir}/${module_name}.sym"
|
|
return 0
|
|
}
|
|
|
|
# Convert the given debug file. No return value.
|
|
function process_file() {
|
|
local debug_file="$1"
|
|
local text_file="$(get_text_for_debug ${debug_file})"
|
|
if [ -h "${debug_file}" ]; then
|
|
# Don't follow symbolic links. In particular, we don't want to bother
|
|
# with the *.debug links in the "debug/.build-id/" directory.
|
|
if [ ${FLAGS_verbose} -eq ${FLAGS_TRUE} ]; then
|
|
info "Skipping symbolic link: ${debug_file}"
|
|
fi
|
|
return 0
|
|
fi
|
|
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 [ ! -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
|
|
elif [ ! -r "${text_file}" ]; then
|
|
# Allow files to not be readable, for instance setuid programs like passwd
|
|
warn "Binary is not readable: ${text_file}"
|
|
return 0
|
|
fi
|
|
|
|
dump_file "${debug_file}" "${text_file}"
|
|
}
|
|
|
|
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}"
|
|
|
|
if [[ -z "${FLAGS_minidump_symbol_root}" ]]; then
|
|
FLAGS_minidump_symbol_root="${SYSROOT}/usr/lib/debug/breakpad"
|
|
fi
|
|
|
|
info "Writing minidump symbols to ${FLAGS_minidump_symbol_root}"
|
|
|
|
DEBUG_ROOT="${SYSROOT}/usr/lib/debug"
|
|
CUMULATIVE_SIZE=0
|
|
sudo rm -rf "${FLAGS_minidump_symbol_root}"
|
|
|
|
if [ -z "${FLAGS_ARGV}" ]; then
|
|
for debug_file in $(find "${DEBUG_ROOT}" -name \*.debug); do
|
|
! process_file "${debug_file}"
|
|
done
|
|
else
|
|
for either_file in ${FLAGS_ARGV}; do
|
|
either_file=${either_file#\'}
|
|
either_file=${either_file%\'}
|
|
if [ ! -h "${either_file}" -a ! -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
|
|
! process_file "${debug_file}"
|
|
done
|
|
fi
|
|
|
|
info "Generated ${CUMULATIVE_SIZE}B of debug information"
|
|
|
|
[ ${ANY_ERRORS} -ne 0 ] && die "Encountered problems"
|
|
return 0
|
|
}
|
|
|
|
main "$@"
|