/* DWARF 2 debugging format support for GDB.
- Copyright (C) 1994-2021 Free Software Foundation, Inc.
+ Copyright (C) 1994-2022 Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
Inc. with support from Florida State University (under contract
#include "gdbsupport/pathstuff.h"
#include "count-one-bits.h"
#include <unordered_set>
+#include "dwarf2/abbrev-cache.h"
+#include "cooked-index.h"
+#include "split-name.h"
+#include "gdbsupport/parallel-for.h"
+#include "gdbsupport/thread-pool.h"
/* When == 1, print basic high level tracing messages.
When > 1, be more verbose.
{ return this->name_count; }
};
-/* See dwarf2read.h. */
+/* See dwarf2/read.h. */
dwarf2_per_objfile *
get_dwarf2_per_objfile (struct objfile *objfile)
dwarf2_per_objfile *per_objfile,
struct abbrev_table *abbrev_table,
dwarf2_cu *existing_cu,
- bool skip_partial);
+ bool skip_partial,
+ abbrev_cache *cache = nullptr);
explicit cutu_reader (struct dwarf2_per_cu_data *this_cu,
dwarf2_per_objfile *per_objfile,
DISABLE_COPY_AND_ASSIGN (cutu_reader);
+ cutu_reader (cutu_reader &&) = default;
+
const gdb_byte *info_ptr = nullptr;
struct die_info *comp_unit_die = nullptr;
bool dummy_p = false;
for dummy CUs. */
void keep ();
+ /* Release the abbrev table, transferring ownership to the
+ caller. */
+ abbrev_table_up release_abbrev_table ()
+ {
+ return std::move (m_abbrev_table_holder);
+ }
+
private:
void init_tu_and_read_dwo_dies (dwarf2_per_cu_data *this_cu,
dwarf2_per_objfile *per_objfile,
unsigned int has_type : 1;
unsigned int has_specification : 1;
unsigned int has_pc_info : 1;
+ unsigned int has_range_info : 1;
unsigned int may_be_inlined : 1;
/* This DIE has been marked DW_AT_main_subprogram. */
sect_offset sect_off;
} d {};
- /* If HAS_PC_INFO, the PC range associated with this DIE. */
- CORE_ADDR lowpc = 0;
- CORE_ADDR highpc = 0;
+ union
+ {
+ /* If HAS_PC_INFO, the PC range associated with this DIE. */
+ struct
+ {
+ CORE_ADDR lowpc;
+ CORE_ADDR highpc;
+ };
+ /* If HAS_RANGE_INFO, the ranges offset associated with this DIE. */
+ ULONGEST ranges_offset;
+ };
/* Pointer into the info_buffer (or types_buffer) pointing at the target of
DW_AT_sibling, if any. */
has_type = 0;
has_specification = 0;
has_pc_info = 0;
+ has_range_info = 0;
may_be_inlined = 0;
main_subprogram = 0;
scope_set = 0;
is_dwz = 0;
spec_is_dwz = 0;
canonical_name = 0;
+ /* Don't set these using NSDMI (Non-static data member initialisation),
+ because g++-4.8 will error out. */
+ lowpc = 0;
+ highpc = 0;
}
};
show_dwarf_max_cache_age (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file, _("The upper bound on the age of cached "
- "DWARF compilation units is %s.\n"),
- value);
+ gdb_printf (file, _("The upper bound on the age of cached "
+ "DWARF compilation units is %s.\n"),
+ value);
}
\f
/* local function prototypes */
(dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile,
const char *name);
-static void build_type_psymtabs_reader (const struct die_reader_specs *reader,
- const gdb_byte *info_ptr,
- struct die_info *type_unit_die);
+class cooked_index_storage;
+static void build_type_psymtabs_reader (cutu_reader *reader,
+ cooked_index_storage *storage);
static void dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile);
static line_header_up dwarf_decode_line_header (sect_offset sect_off,
struct dwarf2_cu *cu);
-static void dwarf_decode_lines (struct line_header *, const char *,
+static void dwarf_decode_lines (struct line_header *,
+ const file_and_directory &,
struct dwarf2_cu *, dwarf2_psymtab *,
CORE_ADDR, int decode_mapping);
static enum pc_bounds_kind dwarf2_get_pc_bounds (struct die_info *,
CORE_ADDR *, CORE_ADDR *,
struct dwarf2_cu *,
- dwarf2_psymtab *);
+ addrmap *,
+ void *);
static void get_scope_pc_bounds (struct die_info *,
CORE_ADDR *, CORE_ADDR *,
static const gdb_byte *skip_one_die (const struct die_reader_specs *reader,
const gdb_byte *info_ptr,
- const struct abbrev_info *abbrev);
+ const struct abbrev_info *abbrev,
+ bool do_skip_children = true);
static hashval_t partial_die_hash (const void *item);
static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit
(sect_offset sect_off, unsigned int offset_in_dwz,
- dwarf2_per_objfile *per_objfile);
+ dwarf2_per_bfd *per_bfd);
static void prepare_one_comp_unit (struct dwarf2_cu *cu,
struct die_info *comp_unit_die,
delete data;
}
-/* The return type of find_file_and_directory. Note, the enclosed
- string pointers are only valid while this object is valid. */
-
-struct file_and_directory
-{
- /* The filename. This is never NULL. */
- const char *name;
-
- /* The compilation directory. NULL if not known. If we needed to
- compute a new string, this points to COMP_DIR_STORAGE, otherwise,
- points directly to the DW_AT_comp_dir string attribute owned by
- the obstack that owns the DIE. */
- const char *comp_dir;
-
- /* If we needed to build a new string for comp_dir, this is what
- owns the storage. */
- std::string comp_dir_storage;
-};
+static file_and_directory &find_file_and_directory
+ (struct die_info *die, struct dwarf2_cu *cu);
-static file_and_directory find_file_and_directory (struct die_info *die,
- struct dwarf2_cu *cu);
+static const char *compute_include_file_name
+ (const struct line_header *lh,
+ const file_entry &fe,
+ const file_and_directory &cu_info,
+ gdb::unique_xmalloc_ptr<char> *name_holder);
static htab_up allocate_signatured_type_table ();
\f
+/* An iterator for all_comp_units that is based on index. This
+ approach makes it possible to iterate over all_comp_units safely,
+ when some caller in the loop may add new units. */
+
+class all_comp_units_iterator
+{
+public:
+
+ all_comp_units_iterator (dwarf2_per_bfd *per_bfd, bool start)
+ : m_per_bfd (per_bfd),
+ m_index (start ? 0 : per_bfd->all_comp_units.size ())
+ {
+ }
+
+ all_comp_units_iterator &operator++ ()
+ {
+ ++m_index;
+ return *this;
+ }
+
+ dwarf2_per_cu_data *operator* () const
+ {
+ return m_per_bfd->get_cu (m_index);
+ }
+
+ bool operator== (const all_comp_units_iterator &other) const
+ {
+ return m_index == other.m_index;
+ }
+
+
+ bool operator!= (const all_comp_units_iterator &other) const
+ {
+ return m_index != other.m_index;
+ }
+
+private:
+
+ dwarf2_per_bfd *m_per_bfd;
+ size_t m_index;
+};
+
+/* A range adapter for the all_comp_units_iterator. */
+class all_comp_units_range
+{
+public:
+
+ all_comp_units_range (dwarf2_per_bfd *per_bfd)
+ : m_per_bfd (per_bfd)
+ {
+ }
+
+ all_comp_units_iterator begin ()
+ {
+ return all_comp_units_iterator (m_per_bfd, true);
+ }
+
+ all_comp_units_iterator end ()
+ {
+ return all_comp_units_iterator (m_per_bfd, false);
+ }
+
+private:
+
+ dwarf2_per_bfd *m_per_bfd;
+};
+
/* See declaration. */
dwarf2_per_bfd::dwarf2_per_bfd (bfd *obfd, const dwarf2_debug_sections *names,
dwarf2_per_bfd::~dwarf2_per_bfd ()
{
for (auto &per_cu : all_comp_units)
- per_cu->imported_symtabs_free ();
+ {
+ per_cu->imported_symtabs_free ();
+ per_cu->free_cached_file_names ();
+ }
/* Everything else should be on this->obstack. */
}
bool
dwarf2_per_objfile::symtab_set_p (const dwarf2_per_cu_data *per_cu) const
{
- gdb_assert (per_cu->index < this->m_symtabs.size ());
-
- return this->m_symtabs[per_cu->index] != nullptr;
+ if (per_cu->index < this->m_symtabs.size ())
+ return this->m_symtabs[per_cu->index] != nullptr;
+ return false;
}
/* See read.h. */
compunit_symtab *
dwarf2_per_objfile::get_symtab (const dwarf2_per_cu_data *per_cu) const
{
- gdb_assert (per_cu->index < this->m_symtabs.size ());
-
- return this->m_symtabs[per_cu->index];
+ if (per_cu->index < this->m_symtabs.size ())
+ return this->m_symtabs[per_cu->index];
+ return nullptr;
}
/* See read.h. */
dwarf2_per_objfile::set_symtab (const dwarf2_per_cu_data *per_cu,
compunit_symtab *symtab)
{
- gdb_assert (per_cu->index < this->m_symtabs.size ());
+ if (per_cu->index >= this->m_symtabs.size ())
+ this->m_symtabs.resize (per_cu->index + 1);
gdb_assert (this->m_symtabs[per_cu->index] == nullptr);
-
this->m_symtabs[per_cu->index] = symtab;
}
*sizep = info->size;
}
+/* See dwarf2/read.h. */
+
+void
+dwarf2_per_bfd::map_info_sections (struct objfile *objfile)
+{
+ info.read (objfile);
+ abbrev.read (objfile);
+ line.read (objfile);
+ str.read (objfile);
+ str_offsets.read (objfile);
+ line_str.read (objfile);
+ ranges.read (objfile);
+ rnglists.read (objfile);
+ addr.read (objfile);
+
+ for (auto §ion : types)
+ section.read (objfile);
+}
+
\f
/* DWARF quick_symbol_functions support. */
/* The number of entries in file_names, real_names. */
unsigned int num_file_names;
+ /* The CU directory, as given by DW_AT_comp_dir. May be
+ nullptr. */
+ const char *comp_dir;
+
/* The file names from the line table, after being run through
file_full_name. */
const char **file_names;
expand_symtabs_matching. */
unsigned int mark : 1;
- /* True if we've tried to read the file table and found there isn't one.
- There will be no point in trying to read it again next time. */
- unsigned int no_file_data : 1;
+ /* True if we've tried to read the file table. There will be no
+ point in trying to read it again next time. */
+ bool files_read : 1;
};
/* A subclass of psymbol_functions that arranges to read the DWARF
return eq_stmt_list_entry (&ea->hash, &eb->hash);
}
-/* Delete function for a quick_file_names. */
-
-static void
-delete_file_name_entry (void *e)
-{
- struct quick_file_names *file_data = (struct quick_file_names *) e;
- int i;
-
- for (i = 0; i < file_data->num_file_names; ++i)
- {
- xfree ((void*) file_data->file_names[i]);
- if (file_data->real_names)
- xfree ((void*) file_data->real_names[i]);
- }
-
- /* The space for the struct itself lives on the obstack, so we don't
- free it here. */
-}
-
/* Create a quick_file_names hash table. */
static htab_up
{
return htab_up (htab_create_alloc (nr_initial_entries,
hash_file_name_entry, eq_file_name_entry,
- delete_file_name_entry, xcalloc, xfree));
+ nullptr, xcalloc, xfree));
}
/* Read in CU (dwarf2_cu object) for PER_CU in the context of PER_OBJFILE. This
&per_bfd->obstack);
}
-/* Read the address map data from DWARF-5 .debug_aranges, and use it to
- populate the psymtabs_addrmap. */
+/* Read the address map data from DWARF-5 .debug_aranges, and use it
+ to populate given addrmap. Returns true on success, false on
+ failure. */
-static void
-create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
- struct dwarf2_section_info *section)
+static bool
+read_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
+ struct dwarf2_section_info *section,
+ addrmap *mutable_map)
{
struct objfile *objfile = per_objfile->objfile;
bfd *abfd = objfile->obfd;
const CORE_ADDR baseaddr = objfile->text_section_offset ();
dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
- auto_obstack temp_obstack;
- addrmap *mutable_map = addrmap_create_mutable (&temp_obstack);
-
std::unordered_map<sect_offset,
dwarf2_per_cu_data *,
gdb::hash_enum<sect_offset>>
debug_info_offset_to_per_cu;
for (const auto &per_cu : per_bfd->all_comp_units)
{
+ /* A TU will not need aranges, and skipping them here is an easy
+ way of ignoring .debug_types -- and possibly seeing a
+ duplicate section offset -- entirely. The same applies to
+ units coming from a dwz file. */
+ if (per_cu->is_debug_types || per_cu->is_dwz)
+ continue;
+
const auto insertpair
= debug_info_offset_to_per_cu.emplace (per_cu->sect_off,
per_cu.get ());
warning (_("Section .debug_aranges in %s has duplicate "
"debug_info_offset %s, ignoring .debug_aranges."),
objfile_name (objfile), sect_offset_str (per_cu->sect_off));
- return;
+ return false;
}
}
plongest (entry_addr - section->buffer),
plongest (bytes_read + entry_length),
pulongest (section->size));
- return;
+ return false;
}
/* The version number. */
"has unsupported version %d, ignoring .debug_aranges."),
objfile_name (objfile),
plongest (entry_addr - section->buffer), version);
- return;
+ return false;
}
const uint64_t debug_info_offset
objfile_name (objfile),
plongest (entry_addr - section->buffer),
pulongest (debug_info_offset));
- return;
+ return false;
}
dwarf2_per_cu_data *const per_cu = per_cu_it->second;
"address_size %u is invalid, ignoring .debug_aranges."),
objfile_name (objfile),
plongest (entry_addr - section->buffer), address_size);
- return;
+ return false;
}
const uint8_t segment_selector_size = *addr++;
objfile_name (objfile),
plongest (entry_addr - section->buffer),
segment_selector_size);
- return;
+ return false;
}
/* Must pad to an alignment boundary that is twice the address
"ignoring .debug_aranges."),
objfile_name (objfile),
plongest (entry_addr - section->buffer));
- return;
+ return false;
}
ULONGEST start = extract_unsigned_integer (addr, address_size,
dwarf5_byte_order);
- baseaddr);
addrmap_set_empty (mutable_map, start, end - 1, per_cu);
}
+
+ per_cu->addresses_seen = true;
}
- per_bfd->index_addrmap = addrmap_create_fixed (mutable_map,
- &per_bfd->obstack);
+ return true;
+}
+
+/* Read the address map data from DWARF-5 .debug_aranges, and use it to
+ populate the psymtabs_addrmap. */
+
+static void
+create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
+ struct dwarf2_section_info *section)
+{
+ dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
+
+ auto_obstack temp_obstack;
+ addrmap *mutable_map = addrmap_create_mutable (&temp_obstack);
+
+ if (read_addrmap_from_aranges (per_objfile, section, mutable_map))
+ per_bfd->index_addrmap = addrmap_create_fixed (mutable_map,
+ &per_bfd->obstack);
}
/* A helper function that reads the .gdb_index from BUFFER and fills
++i;
map->constant_pool = buffer.slice (metadata[i]);
+ if (map->constant_pool.empty () && !map->symbol_table.empty ())
+ {
+ /* An empty constant pool implies that all symbol table entries are
+ empty. Make map->symbol_table.empty () == true. */
+ map->symbol_table
+ = offset_view (gdb::array_view<const gdb_byte> (symbol_table,
+ symbol_table));
+ }
+
return 1;
}
gdb_assert (! this_cu->is_debug_types);
+ this_cu->v.quick->files_read = true;
/* Our callers never want to match partial units -- instead they
will match the enclosing full CU. */
if (comp_unit_die->tag == DW_TAG_partial_unit)
- {
- this_cu->v.quick->no_file_data = 1;
- return;
- }
+ return;
lh_cu = this_cu;
slot = NULL;
lh = dwarf_decode_line_header (line_offset, cu);
}
- if (lh == NULL)
- {
- lh_cu->v.quick->no_file_data = 1;
- return;
- }
+
+ file_and_directory &fnd = find_file_and_directory (comp_unit_die, cu);
+
+ int offset = 0;
+ if (!fnd.is_unknown ())
+ ++offset;
+ else if (lh == nullptr)
+ return;
qfn = XOBNEW (&per_objfile->per_bfd->obstack, struct quick_file_names);
qfn->hash.dwo_unit = cu->dwo_unit;
qfn->hash.line_sect_off = line_offset;
- gdb_assert (slot != NULL);
- *slot = qfn;
+ /* There may not be a DW_AT_stmt_list. */
+ if (slot != nullptr)
+ *slot = qfn;
- file_and_directory fnd = find_file_and_directory (comp_unit_die, cu);
-
- int offset = 0;
- if (strcmp (fnd.name, "<unknown>") != 0)
- ++offset;
+ std::vector<const char *> include_names;
+ if (lh != nullptr)
+ {
+ for (const auto &entry : lh->file_names ())
+ {
+ gdb::unique_xmalloc_ptr<char> name_holder;
+ const char *include_name =
+ compute_include_file_name (lh.get (), entry, fnd, &name_holder);
+ if (include_name != nullptr)
+ {
+ include_name = per_objfile->objfile->intern (include_name);
+ include_names.push_back (include_name);
+ }
+ }
+ }
- qfn->num_file_names = offset + lh->file_names_size ();
+ qfn->num_file_names = offset + include_names.size ();
+ qfn->comp_dir = fnd.intern_comp_dir (per_objfile->objfile);
qfn->file_names =
XOBNEWVEC (&per_objfile->per_bfd->obstack, const char *,
qfn->num_file_names);
if (offset != 0)
- qfn->file_names[0] = xstrdup (fnd.name);
- for (int i = 0; i < lh->file_names_size (); ++i)
- qfn->file_names[i + offset] = lh->file_full_name (i + 1,
- fnd.comp_dir).release ();
+ qfn->file_names[0] = xstrdup (fnd.get_name ());
+
+ if (!include_names.empty ())
+ memcpy (&qfn->file_names[offset], include_names.data (),
+ include_names.size () * sizeof (const char *));
+
qfn->real_names = NULL;
lh_cu->v.quick->file_names = qfn;
/* Nor type unit groups. */
gdb_assert (! this_cu->type_unit_group_p ());
- if (this_cu->v.quick->file_names != NULL)
+ if (this_cu->v.quick->files_read)
return this_cu->v.quick->file_names;
- /* If we know there is no line data, no point in looking again. */
- if (this_cu->v.quick->no_file_data)
- return NULL;
cutu_reader reader (this_cu, per_objfile);
if (!reader.dummy_p)
dw2_get_file_names_reader (&reader, reader.comp_unit_die);
- if (this_cu->v.quick->no_file_data)
- return NULL;
return this_cu->v.quick->file_names;
}
qfn->num_file_names, const char *);
if (qfn->real_names[index] == NULL)
- qfn->real_names[index] = gdb_realpath (qfn->file_names[index]).release ();
+ {
+ const char *dirname = nullptr;
+
+ if (!IS_ABSOLUTE_PATH (qfn->file_names[index]))
+ dirname = qfn->comp_dir;
+
+ gdb::unique_xmalloc_ptr<char> fullname;
+ fullname = find_source_or_rewrite (qfn->file_names[index], dirname);
+
+ qfn->real_names[index] = fullname.release ();
+ }
return qfn->real_names[index];
}
if (cust == NULL)
return NULL;
- return compunit_primary_filetab (cust);
+ return cust->primary_filetab ();
}
-/* Traversal function for dw2_forget_cached_source_info. */
+/* See read.h. */
-static int
-dw2_free_cached_file_names (void **slot, void *info)
+void
+dwarf2_per_cu_data::free_cached_file_names ()
{
- struct quick_file_names *file_data = (struct quick_file_names *) *slot;
+ if (fnd != nullptr)
+ fnd->forget_fullname ();
- if (file_data->real_names)
- {
- int i;
+ if (per_bfd == nullptr || !per_bfd->using_index || v.quick == nullptr)
+ return;
- for (i = 0; i < file_data->num_file_names; ++i)
+ struct quick_file_names *file_data = v.quick->file_names;
+ if (file_data != nullptr && file_data->real_names != nullptr)
+ {
+ for (int i = 0; i < file_data->num_file_names; ++i)
{
- xfree ((void*) file_data->real_names[i]);
- file_data->real_names[i] = NULL;
+ xfree ((void *) file_data->real_names[i]);
+ file_data->real_names[i] = nullptr;
}
}
-
- return 1;
}
void
{
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
- htab_traverse_noresize (per_objfile->per_bfd->quick_file_names_table.get (),
- dw2_free_cached_file_names, NULL);
+ for (auto &per_cu : per_objfile->per_bfd->all_comp_units)
+ per_cu->free_cached_file_names ();
}
/* Struct used to manage iterating over all CUs looking for a symbol. */
if (!per_objfile->symtab_set_p (per_cu))
++count;
}
- printf_filtered (_(" Number of read CUs: %d\n"), total - count);
- printf_filtered (_(" Number of unread CUs: %d\n"), count);
+ gdb_printf (_(" Number of read CUs: %d\n"), total - count);
+ gdb_printf (_(" Number of unread CUs: %d\n"), count);
}
/* This dumps minimal information about the index.
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
gdb_assert (per_objfile->per_bfd->using_index);
- printf_filtered (".gdb_index:");
+ gdb_printf (".gdb_index:");
if (per_objfile->per_bfd->index_table != NULL)
{
- printf_filtered (" version %d\n",
- per_objfile->per_bfd->index_table->version);
+ gdb_printf (" version %d\n",
+ per_objfile->per_bfd->index_table->version);
}
else
- printf_filtered (" faked for \"readnow\"\n");
- printf_filtered ("\n");
+ gdb_printf (" faked for \"readnow\"\n");
+ gdb_printf ("\n");
}
void
if (per_objfile->symtab_set_p (per_cu.get ()))
continue;
+ if (per_cu->fnd != nullptr)
+ {
+ file_and_directory *fnd = per_cu->fnd.get ();
+
+ if (file_matcher (fnd->get_name (), false))
+ {
+ per_cu->v.quick->mark = 1;
+ continue;
+ }
+
+ /* Before we invoke realpath, which can get expensive when many
+ files are involved, do a quick comparison of the basenames. */
+ if ((basenames_may_differ
+ || file_matcher (lbasename (fnd->get_name ()), true))
+ && file_matcher (fnd->get_fullname (), false))
+ {
+ per_cu->v.quick->mark = 1;
+ continue;
+ }
+ }
+
quick_file_names *file_data = dw2_get_file_names (per_cu.get (),
per_objfile);
if (file_data == NULL)
dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
- if (symbol_matcher == NULL && lookup_name == NULL)
+ /* This invariant is documented in quick-functions.h. */
+ gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr);
+ if (lookup_name == nullptr)
{
- for (const auto &per_cu : per_objfile->per_bfd->all_comp_units)
+ for (dwarf2_per_cu_data *per_cu
+ : all_comp_units_range (per_objfile->per_bfd))
{
QUIT;
- if (!dw2_expand_symtabs_matching_one (per_cu.get (), per_objfile,
+ if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
file_matcher,
expansion_notify))
return false;
{
int i;
- if (COMPUNIT_BLOCKVECTOR (cust) != NULL
- && blockvector_contains_pc (COMPUNIT_BLOCKVECTOR (cust), pc))
+ if (cust->blockvector () != nullptr
+ && blockvector_contains_pc (cust->blockvector (), pc))
return cust;
if (cust->includes == NULL)
for (const auto &per_cu : per_objfile->per_bfd->all_comp_units)
{
- if (per_objfile->symtab_set_p (per_cu.get ()))
+ if (!per_cu->is_debug_types
+ && per_objfile->symtab_set_p (per_cu.get ()))
{
if (per_cu->v.quick->file_names != nullptr)
qfn_cache.insert (per_cu->v.quick->file_names);
}
}
- for (const auto &per_cu : per_objfile->per_bfd->all_comp_units)
+ for (dwarf2_per_cu_data *per_cu
+ : all_comp_units_range (per_objfile->per_bfd))
{
/* We only need to look at symtabs not already expanded. */
- if (per_objfile->symtab_set_p (per_cu.get ()))
+ if (per_cu->is_debug_types || per_objfile->symtab_set_p (per_cu))
continue;
- quick_file_names *file_data = dw2_get_file_names (per_cu.get (),
- per_objfile);
+ if (per_cu->fnd != nullptr)
+ {
+ file_and_directory *fnd = per_cu->fnd.get ();
+
+ const char *filename = fnd->get_name ();
+ const char *key = filename;
+ const char *fullname = nullptr;
+
+ if (need_fullname)
+ {
+ fullname = fnd->get_fullname ();
+ key = fullname;
+ }
+
+ if (!filenames_cache.seen (key))
+ fun (filename, fullname);
+ }
+
+ quick_file_names *file_data = dw2_get_file_names (per_cu, per_objfile);
if (file_data == nullptr
|| qfn_cache.find (file_data) != qfn_cache.end ())
continue;
for (int j = 0; j < file_data->num_file_names; ++j)
{
const char *filename = file_data->file_names[j];
- filenames_cache.seen (filename);
- }
- }
+ const char *key = filename;
+ const char *fullname = nullptr;
- filenames_cache.traverse ([&] (const char *filename)
- {
- gdb::unique_xmalloc_ptr<char> this_real_name;
+ if (need_fullname)
+ {
+ fullname = dw2_get_real_path (per_objfile, file_data, j);
+ key = fullname;
+ }
- if (need_fullname)
- this_real_name = gdb_realpath (filename);
- fun (filename, this_real_name.get ());
- });
+ if (!filenames_cache.seen (key))
+ fun (filename, fullname);
+ }
+ }
}
bool
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
gdb_assert (per_objfile->per_bfd->using_index);
- printf_filtered (".debug_names:");
+ gdb_printf (".debug_names:");
if (per_objfile->per_bfd->debug_names_table)
- printf_filtered (" exists\n");
+ gdb_printf (" exists\n");
else
- printf_filtered (" faked for \"readnow\"\n");
- printf_filtered ("\n");
+ gdb_printf (" faked for \"readnow\"\n");
+ gdb_printf ("\n");
}
void
dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
- if (symbol_matcher == NULL && lookup_name == NULL)
+ /* This invariant is documented in quick-functions.h. */
+ gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr);
+ if (lookup_name == nullptr)
{
- for (const auto &per_cu : per_objfile->per_bfd->all_comp_units)
+ for (dwarf2_per_cu_data *per_cu
+ : all_comp_units_range (per_objfile->per_bfd))
{
QUIT;
- if (!dw2_expand_symtabs_matching_one (per_cu.get (), per_objfile,
+ if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
file_matcher,
expansion_notify))
return false;
return global_index_cache.lookup_gdb_index (build_id, &dwz->index_cache_res);
}
+static quick_symbol_functions_up make_cooked_index_funcs ();
+
/* See dwarf2/public.h. */
void
if (per_bfd->using_index)
{
dwarf_read_debug_printf ("using_index already set");
- per_objfile->resize_symtabs ();
objfile->qf.push_front (make_dwarf_gdb_index ());
return;
}
create_all_comp_units (per_objfile);
per_bfd->quick_file_names_table
= create_quick_file_names_table (per_bfd->all_comp_units.size ());
- per_objfile->resize_symtabs ();
for (int i = 0; i < per_bfd->all_comp_units.size (); ++i)
{
if (per_bfd->debug_names_table != nullptr)
{
dwarf_read_debug_printf ("re-using shared debug names table");
- per_objfile->resize_symtabs ();
objfile->qf.push_front (make_dwarf_debug_names ());
return;
}
if (per_bfd->index_table != nullptr)
{
dwarf_read_debug_printf ("re-using shared index table");
- per_objfile->resize_symtabs ();
objfile->qf.push_front (make_dwarf_gdb_index ());
return;
}
+ if (per_bfd->cooked_index_table != nullptr)
+ {
+ dwarf_read_debug_printf ("re-using cooked index table");
+ objfile->qf.push_front (make_cooked_index_funcs ());
+ return;
+ }
+
/* There might already be partial symtabs built for this BFD. This happens
when loading the same binary twice with the index-cache enabled. If so,
don't try to read an index. The objfile / per_objfile initialization will
if (dwarf2_read_debug_names (per_objfile))
{
dwarf_read_debug_printf ("found debug names");
- per_objfile->resize_symtabs ();
objfile->qf.push_front (make_dwarf_debug_names ());
return;
}
get_gdb_index_contents_from_section<dwz_file>))
{
dwarf_read_debug_printf ("found gdb index from file");
- per_objfile->resize_symtabs ();
objfile->qf.push_front (make_dwarf_gdb_index ());
return;
}
{
dwarf_read_debug_printf ("found gdb index from cache");
global_index_cache.hit ();
- per_objfile->resize_symtabs ();
objfile->qf.push_front (make_dwarf_gdb_index ());
return;
}
}
else
psf->set_partial_symtabs (per_bfd->partial_symtabs);
- per_objfile->resize_symtabs ();
return;
}
dwarf2_build_psymtabs_hard (per_objfile);
psymtabs.keep ();
- per_objfile->resize_symtabs ();
-
/* (maybe) store an index in the cache. */
global_index_cache.store (per_objfile);
}
compunit_symtab *get_compunit_symtab (struct objfile *objfile) const override
{
- return nullptr;
+ compunit_symtab *cust = includer ()->get_compunit_symtab (objfile);
+ while (cust != nullptr && cust->user != nullptr)
+ cust = cust->user;
+ return cust;
}
private:
static void
dwarf2_build_include_psymtabs (struct dwarf2_cu *cu,
struct die_info *die,
+ const file_and_directory &fnd,
dwarf2_psymtab *pst)
{
line_header_up lh;
that we pass in the raw text_low here; that is ok because we're
only decoding the line table to make include partial symtabs, and
so the addresses aren't really used. */
- dwarf_decode_lines (lh.get (), pst->dirname, cu, pst,
+ dwarf_decode_lines (lh.get (), fnd, cu, pst,
pst->raw_text_low (), 1);
}
= per_objfile->per_bfd->allocate_signatured_type (sig);
signatured_type *sig_type = sig_type_holder.get ();
- per_objfile->resize_symtabs ();
-
per_objfile->per_bfd->all_comp_units.emplace_back
(sig_type_holder.release ());
if (per_objfile->per_bfd->using_index)
else
gdb_assert (sig_entry->v.psymtab == NULL);
gdb_assert (sig_entry->signature == dwo_entry->signature);
- gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0);
+ gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0
+ || (to_underlying (sig_entry->type_offset_in_section)
+ == to_underlying (dwo_entry->type_offset_in_tu)));
gdb_assert (sig_entry->type_unit_group == NULL);
- gdb_assert (sig_entry->dwo_unit == NULL);
+ gdb_assert (sig_entry->dwo_unit == NULL
+ || sig_entry->dwo_unit == dwo_entry);
sig_entry->section = dwo_entry->section;
sig_entry->sect_off = dwo_entry->sect_off;
if (sig_entry == NULL)
sig_entry = add_type_unit (per_objfile, sig, slot);
- fill_in_sig_entry_from_dwo_entry (per_objfile, sig_entry, dwo_entry);
+ if (sig_entry->dwo_unit == nullptr)
+ fill_in_sig_entry_from_dwo_entry (per_objfile, sig_entry, dwo_entry);
sig_entry->tu_read = 1;
return sig_entry;
}
if (dwarf_die_debug)
{
- fprintf_unfiltered (gdb_stdlog,
- "Read die from %s@0x%x of %s:\n",
- section->get_name (),
- (unsigned) (begin_info_ptr - section->buffer),
- bfd_get_filename (abfd));
+ gdb_printf (gdb_stdlog,
+ "Read die from %s@0x%x of %s:\n",
+ section->get_name (),
+ (unsigned) (begin_info_ptr - section->buffer),
+ bfd_get_filename (abfd));
dump_die (comp_unit_die, dwarf_die_debug);
}
static struct dwo_unit *
lookup_dwo_unit (dwarf2_cu *cu, die_info *comp_unit_die, const char *dwo_name)
{
+#if CXX_STD_THREAD
+ /* We need a lock here both to handle the DWO hash table, and BFD,
+ which is not thread-safe. */
+ static std::mutex dwo_lock;
+
+ std::lock_guard<std::mutex> guard (dwo_lock);
+#endif
+
dwarf2_per_cu_data *per_cu = cu->per_cu;
struct dwo_unit *dwo_unit;
const char *comp_dir;
dwarf2_per_objfile *per_objfile,
struct abbrev_table *abbrev_table,
dwarf2_cu *existing_cu,
- bool skip_partial)
+ bool skip_partial,
+ abbrev_cache *cache)
: die_reader_specs {},
m_this_cu (this_cu)
{
int rereading_dwo_cu = 0;
if (dwarf_die_debug)
- fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset %s\n",
- this_cu->is_debug_types ? "type" : "comp",
- sect_offset_str (this_cu->sect_off));
+ gdb_printf (gdb_stdlog, "Reading %s unit at offset %s\n",
+ this_cu->is_debug_types ? "type" : "comp",
+ sect_offset_str (this_cu->sect_off));
/* If we're reading a TU directly from a DWO file, including a virtual DWO
file (instead of going through the stub), short-circuit all of this. */
}
else
{
- /* If an existing_cu is provided, a dwarf2_cu must not exist for this_cu
- in per_objfile yet. */
- gdb_assert (per_objfile->get_cu (this_cu) == nullptr);
+ /* If an existing_cu is provided, a dwarf2_cu must not exist for
+ this_cu in per_objfile yet. Here, CACHE doubles as a flag to
+ let us know that the CU is being scanned using the parallel
+ indexer. This assert is avoided in this case because (1) it
+ is irrelevant, and (2) the get_cu method is not
+ thread-safe. */
+ gdb_assert (cache != nullptr
+ || per_objfile->get_cu (this_cu) == nullptr);
m_new_cu.reset (new dwarf2_cu (this_cu, per_objfile));
cu = m_new_cu.get ();
}
gdb_assert (cu->header.abbrev_sect_off == abbrev_table->sect_off);
else
{
- abbrev_section->read (objfile);
- m_abbrev_table_holder
- = abbrev_table::read (abbrev_section, cu->header.abbrev_sect_off);
- abbrev_table = m_abbrev_table_holder.get ();
+ if (cache != nullptr)
+ abbrev_table = cache->find (abbrev_section,
+ cu->header.abbrev_sect_off);
+ if (abbrev_table == nullptr)
+ {
+ abbrev_section->read (objfile);
+ m_abbrev_table_holder
+ = abbrev_table::read (abbrev_section, cu->header.abbrev_sect_off);
+ abbrev_table = m_abbrev_table_holder.get ();
+ }
}
/* Read the top level CU/TU die. */
const gdb_byte *begin_info_ptr, *info_ptr;
if (dwarf_die_debug)
- fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset %s\n",
- this_cu->is_debug_types ? "type" : "comp",
- sect_offset_str (this_cu->sect_off));
+ gdb_printf (gdb_stdlog, "Reading %s unit at offset %s\n",
+ this_cu->is_debug_types ? "type" : "comp",
+ sect_offset_str (this_cu->sect_off));
gdb_assert (per_objfile->get_cu (this_cu) == nullptr);
return pst;
}
+\f
-/* DIE reader function for process_psymtab_comp_unit. */
+/* An instance of this is created when scanning DWARF to create a
+ cooked index. */
-static void
-process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
- const gdb_byte *info_ptr,
- struct die_info *comp_unit_die,
- enum language pretend_language)
+class cooked_index_storage
{
- struct dwarf2_cu *cu = reader->cu;
- dwarf2_per_objfile *per_objfile = cu->per_objfile;
- dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
- struct objfile *objfile = per_objfile->objfile;
- struct gdbarch *gdbarch = objfile->arch ();
- struct dwarf2_per_cu_data *per_cu = cu->per_cu;
- CORE_ADDR baseaddr;
- CORE_ADDR best_lowpc = 0, best_highpc = 0;
- dwarf2_psymtab *pst;
- enum pc_bounds_kind cu_bounds_kind;
- const char *filename;
+public:
- gdb_assert (! per_cu->is_debug_types);
+ cooked_index_storage ()
+ : m_reader_hash (htab_create_alloc (10, hash_cutu_reader,
+ eq_cutu_reader,
+ htab_delete_entry<cutu_reader>,
+ xcalloc, xfree)),
+ m_index (new cooked_index),
+ m_addrmap_storage (),
+ m_addrmap (addrmap_create_mutable (&m_addrmap_storage))
+ {
+ }
- prepare_one_comp_unit (cu, comp_unit_die, pretend_language);
+ DISABLE_COPY_AND_ASSIGN (cooked_index_storage);
- /* Allocate a new partial symbol table structure. */
- gdb::unique_xmalloc_ptr<char> debug_filename;
- static const char artificial[] = "<artificial>";
- filename = dwarf2_string_attr (comp_unit_die, DW_AT_name, cu);
- if (filename == NULL)
- filename = "";
- else if (strcmp (filename, artificial) == 0)
- {
- debug_filename.reset (concat (artificial, "@",
- sect_offset_str (per_cu->sect_off),
- (char *) NULL));
- filename = debug_filename.get ();
- }
+ /* Return the current abbrev cache. */
+ abbrev_cache *get_abbrev_cache ()
+ {
+ return &m_abbrev_cache;
+ }
- pst = create_partial_symtab (per_cu, per_objfile, filename);
+ /* Return the DIE reader corresponding to PER_CU. If no such reader
+ has been registered, return NULL. */
+ cutu_reader *get_reader (dwarf2_per_cu_data *per_cu)
+ {
+ int index = per_cu->index;
+ return (cutu_reader *) htab_find_with_hash (m_reader_hash.get (),
+ &index, index);
+ }
- /* This must be done before calling dwarf2_build_include_psymtabs. */
+ /* Preserve READER by storing it in the local hash table. */
+ cutu_reader *preserve (std::unique_ptr<cutu_reader> reader)
+ {
+ m_abbrev_cache.add (reader->release_abbrev_table ());
+
+ int index = reader->cu->per_cu->index;
+ void **slot = htab_find_slot_with_hash (m_reader_hash.get (), &index,
+ index, INSERT);
+ gdb_assert (*slot == nullptr);
+ cutu_reader *result = reader.get ();
+ *slot = reader.release ();
+ return result;
+ }
+
+ /* Add an entry to the index. The arguments describe the entry; see
+ cooked-index.h. The new entry is returned. */
+ const cooked_index_entry *add (sect_offset die_offset, enum dwarf_tag tag,
+ cooked_index_flag flags,
+ const char *name,
+ const cooked_index_entry *parent_entry,
+ dwarf2_per_cu_data *per_cu)
+ {
+ return m_index->add (die_offset, tag, flags, name, parent_entry, per_cu);
+ }
+
+ /* Install the current addrmap into the index being constructed,
+ then transfer ownership of the index to the caller. */
+ std::unique_ptr<cooked_index> release ()
+ {
+ m_index->install_addrmap (m_addrmap);
+ return std::move (m_index);
+ }
+
+ /* Return the mutable addrmap that is currently being created. */
+ addrmap *get_addrmap ()
+ {
+ return m_addrmap;
+ }
+
+private:
+
+ /* Hash function for a cutu_reader. */
+ static hashval_t hash_cutu_reader (const void *a)
+ {
+ const cutu_reader *reader = (const cutu_reader *) a;
+ return reader->cu->per_cu->index;
+ }
+
+ /* Equality function for cutu_reader. */
+ static int eq_cutu_reader (const void *a, const void *b)
+ {
+ const cutu_reader *ra = (const cutu_reader *) a;
+ const int *rb = (const int *) b;
+ return ra->cu->per_cu->index == *rb;
+ }
+
+ /* The abbrev cache used by this indexer. */
+ abbrev_cache m_abbrev_cache;
+ /* A hash table of cutu_reader objects. */
+ htab_up m_reader_hash;
+ /* The index that is being constructed. */
+ std::unique_ptr<cooked_index> m_index;
+
+ /* Storage for the writeable addrmap. */
+ auto_obstack m_addrmap_storage;
+ /* A writeable addrmap being constructed by this scanner. */
+ addrmap *m_addrmap;
+};
+
+/* An instance of this is created to index a CU. */
+
+class cooked_indexer
+{
+public:
+
+ cooked_indexer (cooked_index_storage *storage,
+ dwarf2_per_cu_data *per_cu,
+ enum language language)
+ : m_index_storage (storage),
+ m_per_cu (per_cu),
+ m_language (language),
+ m_obstack (),
+ m_die_range_map (addrmap_create_mutable (&m_obstack))
+ {
+ }
+
+ DISABLE_COPY_AND_ASSIGN (cooked_indexer);
+
+ /* Index the given CU. */
+ void make_index (cutu_reader *reader);
+
+private:
+
+ /* A helper function to turn a section offset into an address that
+ can be used in an addrmap. */
+ CORE_ADDR form_addr (sect_offset offset, bool is_dwz)
+ {
+ CORE_ADDR value = to_underlying (offset);
+ if (is_dwz)
+ value |= ((CORE_ADDR) 1) << (8 * sizeof (CORE_ADDR) - 1);
+ return value;
+ }
+
+ /* A helper function to scan the PC bounds of READER and record them
+ in the storage's addrmap. */
+ void check_bounds (cutu_reader *reader);
+
+ /* Ensure that the indicated CU exists. The cutu_reader for it is
+ returned. FOR_SCANNING is true if the caller intends to scan all
+ the DIEs in the CU; when false, this use is assumed to be to look
+ up just a single DIE. */
+ cutu_reader *ensure_cu_exists (cutu_reader *reader,
+ dwarf2_per_objfile *per_objfile,
+ sect_offset sect_off,
+ bool is_dwz,
+ bool for_scanning);
+
+ /* Index DIEs in the READER starting at INFO_PTR. PARENT_ENTRY is
+ the entry for the enclosing scope (nullptr at top level). FULLY
+ is true when a full scan must be done -- in some languages,
+ function scopes must be fully explored in order to find nested
+ functions. This returns a pointer to just after the spot where
+ reading stopped. */
+ const gdb_byte *index_dies (cutu_reader *reader,
+ const gdb_byte *info_ptr,
+ const cooked_index_entry *parent_entry,
+ bool fully);
+
+ /* Scan the attributes for a given DIE and update the out
+ parameters. Returns a pointer to the byte after the DIE. */
+ const gdb_byte *scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
+ cutu_reader *reader,
+ const gdb_byte *watermark_ptr,
+ const gdb_byte *info_ptr,
+ const abbrev_info *abbrev,
+ const char **name,
+ const char **linkage_name,
+ cooked_index_flag *flags,
+ sect_offset *sibling_offset,
+ const cooked_index_entry **parent_entry,
+ CORE_ADDR *maybe_defer,
+ bool for_specification);
+
+ /* Handle DW_TAG_imported_unit, by scanning the DIE to find
+ DW_AT_import, and then scanning the referenced CU. Returns a
+ pointer to the byte after the DIE. */
+ const gdb_byte *index_imported_unit (cutu_reader *reader,
+ const gdb_byte *info_ptr,
+ const abbrev_info *abbrev);
+
+ /* Recursively read DIEs, recording the section offsets in
+ m_die_range_map and then calling index_dies. */
+ const gdb_byte *recurse (cutu_reader *reader,
+ const gdb_byte *info_ptr,
+ const cooked_index_entry *parent_entry,
+ bool fully);
+
+ /* The storage object, where the results are kept. */
+ cooked_index_storage *m_index_storage;
+ /* The CU that we are reading on behalf of. This object might be
+ asked to index one CU but to treat the results as if they come
+ from some including CU; in this case the including CU would be
+ recorded here. */
+ dwarf2_per_cu_data *m_per_cu;
+ /* The language that we're assuming when reading. */
+ enum language m_language;
+
+ /* Temporary storage. */
+ auto_obstack m_obstack;
+ /* An addrmap that maps from section offsets (see the form_addr
+ method) to newly-created entries. See m_deferred_entries to
+ understand this. */
+ addrmap *m_die_range_map;
+
+ /* A single deferred entry. */
+ struct deferred_entry
+ {
+ sect_offset die_offset;
+ const char *name;
+ CORE_ADDR spec_offset;
+ dwarf_tag tag;
+ cooked_index_flag flags;
+ };
+
+ /* The generated DWARF can sometimes have the declaration for a
+ method in a class (or perhaps namespace) scope, with the
+ definition appearing outside this scope... just one of the many
+ bad things about DWARF. In order to handle this situation, we
+ defer certain entries until the end of scanning, at which point
+ we'll know the containing context of all the DIEs that we might
+ have scanned. This vector stores these deferred entries. */
+ std::vector<deferred_entry> m_deferred_entries;
+};
+
+
+
+/* DIE reader function for process_psymtab_comp_unit. */
+
+static void
+process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
+ const gdb_byte *info_ptr,
+ struct die_info *comp_unit_die,
+ enum language pretend_language)
+{
+ struct dwarf2_cu *cu = reader->cu;
+ dwarf2_per_objfile *per_objfile = cu->per_objfile;
+ dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
+ struct objfile *objfile = per_objfile->objfile;
+ struct gdbarch *gdbarch = objfile->arch ();
+ struct dwarf2_per_cu_data *per_cu = cu->per_cu;
+ CORE_ADDR baseaddr;
+ CORE_ADDR best_lowpc = 0, best_highpc = 0;
+ dwarf2_psymtab *pst;
+ enum pc_bounds_kind cu_bounds_kind;
+
+ gdb_assert (! per_cu->is_debug_types);
+
+ prepare_one_comp_unit (cu, comp_unit_die, pretend_language);
+
+ /* Allocate a new partial symbol table structure. */
+ static const char artificial[] = "<artificial>";
+ file_and_directory &fnd = find_file_and_directory (comp_unit_die, cu);
+ if (strcmp (fnd.get_name (), artificial) == 0)
+ {
+ gdb::unique_xmalloc_ptr<char> debug_filename
+ (concat (artificial, "@",
+ sect_offset_str (per_cu->sect_off),
+ (char *) NULL));
+ fnd.set_name (std::move (debug_filename));
+ }
+
+ pst = create_partial_symtab (per_cu, per_objfile, fnd.get_name ());
+
+ /* This must be done before calling dwarf2_build_include_psymtabs. */
pst->dirname = dwarf2_string_attr (comp_unit_die, DW_AT_comp_dir, cu);
baseaddr = objfile->text_section_offset ();
/* Possibly set the default values of LOWPC and HIGHPC from
`DW_AT_ranges'. */
- cu_bounds_kind = dwarf2_get_pc_bounds (comp_unit_die, &best_lowpc,
- &best_highpc, cu, pst);
+ cu_bounds_kind
+ = dwarf2_get_pc_bounds (comp_unit_die, &best_lowpc,
+ &best_highpc, cu,
+ per_bfd->partial_symtabs->psymtabs_addrmap,
+ pst);
if (cu_bounds_kind == PC_BOUNDS_HIGH_LOW && best_lowpc < best_highpc)
{
CORE_ADDR low
/* Get the list of files included in the current compilation unit,
and build a psymtab for each of them. */
- dwarf2_build_include_psymtabs (cu, comp_unit_die, pst);
+ dwarf2_build_include_psymtabs (cu, comp_unit_die, fnd, pst);
dwarf_read_debug_printf ("Psymtab for %s unit @%s: %s - %s"
", %d global, %d static syms",
process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu,
dwarf2_per_objfile *per_objfile,
bool want_partial_unit,
- enum language pretend_language)
+ enum language pretend_language,
+ cooked_index_storage *storage)
{
/* If this compilation unit was already read in, free the
cached copy in order to read it in again. This is
necessary because we skipped some symbols when we first
read in the compilation unit (see load_partial_dies).
This problem could be avoided, but the benefit is unclear. */
- per_objfile->remove_cu (this_cu);
+ if (!per_objfile->per_bfd->using_index)
+ per_objfile->remove_cu (this_cu);
- cutu_reader reader (this_cu, per_objfile, nullptr, nullptr, false);
+ cutu_reader reader (this_cu, per_objfile, nullptr, nullptr, false,
+ (storage == nullptr
+ ? nullptr
+ : storage->get_abbrev_cache ()));
if (reader.comp_unit_die == nullptr)
return;
/* Nothing. */
}
else if (this_cu->is_debug_types)
- build_type_psymtabs_reader (&reader, reader.info_ptr,
- reader.comp_unit_die);
+ build_type_psymtabs_reader (&reader, storage);
else if (want_partial_unit
|| reader.comp_unit_die->tag != DW_TAG_partial_unit)
- process_psymtab_comp_unit_reader (&reader, reader.info_ptr,
- reader.comp_unit_die,
- pretend_language);
+ {
+ if (per_objfile->per_bfd->using_index)
+ {
+ bool nope = false;
+ if (this_cu->scanned.compare_exchange_strong (nope, true))
+ {
+ prepare_one_comp_unit (reader.cu, reader.comp_unit_die,
+ pretend_language);
+ gdb_assert (storage != nullptr);
+ cooked_indexer indexer (storage, this_cu,
+ reader.cu->per_cu->lang);
+ indexer.make_index (&reader);
+ }
+ }
+ else
+ process_psymtab_comp_unit_reader (&reader, reader.info_ptr,
+ reader.comp_unit_die,
+ pretend_language);
+ }
/* Age out any secondary CUs. */
per_objfile->age_comp_units ();
/* Reader function for build_type_psymtabs. */
static void
-build_type_psymtabs_reader (const struct die_reader_specs *reader,
- const gdb_byte *info_ptr,
- struct die_info *type_unit_die)
+build_type_psymtabs_reader (cutu_reader *reader,
+ cooked_index_storage *storage)
{
dwarf2_per_objfile *per_objfile = reader->cu->per_objfile;
struct dwarf2_cu *cu = reader->cu;
struct partial_die_info *first_die;
CORE_ADDR lowpc, highpc;
dwarf2_psymtab *pst;
+ const gdb_byte *info_ptr = reader->info_ptr;
+ struct die_info *type_unit_die = reader->comp_unit_die;
gdb_assert (per_cu->is_debug_types);
sig_type = (struct signatured_type *) per_cu;
tu_group->tus->push_back (sig_type);
prepare_one_comp_unit (cu, type_unit_die, language_minimal);
- pst = create_partial_symtab (per_cu, per_objfile, "");
- pst->anonymous = true;
- first_die = load_partial_dies (reader, info_ptr, 1);
+ if (per_objfile->per_bfd->using_index)
+ {
+ gdb_assert (storage != nullptr);
+ cooked_indexer indexer (storage, per_cu, cu->per_cu->lang);
+ indexer.make_index (reader);
+ }
+ else
+ {
+ pst = create_partial_symtab (per_cu, per_objfile, "");
+ pst->anonymous = true;
+
+ first_die = load_partial_dies (reader, info_ptr, 1);
- lowpc = (CORE_ADDR) -1;
- highpc = (CORE_ADDR) 0;
- scan_partial_symbols (first_die, &lowpc, &highpc, 0, cu);
+ lowpc = (CORE_ADDR) -1;
+ highpc = (CORE_ADDR) 0;
+ scan_partial_symbols (first_die, &lowpc, &highpc, 0, cu);
- pst->end ();
+ pst->end ();
+ }
}
/* Struct used to sort TUs by their abbreviation table offset. */
dwarf2_per_objfile->per_bfd->type_unit_groups. */
static void
-build_type_psymtabs (dwarf2_per_objfile *per_objfile)
+build_type_psymtabs (dwarf2_per_objfile *per_objfile,
+ cooked_index_storage *storage)
{
struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
abbrev_table_up abbrev_table;
cutu_reader reader (tu.sig_type, per_objfile,
abbrev_table.get (), nullptr, false);
if (!reader.dummy_p)
- build_type_psymtabs_reader (&reader, reader.info_ptr,
- reader.comp_unit_die);
+ build_type_psymtabs_reader (&reader, storage);
}
}
return 1;
}
+struct skeleton_data
+{
+ dwarf2_per_objfile *per_objfile;
+ cooked_index_storage *storage;
+};
+
/* Traversal function for process_skeletonless_type_unit.
Read a TU in a DWO file and build partial symbols for it. */
process_skeletonless_type_unit (void **slot, void *info)
{
struct dwo_unit *dwo_unit = (struct dwo_unit *) *slot;
- dwarf2_per_objfile *per_objfile = (dwarf2_per_objfile *) info;
+ skeleton_data *data = (skeleton_data *) info;
/* If this TU doesn't exist in the global table, add it and read it in. */
- if (per_objfile->per_bfd->signatured_types == NULL)
- per_objfile->per_bfd->signatured_types = allocate_signatured_type_table ();
+ if (data->per_objfile->per_bfd->signatured_types == NULL)
+ data->per_objfile->per_bfd->signatured_types
+ = allocate_signatured_type_table ();
signatured_type find_entry (dwo_unit->signature);
- slot = htab_find_slot (per_objfile->per_bfd->signatured_types.get (),
+ slot = htab_find_slot (data->per_objfile->per_bfd->signatured_types.get (),
&find_entry, INSERT);
/* If we've already seen this type there's nothing to do. What's happening
is we're doing our own version of comdat-folding here. */
/* This does the job that create_all_comp_units would have done for
this TU. */
signatured_type *entry
- = add_type_unit (per_objfile, dwo_unit->signature, slot);
- fill_in_sig_entry_from_dwo_entry (per_objfile, entry, dwo_unit);
+ = add_type_unit (data->per_objfile, dwo_unit->signature, slot);
+ fill_in_sig_entry_from_dwo_entry (data->per_objfile, entry, dwo_unit);
*slot = entry;
/* This does the job that build_type_psymtabs would have done. */
- cutu_reader reader (entry, per_objfile, nullptr, nullptr, false);
+ cutu_reader reader (entry, data->per_objfile, nullptr, nullptr, false);
if (!reader.dummy_p)
- build_type_psymtabs_reader (&reader, reader.info_ptr,
- reader.comp_unit_die);
+ build_type_psymtabs_reader (&reader, data->storage);
return 1;
}
Note: This can't be done until we know what all the DWO files are. */
static void
-process_skeletonless_type_units (dwarf2_per_objfile *per_objfile)
+process_skeletonless_type_units (dwarf2_per_objfile *per_objfile,
+ cooked_index_storage *storage)
{
+ skeleton_data data { per_objfile, storage };
+
/* Skeletonless TUs in DWP files without .gdb_index is not supported yet. */
if (get_dwp_file (per_objfile) == NULL
&& per_objfile->per_bfd->dwo_files != NULL)
{
htab_traverse_noresize (per_objfile->per_bfd->dwo_files.get (),
process_dwo_file_for_skeletonless_type_units,
- per_objfile);
+ &data);
}
}
scoped_restore restore_reading_psyms
= make_scoped_restore (&per_bfd->reading_partial_symbols, true);
- per_bfd->info.read (objfile);
+ per_bfd->map_info_sections (objfile);
/* Any cached compilation units will be linked by the per-objfile
read_in_chain. Make sure to free them when we're done. */
free_cached_comp_units freer (per_objfile);
- create_all_comp_units (per_objfile);
- build_type_psymtabs (per_objfile);
-
/* Create a temporary address map on a temporary obstack. We later
copy this to the final obstack. */
auto_obstack temp_obstack;
= make_scoped_restore (&per_bfd->partial_symtabs->psymtabs_addrmap,
addrmap_create_mutable (&temp_obstack));
- for (const auto &per_cu : per_bfd->all_comp_units)
+ cooked_index_storage index_storage;
+ cooked_index_storage *index_storage_ptr
+ = per_bfd->using_index ? &index_storage : nullptr;
+ create_all_comp_units (per_objfile);
+ build_type_psymtabs (per_objfile, index_storage_ptr);
+ std::vector<std::unique_ptr<cooked_index>> indexes;
+ if (per_bfd->using_index)
{
- if (per_cu->v.psymtab != NULL)
- /* In case a forward DW_TAG_imported_unit has read the CU already. */
- continue;
- process_psymtab_comp_unit (per_cu.get (), per_objfile, false,
- language_minimal);
+ per_bfd->quick_file_names_table
+ = create_quick_file_names_table (per_bfd->all_comp_units.size ());
+
+ if (!per_bfd->debug_aranges.empty ())
+ read_addrmap_from_aranges (per_objfile, &per_bfd->debug_aranges,
+ index_storage.get_addrmap ());
+
+ {
+ /* Ensure that complaints are handled correctly. */
+ complaint_interceptor complaint_handler;
+
+ using iter_type = typeof (per_bfd->all_comp_units.begin ());
+
+ /* Each thread returns a pair holding a cooked index, and a vector
+ of errors that should be printed. The latter is done because
+ GDB's I/O system is not thread-safe. run_on_main_thread could be
+ used, but that would mean the messages are printed after the
+ prompt, which looks weird. */
+ using result_type = std::pair<std::unique_ptr<cooked_index>,
+ std::vector<gdb_exception>>;
+ std::vector<result_type> results
+ = gdb::parallel_for_each (1, per_bfd->all_comp_units.begin (),
+ per_bfd->all_comp_units.end (),
+ [=] (iter_type iter, iter_type end)
+ {
+ std::vector<gdb_exception> errors;
+ cooked_index_storage thread_storage;
+ for (; iter != end; ++iter)
+ {
+ dwarf2_per_cu_data *per_cu = iter->get ();
+ try
+ {
+ process_psymtab_comp_unit (per_cu, per_objfile,
+ false,
+ language_minimal,
+ &thread_storage);
+ }
+ catch (gdb_exception &except)
+ {
+ errors.push_back (std::move (except));
+ }
+ }
+ return result_type (thread_storage.release (),
+ std::move (errors));
+ });
+
+ /* Only show a given exception a single time. */
+ std::unordered_set<gdb_exception> seen_exceptions;
+ for (auto &one_result : results)
+ {
+ indexes.push_back (std::move (one_result.first));
+ for (auto &one_exc : one_result.second)
+ {
+ if (seen_exceptions.insert (one_exc).second)
+ exception_print (gdb_stderr, one_exc);
+ }
+ }
+ }
+ }
+ else
+ {
+ for (const auto &per_cu : per_bfd->all_comp_units)
+ {
+ if (!per_bfd->using_index && per_cu->v.psymtab != NULL)
+ /* In case a forward DW_TAG_imported_unit has read the CU
+ already. */
+ continue;
+ process_psymtab_comp_unit (per_cu.get (), per_objfile, false,
+ language_minimal, nullptr);
+ }
}
/* This has to wait until we read the CUs, we need the list of DWOs. */
- process_skeletonless_type_units (per_objfile);
+ process_skeletonless_type_units (per_objfile, &index_storage);
/* Now that all TUs have been processed we can fill in the dependencies. */
- if (per_bfd->type_unit_groups != NULL)
+ if (!per_bfd->using_index && per_bfd->type_unit_groups != NULL)
{
htab_traverse_noresize (per_bfd->type_unit_groups.get (),
build_type_psymtab_dependencies, per_objfile);
if (dwarf_read_debug > 0)
print_tu_stats (per_objfile);
- set_partial_user (per_objfile);
-
- per_bfd->partial_symtabs->psymtabs_addrmap
- = addrmap_create_fixed (per_bfd->partial_symtabs->psymtabs_addrmap,
- per_bfd->partial_symtabs->obstack ());
- /* At this point we want to keep the address map. */
- save_psymtabs_addrmap.release ();
+ if (per_bfd->using_index)
+ {
+ indexes.push_back (index_storage.release ());
+ /* Remove any NULL entries. This might happen if parallel-for
+ decides to throttle the number of threads that were used. */
+ indexes.erase
+ (std::remove_if (indexes.begin (),
+ indexes.end (),
+ [] (const std::unique_ptr<cooked_index> &entry)
+ {
+ return entry == nullptr;
+ }),
+ indexes.end ());
+ indexes.shrink_to_fit ();
+ per_bfd->cooked_index_table.reset
+ (new cooked_index_vector (std::move (indexes)));
+
+ const cooked_index_entry *main_entry
+ = per_bfd->cooked_index_table->get_main ();
+ if (main_entry != nullptr)
+ set_objfile_main_name (objfile, main_entry->name,
+ main_entry->per_cu->lang);
+ }
+ else
+ {
+ set_partial_user (per_objfile);
+ per_bfd->partial_symtabs->psymtabs_addrmap
+ = addrmap_create_fixed (per_bfd->partial_symtabs->psymtabs_addrmap,
+ per_bfd->partial_symtabs->obstack ());
+ /* At this point we want to keep the address map. */
+ save_psymtabs_addrmap.release ();
+ }
dwarf_read_debug_printf ("Done building psymtabs of %s",
objfile_name (objfile));
}
this_cu->is_dwz = is_dwz;
this_cu->section = section;
+ if (per_objfile->per_bfd->using_index)
+ this_cu->v.quick = OBSTACK_ZALLOC (&per_objfile->per_bfd->obstack,
+ struct dwarf2_per_cu_quick_data);
+
info_ptr = info_ptr + this_cu->length;
per_objfile->per_bfd->all_comp_units.push_back (std::move (this_cu));
}
dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd);
if (dwz != NULL)
- read_comp_units_from_section (per_objfile, &dwz->info, &dwz->abbrev, 1,
- types_htab, rcuh_kind::COMPILE);
+ {
+ /* Pre-read the sections we'll need to construct an index. */
+ struct objfile *objfile = per_objfile->objfile;
+ dwz->abbrev.read (objfile);
+ dwz->info.read (objfile);
+ dwz->str.read (objfile);
+ dwz->line.read (objfile);
+ read_comp_units_from_section (per_objfile, &dwz->info, &dwz->abbrev, 1,
+ types_htab, rcuh_kind::COMPILE);
+ }
per_objfile->per_bfd->signatured_types = std::move (types_htab);
}
add_partial_enumeration (pdi, cu);
break;
case DW_TAG_base_type:
+ case DW_TAG_generic_subrange:
case DW_TAG_subrange_type:
/* File scope base type definitions are added to the partial
symbol table. */
}
per_cu = dwarf2_find_containing_comp_unit
- (pdi->d.sect_off, pdi->is_dwz, cu->per_objfile);
+ (pdi->d.sect_off, pdi->is_dwz,
+ cu->per_objfile->per_bfd);
/* Go read the partial unit, if needed. */
if (per_cu->v.psymtab == NULL)
process_psymtab_comp_unit (per_cu, cu->per_objfile, true,
- cu->per_cu->lang);
+ cu->per_cu->lang, nullptr);
if (pdi->die_parent == nullptr
&& per_cu->unit_type == DW_UT_compile
psymbol.domain = VAR_DOMAIN;
psymbol.aclass = LOC_BLOCK;
psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
- psymbol.ginfo.value.address = addr;
+ psymbol.ginfo.set_value_address (addr);
if (pdi->main_subprogram && actual_name != NULL)
set_objfile_main_name (objfile, actual_name, cu->per_cu->lang);
psymbol.domain = VAR_DOMAIN;
psymbol.aclass = LOC_STATIC;
psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
- psymbol.ginfo.value.address = addr;
+ psymbol.ginfo.set_value_address (addr);
where = psymbol_placement::GLOBAL;
}
}
psymbol.aclass = LOC_STATIC;
psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
if (has_loc)
- psymbol.ginfo.value.address = addr;
+ psymbol.ginfo.set_value_address (addr);
where = psymbol_placement::STATIC;
}
break;
case DW_TAG_typedef:
case DW_TAG_base_type:
case DW_TAG_subrange_type:
+ case DW_TAG_generic_subrange:
psymbol.domain = VAR_DOMAIN;
psymbol.aclass = LOC_TYPEDEF;
where = psymbol_placement::STATIC;
scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu);
}
+static int dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
+ CORE_ADDR *high_return, struct dwarf2_cu *cu,
+ addrmap *map, void *datum, dwarf_tag tag);
+
/* Read a partial die corresponding to a subprogram or an inlined
subprogram and create a partial symbol for that subprogram.
When the CU language allows it, this routine also defines a partial
}
}
- if (pdi->has_pc_info || (!pdi->is_external && pdi->may_be_inlined))
+ if (pdi->has_range_info
+ && dwarf2_ranges_read (pdi->ranges_offset, &pdi->lowpc, &pdi->highpc,
+ cu,
+ (set_addrmap
+ ? cu->per_objfile->per_bfd->partial_symtabs->psymtabs_addrmap
+ : nullptr),
+ set_addrmap ? cu->per_cu->v.psymtab : nullptr,
+ pdi->tag))
+ {
+ if (pdi->lowpc < *lowpc)
+ *lowpc = pdi->lowpc;
+ if (pdi->highpc > *highpc)
+ *highpc = pdi->highpc;
+ }
+
+ if (pdi->has_pc_info || pdi->has_range_info
+ || (!pdi->is_external && pdi->may_be_inlined))
{
if (!pdi->is_declaration)
/* Ignore subprogram DIEs that do not have a name, they are
/* Scan the debug information for CU starting at INFO_PTR in buffer BUFFER.
INFO_PTR should point just after the initial uleb128 of a DIE, and the
abbrev corresponding to that skipped uleb128 should be passed in
- ABBREV. Returns a pointer to this DIE's sibling, skipping any
- children. */
+ ABBREV.
+
+ If DO_SKIP_CHILDREN is true, or if the DIE has no children, this
+ returns a pointer to this DIE's sibling, skipping any children.
+ Otherwise, returns a pointer to the DIE's first child. */
static const gdb_byte *
skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
- const struct abbrev_info *abbrev)
+ const struct abbrev_info *abbrev, bool do_skip_children)
{
unsigned int bytes_read;
struct attribute attr;
const gdb_byte *buffer_end = reader->buffer_end;
unsigned int form, i;
+ if (do_skip_children && abbrev->sibling_offset != (unsigned short) -1)
+ {
+ /* We only handle DW_FORM_ref4 here. */
+ const gdb_byte *sibling_data = info_ptr + abbrev->sibling_offset;
+ unsigned int offset = read_4_bytes (abfd, sibling_data);
+ const gdb_byte *sibling_ptr
+ = buffer + to_underlying (cu->header.sect_off) + offset;
+ if (sibling_ptr >= info_ptr && sibling_ptr < reader->buffer_end)
+ return sibling_ptr;
+ /* Fall through to the slow way. */
+ }
+ else if (abbrev->size_if_constant != 0)
+ {
+ info_ptr += abbrev->size_if_constant;
+ if (do_skip_children && abbrev->has_children)
+ return skip_children (reader, info_ptr);
+ return info_ptr;
+ }
+
for (i = 0; i < abbrev->num_attrs; i++)
{
/* The only abbrev we care about is DW_AT_sibling. */
- if (abbrev->attrs[i].name == DW_AT_sibling)
+ if (do_skip_children && abbrev->attrs[i].name == DW_AT_sibling)
{
read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
if (attr.form == DW_FORM_ref_addr)
}
}
- if (abbrev->has_children)
+ if (do_skip_children && abbrev->has_children)
return skip_children (reader, info_ptr);
else
return info_ptr;
struct symbol *sym = list->symbol[i];
if (sym->language () == language_go
- && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ && sym->aclass () == LOC_BLOCK)
{
gdb::unique_xmalloc_ptr<char> this_package_name
(go_symbol_package_name (sym));
sym->compute_and_set_names (saved_package_name, false, objfile->per_bfd);
/* This is not VAR_DOMAIN because we want a way to ensure a lookup of,
e.g., "main" finds the "main" module and not C's main(). */
- SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
- SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
- SYMBOL_TYPE (sym) = type;
+ sym->set_domain (STRUCT_DOMAIN);
+ sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_type (type);
add_symbol_to_list (sym, cu->get_builder ()->get_global_symbols ());
}
#define RUST_ENUM_PREFIX "RUST$ENCODED$ENUM$"
if (type->num_fields () == 1
- && startswith (TYPE_FIELD_NAME (type, 0), RUST_ENUM_PREFIX))
+ && startswith (type->field (0).name (), RUST_ENUM_PREFIX))
{
- const char *name = TYPE_FIELD_NAME (type, 0) + strlen (RUST_ENUM_PREFIX);
+ const char *name = type->field (0).name () + strlen (RUST_ENUM_PREFIX);
/* Decode the field name to find the offset of the
discriminant. */
name = tail;
if (*name != '$'
|| index >= field_type->num_fields ()
- || (TYPE_FIELD_LOC_KIND (field_type, index)
+ || (field_type->field (index).loc_kind ()
!= FIELD_LOC_KIND_BITPOS))
{
complaint (_("Could not parse Rust enum encoding string \"%s\""
"[in module %s]"),
- TYPE_FIELD_NAME (type, 0),
+ type->field (0).name (),
objfile_name (objfile));
return;
}
++name;
- bit_offset += TYPE_FIELD_BITPOS (field_type, index);
+ bit_offset += field_type->field (index).loc_bitpos ();
field_type = field_type->field (index).type ();
}
/* Put the discriminant at index 0. */
type->field (0).set_type (field_type);
TYPE_FIELD_ARTIFICIAL (type, 0) = 1;
- TYPE_FIELD_NAME (type, 0) = "<<discriminant>>";
- SET_FIELD_BITPOS (type->field (0), bit_offset);
+ type->field (0).set_name ("<<discriminant>>");
+ type->field (0).set_loc_bitpos (bit_offset);
/* The order of fields doesn't really matter, so put the real
field at index 1 and the data-less field at index 2. */
type->field (1) = saved_field;
- TYPE_FIELD_NAME (type, 1)
- = rust_last_path_segment (type->field (1).type ()->name ());
+ type->field (1).set_name
+ (rust_last_path_segment (type->field (1).type ()->name ()));
type->field (1).type ()->set_name
(rust_fully_qualify (&objfile->objfile_obstack, type->name (),
- TYPE_FIELD_NAME (type, 1)));
+ type->field (1).name ()));
const char *dataless_name
= rust_fully_qualify (&objfile->objfile_obstack, type->name (),
type->field (2).set_type (dataless_type);
/* NAME points into the original discriminant name, which
already has the correct lifetime. */
- TYPE_FIELD_NAME (type, 2) = name;
- SET_FIELD_BITPOS (type->field (2), 0);
+ type->field (2).set_name (name);
+ type->field (2).set_loc_bitpos (0);
/* Indicate that this is a variant type. */
static discriminant_range ranges[1] = { { 0, 0 } };
}
/* A union with a single anonymous field is probably an old-style
univariant enum. */
- else if (type->num_fields () == 1 && streq (TYPE_FIELD_NAME (type, 0), ""))
+ else if (type->num_fields () == 1 && streq (type->field (0).name (), ""))
{
/* Smash this type to be a structure type. We have to do this
because the type has already been recorded. */
struct type *field_type = type->field (0).type ();
const char *variant_name
= rust_last_path_segment (field_type->name ());
- TYPE_FIELD_NAME (type, 0) = variant_name;
+ type->field (0).set_name (variant_name);
field_type->set_name
(rust_fully_qualify (&objfile->objfile_obstack,
type->name (), variant_name));
/* Could be data-less variant, so keep going. */
disr_type = nullptr;
}
- else if (strcmp (TYPE_FIELD_NAME (disr_type, 0),
+ else if (strcmp (disr_type->field (0).name (),
"RUST$ENUM$DISR") != 0)
{
/* Not a Rust enum. */
/* Install the discriminant at index 0 in the union. */
type->field (0) = *disr_field;
TYPE_FIELD_ARTIFICIAL (type, 0) = 1;
- TYPE_FIELD_NAME (type, 0) = "<<discriminant>>";
+ type->field (0).set_name ("<<discriminant>>");
/* We need a way to find the correct discriminant given a
variant name. For convenience we build a map here. */
std::unordered_map<std::string, ULONGEST> discriminant_map;
for (int i = 0; i < enum_type->num_fields (); ++i)
{
- if (TYPE_FIELD_LOC_KIND (enum_type, i) == FIELD_LOC_KIND_ENUMVAL)
+ if (enum_type->field (i).loc_kind () == FIELD_LOC_KIND_ENUMVAL)
{
const char *name
- = rust_last_path_segment (TYPE_FIELD_NAME (enum_type, i));
- discriminant_map[name] = TYPE_FIELD_ENUMVAL (enum_type, i);
+ = rust_last_path_segment (enum_type->field (i).name ());
+ discriminant_map[name] = enum_type->field (i).loc_enumval ();
}
}
sub_type->set_num_fields (sub_type->num_fields () - 1);
sub_type->set_fields (sub_type->fields () + 1);
}
- TYPE_FIELD_NAME (type, i) = variant_name;
+ type->field (i).set_name (variant_name);
sub_type->set_name
(rust_fully_qualify (&objfile->objfile_obstack,
type->name (), variant_name));
get_scope_pc_bounds (cu->dies, &lowpc, &highpc, cu);
addr = gdbarch_adjust_dwarf2_addr (gdbarch, highpc + baseaddr);
- static_block = cu->get_builder ()->end_symtab_get_static_block (addr, 0, 1);
+ static_block
+ = cu->get_builder ()->end_compunit_symtab_get_static_block (addr, 0, 1);
/* If the comp unit has DW_AT_ranges, it may have discontiguous ranges.
Also, DW_AT_ranges may record ranges not belonging to any child DIEs
this comp unit. */
dwarf2_record_block_ranges (cu->dies, static_block, baseaddr, cu);
- cust = cu->get_builder ()->end_symtab_from_static_block (static_block,
- SECT_OFF_TEXT (objfile),
- 0);
+ cust = cu->get_builder ()->end_compunit_symtab_from_static_block
+ (static_block, SECT_OFF_TEXT (objfile), 0);
if (cust != NULL)
{
compilation is from a C file generated by language preprocessors, do
not set the language if it was already deduced by start_subfile. */
if (!(cu->per_cu->lang == language_c
- && COMPUNIT_FILETABS (cust)->language != language_unknown))
- COMPUNIT_FILETABS (cust)->language = cu->per_cu->lang;
+ && cust->primary_filetab ()->language () != language_unknown))
+ cust->primary_filetab ()->set_language (cu->per_cu->lang);
/* GCC-4.0 has started to support -fvar-tracking. GCC-3.x still can
produce DW_AT_location with location lists but it can be possibly
options - this waits on GCC PR other/32998 (-frecord-gcc-switches).
*/
if (cu->has_loclist && gcc_4_minor >= 5)
- cust->locations_valid = 1;
+ cust->set_locations_valid (true);
if (gcc_4_minor >= 5)
- cust->epilogue_unwind_valid = 1;
+ cust->set_epilogue_unwind_valid (true);
- cust->call_site_htab = cu->call_site_htab;
+ cust->set_call_site_htab (cu->call_site_htab);
}
per_objfile->set_symtab (cu->per_cu, cust);
do not set the language if it was already deduced by
start_subfile. */
if (!(cu->per_cu->lang == language_c
- && COMPUNIT_FILETABS (cust)->language != language_c))
- COMPUNIT_FILETABS (cust)->language = cu->per_cu->lang;
+ && cust->primary_filetab ()->language () != language_c))
+ cust->primary_filetab ()->set_language (cu->per_cu->lang);
}
}
else
bool is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz);
dwarf2_per_objfile *per_objfile = cu->per_objfile;
dwarf2_per_cu_data *per_cu
- = dwarf2_find_containing_comp_unit (sect_off, is_dwz, per_objfile);
+ = dwarf2_find_containing_comp_unit (sect_off, is_dwz,
+ per_objfile->per_bfd);
/* We're importing a C++ compilation unit with tag DW_TAG_compile_unit
into another compilation unit, at root level. Regard this as a hint,
case DW_TAG_interface_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
+ case DW_TAG_namelist:
process_structure_scope (die, cu);
break;
case DW_TAG_enumeration_type:
/* FALLTHROUGH */
case DW_TAG_base_type:
case DW_TAG_subrange_type:
+ case DW_TAG_generic_subrange:
case DW_TAG_typedef:
/* Add a typedef symbol for the type definition, if it has a
DW_AT_name. */
else if (bytes != NULL)
{
v = allocate_value (type);
- memcpy (value_contents_writeable (v), bytes,
+ memcpy (value_contents_writeable (v).data (), bytes,
TYPE_LENGTH (type));
}
else
to look up their definition from their declaration so
the only disadvantage remains the minimal symbol variant
`long name(params)' does not have the proper inferior type. */
- demangled.reset (gdb_demangle (mangled,
- (DMGL_PARAMS | DMGL_ANSI
- | DMGL_RET_DROP)));
+ demangled = gdb_demangle (mangled, (DMGL_PARAMS | DMGL_ANSI
+ | DMGL_RET_DROP));
}
if (demangled)
canon = demangled.get ();
return cu->producer_is_gcc_lt_4_3;
}
-static file_and_directory
+static file_and_directory &
find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu)
{
- file_and_directory res;
+ if (cu->per_cu->fnd != nullptr)
+ return *cu->per_cu->fnd;
/* Find the filename. Do not use dwarf2_name here, since the filename
is not a source language identifier. */
- res.name = dwarf2_string_attr (die, DW_AT_name, cu);
- res.comp_dir = dwarf2_string_attr (die, DW_AT_comp_dir, cu);
-
- if (res.comp_dir == NULL
- && producer_is_gcc_lt_4_3 (cu) && res.name != NULL
- && IS_ABSOLUTE_PATH (res.name))
- {
- res.comp_dir_storage = ldirname (res.name);
- if (!res.comp_dir_storage.empty ())
- res.comp_dir = res.comp_dir_storage.c_str ();
- }
- if (res.comp_dir != NULL)
- {
- /* Irix 6.2 native cc prepends <machine>.: to the compilation
- directory, get rid of it. */
- const char *cp = strchr (res.comp_dir, ':');
-
- if (cp && cp != res.comp_dir && cp[-1] == '.' && cp[1] == '/')
- res.comp_dir = cp + 1;
- }
+ file_and_directory res (dwarf2_string_attr (die, DW_AT_name, cu),
+ dwarf2_string_attr (die, DW_AT_comp_dir, cu));
- if (res.name == NULL)
- res.name = "<unknown>";
+ if (res.get_comp_dir () == nullptr
+ && producer_is_gcc_lt_4_3 (cu)
+ && res.get_name () != nullptr
+ && IS_ABSOLUTE_PATH (res.get_name ()))
+ res.set_comp_dir (ldirname (res.get_name ()));
- return res;
+ cu->per_cu->fnd.reset (new file_and_directory (std::move (res)));
+ return *cu->per_cu->fnd;
}
/* Handle DW_AT_stmt_list for a compilation unit.
static void
handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
- const char *comp_dir, CORE_ADDR lowpc) /* ARI: editCase function */
+ const file_and_directory &fnd, CORE_ADDR lowpc) /* ARI: editCase function */
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
struct attribute *attr;
gdb_assert (die->tag != DW_TAG_partial_unit);
}
decode_mapping = (die->tag != DW_TAG_partial_unit);
- dwarf_decode_lines (cu->line_header, comp_dir, cu, NULL, lowpc,
+ dwarf_decode_lines (cu->line_header, fnd, cu, nullptr, lowpc,
decode_mapping);
}
lowpc = highpc;
lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
- file_and_directory fnd = find_file_and_directory (die, cu);
+ file_and_directory &fnd = find_file_and_directory (die, cu);
- cu->start_symtab (fnd.name, fnd.comp_dir, lowpc);
+ cu->start_compunit_symtab (fnd.get_name (), fnd.intern_comp_dir (objfile),
+ lowpc);
gdb_assert (per_objfile->sym_cu == nullptr);
scoped_restore restore_sym_cu
/* Decode line number information if present. We do this before
processing child DIEs, so that the line header table is available
- for DW_AT_decl_file. */
- handle_DW_AT_stmt_list (die, cu, fnd.comp_dir, lowpc);
+ for DW_AT_decl_file. The PC check is here because, if LOWPC and
+ HIGHPC are both 0x0, then there won't be any interesting code in
+ the CU, but a check later on (in
+ lnp_state_machine::check_line_address) will fail to properly
+ exclude an entry that was removed via --gc-sections. */
+ if (lowpc != highpc)
+ handle_DW_AT_stmt_list (die, cu, fnd, lowpc);
/* Process all dies in compilation unit. */
if (die->child != NULL)
if (lh == NULL)
{
if (first_time)
- start_symtab ("", NULL, 0);
+ start_compunit_symtab ("", NULL, 0);
else
{
gdb_assert (tug_unshare->symtabs == NULL);
gdb_assert (m_builder == nullptr);
struct compunit_symtab *cust = tug_unshare->compunit_symtab;
m_builder.reset (new struct buildsym_compunit
- (COMPUNIT_OBJFILE (cust), "",
- COMPUNIT_DIRNAME (cust),
+ (cust->objfile (), "",
+ cust->dirname (),
compunit_language (cust),
0, cust));
list_in_scope = get_builder ()->get_file_symbols ();
if (first_time)
{
- struct compunit_symtab *cust = start_symtab ("", NULL, 0);
+ struct compunit_symtab *cust = start_compunit_symtab ("", NULL, 0);
/* Note: We don't assign tu_group->compunit_symtab yet because we're
still initializing it, and our caller (a few levels up)
time. */
tug_unshare->symtabs
- = XOBNEWVEC (&COMPUNIT_OBJFILE (cust)->objfile_obstack,
+ = XOBNEWVEC (&cust->objfile ()->objfile_obstack,
struct symtab *, line_header->file_names_size ());
auto &file_names = line_header->file_names ();
gdb_assert (m_builder == nullptr);
struct compunit_symtab *cust = tug_unshare->compunit_symtab;
m_builder.reset (new struct buildsym_compunit
- (COMPUNIT_OBJFILE (cust), "",
- COMPUNIT_DIRNAME (cust),
+ (cust->objfile (), "",
+ cust->dirname (),
compunit_language (cust),
0, cust));
list_in_scope = get_builder ()->get_file_symbols ();
gdb::unique_xmalloc_ptr<char> search_path_holder;
if (search_cwd)
{
- if (*debug_file_directory != '\0')
+ if (!debug_file_directory.empty ())
{
search_path_holder.reset (concat (".", dirname_separator_string,
- debug_file_directory,
+ debug_file_directory.c_str (),
(char *) NULL));
search_path = search_path_holder.get ();
}
search_path = ".";
}
else
- search_path = debug_file_directory;
+ search_path = debug_file_directory.c_str ();
/* Add the path for the executable binary to the list of search paths. */
std::string objfile_dir = ldirname (objfile_name (per_objfile->objfile));
/* That didn't work, try debug-file-directory, which, despite its name,
is a list of paths. */
- if (*debug_file_directory == '\0')
+ if (debug_file_directory.empty ())
return NULL;
return try_open_dwop_file (per_objfile, file_name,
size of each of the DWO debugging sections we are interested in. */
static void
-dwarf2_locate_dwo_sections (bfd *abfd, asection *sectp,
- dwo_sections *dwo_sections)
+dwarf2_locate_dwo_sections (struct objfile *objfile, bfd *abfd,
+ asection *sectp, dwo_sections *dwo_sections)
{
const struct dwop_section_names *names = &dwop_section_names;
+ struct dwarf2_section_info *dw_sect = nullptr;
+
if (names->abbrev_dwo.matches (sectp->name))
- {
- dwo_sections->abbrev.s.section = sectp;
- dwo_sections->abbrev.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->abbrev;
else if (names->info_dwo.matches (sectp->name))
- {
- dwo_sections->info.s.section = sectp;
- dwo_sections->info.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->info;
else if (names->line_dwo.matches (sectp->name))
- {
- dwo_sections->line.s.section = sectp;
- dwo_sections->line.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->line;
else if (names->loc_dwo.matches (sectp->name))
- {
- dwo_sections->loc.s.section = sectp;
- dwo_sections->loc.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->loc;
else if (names->loclists_dwo.matches (sectp->name))
- {
- dwo_sections->loclists.s.section = sectp;
- dwo_sections->loclists.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->loclists;
else if (names->macinfo_dwo.matches (sectp->name))
- {
- dwo_sections->macinfo.s.section = sectp;
- dwo_sections->macinfo.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->macinfo;
else if (names->macro_dwo.matches (sectp->name))
- {
- dwo_sections->macro.s.section = sectp;
- dwo_sections->macro.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->macro;
else if (names->rnglists_dwo.matches (sectp->name))
- {
- dwo_sections->rnglists.s.section = sectp;
- dwo_sections->rnglists.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->rnglists;
else if (names->str_dwo.matches (sectp->name))
- {
- dwo_sections->str.s.section = sectp;
- dwo_sections->str.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->str;
else if (names->str_offsets_dwo.matches (sectp->name))
- {
- dwo_sections->str_offsets.s.section = sectp;
- dwo_sections->str_offsets.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwo_sections->str_offsets;
else if (names->types_dwo.matches (sectp->name))
{
struct dwarf2_section_info type_section;
memset (&type_section, 0, sizeof (type_section));
- type_section.s.section = sectp;
- type_section.size = bfd_section_size (sectp);
dwo_sections->types.push_back (type_section);
+ dw_sect = &dwo_sections->types.back ();
+ }
+
+ if (dw_sect != nullptr)
+ {
+ dw_sect->s.section = sectp;
+ dw_sect->size = bfd_section_size (sectp);
+ dw_sect->read (objfile);
}
}
dwo_file->dbfd = std::move (dbfd);
for (asection *sec : gdb_bfd_sections (dwo_file->dbfd))
- dwarf2_locate_dwo_sections (dwo_file->dbfd.get (), sec,
- &dwo_file->sections);
+ dwarf2_locate_dwo_sections (per_objfile->objfile, dwo_file->dbfd.get (),
+ sec, &dwo_file->sections);
create_cus_hash_table (per_objfile, cu, *dwo_file, dwo_file->sections.info,
dwo_file->cus);
we are interested in. */
static void
-dwarf2_locate_common_dwp_sections (bfd *abfd, asection *sectp,
- dwp_file *dwp_file)
+dwarf2_locate_common_dwp_sections (struct objfile *objfile, bfd *abfd,
+ asection *sectp, dwp_file *dwp_file)
{
const struct dwop_section_names *names = &dwop_section_names;
unsigned int elf_section_nr = elf_section_data (sectp)->this_idx;
dwp_file->elf_sections[elf_section_nr] = sectp;
/* Look for specific sections that we need. */
+ struct dwarf2_section_info *dw_sect = nullptr;
if (names->str_dwo.matches (sectp->name))
- {
- dwp_file->sections.str.s.section = sectp;
- dwp_file->sections.str.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.str;
else if (names->cu_index.matches (sectp->name))
- {
- dwp_file->sections.cu_index.s.section = sectp;
- dwp_file->sections.cu_index.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.cu_index;
else if (names->tu_index.matches (sectp->name))
+ dw_sect = &dwp_file->sections.tu_index;
+
+ if (dw_sect != nullptr)
{
- dwp_file->sections.tu_index.s.section = sectp;
- dwp_file->sections.tu_index.size = bfd_section_size (sectp);
+ dw_sect->s.section = sectp;
+ dw_sect->size = bfd_section_size (sectp);
+ dw_sect->read (objfile);
}
}
have version 1 or 2 or 5 until we parse the cu_index/tu_index sections. */
static void
-dwarf2_locate_v2_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
+dwarf2_locate_v2_dwp_sections (struct objfile *objfile, bfd *abfd,
+ asection *sectp, void *dwp_file_ptr)
{
struct dwp_file *dwp_file = (struct dwp_file *) dwp_file_ptr;
const struct dwop_section_names *names = &dwop_section_names;
dwp_file->elf_sections[elf_section_nr] = sectp;
/* Look for specific sections that we need. */
+ struct dwarf2_section_info *dw_sect = nullptr;
if (names->abbrev_dwo.matches (sectp->name))
- {
- dwp_file->sections.abbrev.s.section = sectp;
- dwp_file->sections.abbrev.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.abbrev;
else if (names->info_dwo.matches (sectp->name))
- {
- dwp_file->sections.info.s.section = sectp;
- dwp_file->sections.info.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.info;
else if (names->line_dwo.matches (sectp->name))
- {
- dwp_file->sections.line.s.section = sectp;
- dwp_file->sections.line.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.line;
else if (names->loc_dwo.matches (sectp->name))
- {
- dwp_file->sections.loc.s.section = sectp;
- dwp_file->sections.loc.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.loc;
else if (names->macinfo_dwo.matches (sectp->name))
- {
- dwp_file->sections.macinfo.s.section = sectp;
- dwp_file->sections.macinfo.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.macinfo;
else if (names->macro_dwo.matches (sectp->name))
- {
- dwp_file->sections.macro.s.section = sectp;
- dwp_file->sections.macro.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.macro;
else if (names->str_offsets_dwo.matches (sectp->name))
- {
- dwp_file->sections.str_offsets.s.section = sectp;
- dwp_file->sections.str_offsets.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.str_offsets;
else if (names->types_dwo.matches (sectp->name))
+ dw_sect = &dwp_file->sections.types;
+
+ if (dw_sect != nullptr)
{
- dwp_file->sections.types.s.section = sectp;
- dwp_file->sections.types.size = bfd_section_size (sectp);
+ dw_sect->s.section = sectp;
+ dw_sect->size = bfd_section_size (sectp);
+ dw_sect->read (objfile);
}
}
have version 1 or 2 or 5 until we parse the cu_index/tu_index sections. */
static void
-dwarf2_locate_v5_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
+dwarf2_locate_v5_dwp_sections (struct objfile *objfile, bfd *abfd,
+ asection *sectp, void *dwp_file_ptr)
{
struct dwp_file *dwp_file = (struct dwp_file *) dwp_file_ptr;
const struct dwop_section_names *names = &dwop_section_names;
dwp_file->elf_sections[elf_section_nr] = sectp;
/* Look for specific sections that we need. */
+ struct dwarf2_section_info *dw_sect = nullptr;
if (names->abbrev_dwo.matches (sectp->name))
- {
- dwp_file->sections.abbrev.s.section = sectp;
- dwp_file->sections.abbrev.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.abbrev;
else if (names->info_dwo.matches (sectp->name))
- {
- dwp_file->sections.info.s.section = sectp;
- dwp_file->sections.info.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.info;
else if (names->line_dwo.matches (sectp->name))
- {
- dwp_file->sections.line.s.section = sectp;
- dwp_file->sections.line.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.line;
else if (names->loclists_dwo.matches (sectp->name))
- {
- dwp_file->sections.loclists.s.section = sectp;
- dwp_file->sections.loclists.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.loclists;
else if (names->macro_dwo.matches (sectp->name))
- {
- dwp_file->sections.macro.s.section = sectp;
- dwp_file->sections.macro.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.macro;
else if (names->rnglists_dwo.matches (sectp->name))
- {
- dwp_file->sections.rnglists.s.section = sectp;
- dwp_file->sections.rnglists.size = bfd_section_size (sectp);
- }
+ dw_sect = &dwp_file->sections.rnglists;
else if (names->str_offsets_dwo.matches (sectp->name))
+ dw_sect = &dwp_file->sections.str_offsets;
+
+ if (dw_sect != nullptr)
{
- dwp_file->sections.str_offsets.s.section = sectp;
- dwp_file->sections.str_offsets.size = bfd_section_size (sectp);
+ dw_sect->s.section = sectp;
+ dw_sect->size = bfd_section_size (sectp);
+ dw_sect->read (objfile);
}
}
[IWBN if the dwp file name was recorded in the executable, akin to
.gnu_debuglink, but that doesn't exist yet.]
Strip the directory from FILE_NAME and search again. */
- if (*debug_file_directory != '\0')
+ if (!debug_file_directory.empty ())
{
/* Don't implicitly search the current directory here.
If the user wants to search "." to handle this case,
dwp_file->num_sections, asection *);
for (asection *sec : gdb_bfd_sections (dwp_file->dbfd))
- dwarf2_locate_common_dwp_sections (dwp_file->dbfd.get (), sec,
+ dwarf2_locate_common_dwp_sections (objfile, dwp_file->dbfd.get (), sec,
dwp_file.get ());
dwp_file->cus = create_dwp_hash_table (per_objfile, dwp_file.get (), 0);
for (asection *sec : gdb_bfd_sections (dwp_file->dbfd))
{
if (dwp_file->version == 2)
- dwarf2_locate_v2_dwp_sections (dwp_file->dbfd.get (), sec,
+ dwarf2_locate_v2_dwp_sections (objfile, dwp_file->dbfd.get (), sec,
dwp_file.get ());
else
- dwarf2_locate_v5_dwp_sections (dwp_file->dbfd.get (), sec,
+ dwarf2_locate_v5_dwp_sections (objfile, dwp_file->dbfd.get (), sec,
dwp_file.get ());
}
}
/* Ignore functions with missing or invalid low and high pc attributes. */
- if (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL)
+ if (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, nullptr, nullptr)
<= PC_BOUNDS_INVALID)
{
attr = dwarf2_attr (die, DW_AT_external, cu);
as multiple lexical blocks? Handling children in a sane way would
be nasty. Might be easier to properly extend generic blocks to
describe ranges. */
- switch (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL))
+ switch (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, nullptr, nullptr))
{
case PC_BOUNDS_NOT_PRESENT:
/* DW_TAG_lexical_block has no attributes, process its children as if
cu->get_builder ()->set_local_using_directives (cstk.local_using_directives);
}
+static void dwarf2_ranges_read_low_addrs (unsigned offset,
+ struct dwarf2_cu *cu,
+ dwarf_tag tag,
+ std::vector<CORE_ADDR> &result);
+
/* Read in DW_TAG_call_site and insert it to CU->call_site_htab. */
static void
struct gdbarch *gdbarch = objfile->arch ();
CORE_ADDR pc, baseaddr;
struct attribute *attr;
- struct call_site *call_site, call_site_local;
void **slot;
int nparams;
struct die_info *child_die;
}
pc = attr->as_address () + baseaddr;
pc = gdbarch_adjust_dwarf2_addr (gdbarch, pc);
+ pc -= baseaddr;
if (cu->call_site_htab == NULL)
- cu->call_site_htab = htab_create_alloc_ex (16, core_addr_hash, core_addr_eq,
- NULL, &objfile->objfile_obstack,
+ cu->call_site_htab = htab_create_alloc_ex (16, call_site::hash,
+ call_site::eq, NULL,
+ &objfile->objfile_obstack,
hashtab_obstack_allocate, NULL);
- call_site_local.pc = pc;
+ struct call_site call_site_local (pc, nullptr, nullptr);
slot = htab_find_slot (cu->call_site_htab, &call_site_local, INSERT);
if (*slot != NULL)
{
nparams++;
}
- call_site
- = ((struct call_site *)
- obstack_alloc (&objfile->objfile_obstack,
- sizeof (*call_site)
- + (sizeof (*call_site->parameter) * (nparams - 1))));
+ struct call_site *call_site
+ = new (XOBNEWVAR (&objfile->objfile_obstack,
+ struct call_site,
+ sizeof (*call_site) + sizeof (call_site->parameter[0]) * nparams))
+ struct call_site (pc, cu->per_cu, per_objfile);
*slot = call_site;
- memset (call_site, 0, sizeof (*call_site) - sizeof (*call_site->parameter));
- call_site->pc = pc;
+
+ /* We never call the destructor of call_site, so we must ensure it is
+ trivially destructible. */
+ gdb_static_assert(std::is_trivially_destructible<struct call_site>::value);
if (dwarf2_flag_true_p (die, DW_AT_call_tail_call, cu)
|| dwarf2_flag_true_p (die, DW_AT_GNU_tail_call, cu))
/* This was a pre-DWARF-5 GNU extension alias for DW_AT_call_origin. */
attr = dwarf2_attr (die, DW_AT_abstract_origin, cu);
}
- SET_FIELD_DWARF_BLOCK (call_site->target, NULL);
+
+ call_site->target.set_loc_dwarf_block (nullptr);
if (!attr || (attr->form_is_block () && attr->as_block ()->size == 0))
/* Keep NULL DWARF_BLOCK. */;
else if (attr->form_is_block ())
dlbaton->per_objfile = per_objfile;
dlbaton->per_cu = cu->per_cu;
- SET_FIELD_DWARF_BLOCK (call_site->target, dlbaton);
+ call_site->target.set_loc_dwarf_block (dlbaton);
}
else if (attr->form_is_ref ())
{
target_die = follow_die_ref (die, attr, &target_cu);
gdb_assert (target_cu->per_objfile->objfile == objfile);
+
+ struct attribute *ranges_attr
+ = dwarf2_attr (target_die, DW_AT_ranges, target_cu);
+
if (die_is_declaration (target_die, target_cu))
{
const char *target_physname;
"physname, for referencing DIE %s [in module %s]"),
sect_offset_str (die->sect_off), objfile_name (objfile));
else
- SET_FIELD_PHYSNAME (call_site->target, target_physname);
+ call_site->target.set_loc_physname (target_physname);
+ }
+ else if (ranges_attr != nullptr && ranges_attr->form_is_unsigned ())
+ {
+ ULONGEST ranges_offset = (ranges_attr->as_unsigned ()
+ + target_cu->gnu_ranges_base);
+ std::vector<CORE_ADDR> addresses;
+ dwarf2_ranges_read_low_addrs (ranges_offset, target_cu,
+ target_die->tag, addresses);
+ CORE_ADDR *saved = XOBNEWVAR (&objfile->objfile_obstack, CORE_ADDR,
+ addresses.size ());
+ std::copy (addresses.begin (), addresses.end (), saved);
+ call_site->target.set_loc_array (addresses.size (), saved);
}
else
{
CORE_ADDR lowpc;
/* DW_AT_entry_pc should be preferred. */
- if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu, NULL)
+ if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu,
+ nullptr, nullptr)
<= PC_BOUNDS_INVALID)
complaint (_("DW_AT_call_target target DIE has invalid "
"low pc, for referencing DIE %s [in module %s]"),
sect_offset_str (die->sect_off), objfile_name (objfile));
else
{
- lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
- SET_FIELD_PHYSADDR (call_site->target, lowpc);
+ lowpc = (gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr)
+ - baseaddr);
+ call_site->target.set_loc_physaddr (lowpc);
}
}
}
"block nor reference, for DIE %s [in module %s]"),
sect_offset_str (die->sect_off), objfile_name (objfile));
- call_site->per_cu = cu->per_cu;
- call_site->per_objfile = per_objfile;
-
for (child_die = die->child;
child_die && child_die->tag;
child_die = child_die->sibling)
/* Base address selection entry. */
gdb::optional<CORE_ADDR> base;
const gdb_byte *buffer;
- CORE_ADDR baseaddr;
bool overflow = false;
ULONGEST addr_index;
struct dwarf2_section_info *rnglists_section;
}
buffer = rnglists_section->buffer + offset;
- baseaddr = objfile->text_section_offset ();
-
while (1)
{
/* Initialize it due to a false compiler warning. */
/* A not-uncommon case of bad debug info.
Don't pollute the addrmap with bad data. */
- if (range_beginning + baseaddr == 0
+ if (range_beginning == 0
&& !per_objfile->per_bfd->has_section_at_zero)
{
complaint (_(".debug_rnglists entry has start address of zero"
gdb::optional<CORE_ADDR> base;
unsigned int dummy;
const gdb_byte *buffer;
- CORE_ADDR baseaddr;
if (cu_header->version >= 5)
return dwarf2_rnglists_process (offset, cu, tag, callback);
}
buffer = per_objfile->per_bfd->ranges.buffer + offset;
- baseaddr = objfile->text_section_offset ();
-
while (1)
{
CORE_ADDR range_beginning, range_end;
/* A not-uncommon case of bad debug info.
Don't pollute the addrmap with bad data. */
- if (range_beginning + baseaddr == 0
+ if (range_beginning == 0
&& !per_objfile->per_bfd->has_section_at_zero)
{
complaint (_(".debug_ranges entry has start address of zero"
/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
Return 1 if the attributes are present and valid, otherwise, return 0.
- If RANGES_PST is not NULL we should set up the `psymtabs_addrmap'. */
+ TAG is passed to dwarf2_ranges_process. If MAP is not NULL, then
+ ranges in MAP are set, using DATUM as the value. */
static int
dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
CORE_ADDR *high_return, struct dwarf2_cu *cu,
- dwarf2_psymtab *ranges_pst, dwarf_tag tag)
+ addrmap *map, void *datum, dwarf_tag tag)
{
struct objfile *objfile = cu->per_objfile->objfile;
- dwarf2_per_bfd *per_bfd = cu->per_objfile->per_bfd;
struct gdbarch *gdbarch = objfile->arch ();
const CORE_ADDR baseaddr = objfile->text_section_offset ();
int low_set = 0;
retval = dwarf2_ranges_process (offset, cu, tag,
[&] (CORE_ADDR range_beginning, CORE_ADDR range_end)
{
- if (ranges_pst != NULL)
+ if (map != nullptr)
{
CORE_ADDR lowpc;
CORE_ADDR highpc;
highpc = (gdbarch_adjust_dwarf2_addr (gdbarch,
range_end + baseaddr)
- baseaddr);
- addrmap_set_empty (per_bfd->partial_symtabs->psymtabs_addrmap,
- lowpc, highpc - 1, ranges_pst);
+ addrmap_set_empty (map, lowpc, highpc - 1, datum);
}
/* FIXME: This is recording everything as a low-high
return 1;
}
+/* Process ranges and fill in a vector of the low PC values only. */
+
+static void
+dwarf2_ranges_read_low_addrs (unsigned offset, struct dwarf2_cu *cu,
+ dwarf_tag tag,
+ std::vector<CORE_ADDR> &result)
+{
+ dwarf2_ranges_process (offset, cu, tag,
+ [&] (CORE_ADDR start, CORE_ADDR end)
+ {
+ result.push_back (start);
+ });
+}
+
/* Get low and high pc attributes from a die. See enum pc_bounds_kind
definition for the return value. *LOWPC and *HIGHPC are set iff
neither PC_BOUNDS_NOT_PRESENT nor PC_BOUNDS_INVALID are returned. */
static enum pc_bounds_kind
dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
CORE_ADDR *highpc, struct dwarf2_cu *cu,
- dwarf2_psymtab *pst)
+ addrmap *map, void *datum)
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
struct attribute *attr;
/* Value of the DW_AT_ranges attribute is the offset in the
.debug_ranges section. */
- if (!dwarf2_ranges_read (ranges_offset, &low, &high, cu, pst,
- die->tag))
+ if (!dwarf2_ranges_read (ranges_offset, &low, &high, cu,
+ map, datum, die->tag))
return PC_BOUNDS_INVALID;
/* Found discontinuous range of addresses. */
ret = PC_BOUNDS_RANGES;
CORE_ADDR low, high;
struct die_info *child = die->child;
- if (dwarf2_get_pc_bounds (die, &low, &high, cu, NULL) >= PC_BOUNDS_RANGES)
+ if (dwarf2_get_pc_bounds (die, &low, &high, cu, nullptr, nullptr)
+ >= PC_BOUNDS_RANGES)
{
*lowpc = std::min (*lowpc, low);
*highpc = std::max (*highpc, high);
CORE_ADDR best_high = (CORE_ADDR) 0;
CORE_ADDR current_low, current_high;
- if (dwarf2_get_pc_bounds (die, ¤t_low, ¤t_high, cu, NULL)
+ if (dwarf2_get_pc_bounds (die, ¤t_low, ¤t_high, cu,
+ nullptr, nullptr)
>= PC_BOUNDS_RANGES)
{
best_low = current_low;
{
cu->producer_is_gxx_lt_4_6 = major < 4 || (major == 4 && minor < 6);
cu->producer_is_gcc_lt_4_3 = major < 4 || (major == 4 && minor < 3);
+ cu->producer_is_gcc_11 = major == 11;
}
else if (producer_is_icc (cu->producer, &major, &minor))
{
}
}
-/* Look for DW_AT_data_member_location. Set *OFFSET to the byte
- offset. If the attribute was not found return 0, otherwise return
- 1. If it was found but could not properly be handled, set *OFFSET
- to 0. */
+/* Look for DW_AT_data_member_location or DW_AT_data_bit_offset. Set
+ *OFFSET to the byte offset. If the attribute was not found return
+ 0, otherwise return 1. If it was found but could not properly be
+ handled, set *OFFSET to 0. */
static int
-handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu,
- LONGEST *offset)
+handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
+ LONGEST *offset)
{
struct attribute *attr;
return 1;
}
+ else
+ {
+ attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
+ if (attr != nullptr)
+ {
+ *offset = attr->constant_value (0);
+ return 1;
+ }
+ }
return 0;
}
-/* Look for DW_AT_data_member_location and store the results in FIELD. */
+/* Look for DW_AT_data_member_location or DW_AT_data_bit_offset and
+ store the results in FIELD. */
static void
-handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu,
- struct field *field)
+handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
+ struct field *field)
{
struct attribute *attr;
if (attr->form_is_constant ())
{
LONGEST offset = attr->constant_value (0);
- SET_FIELD_BITPOS (*field, offset * bits_per_byte);
+
+ /* Work around this GCC 11 bug, where it would erroneously use -1
+ data member locations, instead of 0:
+
+ Negative DW_AT_data_member_location
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101378
+ */
+ if (offset == -1 && cu->producer_is_gcc_11)
+ {
+ complaint (_("DW_AT_data_member_location value of -1, assuming 0"));
+ offset = 0;
+ }
+
+ field->set_loc_bitpos (offset * bits_per_byte);
}
else if (attr->form_is_section_offset ())
dwarf2_complex_location_expr_complaint ();
bool handled;
CORE_ADDR offset = decode_locdesc (attr->as_block (), cu, &handled);
if (handled)
- SET_FIELD_BITPOS (*field, offset * bits_per_byte);
+ field->set_loc_bitpos (offset * bits_per_byte);
else
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
dlbaton->per_objfile = per_objfile;
dlbaton->per_cu = cu->per_cu;
- SET_FIELD_DWARF_BLOCK (*field, dlbaton);
+ field->set_loc_dwarf_block (dlbaton);
}
}
else
dwarf2_complex_location_expr_complaint ();
}
+ else
+ {
+ attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
+ if (attr != nullptr)
+ field->set_loc_bitpos (attr->constant_value (0));
+ }
}
/* Add an aggregate field to the field list. */
fp = &new_field->field;
- if (die->tag == DW_TAG_member && ! die_is_declaration (die, cu))
- {
+ if ((die->tag == DW_TAG_member || die->tag == DW_TAG_namelist_item)
+ && !die_is_declaration (die, cu))
+ {
+ if (die->tag == DW_TAG_namelist_item)
+ {
+ /* Typically, DW_TAG_namelist_item are references to namelist items.
+ If so, follow that reference. */
+ struct attribute *attr1 = dwarf2_attr (die, DW_AT_namelist_item, cu);
+ struct die_info *item_die = nullptr;
+ struct dwarf2_cu *item_cu = cu;
+ if (attr1->form_is_ref ())
+ item_die = follow_die_ref (die, attr1, &item_cu);
+ if (item_die != nullptr)
+ die = item_die;
+ }
/* Data member other than a C++ static data member. */
/* Get type of field. */
fp->set_type (die_type (die, cu));
- SET_FIELD_BITPOS (*fp, 0);
+ fp->set_loc_bitpos (0);
/* Get bit size of field (zero if none). */
attr = dwarf2_attr (die, DW_AT_bit_size, cu);
}
/* Get bit offset of field. */
- handle_data_member_location (die, cu, fp);
+ handle_member_location (die, cu, fp);
attr = dwarf2_attr (die, DW_AT_bit_offset, cu);
if (attr != nullptr && attr->form_is_constant ())
{
anonymous object to the MSB of the field. We don't
have to do anything special since we don't need to
know the size of the anonymous object. */
- SET_FIELD_BITPOS (*fp, (FIELD_BITPOS (*fp)
- + attr->constant_value (0)));
+ fp->set_loc_bitpos (fp->loc_bitpos () + attr->constant_value (0));
}
else
{
bit field. */
anonymous_size = TYPE_LENGTH (fp->type ());
}
- SET_FIELD_BITPOS (*fp,
- (FIELD_BITPOS (*fp)
- + anonymous_size * bits_per_byte
- - bit_offset - FIELD_BITSIZE (*fp)));
+ fp->set_loc_bitpos (fp->loc_bitpos ()
+ + anonymous_size * bits_per_byte
+ - bit_offset - FIELD_BITSIZE (*fp));
}
}
- attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
- if (attr != NULL)
- SET_FIELD_BITPOS (*fp, (FIELD_BITPOS (*fp)
- + attr->constant_value (0)));
/* Get name of field. */
fieldname = dwarf2_name (die, cu);
/* The name is already allocated along with this objfile, so we don't
need to duplicate it for the type. */
- fp->name = fieldname;
+ fp->set_name (fieldname);
/* Change accessibility for artificial fields (e.g. virtual table
pointer or virtual base class pointer) to private. */
/* The name is already allocated along with this objfile, so we don't
need to duplicate it for the type. */
- SET_FIELD_PHYSNAME (*fp, physname ? physname : "");
+ fp->set_loc_physname (physname ? physname : "");
fp->set_type (die_type (die, cu));
- FIELD_NAME (*fp) = fieldname;
+ fp->set_name (fieldname);
}
else if (die->tag == DW_TAG_inheritance)
{
/* C++ base class field. */
- handle_data_member_location (die, cu, fp);
+ handle_member_location (die, cu, fp);
FIELD_BITSIZE (*fp) = 0;
fp->set_type (die_type (die, cu));
- FIELD_NAME (*fp) = fp->type ()->name ();
+ fp->set_name (fp->type ()->name ());
}
else
gdb_assert_not_reached ("missing case in dwarf2_add_field");
offset_map[fip->fields[i].offset] = i;
struct objfile *objfile = cu->per_objfile->objfile;
- gdb::array_view<variant_part> parts
+ gdb::array_view<const variant_part> parts
= create_variant_parts (&objfile->objfile_obstack, offset_map, fip,
fip->variant_parts);
return;
/* Check for __pfn and __delta members. */
- if (TYPE_FIELD_NAME (type, 0) == NULL
- || strcmp (TYPE_FIELD_NAME (type, 0), "__pfn") != 0
- || TYPE_FIELD_NAME (type, 1) == NULL
- || strcmp (TYPE_FIELD_NAME (type, 1), "__delta") != 0)
+ if (type->field (0).name () == NULL
+ || strcmp (type->field (0).name (), "__pfn") != 0
+ || type->field (1).name () == NULL
+ || strcmp (type->field (1).name (), "__delta") != 0)
return;
/* Find the type of the method. */
return;
/* Check for P_ARRAY and P_BOUNDS members. */
- if (TYPE_FIELD_NAME (type, 0) == NULL
- || strcmp (TYPE_FIELD_NAME (type, 0), "P_ARRAY") != 0
- || TYPE_FIELD_NAME (type, 1) == NULL
- || strcmp (TYPE_FIELD_NAME (type, 1), "P_BOUNDS") != 0)
+ if (type->field (0).name () == NULL
+ || strcmp (type->field (0).name (), "P_ARRAY") != 0
+ || type->field (1).name () == NULL
+ || strcmp (type->field (1).name (), "P_BOUNDS") != 0)
return;
/* Make sure we're looking at a pointer to an array. */
{
type->set_code (TYPE_CODE_UNION);
}
+ else if (die->tag == DW_TAG_namelist)
+ {
+ type->set_code (TYPE_CODE_NAMELIST);
+ }
else
{
type->set_code (TYPE_CODE_STRUCT);
struct dwarf2_cu *cu)
{
if (child_die->tag == DW_TAG_member
- || child_die->tag == DW_TAG_variable)
+ || child_die->tag == DW_TAG_variable
+ || child_die->tag == DW_TAG_namelist_item)
{
/* NOTE: carlton/2002-11-05: A C++ static data member
should be a DW_TAG_member that is a declaration, but
handle_variant (child_die, type, fi, template_args, cu);
}
-/* Finish creating a structure or union type, including filling in
- its members and creating a symbol for it. */
+/* Finish creating a structure or union type, including filling in its
+ members and creating a symbol for it. This function also handles Fortran
+ namelist variables, their items or members and creating a symbol for
+ them. */
static void
process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
i >= TYPE_N_BASECLASSES (t);
--i)
{
- const char *fieldname = TYPE_FIELD_NAME (t, i);
+ const char *fieldname = t->field (i).name ();
if (is_vtable_name (fieldname, cu))
{
i >= TYPE_N_BASECLASSES (type);
--i)
{
- if (strcmp (TYPE_FIELD_NAME (type, i), "__vfp") == 0)
+ if (strcmp (type->field (i).name (), "__vfp") == 0)
{
set_type_vptr_fieldno (type, i);
set_type_vptr_basetype (type, type);
fields.emplace_back ();
struct field &field = fields.back ();
- FIELD_NAME (field) = dwarf2_physname (name, child_die, cu);
- SET_FIELD_ENUMVAL (field, value);
+ field.set_name (dwarf2_physname (name, child_die, cu));
+ field.set_loc_enumval (value);
}
if (!fields.empty ())
else
return false;
- SET_FIELD_BITPOS (*field, 8 * offset);
+ field->set_loc_bitpos (8 * offset);
if (size != TYPE_LENGTH (field->type ()))
FIELD_BITSIZE (*field) = 8 * size;
/* Set the name of each field in the bounds. */
xsnprintf (name, sizeof (name), "LB%d", i / 2);
- FIELD_NAME (range_fields[i]) = objfile->intern (name);
+ range_fields[i].set_name (objfile->intern (name));
xsnprintf (name, sizeof (name), "UB%d", i / 2);
- FIELD_NAME (range_fields[i + 1]) = objfile->intern (name);
+ range_fields[i + 1].set_name (objfile->intern (name));
}
struct type *bounds = alloc_type (objfile);
bounds->num_fields () * sizeof (struct field));
int last_fieldno = range_fields.size () - 1;
- int bounds_size = (TYPE_FIELD_BITPOS (bounds, last_fieldno) / 8
+ int bounds_size = (bounds->field (last_fieldno).loc_bitpos () / 8
+ TYPE_LENGTH (bounds->field (last_fieldno).type ()));
TYPE_LENGTH (bounds) = align_up (bounds_size, max_align);
/* The names are chosen to coincide with what the compiler does with
-fgnat-encodings=all, which the Ada code in gdb already
understands. */
- TYPE_FIELD_NAME (result, 0) = "P_ARRAY";
+ result->field (0).set_name ("P_ARRAY");
result->field (0).set_type (lookup_pointer_type (type));
- TYPE_FIELD_NAME (result, 1) = "P_BOUNDS";
+ result->field (1).set_name ("P_BOUNDS");
result->field (1).set_type (lookup_pointer_type (bounds));
- SET_FIELD_BITPOS (result->field (1), 8 * bounds_offset);
+ result->field (1).set_loc_bitpos (8 * bounds_offset);
result->set_name (type->name ());
TYPE_LENGTH (result) = (TYPE_LENGTH (result->field (0).type ())
child_die = die->child;
while (child_die && child_die->tag)
{
- if (child_die->tag == DW_TAG_subrange_type)
+ if (child_die->tag == DW_TAG_subrange_type
+ || child_die->tag == DW_TAG_generic_subrange)
{
struct type *child_type = read_type_die (child_die, cu);
gdb_assert (ptr - baton->data == baton->size);
SYMBOL_LOCATION_BATON (sym) = baton;
- SYMBOL_ACLASS_INDEX (sym) = dwarf2_locexpr_index;
+ sym->set_aclass_index (dwarf2_locexpr_index);
}
/* Create appropriate locally-scoped variables for all the
}
sym = new_symbol (die, objfile_type (objfile)->builtin_void, cu);
- SYMBOL_VALUE_COMMON_BLOCK (sym) = common_block;
+ sym->set_value_common_block (common_block);
}
}
/* Pass 0 as the default as we know this attribute is constant
and the default value will not be returned. */
LONGEST sz = len->constant_value (0);
- prop_type = cu->per_objfile->int_type (sz, true);
+ prop_type = objfile_int_type (objfile, sz, true);
}
else
{
break;
case DW_ATE_UTF:
{
- if (bits == 16)
- type = builtin_type (arch)->builtin_char16;
- else if (bits == 32)
- type = builtin_type (arch)->builtin_char32;
- else
- {
- complaint (_("unsupported DW_ATE_UTF bit size: '%d'"),
- bits);
- type = dwarf2_init_integer_type (cu, objfile, bits, 1, name);
- }
+ type = init_character_type (objfile, bits, 1, name);
return set_die_type (die, type, cu);
}
break;
break;
}
- if (name && strcmp (name, "char") == 0)
+ if (type->code () == TYPE_CODE_INT
+ && name != nullptr
+ && strcmp (name, "char") == 0)
type->set_has_no_signedness (true);
maybe_set_alignment (cu, die, type);
baton->locexpr.per_cu = cu->per_cu;
baton->locexpr.per_objfile = per_objfile;
- struct dwarf_block *block = attr->as_block ();
+ struct dwarf_block *block;
+ if (attr->form == DW_FORM_data16)
+ {
+ size_t data_size = 16;
+ block = XOBNEW (obstack, struct dwarf_block);
+ block->size = (data_size
+ + 2 /* Extra bytes for DW_OP and arg. */);
+ gdb_byte *data = XOBNEWVEC (obstack, gdb_byte, block->size);
+ data[0] = DW_OP_implicit_value;
+ data[1] = data_size;
+ memcpy (&data[2], attr->as_block ()->data, data_size);
+ block->data = data;
+ }
+ else
+ block = attr->as_block ();
+
baton->locexpr.size = block->size;
baton->locexpr.data = block->data;
switch (attr->name)
if (target_attr == NULL)
target_attr = dwarf2_attr (target_die, DW_AT_data_member_location,
target_cu);
+ if (target_attr == nullptr)
+ target_attr = dwarf2_attr (target_die, DW_AT_data_bit_offset,
+ target_cu);
if (target_attr == NULL)
{
const char *name = var_decl_name (target_die, target_cu);
}
break;
case DW_AT_data_member_location:
+ case DW_AT_data_bit_offset:
{
LONGEST offset;
- if (!handle_data_member_location (target_die, target_cu,
- &offset))
+ if (!handle_member_location (target_die, target_cu, &offset))
return 0;
baton = XOBNEW (obstack, struct dwarf2_property_baton);
}
else if (attr->form_is_constant ())
prop->set_const_val (attr->constant_value (0));
- else
+ else if (attr->form_is_section_offset ())
{
- dwarf2_invalid_attrib_class_complaint (dwarf_form_name (attr->form),
- dwarf2_name (die, cu));
- return 0;
+ switch (attr->name)
+ {
+ case DW_AT_string_length:
+ baton = XOBNEW (obstack, struct dwarf2_property_baton);
+ baton->property_type = default_type;
+ fill_in_loclist_baton (cu, &baton->loclist, attr);
+ prop->set_loclist (baton);
+ gdb_assert (prop->baton () != NULL);
+ break;
+ default:
+ goto invalid;
+ }
}
+ else
+ goto invalid;
return 1;
+
+ invalid:
+ dwarf2_invalid_attrib_class_complaint (dwarf_form_name (attr->form),
+ dwarf2_name (die, cu));
+ return 0;
}
/* See read.h. */
-struct type *
-dwarf2_per_objfile::int_type (int size_in_bytes, bool unsigned_p) const
-{
- struct type *int_type;
-
- /* Helper macro to examine the various builtin types. */
-#define TRY_TYPE(F) \
- int_type = (unsigned_p \
- ? objfile_type (objfile)->builtin_unsigned_ ## F \
- : objfile_type (objfile)->builtin_ ## F); \
- if (int_type != NULL && TYPE_LENGTH (int_type) == size_in_bytes) \
- return int_type
-
- TRY_TYPE (char);
- TRY_TYPE (short);
- TRY_TYPE (int);
- TRY_TYPE (long);
- TRY_TYPE (long_long);
-
-#undef TRY_TYPE
-
- gdb_assert_not_reached ("unable to find suitable integer type");
-}
-
/* Read the DW_AT_type attribute for a sub-range. If this attribute is not
present (which is valid) then compute the default type based on the
compilation units address size. */
if (dwarf_die_debug)
{
- fprintf_unfiltered (gdb_stdlog,
- "Read die from %s@0x%x of %s:\n",
- reader->die_section->get_name (),
- (unsigned) (info_ptr - reader->die_section->buffer),
- bfd_get_filename (reader->abfd));
+ gdb_printf (gdb_stdlog,
+ "Read die from %s@0x%x of %s:\n",
+ reader->die_section->get_name (),
+ (unsigned) (info_ptr - reader->die_section->buffer),
+ bfd_get_filename (reader->abfd));
dump_die (die, dwarf_die_debug);
}
if (dwarf_die_debug)
{
- fprintf_unfiltered (gdb_stdlog,
- "Read die from %s@0x%x of %s:\n",
- reader->die_section->get_name (),
- (unsigned) (info_ptr - reader->die_section->buffer),
- bfd_get_filename (reader->abfd));
+ gdb_printf (gdb_stdlog,
+ "Read die from %s@0x%x of %s:\n",
+ reader->die_section->get_name (),
+ (unsigned) (info_ptr - reader->die_section->buffer),
+ bfd_get_filename (reader->abfd));
dump_die (*diep, dwarf_die_debug);
}
}
\f
+void
+cooked_indexer::check_bounds (cutu_reader *reader)
+{
+ if (reader->cu->per_cu->addresses_seen)
+ return;
+
+ dwarf2_cu *cu = reader->cu;
+
+ CORE_ADDR best_lowpc = 0, best_highpc = 0;
+ /* Possibly set the default values of LOWPC and HIGHPC from
+ `DW_AT_ranges'. */
+ dwarf2_find_base_address (reader->comp_unit_die, cu);
+ enum pc_bounds_kind cu_bounds_kind
+ = dwarf2_get_pc_bounds (reader->comp_unit_die, &best_lowpc, &best_highpc,
+ cu, m_index_storage->get_addrmap (), cu->per_cu);
+ if (cu_bounds_kind == PC_BOUNDS_HIGH_LOW && best_lowpc < best_highpc)
+ {
+ struct objfile *objfile = cu->per_objfile->objfile;
+ CORE_ADDR baseaddr = objfile->text_section_offset ();
+ struct gdbarch *gdbarch = objfile->arch ();
+ CORE_ADDR low
+ = (gdbarch_adjust_dwarf2_addr (gdbarch, best_lowpc + baseaddr)
+ - baseaddr);
+ CORE_ADDR high
+ = (gdbarch_adjust_dwarf2_addr (gdbarch, best_highpc + baseaddr)
+ - baseaddr - 1);
+ /* Store the contiguous range if it is not empty; it can be
+ empty for CUs with no code. */
+ addrmap_set_empty (m_index_storage->get_addrmap (), low, high,
+ cu->per_cu);
+
+ cu->per_cu->addresses_seen = true;
+ }
+}
+
+/* Helper function that returns true if TAG can have a linkage
+ name. */
+
+static bool
+tag_can_have_linkage_name (enum dwarf_tag tag)
+{
+ switch (tag)
+ {
+ /* We include types here because an anonymous C++ type might
+ have a name for linkage purposes. */
+ case DW_TAG_class_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_variable:
+ case DW_TAG_subprogram:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+cutu_reader *
+cooked_indexer::ensure_cu_exists (cutu_reader *reader,
+ dwarf2_per_objfile *per_objfile,
+ sect_offset sect_off, bool is_dwz,
+ bool for_scanning)
+{
+ /* Lookups for type unit references are always in the CU, and
+ cross-CU references will crash. */
+ if (reader->cu->per_cu->is_dwz == is_dwz
+ && reader->cu->header.offset_in_cu_p (sect_off))
+ return reader;
+
+ dwarf2_per_cu_data *per_cu
+ = dwarf2_find_containing_comp_unit (sect_off, is_dwz,
+ per_objfile->per_bfd);
+
+ /* When scanning, we only want to visit a given CU a single time.
+ Doing this check here avoids self-imports as well. */
+ if (for_scanning)
+ {
+ bool nope = false;
+ if (!per_cu->scanned.compare_exchange_strong (nope, true))
+ return nullptr;
+ }
+ if (per_cu == m_per_cu)
+ return reader;
+
+ cutu_reader *result = m_index_storage->get_reader (per_cu);
+ if (result == nullptr)
+ {
+ cutu_reader new_reader (per_cu, per_objfile, nullptr, nullptr, false,
+ m_index_storage->get_abbrev_cache ());
+
+ prepare_one_comp_unit (new_reader.cu, new_reader.comp_unit_die,
+ language_minimal);
+ std::unique_ptr<cutu_reader> copy
+ (new cutu_reader (std::move (new_reader)));
+ result = m_index_storage->preserve (std::move (copy));
+ }
+
+ if (result->dummy_p || !result->comp_unit_die->has_children)
+ return nullptr;
+
+ if (for_scanning)
+ check_bounds (result);
+
+ return result;
+}
+
+const gdb_byte *
+cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
+ cutu_reader *reader,
+ const gdb_byte *watermark_ptr,
+ const gdb_byte *info_ptr,
+ const abbrev_info *abbrev,
+ const char **name,
+ const char **linkage_name,
+ cooked_index_flag *flags,
+ sect_offset *sibling_offset,
+ const cooked_index_entry **parent_entry,
+ CORE_ADDR *maybe_defer,
+ bool for_specification)
+{
+ bool origin_is_dwz = false;
+ bool is_declaration = false;
+ sect_offset origin_offset {};
+
+ gdb::optional<CORE_ADDR> low_pc;
+ gdb::optional<CORE_ADDR> high_pc;
+ bool high_pc_relative = false;
+
+ for (int i = 0; i < abbrev->num_attrs; ++i)
+ {
+ attribute attr;
+ info_ptr = read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
+ if (attr.requires_reprocessing_p ())
+ read_attribute_reprocess (reader, &attr, abbrev->tag);
+
+ /* Store the data if it is of an attribute we want to keep in a
+ partial symbol table. */
+ switch (attr.name)
+ {
+ case DW_AT_name:
+ switch (abbrev->tag)
+ {
+ case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
+ case DW_TAG_type_unit:
+ /* Compilation units have a DW_AT_name that is a filename, not
+ a source language identifier. */
+ break;
+
+ default:
+ if (*name == nullptr)
+ *name = attr.as_string ();
+ break;
+ }
+ break;
+
+ case DW_AT_linkage_name:
+ case DW_AT_MIPS_linkage_name:
+ /* Note that both forms of linkage name might appear. We
+ assume they will be the same, and we only store the last
+ one we see. */
+ if (*linkage_name == nullptr)
+ *linkage_name = attr.as_string ();
+ break;
+
+ case DW_AT_main_subprogram:
+ if (attr.as_boolean ())
+ *flags |= IS_MAIN;
+ break;
+
+ case DW_AT_declaration:
+ is_declaration = attr.as_boolean ();
+ break;
+
+ case DW_AT_sibling:
+ if (sibling_offset != nullptr)
+ *sibling_offset = attr.get_ref_die_offset ();
+ break;
+
+ case DW_AT_specification:
+ case DW_AT_abstract_origin:
+ case DW_AT_extension:
+ origin_offset = attr.get_ref_die_offset ();
+ origin_is_dwz = attr.form == DW_FORM_GNU_ref_alt;
+ break;
+
+ case DW_AT_external:
+ if (attr.as_boolean ())
+ *flags &= ~IS_STATIC;
+ break;
+
+ case DW_AT_enum_class:
+ if (attr.as_boolean ())
+ *flags |= IS_ENUM_CLASS;
+ break;
+
+ case DW_AT_low_pc:
+ low_pc = attr.as_address ();
+ break;
+
+ case DW_AT_high_pc:
+ high_pc = attr.as_address ();
+ if (reader->cu->header.version >= 4 && attr.form_is_constant ())
+ high_pc_relative = true;
+ break;
+
+ case DW_AT_location:
+ if (!scanning_per_cu->addresses_seen && attr.form_is_block ())
+ {
+ struct dwarf_block *locdesc = attr.as_block ();
+ CORE_ADDR addr = decode_locdesc (locdesc, reader->cu);
+ if (addr != 0
+ || reader->cu->per_objfile->per_bfd->has_section_at_zero)
+ {
+ low_pc = addr;
+ /* For variables, we don't want to try decoding the
+ type just to find the size -- for gdb's purposes
+ we only need the address of a variable. */
+ high_pc = addr + 1;
+ high_pc_relative = false;
+ }
+ }
+ break;
+
+ case DW_AT_ranges:
+ if (!scanning_per_cu->addresses_seen)
+ {
+ /* Offset in the .debug_ranges or .debug_rnglist section
+ (depending on DWARF version). */
+ ULONGEST ranges_offset = attr.as_unsigned ();
+
+ /* See dwarf2_cu::gnu_ranges_base's doc for why we might
+ want to add this value. */
+ ranges_offset += reader->cu->gnu_ranges_base;
+
+ CORE_ADDR lowpc, highpc;
+ dwarf2_ranges_read (ranges_offset, &lowpc, &highpc, reader->cu,
+ m_index_storage->get_addrmap (),
+ scanning_per_cu, abbrev->tag);
+ }
+ break;
+ }
+ }
+
+ /* We don't want to examine declarations, but if we found a
+ declaration when handling DW_AT_specification or the like, then
+ that is ok. Similarly, we allow an external variable without a
+ location; those are resolved via minimal symbols. */
+ if (is_declaration && !for_specification
+ && (abbrev->tag != DW_TAG_variable
+ || (*flags & IS_STATIC) != 0))
+ {
+ *linkage_name = nullptr;
+ *name = nullptr;
+ }
+ else if ((*name == nullptr
+ || (*linkage_name == nullptr
+ && tag_can_have_linkage_name (abbrev->tag))
+ || (*parent_entry == nullptr && m_language != language_c))
+ && origin_offset != sect_offset (0))
+ {
+ cutu_reader *new_reader
+ = ensure_cu_exists (reader, reader->cu->per_objfile, origin_offset,
+ origin_is_dwz, false);
+ if (new_reader != nullptr)
+ {
+ const gdb_byte *new_info_ptr = (new_reader->buffer
+ + to_underlying (origin_offset));
+
+ if (new_reader->cu == reader->cu
+ && new_info_ptr > watermark_ptr
+ && maybe_defer != nullptr
+ && *parent_entry == nullptr)
+ *maybe_defer = form_addr (origin_offset, origin_is_dwz);
+ else if (*parent_entry == nullptr)
+ {
+ CORE_ADDR lookup = form_addr (origin_offset, origin_is_dwz);
+ *parent_entry
+ = (cooked_index_entry *) addrmap_find (m_die_range_map,
+ lookup);
+ }
+
+ unsigned int bytes_read;
+ const abbrev_info *new_abbrev = peek_die_abbrev (*new_reader,
+ new_info_ptr,
+ &bytes_read);
+ new_info_ptr += bytes_read;
+ scan_attributes (scanning_per_cu, new_reader, new_info_ptr, new_info_ptr,
+ new_abbrev, name, linkage_name, flags, nullptr,
+ parent_entry, maybe_defer, true);
+ }
+ }
+
+ if (!for_specification)
+ {
+ if (m_language == language_ada
+ && *linkage_name == nullptr)
+ *linkage_name = *name;
+
+ if (!scanning_per_cu->addresses_seen
+ && low_pc.has_value ()
+ && (reader->cu->per_objfile->per_bfd->has_section_at_zero
+ || *low_pc != 0)
+ && high_pc.has_value ())
+ {
+ if (high_pc_relative)
+ high_pc = *high_pc + *low_pc;
+
+ if (*high_pc > *low_pc)
+ {
+ struct objfile *objfile = reader->cu->per_objfile->objfile;
+ CORE_ADDR baseaddr = objfile->text_section_offset ();
+ struct gdbarch *gdbarch = objfile->arch ();
+ CORE_ADDR lo
+ = (gdbarch_adjust_dwarf2_addr (gdbarch, *low_pc + baseaddr)
+ - baseaddr);
+ CORE_ADDR hi
+ = (gdbarch_adjust_dwarf2_addr (gdbarch, *high_pc + baseaddr)
+ - baseaddr);
+ addrmap_set_empty (m_index_storage->get_addrmap (), lo, hi - 1,
+ scanning_per_cu);
+ }
+ }
+
+ if (abbrev->tag == DW_TAG_module || abbrev->tag == DW_TAG_namespace)
+ *flags &= ~IS_STATIC;
+
+ if (abbrev->tag == DW_TAG_namespace && *name == nullptr)
+ *name = "(anonymous namespace)";
+
+ if (m_language == language_cplus
+ && (abbrev->tag == DW_TAG_class_type
+ || abbrev->tag == DW_TAG_interface_type
+ || abbrev->tag == DW_TAG_structure_type
+ || abbrev->tag == DW_TAG_union_type
+ || abbrev->tag == DW_TAG_enumeration_type
+ || abbrev->tag == DW_TAG_enumerator))
+ *flags &= ~IS_STATIC;
+ }
+
+ return info_ptr;
+}
+
+const gdb_byte *
+cooked_indexer::index_imported_unit (cutu_reader *reader,
+ const gdb_byte *info_ptr,
+ const abbrev_info *abbrev)
+{
+ sect_offset sect_off {};
+ bool is_dwz = false;
+
+ for (int i = 0; i < abbrev->num_attrs; ++i)
+ {
+ /* Note that we never need to reprocess attributes here. */
+ attribute attr;
+ info_ptr = read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
+
+ if (attr.name == DW_AT_import)
+ {
+ sect_off = attr.get_ref_die_offset ();
+ is_dwz = (attr.form == DW_FORM_GNU_ref_alt
+ || reader->cu->per_cu->is_dwz);
+ }
+ }
+
+ /* Did not find DW_AT_import. */
+ if (sect_off == sect_offset (0))
+ return info_ptr;
+
+ dwarf2_per_objfile *per_objfile = reader->cu->per_objfile;
+ cutu_reader *new_reader = ensure_cu_exists (reader, per_objfile, sect_off,
+ is_dwz, true);
+ if (new_reader != nullptr)
+ {
+ index_dies (new_reader, new_reader->info_ptr, nullptr, false);
+
+ reader->cu->add_dependence (new_reader->cu->per_cu);
+ }
+
+ return info_ptr;
+}
+
+const gdb_byte *
+cooked_indexer::recurse (cutu_reader *reader,
+ const gdb_byte *info_ptr,
+ const cooked_index_entry *parent_entry,
+ bool fully)
+{
+ info_ptr = index_dies (reader, info_ptr, parent_entry, fully);
+
+ if (parent_entry != nullptr)
+ {
+ CORE_ADDR start = form_addr (parent_entry->die_offset,
+ reader->cu->per_cu->is_dwz);
+ CORE_ADDR end = form_addr (sect_offset (info_ptr - 1 - reader->buffer),
+ reader->cu->per_cu->is_dwz);
+ addrmap_set_empty (m_die_range_map, start, end, (void *) parent_entry);
+ }
+
+ return info_ptr;
+}
+
+const gdb_byte *
+cooked_indexer::index_dies (cutu_reader *reader,
+ const gdb_byte *info_ptr,
+ const cooked_index_entry *parent_entry,
+ bool fully)
+{
+ const gdb_byte *end_ptr = info_ptr + reader->cu->header.get_length ();
+
+ while (info_ptr < end_ptr)
+ {
+ sect_offset this_die = (sect_offset) (info_ptr - reader->buffer);
+ unsigned int bytes_read;
+ const abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr,
+ &bytes_read);
+ info_ptr += bytes_read;
+ if (abbrev == nullptr)
+ break;
+
+ if (abbrev->tag == DW_TAG_imported_unit)
+ {
+ info_ptr = index_imported_unit (reader, info_ptr, abbrev);
+ continue;
+ }
+
+ if (!abbrev->interesting)
+ {
+ info_ptr = skip_one_die (reader, info_ptr, abbrev, !fully);
+ if (fully && abbrev->has_children)
+ info_ptr = index_dies (reader, info_ptr, parent_entry, fully);
+ continue;
+ }
+
+ const char *name = nullptr;
+ const char *linkage_name = nullptr;
+ CORE_ADDR defer = 0;
+ cooked_index_flag flags = IS_STATIC;
+ sect_offset sibling {};
+ const cooked_index_entry *this_parent_entry = parent_entry;
+ info_ptr = scan_attributes (reader->cu->per_cu, reader, info_ptr,
+ info_ptr, abbrev, &name, &linkage_name,
+ &flags, &sibling, &this_parent_entry,
+ &defer, false);
+
+ if (abbrev->tag == DW_TAG_namespace
+ && m_language == language_cplus
+ && strcmp (name, "::") == 0)
+ {
+ /* GCC 4.0 and 4.1 had a bug (PR c++/28460) where they
+ generated bogus DW_TAG_namespace DIEs with a name of "::"
+ for the global namespace. Work around this problem
+ here. */
+ name = nullptr;
+ }
+
+ const cooked_index_entry *this_entry = nullptr;
+ if (name != nullptr)
+ {
+ if (defer != 0)
+ m_deferred_entries.push_back ({
+ this_die, name, defer, abbrev->tag, flags
+ });
+ else
+ this_entry = m_index_storage->add (this_die, abbrev->tag, flags,
+ name, this_parent_entry,
+ m_per_cu);
+ }
+
+ if (linkage_name != nullptr)
+ {
+ /* We only want this to be "main" if it has a linkage name
+ but not an ordinary name. */
+ if (name != nullptr)
+ flags = flags & ~IS_MAIN;
+ m_index_storage->add (this_die, abbrev->tag, flags | IS_LINKAGE,
+ linkage_name, nullptr, m_per_cu);
+ }
+
+ if (abbrev->has_children)
+ {
+ switch (abbrev->tag)
+ {
+ case DW_TAG_class_type:
+ case DW_TAG_interface_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ if (m_language != language_c && this_entry != nullptr)
+ {
+ info_ptr = recurse (reader, info_ptr, this_entry, fully);
+ continue;
+ }
+ break;
+
+ case DW_TAG_enumeration_type:
+ /* We need to recurse even for an anonymous enumeration.
+ Which scope we record as the parent scope depends on
+ whether we're reading an "enum class". If so, we use
+ the enum itself as the parent, yielding names like
+ "enum_class::enumerator"; otherwise we inject the
+ names into our own parent scope. */
+ info_ptr = recurse (reader, info_ptr,
+ ((flags & IS_ENUM_CLASS) == 0)
+ ? parent_entry
+ : this_entry,
+ fully);
+ continue;
+
+ case DW_TAG_module:
+ if (this_entry == nullptr)
+ break;
+ /* FALLTHROUGH */
+ case DW_TAG_namespace:
+ /* We don't check THIS_ENTRY for a namespace, to handle
+ the ancient G++ workaround pointed out above. */
+ info_ptr = recurse (reader, info_ptr, this_entry, fully);
+ continue;
+
+ case DW_TAG_subprogram:
+ if ((m_language == language_fortran
+ || m_language == language_ada)
+ && this_entry != nullptr)
+ {
+ info_ptr = recurse (reader, info_ptr, this_entry, true);
+ continue;
+ }
+ break;
+ }
+
+ if (sibling != sect_offset (0))
+ {
+ const gdb_byte *sibling_ptr
+ = reader->buffer + to_underlying (sibling);
+
+ if (sibling_ptr < info_ptr)
+ complaint (_("DW_AT_sibling points backwards"));
+ else if (sibling_ptr > reader->buffer_end)
+ reader->die_section->overflow_complaint ();
+ else
+ info_ptr = sibling_ptr;
+ }
+ else
+ info_ptr = skip_children (reader, info_ptr);
+ }
+ }
+
+ return info_ptr;
+}
+
+void
+cooked_indexer::make_index (cutu_reader *reader)
+{
+ check_bounds (reader);
+ find_file_and_directory (reader->comp_unit_die, reader->cu);
+ if (!reader->comp_unit_die->has_children)
+ return;
+ index_dies (reader, reader->info_ptr, nullptr, false);
+
+ for (const auto &entry : m_deferred_entries)
+ {
+ CORE_ADDR key = form_addr (entry.die_offset, m_per_cu->is_dwz);
+ cooked_index_entry *parent
+ = (cooked_index_entry *) addrmap_find (m_die_range_map, key);
+ m_index_storage->add (entry.die_offset, entry.tag, entry.flags,
+ entry.name, parent, m_per_cu);
+ }
+}
+
+/* An implementation of quick_symbol_functions for the cooked DWARF
+ index. */
+
+struct cooked_index_functions : public dwarf2_base_index_functions
+{
+ struct compunit_symtab *find_pc_sect_compunit_symtab
+ (struct objfile *objfile, struct bound_minimal_symbol msymbol,
+ CORE_ADDR pc, struct obj_section *section, int warn_if_readin) override;
+
+ struct compunit_symtab *find_compunit_symtab_by_address
+ (struct objfile *objfile, CORE_ADDR address) override;
+
+ void dump (struct objfile *objfile) override
+ {
+ gdb_printf ("Cooked index in use\n");
+ }
+
+ void expand_matching_symbols
+ (struct objfile *,
+ const lookup_name_info &lookup_name,
+ domain_enum domain,
+ int global,
+ symbol_compare_ftype *ordered_compare) override;
+
+ bool expand_symtabs_matching
+ (struct objfile *objfile,
+ gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
+ const lookup_name_info *lookup_name,
+ gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
+ gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+ block_search_flags search_flags,
+ domain_enum domain,
+ enum search_domain kind) override;
+
+ bool can_lazily_read_symbols () override
+ {
+ return true;
+ }
+
+ void read_partial_symbols (struct objfile *objfile) override
+ {
+ if (dwarf2_has_info (objfile, nullptr))
+ dwarf2_build_psymtabs (objfile);
+ }
+};
+
+struct compunit_symtab *
+cooked_index_functions::find_pc_sect_compunit_symtab
+ (struct objfile *objfile,
+ struct bound_minimal_symbol msymbol,
+ CORE_ADDR pc,
+ struct obj_section *section,
+ int warn_if_readin)
+{
+ dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+ if (per_objfile->per_bfd->cooked_index_table == nullptr)
+ return nullptr;
+
+ CORE_ADDR baseaddr = objfile->text_section_offset ();
+ dwarf2_per_cu_data *per_cu
+ = per_objfile->per_bfd->cooked_index_table->lookup (pc - baseaddr);
+ if (per_cu == nullptr)
+ return nullptr;
+
+ if (warn_if_readin && per_objfile->symtab_set_p (per_cu))
+ warning (_("(Internal error: pc %s in read in CU, but not in symtab.)"),
+ paddress (objfile->arch (), pc));
+
+ compunit_symtab *result = (recursively_find_pc_sect_compunit_symtab
+ (dw2_instantiate_symtab (per_cu, per_objfile,
+ false),
+ pc));
+ gdb_assert (result != nullptr);
+ return result;
+}
+
+struct compunit_symtab *
+cooked_index_functions::find_compunit_symtab_by_address
+ (struct objfile *objfile, CORE_ADDR address)
+{
+ if (objfile->sect_index_data == -1)
+ return nullptr;
+
+ dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+ if (per_objfile->per_bfd->cooked_index_table == nullptr)
+ return nullptr;
+
+ CORE_ADDR baseaddr = objfile->data_section_offset ();
+ dwarf2_per_cu_data *per_cu
+ = per_objfile->per_bfd->cooked_index_table->lookup (address - baseaddr);
+ if (per_cu == nullptr)
+ return nullptr;
+
+ return dw2_instantiate_symtab (per_cu, per_objfile, false);
+}
+
+void
+cooked_index_functions::expand_matching_symbols
+ (struct objfile *objfile,
+ const lookup_name_info &lookup_name,
+ domain_enum domain,
+ int global,
+ symbol_compare_ftype *ordered_compare)
+{
+ dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+ if (per_objfile->per_bfd->cooked_index_table == nullptr)
+ return;
+ const block_search_flags search_flags = (global
+ ? SEARCH_GLOBAL_BLOCK
+ : SEARCH_STATIC_BLOCK);
+ const language_defn *lang = language_def (language_ada);
+ symbol_name_matcher_ftype *name_match
+ = lang->get_symbol_name_matcher (lookup_name);
+
+ for (const cooked_index_entry *entry
+ : per_objfile->per_bfd->cooked_index_table->all_entries ())
+ {
+ if (entry->parent_entry != nullptr)
+ continue;
+
+ if (!entry->matches (search_flags)
+ || !entry->matches (domain))
+ continue;
+
+ if (name_match (entry->canonical, lookup_name, nullptr))
+ dw2_instantiate_symtab (entry->per_cu, per_objfile, false);
+ }
+}
+
+bool
+cooked_index_functions::expand_symtabs_matching
+ (struct objfile *objfile,
+ gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
+ const lookup_name_info *lookup_name,
+ gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
+ gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+ block_search_flags search_flags,
+ domain_enum domain,
+ enum search_domain kind)
+{
+ dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+ if (per_objfile->per_bfd->cooked_index_table == nullptr)
+ return true;
+
+ dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
+
+ /* This invariant is documented in quick-functions.h. */
+ gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr);
+ if (lookup_name == nullptr)
+ {
+ for (dwarf2_per_cu_data *per_cu
+ : all_comp_units_range (per_objfile->per_bfd))
+ {
+ QUIT;
+
+ if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
+ file_matcher,
+ expansion_notify))
+ return false;
+ }
+ return true;
+ }
+
+ lookup_name_info lookup_name_without_params
+ = lookup_name->make_ignore_params ();
+ bool completing = lookup_name->completion_mode ();
+
+ /* Unique styles of language splitting. */
+ static const enum language unique_styles[] =
+ {
+ /* No splitting is also a style. */
+ language_c,
+ /* This includes Rust. */
+ language_cplus,
+ /* This includes Go. */
+ language_d,
+ language_ada
+ };
+
+ for (enum language lang : unique_styles)
+ {
+ std::vector<gdb::string_view> name_vec
+ = lookup_name_without_params.split_name (lang);
+
+ for (const cooked_index_entry *entry
+ : per_objfile->per_bfd->cooked_index_table->find (name_vec.back (),
+ completing))
+ {
+ /* No need to consider symbols from expanded CUs. */
+ if (per_objfile->symtab_set_p (entry->per_cu))
+ continue;
+
+ /* If file-matching was done, we don't need to consider
+ symbols from unmarked CUs. */
+ if (file_matcher != nullptr && !entry->per_cu->v.quick->mark)
+ continue;
+
+ /* See if the symbol matches the type filter. */
+ if (!entry->matches (search_flags)
+ || !entry->matches (domain)
+ || !entry->matches (kind))
+ continue;
+
+ /* We've found the base name of the symbol; now walk its
+ parentage chain, ensuring that each component
+ matches. */
+ bool found = true;
+
+ const cooked_index_entry *parent = entry->parent_entry;
+ for (int i = name_vec.size () - 1; i > 0; --i)
+ {
+ /* If we ran out of entries, or if this segment doesn't
+ match, this did not match. */
+ if (parent == nullptr
+ || strncmp (parent->name, name_vec[i - 1].data (),
+ name_vec[i - 1].length ()) != 0)
+ {
+ found = false;
+ break;
+ }
+
+ parent = parent->parent_entry;
+ }
+
+ if (!found)
+ continue;
+
+ /* Might have been looking for "a::b" and found
+ "x::a::b". */
+ if (symbol_matcher == nullptr)
+ {
+ symbol_name_match_type match_type
+ = lookup_name_without_params.match_type ();
+ if ((match_type == symbol_name_match_type::FULL
+ || (lang != language_ada
+ && match_type == symbol_name_match_type::EXPRESSION))
+ && parent != nullptr)
+ continue;
+ }
+ else
+ {
+ auto_obstack temp_storage;
+ const char *full_name = entry->full_name (&temp_storage);
+ if (!symbol_matcher (full_name))
+ continue;
+ }
+
+ if (!dw2_expand_symtabs_matching_one (entry->per_cu, per_objfile,
+ file_matcher,
+ expansion_notify))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* Return a new cooked_index_functions object. */
+
+static quick_symbol_functions_up
+make_cooked_index_funcs ()
+{
+ return quick_symbol_functions_up (new cooked_index_functions);
+}
+
+\f
+
/* Returns nonzero if TAG represents a type that we might generate a partial
symbol for. */
case DW_TAG_enumeration_type:
case DW_TAG_structure_type:
case DW_TAG_subrange_type:
+ case DW_TAG_generic_subrange:
case DW_TAG_typedef:
case DW_TAG_union_type:
return 1;
&& ((pdi.tag == DW_TAG_typedef && !pdi.has_children)
|| pdi.tag == DW_TAG_base_type
|| pdi.tag == DW_TAG_array_type
+ || pdi.tag == DW_TAG_generic_subrange
|| pdi.tag == DW_TAG_subrange_type))
{
if (building_psymtab && pdi.raw_name != NULL)
{
/* Offset in the .debug_ranges or .debug_rnglist section (depending
on DWARF version). */
- ULONGEST ranges_offset = attr.as_unsigned ();
+ ranges_offset = attr.as_unsigned ();
/* See dwarf2_cu::gnu_ranges_base's doc for why we might want to add
this value. */
if (tag != DW_TAG_compile_unit)
ranges_offset += cu->gnu_ranges_base;
- if (dwarf2_ranges_read (ranges_offset, &lowpc, &highpc, cu,
- nullptr, tag))
- has_pc_info = 1;
+ has_range_info = 1;
}
break;
}
dwarf2_per_cu_data *per_cu
= dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
- per_objfile);
+ per_objfile->per_bfd);
cu = per_objfile->get_cu (per_cu);
if (cu == NULL || cu->partial_dies == NULL)
break;
}
default:
- gdb_assert_not_reached (_("Unexpected DWARF form."));
+ gdb_assert_not_reached ("Unexpected DWARF form.");
}
}
/* See read.h. */
+const char *
+dwarf2_per_objfile::read_line_string (const gdb_byte *buf,
+ unsigned int offset_size)
+{
+ bfd *abfd = objfile->obfd;
+ ULONGEST str_offset = read_offset (abfd, buf, offset_size);
+
+ return per_bfd->line_str.read_string (objfile, str_offset, "DW_FORM_line_strp");
+}
+
+/* See read.h. */
+
const char *
dwarf2_per_objfile::read_line_string (const gdb_byte *buf,
const struct comp_unit_head *cu_header,
}
/* Subroutine of dwarf_decode_lines to simplify it.
- Return the file name of the psymtab for the given file_entry.
- COMP_DIR is the compilation directory (DW_AT_comp_dir) or NULL if unknown.
+ Return the file name for the given file_entry.
+ CU_INFO describes the CU's DW_AT_name and DW_AT_comp_dir.
If space for the result is malloc'd, *NAME_HOLDER will be set.
- Returns NULL if FILE_INDEX should be ignored, i.e., it is pst->filename. */
+ Returns NULL if FILE_INDEX should be ignored, i.e., it is
+ equivalent to CU_INFO. */
static const char *
-psymtab_include_file_name (const struct line_header *lh, const file_entry &fe,
- const dwarf2_psymtab *pst,
- const char *comp_dir,
+compute_include_file_name (const struct line_header *lh, const file_entry &fe,
+ const file_and_directory &cu_info,
gdb::unique_xmalloc_ptr<char> *name_holder)
{
const char *include_name = fe.name;
const char *include_name_to_compare = include_name;
- const char *pst_filename;
- int file_is_pst;
const char *dir_name = fe.include_dir (lh);
gdb::unique_xmalloc_ptr<char> hold_compare;
if (!IS_ABSOLUTE_PATH (include_name)
- && (dir_name != NULL || comp_dir != NULL))
+ && (dir_name != nullptr || cu_info.get_comp_dir () != nullptr))
{
- /* Avoid creating a duplicate psymtab for PST.
- We do this by comparing INCLUDE_NAME and PST_FILENAME.
+ /* Avoid creating a duplicate name for CU_INFO.
+ We do this by comparing INCLUDE_NAME and CU_INFO.
Before we do the comparison, however, we need to account
for DIR_NAME and COMP_DIR.
First prepend dir_name (if non-NULL). If we still don't
include_name = name_holder->get ();
include_name_to_compare = include_name;
}
- if (!IS_ABSOLUTE_PATH (include_name) && comp_dir != NULL)
+ if (!IS_ABSOLUTE_PATH (include_name)
+ && cu_info.get_comp_dir () != nullptr)
{
- hold_compare.reset (concat (comp_dir, SLASH_STRING,
+ hold_compare.reset (concat (cu_info.get_comp_dir (), SLASH_STRING,
include_name, (char *) NULL));
include_name_to_compare = hold_compare.get ();
}
}
- pst_filename = pst->filename;
gdb::unique_xmalloc_ptr<char> copied_name;
- if (!IS_ABSOLUTE_PATH (pst_filename) && pst->dirname != NULL)
+ const char *cu_filename = cu_info.get_name ();
+ if (!IS_ABSOLUTE_PATH (cu_filename) && cu_info.get_comp_dir () != nullptr)
{
- copied_name.reset (concat (pst->dirname, SLASH_STRING,
- pst_filename, (char *) NULL));
- pst_filename = copied_name.get ();
+ copied_name.reset (concat (cu_info.get_comp_dir (), SLASH_STRING,
+ cu_filename, (char *) NULL));
+ cu_filename = copied_name.get ();
}
- file_is_pst = FILENAME_CMP (include_name_to_compare, pst_filename) == 0;
-
- if (file_is_pst)
- return NULL;
+ if (FILENAME_CMP (include_name_to_compare, cu_filename) == 0)
+ return nullptr;
return include_name;
}
/* Handle DW_LNS_negate_stmt. */
void handle_negate_stmt ()
{
- m_is_stmt = !m_is_stmt;
+ m_flags ^= LEF_IS_STMT;
}
/* Handle DW_LNS_const_add_pc. */
{
record_line (false);
m_discriminator = 0;
+ m_flags &= ~LEF_PROLOGUE_END;
}
/* Handle DW_LNE_end_sequence. */
m_currently_recording_lines = true;
}
+ /* Handle DW_LNS_set_prologue_end. */
+ void handle_set_prologue_end ()
+ {
+ m_flags |= LEF_PROLOGUE_END;
+ }
+
private:
/* Advance the line by LINE_DELTA. */
void advance_line (int line_delta)
/* These are initialized in the constructor. */
CORE_ADDR m_address;
- bool m_is_stmt;
+ linetable_entry_flags m_flags;
unsigned int m_discriminator;
/* Additional bits of state we need to track. */
CORE_ADDR m_last_address;
/* Set to true when a previous line at the same address (using
- m_last_address) had m_is_stmt true. This is reset to false when a
- line entry at a new address (m_address different to m_last_address) is
- processed. */
+ m_last_address) had LEF_IS_STMT set in m_flags. This is reset to false
+ when a line entry at a new address (m_address different to
+ m_last_address) is processed. */
bool m_stmt_at_address = false;
/* When true, record the lines we decode. */
advance_line (line_delta);
record_line (false);
m_discriminator = 0;
+ m_flags &= ~LEF_PROLOGUE_END;
}
void
static void
dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
- unsigned int line, CORE_ADDR address, bool is_stmt,
+ unsigned int line, CORE_ADDR address,
+ linetable_entry_flags flags,
struct dwarf2_cu *cu)
{
CORE_ADDR addr = gdbarch_addr_bits_remove (gdbarch, address);
if (dwarf_line_debug)
{
- fprintf_unfiltered (gdb_stdlog,
- "Recording line %u, file %s, address %s\n",
- line, lbasename (subfile->name),
- paddress (gdbarch, address));
+ gdb_printf (gdb_stdlog,
+ "Recording line %u, file %s, address %s\n",
+ line, lbasename (subfile->name),
+ paddress (gdbarch, address));
}
if (cu != nullptr)
- cu->get_builder ()->record_line (subfile, line, addr, is_stmt);
+ cu->get_builder ()->record_line (subfile, line, addr, flags);
}
/* Subroutine of dwarf_decode_lines_1 to simplify it.
if (dwarf_line_debug)
{
- fprintf_unfiltered (gdb_stdlog,
- "Finishing current line, file %s, address %s\n",
- lbasename (subfile->name),
- paddress (gdbarch, address));
+ gdb_printf (gdb_stdlog,
+ "Finishing current line, file %s, address %s\n",
+ lbasename (subfile->name),
+ paddress (gdbarch, address));
}
- dwarf_record_line_1 (gdbarch, subfile, 0, address, true, cu);
+ dwarf_record_line_1 (gdbarch, subfile, 0, address, LEF_IS_STMT, cu);
}
void
{
if (dwarf_line_debug)
{
- fprintf_unfiltered (gdb_stdlog,
- "Processing actual line %u: file %u,"
- " address %s, is_stmt %u, discrim %u%s\n",
- m_line, m_file,
- paddress (m_gdbarch, m_address),
- m_is_stmt, m_discriminator,
- (end_sequence ? "\t(end sequence)" : ""));
+ gdb_printf (gdb_stdlog,
+ "Processing actual line %u: file %u,"
+ " address %s, is_stmt %u, prologue_end %u, discrim %u%s\n",
+ m_line, m_file,
+ paddress (m_gdbarch, m_address),
+ (m_flags & LEF_IS_STMT) != 0,
+ (m_flags & LEF_PROLOGUE_END) != 0,
+ m_discriminator,
+ (end_sequence ? "\t(end sequence)" : ""));
}
file_entry *fe = current_file ();
= m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
bool ignore_this_line
= ((file_changed && !end_sequence && m_last_address == m_address
- && !m_is_stmt && m_stmt_at_address)
+ && ((m_flags & LEF_IS_STMT) == 0)
+ && m_stmt_at_address)
|| (!end_sequence && m_line == 0));
if ((file_changed && !ignore_this_line) || end_sequence)
if (!end_sequence && !ignore_this_line)
{
- bool is_stmt = producer_is_codewarrior (m_cu) || m_is_stmt;
+ linetable_entry_flags lte_flags = m_flags;
+ if (producer_is_codewarrior (m_cu))
+ lte_flags |= LEF_IS_STMT;
if (dwarf_record_line_p (m_cu, m_line, m_last_line,
m_line_has_non_zero_discriminator,
buildsym_compunit *builder = m_cu->get_builder ();
dwarf_record_line_1 (m_gdbarch,
builder->get_current_subfile (),
- m_line, m_address, is_stmt,
+ m_line, m_address, lte_flags,
m_currently_recording_lines ? m_cu : nullptr);
}
m_last_subfile = m_cu->get_builder ()->get_current_subfile ();
}
}
- /* Track whether we have seen any m_is_stmt true at m_address in case we
+ /* Track whether we have seen any IS_STMT true at m_address in case we
have multiple line table entries all at m_address. */
if (m_last_address != m_address)
{
m_stmt_at_address = false;
m_last_address = m_address;
}
- m_stmt_at_address |= m_is_stmt;
+ m_stmt_at_address |= (m_flags & LEF_IS_STMT) != 0;
}
lnp_state_machine::lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch,
and also record it in case it needs it. This is currently used by MIPS
code, cf. `mips_adjust_dwarf2_line'. */
m_address = gdbarch_adjust_dwarf2_line (arch, 0, 0);
- m_is_stmt = lh->default_is_stmt;
+ m_flags = 0;
+ if (lh->default_is_stmt)
+ m_flags |= LEF_IS_STMT;
m_discriminator = 0;
m_last_address = m_address;
state_machine.handle_fixed_advance_pc (addr_adj);
}
break;
+ case DW_LNS_set_prologue_end:
+ state_machine.handle_set_prologue_end ();
+ break;
default:
{
/* Unknown standard opcode, ignore it. */
the list of files included by the unit represented by PST, and
builds all the associated partial symbol tables.
- COMP_DIR is the compilation directory (DW_AT_comp_dir) or NULL if unknown.
+ FND holds the CU file name and directory, if known.
It is used for relative paths in the line table.
- NOTE: When processing partial symtabs (pst != NULL),
- comp_dir == pst->dirname.
- NOTE: It is important that psymtabs have the same file name (via strcmp)
- as the corresponding symtab. Since COMP_DIR is not used in the name of the
- symtab we don't use it in the name of the psymtabs we create.
- E.g. expand_line_sal requires this when finding psymtabs to expand.
- A good testcase for this is mb-inline.exp.
+ NOTE: It is important that psymtabs have the same file name (via
+ strcmp) as the corresponding symtab. Since the directory is not
+ used in the name of the symtab we don't use it in the name of the
+ psymtabs we create. E.g. expand_line_sal requires this when
+ finding psymtabs to expand. A good testcase for this is
+ mb-inline.exp.
LOWPC is the lowest address in CU (or 0 if not known).
table is read in. */
static void
-dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
+dwarf_decode_lines (struct line_header *lh, const file_and_directory &fnd,
struct dwarf2_cu *cu, dwarf2_psymtab *pst,
CORE_ADDR lowpc, int decode_mapping)
{
{
gdb::unique_xmalloc_ptr<char> name_holder;
const char *include_name =
- psymtab_include_file_name (lh, file_entry, pst,
- comp_dir, &name_holder);
+ compute_include_file_name (lh, file_entry, fnd, &name_holder);
if (include_name != NULL)
dwarf2_create_include_psymtab
(cu->per_objfile->per_bfd, include_name, pst,
variable has been optimized away. */
if (attr->form_is_block () && attr->as_block ()->size == 0)
{
- SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
+ sym->set_aclass_index (LOC_OPTIMIZED_OUT);
return;
}
unsigned int dummy;
if (block->data[0] == DW_OP_addr)
- SET_SYMBOL_VALUE_ADDRESS
- (sym, cu->header.read_address (objfile->obfd,
- block->data + 1,
- &dummy));
+ sym->set_value_address
+ (cu->header.read_address (objfile->obfd, block->data + 1,
+ &dummy));
else
- SET_SYMBOL_VALUE_ADDRESS
- (sym, read_addr_index_from_leb128 (cu, block->data + 1,
- &dummy));
- SYMBOL_ACLASS_INDEX (sym) = LOC_STATIC;
+ sym->set_value_address
+ (read_addr_index_from_leb128 (cu, block->data + 1, &dummy));
+ sym->set_aclass_index (LOC_STATIC);
fixup_symbol_section (sym, objfile);
- SET_SYMBOL_VALUE_ADDRESS
- (sym,
- SYMBOL_VALUE_ADDRESS (sym)
+ sym->set_value_address
+ (sym->value_address ()
+ objfile->section_offsets[sym->section_index ()]);
return;
}
sym->set_linkage_name (linkagename);
}
+ /* Handle DW_AT_artificial. */
+ attr = dwarf2_attr (die, DW_AT_artificial, cu);
+ if (attr != nullptr)
+ sym->artificial = attr->as_boolean ();
+
/* Default assumptions.
Use the passed type or decode it from the die. */
- SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
- SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
+ sym->set_domain (VAR_DOMAIN);
+ sym->set_aclass_index (LOC_OPTIMIZED_OUT);
if (type != NULL)
- SYMBOL_TYPE (sym) = type;
+ sym->set_type (type);
else
- SYMBOL_TYPE (sym) = die_type (die, cu);
+ sym->set_type (die_type (die, cu));
attr = dwarf2_attr (die,
inlined_func ? DW_AT_call_line : DW_AT_decl_line,
cu);
if (attr != nullptr)
- SYMBOL_LINE (sym) = attr->constant_value (0);
+ sym->set_line (attr->constant_value (0));
attr = dwarf2_attr (die,
inlined_func ? DW_AT_call_file : DW_AT_decl_file,
addr = attr->as_address ();
addr = gdbarch_adjust_dwarf2_addr (gdbarch, addr + baseaddr);
- SET_SYMBOL_VALUE_ADDRESS (sym, addr);
- SYMBOL_ACLASS_INDEX (sym) = LOC_LABEL;
+ sym->set_value_address (addr);
+ sym->set_aclass_index (LOC_LABEL);
}
else
- SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
- SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_core_addr;
- SYMBOL_DOMAIN (sym) = LABEL_DOMAIN;
+ sym->set_aclass_index (LOC_OPTIMIZED_OUT);
+ sym->set_type (objfile_type (objfile)->builtin_core_addr);
+ sym->set_domain (LABEL_DOMAIN);
add_symbol_to_list (sym, cu->list_in_scope);
break;
case DW_TAG_subprogram:
/* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
finish_block. */
- SYMBOL_ACLASS_INDEX (sym) = LOC_BLOCK;
+ sym->set_aclass_index (LOC_BLOCK);
attr2 = dwarf2_attr (die, DW_AT_external, cu);
if ((attr2 != nullptr && attr2->as_boolean ())
|| cu->per_cu->lang == language_ada
case DW_TAG_inlined_subroutine:
/* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
finish_block. */
- SYMBOL_ACLASS_INDEX (sym) = LOC_BLOCK;
- SYMBOL_INLINED (sym) = 1;
+ sym->set_aclass_index (LOC_BLOCK);
+ sym->set_is_inlined (1);
list_to_add = cu->list_in_scope;
break;
case DW_TAG_template_value_param:
/* Compilation with minimal debug info may result in
variables with missing type entries. Change the
misleading `void' type to something sensible. */
- if (SYMBOL_TYPE (sym)->code () == TYPE_CODE_VOID)
- SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_int;
+ if (sym->type ()->code () == TYPE_CODE_VOID)
+ sym->set_type (objfile_type (objfile)->builtin_int);
attr = dwarf2_attr (die, DW_AT_const_value, cu);
/* In the case of DW_TAG_member, we should only be called for
&& die->parent->tag == DW_TAG_common_block)
attr2 = NULL;
- if (SYMBOL_CLASS (sym) == LOC_STATIC
- && SYMBOL_VALUE_ADDRESS (sym) == 0
+ if (sym->aclass () == LOC_STATIC
+ && sym->value_address () == 0
&& !per_objfile->per_bfd->has_section_at_zero)
{
/* When a static variable is eliminated by the linker,
}
else if (attr2 != nullptr && attr2->as_boolean ())
{
- if (SYMBOL_CLASS (sym) == LOC_STATIC
+ if (sym->aclass () == LOC_STATIC
&& (objfile->flags & OBJF_MAINLINE) == 0
&& per_objfile->per_bfd->can_copy)
{
? cu->get_builder ()->get_global_symbols ()
: cu->list_in_scope);
- SYMBOL_ACLASS_INDEX (sym) = LOC_UNRESOLVED;
+ sym->set_aclass_index (LOC_UNRESOLVED);
}
else if (!die_is_declaration (die, cu))
{
/* Use the default LOC_OPTIMIZED_OUT class. */
- gdb_assert (SYMBOL_CLASS (sym) == LOC_OPTIMIZED_OUT);
+ gdb_assert (sym->aclass () == LOC_OPTIMIZED_OUT);
if (!suppress_add)
list_to_add = cu->list_in_scope;
}
struct context_stack *curr
= cu->get_builder ()->get_current_context_stack ();
if (curr != nullptr && curr->name != nullptr)
- SYMBOL_IS_ARGUMENT (sym) = 1;
+ sym->set_is_argument (1);
attr = dwarf2_attr (die, DW_AT_location, cu);
if (attr != nullptr)
{
case DW_TAG_union_type:
case DW_TAG_set_type:
case DW_TAG_enumeration_type:
- SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
- SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
-
+ case DW_TAG_namelist:
+ if (die->tag == DW_TAG_namelist)
+ {
+ sym->set_aclass_index (LOC_STATIC);
+ sym->set_domain (VAR_DOMAIN);
+ }
+ else
+ {
+ sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_domain (STRUCT_DOMAIN);
+ }
{
/* NOTE: carlton/2003-11-10: C++ class symbols shouldn't
really ever be static objects: otherwise, if you try
/* The symbol's name is already allocated along
with this objfile, so we don't need to
duplicate it for the type. */
- if (SYMBOL_TYPE (sym)->name () == 0)
- SYMBOL_TYPE (sym)->set_name (sym->search_name ());
+ if (sym->type ()->name () == 0)
+ sym->type ()->set_name (sym->search_name ());
}
}
}
break;
case DW_TAG_typedef:
- SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
- SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
+ sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_domain (VAR_DOMAIN);
list_to_add = cu->list_in_scope;
break;
case DW_TAG_array_type:
case DW_TAG_base_type:
case DW_TAG_subrange_type:
- SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
- SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
+ case DW_TAG_generic_subrange:
+ sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_domain (VAR_DOMAIN);
list_to_add = cu->list_in_scope;
break;
case DW_TAG_enumerator:
break;
case DW_TAG_imported_declaration:
case DW_TAG_namespace:
- SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
+ sym->set_aclass_index (LOC_TYPEDEF);
list_to_add = cu->get_builder ()->get_global_symbols ();
break;
case DW_TAG_module:
- SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
- SYMBOL_DOMAIN (sym) = MODULE_DOMAIN;
+ sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_domain (MODULE_DOMAIN);
list_to_add = cu->get_builder ()->get_global_symbols ();
break;
case DW_TAG_common_block:
- SYMBOL_ACLASS_INDEX (sym) = LOC_COMMON_BLOCK;
- SYMBOL_DOMAIN (sym) = COMMON_BLOCK_DOMAIN;
+ sym->set_aclass_index (LOC_COMMON_BLOCK);
+ sym->set_domain (COMMON_BLOCK_DOMAIN);
add_symbol_to_list (sym, cu->list_in_scope);
break;
default:
const gdb_byte *bytes;
struct dwarf2_locexpr_baton *baton;
- dwarf2_const_value_attr (attr, SYMBOL_TYPE (sym),
+ dwarf2_const_value_attr (attr, sym->type (),
sym->print_name (),
&objfile->objfile_obstack, cu,
&value, &bytes, &baton);
if (baton != NULL)
{
SYMBOL_LOCATION_BATON (sym) = baton;
- SYMBOL_ACLASS_INDEX (sym) = dwarf2_locexpr_index;
+ sym->set_aclass_index (dwarf2_locexpr_index);
}
else if (bytes != NULL)
- {
- SYMBOL_VALUE_BYTES (sym) = bytes;
- SYMBOL_ACLASS_INDEX (sym) = LOC_CONST_BYTES;
+ {
+ sym->set_value_bytes (bytes);
+ sym->set_aclass_index (LOC_CONST_BYTES);
}
else
{
- SYMBOL_VALUE (sym) = value;
- SYMBOL_ACLASS_INDEX (sym) = LOC_CONST;
+ sym->set_value_longest (value);
+ sym->set_aclass_index (LOC_CONST);
}
}
struct dwarf2_per_cu_data *per_cu;
sect_offset sect_off = attr->get_ref_die_offset ();
- per_cu = dwarf2_find_containing_comp_unit (sect_off, 1, per_objfile);
+ per_cu = dwarf2_find_containing_comp_unit (sect_off, 1,
+ per_objfile->per_bfd);
this_type = get_die_type_at_offset (sect_off, per_cu, per_objfile);
}
else if (attr->form_is_ref ())
case DW_TAG_typedef:
this_type = read_typedef (die, cu);
break;
+ case DW_TAG_generic_subrange:
case DW_TAG_subrange_type:
this_type = read_subrange_type (die, cu);
break;
&& die->tag != DW_TAG_class_type
&& die->tag != DW_TAG_interface_type
&& die->tag != DW_TAG_structure_type
+ && die->tag != DW_TAG_namelist
&& die->tag != DW_TAG_union_type)
return NULL;
case DW_TAG_interface_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
+ case DW_TAG_namelist:
/* Some GCC versions emit spurious DW_AT_name attributes for unnamed
structures or unions. These were of the form "._%d" in GCC 4.1,
or simply "<anonymous struct>" or "<anonymous union>" in GCC 4.3
{
unsigned int i;
- print_spaces (indent, f);
- fprintf_unfiltered (f, "Die: %s (abbrev %d, offset %s)\n",
- dwarf_tag_name (die->tag), die->abbrev,
- sect_offset_str (die->sect_off));
+ gdb_printf (f, "%*sDie: %s (abbrev %d, offset %s)\n",
+ indent, "",
+ dwarf_tag_name (die->tag), die->abbrev,
+ sect_offset_str (die->sect_off));
if (die->parent != NULL)
- {
- print_spaces (indent, f);
- fprintf_unfiltered (f, " parent at offset: %s\n",
- sect_offset_str (die->parent->sect_off));
- }
+ gdb_printf (f, "%*s parent at offset: %s\n",
+ indent, "",
+ sect_offset_str (die->parent->sect_off));
- print_spaces (indent, f);
- fprintf_unfiltered (f, " has children: %s\n",
- dwarf_bool_name (die->child != NULL));
+ gdb_printf (f, "%*s has children: %s\n",
+ indent, "",
+ dwarf_bool_name (die->child != NULL));
- print_spaces (indent, f);
- fprintf_unfiltered (f, " attributes:\n");
+ gdb_printf (f, "%*s attributes:\n", indent, "");
for (i = 0; i < die->num_attrs; ++i)
{
- print_spaces (indent, f);
- fprintf_unfiltered (f, " %s (%s) ",
- dwarf_attr_name (die->attrs[i].name),
- dwarf_form_name (die->attrs[i].form));
+ gdb_printf (f, "%*s %s (%s) ",
+ indent, "",
+ dwarf_attr_name (die->attrs[i].name),
+ dwarf_form_name (die->attrs[i].form));
switch (die->attrs[i].form)
{
case DW_FORM_addr:
case DW_FORM_addrx:
case DW_FORM_GNU_addr_index:
- fprintf_unfiltered (f, "address: ");
- fputs_filtered (hex_string (die->attrs[i].as_address ()), f);
+ gdb_printf (f, "address: ");
+ gdb_puts (hex_string (die->attrs[i].as_address ()), f);
break;
case DW_FORM_block2:
case DW_FORM_block4:
case DW_FORM_block:
case DW_FORM_block1:
- fprintf_unfiltered (f, "block: size %s",
- pulongest (die->attrs[i].as_block ()->size));
+ gdb_printf (f, "block: size %s",
+ pulongest (die->attrs[i].as_block ()->size));
break;
case DW_FORM_exprloc:
- fprintf_unfiltered (f, "expression: size %s",
- pulongest (die->attrs[i].as_block ()->size));
+ gdb_printf (f, "expression: size %s",
+ pulongest (die->attrs[i].as_block ()->size));
break;
case DW_FORM_data16:
- fprintf_unfiltered (f, "constant of 16 bytes");
+ gdb_printf (f, "constant of 16 bytes");
break;
case DW_FORM_ref_addr:
- fprintf_unfiltered (f, "ref address: ");
- fputs_filtered (hex_string (die->attrs[i].as_unsigned ()), f);
+ gdb_printf (f, "ref address: ");
+ gdb_puts (hex_string (die->attrs[i].as_unsigned ()), f);
break;
case DW_FORM_GNU_ref_alt:
- fprintf_unfiltered (f, "alt ref address: ");
- fputs_filtered (hex_string (die->attrs[i].as_unsigned ()), f);
+ gdb_printf (f, "alt ref address: ");
+ gdb_puts (hex_string (die->attrs[i].as_unsigned ()), f);
break;
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
- fprintf_unfiltered (f, "constant ref: 0x%lx (adjusted)",
- (long) (die->attrs[i].as_unsigned ()));
+ gdb_printf (f, "constant ref: 0x%lx (adjusted)",
+ (long) (die->attrs[i].as_unsigned ()));
break;
case DW_FORM_data1:
case DW_FORM_data2:
case DW_FORM_data4:
case DW_FORM_data8:
case DW_FORM_udata:
- fprintf_unfiltered (f, "constant: %s",
- pulongest (die->attrs[i].as_unsigned ()));
+ gdb_printf (f, "constant: %s",
+ pulongest (die->attrs[i].as_unsigned ()));
break;
case DW_FORM_sec_offset:
- fprintf_unfiltered (f, "section offset: %s",
- pulongest (die->attrs[i].as_unsigned ()));
+ gdb_printf (f, "section offset: %s",
+ pulongest (die->attrs[i].as_unsigned ()));
break;
case DW_FORM_ref_sig8:
- fprintf_unfiltered (f, "signature: %s",
- hex_string (die->attrs[i].as_signature ()));
+ gdb_printf (f, "signature: %s",
+ hex_string (die->attrs[i].as_signature ()));
break;
case DW_FORM_string:
case DW_FORM_strp:
case DW_FORM_strx:
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_strp_alt:
- fprintf_unfiltered (f, "string: \"%s\" (%s canonicalized)",
- die->attrs[i].as_string ()
- ? die->attrs[i].as_string () : "",
- die->attrs[i].canonical_string_p () ? "is" : "not");
+ gdb_printf (f, "string: \"%s\" (%s canonicalized)",
+ die->attrs[i].as_string ()
+ ? die->attrs[i].as_string () : "",
+ die->attrs[i].canonical_string_p () ? "is" : "not");
break;
case DW_FORM_flag:
if (die->attrs[i].as_boolean ())
- fprintf_unfiltered (f, "flag: TRUE");
+ gdb_printf (f, "flag: TRUE");
else
- fprintf_unfiltered (f, "flag: FALSE");
+ gdb_printf (f, "flag: FALSE");
break;
case DW_FORM_flag_present:
- fprintf_unfiltered (f, "flag: TRUE");
+ gdb_printf (f, "flag: TRUE");
break;
case DW_FORM_indirect:
/* The reader will have reduced the indirect form to
the "base form" so this form should not occur. */
- fprintf_unfiltered (f,
- "unexpected attribute form: DW_FORM_indirect");
+ gdb_printf (f,
+ "unexpected attribute form: DW_FORM_indirect");
break;
case DW_FORM_sdata:
case DW_FORM_implicit_const:
- fprintf_unfiltered (f, "constant: %s",
- plongest (die->attrs[i].as_signed ()));
+ gdb_printf (f, "constant: %s",
+ plongest (die->attrs[i].as_signed ()));
break;
default:
- fprintf_unfiltered (f, "unsupported attribute form: %d.",
- die->attrs[i].form);
+ gdb_printf (f, "unsupported attribute form: %d.",
+ die->attrs[i].form);
break;
}
- fprintf_unfiltered (f, "\n");
+ gdb_printf (f, "\n");
}
}
if (die->child != NULL)
{
- print_spaces (indent, f);
- fprintf_unfiltered (f, " Children:");
+ gdb_printf (f, "%*s Children:", indent, "");
if (level + 1 < max_level)
{
- fprintf_unfiltered (f, "\n");
+ gdb_printf (f, "\n");
dump_die_1 (f, level + 1, max_level, die->child);
}
else
{
- fprintf_unfiltered (f,
- " [not printed, max nesting level reached]\n");
+ gdb_printf (f,
+ " [not printed, max nesting level reached]\n");
}
}
struct dwarf2_per_cu_data *per_cu;
per_cu = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
- per_objfile);
+ per_objfile->per_bfd);
dwarf_read_debug_printf_v ("target CU offset: %s, "
"target CU DIEs loaded: %d",
struct dwarf2_section_info *str_offsets_section;
struct dwarf2_section_info *str_section;
- ULONGEST str_offsets_base;
+ gdb::optional<ULONGEST> str_offsets_base;
if (cu->dwo_unit != nullptr)
{
{
str_offsets_section = &per_objfile->per_bfd->str_offsets;
str_section = &per_objfile->per_bfd->str;
- str_offsets_base = *cu->str_offsets_base;
+ str_offsets_base = cu->str_offsets_base;
}
dwarf_decode_macros (per_objfile, builder, section, lh,
complaint (_("Location list used without "
"specifying the CU base address."));
- SYMBOL_ACLASS_INDEX (sym) = (is_block
- ? dwarf2_loclist_block_index
- : dwarf2_loclist_index);
+ sym->set_aclass_index ((is_block
+ ? dwarf2_loclist_block_index
+ : dwarf2_loclist_index));
SYMBOL_LOCATION_BATON (sym) = baton;
}
else
baton->size = 0;
}
- SYMBOL_ACLASS_INDEX (sym) = (is_block
- ? dwarf2_locexpr_block_index
- : dwarf2_locexpr_index);
+ sym->set_aclass_index ((is_block
+ ? dwarf2_locexpr_block_index
+ : dwarf2_locexpr_index));
SYMBOL_LOCATION_BATON (sym) = baton;
}
}
static struct dwarf2_per_cu_data *
dwarf2_find_containing_comp_unit (sect_offset sect_off,
unsigned int offset_in_dwz,
- dwarf2_per_objfile *per_objfile)
+ dwarf2_per_bfd *per_bfd)
{
int low = dwarf2_find_containing_comp_unit
- (sect_off, offset_in_dwz, per_objfile->per_bfd->all_comp_units);
- dwarf2_per_cu_data *this_cu
- = per_objfile->per_bfd->all_comp_units[low].get ();
+ (sect_off, offset_in_dwz, per_bfd->all_comp_units);
+ dwarf2_per_cu_data *this_cu = per_bfd->all_comp_units[low].get ();
if (this_cu->is_dwz != offset_in_dwz || this_cu->sect_off > sect_off)
{
error (_("Dwarf Error: could not find partial DIE containing "
"offset %s [in module %s]"),
sect_offset_str (sect_off),
- bfd_get_filename (per_objfile->objfile->obfd));
+ bfd_get_filename (per_bfd->obfd));
- gdb_assert (per_objfile->per_bfd->all_comp_units[low-1]->sect_off
+ gdb_assert (per_bfd->all_comp_units[low-1]->sect_off
<= sect_off);
- return per_objfile->per_bfd->all_comp_units[low - 1].get ();
+ return per_bfd->all_comp_units[low - 1].get ();
}
else
{
- if (low == per_objfile->per_bfd->all_comp_units.size () - 1
+ if (low == per_bfd->all_comp_units.size () - 1
&& sect_off >= this_cu->sect_off + this_cu->length)
error (_("invalid dwarf2 offset %s"), sect_offset_str (sect_off));
gdb_assert (sect_off < this_cu->sect_off + this_cu->length);
type->add_dyn_prop (DYN_PROP_ASSOCIATED, prop);
}
+ /* Read DW_AT_rank and set in type. */
+ attr = dwarf2_attr (die, DW_AT_rank, cu);
+ if (attr != NULL)
+ {
+ struct type *prop_type = cu->addr_sized_int_type (false);
+ if (attr_to_dynamic_prop (attr, die, cu, &prop, prop_type))
+ type->add_dyn_prop (DYN_PROP_RANK, prop);
+ }
+
/* Read DW_AT_data_location and set in type. */
if (!skip_data_location)
{
show_check_physname (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file,
- _("Whether to check \"physname\" is %s.\n"),
- value);
+ gdb_printf (file,
+ _("Whether to check \"physname\" is %s.\n"),
+ value);
}
void _initialize_dwarf2_read ();
void
_initialize_dwarf2_read ()
{
- add_basic_prefix_cmd ("dwarf", class_maintenance, _("\
+ add_setshow_prefix_cmd ("dwarf", class_maintenance,
+ _("\
Set DWARF specific variables.\n\
Configure DWARF variables such as the cache size."),
- &set_dwarf_cmdlist,
- 0/*allow-unknown*/, &maintenance_set_cmdlist);
-
- add_show_prefix_cmd ("dwarf", class_maintenance, _("\
+ _("\
Show DWARF specific variables.\n\
Show DWARF variables such as the cache size."),
- &show_dwarf_cmdlist,
- 0/*allow-unknown*/, &maintenance_show_cmdlist);
+ &set_dwarf_cmdlist, &show_dwarf_cmdlist,
+ &maintenance_set_cmdlist, &maintenance_show_cmdlist);
add_setshow_zinteger_cmd ("max-cache-age", class_obscure,
&dwarf_max_cache_age, _("\