* buildsym.c (watch_main_source_file_lossage): New fn.
authorDoug Evans <dje@google.com>
Thu, 17 Apr 2008 17:54:05 +0000 (17:54 +0000)
committerDoug Evans <dje@google.com>
Thu, 17 Apr 2008 17:54:05 +0000 (17:54 +0000)
(end_symtab): Call it.

* gdb.base/hashline1.exp: New testcase.
* gdb.base/hashline2.exp: New testcase.
* gdb.base/hashline2.exp: New testcase.

gdb/ChangeLog
gdb/buildsym.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/hashline1.exp [new file with mode: 0644]
gdb/testsuite/gdb.base/hashline2.exp [new file with mode: 0644]
gdb/testsuite/gdb.base/hashline3.exp [new file with mode: 0644]

index 28d7ae58a3d6ad8960ac3a6286836df303365fc8..ffb98b2ab1bf47ac5f20050be167eaae5f44e421 100644 (file)
@@ -1,5 +1,8 @@
 2008-04-17  Doug Evans  <dje@google.com>
 
+       * buildsym.c (watch_main_source_file_lossage): New fn.
+       (end_symtab): Call it.
+
        * source.c (find_and_open_source): Add some comments clarifying
        handling of FULLNAME argument.  Make static.  Remove pointless
        xstrdup/xfree.
index cccd769ffa9b4f3480f3ee9c25058519648a7455..282dc4ec244490e50af8ab5bbbe3ab53e577fc19 100644 (file)
@@ -889,6 +889,81 @@ start_symtab (char *name, char *dirname, CORE_ADDR start_addr)
   start_subfile (name, dirname);
 }
 
+/* Subroutine of end_symtab to simplify it.
+   Look for a subfile that matches the main source file's basename.
+   If there is only one, and if the main source file doesn't have any
+   symbol or line number information, then copy this file's symtab and
+   line_vector to the main source file's subfile and discard the other subfile.
+   This can happen because of a compiler bug or from the user playing games
+   with #line or from things like a distributed build system that manipulates
+   the debug info.  */
+
+static void
+watch_main_source_file_lossage (void)
+{
+  struct subfile *mainsub, *subfile;
+
+  /* Find the main source file.
+     This loop could be eliminated if start_symtab saved it for us.  */
+  mainsub = NULL;
+  for (subfile = subfiles; subfile; subfile = subfile->next)
+    {
+      /* The main subfile is guaranteed to be the last one.  */
+      if (subfile->next == NULL)
+       mainsub = subfile;
+    }
+
+  /* If the main source file doesn't have any line number or symbol info,
+     look for an alias in another subfile.
+     We have to watch for mainsub == NULL here.  It's a quirk of end_symtab,
+     it can return NULL so there may not be a main subfile.  */
+
+  if (mainsub
+      && mainsub->line_vector == NULL
+      && mainsub->symtab == NULL)
+    {
+      const char *mainbase = lbasename (mainsub->name);
+      int nr_matches = 0;
+      struct subfile *prevsub;
+      struct subfile *mainsub_alias = NULL;
+      struct subfile *prev_mainsub_alias = NULL;
+
+      prevsub = NULL;
+      for (subfile = subfiles;
+          /* Stop before we get to the last one.  */
+          subfile->next;
+          subfile = subfile->next)
+       {
+         if (strcmp (lbasename (subfile->name), mainbase) == 0)
+           {
+             ++nr_matches;
+             mainsub_alias = subfile;
+             prev_mainsub_alias = prevsub;
+           }
+         prevsub = subfile;
+       }
+
+      if (nr_matches == 1)
+       {
+         gdb_assert (mainsub_alias != NULL && mainsub_alias != mainsub);
+
+         /* Found a match for the main source file.
+            Copy its line_vector and symtab to the main subfile
+            and then discard it.  */
+
+         mainsub->line_vector = mainsub_alias->line_vector;
+         mainsub->line_vector_length = mainsub_alias->line_vector_length;
+         mainsub->symtab = mainsub_alias->symtab;
+
+         if (prev_mainsub_alias == NULL)
+           subfiles = mainsub_alias->next;
+         else
+           prev_mainsub_alias->next = mainsub_alias->next;
+         xfree (mainsub_alias);
+       }
+    }
+}
+
 /* Finish the symbol definitions for one main source file, close off
    all the lexical contexts for that file (creating struct block's for
    them), then make the struct symtab for that file and put it in the
@@ -1010,6 +1085,11 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
   if (objfile->sf->sym_read_linetable != NULL)
     objfile->sf->sym_read_linetable ();
 
+  /* Handle the case where the debug info specifies a different path
+     for the main source file.  It can cause us to lose track of its
+     line number information.  */
+  watch_main_source_file_lossage ();
+
   /* Now create the symtab objects proper, one for each subfile.  */
   /* (The main file is the last one on the chain.)  */
 
index ff3394418cfd5eab7c950fc72f0f614249288e15..82ae12f167f4d973d7ac9876081dc5140f7fe9a8 100644 (file)
@@ -1,3 +1,9 @@
+2008-04-17  Doug Evans  <dje@google.com>
+
+       * gdb.base/hashline1.exp: New testcase.
+       * gdb.base/hashline2.exp: New testcase.
+       * gdb.base/hashline2.exp: New testcase.
+
 2008-04-17  Pedro Alves  <pedro@codesourcery.com>
 
        * gdb.base/step-break.exp, gdb.base/step-break.c: New files.
diff --git a/gdb/testsuite/gdb.base/hashline1.exp b/gdb/testsuite/gdb.base/hashline1.exp
new file mode 100644 (file)
index 0000000..ea3c9c8
--- /dev/null
@@ -0,0 +1,57 @@
+# Copyright 2008 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 <http://www.gnu.org/licenses/>.
+
+# 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 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 "break $srcfile:$bp_location" \
+    "Breakpoint.*at.* file .*$srcfile, line.*" \
+    "set breakpoint"
diff --git a/gdb/testsuite/gdb.base/hashline2.exp b/gdb/testsuite/gdb.base/hashline2.exp
new file mode 100644 (file)
index 0000000..22d051e
--- /dev/null
@@ -0,0 +1,56 @@
+# Copyright 2008 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 <http://www.gnu.org/licenses/>.
+
+# 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 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 "break $srcfile:$bp_location" \
+    "Breakpoint.*at.* file .*$srcfile, line.*" \
+    "set breakpoint"
diff --git a/gdb/testsuite/gdb.base/hashline3.exp b/gdb/testsuite/gdb.base/hashline3.exp
new file mode 100644 (file)
index 0000000..34582b1
--- /dev/null
@@ -0,0 +1,55 @@
+# Copyright 2008 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 <http://www.gnu.org/licenses/>.
+
+# 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 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 "break $srcfile:$bp_location" \
+    "Breakpoint.*at.* file .*$srcfile, line.*" \
+    "set breakpoint"