[PATCH] Add -### option
Ira Ruben
ira@apple.com
Tue Nov 13 15:03:00 GMT 2001
At 5:15 PM -0700 11/19/01, Tom Tromey wrote:
>My `gdb --args' patch is very close to going in. It just needs one
>more approval. I have most of the gcc patch written too, but I
>haven't had the time or the need to finish it yet. Soon you'll be
>able to do this:
>
> gcc --debug-program=jc1 ... all kinds of stuff ...
I'll look forward to that :-) In the meantime, see below...
>Ira> FWIW, and just in case you're interested, I've enclosed my latest
>Ira> version of debug_gcc bash script (which is where I use the -###).
>Ira> It will work for debugging the driver or the compiler.
>
>Ira> (This file must be converted with BinHex 4.0)
>
>I can't read this. Isn't this a Mac-specific format?
Arrrrgggghhhh, emailers :-( I am using Mac Eudora and constantly
forget that its enclosures don't work for everyone (indeed the email
to gcc-patches bounced). Although this makes for a long message
(sorry), below is the script that didn't make it through as the
enclosure.
Ira
=========================================================================================
#!/usr/bin/env bash
#
## This script defines the following two commands:
##
## debug_gcc cc - a command for debugging gcc driver or compiler
## debug_gcc_help - how to use debug_gcc
##
## Basically what debug_gcc does when debugging the driver is pass
all the compiler
## arguments on to gdb through gdb's -command option using a file
containing a gdb
## set args command. It's the same for the compiler except that the set args
## command consists of the arguments passed to the compiler from the driver.
##
## The debug_gcc command contains options to save and/or echo the set
args file,
## adding a gdb dir command, --help to invoke debug_gcc_help, and of course
## whether you want to debug the driver or compiler.
#
# Ira L. Ruben
# Copyright Apple Computer, Inc. 2000-2001
# Last updated 11/19/01
#----------------------------------------------------------------------------------------#
#
## Help info for the debug_gcc function
#
debug_gcc_help()
{
echo
echo "debug_gcc cc [-Bdir/] [-cpp|-driver]
[--dir=dir1:dir2:...:dirN | --dir=name]"
echo " [-ver=n] [--save-commands] [--echo args | dir
| all] [--help]"
echo " cc-options ..."
echo
echo "cc The compiler to invoke. Note that
this MUST be the"
echo " first argument."
echo
echo "-Bdir/ Specifies where to find the cc1*
compiler. Normally"
echo " this may be omitted unless
debugging a specific"
echo " compiler. Since cc must be the
first argument the"
echo " -B is recognized as a compiler
option thus allowing"
echo " a macro to be defined to passed for cc."
echo
echo "-cpp Debug the preprocessor (or cpp-precomp)."
echo
echo "-driver Debug the driver. Either -cpp or
-driver but not both"
echo " may be specified. If neither are
specified then the"
echo " compiler phase is to be debugged
(e.g., cc1plus)."
echo
echo "-ver=n Version of gcc being used if -cpp
not specified. This"
echo " can be 2 or 3. See Notes [2],
[3], and [4] below."
echo
echo "--echo args | dir | all Echo the gdb set args command
written to the command"
echo " file, or the gdb dir command, or
echo both of them."
echo
echo "--dir=dir1:dir2:...:dirN A list of directories for gdb
that will be placed in"
echo " a gdb dir command placed in the
command file."
echo
echo "--dir=name Alternative way to specify the
gdb dir paths. The"
echo " name can either be a filename
containing a line of"
echo " paths separated by colons (like
the explicit previous"
echo " form) OR it can be an environment
variable similarly"
echo " defined with the directory paths.
It is an error for"
echo " the name to be both an
environment variable and a"
echo " filename."
echo
echo "--help Only display this help
information. This can be"
echo " specified in place of the cc."
echo
echo "--save-commands Do not delete command file
(\"debug_gcc_command_file\")."
echo " Setting environment variable
SAVE_COMMANDS to 1 can"
echo " be used in place of --save-commands."
echo
echo
echo "Note [1]: If the command file \"debug_gcc_command_file\"
already exists in the"
echo " current directory when this script is run it is renamed to"
echo " \"debug_gcc_command_file-previous\". When you
exit gdb the original"
echo " debug_gcc_command_file is restored. This is only
mentioned in case"
echo " for some reason you don't exit gdb cleanly."
echo
echo "Note [2]: Gcc 3.x has an integrated preprocessor. Thus
-cpp implies that"
echo " a -save-temps will be added to debug the
stand-alone preprocessor,"
echo " cpp0. For debugging the compiler itself,
including the integrated"
echo " preprocessor, omit the -cpp option."
echo
echo "Note [3]: Gcc 2.x always uses a separate preprocessor and
thus the -cpp is"
echo " always required to debug it. Further, the script
needs to know when"
echo " you want to debug the compiler since it must add
a -save-temps to the"
echo " command to save the temporary file for the
compiler input. Thus a"
echo " -ver=2 is required when debugging a gcc 2.x
compiler. As stated in"
echo " Note [2] this is unnecessary for gcc 3.x because
of it's integrated"
echo " preprocessor and the reason you don't want to add
a -save-temps when"
echo " debugging a gcc 3.x compiler is that implies a
different behavior of"
echo " the compiler (i.e., invoking cpp0 and then the
compiler instead of"
echo " just the compiler)."
echo
echo "Note [4]: The Gcc 3.x driver (at least the Apple version)
supports an option"
echo " (-###) specifically designed to support script
like this one. The"
echo " option is basically the same as -v except that
the displayed"
echo " command line is not executed (since we only need
it for gdb) and"
echo " all arguments are quoted. A -v doesn't quote the
displayed"
echo " arguments leading to possible quoting problems
passing the arguments"
echo " to gdb. Of course for Gcc 2.x you're just screwed!"
}
#
## debug_gcc cc [-Bdir/] [-cpp|-driver] [-ver=n]
[--dir=dir1:dir2:...:dirN | --dir=name]
## [--echo args | dir | all] cc-options...
##
## This script can be used to debug all phases of the gcc compiler;
driver, preprocessor,
## or gcc compiler. It invokes gdb on the appropriate component and
sets up a local
## command script (passed to gdb using its -command option) to define
all the arguments
## appropriate to that phase along with path definitions so that gdb
can access the
## compiler source.
##
## If not debugging the driver, the script will add a -v (and
-save-temps for gcc
## 2.x) option to the command line to allow it to capture the
phases's tool name
## (e.g., cc1plus) and all the arguments passed to that phase. The
tool name is
## what's passed to gdb. The arguments are used to build a SET args
gdb command
## which is placed in a command file generated into the current directory. The
## command file is passed to gdb to execute when gdb is invoked by the script.
##
## Debugging the driver is similar to debugging the preprocessor or
compiler phases
## except the command line use is basically the one passed to the
script minus the
## script's own arguments. Again we have the tool name (e.g., cc)
and its arguments
## for building the command file and invoking gdb.
##
## This script also allows you to specify a set of directory paths
for gdb to use
## through a gdb dir command that would be added to the command file.
##
## Note [1]: If the command file "debug_gcc_command_file" already exists in the
## current directory when this script is run it is renamed to
## "debug_gcc_command_file-previous". When you exit gdb the original
## debug_gcc_command_file is restored. This is only
mentioned in case
## for some reason you don't exit gdb cleanly.
##
## Note [2]: Gcc 3.x has an integrated preprocessor. Thus -cpp implies that
## a -save-temps will be added to debug the stand-alone preprocessor,
## cpp0. For debugging the compiler itself, including the integrated
## preprocessor, omit the -cpp option.
##
## Note [3]: Gcc 2.x always uses a separate preprocessor and thus the -cpp is
## always required to debug it. Further, the script needs
to know when
## you want to debug the compiler since it must add a
-save-temps to the
## command to save the temporary file for the compiler input. Thus a
## -ver=2 is required when debugging a gcc 2.x compiler.
As stated in
## Note [2] this is unnecessary for gcc 3.x because of it's
integrated
## preprocessor and the reason you don't want to add a
-save-temps when
## debugging a gcc 3.x compiler is that implies a different
behavior of
## the compiler (i.e., invoking cpp0 and then the compiler instead of
## just the compiler).
##
## Note [4]: The Gcc 3.x driver (at least the Apple version) supports
an option"
## (-###) specifically designed to support script like this one. The
## option is basically the same as -v except that the displayed"
## command line is not executed (since we only need it for gdb) and"
## all arguments are quoted. A -v doesn't quote the displayed"
## arguments leading to possible quoting problems passing
the arguments"
## to gdb. Of course for Gcc 2.x you're just screwed!"
##
## Options: Must precede any of the gcc command lines options for the compiler.
##
## cc The compiler to invoke. Note that
this MUST be the
## first argument.
##
## -Bdir/ Specifies where to find the cc1*
compiler. Normally
## this may be omitted unless debugging a specific
## compiler. Since cc must be the first
argument the
## -B is recognized as a compiler option
thus allowing
## a macro to be defined to passed for cc.
##
## -cpp Debug the preprocessor (or cpp-precomp).
##
## -driver Debug the driver. Either -cpp or
-driver but not both
## may be specified. If neither are
specified then the
## compiler phase is to be debugged
(e.g., cc1plus).
##
## -ver=n Version of gcc being used if -cpp not
specified. This
## can be 2 or 3. See Notes [2], [3],
and [4] above.
##
## --echo args | dir | all Echo the gdb set args command written
to the command
## file, or the gdb dir command, or echo
both of them.
##
## --dir=dir1:dir2:...:dirN A list of directories for gdb that
will be placed in
## a gdb dir command placed in the command file.
##
## --dir=name Alternative way to specify the gdb
dir paths. The name can
## either be a filename containing a
line of paths separated
## by colons (like the explicit previous
form) OR it can
## be an environment variable similarly
defined with the
## directory paths. It is an error for
the name to be both
## an environment variable and a filename.
##
## --help Only display this help information.
This can be
## specified in place of the cc.
##
## --save-commands Do not delete command file
("debug_gcc_command_file").
## Setting environment variable SAVE_COMMANDS to 1
## can be used in place of --save-commands.
##
## Any script option that is not one of the above is assumed to be
the start of the
## compiler options.
#
debug_gcc()
{
declare -i done=0 shift_cnt=0 cpp=0 driver=0 previous=0 ver=3
status cc_args_index=0
local arg next_arg= cc= objdir= dir= dir1= yn= saw_dir= alius echo= v="-v"
local save_temps=
local line= tool= args=
local save=0 command_file=debug_gcc_command_file
local -a cc_args
 Â
if [ $# -eq 0 ]; then
  debug_gcc_help
  return 0
fi
 Â
if [ "$1" != "--help" ] && [ "$1" != "-help" ] && [ "$1" != "-h" ]; then
  cc=$1
  shift
fi
 Â
for arg; do
case $next_arg in
-dir | --dir)
dir="$arg"
saw_dir="$next_arg"
next_arg=
shift_cnt=$shift_cnt+2
;;
-echo | --echo)
   echo="$arg"
next_arg=
shift_cnt=$shift_cnt+2
   ;;
-ver | --ver)
   ver=$arg
shift_cnt=$shift_cnt+2
   ;;
*)
case $arg in
    -help | --help | -h)
       debug_gcc_help
   return 0
   ;;
-cpp | --cpp)
   cpp=1
   shift_cnt=$shift_cnt+1
   ;;
-driver | --driver)
   driver=1
   shift_cnt=$shift_cnt+1
   ;;
-echo=* | --echo=*)
   echo=`echo $arg | sed -e 's/-*echo=//'`
   shift_cnt=$shift_cnt+1
   ;;
-echo | --echo)
   next_arg=$arg
   ;;
     -dir=* | --dir=*)
        dir=`echo $arg | sed -e 's/-*dir=//'`
        saw_dir=`echo $arg | sed -e 's/\(-*dir\).*$/\1/'`
        shift_cnt=$shift_cnt+1
     ;;
  -dir | --dir)
     next_arg=$arg
     ;;
  -save-commands | --save-commands)
     save=1
   shift_cnt=$shift_cnt+1
     ;;
  -ver=* | --ver=*)
        ver=`echo $arg | sed -e 's/-*ver=//'`
        shift_cnt=$shift_cnt+1
        ;;
  -B*)
     cc="$cc $arg"
     shift_cnt=$shift_cnt+1
     ;;
     *)
        next_arg=
        done=1
        ;;
        esac
esac
if [ $done != 0 ]; then
break
fi
done
 Â
shift $shift_cnt
 Â
# See if the use explicitly specified -v. If so we won't need to
add it when
# we need to generate the command lines.
 Â
for arg; do
if [ "$arg" = "-v" ]; then
v=
break
fi
done
Â
if [ $driver -ne 0 ] && [ $cpp -ne 0 ]; then
  echo "What do you want to debug? Driver or preprocessor. You
can't do both!"
  return 1
fi
 Â
if [ "$echo" != "" ] && \
[ "$echo" != "dir" ] && \
[ "$echo" != "args" ] && \
[ "$echo" != "all" ]; then
echo "Invalid --echo specification: $echo"
return 1
fi
 Â
if [ $ver != 3 -a $ver -ne 2 ]; then
echo "Invalid compiler version specified (2 or 3 expected): $ver"
return 1
fi
 Â
if [ "$dir" != "" ] && [ "`echo $dir | sed -e '/:/D'`" != "" ]; then
  if [ -f "$dir" ]; then
  if [ "`eval echo $\`echo $dir\``" != "" ]; then
     echo "$dir is ambiguous -- it's a valid filename and
