This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: [PATCH] Add -### option


At 4:33 PM -0800 10/29/01, Zack Weinberg wrote:

>As a vaguely related thing: I was contemplating, not so long ago, a mode
>for the driver where it would run gdb on cc1 for you.  I got stuck because
>as far as I know there is no way to set the debuggee's command line arguments
>from gdb's command line.  Your script sounds like it solves this - how?

There were two ways to do this, both involve using a gdb set args command:

1. Place a set args command in a (local) .gdbinit script in the 
current directory assuming that's where you're debugging from.  Gdb 
will always search the cwd for a .gdbinit as well as your home 
directory.

2. Place a set args in a file and use the gdb -command command line 
option which sources in the file just like it would a local .gdbinit).

Form 2 is what I use because I don't have to worry about clobbering a 
previous local .gdbinit (like the one in the gcc object directory). 
FWIW, I've enclosed my script (shown below).  I've extracted it from 
my bash startup environment scripts.  I think it's stand-alone enough 
to run outside that environment but I've never tried it that way.

Ira

PS: Forgive me if anyone is getting this message twice.  I sent it 
with the script as an enclosure from my OS9 machine (where I do mail) 
and the email bounced.  I think it's because my emailer (Eudora) 
compressed the enclosure in an "unacceptable" form (for the 
receivers).  It was mime type application/mac-binhex40.  Just to be 
save this time I stuck it as aprt of this email.

-----------------------------------------------------------------------------------

#
## 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
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]