summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog15
-rw-r--r--gdb/block.c47
-rw-r--r--gdb/block.h34
-rw-r--r--gdb/dwarf2read.c20
-rw-r--r--gdb/psymtab.c22
-rw-r--r--gdb/symtab.c61
-rw-r--r--gdb/testsuite/ChangeLog6
-rw-r--r--gdb/testsuite/gdb.dwarf2/opaque-type-lookup-2.c24
-rw-r--r--gdb/testsuite/gdb.dwarf2/opaque-type-lookup.c23
-rw-r--r--gdb/testsuite/gdb.dwarf2/opaque-type-lookup.exp200
10 files changed, 409 insertions, 43 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 945549248fb..dbcc64448ae 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,18 @@
+2015-05-27 Doug Evans <dje@google.com>
+
+ PR symtab/18258
+ * block.c (block_find_symbol): New function.
+ (block_find_non_opaque_type): Ditto.
+ (block_find_non_opaque_type_preferred): Ditto.
+ * block.h (block_symbol_matcher_ftype): New typedef.
+ (block_find_symbol): Declare.
+ (block_find_non_opaque_type): Ditto.
+ (block_find_non_opaque_type_preferred): Ditto.
+ * dwarf2read.c (dw2_lookup_symbol): Call block_find_symbol.
+ * psymtab.c (psym_lookup_symbol): Ditto.
+ * symtab.c (basic_lookup_transparent_type_1): New function.
+ (basic_lookup_transparent_type): Call it.
+
2015-05-27 Yao Qi <yao.qi@linaro.org>
* aarch64-tdep.c (aarch64_record_data_proc_simd_fp): Return
diff --git a/gdb/block.c b/gdb/block.c
index 00a7012f3ec..79a8f195db8 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -797,3 +797,50 @@ block_lookup_symbol_primary (const struct block *block, const char *name,
return NULL;
}
+
+/* See block.h. */
+
+struct symbol *
+block_find_symbol (const struct block *block, const char *name,
+ const domain_enum domain,
+ block_symbol_matcher_ftype *matcher, void *data)
+{
+ struct block_iterator iter;
+ struct symbol *sym;
+
+ /* Verify BLOCK is STATIC_BLOCK or GLOBAL_BLOCK. */
+ gdb_assert (BLOCK_SUPERBLOCK (block) == NULL
+ || BLOCK_SUPERBLOCK (BLOCK_SUPERBLOCK (block)) == NULL);
+
+ ALL_BLOCK_SYMBOLS_WITH_NAME (block, name, iter, sym)
+ {
+ /* MATCHER is deliberately called second here so that it never sees
+ a non-domain-matching symbol. */
+ if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
+ SYMBOL_DOMAIN (sym), domain)
+ && matcher (sym, data))
+ return sym;
+ }
+ return NULL;
+}
+
+/* See block.h. */
+
+int
+block_find_non_opaque_type (struct symbol *sym, void *data)
+{
+ return !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym));
+}
+
+/* See block.h. */
+
+int
+block_find_non_opaque_type_preferred (struct symbol *sym, void *data)
+{
+ struct symbol **best = data;
+
+ if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
+ return 1;
+ *best = sym;
+ return 0;
+}
diff --git a/gdb/block.h b/gdb/block.h
index bdc58880031..d8ad3430dc7 100644
--- a/gdb/block.h
+++ b/gdb/block.h
@@ -292,6 +292,40 @@ extern struct symbol *block_lookup_symbol_primary (const struct block *block,
const char *name,
const domain_enum domain);
+/* The type of the MATCHER argument to block_find_symbol. */
+
+typedef int (block_symbol_matcher_ftype) (struct symbol *, void *);
+
+/* Find symbol NAME in BLOCK and in DOMAIN that satisfies MATCHER.
+ DATA is passed unchanged to MATCHER.
+ BLOCK must be STATIC_BLOCK or GLOBAL_BLOCK. */
+
+extern struct symbol *block_find_symbol (const struct block *block,
+ const char *name,
+ const domain_enum domain,
+ block_symbol_matcher_ftype *matcher,
+ void *data);
+
+/* A matcher function for block_find_symbol to find only symbols with
+ non-opaque types. */
+
+extern int block_find_non_opaque_type (struct symbol *sym, void *data);
+
+/* A matcher function for block_find_symbol to prefer symbols with
+ non-opaque types. The way to use this function is as follows:
+
+ struct symbol *with_opaque = NULL;
+ struct symbol *sym
+ = block_find_symbol (block, name, domain,
+ block_find_non_opaque_type_preferred, &with_opaque);
+
+ At this point if SYM is non-NULL then a non-opaque type has been found.
+ Otherwise, if WITH_OPAQUE is non-NULL then an opaque type has been found.
+ Otherwise, the symbol was not found. */
+
+extern int block_find_non_opaque_type_preferred (struct symbol *sym,
+ void *data);
+
/* Macro to loop through all symbols in BLOCK, in no particular
order. ITER helps keep track of the iteration, and must be a
struct block_iterator. SYM points to the current symbol. */
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index d72adbe7037..8e30ff384f6 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -3665,23 +3665,25 @@ dw2_lookup_symbol (struct objfile *objfile, int block_index,
while ((per_cu = dw2_symtab_iter_next (&iter)) != NULL)
{
- struct symbol *sym = NULL;
+ struct symbol *sym, *with_opaque = NULL;
struct compunit_symtab *stab = dw2_instantiate_symtab (per_cu);
const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (stab);
struct block *block = BLOCKVECTOR_BLOCK (bv, block_index);
+ sym = block_find_symbol (block, name, domain,
+ block_find_non_opaque_type_preferred,
+ &with_opaque);
+
/* Some caution must be observed with overloaded functions
and methods, since the index will not contain any overload
information (but NAME might contain it). */
- sym = block_lookup_symbol (block, name, domain);
-
- if (sym && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0)
- {
- if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
- return stab;
- stab_best = stab;
- }
+ if (sym != NULL
+ && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0)
+ return stab;
+ if (with_opaque != NULL
+ && strcmp_iw (SYMBOL_SEARCH_NAME (with_opaque), name) == 0)
+ stab_best = stab;
/* Keep looking through other CUs. */
}
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index 383e4c4540f..9ee6ed1b461 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -516,7 +516,7 @@ psym_lookup_symbol (struct objfile *objfile,
if (!ps->readin && lookup_partial_symbol (objfile, ps, name,
psymtab_index, domain))
{
- struct symbol *sym = NULL;
+ struct symbol *sym, *with_opaque = NULL;
struct compunit_symtab *stab = psymtab_to_symtab (objfile, ps);
/* Note: While psymtab_to_symtab can return NULL if the partial symtab
is empty, we can assume it won't here because lookup_partial_symbol
@@ -524,18 +524,20 @@ psym_lookup_symbol (struct objfile *objfile,
const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (stab);
struct block *block = BLOCKVECTOR_BLOCK (bv, block_index);
+ sym = block_find_symbol (block, name, domain,
+ block_find_non_opaque_type_preferred,
+ &with_opaque);
+
/* Some caution must be observed with overloaded functions
- and methods, since the psymtab will not contain any overload
+ and methods, since the index will not contain any overload
information (but NAME might contain it). */
- sym = block_lookup_symbol (block, name, domain);
-
- if (sym && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0)
- {
- if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
- return stab;
- stab_best = stab;
- }
+ if (sym != NULL
+ && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0)
+ return stab;
+ if (with_opaque != NULL
+ && strcmp_iw (SYMBOL_SEARCH_NAME (with_opaque), name) == 0)
+ stab_best = stab;
/* Keep looking through other psymtabs. */
}
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 72df872a9e7..669393060c9 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -2804,12 +2804,39 @@ basic_lookup_transparent_type_quick (struct objfile *objfile, int block_index,
bv = COMPUNIT_BLOCKVECTOR (cust);
block = BLOCKVECTOR_BLOCK (bv, block_index);
- sym = block_lookup_symbol (block, name, STRUCT_DOMAIN);
- if (!sym)
+ sym = block_find_symbol (block, name, STRUCT_DOMAIN,
+ block_find_non_opaque_type, NULL);
+ if (sym == NULL)
error_in_psymtab_expansion (block_index, name, cust);
+ gdb_assert (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)));
+ return SYMBOL_TYPE (sym);
+}
+
+/* Subroutine of basic_lookup_transparent_type to simplify it.
+ Look up the non-opaque definition of NAME in BLOCK_INDEX of OBJFILE.
+ BLOCK_INDEX is either GLOBAL_BLOCK or STATIC_BLOCK. */
- if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
- return SYMBOL_TYPE (sym);
+static struct type *
+basic_lookup_transparent_type_1 (struct objfile *objfile, int block_index,
+ const char *name)
+{
+ const struct compunit_symtab *cust;
+ const struct blockvector *bv;
+ const struct block *block;
+ const struct symbol *sym;
+
+ ALL_OBJFILE_COMPUNITS (objfile, cust)
+ {
+ bv = COMPUNIT_BLOCKVECTOR (cust);
+ block = BLOCKVECTOR_BLOCK (bv, block_index);
+ sym = block_find_symbol (block, name, STRUCT_DOMAIN,
+ block_find_non_opaque_type, NULL);
+ if (sym != NULL)
+ {
+ gdb_assert (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)));
+ return SYMBOL_TYPE (sym);
+ }
+ }
return NULL;
}
@@ -2837,16 +2864,9 @@ basic_lookup_transparent_type (const char *name)
ALL_OBJFILES (objfile)
{
- ALL_OBJFILE_COMPUNITS (objfile, cust)
- {
- bv = COMPUNIT_BLOCKVECTOR (cust);
- block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = block_lookup_symbol (block, name, STRUCT_DOMAIN);
- if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
- {
- return SYMBOL_TYPE (sym);
- }
- }
+ t = basic_lookup_transparent_type_1 (objfile, GLOBAL_BLOCK, name);
+ if (t)
+ return t;
}
ALL_OBJFILES (objfile)
@@ -2865,16 +2885,9 @@ basic_lookup_transparent_type (const char *name)
ALL_OBJFILES (objfile)
{
- ALL_OBJFILE_COMPUNITS (objfile, cust)
- {
- bv = COMPUNIT_BLOCKVECTOR (cust);
- block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- sym = block_lookup_symbol (block, name, STRUCT_DOMAIN);
- if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
- {
- return SYMBOL_TYPE (sym);
- }
- }
+ t = basic_lookup_transparent_type_1 (objfile, STATIC_BLOCK, name);
+ if (t)
+ return t;
}
ALL_OBJFILES (objfile)
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 8f945abb49d..94a032990a0 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2015-05-27 Doug Evans <dje@google.com>
+
+ * gdb.dwarf2/opaque-type-lookup-2.c: New file.
+ * gdb.dwarf2/opaque-type-lookup.c: New file.
+ * gdb.dwarf2/opaque-type-lookup.exp: New file.
+
2015-05-26 Doug Evans <dje@google.com>
* gdb.cp/iostream.cc: New file.
diff --git a/gdb/testsuite/gdb.dwarf2/opaque-type-lookup-2.c b/gdb/testsuite/gdb.dwarf2/opaque-type-lookup-2.c
new file mode 100644
index 00000000000..948e26de5f3
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/opaque-type-lookup-2.c
@@ -0,0 +1,24 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2015 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/>. */
+
+/* These are actually struct struct_{a,b}, but that's handled by the dwarf
+ in opaque-type-lookup.exp.
+ IWBN to give these a different name than what's in the dwarf so that minsym
+ lookup doesn't interfere with the testing. However, that currently doesn't
+ work (we don't record the linkage name of the symbol). */
+char variable_a = 'a';
+char variable_b = 'b';
diff --git a/gdb/testsuite/gdb.dwarf2/opaque-type-lookup.c b/gdb/testsuite/gdb.dwarf2/opaque-type-lookup.c
new file mode 100644
index 00000000000..7cfe08e1746
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/opaque-type-lookup.c
@@ -0,0 +1,23 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2015 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/>. */
+
+int
+main()
+{
+ asm ("main_label: .globl main_label");
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.dwarf2/opaque-type-lookup.exp b/gdb/testsuite/gdb.dwarf2/opaque-type-lookup.exp
new file mode 100644
index 00000000000..67f6dbfa6b5
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/opaque-type-lookup.exp
@@ -0,0 +1,200 @@
+# Copyright 2013-2015 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/>.
+
+# Test PR 18258.
+
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if {![dwarf2_support]} {
+ return 0
+}
+
+standard_testfile opaque-type-lookup.c opaque-type-lookup-1.S opaque-type-lookup-2.c
+
+# Create the DWARF.
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+ declare_labels partial_unit_defining_a partial_unit_defining_b
+ declare_labels partial_unit_with_opaque
+ declare_labels struct_a_label struct_b_label
+ declare_labels opaque_struct_a_label opaque_struct_b_label
+ declare_labels char_type1_label char_type2_label
+ global srcdir subdir srcfile
+
+ extern main
+
+ # The partial units are laid out so we're not dependent on the order that
+ # they appear in compunit_symtab.includes. We need the one with the
+ # opaque definition to appear first to gdb, so we put it in the middle.
+ # Either the handling of variable_a or variable_b will be broken (in an
+ # unpatched gdb).
+ #
+ # However, once a partial unit with a non-opaque type is read in we can
+ # no longer see the bug as gdb will keep looking until it eventually gets
+ # to the defining partial unit, setting aside the symbol lookup cache.
+ # So heads up!
+
+ cu {} {
+ compile_unit {
+ {language @DW_LANG_C}
+ {name opaque_before}
+ } {
+ imported_unit {
+ {import $partial_unit_with_opaque ref_addr}
+ }
+
+ imported_unit {
+ {import $partial_unit_defining_a ref_addr}
+ }
+ }
+ }
+
+ cu {} {
+ compile_unit {
+ {language @DW_LANG_C}
+ {name opaque_after}
+ } {
+ imported_unit {
+ {import $partial_unit_defining_b ref_addr}
+ }
+
+ imported_unit {
+ {import $partial_unit_with_opaque ref_addr}
+ }
+ }
+ }
+
+ cu {} {
+ partial_unit_with_opaque: partial_unit {
+ {name "partial_unit_with_opaque"}
+ } {
+ # Normally gdb doesn't add opaque types to the symbol table
+ # but there are times when it will, and in order to exercise
+ # this bug we need this entry in the symbol table.
+ # By giving it a size of 1 we achieve this.
+
+ opaque_struct_a_label: structure_type {
+ {name struct_a}
+ {declaration 1 flag}
+ {byte_size 1 DW_FORM_sdata}
+ }
+
+ opaque_struct_b_label: structure_type {
+ {name struct_b}
+ {declaration 1 flag}
+ {byte_size 1 DW_FORM_sdata}
+ }
+
+ DW_TAG_variable {
+ {name variable_a}
+ {type :$opaque_struct_a_label}
+ {external 1 flag}
+ {declaration 1 flag}
+ }
+
+ DW_TAG_variable {
+ {name variable_b}
+ {type :$opaque_struct_b_label}
+ {external 1 flag}
+ {declaration 1 flag}
+ }
+ }
+ }
+
+ cu {} {
+ partial_unit_defining_a: partial_unit {
+ {name "partial_unit_defining_a"}
+ } {
+ char_type1_label: base_type {
+ {name "signed char"}
+ {encoding @DW_ATE_signed}
+ {byte_size 1 DW_FORM_sdata}
+ }
+
+ struct_a_label: structure_type {
+ {name struct_a}
+ {byte_size 1 DW_FORM_sdata}
+ } {
+ member {
+ {name xyz}
+ {type :$char_type1_label}
+ {data_member_location 0 DW_FORM_sdata}
+ }
+ }
+
+ DW_TAG_variable {
+ {name variable_a}
+ {type :$struct_a_label}
+ {external 1 flag}
+ {linkage_name variable_a}
+ }
+ }
+ }
+
+ cu {} {
+ partial_unit_defining_b: partial_unit {
+ {name "partial_unit_defining_b"}
+ } {
+ char_type2_label: base_type {
+ {name "signed char"}
+ {encoding @DW_ATE_signed}
+ {byte_size 1 DW_FORM_sdata}
+ }
+
+ struct_b_label: structure_type {
+ {name struct_b}
+ {byte_size 1 DW_FORM_sdata}
+ } {
+ member {
+ {name xyz}
+ {type :$char_type2_label}
+ {data_member_location 0 DW_FORM_sdata}
+ }
+ }
+
+ DW_TAG_variable {
+ {name variable_b}
+ {type :$struct_b_label}
+ {external 1 flag}
+ {linkage_name variable_b}
+ }
+ }
+ }
+
+ # GDB expands the symbol table with main at start up,
+ # so keep this separate.
+ cu {} {
+ compile_unit {
+ {language @DW_LANG_C}
+ {name main}
+ } {
+ subprogram {
+ {MACRO_AT_func { main ${srcdir}/${subdir}/${srcfile} }}
+ }
+ }
+ }
+}
+
+if [prepare_for_testing ${testfile}.exp $testfile "${asm_file} ${srcfile} ${srcfile3}" {nodebug}] {
+ return -1
+}
+
+if ![runto_main] {
+ return -1
+}
+
+gdb_test "p variable_a" " = {xyz = 97 'a'}"
+gdb_test "p variable_b" " = {xyz = 98 'b'}"