mirror of
https://github.com/flatcar/scripts.git
synced 2025-09-22 22:21:10 +02:00
dump_syms can only dump the symbols of an executable with the same ELF format as itself. Some recent build configurations now have binaries with differing ELF formats. For example, issue 25468 has a 64-bit kernel where everything else is 32-bit, and issue 25466 indicates there's a test that contains a 32-bit executable. BUG=chromium-os:25496, chromium-os:25468, chromium-os:25466 TEST=Ran cros_generate_breakpad_symbols on 32/64-bit executables Change-Id: I15f5115585b3ed54ca7ae7b631216285baef8580 Reviewed-on: https://gerrit.chromium.org/gerrit/14835 Tested-by: Michael Krebs <mkrebs@chromium.org> Reviewed-by: David James <davidjames@chromium.org> Commit-Ready: Michael Krebs <mkrebs@chromium.org>
237 lines
7.1 KiB
Bash
Executable File
237 lines
7.1 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.
|
|
#
|
|
|
|
# --- BEGIN COMMON.SH BOILERPLATE ---
|
|
# Load common CrOS utilities. Inside the chroot this file is installed in
|
|
# /usr/lib/crosutils. Outside the chroot we find it relative to the script's
|
|
# location.
|
|
find_common_sh() {
|
|
local common_paths=(/usr/lib/crosutils $(dirname "$(readlink -f "$0")"))
|
|
local path
|
|
|
|
SCRIPT_ROOT=
|
|
for path in "${common_paths[@]}"; do
|
|
if [ -r "${path}/common.sh" ]; then
|
|
SCRIPT_ROOT=${path}
|
|
break
|
|
fi
|
|
done
|
|
}
|
|
|
|
find_common_sh
|
|
. "${SCRIPT_ROOT}/common.sh" || { echo "Unable to load common.sh"; exit 1; }
|
|
# --- END COMMON.SH BOILERPLATE ---
|
|
|
|
# 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."
|
|
|
|
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 64-bit ELF file.
|
|
function is_64b_elf() {
|
|
local elf="$1"
|
|
file "${elf}" | grep -q "ELF 64-bit"
|
|
}
|
|
|
|
# Verify the file given is an ELF file that dump_syms can handle. A 32-bit
|
|
# dump_syms cannot dump a 64-bit ELF file, and vice versa.
|
|
function verify_not_mismatched_elf() {
|
|
local elf="$1"
|
|
if [ ${DUMP_SYMS_IS_64BIT} -ne 0 ]; then
|
|
if ! is_64b_elf "${elf}"; then
|
|
warn "Not dumping symbols for file ${elf} because it is not 64-bit"
|
|
return 1
|
|
fi
|
|
else
|
|
if is_64b_elf "${elf}"; then
|
|
warn "Not dumping symbols for file ${elf} because it is 64-bit"
|
|
return 1
|
|
fi
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# 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}")"
|
|
# 32-bit dump_syms cannot dump a 64-bit ELF file, and vice versa
|
|
verify_not_mismatched_elf "${text_file}" || return 1
|
|
# Dump symbols as root in order to read all files.
|
|
if ! sudo "${DUMP_SYMS}" "${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}" "${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 [ "${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
|
|
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."
|
|
|
|
case "$(portageq-${FLAGS_board} envvar ARCH)" in
|
|
amd64)
|
|
echo "Detected amd64 board.."
|
|
DUMP_SYMS="/build/${FLAGS_board}/usr/bin/dump_syms"
|
|
DUMP_SYMS_IS_64BIT=1
|
|
;;
|
|
*)
|
|
DUMP_SYMS="dump_syms"
|
|
DUMP_SYMS_IS_64BIT=0
|
|
esac
|
|
|
|
echo "Using dump_sys: $DUMP_SYMS"
|
|
|
|
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 [ ! -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 "$@"
|