a valid environment variable"
     return 1
  fi
  dir="`cat \"$dir\"`"
  else
  dir="`eval echo $\`echo $dir\``"
  fi
fi
 Â
if [ "${dir:${#dir}-1:1}" = ":" ]; then
dir="${dir:0:${#dir}-1}"
fi
 Â
if [ "$saw_dir" != "" ] && [ "$dir" = "" ]; then
  while [ "$yn" != "y" ] && [ "$yn" != "n" ]; do
  echo -n "$saw_dir" 'specified which evaluated to null --
do you accept this ? (y,n) '
  read -e yn;
  yn="${yn:0:1}"
  done
  if [ "$yn" = "n" ]; then
  return 1
  fi
fi
 Â
if [ "$cc" = "" ]; then
  echo "No compiler specifed (see --help for syntax)"
  return 0
fi
 Â
#
# If the command line specified a compiler name that was actually
an alias then
# we need to get the actual tool to which that name is aliased.
#
alius="`alias \"$cc\" 2> /dev/null`"
if [ $? -eq 0 ]; then
cc="`echo \"$alius\" | sed -e \"s/alias .*='//\" -e \"s/'\$//\"`"
fi
 Â
#
# The gcc 3.x drive supports -###, after I added it :-) It will cause
# the driver to simply do a -v output without executing the command.
# It will also quote all the arguments since -v normally doesn't do that
# and we lose what needs to be quoted if we don't do this. Of course for
# gcc 2.x you're screwed. Do have any pathnames that need quoting.
#
if [ $ver -eq 2 ]; then
save_temps="-save-temps"
elif [ $driver -eq 0 ]; then
cc_args[$((cc_args_index++))]='-###'
fi
 Â
