PR symtab/18258
authorDoug Evans <dje@google.com>
Wed, 27 May 2015 18:50:38 +0000 (11:50 -0700)
committerDoug Evans <dje@google.com>
Wed, 27 May 2015 18:50:38 +0000 (11:50 -0700)
gdb/ChangeLog:

* 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.

gdb/testsuite/ChangeLog:

* 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.

gdb/ChangeLog
gdb/block.c
gdb/block.h
gdb/dwarf2read.c
gdb/psymtab.c
gdb/symtab.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.dwarf2/opaque-type-lookup-2.c [new file with mode: 0644]
gdb/testsuite/gdb.dwarf2/opaque-type-lookup.c [new file with mode: 0644]
gdb/testsuite/gdb.dwarf2/opaque-type-lookup.exp [new file with mode: 0644]

index 945549248fb8c81fbec2d8b755a729427c350374..dbcc64448ae2ebedd2ee49875195bebf851ad2df 100644 (file)
@@ -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
index 00a7012f3ec71fd79b7b6252d442cb9c94953893..79a8f195db80602d65fee17ef44dcc331707215a 100644 (file)
@@ -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;
+}
index bdc58880031c2755cf5d053fe63c0607144813ce..d8ad3430dc79785eae6964e032f1cb31eced3dc3 100644 (file)
@@ -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.  */
index d72adbe703721886a05ff7bcd2f2ea37dd582753..8e30ff384f64772f1b561e6a912dc82a88ce87c0 100644 (file)
@@ -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.  */
        }
index 383e4c4540f2330738830c997d475d5565c97466..9ee6ed1b4615cb38101b8d9cf0e7c113ad1166b4 100644 (file)
@@ -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.  */
       }
index 72df872a9e776ef8a58e122c18879b987e5d5c63..669393060c9176a8f96dd0967953da6c15dfc3fa 100644 (file)
@@ -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)
index 8f945abb49d5977852cefe2ef227e3bc4ce16eea..94a032990a0fc0d70b3c15e5e6b67c5620f1b163 100644 (file)
@@ -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 (file)
index 0000000..948e26d
--- /dev/null
@@ -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 (file)
index 0000000..7cfe08e
--- /dev/null
@@ -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 (file)
index 0000000..67f6dbf
--- /dev/null
@@ -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'}"