binutils-gdb/gdb/psymtab.h
Tom de Vries 96c7f87394 [gdb/symtab] Fix partial unit psymtabs
Consider test-case gdb.dwarf2/imported-unit.exp.

It contains a CU with type int:
...
 <0><129>: Abbrev Number: 2 (DW_TAG_compile_unit)
    <12a>   DW_AT_language    : 4       (C++)
    <12b>   DW_AT_name        : imported_unit.c
 <1><13b>: Abbrev Number: 3 (DW_TAG_base_type)
    <13c>   DW_AT_byte_size   : 4
    <13d>   DW_AT_encoding    : 5       (signed)
    <13e>   DW_AT_name        : int
...
which is imported in another CU:
...
 <0><d2>: Abbrev Number: 2 (DW_TAG_compile_unit)
    <d3>   DW_AT_language    : 4        (C++)
    <d4>   DW_AT_name        : <artificial>
 <1><e1>: Abbrev Number: 3 (DW_TAG_imported_unit)
    <e2>   DW_AT_import      : <0x129>  [Abbrev Number: 2]
...

However, if we print the partial symbols:
...
$ gdb -batch imported-unit  -ex "maint print psymbols"
...
we see type int both in the importing CU:
...
Partial symtab for source file <artificial>@0xc7 (object 0x29f9b80)
  ...
  Depends on 1 other partial symtabs.
    0 0x2a24240 imported_unit.c
  Global partial symbols:
    `main', function, 0x4004b2
  Static partial symbols:
    `int', type, 0x0
