1#!/usr/bin/env bash 2# Wrapper around gcc to tweak the output in various ways when running 3# the testsuite. 4 5# Copyright (C) 2010-2023 Free Software Foundation, Inc. 6# This program is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 3 of the License, or 9# (at your option) any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with this program. If not, see <http://www.gnu.org/licenses/>. 18 19# This program requires gdb and objcopy in addition to gcc. 20# The default values are gdb from the build tree and objcopy from $PATH. 21# They may be overridden by setting environment variables GDB and OBJCOPY 22# respectively. Note that GDB should contain the gdb binary as well as the 23# -data-directory flag, e.g., "foo/gdb -data-directory foo/data-directory". 24# We assume the current directory is either $obj/gdb or $obj/gdb/testsuite. 25# 26# Example usage: 27# 28# bash$ cd $objdir/gdb/testsuite 29# bash$ runtest \ 30# CC_FOR_TARGET="/bin/bash $srcdir/gdb/contrib/cc-with-tweaks.sh ARGS gcc" \ 31# CXX_FOR_TARGET="/bin/bash $srcdir/gdb/contrib/cc-with-tweaks.sh ARGS g++" 32# 33# For documentation on Fission and dwp files: 34# http://gcc.gnu.org/wiki/DebugFission 35# http://gcc.gnu.org/wiki/DebugFissionDWP 36# For documentation on index files: info -f gdb.info -n "Index Files" 37# For information about 'dwz', see the announcement: 38# http://gcc.gnu.org/ml/gcc/2012-04/msg00686.html 39# (More documentation is to come.) 40 41# ARGS determine what is done. They can be: 42# -Z invoke objcopy --compress-debug-sections 43# -z compress using dwz 44# -m compress using dwz -m 45# -i make an index (.gdb_index) 46# -n make a dwarf5 index (.debug_names) 47# -p create .dwp files (Fission), you need to also use gcc option -gsplit-dwarf 48# -l creates separate debuginfo files linked to using .gnu_debuglink 49# If nothing is given, no changes are made 50 51myname=cc-with-tweaks.sh 52mydir=`dirname "$0"` 53 54if [ -z "$GDB" ] 55then 56 if [ -f ./gdb ] 57 then 58 GDB="./gdb -data-directory data-directory" 59 elif [ -f ../gdb ] 60 then 61 GDB="../gdb -data-directory ../data-directory" 62 elif [ -f ../../gdb ] 63 then 64 GDB="../../gdb -data-directory ../../data-directory" 65 else 66 echo "$myname: unable to find usable gdb" >&2 67 exit 1 68 fi 69fi 70 71OBJCOPY=${OBJCOPY:-objcopy} 72READELF=${READELF:-readelf} 73 74DWZ=${DWZ:-dwz} 75DWP=${DWP:-dwp} 76 77# shellcheck disable=SC2206 # Allow word splitting. 78STRIP_ARGS_STRIP_DEBUG=(${STRIP_ARGS_STRIP_DEBUG:---strip-debug}) 79# shellcheck disable=SC2206 # Allow word splitting. 80STRIP_ARGS_KEEP_DEBUG=(${STRIP_ARGS_KEEP_DEBUG:---only-keep-debug}) 81 82have_link=unknown 83next_is_output_file=no 84output_file=a.out 85 86want_index=false 87index_options="" 88want_dwz=false 89want_multi=false 90want_dwp=false 91want_objcopy_compress=false 92want_gnu_debuglink=false 93 94while [ $# -gt 0 ]; do 95 case "$1" in 96 -Z) want_objcopy_compress=true ;; 97 -z) want_dwz=true ;; 98 -i) want_index=true ;; 99 -n) want_index=true; index_options=-dwarf-5;; 100 -m) want_multi=true ;; 101 -p) want_dwp=true ;; 102 -l) want_gnu_debuglink=true ;; 103 *) break ;; 104 esac 105 shift 106done 107 108if [ "$want_index" = true ] 109then 110 if [ -z "$GDB_ADD_INDEX" ] 111 then 112 if [ -f $mydir/gdb-add-index.sh ] 113 then 114 GDB_ADD_INDEX="$mydir/gdb-add-index.sh" 115 else 116 echo "$myname: unable to find usable contrib/gdb-add-index.sh" >&2 117 exit 1 118 fi 119 fi 120fi 121 122for arg in "$@" 123do 124 if [ "$next_is_output_file" = "yes" ] 125 then 126 output_file="$arg" 127 next_is_output_file=no 128 continue 129 fi 130 131 # Poor man's gcc argument parser. 132 # We don't need to handle all arguments, we just need to know if we're 133 # doing a link and what the output file is. 134 # It's not perfect, but it seems to work well enough for the task at hand. 135 case "$arg" in 136 "-c") have_link=no ;; 137 "-E") have_link=no ;; 138 "-S") have_link=no ;; 139 "-o") next_is_output_file=yes ;; 140 esac 141done 142 143if [ "$next_is_output_file" = "yes" ] 144then 145 echo "$myname: Unable to find output file" >&2 146 exit 1 147fi 148 149if [ "$have_link" = "no" ] 150then 151 "$@" 152 exit $? 153fi 154 155output_dir="${output_file%/*}" 156[ "$output_dir" = "$output_file" ] && output_dir="." 157 158"$@" 159rc=$? 160[ $rc != 0 ] && exit $rc 161if [ ! -f "$output_file" ] 162then 163 echo "$myname: Internal error: $output_file missing." >&2 164 exit 1 165fi 166 167get_tmpdir () 168{ 169 subdir="$1" 170 if [ "$subdir" = "" ]; then 171 subdir=.tmp 172 fi 173 174 tmpdir=$(dirname "$output_file")/"$subdir" 175 mkdir -p "$tmpdir" 176} 177 178if [ "$want_objcopy_compress" = true ]; then 179 $OBJCOPY --compress-debug-sections "$output_file" 180 rc=$? 181 [ $rc != 0 ] && exit $rc 182fi 183 184if [ "$want_index" = true ]; then 185 get_tmpdir 186 mv "$output_file" "$tmpdir" 187 output_dir=$(dirname "$output_file") 188 189 # Copy .dwo file alongside, to fix gdb.dwarf2/fission-relative-dwo.exp. 190 # Use copy instead of move to not break 191 # rtf=gdb.dwarf2/fission-absolute-dwo.exp. 192 dwo_pattern="$output_dir/*.dwo" 193 for f in $dwo_pattern; do 194 if [ "$f" = "$dwo_pattern" ]; then 195 break 196 fi 197 cp "$f" "$tmpdir" 198 done 199 200 tmpfile="$tmpdir/$(basename $output_file)" 201 # Filter out these messages which would stop dejagnu testcase run: 202 # echo "$myname: No index was created for $file" 1>&2 203 # echo "$myname: [Was there no debuginfo? Was there already an index?]" 1>&2 204 GDB=$GDB $GDB_ADD_INDEX $index_options "$tmpfile" 2>&1 \ 205 | grep -v "^${GDB_ADD_INDEX##*/}: " >&2 206 rc=${PIPESTATUS[0]} 207 mv "$tmpfile" "$output_file" 208 rm -f "$tmpdir"/*.dwo 209 [ $rc != 0 ] && exit $rc 210fi 211 212if [ "$want_dwz" = true ]; then 213 # Validate dwz's result by checking if the executable was modified. 214 cp "$output_file" "${output_file}.copy" 215 $DWZ "$output_file" > /dev/null 216 cmp "$output_file" "$output_file.copy" > /dev/null 217 cmp_rc=$? 218 rm -f "${output_file}.copy" 219 220 case $cmp_rc in 221 0) 222 echo "$myname: dwz did not modify ${output_file}." 223 exit 1 224 ;; 225 1) 226 # File was modified, great. 227 ;; 228 *) 229 # Other cmp error, it presumably has already printed something on 230 # stderr. 231 exit 1 232 ;; 233 esac 234elif [ "$want_multi" = true ]; then 235 get_tmpdir 236 dwz_file=$tmpdir/$(basename "$output_file").dwz 237 # Remove the dwz output file if it exists, so we don't mistake it for a 238 # new file in case dwz fails. 239 rm -f "$dwz_file" 240 241 cp $output_file ${output_file}.alt 242 $DWZ -m "$dwz_file" "$output_file" ${output_file}.alt > /dev/null 243 rm -f ${output_file}.alt 244 245 # Validate dwz's work by checking if the expected output file exists. 246 if [ ! -f "$dwz_file" ]; then 247 echo "$myname: dwz file $dwz_file missing." 248 exit 1 249 fi 250fi 251 252if [ "$want_dwp" = true ]; then 253 dwo_files=$($READELF -wi "${output_file}" | grep _dwo_name | \ 254 sed -e 's/^.*: //' | sort | uniq) 255 rc=0 256 if [ -n "$dwo_files" ]; then 257 $DWP -o "${output_file}.dwp" ${dwo_files} > /dev/null 258 rc=$? 259 [ $rc != 0 ] && exit $rc 260 rm -f ${dwo_files} 261 fi 262fi 263 264if [ "$want_gnu_debuglink" = true ]; then 265 # Based on gdb_gnu_strip_debug. 266 267 # Gdb looks for the .gnu_debuglink file in the .debug subdirectory 268 # of the directory of the executable. 269 get_tmpdir .debug 270 271 stripped_file="$tmpdir"/$(basename "$output_file").stripped 272 debug_file="$tmpdir"/$(basename "$output_file").debug 273 274 # Create stripped and debug versions of output_file. 275 strip "${STRIP_ARGS_STRIP_DEBUG[@]}" "${output_file}" \ 276 -o "${stripped_file}" 277 rc=$? 278 [ $rc != 0 ] && exit $rc 279 strip "${STRIP_ARGS_KEEP_DEBUG[@]}" "${output_file}" \ 280 -o "${debug_file}" 281 rc=$? 282 [ $rc != 0 ] && exit $rc 283 284 # The .gnu_debuglink is supposed to contain no leading directories. 285 link=$(basename "${debug_file}") 286 287 ( 288 # Temporarily cd to tmpdir to allow objcopy to find $link 289 cd "$tmpdir" || exit 1 290 291 # Overwrite output_file with stripped version containing 292 # .gnu_debuglink to debug_file. 293 $OBJCOPY --add-gnu-debuglink="$link" "${stripped_file}" \ 294 "${output_file}" 295 rc=$? 296 [ $rc != 0 ] && exit $rc 297 ) 298fi 299 300exit $rc 301