From: Doug Evans Date: Thu, 17 Apr 2008 17:54:05 +0000 (+0000) Subject: * buildsym.c (watch_main_source_file_lossage): New fn. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4584e32ea409bd2b80cd4aba8635de091a47da4b;p=binutils-gdb.git * buildsym.c (watch_main_source_file_lossage): New fn. (end_symtab): Call it. * gdb.base/hashline1.exp: New testcase. * gdb.base/hashline2.exp: New testcase. * gdb.base/hashline2.exp: New testcase. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 28d7ae58a3d..ffb98b2ab1b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,8 @@ 2008-04-17 Doug Evans + * 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. diff --git a/gdb/buildsym.c b/gdb/buildsym.c index cccd769ffa9..282dc4ec244 100644 --- a/gdb/buildsym.c +++ b/gdb/buildsym.c @@ -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.) */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index ff3394418cf..82ae12f167f 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2008-04-17 Doug Evans + + * gdb.base/hashline1.exp: New testcase. + * gdb.base/hashline2.exp: New testcase. + * gdb.base/hashline2.exp: New testcase. + 2008-04-17 Pedro Alves * 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 index 00000000000..ea3c9c8ed29 --- /dev/null +++ b/gdb/testsuite/gdb.base/hashline1.exp @@ -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 . + +# 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 index 00000000000..22d051e0a7e --- /dev/null +++ b/gdb/testsuite/gdb.base/hashline2.exp @@ -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 . + +# 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 index 00000000000..34582b19a48 --- /dev/null +++ b/gdb/testsuite/gdb.base/hashline3.exp @@ -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 . + +# 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"