diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ff22280ef6..08883486a4 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,13 @@ 2013-08-01 Doug Evans + PR symtab/15691 + * dwarf2read.c (struct dwarf2_per_cu_data): New member tu_read. + (fill_in_sig_entry_from_dwo_entry): Reorganize asserts. + Add assert of sig_entry->dwo_unit == NULL. + (lookup_dwo_signatured_type): Don't assign TU to a DWO if the TU + had already been read. + (read_signatured_type): Set per_cu.tu_read. + PR symtab/15695 * valops.c (value_struct_elt): Add missing call to check_typedef. (value_find_oload_method_list): Ditto. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 241c83e87b..cb77386f6f 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -558,6 +558,16 @@ struct dwarf2_per_cu_data attributes in the stub. */ unsigned int reading_dwo_directly : 1; + /* Non-zero if the TU has been read. + This is used to assist the "Stay in DWO Optimization" for Fission: + When reading a DWO, it's faster to read TUs from the DWO instead of + fetching them from random other DWOs (due to comdat folding). + If the TU has already been read, the optimization is unnecessary + (and unwise - we don't want to change where gdb thinks the TU lives + "midflight"). + This flag is only valid if is_debug_types is true. */ + unsigned int tu_read : 1; + /* The section this CU/TU lives in. If the DIE refers to a DWO file, this is always the original die, not the DWO file. */ @@ -4443,11 +4453,7 @@ fill_in_sig_entry_from_dwo_entry (struct objfile *objfile, struct signatured_type *sig_entry, struct dwo_unit *dwo_entry) { - sig_entry->per_cu.section = dwo_entry->section; - sig_entry->per_cu.offset = dwo_entry->offset; - sig_entry->per_cu.length = dwo_entry->length; - sig_entry->per_cu.reading_dwo_directly = 1; - sig_entry->per_cu.objfile = objfile; + /* Make sure we're not clobbering something we don't expect to. */ gdb_assert (! sig_entry->per_cu.queued); gdb_assert (sig_entry->per_cu.cu == NULL); gdb_assert (sig_entry->per_cu.v.quick != NULL); @@ -4455,19 +4461,26 @@ fill_in_sig_entry_from_dwo_entry (struct objfile *objfile, gdb_assert (sig_entry->signature == dwo_entry->signature); gdb_assert (sig_entry->type_offset_in_section.sect_off == 0); gdb_assert (sig_entry->type_unit_group == NULL); + gdb_assert (sig_entry->dwo_unit == NULL); + + sig_entry->per_cu.section = dwo_entry->section; + sig_entry->per_cu.offset = dwo_entry->offset; + sig_entry->per_cu.length = dwo_entry->length; + sig_entry->per_cu.reading_dwo_directly = 1; + sig_entry->per_cu.objfile = objfile; sig_entry->type_offset_in_tu = dwo_entry->type_offset_in_tu; sig_entry->dwo_unit = dwo_entry; } /* Subroutine of lookup_signatured_type. - Create the signatured_type data structure for a TU to be read in - directly from a DWO file, bypassing the stub. - We do this for the case where there is no DWP file and we're using - .gdb_index: When reading a CU we want to stay in the DWO file containing - that CU. Otherwise we could end up reading several other DWO files (due - to comdat folding) to process the transitive closure of all the mentioned - TUs, and that can be slow. The current DWO file will have every type - signature that it needs. + If we haven't read the TU yet, create the signatured_type data structure + for a TU to be read in directly from a DWO file, bypassing the stub. + This is the "Stay in DWO Optimization": When there is no DWP file and we're + using .gdb_index, then when reading a CU we want to stay in the DWO file + containing that CU. Otherwise we could end up reading several other DWO + files (due to comdat folding) to process the transitive closure of all the + mentioned TUs, and that can be slow. The current DWO file will have every + type signature that it needs. We only do this for .gdb_index because in the psymtab case we already have to read all the DWOs to build the type unit groups. */ @@ -4496,8 +4509,13 @@ lookup_dwo_signatured_type (struct dwarf2_cu *cu, ULONGEST sig) sig_entry = htab_find (dwarf2_per_objfile->signatured_types, &find_sig_entry); if (sig_entry == NULL) return NULL; + + /* We can get here with the TU already read, *or* in the process of being + read. Don't reassign it if that's the case. Also note that if the TU is + already being read, it may not have come from a DWO, the program may be + a mix of Fission-compiled code and non-Fission-compiled code. */ /* Have we already tried to read this TU? */ - if (sig_entry->dwo_unit != NULL) + if (sig_entry->per_cu.tu_read) return sig_entry; /* Ok, this is the first time we're reading this TU. */ @@ -18608,6 +18626,7 @@ read_signatured_type (struct signatured_type *sig_type) init_cutu_and_read_dies (per_cu, NULL, 0, 1, read_signatured_type_reader, NULL); + sig_type->per_cu.tu_read = 1; } /* Decode simple location descriptions. diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index e3b068385c..25a1b01cb3 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,11 @@ 2013-08-01 Doug Evans + PR symtab/15691 + * gdb.dwarf2/fission-mix.exp: New file. + * gdb.dwarf2/fission-mix.h: New file. + * gdb.dwarf2/fission-mix.c: New file. + * gdb.dwarf2/fission-mix2.c: New file. + PR symtab/15695 * gdb.base/func-ptr.exp: New file. * gdb.base/func-ptr.c: New file. diff --git a/gdb/testsuite/gdb.dwarf2/fission-mix.c b/gdb/testsuite/gdb.dwarf2/fission-mix.c new file mode 100644 index 0000000000..c8fdde22b8 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/fission-mix.c @@ -0,0 +1,33 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2013 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 . */ + +#include "fission-mix.h" + +struct s foo; + +int +func (int arg) +{ + return arg + 1; +} + +int +main () +{ + foo.x = 1; + return func (-1); +} diff --git a/gdb/testsuite/gdb.dwarf2/fission-mix.exp b/gdb/testsuite/gdb.dwarf2/fission-mix.exp new file mode 100644 index 0000000000..3a1090f5f4 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/fission-mix.exp @@ -0,0 +1,46 @@ +# Copyright 2013 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 . + +load_lib dwarf.exp + +# This test can only be run on targets which support DWARF-2. +if ![dwarf2_support] { + return 0 +} + +standard_testfile fission-mix.c fission-mix2.c +set objfile [standard_output_file ${testfile}.o] +set objfile2 [standard_output_file ${testfile}2.o] + +# Compile fission-mix.c without Fission and fission-mix2.c with Fission. +if { [gdb_compile ${srcdir}/${subdir}/${srcfile} $objfile object {debug}] != "" } { + return -1 +} +if { [gdb_compile ${srcdir}/${subdir}/${srcfile2} $objfile2 object {debug additional_flags=-gsplit-dwarf}] != "" } { + return -1 +} +if {[gdb_compile "$objfile $objfile2" $binfile executable {debug}] != "" } { + return -1 +} + +clean_restart $binfile + +gdb_test "break main" "Breakpoint .*" + +# Bug 15691: gdb would crash here on an assert violation. +# The debug info for the TU for "struct s" has already been read, +# but gdb doesn't think so. +# To repro the bug, --target_board=dwarf4-gdb-index, or equivalent, is needed. +gdb_test "break func2" "Breakpoint .*" diff --git a/gdb/testsuite/gdb.dwarf2/fission-mix.h b/gdb/testsuite/gdb.dwarf2/fission-mix.h new file mode 100644 index 0000000000..2521e68042 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/fission-mix.h @@ -0,0 +1,23 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2013 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 . */ + +/* A type to be recorded as a DW_TAG_type_unit. */ + +struct s +{ + int x; +}; diff --git a/gdb/testsuite/gdb.dwarf2/fission-mix2.c b/gdb/testsuite/gdb.dwarf2/fission-mix2.c new file mode 100644 index 0000000000..a9194fa21b --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/fission-mix2.c @@ -0,0 +1,27 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2013 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 . */ + +#include "fission-mix.h" + +struct s bar; + +int +func2 () +{ + bar.x = 1; + return 42; +}