#
# Remove possible -pipe argument. Must do this in $@ to preserve quoting.
#
if [ $driver -ne 0 ]; then
for arg; do
if [ "$arg" != "-pipe" ]; then
cc_args[$((cc_args_index++))]="\"$arg\""
fi
done
else
for arg; do
if [ "$arg" != "-pipe" ]; then
cc_args[$((cc_args_index++))]="$arg"
fi
done
fi
 Â
if false; then
  echo '$cc =' $cc
  echo '$cpp =' $cpp
  echo '$driver =' $driver
  echo '$dir =' $dir
  echo '$echo =' $echo
  echo '$objdir =' $objdir
  echo '$save =' $save
  echo '$v =' $v
  echo '$ver =' $ver
  echo '$@ =' $@
  return 1
fi
#
# Set the appropriate command line to use (driver line,
preprocessor line, or c/c++
# compiler line) depending on the script options. The line
allows us to extract the
# tool name that is invoked and all the arguments that follow.
The tool is what
# is passed to gdb to debug. The arguments are used to build a
set args gdb
# command for a local -command file.
#
if [ $driver -ne 0 ]; then
  #
# If debugging the driver, the command line is obviously all
the script's command
# line options minus the ones specific to the script.
#
  line="$cc ""${cc_args[@]}"
  tool="`echo $line | sed -e 's/^[ ]*\([^ ]*\)\(.*\)$/\1/'`"
  if [ "$tool" = "" ]; then
  echo "Could not find driver name (?)"
  return 1
  fi
