Index: buildsym.c =================================================================== RCS file: /cvs/src/src/gdb/buildsym.c,v retrieving revision 1.59 diff -u -p -u -p -r1.59 buildsym.c --- buildsym.c 1 Jan 2008 22:53:09 -0000 1.59 +++ buildsym.c 4 Jan 2008 21:26:11 -0000 @@ -44,6 +44,7 @@ #include "cp-support.h" #include "dictionary.h" #include "addrmap.h" +#include "source.h" /* Ask buildsym.h to define the vars it normally declares `extern'. */ #define EXTERN @@ -86,6 +87,7 @@ static struct obstack pending_addrmap_ob static int pending_addrmap_interesting; +static char *rewrite_subfile_path (char *name, char* dirname); static int compare_line_numbers (const void *ln1p, const void *ln2p); @@ -574,6 +576,20 @@ make_blockvector (struct objfile *objfil return (blockvector); } + +/* Workaround for IS_ABSOLUTE_PATH issue. When gdb is configured for + *ix, and we are debugging binary cross-compiled on windows, the original + IS_ABSOLUTE_PATH will always return 0. This is not good. */ +#undef IS_ABSOLUTE_PATH +#undef IS_DIR_SEPARATOR + +#define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == '\\') +/* Note that IS_ABSOLUTE_PATH accepts d:foo as well, although it is + only semi-absolute. This is because the users of IS_ABSOLUTE_PATH + want to know whether to prepend the current working directory to + a file name, which should not be done with a name like d:foo. */ +#define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]) || (((f)[0]) && ((f)[1] == ':'))) + /* Start recording information about source code that came from an included (or otherwise merged-in) source file with a different name. NAME is the name of the file (cannot be NULL), DIRNAME is @@ -583,35 +599,32 @@ void start_subfile (char *name, char *dirname) { struct subfile *subfile; + /* Rewritten NAME, typically an absolute path, that is used to detect + identical subfiles. */ + char *comparable_name; + + comparable_name = rewrite_subfile_path (name, dirname); /* See if this subfile is already known as a subfile of the current main source file. */ for (subfile = subfiles; subfile; subfile = subfile->next) { - char *subfile_name; - - /* If NAME is an absolute path, and this subfile is not, then - attempt to create an absolute path to compare. */ - if (IS_ABSOLUTE_PATH (name) - && !IS_ABSOLUTE_PATH (subfile->name) - && subfile->dirname != NULL) - subfile_name = concat (subfile->dirname, SLASH_STRING, - subfile->name, NULL); - else - subfile_name = subfile->name; + char *subfile_name = rewrite_subfile_path (subfile->name, + subfile->dirname); - if (FILENAME_CMP (subfile_name, name) == 0) + if (FILENAME_CMP (subfile_name, comparable_name) == 0) { current_subfile = subfile; - if (subfile_name != subfile->name) - xfree (subfile_name); + xfree (comparable_name); + xfree (subfile_name); return; } - if (subfile_name != subfile->name) - xfree (subfile_name); + xfree (subfile_name); } + xfree (comparable_name); + /* This subfile is not known. Add an entry for it. Make an entry for this subfile in the list of all subfiles of the current main source file. */ @@ -681,6 +694,34 @@ start_subfile (char *name, char *dirname } } +/* Subroutine of start_subfile to simplify it. + Convert NAME, DIRNAME to a form that can be used to watch for + identical subfiles. + Space for the result is malloc'd, caller must free. */ + +static char * +rewrite_subfile_path (char *name, char *dirname) +{ + char *p = name; + char *rwname; + + if (! IS_ABSOLUTE_PATH (name) + && dirname != NULL) + p = concat (dirname, SLASH_STRING, name, NULL); + + rwname = rewrite_source_path (p); + + if (rwname != NULL) + { + if (p != name) + xfree (p); + return rwname; + } + if (p != name) + return p; + return xstrdup (name); +} + /* For stabs readers, the first N_SO symbol is assumed to be the source file name, and the subfile struct is initialized using that assumption. If another N_SO symbol is later seen, immediately Index: source.c =================================================================== RCS file: /cvs/src/src/gdb/source.c,v retrieving revision 1.83 diff -u -p -u -p -r1.83 source.c --- source.c 1 Jan 2008 22:53:13 -0000 1.83 +++ source.c 4 Jan 2008 21:26:11 -0000 @@ -895,10 +895,12 @@ get_substitute_path_rule (const char *pa Return NULL if no substitution rule was specified by the user, or if no rule applied to the given PATH. */ -static char * +char * rewrite_source_path (const char *path) { - const struct substitute_path_rule *rule = get_substitute_path_rule (path); + const struct substitute_path_rule *rule = (path != NULL) ? + get_substitute_path_rule (path): + NULL; char *new_path; int from_len; @@ -999,10 +1001,11 @@ find_and_open_source (struct objfile *ob strcat (path + len, source_path + len + cdir_len); /* After $cdir */ } } - else + + if (IS_ABSOLUTE_PATH (filename)) { - /* If dirname is NULL, chances are the path is embedded in - the filename. Try the source path substitution on it. */ + /* If filename is absolute path, try the source path + substitution on it. */ char *rewritten_filename = rewrite_source_path (filename); if (rewritten_filename != NULL) Index: source.h =================================================================== RCS file: /cvs/src/src/gdb/source.h,v retrieving revision 1.9 diff -u -p -u -p -r1.9 source.h --- source.h 1 Jan 2008 22:53:13 -0000 1.9 +++ source.h 4 Jan 2008 21:26:11 -0000 @@ -66,4 +66,14 @@ extern struct symtab_and_line set_curren /* Reset any information stored about a default file and line to print. */ extern void clear_current_source_symtab_and_line (void); + +/* If the user specified a source path substitution rule that applies + to PATH, then apply it and return the new path. This new path must + be deallocated afterwards. + + Return NULL if no substitution rule was specified by the user, + or if no rule applied to the given PATH. */ + +extern char *rewrite_source_path (const char *path); + #endif Index: testsuite/gdb.base/hashline1.exp =================================================================== RCS file: testsuite/gdb.base/hashline1.exp diff -N testsuite/gdb.base/hashline1.exp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.base/hashline1.exp 4 Jan 2008 21:26:18 -0000 @@ -0,0 +1,60 @@ +# Copyright 2007 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This file is part of the gdb testsuite. + +# Test loading of line number information with absolute path in #line, bug 2360. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 2360 +set bug_id 0 + +# srcfile is in objdir because we need to machine generate it in order +# to get correct the correct path in the #line directive. + +set testfile "hashline1" +set srcfile "${testfile}.c" +set binfile "${objdir}/${subdir}/${testfile}" + +set fd [open ${objdir}/${subdir}/${srcfile} w] +puts $fd "#line 2 \"[pwd]/${subdir}/${srcfile}\"" +puts $fd "int main () { return 0; } /* set breakpoint here */" +close $fd + +# The choice of path name for the source file is important in order to +# trigger the bug. Using ${objdir}/${subdir}/${srcfile} here won't trigger +# the bug. +if { [gdb_compile "./${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested hashline1.exp + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +set bp_location [gdb_get_line_number "set breakpoint here" ${objdir}/${subdir}/${srcfile}] + +# Try to set a breakpoint on the specified file location. + +gdb_test "set substitute-path [pwd]/. [pwd]" "" "" + +gdb_test "break $srcfile:$bp_location" \ + "Breakpoint.*at.* file .*$srcfile, line.*" \ + "set breakpoint" Index: testsuite/gdb.base/hashline2.exp =================================================================== RCS file: testsuite/gdb.base/hashline2.exp diff -N testsuite/gdb.base/hashline2.exp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.base/hashline2.exp 4 Jan 2008 21:26:18 -0000 @@ -0,0 +1,58 @@ +# Copyright 2007 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This file is part of the gdb testsuite. + +# Test loading of line number information with an absolute path with extra +# /'s in #line, bug 2360. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 2360 +set bug_id 0 + +# srcfile is in objdir because we need to machine generate it in order +# to get correct the correct path in the #line directive. + +set testfile "hashline2" +set srcfile "${testfile}.c" +set binfile "${objdir}/${subdir}/${testfile}" + +set fd [open ${objdir}/${subdir}/${srcfile} w] +puts $fd "#line 2 \"///[pwd]/${subdir}/${srcfile}\"" +puts $fd "int main () { return 0; } /* set breakpoint here */" +close $fd + +if { [gdb_compile "${objdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested hashline1.exp + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +set bp_location [gdb_get_line_number "set breakpoint here" ${objdir}/${subdir}/${srcfile}] + +# Try to set a breakpoint on the specified file location. + +gdb_test "set substitute-path ///[pwd] [pwd]" "" "" + +gdb_test "break $srcfile:$bp_location" \ + "Breakpoint.*at.* file .*$srcfile, line.*" \ + "set breakpoint" Index: testsuite/gdb.base/hashline3.exp =================================================================== RCS file: testsuite/gdb.base/hashline3.exp diff -N testsuite/gdb.base/hashline3.exp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.base/hashline3.exp 4 Jan 2008 21:26:18 -0000 @@ -0,0 +1,57 @@ +# Copyright 2007 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This file is part of the gdb testsuite. + +# Test loading of line number information with relative path in #line, bug 2360. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 2360 +set bug_id 0 + +# srcfile is in objdir because we need to machine generate it in order +# to get correct the correct path in the #line directive. + +set testfile "hashline3" +set srcfile "${testfile}.c" +set binfile "${objdir}/${subdir}/${testfile}" + +set fd [open ${objdir}/${subdir}/${srcfile} w] +puts $fd "#line 2 \"./${subdir}/${srcfile}\"" +puts $fd "int main () { return 0; } /* set breakpoint here */" +close $fd + +if { [gdb_compile "${objdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested hashline1.exp + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +set bp_location [gdb_get_line_number "set breakpoint here" ${objdir}/${subdir}/${srcfile}] + +# Try to set a breakpoint on the specified file location. + +gdb_test "set substitute-path ${objdir}/. ${objdir}" "" "" + +gdb_test "break $srcfile:$bp_location" \ + "Breakpoint.*at.* file .*$srcfile, line.*" \ + "set breakpoint"