xref: /netbsd-src/external/gpl3/gcc/dist/contrib/compare-debug (revision b1e838363e3c6fc78a55519254d99869742dd33c)
14fee23f9Smrg#! /bin/sh
24fee23f9Smrg
34fee23f9Smrg# Compare stripped copies of two given object files.
44fee23f9Smrg
5*b1e83836Smrg# Copyright (C) 2007, 2008, 2009, 2010, 2012, 2020 Free Software Foundation
64fee23f9Smrg# Originally by Alexandre Oliva <aoliva@redhat.com>
74fee23f9Smrg
84fee23f9Smrg# This file is part of GCC.
94fee23f9Smrg
104fee23f9Smrg# GCC is free software; you can redistribute it and/or modify it under
114fee23f9Smrg# the terms of the GNU General Public License as published by the Free
124fee23f9Smrg# Software Foundation; either version 3, or (at your option) any later
134fee23f9Smrg# version.
144fee23f9Smrg
154fee23f9Smrg# GCC is distributed in the hope that it will be useful, but WITHOUT
164fee23f9Smrg# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
174fee23f9Smrg# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
184fee23f9Smrg# License for more details.
194fee23f9Smrg
204fee23f9Smrg# You should have received a copy of the GNU General Public License
214fee23f9Smrg# along with GCC; see the file COPYING3.  If not see
224fee23f9Smrg# <http://www.gnu.org/licenses/>.
234fee23f9Smrg
244fee23f9Smrgrm='rm -f'
254fee23f9Smrg
264fee23f9Smrgcase $1 in
274fee23f9Smrg-p | --preserve)
284fee23f9Smrg  rm='echo preserving'
294fee23f9Smrg  shift
304fee23f9Smrg  ;;
314fee23f9Smrgesac
324fee23f9Smrg
334fee23f9Smrgif test $# != 2; then
344fee23f9Smrg  echo 'usage: compare-debug file1.o file2.o' >&2
354fee23f9Smrg  exit 1
364fee23f9Smrgfi
374fee23f9Smrg
384fee23f9Smrgif test ! -f "$1"; then
394fee23f9Smrg  echo "$1" does not exist >&2
404fee23f9Smrg  exit 1
414fee23f9Smrgfi
424fee23f9Smrg
434fee23f9Smrgif test ! -f "$2"; then
444fee23f9Smrg  echo "$2" does not exist >&2
454fee23f9Smrg  exit 1
464fee23f9Smrgfi
474fee23f9Smrg
484fee23f9Smrgsuf1=stripped
494fee23f9Smrgwhile test -f "$1.$suf1"; do
504fee23f9Smrg  suf1=$suf1.
514fee23f9Smrgdone
524fee23f9Smrg
534fee23f9Smrgsuf2=stripped
544fee23f9Smrgwhile test -f "$2.$suf2"; do
554fee23f9Smrg  suf2=$suf2.
564fee23f9Smrgdone
574fee23f9Smrg
584fee23f9Smrgtrap 'rm -f "$1.$suf1" "$2.$suf2"' 0 1 2 15
594fee23f9Smrg
604fee23f9Smrgcase `uname -s` in
614fee23f9SmrgDarwin)
624fee23f9Smrg  # The strip command on darwin does not remove all debug info.
634fee23f9Smrg  # Fortunately, we can use ld to do it instead.
644fee23f9Smrg  ld -S -r -no_uuid "$1" -o "$1.$suf1"
654fee23f9Smrg  ld -S -r -no_uuid "$2" -o "$2.$suf2"
664fee23f9Smrg  ;;
674fee23f9Smrg*)
684fee23f9Smrg  cp "$1" "$1.$suf1"
694fee23f9Smrg  strip "$1.$suf1"
704fee23f9Smrg
714fee23f9Smrg  cp "$2" "$2.$suf2"
724fee23f9Smrg  strip "$2.$suf2"
734fee23f9Smrg  ;;
744fee23f9Smrgesac
754fee23f9Smrg
7648fb7bfaSmrgremove_comment ()
7748fb7bfaSmrg{
7848fb7bfaSmrg  file=$1
7948fb7bfaSmrg  opts=
8048fb7bfaSmrg  for s in `objdump --section-headers "$file" | awk '{ print $2 }'`; do
8148fb7bfaSmrg    case "$s" in
8248fb7bfaSmrg    .comment*)
8348fb7bfaSmrg      opts="$opts --remove-section $s"
8448fb7bfaSmrg      ;;
8548fb7bfaSmrg    esac
8648fb7bfaSmrg  done
8748fb7bfaSmrg  [ -n "$opts" ] && objcopy $opts $file
8848fb7bfaSmrg}
8948fb7bfaSmrg
904fee23f9Smrgif cmp "$1.$suf1" "$2.$suf2"; then
914fee23f9Smrg  status=0
924fee23f9Smrgelse
934fee23f9Smrg  status=1
944fee23f9Smrg
9548fb7bfaSmrg  # Remove any .comment sections.
9648fb7bfaSmrg  if (objcopy -v) 2>&1 | grep ' --remove-section' > /dev/null \
9748fb7bfaSmrg     && (objdump --help) 2>&1 | grep ' --\[*section-\]*headers' > /dev/null; then
9848fb7bfaSmrg    remove_comment "$1.$suf1"
9948fb7bfaSmrg    remove_comment "$2.$suf2"
10048fb7bfaSmrg    if cmp "$1.$suf1" "$2.$suf2"; then
10148fb7bfaSmrg      status=0
10248fb7bfaSmrg    fi
10348fb7bfaSmrg  fi
10448fb7bfaSmrg
1054fee23f9Smrg  # Assembler-generated CFI will add an .eh_frame section for -g not
1064fee23f9Smrg  # present in -g0.  Try to cope with it by checking that an .eh_frame
1074fee23f9Smrg  # section is present in either object file, and then stripping it
1084fee23f9Smrg  # off before re-comparing.
1094fee23f9Smrg
1104fee23f9Smrg  cmd=
1114fee23f9Smrg  cmp1=
1124fee23f9Smrg  cmp2=
1134fee23f9Smrg
1144fee23f9Smrg  for t in objdump readelf eu-readelf; do
1154fee23f9Smrg    if ($t --help) 2>&1 | grep ' --\[*section-\]*headers' > /dev/null; then
1164fee23f9Smrg      cmd=$t
1174fee23f9Smrg
1184fee23f9Smrg      $cmd --section-headers "$1.$suf1" | grep '\.eh_frame' > /dev/null
1194fee23f9Smrg      cmp1=$?
1204fee23f9Smrg
1214fee23f9Smrg      $cmd --section-headers "$2.$suf2" | grep '\.eh_frame' > /dev/null
1224fee23f9Smrg      cmp2=$?
1234fee23f9Smrg
1244fee23f9Smrg      break
1254fee23f9Smrg    fi
1264fee23f9Smrg  done
1274fee23f9Smrg
1284fee23f9Smrg  # If we found .eh_frame in one but not the other, or if we could not
12948fb7bfaSmrg  # find a command to tell, or if there are LTO sections, try to strip
13048fb7bfaSmrg  # off the .eh_frame and LTO sections from both.
13148fb7bfaSmrg  if test "x$cmp1" != "x$cmp2" || test "x$cmd" = "x" ||
13248fb7bfaSmrg     $cmd --section-headers "$1.$suf1" | grep '.gnu.lto_' > /dev/null ||
13348fb7bfaSmrg     $cmd --section-headers "$2.$suf2" | grep '.gnu.lto_' > /dev/null ; then
1344fee23f9Smrg    suf3=$suf1.
1354fee23f9Smrg    while test -f "$1.$suf3"; do
1364fee23f9Smrg      suf3=$suf3.
1374fee23f9Smrg    done
1384fee23f9Smrg
1394fee23f9Smrg    suf4=$suf2.
1404fee23f9Smrg    while test -f "$2.$suf4"; do
1414fee23f9Smrg      suf4=$suf4.
1424fee23f9Smrg    done
1434fee23f9Smrg
1444fee23f9Smrg    trap 'rm -f "$1.$suf1" "$2.$suf2" "$1.$suf3" "$2.$suf4"' 0 1 2 15
1454fee23f9Smrg
14648fb7bfaSmrg    echo stripping off .eh_frame and LTO sections, then retrying >&2
14748fb7bfaSmrg
14848fb7bfaSmrg    seclist=".eh_frame .rel.eh_frame .rela.eh_frame"
14948fb7bfaSmrg    if test "x$cmd" != "x"; then
15048fb7bfaSmrg      seclist="$seclist "`{ $cmd --section-headers "$1.$suf1"; $cmd --section-headers "$2.$suf2"; } | sed -n 's,.* \(\.gnu\.lto_[^ 	]*\).*,\1,p' | sort -u`
15148fb7bfaSmrg    fi
15248fb7bfaSmrg    rsopts=`for sec in $seclist; do echo " --remove-section $sec"; done`
1534fee23f9Smrg
1544fee23f9Smrg    if (objcopy -v) 2>&1 | grep ' --remove-section' > /dev/null; then
15548fb7bfaSmrg      objcopy $rsopts "$1.$suf1" "$1.$suf3"
1564fee23f9Smrg      mv "$1.$suf3" "$1.$suf1"
1574fee23f9Smrg
15848fb7bfaSmrg      objcopy $rsopts "$2.$suf2" "$2.$suf4"
1594fee23f9Smrg      mv "$2.$suf4" "$2.$suf2"
1604fee23f9Smrg    elif (strip --help) 2>&1 | grep ' --remove-section' > /dev/null; then
1614fee23f9Smrg      cp "$1.$suf1" "$1.$suf3"
16248fb7bfaSmrg      strip $rsopts "$1.$suf3"
1634fee23f9Smrg      mv "$1.$suf3" "$1.$suf1"
1644fee23f9Smrg
1654fee23f9Smrg      cp "$2.$suf2" "$2.$suf4"
16648fb7bfaSmrg      strip $rsopts "$2.$suf4"
1674fee23f9Smrg      mv "$2.$suf4" "$2.$suf2"
1684fee23f9Smrg    else
1694fee23f9Smrg      echo failed to strip off .eh_frame >&2
1704fee23f9Smrg    fi
1714fee23f9Smrg
1724fee23f9Smrg    trap 'rm -f "$1.$suf1" "$2.$suf2"' 0 1 2 15
1734fee23f9Smrg
1744fee23f9Smrg    if cmp "$1.$suf1" "$2.$suf2"; then
1754fee23f9Smrg      status=0
1764fee23f9Smrg    else
1774fee23f9Smrg      status=1
1784fee23f9Smrg    fi
1794fee23f9Smrg  fi
1804fee23f9Smrgfi
1814fee23f9Smrg
1824fee23f9Smrg$rm "$1.$suf1" "$2.$suf2"
1834fee23f9Smrg
1844fee23f9Smrgtrap "exit $status; exit" 0 1 2 15
1854fee23f9Smrg
186*b1e83836Smrg# Replace the suffix in $1 and $2 with .*.gkd, compare them if a
187*b1e83836Smrg# single file is found by the globbing.
188*b1e83836Smrgbase1=`echo "$1" | sed '$s,\.[^.]*$,,'` gkd1=
189*b1e83836Smrgfor f in "$base1".*.gkd; do
190*b1e83836Smrg  if test "x$gkd1" != x; then
191*b1e83836Smrg    gkd1=
192*b1e83836Smrg    break
193*b1e83836Smrg  elif test -f "$f"; then
194*b1e83836Smrg    gkd1=$f
195*b1e83836Smrg  fi
196*b1e83836Smrgdone
197*b1e83836Smrgbase2=`echo "$2" | sed '$s,\.[^.]*$,,'` gkd2=
198*b1e83836Smrgfor f in "$base2".*.gkd; do
199*b1e83836Smrg  if test "x$gkd2" != x; then
200*b1e83836Smrg    gkd2=
201*b1e83836Smrg    break
202*b1e83836Smrg  elif test -f "$f"; then
203*b1e83836Smrg    gkd2=$f
204*b1e83836Smrg  fi
205*b1e83836Smrgdone
206*b1e83836Smrgif test "x$gkd1" != x || test "x$gkd2" != x; then
207*b1e83836Smrg  if cmp "${gkd1-/dev/null}" "${gkd2-/dev/null}"; then
2084fee23f9Smrg    :
2094fee23f9Smrg  else
2104fee23f9Smrg    status=$?
2114fee23f9Smrg  fi
2124fee23f9Smrgfi
2134fee23f9Smrg
2144fee23f9Smrgexit $status
215