else
#
# Compile program and save the -v output in a temp file that
we can grep for
# the prerocessor line or c/c++ compiler line. If the user exlicitly
# specified -v then we don't have to. But if we do then we
must remove it
# from the gdb args list. In other words the args list only
has the -v if
# the user explicitly specified it.
#
  $cc "${cc_args[@]}" $v -c $save_temps 2> /tmp/dbg.$$
  status=$?
  if [ $status -gt 1 ]; then
  echo "Unexpected status returned from compilation: $status"
  more /tmp/dbg.$$
  return 1
  fi
 Â
# ignore any compile-time errors
 Â
  if false; then
  echo '##############' /tmp/dbg.$$ '##############'
  more /tmp/dbg.$$
  return 1
fi
if [ $cpp -ne 0 ]; then
line="`cat /tmp/dbg.$$ | grep [-]D__GNUC__`"
tool="`echo $line | sed -e 's/^[ ]*\([^ ]*\)\(.*\)$/\1/'`"
if [ "$tool" = "" ]; then
echo "Could not find preprocessor name in the -v
output (in /tmp/dbg.$$)"
return 1
fi
else
#line="`cat /tmp/dbg.$$ | grep [-]o[\ ] | grep --invert-match /as`"
#line="`cat /tmp/dbg.$$ | grep [-]o[\ ] | grep .*cc1.* `"
line="`cat /tmp/dbg.$$ | grep .*cc1.*`"
tool="`echo $line | sed -e 's/^[ ]*\([^ ]*\).*$/\1/'`"
if [ "$tool" = "" ]; then
echo "Could not find compiler name in the -v output
(in /tmp/dbg.$$)"
return 1
fi
# do -version first so -v removal doesn't screw it up.
line="`echo \"$line\" | sed -e 's/-version//'`"
if [ "$v" = "-v" ]; then
line="`echo \"$line\" | sed -e 's/-v//'`"
fi
# remove null but quoted arguments...
line="`echo \"$line\" | sed -e 's/\"\"//g'`"
fi
rm -f /tmp/dbg.$$ # don't need this any more
fi
 Â