...
and in the imported CU:
...
Partial symtab for source file imported_unit.c (object 0x2a24240)
  ...
  Depends on 0 other partial symtabs.
  Shared partial symtab with user 0x29f9b80
  Static partial symbols:
    `int', type, 0x0
...

This is an artefact resulting from the fact that all CUs in an objfile
share the same storage array for static partial symbols (and another array for
global partial symbols), using a range to describe their symbols.

Then when scanning the partial symbols of a CU and encountering an import, either:
- the referred CU has not been parsed yet, and will be parsed, and the range of
  static partial symbols of the referred CU will be a subrange of the range of
  static partial symbols of this CU, or
- the referred CU has already been parsed, and the range of static partial
  symbols of the referred CU will not be a subrange of the range of static
  partial symbols of this CU.

This is inconsistent handling, and confuses the notion of a symbol belonging to
a single symtab.

Furthermore, it might slow down searches, given that the symbol needs to be
skipped twice.

Finally, the same issue holds for global partial symbols, where the range of a
CU is sorted after parsing is finished.  Obviously sorting the range of a CU
may invalidate subranges, effectively moving symbols in and out of imported
CUs.

Fix this for both static and global partial symbols, by gathering partial
symbols in a per-CU vector, and adding those symbols to the per-objfile
storage only once complete.

Tested on x86_64-linux, with native and board cc-with-dwz and cc-with-dwz-m.

gdb/ChangeLog:

2020-03-13  Tom de Vries  <tdevries@suse.de>

	PR symtab/25646
	* psymtab.c (partial_symtab::partial_symtab): Don't set
	globals_offset and statics_offset.  Push element onto
	current_global_psymbols and current_static_psymbols stacks.
	(concat): New function.
	(end_psymtab_common): Set globals_offset and statics_offset.  Pop
	element from current_global_psymbols and current_static_psymbols
	stacks.  Concat popped elements to global_psymbols and
	static_symbols.
	(add_psymbol_to_list): Use current_global_psymbols and
	current_static_psymbols stacks.
	* psymtab.h (class psymtab_storage): Add current_global_psymbols and
	current_static_psymbols fields.

gdb/testsuite/ChangeLog:

2020-03-13  Tom de Vries  <tdevries@suse.de>

	PR symtab/25646
	* gdb.dwarf2/imported-unit.exp: Add test.
2020-03-13 08:50:51 +01:00

161 lines
5.2 KiB
C++

/* Public partial symbol table definitions.
Copyright (C) 2009-2020 Free Software Foundation, Inc.
This file is part of GDB.
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/>. */
#ifndef PSYMTAB_H
#define PSYMTAB_H
#include "gdb_obstack.h"
#include "symfile.h"
#include "gdbsupport/next-iterator.h"
#include "bcache.h"
struct partial_symbol;
/* An instance of this class manages the partial symbol tables and
partial symbols for a given objfile.
The core psymtab functions -- those in psymtab.c -- arrange for
nearly all psymtab- and psymbol-related allocations to happen
either in the psymtab_storage object (either on its obstack or in
other memory managed by this class), or on the per-BFD object. The
only link from the psymtab storage object back to the objfile (or
objfile_obstack) that is made by the core psymtab code is the
compunit_symtab member in the standard_psymtab -- and a given
symbol reader can avoid this by implementing its own subclasses of
partial_symtab.
However, it is up to each symbol reader to maintain this invariant
in other ways, if it wants to reuse psymtabs across multiple
objfiles. The main issue here is ensuring that read_symtab_private
does not point into objfile_obstack. */
class psymtab_storage
{
public:
psymtab_storage ();
~psymtab_storage ();
DISABLE_COPY_AND_ASSIGN (psymtab_storage);
/* Discard all partial symbol tables starting with "psymtabs" and
proceeding until "to" has been discarded. */
void discard_psymtabs_to (struct partial_symtab *to)
{
while (psymtabs != to)
discard_psymtab (psymtabs);
}
/* Discard the partial symbol table. */
void discard_psymtab (struct partial_symtab *pst);
/* Return the obstack that is used for storage by this object. */
struct obstack *obstack ()
{
if (!m_obstack.has_value ())
m_obstack.emplace ();
return &*m_obstack;
}
/* Allocate storage for the "dependencies" field of a psymtab.
NUMBER says how many dependencies there are. */
struct partial_symtab **allocate_dependencies (int number)
{
return OBSTACK_CALLOC (obstack (), number, struct partial_symtab *);
}
/* Install a psymtab on the psymtab list. This transfers ownership
of PST to this object. */
void install_psymtab (partial_symtab *pst);
typedef next_adapter<struct partial_symtab> partial_symtab_range;
/* A range adapter that makes it possible to iterate over all
psymtabs in one objfile. */
partial_symtab_range range ()
{
return partial_symtab_range (psymtabs);
}
/* Each objfile points to a linked list of partial symtabs derived from
this file, one partial symtab structure for each compilation unit
(source file). */
struct partial_symtab *psymtabs = nullptr;
/* Map addresses to the entries of PSYMTABS. It would be more efficient to
have a map per the whole process but ADDRMAP cannot selectively remove
its items during FREE_OBJFILE. This mapping is already present even for
PARTIAL_SYMTABs which still have no corresponding full SYMTABs read.
The DWARF parser reuses this addrmap to store things other than
psymtabs in the cases where debug information is being read from, for
example, the .debug-names section. */
struct addrmap *psymtabs_addrmap = nullptr;
/* A byte cache where we can stash arbitrary "chunks" of bytes that
will not change. */
gdb::bcache psymbol_cache;
/* Vectors of all partial symbols read in from file. The actual data
is stored in the objfile_obstack. */
std::vector<partial_symbol *> global_psymbols;
std::vector<partial_symbol *> static_psymbols;
/* Stack of vectors of partial symbols, using during psymtab
initialization. */
std::vector<std::vector<partial_symbol *>*> current_global_psymbols;
std::vector<std::vector<partial_symbol *>*> current_static_psymbols;
private:
/* The obstack where allocations are made. This is lazily allocated
so that we don't waste memory when there are no psymtabs. */
gdb::optional<auto_obstack> m_obstack;
};
extern const struct quick_symbol_functions psym_functions;
extern const struct quick_symbol_functions dwarf2_gdb_index_functions;
extern const struct quick_symbol_functions dwarf2_debug_names_functions;
/* Ensure that the partial symbols for OBJFILE have been loaded. If
VERBOSE is true, then this will print a message when symbols
are loaded. This function returns a range adapter suitable for
iterating over the psymtabs of OBJFILE. */
extern psymtab_storage::partial_symtab_range require_partial_symbols
(struct objfile *objfile, bool verbose);
#endif /* PSYMTAB_H */