PR symtab/18258

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.
This commit is contained in:
Doug Evans 2015-05-27 11:50:38 -07:00
parent f62fce356b
commit b2e2f908b8
10 changed files with 409 additions and 43 deletions

View 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

View 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;
}

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

View 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. */
}

View 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. */
}

View 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);
}
if (!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. */
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)

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

View File

@ -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';

View File

@ -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;
}

View File

@ -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'}"