#
# Once the tool name is known and we have the appropriate command
line from it we
# can extract all the arguments we'll need to build the gdb set
args command for the
# -command file.
#
# Note, the original line (commented out below) blows in sed
apparently when $line
# is more than 1098 characters. The second one doesn't. Go figure!
#
#args="`echo $line | sed -e 's,^[ ]*'"$tool"'[ ]*\(.*\)$,\1,'`"
args="`echo \"$line\" | sed -e 's,'\"$tool\"',,'`"
 Â
#
# At last we got all of what we were after; tool and its
arguments. Create a
# -command file in the current directory containing a set args to
define the
# tools arguments.
#
 Â
if [ $save -eq 0 ] && [ -e $command_file ] && [ "$SAVE_COMMANDS"
!= "1" ]; then
  mv $command_file ${command_file}-previous
  previous=1
fi
 Â
if [ "$args" != "" ];then
  echo "set args $args" > $command_file # set args arguments...
  if [ "$echo" = "args" ] || [ "$echo" = "all" ]; then
  echo "$command_file: set args $args"
  fi
fi
 Â
#
# If the --dir script options was specified add it to the command
file too as a
# dir gdb command. The --dir arguments are defines as being in
the syntax that
# gdb expects.
#
if [ "$dir" != "" ]; then
  echo "dir $dir" >> $command_file # dir all the useful
compiler directories
  if [ "$echo" = "dir" ] || [ "$echo" = "all" ]; then
  echo "$command_file: dir $dir"
  fi
fi
 Â
#
# Finally we can invoke gdb...
#
if [ "$echo" != "" ]; then
  echo "gdb -command $command_file $tool"
fi
gdb -command $command_file "$tool" # debug that sucker
 Â
#
# Delete the command file and rename any previous one (unless
-save-commands
# was specified).
#
if [ $save -eq 0 ] && [ "$SAVE_COMMANDS" != "1" ]; then
rm -f $command_file # now we don't need
this any more
if [ $previous -ne 0 ]; then
mv ${command_file}-previous $command_file
fi
fi
}
More information about the Gcc-patches
mailing list