OLD | NEW |
(Empty) | |
| 1 #!/bin/bash |
| 2 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. |
| 5 |
| 6 # Script to generate minidump symbols in the format required by |
| 7 # minidump_stackwalk to dump stack information. |
| 8 # |
| 9 # NOTE: This script must be run from the chromeos build chroot environment. |
| 10 # |
| 11 |
| 12 # Load common constants. This should be the first executable line. |
| 13 # The path to common.sh should be relative to your script's location. |
| 14 . "$(dirname "$0")/common.sh" |
| 15 |
| 16 # Script must be run inside the chroot |
| 17 restart_in_chroot_if_needed $* |
| 18 |
| 19 get_default_board |
| 20 |
| 21 # Flags |
| 22 DEFINE_string board "$DEFAULT_BOARD" "The board to build packages for." |
| 23 DEFINE_string minidump_symbol_root "" \ |
| 24 "Symbol root (defaults to /usr/lib/debug/breakpad for board)" |
| 25 DEFINE_boolean verbose ${FLAGS_FALSE} "Be verbose." |
| 26 |
| 27 DUMP_SYMS="dump_syms" |
| 28 |
| 29 CUMULATIVE_SIZE=0 |
| 30 ANY_ERRORS=0 |
| 31 |
| 32 SYM_FILE=$(mktemp "/tmp/sym.XXXX") |
| 33 ERR_FILE=$(mktemp "/tmp/err.XXXX") |
| 34 |
| 35 function cleanup() { |
| 36 rm -f "${SYM_FILE}" "${ERR_FILE}" |
| 37 } |
| 38 |
| 39 # Given path to a debug file, return its text file |
| 40 function get_text_for_debug() { |
| 41 local debug_file=$1 |
| 42 local text_dir=$(dirname ${debug_file#$DEBUG_ROOT}) |
| 43 local text_path=${SYSROOT}${text_dir}/$(basename "${debug_file}" .debug) |
| 44 echo ${text_path} |
| 45 } |
| 46 |
| 47 # Given path to a text file, return its debug file |
| 48 function get_debug_for_text() { |
| 49 local text_file=$1 |
| 50 local text_path=${text_file#${SYSROOT}} |
| 51 local debug_path=${DEBUG_ROOT}${text_path}.debug |
| 52 echo ${debug_path} |
| 53 } |
| 54 |
| 55 # Verify the file given is not a 64-bit ELF file. For now all targets |
| 56 # are 32-bit, we'll need to determine the correct bit automatically |
| 57 # once we release 64-bit versions. Allow files in /usr/lib64 to exist |
| 58 # on the image and only give warnings. |
| 59 function verify_not_64b_elf() { |
| 60 local elf="$1" |
| 61 if file "${elf}" | grep -q "ELF 64-bit"; then |
| 62 # Allow with a warning if in /usr/lib64 |
| 63 if echo "${elf}" | grep -q /usr/lib64; then |
| 64 warn "64-bit usr/lib64 file ${elf} ignored." |
| 65 else |
| 66 error "File ${elf} is a 64b executable" |
| 67 ANY_ERRORS=1 |
| 68 fi |
| 69 return 1 |
| 70 fi |
| 71 return 0 |
| 72 } |
| 73 |
| 74 # Dump given debug and text file. Returns 1 if any errors, even |
| 75 # if they can be ignored, but only sets ANY_ERRORS if the error should not |
| 76 # be ignored (and we should not proceed to upload). |
| 77 function dump_file() { |
| 78 local debug_file="$1" |
| 79 local text_file="$2" |
| 80 # 64b ELF files may be installed on the target in PERL directories |
| 81 verify_not_64b_elf "${debug_file}" || return 1 |
| 82 verify_not_64b_elf "${text_file}" || return 1 |
| 83 # Dump symbols as root in order to read all files. |
| 84 if ! sudo "${DUMP_SYMS}" "${debug_file}" "${text_file}" > "${SYM_FILE}" \ |
| 85 2> "${ERR_FILE}"; then |
| 86 # A lot of files (like kernel files) contain no debug information, do |
| 87 # not consider such occurrences as errors. |
| 88 if grep -q "file contains no debugging information" "${ERR_FILE}"; then |
| 89 warn "No symbols found for ${text_file}" |
| 90 return 1 |
| 91 fi |
| 92 error "Unable to dump symbols for ${text_file}:" |
| 93 cat "${ERR_FILE}" |
| 94 ANY_ERRORS=1 |
| 95 return 1 |
| 96 fi |
| 97 local file_id=$(head -1 ${SYM_FILE} | cut -d' ' -f4) |
| 98 local module_name=$(head -1 ${SYM_FILE} | cut -d' ' -f5) |
| 99 if [ ${FLAGS_verbose} -eq ${FLAGS_TRUE} ]; then |
| 100 # Show file upload success and symbol info for easier lookup |
| 101 info "Dumped symbols from ${text_file} for ${module_name}|${file_id}." |
| 102 fi |
| 103 # Sanity check: if we've created the same named file in the /usr/lib/debug |
| 104 # directory during the src_compile stage of an ebuild, verify our sym file |
| 105 # is the same. |
| 106 local installed_sym="${DEBUG_ROOT}"/$(basename "${text_file}").sym |
| 107 if [ -e "${installed_sym}" ]; then |
| 108 if ! diff "${installed_sym}" "${SYM_FILE}"; then |
| 109 error "${installed_sym} differ from current sym file:" |
| 110 diff "${installed_sym}" "${SYM_FILE}" |
| 111 ANY_ERRORS=1 |
| 112 return 1 |
| 113 fi |
| 114 fi |
| 115 size=$(wc -c "${SYM_FILE}" | cut -d' ' -f1) |
| 116 CUMULATIVE_SIZE=$((CUMULATIVE_SIZE + $size)) |
| 117 |
| 118 local container_dir="${FLAGS_minidump_symbol_root}/${module_name}/${file_id}" |
| 119 sudo mkdir -p "${container_dir}" |
| 120 sudo mv "${SYM_FILE}" "${container_dir}/${module_name}.sym" |
| 121 return 0 |
| 122 } |
| 123 |
| 124 # Convert the given debug file. No return value. |
| 125 function process_file() { |
| 126 local debug_file="$1" |
| 127 local text_file="$(get_text_for_debug ${debug_file})" |
| 128 if [ "${text_file##*.}" == "ko" ]; then |
| 129 # Skip kernel objects. We can't use their symbols and they sometimes |
| 130 # have objects with empty text sections which trigger errors in dump_sym. |
| 131 if [ ${FLAGS_verbose} -eq ${FLAGS_TRUE} ]; then |
| 132 info "Skipping kernel object: ${text_file}" |
| 133 fi |
| 134 return 0 |
| 135 fi |
| 136 if [ "${text_file#${AUTOTEST_ROOT}}" != "${text_file}" ]; then |
| 137 # Skip autotest files, they are not part of the image to debug |
| 138 # and some cause trouble to dump_syms because they are built |
| 139 # externally (with different build options). |
| 140 if [ ${FLAGS_verbose} -eq ${FLAGS_TRUE} ]; then |
| 141 info "Skipping autotest file: ${text_file}" |
| 142 fi |
| 143 return 0 |
| 144 fi |
| 145 if [ ! -f "${text_file}" ]; then |
| 146 # Allow files to not exist, for instance if they are in the INSTALL_MASK. |
| 147 warn "Binary does not exist: ${text_file}" |
| 148 return 0 |
| 149 fi |
| 150 |
| 151 dump_file "${debug_file}" "${text_file}" |
| 152 } |
| 153 |
| 154 function main() { |
| 155 trap cleanup EXIT |
| 156 |
| 157 # Parse command line |
| 158 FLAGS_HELP="usage: $0 [flags] [<files...>]" |
| 159 FLAGS "$@" || exit 1 |
| 160 eval set -- "${FLAGS_ARGV}" |
| 161 |
| 162 set -e |
| 163 |
| 164 [ -n "$FLAGS_board" ] || die "--board is required." |
| 165 |
| 166 SYSROOT="/build/${FLAGS_board}" |
| 167 |
| 168 if [[ -z "${FLAGS_minidump_symbol_root}" ]]; then |
| 169 FLAGS_minidump_symbol_root="${SYSROOT}/usr/lib/debug/breakpad" |
| 170 fi |
| 171 |
| 172 info "Writing minidump symbols to ${FLAGS_minidump_symbol_root}" |
| 173 |
| 174 DEBUG_ROOT="${SYSROOT}/usr/lib/debug" |
| 175 AUTOTEST_ROOT="${SYSROOT}/usr/local/autotest" |
| 176 CUMULATIVE_SIZE=0 |
| 177 |
| 178 if [ -z "${FLAGS_ARGV}" ]; then |
| 179 for debug_file in $(find "${DEBUG_ROOT}" -name \*.debug); do |
| 180 ! process_file "${debug_file}" |
| 181 done |
| 182 else |
| 183 for either_file in ${FLAGS_ARGV}; do |
| 184 either_file=${either_file#\'} |
| 185 either_file=${either_file%\'} |
| 186 if [ ! -f "${either_file}" ]; then |
| 187 error "Specified file ${either_file} does not exist" |
| 188 ANY_ERRORS=1 |
| 189 continue |
| 190 fi |
| 191 if [ "${either_file##*.}" == "debug" ]; then |
| 192 debug_file="${either_file}" |
| 193 else |
| 194 debug_file="$(get_debug_for_text ${either_file})" |
| 195 fi |
| 196 ! process_file "${debug_file}" |
| 197 done |
| 198 fi |
| 199 |
| 200 info "Generated ${CUMULATIVE_SIZE}B of debug information" |
| 201 |
| 202 [ ${ANY_ERRORS} -ne 0 ] && die "Encountered problems" |
| 203 return 0 |
| 204 } |
| 205 |
| 206 main "$@" |
OLD | NEW |