aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2/read.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/dwarf2/read.c')
-rw-r--r--gdb/dwarf2/read.c3708
1 files changed, 1567 insertions, 2141 deletions
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 55cf02f..162c0bd 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -31,13 +31,14 @@
#include "dwarf2/abbrev.h"
#include "dwarf2/aranges.h"
#include "dwarf2/attribute.h"
-#include "dwarf2/comp-unit-head.h"
+#include "dwarf2/unit-head.h"
#include "dwarf2/cooked-index-worker.h"
#include "dwarf2/cooked-indexer.h"
#include "dwarf2/cu.h"
#include "dwarf2/index-cache.h"
#include "dwarf2/leb.h"
#include "dwarf2/line-header.h"
+#include "dwarf2/line-program.h"
#include "dwarf2/dwz.h"
#include "dwarf2/macro.h"
#include "dwarf2/die.h"
@@ -51,7 +52,8 @@
#include "elf-bfd.h"
#include "event-top.h"
#include "exceptions.h"
-#include "gdbsupport/task-group.h"
+#include "gdbsupport/parallel-for.h"
+#include "maint.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "objfiles.h"
@@ -91,7 +93,6 @@
#include "count-one-bits.h"
#include "dwarf2/abbrev-table-cache.h"
#include "cooked-index.h"
-#include "gdbsupport/thread-pool.h"
#include "run-on-main-thread.h"
#include "dwarf2/parent-map.h"
#include "dwarf2/error.h"
@@ -146,7 +147,7 @@ static const registry<bfd>::key<dwarf2_per_bfd> dwarf2_per_bfd_bfd_data_key;
static const registry<objfile>::key<dwarf2_per_bfd>
dwarf2_per_bfd_objfile_data_key;
-/* The "aclass" indices for various kinds of computed DWARF symbols. */
+/* The "loc_class" indices for various kinds of computed DWARF symbols. */
static int dwarf2_locexpr_index;
static int dwarf2_loclist_index;
@@ -279,7 +280,7 @@ struct dwo_sections
struct dwarf2_section_info str;
struct dwarf2_section_info str_offsets;
/* In the case of a virtual DWO file, these two are unused. */
- struct dwarf2_section_info info;
+ std::vector<dwarf2_section_info> infos;
std::vector<dwarf2_section_info> types;
};
@@ -288,24 +289,29 @@ struct dwo_sections
struct dwo_unit
{
/* Backlink to the containing struct dwo_file. */
- struct dwo_file *dwo_file;
+ struct dwo_file *dwo_file = nullptr;
/* The "id" that distinguishes this CU/TU.
.debug_info calls this "dwo_id", .debug_types calls this "signature".
Since signatures came first, we stick with it for consistency. */
- ULONGEST signature;
+ ULONGEST signature = 0;
/* The section this CU/TU lives in, in the DWO file. */
- struct dwarf2_section_info *section;
+ dwarf2_section_info *section = nullptr;
+
+ /* This is set if SECTION is owned by this dwo_unit. */
+ dwarf2_section_info_up section_holder;
/* Same as dwarf2_per_cu::{sect_off,length} but in the DWO section. */
- sect_offset sect_off;
- unsigned int length;
+ sect_offset sect_off {};
+ unsigned int length = 0;
/* For types, offset in the type's DIE of the type defined by this TU. */
cu_offset type_offset_in_tu;
};
+using dwo_unit_up = std::unique_ptr<dwo_unit>;
+
/* Hash function for dwo_unit objects, based on the signature. */
struct dwo_unit_hash
@@ -315,7 +321,7 @@ struct dwo_unit_hash
std::size_t operator() (ULONGEST signature) const noexcept
{ return signature; }
- std::size_t operator() (const dwo_unit *unit) const noexcept
+ std::size_t operator() (const dwo_unit_up &unit) const noexcept
{ return (*this) (unit->signature); }
};
@@ -329,16 +335,16 @@ struct dwo_unit_eq
{
using is_transparent = void;
- bool operator() (ULONGEST sig, const dwo_unit *unit) const noexcept
+ bool operator() (ULONGEST sig, const dwo_unit_up &unit) const noexcept
{ return sig == unit->signature; }
- bool operator() (const dwo_unit *a, const dwo_unit *b) const noexcept
+ bool operator() (const dwo_unit_up &a, const dwo_unit_up &b) const noexcept
{ return (*this) (a->signature, b); }
};
/* Set of dwo_unit object, using their signature as identity. */
-using dwo_unit_set = gdb::unordered_set<dwo_unit *, dwo_unit_hash, dwo_unit_eq>;
+using dwo_unit_set = gdb::unordered_set<dwo_unit_up, dwo_unit_hash, dwo_unit_eq>;
/* include/dwarf2.h defines the DWP section codes.
It defines a max value but it doesn't define a min value, which we
@@ -598,6 +604,9 @@ struct dwp_file
dwo_unit_set loaded_cus;
dwo_unit_set loaded_tus;
+ /* Mutex to synchronize access to LOADED_CUS and LOADED_TUS. */
+ gdb::mutex loaded_cutus_lock;
+
/* Table to map ELF section numbers to their sections.
This is only needed for the DWP V1 file format. */
unsigned int num_sections = 0;
@@ -622,15 +631,21 @@ struct variant_field
/* A variant can contain other variant parts. */
std::vector<variant_part_builder> variant_parts;
- /* If we see a DW_TAG_variant, then this will be set if this is the
- default branch. */
- bool default_branch = false;
/* If we see a DW_AT_discr_value, then this will be the discriminant
- value. */
- ULONGEST discriminant_value = 0;
+ value. Just the attribute is stored here, because we have to
+ defer deciding whether the value is signed or unsigned until the
+ end. */
+ const attribute *discriminant_attr = nullptr;
/* If we see a DW_AT_discr_list, then this is a pointer to the list
data. */
struct dwarf_block *discr_list_data = nullptr;
+
+ /* If both DW_AT_discr_value and DW_AT_discr_list are absent, then
+ this is the default branch. */
+ bool is_default () const
+ {
+ return discriminant_attr == nullptr && discr_list_data == nullptr;
+ }
};
/* This represents a DW_TAG_variant_part. */
@@ -727,9 +742,6 @@ show_dwarf_synchronous (struct ui_file *file, int from_tty,
/* local function prototypes */
-static void build_type_psymtabs_reader (cutu_reader *reader,
- cooked_index_worker_result *storage);
-
static void var_decode_location (struct attribute *attr,
struct symbol *sym,
struct dwarf2_cu *cu);
@@ -742,9 +754,9 @@ static unrelocated_addr read_addr_index (struct dwarf2_cu *cu,
static sect_offset read_abbrev_offset (dwarf2_per_objfile *per_objfile,
dwarf2_section_info *, sect_offset);
-static const char *read_indirect_string
- (dwarf2_per_objfile *per_objfile, bfd *, const gdb_byte *,
- const struct comp_unit_head *, unsigned int *);
+static const char *read_indirect_string (dwarf2_per_objfile *per_objfile, bfd *,
+ const gdb_byte *, const unit_head *,
+ unsigned int *);
static unrelocated_addr read_addr_index_from_leb128 (struct dwarf2_cu *,
const gdb_byte *,
@@ -773,13 +785,6 @@ static line_header_up dwarf_decode_line_header (sect_offset sect_off,
struct dwarf2_cu *cu,
const char *comp_dir);
-static void dwarf_decode_lines (struct line_header *,
- struct dwarf2_cu *,
- unrelocated_addr, int decode_mapping);
-
-static void dwarf2_start_subfile (dwarf2_cu *cu, const file_entry &fe,
- const line_header &lh);
-
static struct symbol *new_symbol (struct die_info *, struct type *,
struct dwarf2_cu *, struct symbol * = NULL);
@@ -843,6 +848,11 @@ static struct dwarf2_section_info *cu_debug_loc_section (struct dwarf2_cu *cu);
static struct dwarf2_section_info *cu_debug_rnglists_section
(struct dwarf2_cu *cu, dwarf_tag tag);
+static void dw_search_file_matcher
+ (dwarf2_per_objfile *per_objfile,
+ auto_bool_vector &cus_to_skip,
+ search_symtabs_file_matcher file_matcher);
+
static void get_scope_pc_bounds (struct die_info *,
unrelocated_addr *, unrelocated_addr *,
struct dwarf2_cu *);
@@ -906,6 +916,9 @@ static const char *dwarf2_physname (const char *name, struct die_info *die,
static struct die_info *dwarf2_extension (struct die_info *die,
struct dwarf2_cu **);
+static die_info *follow_die_offset (const section_and_offset &target,
+ dwarf2_cu **ref_cu);
+
static struct die_info *follow_die_ref_or_sig (struct die_info *,
const struct attribute *,
struct dwarf2_cu **);
@@ -973,8 +986,12 @@ static void queue_comp_unit (dwarf2_per_cu *per_cu,
static void process_queue (dwarf2_per_objfile *per_objfile);
-static bool is_ada_import_or_export (dwarf2_cu *cu, const char *name,
- const char *linkagename);
+static bool dw2_search_one (dwarf2_per_cu *per_cu,
+ dwarf2_per_objfile *per_objfile,
+ auto_bool_vector &cus_to_skip,
+ search_symtabs_file_matcher file_matcher,
+ search_symtabs_expansion_listener listener,
+ search_symtabs_lang_matcher lang_matcher);
/* Class, the destructor of which frees all allocated queue entries. This
will only have work to do if an error was thrown while processing the
@@ -1023,18 +1040,12 @@ dwarf2_queue_item::~dwarf2_queue_item ()
void
dwarf2_per_cu_deleter::operator() (dwarf2_per_cu *data)
{
- if (data->is_debug_types)
+ if (data->is_debug_types ())
delete static_cast<signatured_type *> (data);
else
delete data;
}
-static const char *compute_include_file_name
- (const struct line_header *lh,
- const file_entry &fe,
- const file_and_directory &cu_info,
- std::string &name_holder);
-
static struct dwo_unit *lookup_dwo_unit_in_dwp
(dwarf2_per_bfd *per_bfd, struct dwp_file *dwp_file,
const char *comp_dir, ULONGEST signature, int is_debug_types);
@@ -1049,19 +1060,6 @@ static void process_cu_includes (dwarf2_per_objfile *per_objfile);
/* Various complaints about symbol reading that don't abort the process. */
static void
-dwarf2_debug_line_missing_file_complaint (void)
-{
- complaint (_(".debug_line section has line data without a file"));
-}
-
-static void
-dwarf2_debug_line_missing_end_sequence_complaint (void)
-{
- complaint (_(".debug_line section has line "
- "program sequence without an end"));
-}
-
-static void
dwarf2_complex_location_expr_complaint (void)
{
complaint (_("location expression too complex"));
@@ -1282,7 +1280,7 @@ dwarf2_has_info (struct objfile *objfile,
BFD, to avoid races. */
try
{
- dwarf2_read_dwz_file (per_objfile);
+ dwz_file::read_dwz_file (per_objfile);
}
catch (const gdb_exception_error &err)
{
@@ -1318,7 +1316,7 @@ dwarf2_per_bfd::locate_sections (asection *sectp,
bfd_size_type size = sectp->size;
warning (_("Discarding section %s which has an invalid size (%s) "
"[in module %s]"),
- bfd_section_name (sectp), phex_nz (size, sizeof (size)),
+ bfd_section_name (sectp), phex_nz (size),
this->filename ());
}
else if (names.info.matches (sectp->name))
@@ -1539,18 +1537,52 @@ struct readnow_functions : public dwarf2_base_index_functions
{
}
- bool expand_symtabs_matching
- (struct objfile *objfile,
- expand_symtabs_file_matcher file_matcher,
- const lookup_name_info *lookup_name,
- expand_symtabs_symbol_matcher symbol_matcher,
- expand_symtabs_expansion_listener expansion_notify,
- block_search_flags search_flags,
- domain_search_flags domain,
- expand_symtabs_lang_matcher lang_matcher) override
+ bool search (struct objfile *objfile,
+ search_symtabs_file_matcher file_matcher,
+ const lookup_name_info *lookup_name,
+ search_symtabs_symbol_matcher symbol_matcher,
+ search_symtabs_expansion_listener listener,
+ block_search_flags search_flags,
+ domain_search_flags domain,
+ search_symtabs_lang_matcher lang_matcher) override
{
+ dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+ auto_bool_vector cus_to_skip;
+ dw_search_file_matcher (per_objfile, cus_to_skip, file_matcher);
+
+ for (const auto &per_cu : per_objfile->per_bfd->all_units)
+ {
+ QUIT;
+
+ /* Skip various types of unit that should not be searched
+ directly: partial units and dummy units. */
+ if (/* Note that we request the non-strict unit type here. If
+ there was an error while reading, like in
+ dw-form-strx-out-of-bounds.exp, then the unit type may
+ not be set. */
+ per_cu->unit_type (false) == DW_UT_partial
+ || per_cu->unit_type (false) == 0
+ || per_objfile->get_symtab (per_cu.get ()) == nullptr)
+ continue;
+ if (!dw2_search_one (per_cu.get (), per_objfile, cus_to_skip,
+ file_matcher, listener, lang_matcher))
+ return false;
+ }
return true;
}
+
+ struct symbol *find_symbol_by_address (struct objfile *objfile,
+ CORE_ADDR address) override
+ {
+ for (compunit_symtab &symtab : objfile->compunits ())
+ {
+ struct symbol *sym = symtab.symbol_at_address (address);
+ if (sym != nullptr)
+ return sym;
+ }
+
+ return nullptr;
+ }
};
/* See read.h. */
@@ -1591,7 +1623,7 @@ static dwarf2_cu *
load_cu (dwarf2_per_cu *per_cu, dwarf2_per_objfile *per_objfile,
bool skip_partial)
{
- if (per_cu->is_debug_types)
+ if (per_cu->is_debug_types ())
load_full_type_unit (per_cu, per_objfile);
else
load_full_comp_unit (per_cu, per_objfile, skip_partial, language_minimal);
@@ -1628,7 +1660,7 @@ dw2_do_instantiate_symtab (dwarf2_per_cu *per_cu,
/* If we just loaded a CU from a DWO, and we're working with an index
that may badly handle TUs, load all the TUs in that DWO as well.
http://sourceware.org/bugzilla/show_bug.cgi?id=15021 */
- if (!per_cu->is_debug_types
+ if (!per_cu->is_debug_types ()
&& cu != NULL
&& cu->dwo_unit != NULL
&& per_objfile->per_bfd->index_table != NULL
@@ -1676,6 +1708,7 @@ dwarf2_per_bfd::allocate_per_cu (dwarf2_section_info *section,
dwarf2_per_cu_up result (new dwarf2_per_cu (this, section, sect_off,
length, is_dwz));
result->index = all_units.size ();
+ this->num_comp_units++;
return result;
}
@@ -1692,10 +1725,79 @@ dwarf2_per_bfd::allocate_signatured_type (dwarf2_section_info *section,
= std::make_unique<signatured_type> (this, section, sect_off, length,
is_dwz, signature);
result->index = all_units.size ();
- tu_stats.nr_tus++;
+ this->num_type_units++;
return result;
}
+/* Subroutine of dw2_get_file_names_reader to simplify it.
+ 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
+ equivalent to CU_INFO. */
+
+static const char *
+compute_include_file_name (const struct line_header *lh, const file_entry &fe,
+ const file_and_directory &cu_info,
+ std::string &name_holder)
+{
+ const char *include_name = fe.name;
+ const char *include_name_to_compare = include_name;
+
+ const char *dir_name = fe.include_dir (lh);
+
+ std::string hold_compare;
+ if (!IS_ABSOLUTE_PATH (include_name)
+ && (dir_name != nullptr || cu_info.get_comp_dir () != nullptr))
+ {
+ /* 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
+ have an absolute path prepend comp_dir (if non-NULL).
+ However, the directory we record in the include-file's
+ psymtab does not contain COMP_DIR (to match the
+ corresponding symtab(s)).
+
+ Example:
+
+ bash$ cd /tmp
+ bash$ gcc -g ./hello.c
+ include_name = "hello.c"
+ dir_name = "."
+ DW_AT_comp_dir = comp_dir = "/tmp"
+ DW_AT_name = "./hello.c"
+
+ */
+
+ if (dir_name != NULL)
+ {
+ name_holder = path_join (dir_name, include_name);
+ include_name = name_holder.c_str ();
+ include_name_to_compare = include_name;
+ }
+ if (!IS_ABSOLUTE_PATH (include_name)
+ && cu_info.get_comp_dir () != nullptr)
+ {
+ hold_compare = path_join (cu_info.get_comp_dir (), include_name);
+ include_name_to_compare = hold_compare.c_str ();
+ }
+ }
+
+ std::string copied_name;
+ const char *cu_filename = cu_info.get_name ();
+ if (!IS_ABSOLUTE_PATH (cu_filename) && cu_info.get_comp_dir () != nullptr)
+ {
+ copied_name = path_join (cu_info.get_comp_dir (), cu_filename);
+ cu_filename = copied_name.c_str ();
+ }
+
+ if (FILENAME_CMP (include_name_to_compare, cu_filename) == 0)
+ return nullptr;
+ return include_name;
+}
+
/* die_reader_func for dw2_get_file_names. */
static void
@@ -1705,7 +1807,7 @@ dw2_get_file_names_reader (dwarf2_cu *cu, die_info *comp_unit_die)
dwarf2_per_objfile *per_objfile = cu->per_objfile;
dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
- gdb_assert (! this_cu->is_debug_types);
+ gdb_assert (!this_cu->is_debug_types ());
this_cu->files_read = true;
/* Our callers never want to match partial units -- instead they
@@ -1788,7 +1890,7 @@ static struct quick_file_names *
dw2_get_file_names (dwarf2_per_cu *this_cu, dwarf2_per_objfile *per_objfile)
{
/* This should never be called for TUs. */
- gdb_assert (! this_cu->is_debug_types);
+ gdb_assert (!this_cu->is_debug_types ());
if (this_cu->files_read)
return this_cu->file_names;
@@ -1850,7 +1952,7 @@ dwarf2_per_cu::free_cached_file_names ()
if (fnd != nullptr)
fnd->forget_fullname ();
- if (per_bfd == nullptr)
+ if (this->per_bfd () == nullptr)
return;
struct quick_file_names *file_data = file_names;
@@ -1887,13 +1989,13 @@ dwarf2_base_index_functions::print_stats (struct objfile *objfile,
for (int i = 0; i < total; ++i)
{
- dwarf2_per_cu *per_cu = per_objfile->per_bfd->get_cu (i);
+ dwarf2_per_cu *per_cu = per_objfile->per_bfd->get_unit (i);
if (!per_objfile->symtab_set_p (per_cu))
++count;
}
- gdb_printf (_(" Number of read CUs: %d\n"), total - count);
- gdb_printf (_(" Number of unread CUs: %d\n"), count);
+ gdb_printf (_(" Number of read units: %d\n"), total - count);
+ gdb_printf (_(" Number of unread units: %d\n"), count);
}
void
@@ -1912,17 +2014,20 @@ dwarf2_base_index_functions::expand_all_symtabs (struct objfile *objfile)
}
}
-/* See read.h. */
+/* If FILE_MATCHER is NULL and if CUS_TO_SKIP does not include the
+ CU's index, expand the CU and call LISTENER on it. */
-bool
-dw2_expand_symtabs_matching_one
+static bool
+dw2_search_one
(dwarf2_per_cu *per_cu,
dwarf2_per_objfile *per_objfile,
- expand_symtabs_file_matcher file_matcher,
- expand_symtabs_expansion_listener expansion_notify,
- expand_symtabs_lang_matcher lang_matcher)
+ auto_bool_vector &cus_to_skip,
+ search_symtabs_file_matcher file_matcher,
+ search_symtabs_expansion_listener listener,
+ search_symtabs_lang_matcher lang_matcher)
{
- if (file_matcher != nullptr && !per_cu->mark)
+ /* Already visited, or intentionally skipped. */
+ if (cus_to_skip.is_set (per_cu->index))
return true;
if (lang_matcher != nullptr)
@@ -1934,22 +2039,27 @@ dw2_expand_symtabs_matching_one
return true;
}
- bool symtab_was_null = !per_objfile->symtab_set_p (per_cu);
compunit_symtab *symtab
= dw2_instantiate_symtab (per_cu, per_objfile, false);
gdb_assert (symtab != nullptr);
- if (expansion_notify != NULL && symtab_was_null)
- return expansion_notify (symtab);
+ if (listener != nullptr)
+ {
+ cus_to_skip.set (per_cu->index, true);
+ return listener (symtab);
+ }
return true;
}
-/* See read.h. */
+/* If FILE_MATCHER is non-NULL, update CUS_TO_SKIP as appropriate
+ based on FILE_MATCHER. */
-void
-dw_expand_symtabs_matching_file_matcher
- (dwarf2_per_objfile *per_objfile, expand_symtabs_file_matcher file_matcher)
+static void
+dw_search_file_matcher
+ (dwarf2_per_objfile *per_objfile,
+ auto_bool_vector &cus_to_skip,
+ search_symtabs_file_matcher file_matcher)
{
if (file_matcher == NULL)
return;
@@ -1964,55 +2074,51 @@ dw_expand_symtabs_matching_file_matcher
{
QUIT;
- if (per_cu->is_debug_types)
- continue;
- per_cu->mark = 0;
-
- /* We only need to look at symtabs not already expanded. */
- if (per_objfile->symtab_set_p (per_cu.get ()))
- continue;
+ if (per_cu->is_debug_types ())
+ {
+ cus_to_skip.set (per_cu->index, true);
+ continue;
+ }
if (per_cu->fnd != nullptr)
{
file_and_directory *fnd = per_cu->fnd.get ();
if (file_matcher (fnd->get_name (), false))
- {
- per_cu->mark = 1;
- continue;
- }
+ 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->mark = 1;
- continue;
- }
+ continue;
}
quick_file_names *file_data = dw2_get_file_names (per_cu.get (),
per_objfile);
if (file_data == NULL)
- continue;
+ {
+ cus_to_skip.set (per_cu->index, true);
+ continue;
+ }
if (visited_not_found.contains (file_data))
- continue;
- else if (visited_found.contains (file_data))
{
- per_cu->mark = 1;
+ cus_to_skip.set (per_cu->index, true);
continue;
}
+ else if (visited_found.contains (file_data))
+ continue;
+ bool matched = false;
for (int j = 0; j < file_data->num_file_names; ++j)
{
const char *this_real_name;
if (file_matcher (file_data->file_names[j], false))
{
- per_cu->mark = 1;
+ matched = true;
break;
}
@@ -2026,15 +2132,18 @@ dw_expand_symtabs_matching_file_matcher
this_real_name = dw2_get_real_path (per_objfile, file_data, j);
if (file_matcher (this_real_name, false))
{
- per_cu->mark = 1;
+ matched = true;
break;
}
}
- if (per_cu->mark)
+ if (matched)
visited_found.insert (file_data);
else
- visited_not_found.insert (file_data);
+ {
+ cus_to_skip.set (per_cu->index, true);
+ visited_not_found.insert (file_data);
+ }
}
}
@@ -2048,8 +2157,7 @@ recursively_find_pc_sect_compunit_symtab (struct compunit_symtab *cust,
{
int i;
- if (cust->blockvector () != nullptr
- && blockvector_contains_pc (cust->blockvector (), pc))
+ if (cust->blockvector () != nullptr && cust->blockvector ()->contains (pc))
return cust;
if (cust->includes == NULL)
@@ -2122,7 +2230,7 @@ dwarf2_base_index_functions::map_symbol_filenames (objfile *objfile,
for (const auto &per_cu : per_objfile->per_bfd->all_units)
{
- if (!per_cu->is_debug_types
+ if (!per_cu->is_debug_types ()
&& per_objfile->symtab_set_p (per_cu.get ()))
{
if (per_cu->file_names != nullptr)
@@ -2133,7 +2241,7 @@ dwarf2_base_index_functions::map_symbol_filenames (objfile *objfile,
for (dwarf2_per_cu *per_cu : all_units_range (per_objfile->per_bfd))
{
/* We only need to look at symtabs not already expanded. */
- if (per_cu->is_debug_types || per_objfile->symtab_set_p (per_cu))
+ if (per_cu->is_debug_types () || per_objfile->symtab_set_p (per_cu))
continue;
if (per_cu->fnd != nullptr)
@@ -2288,7 +2396,7 @@ dwarf2_initialize_objfile (struct objfile *objfile,
/* Was a GDB index already read when we processed an objfile sharing
PER_BFD? */
else if (per_bfd->index_table != nullptr)
- dwarf_read_debug_printf ("re-using symbols");
+ dwarf_read_debug_printf ("reusing symbols");
else if (dwarf2_read_debug_names (per_objfile))
dwarf_read_debug_printf ("found debug names");
else if (dwarf2_read_gdb_index (per_objfile,
@@ -2346,9 +2454,9 @@ static struct dwarf2_section_info *
get_abbrev_section_for_cu (dwarf2_per_cu *this_cu)
{
struct dwarf2_section_info *abbrev;
- dwarf2_per_bfd *per_bfd = this_cu->per_bfd;
+ dwarf2_per_bfd *per_bfd = this_cu->per_bfd ();
- if (this_cu->is_dwz)
+ if (this_cu->is_dwz ())
abbrev = &per_bfd->get_dwz_file (true)->abbrev;
else
abbrev = &per_bfd->abbrev;
@@ -2356,6 +2464,24 @@ get_abbrev_section_for_cu (dwarf2_per_cu *this_cu)
return abbrev;
}
+/* "less than" function used to both sort and bisect units in the
+ `dwarf2_per_bfd::all_units` vector. Return true if the LHS CU comes before
+ (is "less" than) the section and offset in RHS.
+
+ For simplicity, sort sections by their pointer. This is not ideal, because
+ it can cause the behavior to change across runs, making some bugs harder to
+ investigate. An improvement would be for sections to be sorted by their
+ properties. */
+
+static bool
+all_units_less_than (const dwarf2_per_cu &lhs, const section_and_offset &rhs)
+{
+ if (lhs.section () != rhs.section)
+ return lhs.section () < rhs.section;
+
+ return lhs.sect_off () < rhs.offset;
+}
+
/* Fetch the abbreviation table offset from a comp or type unit header. */
static sect_offset
@@ -2385,110 +2511,10 @@ read_abbrev_offset (dwarf2_per_objfile *per_objfile,
return (sect_offset) read_offset (abfd, info_ptr, offset_size);
}
-/* A helper for create_dwo_debug_types_hash_table. Read types from SECTION
- and fill them into DWO_FILE's type unit hash table. It will process only
- type units, therefore DW_UT_type. */
-
-void
-cutu_reader::create_dwo_debug_type_hash_table (dwarf2_per_bfd *per_bfd,
- dwo_file *dwo_file,
- dwarf2_section_info *section,
- rcuh_kind section_kind)
-{
- struct dwarf2_section_info *abbrev_section;
- bfd *abfd;
- const gdb_byte *info_ptr, *end_ptr;
-
- abbrev_section = &dwo_file->sections.abbrev;
-
- dwarf_read_debug_printf ("Reading %s for %s",
- section->get_name (),
- abbrev_section->get_file_name ());
-
- info_ptr = section->buffer;
-
- if (info_ptr == NULL)
- return;
-
- /* We can't set abfd until now because the section may be empty or
- not present, in which case the bfd is unknown. */
- abfd = section->get_bfd_owner ();
-
- /* We don't use cutu_reader here because we don't need to read
- any dies: the signature is in the header. */
-
- end_ptr = info_ptr + section->size;
- while (info_ptr < end_ptr)
- {
- const gdb_byte *ptr = info_ptr;
- struct comp_unit_head header;
- unsigned int length;
-
- sect_offset sect_off = (sect_offset) (ptr - section->buffer);
-
- /* Initialize it due to a false compiler warning. */
- header.signature = -1;
- header.type_cu_offset_in_tu = (cu_offset) -1;
-
- /* We need to read the type's signature in order to build the hash
- table, but we don't need anything else just yet. */
-
- ptr = read_and_check_comp_unit_head (&header, section, abbrev_section,
- ptr, section_kind);
-
- length = header.get_length_with_initial ();
-
- /* Skip dummy type units. */
- if (ptr >= info_ptr + length
- || peek_abbrev_code (abfd, ptr) == 0
- || (header.unit_type != DW_UT_type
- && header.unit_type != DW_UT_split_type))
- {
- info_ptr += length;
- continue;
- }
-
- dwo_unit *dwo_tu = OBSTACK_ZALLOC (&per_bfd->obstack, dwo_unit);
- dwo_tu->dwo_file = dwo_file;
- dwo_tu->signature = header.signature;
- dwo_tu->type_offset_in_tu = header.type_cu_offset_in_tu;
- dwo_tu->section = section;
- dwo_tu->sect_off = sect_off;
- dwo_tu->length = length;
-
- auto [it, inserted] = dwo_file->tus.emplace (dwo_tu);
- if (!inserted)
- complaint (_("debug type entry at offset %s is duplicate to"
- " the entry at offset %s, signature %s"),
- sect_offset_str (sect_off),
- sect_offset_str ((*it)->sect_off),
- hex_string (header.signature));
-
- dwarf_read_debug_printf_v (" offset %s, signature %s",
- sect_offset_str (sect_off),
- hex_string (header.signature));
-
- info_ptr += length;
- }
-}
-
-/* Create the hash table of all entries in the .debug_types
- (or .debug_types.dwo) section(s).
- DWO_FILE is a pointer to the DWO file object.
+/* Add an entry for signature SIG to per_bfd->signatured_types.
- Note: This function processes DWO files only, not DWP files. */
-
-void
-cutu_reader::create_dwo_debug_types_hash_table
- (dwarf2_per_bfd *per_bfd, dwo_file *dwo_file,
- gdb::array_view<dwarf2_section_info> type_sections)
-{
- for (dwarf2_section_info &section : type_sections)
- create_dwo_debug_type_hash_table (per_bfd, dwo_file, &section,
- rcuh_kind::TYPE);
-}
-
-/* Add an entry for signature SIG to per_bfd->signatured_types. */
+ This functions leaves PER_BFD::ALL_UNITS unsorted. The caller must call
+ finalize_all_units after adding one or more type units. */
static signatured_type_set::iterator
add_type_unit (dwarf2_per_bfd *per_bfd, dwarf2_section_info *section,
@@ -2586,12 +2612,15 @@ lookup_dwo_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
if (it == dwo_file->tus.end ())
return nullptr;
- dwo_unit *dwo_entry = *it;
+ dwo_unit *dwo_entry = it->get ();
/* If the global table doesn't have an entry for this TU, add one. */
if (sig_type_it == per_bfd->signatured_types.end ())
- sig_type_it = add_type_unit (per_bfd, dwo_entry->section,
- dwo_entry->sect_off, dwo_entry->length, sig);
+ {
+ sig_type_it = add_type_unit (per_bfd, dwo_entry->section,
+ dwo_entry->sect_off, dwo_entry->length, sig);
+ finalize_all_units (per_bfd);
+ }
if ((*sig_type_it)->dwo_unit == nullptr)
fill_in_sig_entry_from_dwo_entry (per_objfile, *sig_type_it, dwo_entry);
@@ -2633,6 +2662,7 @@ lookup_dwp_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
sig_type_it = add_type_unit (per_bfd, dwo_entry->section,
dwo_entry->sect_off, dwo_entry->length, sig);
+ finalize_all_units (per_bfd);
fill_in_sig_entry_from_dwo_entry (per_objfile, *sig_type_it, dwo_entry);
return *sig_type_it;
@@ -2677,7 +2707,7 @@ cutu_reader::init_cu_die_reader (dwarf2_cu *cu, dwarf2_section_info *section,
struct dwo_file *dwo_file,
const struct abbrev_table *abbrev_table)
{
- gdb_assert (section->readin && section->buffer != NULL);
+ gdb_assert (section->read_in && section->buffer != NULL);
m_abfd = section->get_bfd_owner ();
m_cu = cu;
m_dwo_file = dwo_file;
@@ -2744,7 +2774,7 @@ cutu_reader::read_cutu_die_from_dwo (dwarf2_cu *cu, dwo_unit *dwo_unit,
{
/* For TUs in DWO files, the DW_AT_stmt_list attribute lives in the
DWO file. */
- if (!per_cu->is_debug_types)
+ if (!per_cu->is_debug_types ())
push_back (dwarf2_attr (stub_comp_unit_die, DW_AT_stmt_list, cu));
push_back (dwarf2_attr (stub_comp_unit_die, DW_AT_low_pc, cu));
push_back (dwarf2_attr (stub_comp_unit_die, DW_AT_high_pc, cu));
@@ -2785,13 +2815,13 @@ cutu_reader::read_cutu_die_from_dwo (dwarf2_cu *cu, dwo_unit *dwo_unit,
const gdb_byte *begin_info_ptr = m_info_ptr;
dwo_abbrev_section = &dwo_unit->dwo_file->sections.abbrev;
- if (per_cu->is_debug_types)
+ if (per_cu->is_debug_types ())
{
signatured_type *sig_type = (struct signatured_type *) per_cu;
- m_info_ptr = read_and_check_comp_unit_head (&cu->header, section,
- dwo_abbrev_section,
- m_info_ptr, rcuh_kind::TYPE);
+ m_info_ptr = read_and_check_unit_head (&cu->header, section,
+ dwo_abbrev_section, m_info_ptr,
+ ruh_kind::TYPE);
/* This is not an assert because it can be caused by bad debug info. */
if (sig_type->signature != cu->header.signature)
@@ -2808,7 +2838,7 @@ cutu_reader::read_cutu_die_from_dwo (dwarf2_cu *cu, dwo_unit *dwo_unit,
/* For DWOs coming from DWP files, we don't know the CU length
nor the type's offset in the TU until now. */
dwo_unit->length = cu->header.get_length_with_initial ();
- dwo_unit->type_offset_in_tu = cu->header.type_cu_offset_in_tu;
+ dwo_unit->type_offset_in_tu = cu->header.type_offset_in_tu;
/* Establish the type offset that can be used to lookup the type.
For DWO files, we don't know it until now. */
@@ -2817,16 +2847,23 @@ cutu_reader::read_cutu_die_from_dwo (dwarf2_cu *cu, dwo_unit *dwo_unit,
}
else
{
- m_info_ptr
- = read_and_check_comp_unit_head (&cu->header, section,
- dwo_abbrev_section, m_info_ptr,
- rcuh_kind::COMPILE);
+ m_info_ptr = read_and_check_unit_head (&cu->header, section,
+ dwo_abbrev_section, m_info_ptr,
+ ruh_kind::COMPILE);
gdb_assert (dwo_unit->sect_off == cu->header.sect_off);
/* For DWOs coming from DWP files, we don't know the CU length
until now. */
dwo_unit->length = cu->header.get_length_with_initial ();
}
+ /* Record some information found in the header. This will be needed when
+ evaluating DWARF expressions in the context of this unit, for instance. */
+ per_cu->set_addr_size (cu->header.addr_size);
+ per_cu->set_offset_size (cu->header.offset_size);
+ per_cu->set_ref_addr_size (cu->header.version == 2
+ ? cu->header.addr_size
+ : cu->header.offset_size);
+
dwo_abbrev_section->read (objfile);
m_dwo_abbrev_table
= abbrev_table::read (dwo_abbrev_section, cu->header.abbrev_sect_off);
@@ -2877,13 +2914,6 @@ dwo_unit *
cutu_reader::lookup_dwo_unit (dwarf2_cu *cu, die_info *comp_unit_die,
const char *dwo_name)
{
-#if CXX_STD_THREAD
- /* We need a lock here to handle the DWO hash table. */
- static std::mutex dwo_lock;
-
- std::lock_guard<std::mutex> guard (dwo_lock);
-#endif
-
dwarf2_per_cu *per_cu = cu->per_cu;
struct dwo_unit *dwo_unit;
const char *comp_dir;
@@ -2892,7 +2922,7 @@ cutu_reader::lookup_dwo_unit (dwarf2_cu *cu, die_info *comp_unit_die,
comp_dir = dwarf2_string_attr (comp_unit_die, DW_AT_comp_dir, cu);
- if (per_cu->is_debug_types)
+ if (per_cu->is_debug_types ())
dwo_unit = lookup_dwo_type_unit (cu, dwo_name, comp_dir);
else
{
@@ -2902,7 +2932,7 @@ cutu_reader::lookup_dwo_unit (dwarf2_cu *cu, die_info *comp_unit_die,
error (_(DWARF_ERROR_PREFIX
"missing dwo_id for dwo_name %s"
" [in module %s]"),
- dwo_name, per_cu->per_bfd->filename ());
+ dwo_name, per_cu->per_bfd ()->filename ());
dwo_unit = lookup_dwo_comp_unit (cu, dwo_name, comp_dir, *signature);
}
@@ -2924,7 +2954,7 @@ cutu_reader::init_tu_and_read_dwo_dies (dwarf2_per_cu *this_cu,
/* Verify we can do the following downcast, and that we have the
data we need. */
- gdb_assert (this_cu->is_debug_types && this_cu->reading_dwo_directly);
+ gdb_assert (this_cu->is_debug_types () && this_cu->reading_dwo_directly);
sig_type = (struct signatured_type *) this_cu;
gdb_assert (sig_type->dwo_unit != NULL);
@@ -2974,7 +3004,7 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu,
const abbrev_table_cache *abbrev_cache)
{
struct objfile *objfile = per_objfile.objfile;
- struct dwarf2_section_info *section = this_cu.section;
+ struct dwarf2_section_info *section = this_cu.section ();
bfd *abfd = section->get_bfd_owner ();
const gdb_byte *begin_info_ptr;
struct signatured_type *sig_type = NULL;
@@ -2986,15 +3016,15 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu,
if (dwarf_die_debug)
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));
+ 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. */
if (this_cu.reading_dwo_directly)
{
/* Narrow down the scope of possibilities to have to understand. */
- gdb_assert (this_cu.is_debug_types);
+ gdb_assert (this_cu.is_debug_types ());
gdb_assert (abbrev_table == NULL);
init_tu_and_read_dwo_dies (&this_cu, &per_objfile, existing_cu,
pretend_language);
@@ -3005,7 +3035,7 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu,
section->read (objfile);
begin_info_ptr = m_info_ptr
- = section->buffer + to_underlying (this_cu.sect_off);
+ = section->buffer + to_underlying (this_cu.sect_off ());
abbrev_section = get_abbrev_section_for_cu (&this_cu);
@@ -3038,27 +3068,27 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu,
}
/* Get the header. */
- if (to_underlying (cu->header.first_die_cu_offset) != 0 && !rereading_dwo_cu)
+ if (to_underlying (cu->header.first_die_offset_in_unit) != 0
+ && !rereading_dwo_cu)
{
/* We already have the header, there's no need to read it in again. */
- m_info_ptr += to_underlying (cu->header.first_die_cu_offset);
+ m_info_ptr += to_underlying (cu->header.first_die_offset_in_unit);
}
else
{
- if (this_cu.is_debug_types)
+ if (this_cu.is_debug_types ())
{
- m_info_ptr
- = read_and_check_comp_unit_head (&cu->header, section,
- abbrev_section, m_info_ptr,
- rcuh_kind::TYPE);
+ m_info_ptr = read_and_check_unit_head (&cu->header, section,
+ abbrev_section, m_info_ptr,
+ ruh_kind::TYPE);
/* Since per_cu is the first member of struct signatured_type,
we can go from a pointer to one to a pointer to the other. */
sig_type = (struct signatured_type *) &this_cu;
gdb_assert (sig_type->signature == cu->header.signature);
gdb_assert (sig_type->type_offset_in_tu
- == cu->header.type_cu_offset_in_tu);
- gdb_assert (this_cu.sect_off == cu->header.sect_off);
+ == cu->header.type_offset_in_tu);
+ gdb_assert (this_cu.sect_off () == cu->header.sect_off);
/* LENGTH has not been set yet for type units if we're
using .gdb_index. */
@@ -3066,18 +3096,26 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu,
/* Establish the type offset that can be used to lookup the type. */
sig_type->type_offset_in_section =
- this_cu.sect_off + to_underlying (sig_type->type_offset_in_tu);
+ this_cu.sect_off () + to_underlying (sig_type->type_offset_in_tu);
}
else
{
- m_info_ptr
- = read_and_check_comp_unit_head (&cu->header, section,
- abbrev_section, m_info_ptr,
- rcuh_kind::COMPILE);
+ m_info_ptr = read_and_check_unit_head (&cu->header, section,
+ abbrev_section, m_info_ptr,
+ ruh_kind::COMPILE);
- gdb_assert (this_cu.sect_off == cu->header.sect_off);
+ gdb_assert (this_cu.sect_off () == cu->header.sect_off);
this_cu.set_length (cu->header.get_length_with_initial ());
}
+
+ /* Record some information found in the header. This will be needed
+ when evaluating DWARF expressions in the context of this unit, for
+ instance. */
+ this_cu.set_addr_size (cu->header.addr_size);
+ this_cu.set_offset_size (cu->header.offset_size);
+ this_cu.set_ref_addr_size (cu->header.version == 2
+ ? cu->header.addr_size
+ : cu->header.offset_size);
}
/* Skip dummy compilation units. */
@@ -3133,7 +3171,7 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu,
{
complaint (_("compilation unit with DW_AT_GNU_dwo_name"
" has children (offset %s) [in module %s]"),
- sect_offset_str (this_cu.sect_off),
+ sect_offset_str (this_cu.sect_off ()),
bfd_get_filename (abfd));
}
@@ -3186,13 +3224,13 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu,
dwo_file &dwo_file)
{
struct objfile *objfile = per_objfile.objfile;
- struct dwarf2_section_info *section = this_cu.section;
+ struct dwarf2_section_info *section = this_cu.section ();
bfd *abfd = section->get_bfd_owner ();
if (dwarf_die_debug)
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));
+ this_cu.is_debug_types () ? "type" : "comp",
+ sect_offset_str (this_cu.sect_off ()));
gdb_assert (per_objfile.get_cu (&this_cu) == nullptr);
@@ -3203,13 +3241,13 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu,
m_new_cu = std::make_unique<dwarf2_cu> (&this_cu, &per_objfile);
- m_info_ptr = section->buffer + to_underlying (this_cu.sect_off);
+ m_info_ptr = section->buffer + to_underlying (this_cu.sect_off ());
const gdb_byte *begin_info_ptr = m_info_ptr;
- m_info_ptr = read_and_check_comp_unit_head (&m_new_cu->header, section,
- abbrev_section, m_info_ptr,
- (this_cu.is_debug_types
- ? rcuh_kind::TYPE
- : rcuh_kind::COMPILE));
+ m_info_ptr = read_and_check_unit_head (&m_new_cu->header, section,
+ abbrev_section, m_info_ptr,
+ (this_cu.is_debug_types ()
+ ? ruh_kind::TYPE
+ : ruh_kind::COMPILE));
m_new_cu->str_offsets_base = parent_cu.str_offsets_base;
m_new_cu->addr_base = parent_cu.addr_base;
@@ -3283,33 +3321,178 @@ get_type_unit_group_key (struct dwarf2_cu *cu, const struct attribute *stmt_list
return {cu->dwo_unit, static_cast<sect_offset> (line_offset)};
}
-/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
- Process compilation unit THIS_CU for a psymtab. */
+/* A subclass of cooked_index_worker that handles scanning
+ .debug_info. */
-static void
-process_psymtab_comp_unit (dwarf2_per_cu *this_cu,
- dwarf2_per_objfile *per_objfile,
- cooked_index_worker_result *storage)
+class cooked_index_worker_debug_info : public cooked_index_worker
+{
+public:
+ cooked_index_worker_debug_info (dwarf2_per_objfile *per_objfile)
+ : cooked_index_worker (per_objfile)
+ {
+ gdb_assert (is_main_thread ());
+
+ struct objfile *objfile = per_objfile->objfile;
+ dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
+
+ dwarf_read_debug_printf ("Building psymtabs of objfile %s ...",
+ objfile_name (objfile));
+
+ per_bfd->map_info_sections (objfile);
+ }
+
+private:
+ /* The task for parallel workers that index units. */
+ struct parallel_indexing_worker
+ {
+ parallel_indexing_worker (const char *step_name,
+ cooked_index_worker_debug_info *parent)
+ : m_scoped_time_it (step_name, parent->m_per_command_time),
+ m_parent (parent)
+ {
+ }
+
+ DISABLE_COPY_AND_ASSIGN (parallel_indexing_worker);
+
+ ~parallel_indexing_worker ()
+ {
+ bfd_thread_cleanup ();
+
+ m_thread_storage.done_reading (m_complaint_handler.release ());
+
+ /* Append the results of this worker to the parent instance. */
+ gdb::lock_guard<gdb::mutex> lock (m_parent->m_results_mutex);
+ m_parent->m_results.emplace_back (std::move (m_thread_storage));
+ }
+
+ void operator() (iterator_range<dwarf2_per_cu_up *> range)
+ {
+ for (auto &it : range)
+ this->process_one (*it);
+ }
+
+ private:
+ void process_one (dwarf2_per_cu &unit)
+ {
+ m_thread_storage.catch_error ([&] ()
+ {
+ m_parent->process_unit (&unit, m_parent->m_per_objfile,
+ &m_thread_storage);
+ });
+ }
+
+ /* Measures the execution time of this worker. */
+ scoped_time_it m_scoped_time_it;
+
+ /* Delayed complaints and errors recorded while indexing units. */
+ complaint_interceptor m_complaint_handler;
+ std::vector<gdb_exception> m_errors;
+
+ /* Index storage for this worker. */
+ cooked_index_worker_result m_thread_storage;
+
+ /* The instance that spawned this worker. */
+ cooked_index_worker_debug_info *m_parent;
+ };
+
+ void do_reading () override;
+
+ /* Print collected type unit statistics. */
+
+ void print_tu_stats (dwarf2_per_objfile *per_objfile)
+ {
+ dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
+ tu_stats *tu_stats = &per_bfd->tu_stats;
+
+ dwarf_read_debug_printf ("Type unit statistics:");
+ dwarf_read_debug_printf (" %d TUs", per_bfd->num_type_units);
+ dwarf_read_debug_printf (" %d uniq abbrev tables",
+ tu_stats->nr_uniq_abbrev_tables);
+ dwarf_read_debug_printf (" %d symtabs from stmt_list entries",
+ tu_stats->nr_symtabs);
+ dwarf_read_debug_printf (" %d symtab sharers",
+ tu_stats->nr_symtab_sharers);
+ dwarf_read_debug_printf (" %d type units without a stmt_list",
+ tu_stats->nr_stmt_less_type_units);
+ dwarf_read_debug_printf (" %d all_type_units reallocs",
+ tu_stats->nr_all_type_units_reallocs);
+ }
+
+ void print_stats () override
+ {
+ if (dwarf_read_debug > 0)
+ print_tu_stats (m_per_objfile);
+
+ if (dwarf_read_debug > 1)
+ {
+ dwarf_read_debug_printf_v ("Final m_all_parents_map:");
+ m_all_parents_map.dump (m_per_objfile->per_bfd);
+ }
+ }
+
+ /* After the last DWARF-reading task has finished, this function
+ does the remaining work to finish the scan. */
+ void done_reading () override;
+
+ /* An iterator for the comp units. */
+ using unit_iterator = std::vector<dwarf2_per_cu_up>::iterator;
+
+ /* Process unit THIS_CU. */
+ void process_unit (dwarf2_per_cu *this_cu, dwarf2_per_objfile *per_objfile,
+ cooked_index_worker_result *storage);
+
+ /* Process all type units existing in PER_OBJFILE::PER_BFD::ALL_UNITS. */
+ void process_type_units (dwarf2_per_objfile *per_objfile,
+ cooked_index_worker_result *storage);
+
+ /* Process the type unit wrapped in READER. */
+ void process_type_unit (cutu_reader *reader,
+ cooked_index_worker_result *storage);
+
+ /* Process all type units of all DWO files.
+
+ This is needed in case a TU was emitted without its skeleton.
+ Note: This can't be done until we know what all the DWO files are. */
+ void process_skeletonless_type_units (dwarf2_per_objfile *per_objfile,
+ cooked_index_worker_result *storage);
+
+ /* Process the type unit represented by DWO_UNIT. */
+ void process_skeletonless_type_unit (dwo_unit *dwo_unit,
+ dwarf2_per_objfile *per_objfile,
+ cooked_index_worker_result *storage);
+
+ /* A storage object for "leftovers" -- see the 'start' method, but
+ essentially things not parsed during the normal CU parsing
+ passes. */
+ cooked_index_worker_result m_index_storage;
+};
+
+void
+cooked_index_worker_debug_info::process_unit
+ (dwarf2_per_cu *this_cu, dwarf2_per_objfile *per_objfile,
+ cooked_index_worker_result *storage)
{
cutu_reader *reader = storage->get_reader (this_cu);
if (reader == nullptr)
{
- cutu_reader new_reader (*this_cu, *per_objfile, nullptr, nullptr, false,
- language_minimal,
- &storage->get_abbrev_table_cache ());
+ const abbrev_table_cache &abbrev_table_cache
+ = storage->get_abbrev_table_cache ();
+ auto new_reader = std::make_unique<cutu_reader> (*this_cu, *per_objfile,
+ nullptr, nullptr, false,
+ language_minimal,
+ &abbrev_table_cache);
- if (new_reader.cu () == nullptr || new_reader.is_dummy ())
+ if (new_reader->is_dummy ())
return;
- auto copy = std::make_unique<cutu_reader> (std::move (new_reader));
- reader = storage->preserve (std::move (copy));
+ reader = storage->preserve (std::move (new_reader));
}
- if (reader->top_level_die () == nullptr || reader->is_dummy ())
+ if (reader->is_dummy ())
return;
- if (this_cu->is_debug_types)
- build_type_psymtabs_reader (reader, storage);
+ if (this_cu->is_debug_types ())
+ process_type_unit (reader, storage);
else if (reader->top_level_die ()->tag != DW_TAG_partial_unit)
{
bool nope = false;
@@ -3322,17 +3505,15 @@ process_psymtab_comp_unit (dwarf2_per_cu *this_cu,
}
}
-/* Reader function for build_type_psymtabs. */
-
-static void
-build_type_psymtabs_reader (cutu_reader *reader,
- cooked_index_worker_result *storage)
+void
+cooked_index_worker_debug_info::process_type_unit
+ (cutu_reader *reader, cooked_index_worker_result *storage)
{
struct dwarf2_cu *cu = reader->cu ();
dwarf2_per_cu *per_cu = cu->per_cu;
die_info *type_unit_die = reader->top_level_die ();
- gdb_assert (per_cu->is_debug_types);
+ gdb_assert (per_cu->is_debug_types ());
if (! type_unit_die->has_children)
return;
@@ -3360,32 +3541,14 @@ struct tu_abbrev_offset
sect_offset abbrev_offset;
};
-/* Efficiently read all the type units.
-
- The efficiency is because we sort TUs by the abbrev table they use and
- only read each abbrev table once. In one program there are 200K TUs
- sharing 8K abbrev tables.
-
- The main purpose of this function is to support building the
- dwarf2_per_objfile->per_bfd->type_unit_groups table.
- TUs typically share the DW_AT_stmt_list of the CU they came from, so we
- can collapse the search space by grouping them by stmt_list.
- The savings can be significant, in the same program from above the 200K TUs
- share 8K stmt_list tables.
-
- FUNC is expected to call get_type_unit_group, which will create the
- struct type_unit_group if necessary and add it to
- dwarf2_per_objfile->per_bfd->type_unit_groups. */
-
-static void
-build_type_psymtabs (dwarf2_per_objfile *per_objfile,
- cooked_index_worker_result *storage)
+void
+cooked_index_worker_debug_info::process_type_units
+ (dwarf2_per_objfile *per_objfile, cooked_index_worker_result *storage)
{
struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
abbrev_table_up abbrev_table;
- sect_offset abbrev_offset;
- if (per_objfile->per_bfd->all_type_units.size () == 0)
+ if (per_objfile->per_bfd->num_type_units == 0)
return;
/* TUs typically share abbrev tables, and there can be way more TUs than
@@ -3412,21 +3575,21 @@ build_type_psymtabs (dwarf2_per_objfile *per_objfile,
/* Sort in a separate table to maintain the order of all_units
for .gdb_index: TU indices directly index all_type_units. */
std::vector<tu_abbrev_offset> sorted_by_abbrev;
- sorted_by_abbrev.reserve (per_objfile->per_bfd->all_type_units.size ());
+ sorted_by_abbrev.reserve (per_objfile->per_bfd->num_type_units);
for (const auto &cu : per_objfile->per_bfd->all_units)
- if (cu->is_debug_types)
+ if (cu->is_debug_types ())
{
auto sig_type = static_cast<signatured_type *> (cu.get ());
- sorted_by_abbrev.emplace_back (sig_type,
- read_abbrev_offset (per_objfile,
- sig_type->section,
- sig_type->sect_off));
+ sect_offset abbrev_offset
+ = read_abbrev_offset (per_objfile, sig_type->section (),
+ sig_type->sect_off ());
+ sorted_by_abbrev.emplace_back (sig_type, abbrev_offset);
}
std::sort (sorted_by_abbrev.begin (), sorted_by_abbrev.end ());
- abbrev_offset = (sect_offset) ~(unsigned) 0;
+ sect_offset abbrev_offset = (sect_offset) ~(unsigned) 0;
for (const tu_abbrev_offset &tu : sorted_by_abbrev)
{
@@ -3445,38 +3608,17 @@ build_type_psymtabs (dwarf2_per_objfile *per_objfile,
abbrev_table.get (), nullptr, false,
language_minimal);
if (!reader.is_dummy ())
- build_type_psymtabs_reader (&reader, storage);
+ storage->catch_error ([&] ()
+ {
+ process_type_unit (&reader, storage);
+ });
}
}
-/* Print collected type unit statistics. */
-
-static void
-print_tu_stats (dwarf2_per_objfile *per_objfile)
-{
- struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
-
- dwarf_read_debug_printf ("Type unit statistics:");
- dwarf_read_debug_printf (" %d TUs", tu_stats->nr_tus);
- dwarf_read_debug_printf (" %d uniq abbrev tables",
- tu_stats->nr_uniq_abbrev_tables);
- dwarf_read_debug_printf (" %d symtabs from stmt_list entries",
- tu_stats->nr_symtabs);
- dwarf_read_debug_printf (" %d symtab sharers",
- tu_stats->nr_symtab_sharers);
- dwarf_read_debug_printf (" %d type units without a stmt_list",
- tu_stats->nr_stmt_less_type_units);
- dwarf_read_debug_printf (" %d all_type_units reallocs",
- tu_stats->nr_all_type_units_reallocs);
-}
-
-/* Traversal function for process_skeletonless_type_units.
- Read a TU in a DWO file and build partial symbols for it. */
-
-static void
-process_skeletonless_type_unit (dwo_unit *dwo_unit,
- dwarf2_per_objfile *per_objfile,
- cooked_index_worker_result *storage)
+void
+cooked_index_worker_debug_info::process_skeletonless_type_unit
+ (dwo_unit *dwo_unit, dwarf2_per_objfile *per_objfile,
+ cooked_index_worker_result *storage)
{
dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
@@ -3492,112 +3634,36 @@ process_skeletonless_type_unit (dwo_unit *dwo_unit,
this TU. */
sig_type_it = add_type_unit (per_bfd, dwo_unit->section, dwo_unit->sect_off,
dwo_unit->length, dwo_unit->signature);
+ /* finalize_all_units is called just once by process_skeletonless_type_units
+ after going through all skeletonless type units. */
fill_in_sig_entry_from_dwo_entry (per_objfile, *sig_type_it, dwo_unit);
/* This does the job that build_type_psymtabs would have done. */
cutu_reader reader (**sig_type_it, *per_objfile, nullptr, nullptr, false,
language_minimal);
if (!reader.is_dummy ())
- build_type_psymtabs_reader (&reader, storage);
-}
-
-/* Scan all TUs of DWO files, verifying we've processed them.
- This is needed in case a TU was emitted without its skeleton.
- 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,
- cooked_index_worker_result *storage)
-{
- /* Skeletonless TUs in DWP files without .gdb_index is not supported yet. */
- if (per_objfile->per_bfd->dwp_file == nullptr)
- for (const dwo_file_up &file : per_objfile->per_bfd->dwo_files)
- for (dwo_unit *unit : file->tus)
- process_skeletonless_type_unit (unit, per_objfile, storage);
+ process_type_unit (&reader, storage);
}
-/* A subclass of cooked_index_worker that handles scanning
- .debug_info. */
-
-class cooked_index_worker_debug_info : public cooked_index_worker
-{
-public:
- cooked_index_worker_debug_info (dwarf2_per_objfile *per_objfile)
- : cooked_index_worker (per_objfile)
- {
- gdb_assert (is_main_thread ());
-
- struct objfile *objfile = per_objfile->objfile;
- dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
-
- dwarf_read_debug_printf ("Building psymtabs of objfile %s ...",
- objfile_name (objfile));
-
- per_bfd->map_info_sections (objfile);
- }
-
-private:
-
- void do_reading () override;
-
- void print_stats () override
- {
- if (dwarf_read_debug > 0)
- print_tu_stats (m_per_objfile);
- if (dwarf_read_debug > 1)
- {
- dwarf_read_debug_printf_v ("Final m_all_parents_map:");
- m_all_parents_map.dump (m_per_objfile->per_bfd);
- }
- }
-
- /* After the last DWARF-reading task has finished, this function
- does the remaining work to finish the scan. */
- void done_reading () override;
-
- /* An iterator for the comp units. */
- using unit_iterator = std::vector<dwarf2_per_cu_up>::iterator;
-
- /* Process a batch of CUs. This may be called multiple times in
- separate threads. TASK_NUMBER indicates which task this is --
- the result is stored in that slot of M_RESULTS. */
- void process_cus (size_t task_number, unit_iterator first,
- unit_iterator end);
-
- /* A storage object for "leftovers" -- see the 'start' method, but
- essentially things not parsed during the normal CU parsing
- passes. */
- cooked_index_worker_result m_index_storage;
-};
-
void
-cooked_index_worker_debug_info::process_cus (size_t task_number,
- unit_iterator first,
- unit_iterator end)
+cooked_index_worker_debug_info::process_skeletonless_type_units
+ (dwarf2_per_objfile *per_objfile, cooked_index_worker_result *storage)
{
- SCOPE_EXIT { bfd_thread_cleanup (); };
-
- /* Ensure that complaints are handled correctly. */
- complaint_interceptor complaint_handler;
+ scoped_time_it time_it ("DWARF skeletonless type units", m_per_command_time);
+ dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
- std::vector<gdb_exception> errors;
- cooked_index_worker_result thread_storage;
- for (auto inner = first; inner != end; ++inner)
+ /* Skeletonless TUs in DWP files without .gdb_index is not supported yet. */
+ if (per_bfd->dwp_file == nullptr)
{
- dwarf2_per_cu *per_cu = inner->get ();
+ for (const dwo_file_up &file : per_bfd->dwo_files)
+ for (const dwo_unit_up &unit : file->tus)
+ storage->catch_error ([&] ()
+ {
+ process_skeletonless_type_unit (unit.get (), per_objfile, storage);
+ });
- try
- {
- process_psymtab_comp_unit (per_cu, m_per_objfile, &thread_storage);
- }
- catch (gdb_exception &except)
- {
- thread_storage.note_error (std::move (except));
- }
+ finalize_all_units (per_bfd);
}
-
- thread_storage.done_reading (complaint_handler.release ());
- m_results[task_number] = std::move (thread_storage);
}
void
@@ -3618,68 +3684,23 @@ cooked_index_worker_debug_info::do_reading ()
dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd;
create_all_units (m_per_objfile);
- build_type_psymtabs (m_per_objfile, &m_index_storage);
+ process_type_units (m_per_objfile, &m_index_storage);
if (!per_bfd->debug_aranges.empty ())
read_addrmap_from_aranges (m_per_objfile, &per_bfd->debug_aranges,
m_index_storage.get_addrmap (),
&m_warnings);
- /* We want to balance the load between the worker threads. This is
- done by using the size of each CU as a rough estimate of how
- difficult it will be to operate on. This isn't ideal -- for
- example if dwz is used, the early CUs will all tend to be
- "included" and won't be parsed independently. However, this
- heuristic works well for typical compiler output. */
-
- size_t total_size = 0;
- for (const auto &per_cu : per_bfd->all_units)
- total_size += per_cu->length ();
-
- /* How many worker threads we plan to use. We may not actually use
- this many. We use 1 as the minimum to avoid division by zero,
- and anyway in the N==0 case the work will be done
- synchronously. */
- const size_t n_worker_threads
- = std::max (gdb::thread_pool::g_thread_pool->thread_count (), (size_t) 1);
-
- /* How much effort should be put into each worker. */
- const size_t size_per_thread
- = std::max (total_size / n_worker_threads, (size_t) 1);
-
- /* Work is done in a task group. */
- gdb::task_group workers ([this] ()
- {
- this->done_reading ();
- });
-
- auto end = per_bfd->all_units.end ();
- size_t task_count = 0;
- for (auto iter = per_bfd->all_units.begin (); iter != end; )
- {
- auto last = iter;
- /* Put all remaining CUs into the last task. */
- if (task_count == n_worker_threads - 1)
- last = end;
- else
- {
- size_t chunk_size = 0;
- for (; last != end && chunk_size < size_per_thread; ++last)
- chunk_size += (*last)->length ();
- }
-
- gdb_assert (iter != last);
- workers.add_task ([this, task_count, iter, last] ()
- {
- process_cus (task_count, iter, last);
- });
-
- ++task_count;
- iter = last;
- }
+ /* Launch parallel tasks to index units.
- m_results.resize (task_count);
- workers.start ();
+ The (unfortunate) reason why we don't use
+ std::vector<dwarf2_per_cu_up>::iterator as the parallel-for-each iterator
+ type is that std::atomic won't work with that type when building with
+ -D_GLIBCXX_DEBUG. */
+ gdb::parallel_for_each_async<1, dwarf2_per_cu_up *, parallel_indexing_worker>
+ (per_bfd->all_units.data (),
+ per_bfd->all_units.data () + per_bfd->all_units.size (),
+ [this] () { this->done_reading (); }, "DWARF indexing worker", this);
}
static void
@@ -3688,7 +3709,7 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
struct dwarf2_section_info *abbrev_section,
unsigned int is_dwz,
signatured_type_set &sig_types,
- rcuh_kind section_kind)
+ ruh_kind section_kind)
{
const gdb_byte *info_ptr;
struct objfile *objfile = per_objfile->objfile;
@@ -3708,9 +3729,9 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
sect_offset sect_off = (sect_offset) (info_ptr - section->buffer);
- comp_unit_head cu_header;
- read_and_check_comp_unit_head (&cu_header, section, abbrev_section,
- info_ptr, section_kind);
+ unit_head cu_header;
+ read_and_check_unit_head (&cu_header, section, abbrev_section, info_ptr,
+ section_kind);
unsigned int length = cu_header.get_length_with_initial ();
@@ -3723,7 +3744,7 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
= per_bfd->allocate_signatured_type (section, sect_off, length,
is_dwz, cu_header.signature);
signatured_type *sig_ptr = sig_type.get ();
- sig_type->type_offset_in_tu = cu_header.type_cu_offset_in_tu;
+ sig_type->type_offset_in_tu = cu_header.type_offset_in_tu;
this_cu.reset (sig_type.release ());
auto inserted = sig_types.emplace (sig_ptr).second;
@@ -3732,7 +3753,7 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
complaint (_("debug type entry at offset %s is duplicate to"
" the entry at offset %s, signature %s"),
sect_offset_str (sect_off),
- sect_offset_str (sig_ptr->sect_off),
+ sect_offset_str (sig_ptr->sect_off ()),
hex_string (sig_ptr->signature));
}
@@ -3741,16 +3762,23 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
}
}
-/* Initialize the views on all_units. */
+/* See read.h. */
void
finalize_all_units (dwarf2_per_bfd *per_bfd)
{
- size_t nr_tus = per_bfd->tu_stats.nr_tus;
- size_t nr_cus = per_bfd->all_units.size () - nr_tus;
- gdb::array_view<dwarf2_per_cu_up> tmp = per_bfd->all_units;
- per_bfd->all_comp_units = tmp.slice (0, nr_cus);
- per_bfd->all_type_units = tmp.slice (nr_cus, nr_tus);
+ /* Sanity check. */
+ gdb_assert (per_bfd->all_units.size ()
+ == per_bfd->num_comp_units + per_bfd->num_type_units);
+
+ /* Ensure that the all_units vector is in the expected order for
+ dwarf2_find_containing_unit to be able to perform a binary search. */
+ std::sort (per_bfd->all_units.begin (), per_bfd->all_units.end (),
+ [] (const dwarf2_per_cu_up &a, const dwarf2_per_cu_up &b)
+ {
+ return all_units_less_than (*a, { b->section (),
+ b->sect_off () });
+ });
}
/* See read.h. */
@@ -3759,28 +3787,27 @@ void
create_all_units (dwarf2_per_objfile *per_objfile)
{
gdb_assert (per_objfile->per_bfd->all_units.empty ());
+ scoped_remove_all_units remove_all_units (*per_objfile->per_bfd);
signatured_type_set sig_types;
for (dwarf2_section_info &section : per_objfile->per_bfd->infos)
read_comp_units_from_section (per_objfile, &section,
&per_objfile->per_bfd->abbrev, 0, sig_types,
- rcuh_kind::COMPILE);
+ ruh_kind::COMPILE);
for (dwarf2_section_info &section : per_objfile->per_bfd->types)
read_comp_units_from_section (per_objfile, &section,
&per_objfile->per_bfd->abbrev, 0, sig_types,
- rcuh_kind::TYPE);
+ ruh_kind::TYPE);
dwz_file *dwz = per_objfile->per_bfd->get_dwz_file ();
if (dwz != NULL)
{
read_comp_units_from_section (per_objfile, &dwz->info, &dwz->abbrev, 1,
- sig_types, rcuh_kind::COMPILE);
+ sig_types, ruh_kind::COMPILE);
if (!dwz->types.empty ())
{
- per_objfile->per_bfd->all_units.clear ();
-
/* See enhancement PR symtab/30838. */
error (_(DWARF_ERROR_PREFIX
".debug_types section not supported in dwz file"));
@@ -3790,6 +3817,7 @@ create_all_units (dwarf2_per_objfile *per_objfile)
per_objfile->per_bfd->signatured_types = std::move (sig_types);
finalize_all_units (per_objfile->per_bfd);
+ remove_all_units.disable ();
}
/* Return the initial uleb128 in the die at INFO_PTR. */
@@ -3825,7 +3853,7 @@ cutu_reader::peek_die_abbrev (const gdb_byte *info_ptr,
error (_(DWARF_ERROR_PREFIX
"Could not find abbrev number %d in %s at offset %s"
" [in module %s]"),
- abbrev_number, m_cu->per_cu->is_debug_types ? "TU" : "CU",
+ abbrev_number, m_cu->per_cu->is_debug_types () ? "TU" : "CU",
sect_offset_str (m_cu->header.sect_off),
bfd_get_filename (m_abfd));
}
@@ -3862,12 +3890,7 @@ cutu_reader::skip_one_attribute (dwarf_form form, const gdb_byte *info_ptr)
switch (form)
{
case DW_FORM_ref_addr:
- /* In DWARF 2, DW_FORM_ref_addr is address sized; in DWARF 3
- and later it is offset sized. */
- if (m_cu->header.version == 2)
- return info_ptr + m_cu->header.addr_size;
- else
- return info_ptr + m_cu->header.offset_size;
+ return info_ptr + m_cu->per_cu->ref_addr_size ();
case DW_FORM_GNU_ref_alt:
return info_ptr + m_cu->header.offset_size;
@@ -3896,11 +3919,13 @@ cutu_reader::skip_one_attribute (dwarf_form form, const gdb_byte *info_ptr)
case DW_FORM_data4:
case DW_FORM_ref4:
case DW_FORM_strx4:
+ case DW_FORM_ref_sup4:
return info_ptr + 4;
case DW_FORM_data8:
case DW_FORM_ref8:
case DW_FORM_ref_sig8:
+ case DW_FORM_ref_sup8:
return info_ptr + 8;
case DW_FORM_data16:
@@ -3913,6 +3938,7 @@ cutu_reader::skip_one_attribute (dwarf_form form, const gdb_byte *info_ptr)
case DW_FORM_sec_offset:
case DW_FORM_strp:
case DW_FORM_GNU_strp_alt:
+ case DW_FORM_strp_sup:
return info_ptr + m_cu->header.offset_size;
case DW_FORM_exprloc:
@@ -3956,7 +3982,7 @@ cutu_reader::skip_one_attribute (dwarf_form form, const gdb_byte *info_ptr)
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.
-
+
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. */
@@ -4092,7 +4118,7 @@ maybe_queue_comp_unit (struct dwarf2_cu *dependent_cu, dwarf2_per_cu *per_cu,
dwarf_read_debug_printf ("Queuing CU for expansion: "
"section offset = 0x%" PRIx64 ", "
"queue size = %zu",
- to_underlying (per_cu->sect_off),
+ to_underlying (per_cu->sect_off ()),
per_objfile->queue->size ());
}
@@ -4138,14 +4164,14 @@ process_queue (dwarf2_per_objfile *per_objfile)
char buf[100];
std::optional<chr::time_point<chr::steady_clock>> start_time;
- if (per_cu->is_debug_types)
+ if (per_cu->is_debug_types ())
{
struct signatured_type *sig_type =
(struct signatured_type *) per_cu;
sprintf (buf, "TU %s at offset %s",
hex_string (sig_type->signature),
- sect_offset_str (per_cu->sect_off));
+ sect_offset_str (per_cu->sect_off ()));
/* There can be 100s of TUs.
Only print them in verbose mode. */
debug_print_threshold = 2;
@@ -4153,7 +4179,7 @@ process_queue (dwarf2_per_objfile *per_objfile)
else
{
sprintf (buf, "CU at offset %s",
- sect_offset_str (per_cu->sect_off));
+ sect_offset_str (per_cu->sect_off ()));
debug_print_threshold = 1;
}
@@ -4165,7 +4191,7 @@ process_queue (dwarf2_per_objfile *per_objfile)
++expanded_count;
- if (per_cu->is_debug_types)
+ if (per_cu->is_debug_types ())
process_full_type_unit (cu);
else
process_full_comp_unit (cu);
@@ -4196,7 +4222,7 @@ static void
load_full_comp_unit (dwarf2_per_cu *this_cu, dwarf2_per_objfile *per_objfile,
bool skip_partial, enum language pretend_language)
{
- gdb_assert (! this_cu->is_debug_types);
+ gdb_assert (!this_cu->is_debug_types ());
gdb_assert (per_objfile->get_cu (this_cu) == nullptr);
cutu_reader reader (*this_cu, *per_objfile, nullptr, nullptr, skip_partial,
@@ -4319,7 +4345,7 @@ fixup_go_packaging (struct dwarf2_cu *cu)
struct symbol *sym = list->symbol[i];
if (sym->language () == language_go
- && sym->aclass () == LOC_BLOCK)
+ && sym->loc_class () == LOC_BLOCK)
{
gdb::unique_xmalloc_ptr<char> this_package_name
= go_symbol_package_name (sym);
@@ -4356,7 +4382,7 @@ fixup_go_packaging (struct dwarf2_cu *cu)
sym->set_language (language_go, &objfile->objfile_obstack);
sym->compute_and_set_names (saved_package_name, false, objfile->per_bfd);
sym->set_domain (TYPE_DOMAIN);
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
sym->set_type (type);
add_symbol_to_list (sym, cu->get_builder ()->get_global_symbols ());
@@ -4566,9 +4592,9 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
else
{
struct type *disr_type = nullptr;
- for (int i = 0; i < type->num_fields (); ++i)
+ for (const auto &field : type->fields ())
{
- disr_type = type->field (i).type ();
+ disr_type = field.type ();
if (disr_type->code () != TYPE_CODE_STRUCT)
{
@@ -4607,7 +4633,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
field *new_fields
= (struct field *) TYPE_ZALLOC (type, ((type->num_fields () + 1)
* sizeof (struct field)));
- memcpy (new_fields + 1, type->fields (),
+ memcpy (new_fields + 1, type->fields ().data (),
type->num_fields () * sizeof (struct field));
type->set_fields (new_fields);
type->set_num_fields (type->num_fields () + 1);
@@ -4621,13 +4647,12 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
variant name. For convenience we build a map here. */
struct type *enum_type = disr_field->type ();
gdb::unordered_map<std::string_view, ULONGEST> discriminant_map;
- for (int i = 0; i < enum_type->num_fields (); ++i)
+ for (const auto &field : enum_type->fields ())
{
- if (enum_type->field (i).loc_kind () == FIELD_LOC_KIND_ENUMVAL)
+ if (field.loc_kind () == FIELD_LOC_KIND_ENUMVAL)
{
- const char *name
- = rust_last_path_segment (enum_type->field (i).name ());
- discriminant_map[name] = enum_type->field (i).loc_enumval ();
+ const char *name = rust_last_path_segment (field.name ());
+ discriminant_map[name] = field.loc_enumval ();
}
}
@@ -4663,7 +4688,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
if (sub_type->num_fields () > 0)
{
sub_type->set_num_fields (sub_type->num_fields () - 1);
- sub_type->set_fields (sub_type->fields () + 1);
+ sub_type->set_fields (sub_type->fields ().data () + 1);
}
type->field (i).set_name (variant_name);
sub_type->set_name
@@ -4748,7 +4773,7 @@ recursively_compute_inclusions
{
/* If this is a type unit only add its symbol table if we haven't
seen it yet (type unit per_cu's can share symtabs). */
- if (per_cu->is_debug_types)
+ if (per_cu->is_debug_types ())
{
if (bool inserted = all_type_symtabs.insert (cust).second;
inserted)
@@ -4779,7 +4804,7 @@ static void
compute_compunit_symtab_includes (dwarf2_per_cu *per_cu,
dwarf2_per_objfile *per_objfile)
{
- gdb_assert (! per_cu->is_debug_types);
+ gdb_assert (!per_cu->is_debug_types ());
if (!per_cu->imported_symtabs.empty ())
{
@@ -4818,7 +4843,7 @@ process_cu_includes (dwarf2_per_objfile *per_objfile)
{
for (dwarf2_per_cu *iter : per_objfile->per_bfd->just_read_cus)
{
- if (! iter->is_debug_types)
+ if (!iter->is_debug_types ())
compute_compunit_symtab_includes (iter, per_objfile);
}
@@ -4854,7 +4879,7 @@ process_full_comp_unit (dwarf2_cu *cu)
error (_(DWARF_ERROR_PREFIX
"unexpected tag '%s' at offset %s [in module %s]"),
dwarf_tag_name (cu->dies->tag),
- sect_offset_str (cu->per_cu->sect_off),
+ sect_offset_str (cu->per_cu->sect_off ()),
objfile_name (per_objfile->objfile));
}
@@ -4880,7 +4905,8 @@ process_full_comp_unit (dwarf2_cu *cu)
addr = per_objfile->relocate (highpc);
static_block
- = cu->get_builder ()->end_compunit_symtab_get_static_block (addr, 0, 1);
+ = cu->get_builder ()->end_compunit_symtab_get_static_block (addr, false,
+ true);
/* 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
@@ -4890,7 +4916,7 @@ process_full_comp_unit (dwarf2_cu *cu)
dwarf2_record_block_ranges (cu->dies, static_block, cu);
cust = cu->get_builder ()->end_compunit_symtab_from_static_block
- (static_block, 0);
+ (static_block, false);
if (cust != NULL)
{
@@ -4947,7 +4973,7 @@ process_full_type_unit (dwarf2_cu *cu)
struct compunit_symtab *cust;
struct signatured_type *sig_type;
- gdb_assert (cu->per_cu->is_debug_types);
+ gdb_assert (cu->per_cu->is_debug_types ());
sig_type = (struct signatured_type *) cu->per_cu;
/* Clear the list here in case something was left over. */
@@ -5003,6 +5029,21 @@ process_full_type_unit (dwarf2_cu *cu)
cu->reset_builder ();
}
+/* See read.h. */
+
+const dwarf2_section_info &
+get_section_for_ref (const attribute &attr, dwarf2_cu *cu)
+{
+ gdb_assert (attr.form_is_ref ());
+
+ if (attr.form_is_alt ())
+ return cu->per_cu->per_bfd ()->get_dwz_file (true)->info;
+
+ /* If the source is already in the supplementary (dwz) file, then CU->SECTION
+ already represents the section in the supplementary file. */
+ return cu->section ();
+}
+
/* Process an imported unit DIE. */
static void
@@ -5011,7 +5052,7 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
struct attribute *attr;
/* For now we don't handle imported units in type units. */
- if (cu->per_cu->is_debug_types)
+ if (cu->per_cu->is_debug_types ())
{
error (_(DWARF_ERROR_PREFIX
"DW_TAG_imported_unit is not supported in type units"
@@ -5022,12 +5063,11 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
attr = dwarf2_attr (die, DW_AT_import, cu);
if (attr != NULL)
{
+ const dwarf2_section_info &section = get_section_for_ref (*attr, cu);
sect_offset sect_off = attr->get_ref_die_offset ();
- 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 *per_cu
- = dwarf2_find_containing_comp_unit (sect_off, is_dwz,
- per_objfile->per_bfd);
+ = dwarf2_find_containing_unit ({ &section, sect_off }, per_objfile);
/* 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,
@@ -5729,7 +5769,7 @@ read_alias (struct die_info *die, struct dwarf2_cu *cu)
type = die_type (d, imported_cu);
struct symbol *sym = new_symbol (die, type, cu);
attr = dwarf2_attr (d, DW_AT_location, imported_cu);
- sym->set_aclass_index (LOC_UNRESOLVED);
+ sym->set_loc_class_index (LOC_UNRESOLVED);
if (attr != nullptr)
var_decode_location (attr, sym, cu);
return true;
@@ -5952,7 +5992,7 @@ find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu)
&& res.get_name () != nullptr
&& IS_ABSOLUTE_PATH (res.get_name ()))
{
- res.set_comp_dir (ldirname (res.get_name ()));
+ res.set_comp_dir (gdb_ldirname (res.get_name ()));
res.set_name (make_unique_xstrdup (lbasename (res.get_name ())));
}
@@ -5976,7 +6016,7 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
void **slot;
int decode_mapping;
- gdb_assert (! cu->per_cu->is_debug_types);
+ gdb_assert (!cu->per_cu->is_debug_types ());
attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
if (attr == NULL || !attr->form_is_unsigned ())
@@ -6000,7 +6040,7 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
xcalloc, xfree));
}
- line_header line_header_local (line_offset, cu->per_cu->is_dwz);
+ line_header line_header_local (line_offset, cu->per_cu->is_dwz ());
line_header_local_hash = line_header_hash (&line_header_local);
if (per_objfile->line_header_hash != NULL)
{
@@ -6096,7 +6136,7 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
sect_offset line_offset = (sect_offset) attr->as_unsigned ();
line_header_up lh = dwarf_decode_line_header (line_offset, cu,
fnd.get_comp_dir ());
- if (lh->version == 5 && lh->is_valid_file_index (1))
+ if (lh->version == 5 && lh->include_dir_at (1) != nullptr)
{
std::string dir = lh->include_dir_at (1);
fnd.set_comp_dir (std::move (dir));
@@ -6148,6 +6188,20 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
}
}
+/* See cu.h.
+
+ This function is defined in this file (instead of cu.c) because it needs
+ to see the definition of struct dwo_unit. */
+
+const dwarf2_section_info &
+dwarf2_cu::section () const
+{
+ if (this->dwo_unit != nullptr)
+ return *this->dwo_unit->section;
+ else
+ return *this->per_cu->section ();
+}
+
void
dwarf2_cu::setup_type_unit_groups (struct die_info *die)
{
@@ -6156,7 +6210,7 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
unsigned int i;
struct signatured_type *sig_type;
- gdb_assert (per_cu->is_debug_types);
+ gdb_assert (per_cu->is_debug_types ());
sig_type = (struct signatured_type *) per_cu;
attr = dwarf2_attr (die, DW_AT_stmt_list, this);
@@ -6299,84 +6353,151 @@ static dwo_file *
lookup_dwo_file (dwarf2_per_bfd *per_bfd, const char *dwo_name,
const char *comp_dir)
{
+ gdb::lock_guard<gdb::mutex> guard (per_bfd->dwo_files_lock);
auto it = per_bfd->dwo_files.find (dwo_file_search {dwo_name, comp_dir});
-
return it != per_bfd->dwo_files.end () ? it->get() : nullptr;
}
-/* Create the dwo_units for the CUs in a DWO_FILE.
- Note: This function processes DWO files only, not DWP files. */
+/* Add DWO_FILE to the per-BFD DWO file hash table.
+
+ Return the dwo_file actually kept in the hash table.
+
+ If another thread raced with this one, opening the exact same DWO file and
+ inserting it first in the hash table, then keep that other thread's copy
+ and DWO_FILE gets freed. */
+
+static dwo_file *
+add_dwo_file (dwarf2_per_bfd *per_bfd, dwo_file_up dwo_file)
+{
+ gdb::lock_guard<gdb::mutex> lock (per_bfd->dwo_files_lock);
+ return per_bfd->dwo_files.emplace (std::move (dwo_file)).first->get ();
+}
void
-cutu_reader::create_dwo_cus_hash_table (dwarf2_cu *cu, dwo_file &dwo_file)
+cutu_reader::create_dwo_unit_hash_tables (dwo_file &dwo_file,
+ dwarf2_cu &skeleton_cu,
+ dwarf2_section_info &section,
+ ruh_kind section_kind)
{
- dwarf2_per_objfile *per_objfile = cu->per_objfile;
- dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
- const gdb_byte *info_ptr, *end_ptr;
- auto &section = dwo_file.sections.info;
+ dwarf2_per_objfile &per_objfile = *skeleton_cu.per_objfile;
+ dwarf2_per_bfd &per_bfd = *per_objfile.per_bfd;
- info_ptr = section.buffer;
+ const gdb_byte *info_ptr = section.buffer;
if (info_ptr == NULL)
return;
- dwarf_read_debug_printf ("Reading %s for %s:",
- section.get_name (),
+ dwarf_read_debug_printf ("Reading %s for %s:", section.get_name (),
section.get_file_name ());
- end_ptr = info_ptr + section.size;
+ const gdb_byte *end_ptr = info_ptr + section.size;
+
while (info_ptr < end_ptr)
{
sect_offset sect_off = (sect_offset) (info_ptr - section.buffer);
+ unit_head header;
+ dwarf2_section_info *abbrev_section = &dwo_file.sections.abbrev;
+ const gdb_byte *info_ptr_post_header
+ = read_and_check_unit_head (&header, &section, abbrev_section,
+ info_ptr, section_kind);
- /* The length of the CU gets set by the cutu_reader just below. */
- dwarf2_per_cu per_cu (per_bfd, &section, sect_off, 0 /* length */,
- false /* is_dwz */);
- cutu_reader reader (per_cu, *per_objfile, language_minimal,
- *cu, dwo_file);
-
- info_ptr += per_cu.length ();
+ unsigned int length = header.get_length_with_initial ();
+ info_ptr += length;
- if (reader.is_dummy())
+ /* Skip dummy units. */
+ if (info_ptr_post_header >= info_ptr
+ || peek_abbrev_code (section.get_bfd_owner (),
+ info_ptr_post_header) == 0)
continue;
- /* DWARF 5 .debug_info.dwo sections may contain some type units. Skip
- everything that is not a compile unit. */
- if (const auto ut = reader.cu ()->header.unit_type;
- ut != DW_UT_compile && ut != DW_UT_split_compile)
+ if (header.unit_type != DW_UT_compile
+ && header.unit_type != DW_UT_split_compile
+ && header.unit_type != DW_UT_type
+ && header.unit_type != DW_UT_split_type)
continue;
- std::optional<ULONGEST> signature
- = lookup_dwo_id (reader.cu (), reader.top_level_die ());
- if (!signature.has_value ())
+ ULONGEST signature;
+
+ /* For type units (all DWARF versions) and DWARF 5 compile units, the
+ signature/DWO ID is already available in the header. For compile
+ units in DWARF < 5, we need to read the DW_AT_GNU_dwo_id attribute
+ from the top-level DIE.
+
+ For DWARF < 5 compile units, the unit type will be set to DW_UT_compile
+ by read_and_check_comp_unit_head. */
+ if (header.version < 5 && header.unit_type == DW_UT_compile)
{
- complaint (_(DWARF_ERROR_PREFIX
- "debug entry at offset %s is missing its dwo_id"
- " [in module %s]"),
- sect_offset_str (sect_off),
- dwo_file.dwo_name.c_str ());
- continue;
+ /* The length of the CU is not necessary. */
+ dwarf2_per_cu per_cu (&per_bfd, &section, sect_off, length,
+ false /* is_dwz */);
+ cutu_reader reader (per_cu, per_objfile, language_minimal,
+ skeleton_cu, dwo_file);
+
+ std::optional<ULONGEST> opt_signature
+ = lookup_dwo_id (reader.cu (), reader.top_level_die ());
+
+ if (!opt_signature.has_value ())
+ {
+ complaint (_ (DWARF_ERROR_PREFIX
+ "debug entry at offset %s is missing its dwo_id"
+ " [in module %s]"),
+ sect_offset_str (sect_off),
+ dwo_file.dwo_name.c_str ());
+ continue;
+ }
+
+ signature = *opt_signature;
}
+ else
+ signature = header.signature;
- dwo_unit *dwo_unit = OBSTACK_ZALLOC (&per_bfd->obstack, struct dwo_unit);
+ auto dwo_unit = std::make_unique<struct dwo_unit> ();
+ /* Set the fields common to compile and type units. */
dwo_unit->dwo_file = &dwo_file;
- dwo_unit->signature = *signature;
+ dwo_unit->signature = signature;
dwo_unit->section = &section;
dwo_unit->sect_off = sect_off;
- dwo_unit->length = per_cu.length ();
+ dwo_unit->length = length;
+
+ switch (header.unit_type)
+ {
+ case DW_UT_compile:
+ case DW_UT_split_compile:
+ {
+ dwarf_read_debug_printf (" compile unit at offset %s, dwo_id %s",
+ sect_offset_str (sect_off),
+ hex_string (dwo_unit->signature));
+
+ auto [it, inserted] = dwo_file.cus.emplace (std::move (dwo_unit));
+ if (!inserted)
+ complaint (_("debug cu entry at offset %s is duplicate to"
+ " the entry at offset %s, signature %s"),
+ sect_offset_str (sect_off),
+ sect_offset_str ((*it)->sect_off),
+ hex_string (dwo_unit->signature));
+ break;
+ }
+
+ case DW_UT_type:
+ case DW_UT_split_type:
+ {
+ dwo_unit->type_offset_in_tu = header.type_offset_in_tu;
- dwarf_read_debug_printf (" offset %s, dwo_id %s",
- sect_offset_str (sect_off),
- hex_string (dwo_unit->signature));
+ dwarf_read_debug_printf (" type unit at offset %s, signature %s",
+ sect_offset_str (sect_off),
+ hex_string (dwo_unit->signature));
- auto [it, inserted] = dwo_file.cus.emplace (dwo_unit);
- if (!inserted)
- complaint (_("debug cu entry at offset %s is duplicate to"
- " the entry at offset %s, signature %s"),
- sect_offset_str (sect_off),
- sect_offset_str ((*it)->sect_off),
- hex_string (dwo_unit->signature));
+ auto [it, inserted] = dwo_file.tus.emplace (std::move (dwo_unit));
+ if (!inserted)
+ complaint (_("debug type entry at offset %s is duplicate to"
+ " the entry at offset %s, signature %s"),
+ sect_offset_str (sect_off),
+ sect_offset_str ((*it)->sect_off),
+ hex_string (header.signature));
+ break;
+ }
+ }
}
}
@@ -6848,7 +6969,7 @@ locate_v1_virtual_dwo_sections (asection *sectp,
COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU.
This is for DWP version 1 files. */
-static struct dwo_unit *
+static dwo_unit_up
create_dwo_unit_in_dwp_v1 (dwarf2_per_bfd *per_bfd,
struct dwp_file *dwp_file,
uint32_t unit_index,
@@ -6971,19 +7092,17 @@ create_dwo_unit_in_dwp_v1 (dwarf2_per_bfd *per_bfd,
types we'll grow the vector and eventually have to reallocate space
for it, invalidating all copies of pointers into the previous
contents. */
- auto [it, inserted]
- = per_bfd->dwo_files.emplace (std::move (new_dwo_file));
- gdb_assert (inserted);
- dwo_file = it->get ();
+ dwo_file = add_dwo_file (per_bfd, std::move (new_dwo_file));
}
else
dwarf_read_debug_printf ("Using existing virtual DWO: %s",
virtual_dwo_name.c_str ());
- dwo_unit *dwo_unit = OBSTACK_ZALLOC (&per_bfd->obstack, struct dwo_unit);
+ auto dwo_unit = std::make_unique<struct dwo_unit> ();
dwo_unit->dwo_file = dwo_file;
dwo_unit->signature = signature;
- dwo_unit->section = XOBNEW (&per_bfd->obstack, struct dwarf2_section_info);
+ dwo_unit->section_holder = std::make_unique<dwarf2_section_info> ();
+ dwo_unit->section = dwo_unit->section_holder.get ();
*dwo_unit->section = sections.info_or_types;
/* dwo_unit->{offset,length,type_offset_in_tu} are set later. */
@@ -7030,8 +7149,8 @@ create_dwp_v2_or_v5_section (dwarf2_per_bfd *per_bfd,
result.virtual_offset = offset;
result.size = size;
- gdb_assert (section->readin);
- result.readin = true;
+ gdb_assert (section->read_in);
+ result.read_in = true;
result.buffer = section->buffer + offset;
return result;
}
@@ -7041,7 +7160,7 @@ create_dwp_v2_or_v5_section (dwarf2_per_bfd *per_bfd,
COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU.
This is for DWP version 2 files. */
-static struct dwo_unit *
+static dwo_unit_up
create_dwo_unit_in_dwp_v2 (dwarf2_per_bfd *per_bfd,
struct dwp_file *dwp_file,
uint32_t unit_index,
@@ -7176,19 +7295,17 @@ create_dwo_unit_in_dwp_v2 (dwarf2_per_bfd *per_bfd,
types we'll grow the vector and eventually have to reallocate space
for it, invalidating all copies of pointers into the previous
contents. */
- auto [it, inserted]
- = per_bfd->dwo_files.emplace (std::move (new_dwo_file));
- gdb_assert (inserted);
- dwo_file = it->get ();
+ dwo_file = add_dwo_file (per_bfd, std::move (new_dwo_file));
}
else
dwarf_read_debug_printf ("Using existing virtual DWO: %s",
virtual_dwo_name.c_str ());
- dwo_unit *dwo_unit = OBSTACK_ZALLOC (&per_bfd->obstack, struct dwo_unit);
+ auto dwo_unit = std::make_unique<struct dwo_unit> ();
dwo_unit->dwo_file = dwo_file;
dwo_unit->signature = signature;
- dwo_unit->section = XOBNEW (&per_bfd->obstack, struct dwarf2_section_info);
+ dwo_unit->section_holder = std::make_unique<dwarf2_section_info> ();
+ dwo_unit->section = dwo_unit->section_holder.get ();
*dwo_unit->section = create_dwp_v2_or_v5_section
(per_bfd,
is_debug_types
@@ -7206,7 +7323,7 @@ create_dwo_unit_in_dwp_v2 (dwarf2_per_bfd *per_bfd,
COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU.
This is for DWP version 5 files. */
-static struct dwo_unit *
+static dwo_unit_up
create_dwo_unit_in_dwp_v5 (dwarf2_per_bfd *per_bfd,
struct dwp_file *dwp_file,
uint32_t unit_index,
@@ -7346,16 +7463,13 @@ create_dwo_unit_in_dwp_v5 (dwarf2_per_bfd *per_bfd,
types we'll grow the vector and eventually have to reallocate space
for it, invalidating all copies of pointers into the previous
contents. */
- auto [it, inserted]
- = per_bfd->dwo_files.emplace (std::move (new_dwo_file));
- gdb_assert (inserted);
- dwo_file = it->get ();
+ dwo_file = add_dwo_file (per_bfd, std::move (new_dwo_file));
}
else
dwarf_read_debug_printf ("Using existing virtual DWO: %s",
virtual_dwo_name.c_str ());
- dwo_unit *dwo_unit = OBSTACK_ZALLOC (&per_bfd->obstack, struct dwo_unit);
+ auto dwo_unit = std::make_unique<struct dwo_unit> ();
dwo_unit->dwo_file = dwo_file;
dwo_unit->signature = signature;
dwo_unit->section
@@ -7386,9 +7500,12 @@ lookup_dwo_unit_in_dwp (dwarf2_per_bfd *per_bfd,
auto &dwo_unit_set
= is_debug_types ? dwp_file->loaded_tus : dwp_file->loaded_cus;
- if (auto it = dwo_unit_set.find (signature);
- it != dwo_unit_set.end ())
- return *it;
+ {
+ gdb::lock_guard<gdb::mutex> guard (dwp_file->loaded_cutus_lock);
+ if (auto it = dwo_unit_set.find (signature);
+ it != dwo_unit_set.end ())
+ return it->get ();
+ }
/* Use a for loop so that we don't loop forever on bad debug info. */
for (unsigned int i = 0; i < dwp_htab->nr_slots; ++i)
@@ -7402,7 +7519,7 @@ lookup_dwo_unit_in_dwp (dwarf2_per_bfd *per_bfd,
uint32_t unit_index =
read_4_bytes (dbfd,
dwp_htab->unit_table + hash * sizeof (uint32_t));
- dwo_unit *dwo_unit;
+ dwo_unit_up dwo_unit;
if (dwp_file->version == 1)
dwo_unit
@@ -7417,9 +7534,11 @@ lookup_dwo_unit_in_dwp (dwarf2_per_bfd *per_bfd,
= create_dwo_unit_in_dwp_v5 (per_bfd, dwp_file, unit_index,
comp_dir, signature, is_debug_types);
- auto [it, inserted] = dwo_unit_set.emplace (dwo_unit);
- gdb_assert (inserted);
- return *it;
+ /* If another thread raced with this one, opening the exact same
+ DWO unit, then we'll keep that other thread's copy. */
+ gdb::lock_guard<gdb::mutex> guard (dwp_file->loaded_cutus_lock);
+ auto it = dwo_unit_set.emplace (std::move (dwo_unit)).first;
+ return it->get ();
}
if (signature_in_table == 0)
@@ -7475,7 +7594,7 @@ try_open_dwop_file (dwarf2_per_bfd *per_bfd, const char *file_name, int is_dwp,
search_path = per_bfd->captured_debug_dir.c_str ();
/* Add the path for the executable binary to the list of search paths. */
- std::string objfile_dir = ldirname (per_bfd->filename ());
+ std::string objfile_dir = gdb_ldirname (per_bfd->filename ());
search_path_holder.reset (concat (objfile_dir.c_str (),
dirname_separator_string,
search_path, nullptr));
@@ -7496,14 +7615,21 @@ try_open_dwop_file (dwarf2_per_bfd *per_bfd, const char *file_name, int is_dwp,
if (sym_bfd == NULL)
return NULL;
- if (!bfd_check_format (sym_bfd.get (), bfd_object))
- return NULL;
+ {
+ /* The operations below are not thread-safe, use a lock to synchronize
+ concurrent accesses. */
+ static gdb::mutex mutex;
+ gdb::lock_guard<gdb::mutex> lock (mutex);
- /* Success. Record the bfd as having been included by the objfile's bfd.
+ if (!bfd_check_format (sym_bfd.get (), bfd_object))
+ return NULL;
+
+ /* Success. Record the bfd as having been included by the objfile's bfd.
This is important because things like demangled_names_hash lives in the
objfile's per_bfd space and may have references to things like symbol
names that live in the DWO/DWP file's per_bfd space. PR 16426. */
- gdb_bfd_record_inclusion (per_bfd->obfd, sym_bfd.get ());
+ gdb_bfd_record_inclusion (per_bfd->obfd, sym_bfd.get ());
+ }
return sym_bfd;
}
@@ -7553,47 +7679,66 @@ cutu_reader::open_dwo_file (dwarf2_per_bfd *per_bfd, const char *file_name,
size of each of the DWO debugging sections we are interested in. */
void
-cutu_reader::locate_dwo_sections (struct objfile *objfile, bfd *abfd,
- asection *sectp, dwo_sections *dwo_sections)
+cutu_reader::locate_dwo_sections (objfile *objfile, dwo_file &dwo_file)
{
const struct dwop_section_names *names = &dwop_section_names;
+ dwo_sections &dwo_sections = dwo_file.sections;
+ bool complained_about_macro_already = false;
+
+ for (asection *sec : gdb_bfd_sections (dwo_file.dbfd))
+ {
+ struct dwarf2_section_info *dw_sect = nullptr;
+
+ if (names->abbrev_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.abbrev;
+ else if (names->info_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.infos.emplace_back (dwarf2_section_info {});
+ else if (names->line_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.line;
+ else if (names->loc_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.loc;
+ else if (names->loclists_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.loclists;
+ else if (names->macinfo_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.macinfo;
+ else if (names->macro_dwo.matches (sec->name))
+ {
+ /* gcc versions <= 13 generate multiple .debug_macro.dwo sections with
+ some unresolved links between them. It's not usable, so do as if
+ there were not there. */
+ if (!complained_about_macro_already)
+ {
+ if (dwo_sections.macro.s.section == nullptr)
+ dw_sect = &dwo_sections.macro;
+ else
+ {
+ warning (_("Multiple .debug_macro.dwo sections found in "
+ "%s, ignoring them."), dwo_file.dbfd->filename);
- struct dwarf2_section_info *dw_sect = nullptr;
-
- if (names->abbrev_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->abbrev;
- else if (names->info_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->info;
- else if (names->line_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->line;
- else if (names->loc_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->loc;
- else if (names->loclists_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->loclists;
- else if (names->macinfo_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->macinfo;
- else if (names->macro_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->macro;
- else if (names->rnglists_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->rnglists;
- else if (names->str_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->str;
- else if (names->str_offsets_dwo.matches (sectp->name))
- 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));
- dwo_sections->types.push_back (type_section);
- dw_sect = &dwo_sections->types.back ();
- }
+ dwo_sections.macro = dwarf2_section_info {};
+ complained_about_macro_already = true;
+ }
+ }
+ }
+ else if (names->rnglists_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.rnglists;
+ else if (names->str_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.str;
+ else if (names->str_offsets_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.str_offsets;
+ else if (names->types_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.types.emplace_back (dwarf2_section_info {});
+
+ if (dw_sect != nullptr)
+ {
+ /* Make sure we don't overwrite a section info that has been filled in
+ already. */
+ gdb_assert (!dw_sect->read_in);
- if (dw_sect != nullptr)
- {
- dw_sect->s.section = sectp;
- dw_sect->size = bfd_section_size (sectp);
- dw_sect->read (objfile);
+ dw_sect->s.section = sec;
+ dw_sect->size = bfd_section_size (sec);
+ dw_sect->read (objfile);
+ }
}
}
@@ -7606,7 +7751,6 @@ cutu_reader::open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name,
const char *comp_dir)
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
- dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
gdb_bfd_ref_ptr dbfd
= open_dwo_file (per_objfile->per_bfd, dwo_name, comp_dir);
@@ -7622,19 +7766,13 @@ cutu_reader::open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name,
dwo_file->comp_dir = comp_dir;
dwo_file->dbfd = std::move (dbfd);
- for (asection *sec : gdb_bfd_sections (dwo_file->dbfd))
- this->locate_dwo_sections (per_objfile->objfile, dwo_file->dbfd.get (), sec,
- &dwo_file->sections);
+ this->locate_dwo_sections (per_objfile->objfile, *dwo_file);
- create_dwo_cus_hash_table (cu, *dwo_file);
+ for (dwarf2_section_info &section : dwo_file->sections.infos)
+ create_dwo_unit_hash_tables (*dwo_file, *cu, section, ruh_kind::COMPILE);
- if (cu->header.version < 5)
- create_dwo_debug_types_hash_table (per_bfd, dwo_file.get (),
- dwo_file->sections.types);
- else
- create_dwo_debug_type_hash_table (per_bfd, dwo_file.get (),
- &dwo_file->sections.info,
- rcuh_kind::COMPILE);
+ for (dwarf2_section_info &section : dwo_file->sections.types)
+ create_dwo_unit_hash_tables (*dwo_file, *cu, section, ruh_kind::TYPE);
dwarf_read_debug_printf ("DWO file found: %s", dwo_name);
@@ -7670,6 +7808,10 @@ dwarf2_locate_common_dwp_sections (struct objfile *objfile, bfd *abfd,
if (dw_sect != nullptr)
{
+ /* Make sure we don't overwrite a section info that has been filled in
+ already. */
+ gdb_assert (!dw_sect->read_in);
+
dw_sect->s.section = sectp;
dw_sect->size = bfd_section_size (sectp);
dw_sect->read (objfile);
@@ -7715,6 +7857,10 @@ dwarf2_locate_v2_dwp_sections (struct objfile *objfile, bfd *abfd,
if (dw_sect != nullptr)
{
+ /* Make sure we don't overwrite a section info that has been filled in
+ already. */
+ gdb_assert (!dw_sect->read_in);
+
dw_sect->s.section = sectp;
dw_sect->size = bfd_section_size (sectp);
dw_sect->read (objfile);
@@ -7758,6 +7904,10 @@ dwarf2_locate_v5_dwp_sections (struct objfile *objfile, bfd *abfd,
if (dw_sect != nullptr)
{
+ /* Make sure we don't overwrite a section info that has been filled in
+ already. */
+ gdb_assert (!dw_sect->read_in);
+
dw_sect->s.section = sectp;
dw_sect->size = bfd_section_size (sectp);
dw_sect->read (objfile);
@@ -7819,7 +7969,7 @@ open_and_init_dwp_file (dwarf2_per_objfile *per_objfile)
struct objfile *backlink = objfile->separate_debug_objfile_backlink;
const char *backlink_basename = lbasename (backlink->original_name);
- dwp_name = ldirname (objfile->original_name) + SLASH_STRING + backlink_basename;
+ dwp_name = gdb_ldirname (objfile->original_name) + SLASH_STRING + backlink_basename;
}
else
dwp_name = objfile->original_name;
@@ -7969,12 +8119,7 @@ cutu_reader::lookup_dwo_cutu (dwarf2_cu *cu, const char *dwo_name,
= open_and_init_dwo_file (cu, dwo_name, comp_dir);
if (new_dwo_file != nullptr)
- {
- auto [it, inserted]
- = per_bfd->dwo_files.emplace (std::move (new_dwo_file));
- gdb_assert (inserted);
- dwo_file = (*it).get ();
- }
+ dwo_file = add_dwo_file (per_bfd, std::move (new_dwo_file));
}
if (dwo_file != NULL)
@@ -7985,13 +8130,13 @@ cutu_reader::lookup_dwo_cutu (dwarf2_cu *cu, const char *dwo_name,
{
if (auto it = dwo_file->tus.find (signature);
it != dwo_file->tus.end ())
- dwo_cutu = *it;
+ dwo_cutu = it->get ();
}
else if (!is_debug_types && !dwo_file->cus.empty ())
{
if (auto it = dwo_file->cus.find (signature);
it != dwo_file->cus.end ())
- dwo_cutu = *it;
+ dwo_cutu = it->get ();
}
if (dwo_cutu != NULL)
@@ -8026,7 +8171,7 @@ cutu_reader::lookup_dwo_cutu (dwarf2_cu *cu, const char *dwo_name,
warning (_("Could not find DWO %s %s(%s)%s referenced by %s at offset %s"
" [in module %s]"),
kind, dwo_name, hex_string (signature), dwp_text.c_str (), kind,
- sect_offset_str (cu->per_cu->sect_off), objfile_name (objfile));
+ sect_offset_str (cu->per_cu->sect_off ()), objfile_name (objfile));
}
return NULL;
}
@@ -8038,7 +8183,7 @@ dwo_unit *
cutu_reader::lookup_dwo_comp_unit (dwarf2_cu *cu, const char *dwo_name,
const char *comp_dir, ULONGEST signature)
{
- gdb_assert (!cu->per_cu->is_debug_types);
+ gdb_assert (!cu->per_cu->is_debug_types ());
return lookup_dwo_cutu (cu, dwo_name, comp_dir, signature, 0);
}
@@ -8050,7 +8195,7 @@ dwo_unit *
cutu_reader::lookup_dwo_type_unit (dwarf2_cu *cu, const char *dwo_name,
const char *comp_dir)
{
- gdb_assert (cu->per_cu->is_debug_types);
+ gdb_assert (cu->per_cu->is_debug_types ());
signatured_type *sig_type = (signatured_type *) cu->per_cu;
@@ -8090,7 +8235,7 @@ queue_and_load_all_dwo_tus (dwarf2_cu *cu)
struct dwo_file *dwo_file;
gdb_assert (cu != nullptr);
- gdb_assert (!cu->per_cu->is_debug_types);
+ gdb_assert (!cu->per_cu->is_debug_types ());
gdb_assert (cu->per_objfile->per_bfd->dwp_file == nullptr);
dwo_unit = cu->dwo_unit;
@@ -8098,8 +8243,8 @@ queue_and_load_all_dwo_tus (dwarf2_cu *cu)
dwo_file = dwo_unit->dwo_file;
- for (struct dwo_unit *unit : dwo_file->tus)
- queue_and_load_dwo_tu (unit, cu);
+ for (const dwo_unit_up &unit : dwo_file->tus)
+ queue_and_load_dwo_tu (unit.get (), cu);
}
/* Read in various DIEs. */
@@ -8693,7 +8838,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
struct call_site,
sizeof (*call_site) + sizeof (call_site->parameter[0]) * nparams))
struct call_site (pc, cu->per_cu, per_objfile);
-
+
if (!cu->call_site_htab.emplace (call_site).second)
{
complaint (_("Duplicate PC %s for DW_TAG_call_site "
@@ -8775,7 +8920,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
struct dwarf2_locexpr_baton *dlbaton;
struct dwarf_block *block = attr->as_block ();
- dlbaton = XOBNEW (&objfile->objfile_obstack, struct dwarf2_locexpr_baton);
+ dlbaton = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwarf2_locexpr_baton);
dlbaton->data = block->data;
dlbaton->size = block->size;
dlbaton->per_objfile = per_objfile;
@@ -8874,7 +9020,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
parameter->kind = CALL_SITE_PARAMETER_PARAM_OFFSET;
sect_offset sect_off = origin->get_ref_die_offset ();
- if (!cu->header.offset_in_cu_p (sect_off))
+ if (!cu->header.offset_in_unit_p (sect_off))
{
/* As DW_OP_GNU_parameter_ref uses CU-relative offset this
binding can be done only inside one CU. Such referenced DIE
@@ -9242,7 +9388,7 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu, dwarf_tag tag,
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
struct objfile *objfile = per_objfile->objfile;
- struct comp_unit_head *cu_header = &cu->header;
+ unit_head *cu_header = &cu->header;
bfd *obfd = objfile->obfd.get ();
unsigned int addr_size = cu_header->addr_size;
CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
@@ -9898,69 +10044,44 @@ dwarf2_access_attribute (struct die_info *die, struct dwarf2_cu *cu)
}
}
-/* 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. */
+/* Look for DW_AT_data_member_location or DW_AT_data_bit_offset and
+ store the results in FIELD. */
-static int
+static void
handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
- LONGEST *offset)
+ struct field *field)
{
- struct attribute *attr;
+ const auto data_member_location_attr
+ = dwarf2_attr (die, DW_AT_data_member_location, cu);
- attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
- if (attr != NULL)
+ if (data_member_location_attr != nullptr)
{
- *offset = 0;
- CORE_ADDR temp;
+ bool has_bit_offset = false;
+ LONGEST bit_offset = 0;
+ LONGEST anonymous_size = 0;
+ const auto bit_offset_attr = dwarf2_attr (die, DW_AT_bit_offset, cu);
- /* Note that we do not check for a section offset first here.
- This is because DW_AT_data_member_location is new in DWARF 4,
- so if we see it, we can assume that a constant form is really
- a constant and not a section offset. */
- if (attr->form_is_constant ())
- *offset = attr->constant_value (0);
- else if (attr->form_is_section_offset ())
- dwarf2_complex_location_expr_complaint ();
- else if (attr->form_is_block ()
- && decode_locdesc (attr->as_block (), cu, &temp))
+ if (bit_offset_attr != nullptr && bit_offset_attr->form_is_constant ())
{
- *offset = temp;
- }
- else
- dwarf2_complex_location_expr_complaint ();
+ has_bit_offset = true;
+ bit_offset = bit_offset_attr->confused_constant ().value_or (0);
- 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 or DW_AT_data_bit_offset and
- store the results in FIELD. */
+ const auto byte_size_attr = dwarf2_attr (die, DW_AT_byte_size, cu);
-static void
-handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
- struct field *field)
-{
- struct attribute *attr;
+ if (byte_size_attr != nullptr && byte_size_attr->form_is_constant ())
+ {
+ /* The size of the anonymous object containing
+ the bit field is explicit, so use the
+ indicated size (in bytes). */
+ anonymous_size
+ = byte_size_attr->unsigned_constant ().value_or (0);
+ }
+ }
- attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
- if (attr != NULL)
- {
- if (attr->form_is_constant ())
+ if (data_member_location_attr->form_is_constant ())
{
- LONGEST offset = attr->constant_value (0);
+ LONGEST offset
+ = data_member_location_attr->confused_constant ().value_or (0);
/* Work around this GCC 11 bug, where it would erroneously use -1
data member locations, instead of 0:
@@ -9975,23 +10096,40 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
}
field->set_loc_bitpos (offset * bits_per_byte);
+ if (has_bit_offset)
+ apply_bit_offset_to_field (*field, bit_offset, anonymous_size);
}
- else if (attr->form_is_section_offset ())
- dwarf2_complex_location_expr_complaint ();
- else if (attr->form_is_block ())
+ else if (data_member_location_attr->form_is_block ())
{
CORE_ADDR offset;
- if (decode_locdesc (attr->as_block (), cu, &offset))
- field->set_loc_bitpos (offset * bits_per_byte);
+ if (decode_locdesc (data_member_location_attr->as_block (), cu,
+ &offset))
+ {
+ field->set_loc_bitpos (offset * bits_per_byte);
+
+ if (has_bit_offset)
+ apply_bit_offset_to_field (*field, bit_offset, anonymous_size);
+ }
else
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
struct objfile *objfile = per_objfile->objfile;
- struct dwarf2_locexpr_baton *dlbaton
- = XOBNEW (&objfile->objfile_obstack,
- struct dwarf2_locexpr_baton);
- dlbaton->data = attr->as_block ()->data;
- dlbaton->size = attr->as_block ()->size;
+ struct dwarf2_locexpr_baton *dlbaton;
+ if (has_bit_offset)
+ {
+ dwarf2_field_location_baton *flbaton
+ = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ dwarf2_field_location_baton);
+ flbaton->is_field_location = true;
+ flbaton->bit_offset = bit_offset;
+ flbaton->explicit_byte_size = anonymous_size;
+ dlbaton = flbaton;
+ }
+ else
+ dlbaton = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwarf2_locexpr_baton);
+ dlbaton->data = data_member_location_attr->as_block ()->data;
+ dlbaton->size = data_member_location_attr->as_block ()->size;
/* When using this baton, we want to compute the address
of the field, not the value. This is why
is_reference is set to false here. */
@@ -9999,28 +10137,74 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
dlbaton->per_objfile = per_objfile;
dlbaton->per_cu = cu->per_cu;
- field->set_loc_dwarf_block (dlbaton);
+ field->set_loc_dwarf_block_addr (dlbaton);
}
}
else
- dwarf2_complex_location_expr_complaint ();
+ complaint (_("Unsupported form %s for DW_AT_data_member_location"),
+ dwarf_form_name (data_member_location_attr->form));
}
else
{
- attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
- if (attr != nullptr)
- field->set_loc_bitpos (attr->constant_value (0));
+ const auto data_bit_offset_attr
+ = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
+
+ if (data_bit_offset_attr != nullptr)
+ {
+ if (data_bit_offset_attr->form_is_constant ())
+ field->set_loc_bitpos (data_bit_offset_attr->unsigned_constant ()
+ .value_or (0));
+ else if (data_bit_offset_attr->form_is_block ())
+ {
+ /* This is a DWARF extension. See
+ https://dwarfstd.org/issues/250501.1.html. */
+ dwarf2_per_objfile *per_objfile = cu->per_objfile;
+ dwarf2_locexpr_baton *dlbaton
+ = OBSTACK_ZALLOC (&per_objfile->objfile->objfile_obstack,
+ dwarf2_locexpr_baton);
+ dlbaton->data = data_bit_offset_attr->as_block ()->data;
+ dlbaton->size = data_bit_offset_attr->as_block ()->size;
+ dlbaton->per_objfile = per_objfile;
+ dlbaton->per_cu = cu->per_cu;
+
+ field->set_loc_dwarf_block_bitpos (dlbaton);
+ }
+ else
+ complaint (_("Unsupported form %s for DW_AT_data_bit_offset"),
+ dwarf_form_name (data_bit_offset_attr->form));
+ }
}
}
+/* A helper that computes the location of a field. The CU and the
+ DW_TAG_member DIE are passed in. The results are stored in
+ *FP. */
+
+static void
+compute_field_location (dwarf2_cu *cu, die_info *die, field *fp)
+{
+ /* Get type of field. */
+ fp->set_type (die_type (die, cu));
+
+ fp->set_loc_bitpos (0);
+
+ /* Get bit size of field (zero if none). */
+ attribute *attr = dwarf2_attr (die, DW_AT_bit_size, cu);
+ if (attr != nullptr)
+ fp->set_bitsize (attr->unsigned_constant ().value_or (0));
+ else
+ fp->set_bitsize (0);
+
+ /* Get bit offset of field. */
+ handle_member_location (die, cu, fp);
+}
+
/* Add an aggregate field to the field list. */
static void
dwarf2_add_field (struct field_info *fip, struct die_info *die,
struct dwarf2_cu *cu)
{
- struct objfile *objfile = cu->per_objfile->objfile;
- struct gdbarch *gdbarch = objfile->arch ();
struct nextfield *new_field;
struct attribute *attr;
struct field *fp;
@@ -10070,64 +10254,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
}
/* Data member other than a C++ static data member. */
- /* Get type of field. */
- fp->set_type (die_type (die, cu));
-
- fp->set_loc_bitpos (0);
-
- /* Get bit size of field (zero if none). */
- attr = dwarf2_attr (die, DW_AT_bit_size, cu);
- if (attr != nullptr)
- fp->set_bitsize (attr->constant_value (0));
- else
- fp->set_bitsize (0);
-
- /* Get bit offset of field. */
- handle_member_location (die, cu, fp);
- attr = dwarf2_attr (die, DW_AT_bit_offset, cu);
- if (attr != nullptr && attr->form_is_constant ())
- {
- if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
- {
- /* For big endian bits, the DW_AT_bit_offset gives the
- additional bit offset from the MSB of the containing
- 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. */
- fp->set_loc_bitpos (fp->loc_bitpos () + attr->constant_value (0));
- }
- else
- {
- /* For little endian bits, compute the bit offset to the
- MSB of the anonymous object, subtract off the number of
- bits from the MSB of the field to the MSB of the
- object, and then subtract off the number of bits of
- the field itself. The result is the bit offset of
- the LSB of the field. */
- int anonymous_size;
- int bit_offset = attr->constant_value (0);
-
- attr = dwarf2_attr (die, DW_AT_byte_size, cu);
- if (attr != nullptr && attr->form_is_constant ())
- {
- /* The size of the anonymous object containing
- the bit field is explicit, so use the
- indicated size (in bytes). */
- anonymous_size = attr->constant_value (0);
- }
- else
- {
- /* The size of the anonymous object containing
- the bit field must be inferred from the type
- attribute of the data member containing the
- bit field. */
- anonymous_size = fp->type ()->length ();
- }
- fp->set_loc_bitpos (fp->loc_bitpos ()
- + anonymous_size * bits_per_byte
- - bit_offset - fp->bitsize ());
- }
- }
+ compute_field_location (cu, die, fp);
/* Get name of field. */
fieldname = dwarf2_name (die, cu);
@@ -10266,13 +10393,19 @@ convert_variant_range (struct obstack *obstack, const variant_field &variant,
{
std::vector<discriminant_range> ranges;
- if (variant.default_branch)
+ if (variant.is_default ())
return {};
if (variant.discr_list_data == nullptr)
{
- discriminant_range r
- = {variant.discriminant_value, variant.discriminant_value};
+ ULONGEST value;
+
+ if (is_unsigned)
+ value = variant.discriminant_attr->unsigned_constant ().value_or (0);
+ else
+ value = variant.discriminant_attr->signed_constant ().value_or (0);
+
+ discriminant_range r = { value, value };
ranges.push_back (r);
}
else
@@ -10342,14 +10475,16 @@ static const gdb::array_view<variant_part> create_variant_parts
the variant to fill in. OBSTACK is where any needed allocations
will be done. OFFSET_MAP holds the mapping from section offsets to
fields for the type. FI describes the fields of the type we're
- processing. FIELD is the variant field we're converting. */
+ processing. FIELD is the variant field we're converting. IS_UNSIGNED
+ contains the signedness of the discriminant. */
static void
create_one_variant (variant &result, struct obstack *obstack,
const offset_map_type &offset_map,
- struct field_info *fi, const variant_field &field)
+ struct field_info *fi, const variant_field &field,
+ bool is_unsigned)
{
- result.discriminants = convert_variant_range (obstack, field, false);
+ result.discriminants = convert_variant_range (obstack, field, is_unsigned);
result.first_field = field.first_field + fi->baseclasses.size ();
result.last_field = field.last_field + fi->baseclasses.size ();
result.parts = create_variant_parts (obstack, offset_map, fi,
@@ -10388,7 +10523,7 @@ create_one_variant_part (variant_part &result,
variant *output = new (obstack) variant[n];
for (size_t i = 0; i < n; ++i)
create_one_variant (output[i], obstack, offset_map, fi,
- builder.variants[i]);
+ builder.variants[i], result.is_unsigned);
result.variants = gdb::array_view<variant> (output, n);
}
@@ -10569,7 +10704,6 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
smash_to_method_type (fnp->type, type,
this_type->target_type (),
this_type->fields (),
- this_type->num_fields (),
this_type->has_varargs ());
/* Handle static member functions.
@@ -10791,8 +10925,7 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
self_type = pfn_type->field (0).type ()->target_type ();
new_type = type_allocator (type).new_type ();
smash_to_method_type (new_type, self_type, pfn_type->target_type (),
- pfn_type->fields (), pfn_type->num_fields (),
- pfn_type->has_varargs ());
+ pfn_type->fields (), pfn_type->has_varargs ());
smash_to_methodptr_type (type, new_type);
}
@@ -11086,7 +11219,7 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
if (attr != nullptr)
{
if (attr->form_is_constant ())
- type->set_length (attr->constant_value (0));
+ type->set_length (attr->unsigned_constant ().value_or (0));
else
{
struct dynamic_prop prop;
@@ -11097,7 +11230,27 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
}
}
else
- type->set_length (0);
+ {
+ attr = dwarf2_attr (die, DW_AT_bit_size, cu);
+ if (attr != nullptr)
+ {
+ if (attr->form_is_constant ())
+ {
+ ULONGEST len = attr->unsigned_constant ().value_or (0);
+ type->set_length (align_up (len, 8) / 8);
+ }
+ else
+ {
+ struct dynamic_prop prop;
+ if (attr_to_dynamic_prop (attr, die, cu, &prop, cu->addr_type ()))
+ type->add_dyn_prop (DYN_PROP_BIT_SIZE, prop);
+
+ type->set_length (0);
+ }
+ }
+ else
+ type->set_length (0);
+ }
maybe_set_alignment (cu, die, type);
@@ -11231,12 +11384,14 @@ handle_variant (struct die_info *die, struct type *type,
{
discr = dwarf2_attr (die, DW_AT_discr_list, cu);
if (discr == nullptr || discr->as_block ()->size == 0)
- variant.default_branch = true;
+ {
+ /* Nothing to do here -- default branch. */
+ }
else
variant.discr_list_data = discr->as_block ();
}
else
- variant.discriminant_value = discr->constant_value (0);
+ variant.discriminant_attr = discr;
for (die_info *variant_child : die->children ())
handle_struct_member_die (variant_child, type, fi, template_args, cu);
@@ -11298,6 +11453,21 @@ handle_struct_member_die (struct die_info *child_die, struct type *type,
handle_variant (child_die, type, fi, template_args, cu);
}
+/* Create a property baton for a field. DIE is the field's DIE. The
+ baton's "field" member is filled in, but the other members of the
+ baton are not. The new property baton is returned. */
+
+static dwarf2_property_baton *
+find_field_create_baton (dwarf2_cu *cu, die_info *die)
+{
+ dwarf2_property_baton *result
+ = XOBNEW (&cu->per_objfile->objfile->objfile_obstack,
+ struct dwarf2_property_baton);
+ memset (&result->field, 0, sizeof (result->field));
+ compute_field_location (cu, die, &result->field);
+ return result;
+}
+
/* 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
@@ -11531,11 +11701,11 @@ die_byte_order (die_info *die, dwarf2_cu *cu, enum bfd_endian *byte_order)
attribute *attr = dwarf2_attr (die, DW_AT_endianity, cu);
if (attr != nullptr && attr->form_is_constant ())
{
- std::optional<ULONGEST> endianity = attr->unsigned_constant ();
+ std::optional<ULONGEST> endianness = attr->unsigned_constant ();
- if (endianity.has_value ())
+ if (endianness.has_value ())
{
- switch (*endianity)
+ switch (*endianness)
{
case DW_END_default:
/* Nothing. */
@@ -11548,7 +11718,7 @@ die_byte_order (die_info *die, dwarf2_cu *cu, enum bfd_endian *byte_order)
break;
default:
complaint (_("DW_AT_endianity has unrecognized value %s"),
- pulongest (*endianity));
+ pulongest (*endianness));
break;
}
}
@@ -11562,25 +11732,30 @@ die_byte_order (die_info *die, dwarf2_cu *cu, enum bfd_endian *byte_order)
/* Assuming DIE is an enumeration type, and TYPE is its associated
type, update TYPE using some information only available in DIE's
- children. In particular, the fields are computed. */
+ children. In particular, the fields are computed. If IS_UNSIGNED
+ is set, the enumeration type's sign is already known (a true value
+ means unsigned), and so examining the constants to determine the
+ sign isn't needed; when this is unset, the enumerator constants are
+ read as signed values. */
static void
update_enumeration_type_from_children (struct die_info *die,
struct type *type,
- struct dwarf2_cu *cu)
+ struct dwarf2_cu *cu,
+ std::optional<bool> is_unsigned)
{
- int unsigned_enum = 1;
- int flag_enum = 1;
+ /* This is used to check whether the enum is signed or unsigned; for
+ simplicity, it is always correct regardless of whether
+ IS_UNSIGNED is set. */
+ bool unsigned_enum = is_unsigned.value_or (true);
+ bool flag_enum = true;
- auto_obstack obstack;
std::vector<struct field> fields;
for (die_info *child_die : die->children ())
{
struct attribute *attr;
LONGEST value;
- const gdb_byte *bytes;
- struct dwarf2_locexpr_baton *baton;
const char *name;
if (child_die->tag != DW_TAG_enumerator)
@@ -11594,19 +11769,26 @@ update_enumeration_type_from_children (struct die_info *die,
if (name == NULL)
name = "<anonymous enumerator>";
- dwarf2_const_value_attr (attr, type, name, &obstack, cu,
- &value, &bytes, &baton);
- if (value < 0)
- {
- unsigned_enum = 0;
- flag_enum = 0;
- }
+ /* Can't check UNSIGNED_ENUM here because that is
+ optimistic. */
+ if (is_unsigned.has_value () && *is_unsigned)
+ value = attr->unsigned_constant ().value_or (0);
else
{
- if (count_one_bits_ll (value) >= 2)
- flag_enum = 0;
+ /* Read as signed, either because we don't know the sign or
+ because we know it is definitely signed. */
+ value = attr->signed_constant ().value_or (0);
+
+ if (value < 0)
+ {
+ unsigned_enum = false;
+ flag_enum = false;
+ }
}
+ if (flag_enum && count_one_bits_ll (value) >= 2)
+ flag_enum = false;
+
struct field &field = fields.emplace_back ();
field.set_name (dwarf2_physname (name, child_die, cu));
field.set_loc_enumval (value);
@@ -11615,13 +11797,10 @@ update_enumeration_type_from_children (struct die_info *die,
if (!fields.empty ())
type->copy_fields (fields);
else
- flag_enum = 0;
-
- if (unsigned_enum)
- type->set_is_unsigned (true);
+ flag_enum = false;
- if (flag_enum)
- type->set_is_flag_enum (true);
+ type->set_is_unsigned (unsigned_enum);
+ type->set_is_flag_enum (flag_enum);
}
/* Given a DW_AT_enumeration_type die, set its type. We do not
@@ -11665,7 +11844,7 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr != nullptr)
- type->set_length (attr->constant_value (0));
+ type->set_length (attr->unsigned_constant ().value_or (0));
else
type->set_length (0);
@@ -11679,6 +11858,11 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
if (die_is_declaration (die, cu))
type->set_is_stub (true);
+ /* If the underlying type is known, and is unsigned, then we'll
+ assume the enumerator constants are unsigned. Otherwise we have
+ to assume they are signed. */
+ std::optional<bool> is_unsigned;
+
/* If this type has an underlying type that is not a stub, then we
may use its attributes. We always use the "unsigned" attribute
in this situation, because ordinarily we guess whether the type
@@ -11691,7 +11875,8 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
struct type *underlying_type = type->target_type ();
underlying_type = check_typedef (underlying_type);
- type->set_is_unsigned (underlying_type->is_unsigned ());
+ is_unsigned = underlying_type->is_unsigned ();
+ type->set_is_unsigned (*is_unsigned);
if (type->length () == 0)
type->set_length (underlying_type->length ());
@@ -11711,7 +11896,7 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
Note that, as usual, this must come after set_die_type to avoid
infinite recursion when trying to compute the names of the
enumerators. */
- update_enumeration_type_from_children (die, type, cu);
+ update_enumeration_type_from_children (die, type, cu, is_unsigned);
return type;
}
@@ -11752,7 +11937,7 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
actually available. Note that we do not want to do this for all
enums which are just declarations, because C++0x allows forward
enum declarations. */
- if (cu->per_cu->is_debug_types
+ if (cu->per_cu->is_debug_types ()
&& die_is_declaration (die, cu))
{
struct signatured_type *sig_type;
@@ -12061,14 +12246,14 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
attr = dwarf2_attr (die, DW_AT_bit_stride, cu);
if (attr != NULL)
- bit_stride = attr->constant_value (0);
+ bit_stride = attr->unsigned_constant ().value_or (0);
/* Irix 6.2 native cc creates array types without children for
arrays with unspecified length. */
if (die->child == NULL)
{
- index_type = builtin_type (objfile)->builtin_int;
type_allocator alloc (objfile, cu->lang ());
+ index_type = alloc.copy_type (builtin_type (objfile)->builtin_int);
range_type = create_static_range_type (alloc, index_type, 0, -1);
type = create_array_type_with_stride (alloc, element_type, range_type,
byte_stride_prop, bit_stride);
@@ -12276,7 +12461,8 @@ mark_common_block_symbol_computed (struct symbol *sym,
gdb_assert (member_loc->form_is_block ()
|| member_loc->form_is_constant ());
- baton = XOBNEW (&objfile->objfile_obstack, struct dwarf2_locexpr_baton);
+ baton = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwarf2_locexpr_baton);
baton->per_objfile = per_objfile;
baton->per_cu = cu->per_cu;
gdb_assert (baton->per_cu);
@@ -12285,7 +12471,7 @@ mark_common_block_symbol_computed (struct symbol *sym,
if (member_loc->form_is_constant ())
{
- offset = member_loc->constant_value (0);
+ offset = member_loc->unsigned_constant ().value_or (0);
baton->size += 1 /* DW_OP_addr */ + cu->header.addr_size;
}
else
@@ -12295,7 +12481,7 @@ mark_common_block_symbol_computed (struct symbol *sym,
baton->data = ptr;
*ptr++ = DW_OP_call4;
- cu_off = common_die->sect_off - cu->per_cu->sect_off;
+ cu_off = common_die->sect_off - cu->per_cu->sect_off ();
store_unsigned_integer (ptr, 4, byte_order, cu_off);
ptr += 4;
@@ -12318,7 +12504,7 @@ mark_common_block_symbol_computed (struct symbol *sym,
gdb_assert (ptr - baton->data == baton->size);
SYMBOL_LOCATION_BATON (sym) = baton;
- sym->set_aclass_index (dwarf2_locexpr_index);
+ sym->set_loc_class_index (dwarf2_locexpr_index);
}
/* Create appropriate locally-scoped variables for all the
@@ -12411,7 +12597,9 @@ read_common_block (struct die_info *die, struct dwarf2_cu *cu)
}
}
- sym = new_symbol (die, builtin_type (objfile)->builtin_void, cu);
+ type_allocator alloc (objfile, cu->lang ());
+ type *void_type = alloc.copy_type (builtin_type (objfile)->builtin_void);
+ sym = new_symbol (die, void_type, cu);
sym->set_value_common_block (common_block);
}
}
@@ -12575,6 +12763,75 @@ namespace_name (struct die_info *die, int *is_anonymous, struct dwarf2_cu *cu)
return name;
}
+/* A convenience structure that holds a CU and a DIE. */
+
+struct cu_die_pair
+{
+ die_info *die;
+ dwarf2_cu *cu;
+
+ /* Return true if this object holds a valid DIE. */
+ bool valid () const
+ {
+ return die != nullptr;
+ }
+
+ /* Compare two cu_die_pair objects. */
+ bool operator!= (const cu_die_pair &other) const
+ {
+ return die != other.die || cu != other.cu;
+ }
+};
+
+/* Follow the DW_AT_type reference, if any, from ORIG. The return
+ value will be valid only when DW_AT_type exists. In other cases,
+ including when the incoming ORIG is not valid, an invalid
+ cu_die_pair is returned. */
+
+static cu_die_pair
+follow_type (cu_die_pair orig)
+{
+ /* This simplifies the caller a little. */
+ if (!orig.valid ())
+ return {};
+
+ attribute *type_attr = dwarf2_attr (orig.die, DW_AT_type, orig.cu);
+ if (type_attr == nullptr || !type_attr->form_is_ref ())
+ return {};
+
+ cu_die_pair result = orig;
+ sect_offset sect_off = type_attr->get_ref_die_offset ();
+ const dwarf2_section_info &section = get_section_for_ref (*type_attr,
+ orig.cu);
+ result.die = follow_die_offset ({ &section, sect_off }, &result.cu);
+
+ /* Note that we do not check for DW_TAG_pointer_type here. GNAT, at
+ least, will emit recursive pointers that "indirect" via typedefs,
+ so checkpoint purely for pointer types would not find these. */
+ return result;
+}
+
+/* Return true if DIE is a self-referential pointer type; false
+ otherwise. CU is the origin of DIE. */
+
+static bool
+is_recursive_pointer (die_info *die, dwarf2_cu *cu)
+{
+ cu_die_pair tortoise { die, cu };
+ gdb_assert (tortoise.valid ());
+ cu_die_pair hare = follow_type (tortoise);
+
+ while (tortoise != hare)
+ {
+ tortoise = follow_type (tortoise);
+ hare = follow_type (follow_type (hare));
+ if (!tortoise.valid () || !hare.valid ())
+ return false;
+ }
+
+ return true;
+}
+
/* Extract all information from a DW_TAG_pointer_type DIE and add to
the user defined type vector. */
@@ -12582,14 +12839,24 @@ static struct type *
read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct gdbarch *gdbarch = cu->per_objfile->objfile->arch ();
- struct comp_unit_head *cu_header = &cu->header;
+ unit_head *cu_header = &cu->header;
struct type *type;
struct attribute *attr_byte_size;
struct attribute *attr_address_class;
int byte_size;
struct type *target_type;
- target_type = die_type (die, cu);
+ /* In Ada, it's possible to create a self-referential pointer type.
+ These aren't useful, but nevertheless we take care to avoid a gdb
+ crash in this situation. Instead just turn these into a
+ pointer-to-void. */
+ if (is_recursive_pointer (die, cu))
+ {
+ type_allocator alloc (cu->per_objfile->objfile, cu->lang ());
+ target_type = alloc.new_type (TYPE_CODE_VOID, 0, nullptr);
+ }
+ else
+ target_type = die_type (die, cu);
/* The die_type call above may have already set the type for this DIE. */
type = get_die_type (die, cu);
@@ -12600,7 +12867,8 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
attr_byte_size = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr_byte_size)
- byte_size = attr_byte_size->constant_value (cu_header->addr_size);
+ byte_size = (attr_byte_size->unsigned_constant ()
+ .value_or (cu_header->addr_size));
else
byte_size = cu_header->addr_size;
@@ -12679,8 +12947,7 @@ read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu)
= type_allocator (cu->per_objfile->objfile, cu->lang ()).new_type ();
smash_to_method_type (new_type, domain, to_type->target_type (),
- to_type->fields (), to_type->num_fields (),
- to_type->has_varargs ());
+ to_type->fields (), to_type->has_varargs ());
type = lookup_methodptr_type (new_type);
}
else
@@ -12696,7 +12963,7 @@ static struct type *
read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu,
enum type_code refcode)
{
- struct comp_unit_head *cu_header = &cu->header;
+ unit_head *cu_header = &cu->header;
struct type *type, *target_type;
struct attribute *attr;
@@ -12712,7 +12979,8 @@ read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu,
type = lookup_reference_type (target_type, refcode);
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr != nullptr)
- type->set_length (attr->constant_value (cu_header->addr_size));
+ type->set_length (attr->unsigned_constant ()
+ .value_or (cu_header->addr_size));
else
type->set_length (cu_header->addr_size);
@@ -12876,10 +13144,10 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
len = dwarf2_attr (die, DW_AT_byte_size, cu);
if (len != nullptr && len->form_is_constant ())
{
- /* 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);
+ LONGEST sz = len->unsigned_constant ().value_or (0);
prop_type = objfile_int_type (objfile, sz, true);
+ type_allocator alloc (objfile, cu->lang ());
+ prop_type = alloc.copy_type (prop_type);
}
else
{
@@ -12897,15 +13165,14 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
else if (attr != nullptr)
{
/* This DW_AT_string_length just contains the length with no
- indirection. There's no need to create a dynamic property in this
- case. Pass 0 for the default value as we know it will not be
- returned in this case. */
- length = attr->constant_value (0);
+ indirection. There's no need to create a dynamic property in
+ this case. */
+ length = attr->unsigned_constant ().value_or (0);
}
else if ((attr = dwarf2_attr (die, DW_AT_byte_size, cu)) != nullptr)
{
/* We don't currently support non-constant byte sizes for strings. */
- length = attr->constant_value (1);
+ length = attr->unsigned_constant ().value_or (1);
}
else
{
@@ -12913,8 +13180,8 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
length = 1;
}
- index_type = builtin_type (objfile)->builtin_int;
type_allocator alloc (objfile, cu->lang ());
+ index_type = alloc.copy_type (builtin_type (objfile)->builtin_int);
if (length_is_constant)
range_type = create_static_range_type (alloc, index_type, 1, length);
else
@@ -13036,7 +13303,9 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
if (die->child != NULL)
{
- struct type *void_type = builtin_type (objfile)->builtin_void;
+ type_allocator alloc (objfile, cu->lang ());
+ struct type *void_type
+ = alloc.copy_type (builtin_type (objfile)->builtin_void);
int nparams, iparams;
/* Count the number of parameters.
@@ -13180,7 +13449,7 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu)
a given gmp_mpz given an attribute. */
static void
-get_mpz (struct dwarf2_cu *cu, gdb_mpz *value, struct attribute *attr)
+get_mpz_for_rational (dwarf2_cu *cu, gdb_mpz *value, attribute *attr)
{
/* GCC will sometimes emit a 16-byte constant value as a DWARF
location expression that pushes an implicit value. */
@@ -13214,10 +13483,11 @@ get_mpz (struct dwarf2_cu *cu, gdb_mpz *value, struct attribute *attr)
? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE,
true);
}
- else if (attr->form_is_unsigned ())
- *value = gdb_mpz (attr->as_unsigned ());
else
- *value = gdb_mpz (attr->constant_value (1));
+ {
+ /* Rational constants for Ada are always unsigned. */
+ *value = gdb_mpz (attr->unsigned_constant ().value_or (1));
+ }
}
/* Assuming DIE is a rational DW_TAG_constant, read the DIE's
@@ -13246,8 +13516,8 @@ get_dwarf2_rational_constant (struct die_info *die, struct dwarf2_cu *cu,
if (num_attr == nullptr || denom_attr == nullptr)
return;
- get_mpz (cu, numerator, num_attr);
- get_mpz (cu, denominator, denom_attr);
+ get_mpz_for_rational (cu, numerator, num_attr);
+ get_mpz_for_rational (cu, denominator, denom_attr);
}
/* Same as get_dwarf2_rational_constant, but extracting an unsigned
@@ -13303,7 +13573,7 @@ ada_get_gnat_encoded_number (const char *encoding, int &k, gdb_mpz *result)
{
/* The next character should be an underscore ('_') followed
by a digit. */
- if (encoding[k] != '_' || !isdigit (encoding[k + 1]))
+ if (encoding[k] != '_' || !c_isdigit (encoding[k + 1]))
return false;
/* Skip the underscore. */
@@ -13311,7 +13581,7 @@ ada_get_gnat_encoded_number (const char *encoding, int &k, gdb_mpz *result)
int start = k;
/* Determine the number of digits for our number. */
- while (isdigit (encoding[k]))
+ while (c_isdigit (encoding[k]))
k++;
if (k == start)
return false;
@@ -13396,14 +13666,14 @@ finish_fixed_point_type (struct type *type, const char *suffix,
}
else if (attr->name == DW_AT_binary_scale)
{
- LONGEST scale_exp = attr->constant_value (0);
+ LONGEST scale_exp = attr->signed_constant ().value_or (0);
gdb_mpz &num_or_denom = scale_exp > 0 ? scale_num : scale_denom;
num_or_denom <<= std::abs (scale_exp);
}
else if (attr->name == DW_AT_decimal_scale)
{
- LONGEST scale_exp = attr->constant_value (0);
+ LONGEST scale_exp = attr->signed_constant ().value_or (0);
gdb_mpz &num_or_denom = scale_exp > 0 ? scale_num : scale_denom;
num_or_denom = gdb_mpz::pow (10, std::abs (scale_exp));
@@ -13482,14 +13752,12 @@ dwarf2_init_integer_type (struct dwarf2_cu *cu, int bits, int unsigned_p,
/* Versions of Intel's C Compiler generate an integer type called "void"
instead of using DW_TAG_unspecified_type. This has been seen on
at least versions 14, 17, and 18. */
+ type_allocator alloc (objfile, cu->lang ());
if (bits == 0 && cu->producer_is_icc () && name != nullptr
&& strcmp (name, "void") == 0)
- type = builtin_type (objfile)->builtin_void;
+ type = alloc.copy_type (builtin_type (objfile)->builtin_void);
else
- {
- type_allocator alloc (objfile, cu->lang ());
- type = init_integer_type (alloc, bits, unsigned_p, name);
- }
+ type = init_integer_type (alloc, bits, unsigned_p, name);
return type;
}
@@ -13603,7 +13871,6 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
struct type *type;
struct attribute *attr;
ULONGEST encoding = 0;
- int bits = 0;
const char *name;
attr = dwarf2_attr (die, DW_AT_encoding, cu);
@@ -13613,9 +13880,33 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
if (value.has_value ())
encoding = *value;
}
+
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
+ std::optional<ULONGEST> byte_size;
+ if (attr != nullptr)
+ byte_size = attr->unsigned_constant ();
+ attr = dwarf2_attr (die, DW_AT_bit_size, cu);
+ std::optional<ULONGEST> bit_size;
if (attr != nullptr)
- bits = attr->constant_value (0) * TARGET_CHAR_BIT;
+ bit_size = attr->unsigned_constant ();
+
+ attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
+ std::optional<ULONGEST> bit_offset;
+ if (attr != nullptr)
+ bit_offset = attr->unsigned_constant ();
+
+ int bits = 0;
+ if (byte_size.has_value ())
+ bits = TARGET_CHAR_BIT * *byte_size;
+ else if (bit_size.has_value ())
+ bits = align_up (*bit_size, 8);
+ else
+ {
+ /* No size, so arrange for an error type. */
+ complaint (_("DW_TAG_base_type has neither bit- nor byte-size"));
+ encoding = (ULONGEST) -1;
+ }
+
name = dwarf2_full_name (nullptr, die, cu);
if (!name)
complaint (_("DW_AT_name missing from DW_TAG_base_type"));
@@ -13761,29 +14052,21 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
type->set_endianity_is_not_default (not_default);
- if (TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_INT)
+ /* If both a byte size and bit size were provided, then that means
+ that not every bit in the object contributes to the value. */
+ if (TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_INT
+ && byte_size.has_value ()
+ && bit_size.has_value ())
{
- attr = dwarf2_attr (die, DW_AT_bit_size, cu);
- if (attr != nullptr && attr->form_is_constant ())
+ /* DWARF says: If this attribute is omitted a default data bit
+ offset of zero is assumed. */
+ ULONGEST offset = bit_offset.value_or (0);
+
+ /* Only use the attributes if they make sense together. */
+ if (*bit_size + offset <= 8 * type->length ())
{
- unsigned real_bit_size = attr->constant_value (0);
- if (real_bit_size >= 0 && real_bit_size <= 8 * type->length ())
- {
- attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
- /* Only use the attributes if they make sense together. */
- if (attr == nullptr
- || (attr->form_is_constant ()
- && attr->constant_value (0) >= 0
- && (attr->constant_value (0) + real_bit_size
- <= 8 * type->length ())))
- {
- TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_size
- = real_bit_size;
- if (attr != nullptr)
- TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_offset
- = attr->constant_value (0);
- }
- }
+ TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_size = *bit_size;
+ TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_offset = offset;
}
}
@@ -13924,17 +14207,13 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
case DW_AT_data_member_location:
case DW_AT_data_bit_offset:
{
- LONGEST offset;
-
- if (!handle_member_location (target_die, target_cu, &offset))
+ baton = find_field_create_baton (cu, target_die);
+ if (baton == nullptr)
return 0;
- baton = XOBNEW (obstack, struct dwarf2_property_baton);
baton->property_type = read_type_die (target_die->parent,
- target_cu);
- baton->offset_info.offset = offset;
- baton->offset_info.type = die_type (target_die, target_cu);
- prop->set_addr_offset (baton);
+ target_cu);
+ prop->set_field (baton);
break;
}
}
@@ -14094,8 +14373,13 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
LONGEST bias = 0;
struct attribute *bias_attr = dwarf2_attr (die, DW_AT_GNU_bias, cu);
- if (bias_attr != nullptr && bias_attr->form_is_constant ())
- bias = bias_attr->constant_value (0);
+ if (bias_attr != nullptr)
+ {
+ if (base_type->is_unsigned ())
+ bias = (LONGEST) bias_attr->unsigned_constant ().value_or (0);
+ else
+ bias = bias_attr->signed_constant ().value_or (0);
+ }
/* Normally, the DWARF producers are expected to use a signed
constant form (Eg. DW_FORM_sdata) to express negative bounds.
@@ -14182,7 +14466,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr != nullptr)
- range_type->set_length (attr->constant_value (0));
+ range_type->set_length (attr->unsigned_constant ().value_or (0));
maybe_set_alignment (cu, die, range_type);
@@ -14391,8 +14675,8 @@ cutu_reader::read_toplevel_die (gdb::array_view<attribute *> extra_attrs)
return die;
}
-struct compunit_symtab *
-cooked_index_functions::find_compunit_symtab_by_address
+struct symbol *
+cooked_index_functions::find_symbol_by_address
(struct objfile *objfile, CORE_ADDR address)
{
if (objfile->sect_index_data == -1)
@@ -14407,25 +14691,28 @@ cooked_index_functions::find_compunit_symtab_by_address
if (per_cu == nullptr)
return nullptr;
- return dw2_instantiate_symtab (per_cu, per_objfile, false);
+ struct compunit_symtab *cu = dw2_instantiate_symtab (per_cu, per_objfile,
+ false);
+ return cu->symbol_at_address (address);
}
bool
-cooked_index_functions::expand_symtabs_matching
+cooked_index_functions::search
(objfile *objfile,
- expand_symtabs_file_matcher file_matcher,
+ search_symtabs_file_matcher file_matcher,
const lookup_name_info *lookup_name,
- expand_symtabs_symbol_matcher symbol_matcher,
- expand_symtabs_expansion_listener expansion_notify,
+ search_symtabs_symbol_matcher symbol_matcher,
+ search_symtabs_expansion_listener listener,
block_search_flags search_flags,
domain_search_flags domain,
- expand_symtabs_lang_matcher lang_matcher)
+ search_symtabs_lang_matcher lang_matcher)
{
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
cooked_index *table = wait (objfile, true);
- dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
+ auto_bool_vector cus_to_skip;
+ dw_search_file_matcher (per_objfile, cus_to_skip, file_matcher);
/* This invariant is documented in quick-functions.h. */
gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr);
@@ -14435,10 +14722,8 @@ cooked_index_functions::expand_symtabs_matching
{
QUIT;
- if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
- file_matcher,
- expansion_notify,
- lang_matcher))
+ if (!dw2_search_one (per_cu, per_objfile, cus_to_skip, file_matcher,
+ listener, lang_matcher))
return false;
}
return true;
@@ -14513,13 +14798,8 @@ cooked_index_functions::expand_symtabs_matching
{
QUIT;
- /* 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->mark)
+ /* We don't need to consider symbols from some CUs. */
+ if (cus_to_skip.is_set (entry->per_cu->index))
continue;
/* See if the symbol matches the type filter. */
@@ -14536,13 +14816,26 @@ cooked_index_functions::expand_symtabs_matching
continue;
}
+ /* This is a bit of a hack to support .gdb_index. Since
+ .gdb_index does not record languages, and since we want
+ to know the language to avoid excessive CU expansion due
+ to false matches, if we see a symbol with an unknown
+ language we find the CU's language. Only the .gdb_index
+ reader creates such symbols. */
+ enum language entry_lang = entry->lang;
+ if (entry_lang == language_unknown)
+ {
+ entry->per_cu->ensure_lang (per_objfile);
+ entry_lang = entry->per_cu->lang ();
+ }
+
/* 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->get_parent ();
- const language_defn *lang_def = language_def (entry->lang);
+ const language_defn *lang_def = language_def (entry_lang);
for (int i = name_vec.size () - 1; i > 0; --i)
{
/* If we ran out of entries, or if this segment doesn't
@@ -14552,17 +14845,15 @@ cooked_index_functions::expand_symtabs_matching
found = false;
break;
}
- if (parent->lang != language_unknown)
+
+ symbol_name_matcher_ftype *name_matcher
+ = (lang_def->get_symbol_name_matcher
+ (segment_lookup_names[i-1]));
+ if (!name_matcher (parent->canonical,
+ segment_lookup_names[i-1], nullptr))
{
- symbol_name_matcher_ftype *name_matcher
- = lang_def->get_symbol_name_matcher
- (segment_lookup_names[i-1]);
- if (!name_matcher (parent->canonical,
- segment_lookup_names[i-1], nullptr))
- {
- found = false;
- break;
- }
+ found = false;
+ break;
}
parent = parent->get_parent ();
@@ -14585,27 +14876,23 @@ cooked_index_functions::expand_symtabs_matching
seems like the loop above could just examine every
element of the name, avoiding the need to check here; but
this is hard. See PR symtab/32733. */
- if (symbol_matcher != nullptr || entry->lang != language_unknown)
+ auto_obstack temp_storage;
+ const char *full_name = entry->full_name (&temp_storage,
+ FOR_ADA_LINKAGE_NAME);
+ if (symbol_matcher == nullptr)
{
- auto_obstack temp_storage;
- const char *full_name = entry->full_name (&temp_storage,
- FOR_ADA_LINKAGE_NAME);
- if (symbol_matcher == nullptr)
- {
- symbol_name_matcher_ftype *name_matcher
- = (lang_def->get_symbol_name_matcher
- (lookup_name_without_params));
- if (!name_matcher (full_name, lookup_name_without_params,
- nullptr))
- continue;
- }
- else if (!symbol_matcher (full_name))
+ symbol_name_matcher_ftype *name_matcher
+ = (lang_def->get_symbol_name_matcher
+ (lookup_name_without_params));
+ if (!name_matcher (full_name, lookup_name_without_params,
+ nullptr))
continue;
}
+ else if (!symbol_matcher (full_name))
+ continue;
- if (!dw2_expand_symtabs_matching_one (entry->per_cu, per_objfile,
- file_matcher,
- expansion_notify, nullptr))
+ if (!dw2_search_one (entry->per_cu, per_objfile, cus_to_skip,
+ file_matcher, listener, nullptr))
return false;
}
}
@@ -14863,7 +15150,7 @@ cutu_reader::read_attribute_value (attribute *attr, unsigned form,
{
dwarf2_per_objfile *per_objfile = m_cu->per_objfile;
struct objfile *objfile = per_objfile->objfile;
- struct comp_unit_head *cu_header = &m_cu->header;
+ unit_head *cu_header = &m_cu->header;
unsigned int bytes_read;
struct dwarf_block *blk;
@@ -14914,10 +15201,12 @@ cutu_reader::read_attribute_value (attribute *attr, unsigned form,
info_ptr += 2;
break;
case DW_FORM_data4:
+ case DW_FORM_ref_sup4:
attr->set_unsigned (read_4_bytes (m_abfd, info_ptr));
info_ptr += 4;
break;
case DW_FORM_data8:
+ case DW_FORM_ref_sup8:
attr->set_unsigned (read_8_bytes (m_abfd, info_ptr));
info_ptr += 8;
break;
@@ -14948,7 +15237,7 @@ cutu_reader::read_attribute_value (attribute *attr, unsigned form,
info_ptr += bytes_read;
break;
case DW_FORM_strp:
- if (!m_cu->per_cu->is_dwz)
+ if (!m_cu->per_cu->is_dwz ())
{
attr->set_string_noncanonical (read_indirect_string (per_objfile,
m_abfd, info_ptr,
@@ -14959,7 +15248,7 @@ cutu_reader::read_attribute_value (attribute *attr, unsigned form,
}
[[fallthrough]];
case DW_FORM_line_strp:
- if (!m_cu->per_cu->is_dwz)
+ if (!m_cu->per_cu->is_dwz ())
{
attr->set_string_noncanonical
(per_objfile->read_line_string (info_ptr, cu_header,
@@ -14969,6 +15258,7 @@ cutu_reader::read_attribute_value (attribute *attr, unsigned form,
}
[[fallthrough]];
case DW_FORM_GNU_strp_alt:
+ case DW_FORM_strp_sup:
{
dwz_file *dwz = per_objfile->per_bfd->get_dwz_file (true);
LONGEST str_offset
@@ -15118,7 +15408,7 @@ cutu_reader::read_attribute_value (attribute *attr, unsigned form,
}
/* Super hack. */
- if (m_cu->per_cu->is_dwz && attr->form_is_ref ())
+ if (m_cu->per_cu->is_dwz () && attr->form_is_ref ())
attr->form = DW_FORM_GNU_ref_alt;
/* We have seen instances where the compiler tried to emit a byte
@@ -15168,8 +15458,7 @@ read_indirect_string_at_offset (dwarf2_per_objfile *per_objfile,
static const char *
read_indirect_string (dwarf2_per_objfile *per_objfile, bfd *abfd,
- const gdb_byte *buf,
- const struct comp_unit_head *cu_header,
+ const gdb_byte *buf, const unit_head *cu_header,
unsigned int *bytes_read_ptr)
{
LONGEST str_offset = cu_header->read_offset (abfd, buf, bytes_read_ptr);
@@ -15193,7 +15482,7 @@ dwarf2_per_objfile::read_line_string (const gdb_byte *buf,
const char *
dwarf2_per_objfile::read_line_string (const gdb_byte *buf,
- const struct comp_unit_head *cu_header,
+ const unit_head *cu_header,
unsigned int *bytes_read_ptr)
{
bfd *abfd = objfile->obfd.get ();
@@ -15326,9 +15615,16 @@ read_str_index (struct dwarf2_cu *cu,
" in CU at offset %s [in module %s]"),
form_name, str_section->get_name (),
sect_offset_str (cu->header.sect_off), objf_name);
- info_ptr = (str_offsets_section->buffer
- + str_offsets_base
- + str_index * offset_size);
+
+ ULONGEST str_offsets_offset = str_offsets_base + str_index * offset_size;
+ if (str_offsets_offset >= str_offsets_section->size)
+ error (_(DWARF_ERROR_PREFIX
+ "Offset from %s pointing outside of %s section in CU at offset %s"
+ " [in module %s]"),
+ form_name, str_offsets_section->get_name (),
+ sect_offset_str (cu->header.sect_off), objf_name);
+ info_ptr = str_offsets_section->buffer + str_offsets_offset;
+
if (offset_size == 4)
str_offset = bfd_get_32 (abfd, info_ptr);
else
@@ -15641,9 +15937,9 @@ die_specification (struct die_info *die, struct dwarf2_cu **spec_cu)
return follow_die_ref (die, spec_attr, spec_cu);
}
-/* A convenience function to find the proper .debug_line section for a CU. */
+/* See dwarf2/read.h. */
-static struct dwarf2_section_info *
+struct dwarf2_section_info *
get_debug_line_section (struct dwarf2_cu *cu)
{
struct dwarf2_section_info *section;
@@ -15651,9 +15947,9 @@ get_debug_line_section (struct dwarf2_cu *cu)
/* For TUs in DWO files, the DW_AT_stmt_list attribute lives in the
DWO file. */
- if (cu->dwo_unit && cu->per_cu->is_debug_types)
+ if (cu->dwo_unit && cu->per_cu->is_debug_types ())
section = &cu->dwo_unit->dwo_file->sections.line;
- else if (cu->per_cu->is_dwz)
+ else if (cu->per_cu->is_dwz ())
section = &per_objfile->per_bfd->get_dwz_file (true)->line;
else
section = &per_objfile->per_bfd->line;
@@ -15682,820 +15978,21 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu,
section->read (per_objfile->objfile);
if (section->buffer == NULL)
{
- if (cu->dwo_unit && cu->per_cu->is_debug_types)
+ if (cu->dwo_unit && cu->per_cu->is_debug_types ())
complaint (_("missing .debug_line.dwo section"));
else
complaint (_("missing .debug_line section"));
return 0;
}
- return dwarf_decode_line_header (sect_off, cu->per_cu->is_dwz,
+ return dwarf_decode_line_header (sect_off, cu->per_cu->is_dwz (),
per_objfile, section, &cu->header,
comp_dir);
}
-/* Subroutine of dwarf_decode_lines to simplify it.
- 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
- equivalent to CU_INFO. */
-
-static const char *
-compute_include_file_name (const struct line_header *lh, const file_entry &fe,
- const file_and_directory &cu_info,
- std::string &name_holder)
-{
- const char *include_name = fe.name;
- const char *include_name_to_compare = include_name;
-
- const char *dir_name = fe.include_dir (lh);
-
- std::string hold_compare;
- if (!IS_ABSOLUTE_PATH (include_name)
- && (dir_name != nullptr || cu_info.get_comp_dir () != nullptr))
- {
- /* 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
- have an absolute path prepend comp_dir (if non-NULL).
- However, the directory we record in the include-file's
- psymtab does not contain COMP_DIR (to match the
- corresponding symtab(s)).
-
- Example:
-
- bash$ cd /tmp
- bash$ gcc -g ./hello.c
- include_name = "hello.c"
- dir_name = "."
- DW_AT_comp_dir = comp_dir = "/tmp"
- DW_AT_name = "./hello.c"
-
- */
-
- if (dir_name != NULL)
- {
- name_holder = path_join (dir_name, include_name);
- include_name = name_holder.c_str ();
- include_name_to_compare = include_name;
- }
- if (!IS_ABSOLUTE_PATH (include_name)
- && cu_info.get_comp_dir () != nullptr)
- {
- hold_compare = path_join (cu_info.get_comp_dir (), include_name);
- include_name_to_compare = hold_compare.c_str ();
- }
- }
-
- std::string copied_name;
- const char *cu_filename = cu_info.get_name ();
- if (!IS_ABSOLUTE_PATH (cu_filename) && cu_info.get_comp_dir () != nullptr)
- {
- copied_name = path_join (cu_info.get_comp_dir (), cu_filename);
- cu_filename = copied_name.c_str ();
- }
-
- if (FILENAME_CMP (include_name_to_compare, cu_filename) == 0)
- return nullptr;
- return include_name;
-}
-
-/* State machine to track the state of the line number program. */
-
-class lnp_state_machine
-{
-public:
- /* Initialize a machine state for the start of a line number
- program. */
- lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch, line_header *lh);
-
- file_entry *current_file ()
- {
- /* lh->file_names is 0-based, but the file name numbers in the
- statement program are 1-based. */
- return m_line_header->file_name_at (m_file);
- }
-
- /* Record the line in the state machine. END_SEQUENCE is true if
- we're processing the end of a sequence. */
- void record_line (bool end_sequence);
-
- /* Check ADDRESS is -1, -2, or zero and less than UNRELOCATED_LOWPC, and if
- true nop-out rest of the lines in this sequence. */
- void check_line_address (struct dwarf2_cu *cu,
- const gdb_byte *line_ptr,
- unrelocated_addr unrelocated_lowpc,
- unrelocated_addr address);
-
- void handle_set_discriminator (unsigned int discriminator)
- {
- m_discriminator = discriminator;
- m_line_has_non_zero_discriminator |= discriminator != 0;
- }
-
- /* Handle DW_LNE_set_address. */
- void handle_set_address (unrelocated_addr address)
- {
- m_op_index = 0;
- m_address
- = (unrelocated_addr) gdbarch_adjust_dwarf2_line (m_gdbarch,
- (CORE_ADDR) address,
- false);
- }
-
- /* Handle DW_LNS_advance_pc. */
- void handle_advance_pc (CORE_ADDR adjust);
-
- /* Handle a special opcode. */
- void handle_special_opcode (unsigned char op_code);
-
- /* Handle DW_LNS_advance_line. */
- void handle_advance_line (int line_delta)
- {
- advance_line (line_delta);
- }
-
- /* Handle DW_LNS_set_file. */
- void handle_set_file (file_name_index file);
-
- /* Handle DW_LNS_negate_stmt. */
- void handle_negate_stmt ()
- {
- m_flags ^= LEF_IS_STMT;
- }
-
- /* Handle DW_LNS_const_add_pc. */
- void handle_const_add_pc ();
-
- /* Handle DW_LNS_fixed_advance_pc. */
- void handle_fixed_advance_pc (CORE_ADDR addr_adj)
- {
- addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
- m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
- m_op_index = 0;
- }
-
- /* Handle DW_LNS_copy. */
- void handle_copy ()
- {
- record_line (false);
- m_discriminator = 0;
- m_flags &= ~LEF_PROLOGUE_END;
- m_flags &= ~LEF_EPILOGUE_BEGIN;
- }
-
- /* Handle DW_LNE_end_sequence. */
- void handle_end_sequence ()
- {
- m_currently_recording_lines = true;
- }
-
- /* Handle DW_LNS_set_prologue_end. */
- void handle_set_prologue_end ()
- {
- m_flags |= LEF_PROLOGUE_END;
- }
-
- void handle_set_epilogue_begin ()
- {
- m_flags |= LEF_EPILOGUE_BEGIN;
- }
-
-private:
- /* Advance the line by LINE_DELTA. */
- void advance_line (int line_delta)
- {
- m_line += line_delta;
-
- if (line_delta != 0)
- m_line_has_non_zero_discriminator = m_discriminator != 0;
- }
-
- struct dwarf2_cu *m_cu;
-
- gdbarch *m_gdbarch;
-
- /* The line number header. */
- line_header *m_line_header;
-
- /* These are part of the standard DWARF line number state machine,
- and initialized according to the DWARF spec. */
-
- unsigned char m_op_index = 0;
- /* The line table index of the current file. */
- file_name_index m_file = 1;
- unsigned int m_line = 1;
-
- /* These are initialized in the constructor. */
-
- unrelocated_addr m_address;
- linetable_entry_flags m_flags;
- unsigned int m_discriminator = 0;
-
- /* Additional bits of state we need to track. */
-
- /* The last file a line number was recorded for. */
- struct subfile *m_last_subfile = NULL;
-
- /* The address of the last line entry. */
- unrelocated_addr m_last_address;
-
- /* Set to true when a previous line at the same address (using
- 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. */
- bool m_currently_recording_lines = true;
-
- /* The last line number that was recorded, used to coalesce
- consecutive entries for the same line. This can happen, for
- example, when discriminators are present. PR 17276. */
- unsigned int m_last_line = 0;
- bool m_line_has_non_zero_discriminator = false;
-};
-
-void
-lnp_state_machine::handle_advance_pc (CORE_ADDR adjust)
-{
- CORE_ADDR addr_adj = (((m_op_index + adjust)
- / m_line_header->maximum_ops_per_instruction)
- * m_line_header->minimum_instruction_length);
- addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
- m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
- m_op_index = ((m_op_index + adjust)
- % m_line_header->maximum_ops_per_instruction);
-}
-
-void
-lnp_state_machine::handle_special_opcode (unsigned char op_code)
-{
- unsigned char adj_opcode = op_code - m_line_header->opcode_base;
- unsigned char adj_opcode_d = adj_opcode / m_line_header->line_range;
- unsigned char adj_opcode_r = adj_opcode % m_line_header->line_range;
- CORE_ADDR addr_adj = (((m_op_index + adj_opcode_d)
- / m_line_header->maximum_ops_per_instruction)
- * m_line_header->minimum_instruction_length);
- addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
- m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
- m_op_index = ((m_op_index + adj_opcode_d)
- % m_line_header->maximum_ops_per_instruction);
-
- int line_delta = m_line_header->line_base + adj_opcode_r;
- advance_line (line_delta);
- record_line (false);
- m_discriminator = 0;
- m_flags &= ~LEF_PROLOGUE_END;
- m_flags &= ~LEF_EPILOGUE_BEGIN;
-}
-
-void
-lnp_state_machine::handle_set_file (file_name_index file)
-{
- m_file = file;
-
- const file_entry *fe = current_file ();
- if (fe == NULL)
- dwarf2_debug_line_missing_file_complaint ();
- else
- {
- m_line_has_non_zero_discriminator = m_discriminator != 0;
- dwarf2_start_subfile (m_cu, *fe, *m_line_header);
- }
-}
-
-void
-lnp_state_machine::handle_const_add_pc ()
-{
- CORE_ADDR adjust
- = (255 - m_line_header->opcode_base) / m_line_header->line_range;
-
- CORE_ADDR addr_adj
- = (((m_op_index + adjust)
- / m_line_header->maximum_ops_per_instruction)
- * m_line_header->minimum_instruction_length);
-
- addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
- m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
- m_op_index = ((m_op_index + adjust)
- % m_line_header->maximum_ops_per_instruction);
-}
-
-/* Return non-zero if we should add LINE to the line number table.
- LINE is the line to add, LAST_LINE is the last line that was added,
- LAST_SUBFILE is the subfile for LAST_LINE.
- LINE_HAS_NON_ZERO_DISCRIMINATOR is non-zero if LINE has ever
- had a non-zero discriminator.
-
- We have to be careful in the presence of discriminators.
- E.g., for this line:
-
- for (i = 0; i < 100000; i++);
-
- clang can emit four line number entries for that one line,
- each with a different discriminator.
- See gdb.dwarf2/dw2-single-line-discriminators.exp for an example.
-
- However, we want gdb to coalesce all four entries into one.
- Otherwise the user could stepi into the middle of the line and
- gdb would get confused about whether the pc really was in the
- middle of the line.
-
- Things are further complicated by the fact that two consecutive
- line number entries for the same line is a heuristic used by gcc
- to denote the end of the prologue. So we can't just discard duplicate
- entries, we have to be selective about it. The heuristic we use is
- that we only collapse consecutive entries for the same line if at least
- one of those entries has a non-zero discriminator. PR 17276.
-
- Note: Addresses in the line number state machine can never go backwards
- within one sequence, thus this coalescing is ok. */
-
-static int
-dwarf_record_line_p (struct dwarf2_cu *cu,
- unsigned int line, unsigned int last_line,
- int line_has_non_zero_discriminator,
- struct subfile *last_subfile)
-{
- if (cu->get_builder ()->get_current_subfile () != last_subfile)
- return 1;
- if (line != last_line)
- return 1;
- /* Same line for the same file that we've seen already.
- As a last check, for pr 17276, only record the line if the line
- has never had a non-zero discriminator. */
- if (!line_has_non_zero_discriminator)
- return 1;
- return 0;
-}
-
-/* Use the CU's builder to record line number LINE beginning at
- address ADDRESS in the line table of subfile SUBFILE. */
-
-static void
-dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
- unsigned int line, unrelocated_addr address,
- linetable_entry_flags flags,
- struct dwarf2_cu *cu)
-{
- unrelocated_addr addr
- = unrelocated_addr (gdbarch_addr_bits_remove (gdbarch,
- (CORE_ADDR) address));
-
- if (cu != nullptr)
- {
- if (dwarf_line_debug)
- gdb_printf (gdb_stdlog, "Recording line %u, file %s, address %s\n",
- line, lbasename (subfile->name.c_str ()),
- paddress (gdbarch, (CORE_ADDR) address));
-
- cu->get_builder ()->record_line (subfile, line, addr, flags);
- }
-}
-
-/* Subroutine of dwarf_decode_lines_1 to simplify it.
- Mark the end of a set of line number records.
- The arguments are the same as for dwarf_record_line_1.
- If SUBFILE is NULL the request is ignored. */
-
-static void
-dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile,
- unrelocated_addr address, struct dwarf2_cu *cu)
-{
- if (subfile == NULL)
- return;
-
- if (dwarf_line_debug)
- {
- gdb_printf (gdb_stdlog,
- "Finishing current line, file %s, address %s\n",
- lbasename (subfile->name.c_str ()),
- paddress (gdbarch, (CORE_ADDR) address));
- }
-
- dwarf_record_line_1 (gdbarch, subfile, 0, address, LEF_IS_STMT, cu);
-}
-
-void
-lnp_state_machine::record_line (bool end_sequence)
-{
- if (dwarf_line_debug)
- {
- gdb_printf (gdb_stdlog,
- "Processing actual line %u: file %u,"
- " address %s, is_stmt %u, prologue_end %u,"
- " epilogue_begin %u, discrim %u%s\n",
- m_line, m_file,
- paddress (m_gdbarch, (CORE_ADDR) m_address),
- (m_flags & LEF_IS_STMT) != 0,
- (m_flags & LEF_PROLOGUE_END) != 0,
- (m_flags & LEF_EPILOGUE_BEGIN) != 0,
- m_discriminator,
- (end_sequence ? "\t(end sequence)" : ""));
- }
-
- file_entry *fe = current_file ();
-
- if (fe == NULL)
- dwarf2_debug_line_missing_file_complaint ();
- /* For now we ignore lines not starting on an instruction boundary.
- But not when processing end_sequence for compatibility with the
- previous version of the code. */
- else if (m_op_index == 0 || end_sequence)
- {
- /* When we switch files we insert an end maker in the first file,
- switch to the second file and add a new line entry. The
- problem is that the end marker inserted in the first file will
- discard any previous line entries at the same address. If the
- line entries in the first file are marked as is-stmt, while
- the new line in the second file is non-stmt, then this means
- the end marker will discard is-stmt lines so we can have a
- non-stmt line. This means that there are less addresses at
- which the user can insert a breakpoint.
-
- To improve this we track the last address in m_last_address,
- and whether we have seen an is-stmt at this address. Then
- when switching files, if we have seen a stmt at the current
- address, and we are switching to create a non-stmt line, then
- discard the new line. */
- bool file_changed
- = m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
- bool ignore_this_line
- = ((file_changed && !end_sequence && m_last_address == m_address
- && ((m_flags & LEF_IS_STMT) == 0)
- && m_stmt_at_address)
- || (!end_sequence && m_line == 0));
-
- if ((file_changed && !ignore_this_line) || end_sequence)
- {
- dwarf_finish_line (m_gdbarch, m_last_subfile, m_address,
- m_currently_recording_lines ? m_cu : nullptr);
- }
-
- if (!end_sequence && !ignore_this_line)
- {
- linetable_entry_flags lte_flags = m_flags;
- if (m_cu->producer_is_codewarrior ())
- lte_flags |= LEF_IS_STMT;
-
- if (dwarf_record_line_p (m_cu, m_line, m_last_line,
- m_line_has_non_zero_discriminator,
- m_last_subfile))
- {
- buildsym_compunit *builder = m_cu->get_builder ();
- dwarf_record_line_1 (m_gdbarch,
- builder->get_current_subfile (),
- m_line, m_address, lte_flags,
- m_currently_recording_lines ? m_cu : nullptr);
-
- m_last_subfile = m_cu->get_builder ()->get_current_subfile ();
- m_last_line = m_line;
- }
- }
- }
-
- /* 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_flags & LEF_IS_STMT) != 0;
-}
-
-lnp_state_machine::lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch,
- line_header *lh)
- : m_cu (cu),
- m_gdbarch (arch),
- m_line_header (lh),
- /* Call `gdbarch_adjust_dwarf2_line' on the initial 0 address as
- if there was a line entry for it so that the backend has a
- chance to adjust it and also record it in case it needs it.
- This is currently used by MIPS code,
- cf. `mips_adjust_dwarf2_line'. */
- m_address ((unrelocated_addr) gdbarch_adjust_dwarf2_line (arch, 0, 0)),
- m_flags (lh->default_is_stmt ? LEF_IS_STMT : (linetable_entry_flags) 0),
- m_last_address (m_address)
-{
-}
+/* See dwarf2/read.h. */
void
-lnp_state_machine::check_line_address (struct dwarf2_cu *cu,
- const gdb_byte *line_ptr,
- unrelocated_addr unrelocated_lowpc,
- unrelocated_addr address)
-{
- /* Linkers resolve a symbolic relocation referencing a GC'd function to 0,
- -1 or -2 (-2 is used by certain lld versions, see
- https://github.com/llvm/llvm-project/commit/e618ccbf431f6730edb6d1467a127c3a52fd57f7).
- If ADDRESS is 0, ignoring the opcode will err if the text section is
- located at 0x0. In this case, additionally check that if
- ADDRESS < UNRELOCATED_LOWPC. */
-
- if ((address == (unrelocated_addr) 0 && address < unrelocated_lowpc)
- || address == (unrelocated_addr) -1
- || address == (unrelocated_addr) -2)
- {
- /* This line table is for a function which has been
- GCd by the linker. Ignore it. PR gdb/12528 */
-
- struct objfile *objfile = cu->per_objfile->objfile;
- long line_offset = line_ptr - get_debug_line_section (cu)->buffer;
-
- complaint (_(".debug_line address at offset 0x%lx is 0 [in module %s]"),
- line_offset, objfile_name (objfile));
- m_currently_recording_lines = false;
- /* Note: m_currently_recording_lines is left as false until we see
- DW_LNE_end_sequence. */
- }
-}
-
-/* Subroutine of dwarf_decode_lines to simplify it.
- Process the line number information in LH. */
-
-static void
-dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
- unrelocated_addr lowpc)
-{
- const gdb_byte *line_ptr, *extended_end;
- const gdb_byte *line_end;
- unsigned int bytes_read, extended_len;
- unsigned char op_code, extended_op;
- struct objfile *objfile = cu->per_objfile->objfile;
- bfd *abfd = objfile->obfd.get ();
- struct gdbarch *gdbarch = objfile->arch ();
-
- line_ptr = lh->statement_program_start;
- line_end = lh->statement_program_end;
-
- /* Read the statement sequences until there's nothing left. */
- while (line_ptr < line_end)
- {
- /* The DWARF line number program state machine. Reset the state
- machine at the start of each sequence. */
- lnp_state_machine state_machine (cu, gdbarch, lh);
- bool end_sequence = false;
-
- /* Start a subfile for the current file of the state
- machine. */
- const file_entry *fe = state_machine.current_file ();
-
- if (fe != NULL)
- dwarf2_start_subfile (cu, *fe, *lh);
-
- /* Decode the table. */
- while (line_ptr < line_end && !end_sequence)
- {
- op_code = read_1_byte (abfd, line_ptr);
- line_ptr += 1;
-
- if (op_code >= lh->opcode_base)
- {
- /* Special opcode. */
- state_machine.handle_special_opcode (op_code);
- }
- else switch (op_code)
- {
- case DW_LNS_extended_op:
- extended_len = read_unsigned_leb128 (abfd, line_ptr,
- &bytes_read);
- line_ptr += bytes_read;
- extended_end = line_ptr + extended_len;
- extended_op = read_1_byte (abfd, line_ptr);
- line_ptr += 1;
- if (DW_LNE_lo_user <= extended_op
- && extended_op <= DW_LNE_hi_user)
- {
- /* Vendor extension, ignore. */
- line_ptr = extended_end;
- break;
- }
- switch (extended_op)
- {
- case DW_LNE_end_sequence:
- state_machine.handle_end_sequence ();
- end_sequence = true;
- break;
- case DW_LNE_set_address:
- {
- unrelocated_addr address
- = cu->header.read_address (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
-
- state_machine.check_line_address (cu, line_ptr, lowpc,
- address);
- state_machine.handle_set_address (address);
- }
- break;
- case DW_LNE_define_file:
- {
- const char *cur_file;
- unsigned int mod_time, length;
- dir_index dindex;
-
- cur_file = read_direct_string (abfd, line_ptr,
- &bytes_read);
- line_ptr += bytes_read;
- dindex = (dir_index)
- read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- mod_time =
- read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- length =
- read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- lh->add_file_name (cur_file, dindex, mod_time, length);
- }
- break;
- case DW_LNE_set_discriminator:
- {
- /* The discriminator is not interesting to the
- debugger; just ignore it. We still need to
- check its value though:
- if there are consecutive entries for the same
- (non-prologue) line we want to coalesce them.
- PR 17276. */
- unsigned int discr
- = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
-
- state_machine.handle_set_discriminator (discr);
- }
- break;
- default:
- complaint (_("mangled .debug_line section"));
- return;
- }
- /* Make sure that we parsed the extended op correctly. If e.g.
- we expected a different address size than the producer used,
- we may have read the wrong number of bytes. */
- if (line_ptr != extended_end)
- {
- complaint (_("mangled .debug_line section"));
- return;
- }
- break;
- case DW_LNS_copy:
- state_machine.handle_copy ();
- break;
- case DW_LNS_advance_pc:
- {
- CORE_ADDR adjust
- = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
-
- state_machine.handle_advance_pc (adjust);
- }
- break;
- case DW_LNS_advance_line:
- {
- int line_delta
- = read_signed_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
-
- state_machine.handle_advance_line (line_delta);
- }
- break;
- case DW_LNS_set_file:
- {
- file_name_index file
- = (file_name_index) read_unsigned_leb128 (abfd, line_ptr,
- &bytes_read);
- line_ptr += bytes_read;
-
- state_machine.handle_set_file (file);
- }
- break;
- case DW_LNS_set_column:
- (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- break;
- case DW_LNS_negate_stmt:
- state_machine.handle_negate_stmt ();
- break;
- case DW_LNS_set_basic_block:
- break;
- /* Add to the address register of the state machine the
- address increment value corresponding to special opcode
- 255. I.e., this value is scaled by the minimum
- instruction length since special opcode 255 would have
- scaled the increment. */
- case DW_LNS_const_add_pc:
- state_machine.handle_const_add_pc ();
- break;
- case DW_LNS_fixed_advance_pc:
- {
- CORE_ADDR addr_adj = read_2_bytes (abfd, line_ptr);
- line_ptr += 2;
-
- state_machine.handle_fixed_advance_pc (addr_adj);
- }
- break;
- case DW_LNS_set_prologue_end:
- state_machine.handle_set_prologue_end ();
- break;
- case DW_LNS_set_epilogue_begin:
- state_machine.handle_set_epilogue_begin ();
- break;
- default:
- {
- /* Unknown standard opcode, ignore it. */
- int i;
-
- for (i = 0; i < lh->standard_opcode_lengths[op_code]; i++)
- {
- (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- }
- }
- }
- }
-
- if (!end_sequence)
- dwarf2_debug_line_missing_end_sequence_complaint ();
-
- /* We got a DW_LNE_end_sequence (or we ran off the end of the buffer,
- in which case we still finish recording the last line). */
- state_machine.record_line (true);
- }
-}
-
-/* Decode the Line Number Program (LNP) for the given line_header
- structure and CU. The actual information extracted and the type
- of structures created from the LNP depends on the value of PST.
-
- FND holds the CU file name and directory, if known.
- It is used for relative paths in the line table.
-
- 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).
-
- Boolean DECODE_MAPPING specifies we need to fully decode .debug_line
- for its PC<->lines mapping information. Otherwise only the filename
- table is read in. */
-
-static void
-dwarf_decode_lines (struct line_header *lh, struct dwarf2_cu *cu,
- unrelocated_addr lowpc, int decode_mapping)
-{
- if (decode_mapping)
- dwarf_decode_lines_1 (lh, cu, lowpc);
-
- /* Make sure a symtab is created for every file, even files
- which contain only variables (i.e. no code with associated
- line numbers). */
- buildsym_compunit *builder = cu->get_builder ();
- struct compunit_symtab *cust = builder->get_compunit_symtab ();
-
- for (auto &fe : lh->file_names ())
- {
- dwarf2_start_subfile (cu, fe, *lh);
- subfile *sf = builder->get_current_subfile ();
-
- if (sf->symtab == nullptr)
- sf->symtab = allocate_symtab (cust, sf->name.c_str (),
- sf->name_for_id.c_str ());
-
- fe.symtab = sf->symtab;
- }
-}
-
-/* Start a subfile for DWARF. FILENAME is the name of the file and
- DIRNAME the name of the source directory which contains FILENAME
- or NULL if not known.
- This routine tries to keep line numbers from identical absolute and
- relative file names in a common subfile.
-
- Using the `list' example from the GDB testsuite, which resides in
- /srcdir and compiling it with Irix6.2 cc in /compdir using a filename
- of /srcdir/list0.c yields the following debugging information for list0.c:
-
- DW_AT_name: /srcdir/list0.c
- DW_AT_comp_dir: /compdir
- files.files[0].name: list0.h
- files.files[0].dir: /srcdir
- files.files[1].name: list0.c
- files.files[1].dir: /srcdir
-
- The line number information for list0.c has to end up in a single
- subfile, so that `break /srcdir/list0.c:1' works as expected.
- start_subfile will ensure that this happens provided that we pass the
- concatenation of files.files[1].dir and files.files[1].name as the
- subfile's name. */
-
-static void
dwarf2_start_subfile (dwarf2_cu *cu, const file_entry &fe,
const line_header &lh)
{
@@ -16525,7 +16022,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->per_objfile->objfile;
- struct comp_unit_head *cu_header = &cu->header;
+ unit_head *cu_header = &cu->header;
/* NOTE drow/2003-01-30: There used to be a comment and some special
code here to turn a symbol with DW_AT_external and a
@@ -16541,7 +16038,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
variable has been optimized away. */
if (attr->form_is_block () && attr->as_block ()->size == 0)
{
- sym->set_aclass_index (LOC_OPTIMIZED_OUT);
+ sym->set_loc_class_index (LOC_OPTIMIZED_OUT);
return;
}
@@ -16571,7 +16068,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
else
tem = read_addr_index_from_leb128 (cu, block->data + 1, &dummy);
sym->set_value_address ((CORE_ADDR) tem);
- sym->set_aclass_index (LOC_STATIC);
+ sym->set_loc_class_index (LOC_STATIC);
fixup_symbol_section (sym, objfile);
sym->set_value_address
(sym->value_address ()
@@ -16608,20 +16105,20 @@ add_ada_export_symbol (struct symbol *orig, const char *new_name,
= new (&cu->per_objfile->objfile->objfile_obstack) symbol (*orig);
copy->set_linkage_name (new_name);
SYMBOL_LOCATION_BATON (copy) = (void *) orig_name;
- copy->set_aclass_index (copy->aclass () == LOC_BLOCK
+ copy->set_loc_class_index (copy->loc_class () == LOC_BLOCK
? ada_block_index
: ada_imported_index);
add_symbol_to_list (copy, list_to_add);
}
-/* A helper function that decides if a given symbol is an Ada Pragma
- Import or Pragma Export. */
+/* See read.h. */
-static bool
+bool
is_ada_import_or_export (dwarf2_cu *cu, const char *name,
const char *linkagename)
{
return (cu->lang () == language_ada
+ && name != nullptr
&& linkagename != nullptr
&& !streq (name, linkagename)
/* The following exclusions are necessary because symbols
@@ -16708,7 +16205,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
/* Default assumptions.
Use the passed type or decode it from the die. */
sym->set_domain (UNDEF_DOMAIN);
- sym->set_aclass_index (LOC_OPTIMIZED_OUT);
+ sym->set_loc_class_index (LOC_OPTIMIZED_OUT);
if (type != NULL)
sym->set_type (type);
else
@@ -16752,25 +16249,30 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
switch (die->tag)
{
case DW_TAG_label:
- attr = dwarf2_attr (die, DW_AT_low_pc, cu);
- if (attr != nullptr)
- {
- CORE_ADDR addr = per_objfile->relocate (attr->as_address ());
- sym->set_section_index (SECT_OFF_TEXT (objfile));
- sym->set_value_address (addr);
- sym->set_aclass_index (LOC_LABEL);
- }
- else
- sym->set_aclass_index (LOC_OPTIMIZED_OUT);
- sym->set_type (builtin_type (objfile)->builtin_core_addr);
- sym->set_domain (LABEL_DOMAIN);
- list_to_add = cu->list_in_scope;
+ {
+ attr = dwarf2_attr (die, DW_AT_low_pc, cu);
+ if (attr != nullptr)
+ {
+ CORE_ADDR addr = per_objfile->relocate (attr->as_address ());
+ sym->set_section_index (SECT_OFF_TEXT (objfile));
+ sym->set_value_address (addr);
+ sym->set_loc_class_index (LOC_LABEL);
+ }
+ else
+ sym->set_loc_class_index (LOC_OPTIMIZED_OUT);
+ type_allocator alloc (objfile, cu->lang ());
+ struct type *addr_type
+ = alloc.copy_type (builtin_type (objfile)->builtin_core_addr);
+ sym->set_type (addr_type);
+ sym->set_domain (LABEL_DOMAIN);
+ list_to_add = cu->list_in_scope;
+ }
break;
case DW_TAG_entry_point:
/* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
finish_block. */
sym->set_domain (FUNCTION_DOMAIN);
- sym->set_aclass_index (LOC_BLOCK);
+ sym->set_loc_class_index (LOC_BLOCK);
/* DW_TAG_entry_point provides an additional entry_point to an
existing sub_program. Therefore, we inherit the "external"
attribute from the sub_program to which the entry_point
@@ -16785,7 +16287,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
/* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
finish_block. */
sym->set_domain (FUNCTION_DOMAIN);
- sym->set_aclass_index (LOC_BLOCK);
+ sym->set_loc_class_index (LOC_BLOCK);
attr2 = dwarf2_attr (die, DW_AT_external, cu);
if ((attr2 != nullptr && attr2->as_boolean ())
|| cu->lang () == language_ada
@@ -16814,7 +16316,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
/* For Import, create a symbol using the source
name, and have it refer to the linkage name. */
SYMBOL_LOCATION_BATON (sym) = (void *) linkagename;
- sym->set_aclass_index (ada_block_index);
+ sym->set_loc_class_index (ada_block_index);
}
else
{
@@ -16830,7 +16332,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
/* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
finish_block. */
sym->set_domain (FUNCTION_DOMAIN);
- sym->set_aclass_index (LOC_BLOCK);
+ sym->set_loc_class_index (LOC_BLOCK);
sym->set_is_inlined (1);
list_to_add = cu->list_in_scope;
break;
@@ -16845,7 +16347,12 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
variables with missing type entries. Change the
misleading `void' type to something sensible. */
if (sym->type ()->code () == TYPE_CODE_VOID)
- sym->set_type (builtin_type (objfile)->builtin_int);
+ {
+ type_allocator alloc (objfile, cu->lang ());
+ struct type *int_type
+ = alloc.copy_type (builtin_type (objfile)->builtin_int);
+ sym->set_type (int_type);
+ }
attr = dwarf2_attr (die, DW_AT_const_value, cu);
/* In the case of DW_TAG_member, we should only be called for
@@ -16882,7 +16389,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
&& die->parent->tag == DW_TAG_common_block)
attr2 = NULL;
- if (sym->aclass () == LOC_STATIC
+ if (sym->loc_class () == LOC_STATIC
&& sym->value_address () == 0
&& !per_objfile->per_bfd->has_section_at_zero)
{
@@ -16893,7 +16400,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
}
else if (attr2 != nullptr && attr2->as_boolean ())
{
- if (sym->aclass () == LOC_STATIC
+ if (sym->loc_class () == LOC_STATIC
&& (objfile->flags & OBJF_MAINLINE) == 0
&& per_objfile->per_bfd->can_copy)
{
@@ -16962,7 +16469,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
? cu->get_builder ()->get_global_symbols ()
: cu->list_in_scope);
SYMBOL_LOCATION_BATON (sym) = (void *) linkagename;
- sym->set_aclass_index (ada_imported_index);
+ sym->set_loc_class_index (ada_imported_index);
}
else if (attr2 != nullptr && attr2->as_boolean ()
&& dwarf2_attr (die, DW_AT_type, cu) != NULL)
@@ -16975,12 +16482,12 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
? cu->get_builder ()->get_global_symbols ()
: cu->list_in_scope);
- sym->set_aclass_index (LOC_UNRESOLVED);
+ sym->set_loc_class_index (LOC_UNRESOLVED);
}
else if (!die_is_declaration (die, cu))
{
/* Use the default LOC_OPTIMIZED_OUT class. */
- gdb_assert (sym->aclass () == LOC_OPTIMIZED_OUT);
+ gdb_assert (sym->loc_class () == LOC_OPTIMIZED_OUT);
if (!suppress_add)
list_to_add = cu->list_in_scope;
}
@@ -17036,13 +16543,13 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
there's a special hack for C++ in the matching code,
so we don't need to enter a separate typedef for the
tag. */
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
sym->set_domain (STRUCT_DOMAIN);
}
else
{
/* Other languages don't have a tag namespace. */
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
sym->set_domain (TYPE_DOMAIN);
}
@@ -17087,7 +16594,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
case DW_TAG_base_type:
case DW_TAG_subrange_type:
case DW_TAG_generic_subrange:
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
sym->set_domain (TYPE_DOMAIN);
list_to_add = cu->list_in_scope;
break;
@@ -17111,21 +16618,21 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
case DW_TAG_imported_declaration:
case DW_TAG_namespace:
sym->set_domain (TYPE_DOMAIN);
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
list_to_add = cu->get_builder ()->get_global_symbols ();
break;
case DW_TAG_module:
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
sym->set_domain (MODULE_DOMAIN);
list_to_add = cu->get_builder ()->get_global_symbols ();
break;
case DW_TAG_common_block:
- sym->set_aclass_index (LOC_COMMON_BLOCK);
+ sym->set_loc_class_index (LOC_COMMON_BLOCK);
sym->set_domain (COMMON_BLOCK_DOMAIN);
list_to_add = cu->list_in_scope;
break;
case DW_TAG_namelist:
- sym->set_aclass_index (LOC_STATIC);
+ sym->set_loc_class_index (LOC_STATIC);
sym->set_domain (VAR_DOMAIN);
list_to_add = cu->list_in_scope;
break;
@@ -17158,40 +16665,6 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
return (sym);
}
-/* Given an attr with a DW_FORM_dataN value in host byte order,
- zero-extend it as appropriate for the symbol's type. The DWARF
- standard (v4) is not entirely clear about the meaning of using
- DW_FORM_dataN for a constant with a signed type, where the type is
- wider than the data. The conclusion of a discussion on the DWARF
- list was that this is unspecified. We choose to always zero-extend
- because that is the interpretation long in use by GCC. */
-
-static gdb_byte *
-dwarf2_const_value_data (const struct attribute *attr, struct obstack *obstack,
- struct dwarf2_cu *cu, LONGEST *value, int bits)
-{
- struct objfile *objfile = cu->per_objfile->objfile;
- enum bfd_endian byte_order = bfd_big_endian (objfile->obfd.get ()) ?
- BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
- LONGEST l = attr->constant_value (0);
-
- if (bits < sizeof (*value) * 8)
- {
- l &= ((LONGEST) 1 << bits) - 1;
- *value = l;
- }
- else if (bits == sizeof (*value) * 8)
- *value = l;
- else
- {
- gdb_byte *bytes = (gdb_byte *) obstack_alloc (obstack, bits / 8);
- store_unsigned_integer (bytes, bits / 8, byte_order, l);
- return bytes;
- }
-
- return NULL;
-}
-
/* Read a constant value from an attribute. Either set *VALUE, or if
the value does not fit in *VALUE, set *BYTES - either already
allocated on the objfile obstack, or newly allocated on OBSTACK,
@@ -17207,7 +16680,7 @@ dwarf2_const_value_attr (const struct attribute *attr, struct type *type,
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
struct objfile *objfile = per_objfile->objfile;
- struct comp_unit_head *cu_header = &cu->header;
+ unit_head *cu_header = &cu->header;
struct dwarf_block *blk;
enum bfd_endian byte_order = (bfd_big_endian (objfile->obfd.get ()) ?
BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE);
@@ -17231,7 +16704,7 @@ dwarf2_const_value_attr (const struct attribute *attr, struct type *type,
/* Symbols of this form are reasonably rare, so we just
piggyback on the existing location code rather than writing
a new implementation of symbol_computed_ops. */
- *baton = XOBNEW (obstack, struct dwarf2_locexpr_baton);
+ *baton = OBSTACK_ZALLOC (obstack, struct dwarf2_locexpr_baton);
(*baton)->per_objfile = per_objfile;
(*baton)->per_cu = cu->per_cu;
gdb_assert ((*baton)->per_cu);
@@ -17251,6 +16724,7 @@ dwarf2_const_value_attr (const struct attribute *attr, struct type *type,
case DW_FORM_strx:
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_strp_alt:
+ case DW_FORM_strp_sup:
/* The string is already allocated on the objfile obstack, point
directly to it. */
*bytes = (const gdb_byte *) attr->as_string ();
@@ -17274,25 +16748,13 @@ dwarf2_const_value_attr (const struct attribute *attr, struct type *type,
converted to host endianness, so we just need to sign- or
zero-extend it as appropriate. */
case DW_FORM_data1:
- *bytes = dwarf2_const_value_data (attr, obstack, cu, value, 8);
- break;
case DW_FORM_data2:
- *bytes = dwarf2_const_value_data (attr, obstack, cu, value, 16);
- break;
case DW_FORM_data4:
- *bytes = dwarf2_const_value_data (attr, obstack, cu, value, 32);
- break;
case DW_FORM_data8:
- *bytes = dwarf2_const_value_data (attr, obstack, cu, value, 64);
- break;
-
case DW_FORM_sdata:
case DW_FORM_implicit_const:
- *value = attr->as_signed ();
- break;
-
case DW_FORM_udata:
- *value = attr->as_unsigned ();
+ *value = attr->confused_constant ().value_or (0);
break;
default:
@@ -17323,17 +16785,17 @@ dwarf2_const_value (const struct attribute *attr, struct symbol *sym,
if (baton != NULL)
{
SYMBOL_LOCATION_BATON (sym) = baton;
- sym->set_aclass_index (dwarf2_locexpr_index);
+ sym->set_loc_class_index (dwarf2_locexpr_index);
}
else if (bytes != NULL)
{
sym->set_value_bytes (bytes);
- sym->set_aclass_index (LOC_CONST_BYTES);
+ sym->set_loc_class_index (LOC_CONST_BYTES);
}
else
{
sym->set_value_longest (value);
- sym->set_aclass_index (LOC_CONST);
+ sym->set_loc_class_index (LOC_CONST);
}
}
@@ -17349,7 +16811,8 @@ die_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->per_objfile->objfile;
/* A missing DW_AT_type represents a void type. */
- return builtin_type (objfile)->builtin_void;
+ type_allocator alloc (objfile, cu->lang ());
+ return alloc.copy_type (builtin_type (objfile)->builtin_void);
}
return lookup_die_type (die, type_attr, cu);
@@ -17457,11 +16920,12 @@ lookup_die_type (struct die_info *die, const struct attribute *attr,
/* First see if we have it cached. */
- if (attr->form == DW_FORM_GNU_ref_alt)
+ if (attr->form_is_alt ())
{
+ const auto &section = get_section_for_ref (*attr, cu);
sect_offset sect_off = attr->get_ref_die_offset ();
dwarf2_per_cu *per_cu
- = dwarf2_find_containing_comp_unit (sect_off, 1, per_objfile->per_bfd);
+ = dwarf2_find_containing_unit ({ &section, sect_off }, per_objfile);
this_type = get_die_type_at_offset (sect_off, per_cu, per_objfile);
}
@@ -17699,9 +17163,11 @@ anonymous_struct_prefix (struct die_info *die, struct dwarf2_cu *cu)
return NULL;
attr = dw2_linkage_name_attr (die, cu);
+ if (attr == nullptr)
+ return nullptr;
const char *attr_name = attr->as_string ();
- if (attr == NULL || attr_name == NULL)
- return NULL;
+ if (attr_name == nullptr)
+ return nullptr;
/* dwarf2_name had to be already called. */
gdb_assert (attr->canonical_string_p ());
@@ -18162,14 +17628,13 @@ follow_die_ref_or_sig (struct die_info *src_die, const struct attribute *attr,
return die;
}
-/* Follow reference OFFSET.
- On entry *REF_CU is the CU of the source die referencing OFFSET.
+/* Follow reference TARGET.
+ On entry *REF_CU is the CU of the source die referencing TARGET.
On exit *REF_CU is the CU of the result.
- Returns NULL if OFFSET is invalid. */
+ Returns nullptr if TARGET is invalid. */
-static struct die_info *
-follow_die_offset (sect_offset sect_off, int offset_in_dwz,
- struct dwarf2_cu **ref_cu)
+static die_info *
+follow_die_offset (const section_and_offset &target, dwarf2_cu **ref_cu)
{
dwarf2_cu *source_cu = *ref_cu;
dwarf2_cu *target_cu = source_cu;
@@ -18180,28 +17645,28 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz,
dwarf_read_debug_printf_v ("source CU offset: %s, target offset: %s, "
"source CU contains target offset: %d",
- sect_offset_str (source_cu->per_cu->sect_off),
- sect_offset_str (sect_off),
- source_cu->header.offset_in_cu_p (sect_off));
+ sect_offset_str (source_cu->per_cu->sect_off ()),
+ sect_offset_str (target.offset),
+ (target.section == &source_cu->section ()
+ && source_cu->header.offset_in_unit_p (target.offset)));
- if (source_cu->per_cu->is_debug_types)
+ if (source_cu->per_cu->is_debug_types ())
{
/* .debug_types CUs cannot reference anything outside their CU.
If they need to, they have to reference a signatured type via
DW_FORM_ref_sig8. */
- if (!source_cu->header.offset_in_cu_p (sect_off))
+ if (!source_cu->header.offset_in_unit_p (target.offset))
return NULL;
}
- else if (offset_in_dwz != source_cu->per_cu->is_dwz
- || !source_cu->header.offset_in_cu_p (sect_off))
+ else if (target.section != &source_cu->section ()
+ || !source_cu->header.offset_in_unit_p (target.offset))
{
dwarf2_per_cu *target_per_cu
- = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
- per_objfile->per_bfd);
+ = dwarf2_find_containing_unit (target, per_objfile);
dwarf_read_debug_printf_v ("target CU offset: %s, "
"target CU DIEs loaded: %d",
- sect_offset_str (target_per_cu->sect_off),
+ sect_offset_str (target_per_cu->sect_off ()),
per_objfile->get_cu (target_per_cu) != nullptr);
/* If necessary, add it to the queue and load its DIEs.
@@ -18219,14 +17684,13 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz,
error (_(DWARF_ERROR_PREFIX
"cannot follow reference to DIE at %s"
" [in module %s]"),
- sect_offset_str (sect_off),
+ sect_offset_str (target.offset),
objfile_name (per_objfile->objfile));
}
*ref_cu = target_cu;
- auto it = target_cu->die_hash.find (sect_off);
- return it != target_cu->die_hash.end () ? *it : nullptr;
+ return target_cu->find_die (target.offset);
}
/* Follow reference attribute ATTR of SRC_DIE.
@@ -18238,24 +17702,21 @@ follow_die_ref (struct die_info *src_die, const struct attribute *attr,
struct dwarf2_cu **ref_cu)
{
sect_offset sect_off = attr->get_ref_die_offset ();
- struct dwarf2_cu *cu = *ref_cu;
- struct die_info *die;
+ struct dwarf2_cu *src_cu = *ref_cu;
- if (attr->form != DW_FORM_GNU_ref_alt && src_die->sect_off == sect_off)
+ if (!attr->form_is_alt () && src_die->sect_off == sect_off)
{
/* Self-reference, we're done. */
return src_die;
}
- die = follow_die_offset (sect_off,
- (attr->form == DW_FORM_GNU_ref_alt
- || cu->per_cu->is_dwz),
- ref_cu);
- if (!die)
+ const dwarf2_section_info &section = get_section_for_ref (*attr, src_cu);
+ die_info *die = follow_die_offset ({ &section, sect_off }, ref_cu);
+ if (die == nullptr)
error (_(DWARF_ERROR_PREFIX
"Cannot find DIE at %s referenced from DIE at %s [in module %s]"),
sect_offset_str (sect_off), sect_offset_str (src_die->sect_off),
- objfile_name (cu->per_objfile->objfile));
+ objfile_name (src_cu->per_objfile->objfile));
return die;
}
@@ -18268,7 +17729,6 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
gdb::function_view<CORE_ADDR ()> get_frame_pc,
bool resolve_abstract_p)
{
- struct die_info *die;
struct attribute *attr;
struct dwarf2_locexpr_baton retval;
struct objfile *objfile = per_objfile->objfile;
@@ -18286,8 +17746,8 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
sect_offset_str (sect_off), objfile_name (objfile));
}
- die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
- if (!die)
+ die_info *die = follow_die_offset ({ &cu->section (), sect_off }, &cu);
+ if (die == nullptr)
error (_(DWARF_ERROR_PREFIX
"Cannot find DIE at %s referenced [in module %s]"),
sect_offset_str (sect_off), objfile_name (objfile));
@@ -18303,8 +17763,8 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
: per_objfile->per_bfd->abstract_to_concrete[die->sect_off])
{
struct dwarf2_cu *cand_cu = cu;
- struct die_info *cand
- = follow_die_offset (cand_off, per_cu->is_dwz, &cand_cu);
+ die_info *cand
+ = follow_die_offset ({ &cu->section (), cand_off }, &cand_cu);
if (!cand
|| !cand->parent
|| cand->parent->tag != DW_TAG_subprogram)
@@ -18372,7 +17832,7 @@ dwarf2_fetch_die_loc_cu_off (cu_offset offset_in_cu, dwarf2_per_cu *per_cu,
dwarf2_per_objfile *per_objfile,
gdb::function_view<CORE_ADDR ()> get_frame_pc)
{
- sect_offset sect_off = per_cu->sect_off + to_underlying (offset_in_cu);
+ sect_offset sect_off = per_cu->sect_off () + to_underlying (offset_in_cu);
return dwarf2_fetch_die_loc_sect_off (sect_off, per_cu, per_objfile,
get_frame_pc);
@@ -18406,7 +17866,6 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
obstack *obstack,
LONGEST *len)
{
- struct die_info *die;
struct attribute *attr;
const gdb_byte *result = NULL;
struct type *type;
@@ -18427,7 +17886,7 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
sect_offset_str (sect_off), objfile_name (objfile));
}
- die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
+ die_info *die = follow_die_offset ({ &cu->section (), sect_off }, &cu);
if (!die)
error (_(DWARF_ERROR_PREFIX
"Cannot find DIE at %s referenced [in module %s]"),
@@ -18460,6 +17919,7 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
case DW_FORM_strx:
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_strp_alt:
+ case DW_FORM_strp_sup:
/* The string is already allocated on the objfile obstack, point
directly to it. */
{
@@ -18485,47 +17945,19 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
symbol's value "represented as it would be on the target
architecture." By the time we get here, it's already been
converted to host endianness, so we just need to sign- or
- zero-extend it as appropriate. */
+ zero-extend it as appropriate.
+
+ Both GCC and LLVM agree that these are always signed, though. */
case DW_FORM_data1:
- type = die_type (die, cu);
- result = dwarf2_const_value_data (attr, obstack, cu, &value, 8);
- if (result == NULL)
- result = write_constant_as_bytes (obstack, byte_order,
- type, value, len);
- break;
case DW_FORM_data2:
- type = die_type (die, cu);
- result = dwarf2_const_value_data (attr, obstack, cu, &value, 16);
- if (result == NULL)
- result = write_constant_as_bytes (obstack, byte_order,
- type, value, len);
- break;
case DW_FORM_data4:
- type = die_type (die, cu);
- result = dwarf2_const_value_data (attr, obstack, cu, &value, 32);
- if (result == NULL)
- result = write_constant_as_bytes (obstack, byte_order,
- type, value, len);
- break;
case DW_FORM_data8:
- type = die_type (die, cu);
- result = dwarf2_const_value_data (attr, obstack, cu, &value, 64);
- if (result == NULL)
- result = write_constant_as_bytes (obstack, byte_order,
- type, value, len);
- break;
-
case DW_FORM_sdata:
case DW_FORM_implicit_const:
- type = die_type (die, cu);
- result = write_constant_as_bytes (obstack, byte_order,
- type, attr->as_signed (), len);
- break;
-
case DW_FORM_udata:
type = die_type (die, cu);
- result = write_constant_as_bytes (obstack, byte_order,
- type, attr->as_unsigned (), len);
+ value = attr->confused_constant ().value_or (0);
+ result = write_constant_as_bytes (obstack, byte_order, type, value, len);
break;
default:
@@ -18544,8 +17976,6 @@ dwarf2_fetch_die_type_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
dwarf2_per_objfile *per_objfile,
const char **var_name)
{
- struct die_info *die;
-
dwarf2_cu *cu = per_objfile->get_cu (per_cu);
if (cu == nullptr)
cu = load_cu (per_cu, per_objfile, false);
@@ -18553,7 +17983,7 @@ dwarf2_fetch_die_type_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
if (cu == nullptr)
return nullptr;
- die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
+ die_info *die = follow_die_offset ({ &cu->section (), sect_off }, &cu);
if (!die)
return NULL;
@@ -18568,7 +17998,8 @@ struct type *
dwarf2_get_die_type (cu_offset die_offset, dwarf2_per_cu *per_cu,
dwarf2_per_objfile *per_objfile)
{
- sect_offset die_offset_sect = per_cu->sect_off + to_underlying (die_offset);
+ sect_offset die_offset_sect
+ = per_cu->sect_off () + to_underlying (die_offset);
return get_die_type_at_offset (die_offset_sect, per_cu, per_objfile);
}
@@ -18602,8 +18033,8 @@ follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type,
gdb_assert (sig_cu != NULL);
gdb_assert (to_underlying (sig_type->type_offset_in_section) != 0);
- if (auto die_it = sig_cu->die_hash.find (sig_type->type_offset_in_section);
- die_it != sig_cu->die_hash.end ())
+ if (die_info *die = sig_cu->find_die (sig_type->type_offset_in_section);
+ die != nullptr)
{
/* For .gdb_index version 7 keep track of included TUs.
http://sourceware.org/bugzilla/show_bug.cgi?id=15021. */
@@ -18612,7 +18043,7 @@ follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type,
(*ref_cu)->per_cu->imported_symtabs.push_back (sig_cu->per_cu);
*ref_cu = sig_cu;
- return *die_it;
+ return die;
}
return NULL;
@@ -18765,7 +18196,7 @@ load_full_type_unit (dwarf2_per_cu *per_cu, dwarf2_per_objfile *per_objfile)
/* We have the per_cu, but we need the signatured_type.
Fortunately this is an easy translation. */
- gdb_assert (per_cu->is_debug_types);
+ gdb_assert (per_cu->is_debug_types ());
sig_type = (struct signatured_type *) per_cu;
gdb_assert (per_objfile->get_cu (per_cu) == nullptr);
@@ -18783,7 +18214,7 @@ static void
read_signatured_type (signatured_type *sig_type,
dwarf2_per_objfile *per_objfile)
{
- gdb_assert (sig_type->is_debug_types);
+ gdb_assert (sig_type->is_debug_types ());
gdb_assert (per_objfile->get_cu (sig_type) == nullptr);
cutu_reader reader (*sig_type, *per_objfile, nullptr, nullptr, false,
@@ -18939,7 +18370,7 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu,
case DW_OP_deref:
/* If we're not the last op, then we definitely can't encode
- this using GDB's address_class enum. This is valid for partial
+ this using GDB's location_class enum. This is valid for partial
global symbols, although the variable's address will be bogus
in the psymtab. */
if (i < size)
@@ -19181,7 +18612,7 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym,
complaint (_("Location list used without "
"specifying the CU base address."));
- sym->set_aclass_index ((is_block
+ sym->set_loc_class_index ((is_block
? dwarf2_loclist_block_index
: dwarf2_loclist_index));
SYMBOL_LOCATION_BATON (sym) = baton;
@@ -19190,7 +18621,8 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym,
{
struct dwarf2_locexpr_baton *baton;
- baton = XOBNEW (&objfile->objfile_obstack, struct dwarf2_locexpr_baton);
+ baton = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwarf2_locexpr_baton);
baton->per_objfile = per_objfile;
baton->per_cu = cu->per_cu;
gdb_assert (baton->per_cu);
@@ -19213,7 +18645,7 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym,
baton->size = 0;
}
- sym->set_aclass_index ((is_block
+ sym->set_loc_class_index ((is_block
? dwarf2_locexpr_block_index
: dwarf2_locexpr_index));
SYMBOL_LOCATION_BATON (sym) = baton;
@@ -19222,54 +18654,6 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym,
/* See read.h. */
-const comp_unit_head *
-dwarf2_per_cu::get_header () const
-{
- if (!m_header_read_in)
- {
- const gdb_byte *info_ptr
- = this->section->buffer + to_underlying (this->sect_off);
-
- read_comp_unit_head (&m_header, info_ptr, this->section,
- rcuh_kind::COMPILE);
-
- m_header_read_in = true;
- }
-
- return &m_header;
-}
-
-/* See read.h. */
-
-int
-dwarf2_per_cu::addr_size () const
-{
- return this->get_header ()->addr_size;
-}
-
-/* See read.h. */
-
-int
-dwarf2_per_cu::offset_size () const
-{
- return this->get_header ()->offset_size;
-}
-
-/* See read.h. */
-
-int
-dwarf2_per_cu::ref_addr_size () const
-{
- const comp_unit_head *header = this->get_header ();
-
- if (header->version == 2)
- return header->addr_size;
- else
- return header->offset_size;
-}
-
-/* See read.h. */
-
void
dwarf2_per_cu::set_lang (enum language lang, dwarf_source_language dw_lang)
{
@@ -19303,69 +18687,117 @@ dwarf2_per_cu::ensure_lang (dwarf2_per_objfile *per_objfile)
true, language_minimal, nullptr);
}
-/* A helper function for dwarf2_find_containing_comp_unit that returns
- the index of the result, and that searches a vector. It will
- return a result even if the offset in question does not actually
- occur in any CU. This is separate so that it can be unit
- tested. */
+/* Return the unit from ALL_UNITS that potentially contains TARGET.
-static int
-dwarf2_find_containing_comp_unit
- (sect_offset sect_off,
- unsigned int offset_in_dwz,
- const std::vector<dwarf2_per_cu_up> &all_units)
+ Since the unit lengths may not be known yet, this function doesn't check that
+ TARGET.OFFSET actually falls within the range of the returned unit. The
+ caller is responsible for this.
+
+ If no units possibly match TARGET, return nullptr. */
+
+static dwarf2_per_cu *
+dwarf2_find_containing_unit (const section_and_offset &target,
+ const std::vector<dwarf2_per_cu_up> &all_units)
{
- int low, high;
+ auto it = std::lower_bound (all_units.begin (), all_units.end (), target,
+ [] (const dwarf2_per_cu_up &per_cu,
+ const section_and_offset &key)
+ {
+ return all_units_less_than (*per_cu, key);
+ });
- low = 0;
- high = all_units.size () - 1;
- while (high > low)
+ if (it == all_units.begin ())
{
- int mid = low + (high - low) / 2;
- dwarf2_per_cu *mid_cu = all_units[mid].get ();
-
- if (mid_cu->is_dwz > offset_in_dwz
- || (mid_cu->is_dwz == offset_in_dwz
- && mid_cu->sect_off + mid_cu->length () > sect_off))
- high = mid;
+ /* TARGET falls before the first unit of the first section, or is an
+ exact match with the first. */
+ if ((*it)->section () == target.section
+ && (*it)->sect_off () == target.offset)
+ return it->get ();
else
- low = mid + 1;
+ return nullptr;
}
- gdb_assert (low == high);
- return low;
+
+ if (it != all_units.end ()
+ && (*it)->section () == target.section
+ && (*it)->sect_off () == target.offset)
+ {
+ /* TARGET is an exact match with the start of *IT, so *IT is what we're
+ looking for. */
+ return it->get ();
+ }
+
+ /* Otherwise, the match is the one just before, as long as it matches the
+ section we're looking for. */
+ --it;
+
+ if ((*it)->section () == target.section)
+ return it->get ();
+
+ return nullptr;
}
/* See read.h. */
dwarf2_per_cu *
-dwarf2_find_containing_comp_unit (sect_offset sect_off,
- unsigned int offset_in_dwz,
- dwarf2_per_bfd *per_bfd)
+dwarf2_find_containing_unit (const section_and_offset &target,
+ dwarf2_per_objfile *per_objfile)
{
- int low = dwarf2_find_containing_comp_unit
- (sect_off, offset_in_dwz, per_bfd->all_units);
- dwarf2_per_cu *this_cu = per_bfd->all_units[low].get ();
-
- if (this_cu->is_dwz != offset_in_dwz || this_cu->sect_off > sect_off)
+ dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
+ dwarf2_per_cu *per_cu
+ = dwarf2_find_containing_unit (target, per_bfd->all_units);
+ auto error_out = [&target, per_bfd] ()
{
- if (low == 0 || this_cu->is_dwz != offset_in_dwz)
- error (_(DWARF_ERROR_PREFIX
- "could not find CU containing offset %s [in module %s]"),
- sect_offset_str (sect_off),
- per_bfd->filename ());
+ error (_(DWARF_ERROR_PREFIX
+ "could not find unit containing offset %s [in module %s]"),
+ sect_offset_str (target.offset), per_bfd->filename ());
+ };
- gdb_assert (per_bfd->all_units[low-1]->sect_off
- <= sect_off);
- return per_bfd->all_units[low - 1].get ();
- }
- else
- {
- if (low == per_bfd->all_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 ());
- return this_cu;
- }
+ if (per_cu == nullptr)
+ error_out ();
+
+ gdb_assert (per_cu->section () == target.section);
+
+ /* Some producers of dwarf2_per_cu objects (thinking of the .gdb_index reader)
+ do not set the length ahead of time. The length is needed to check if
+ the target is truly within PER_CU's range, so compute it now. Constructing
+ the cutu_reader object has the side-effect of setting PER_CU's length.
+ Even though it should happen too often, it could be replaced with
+ something more lightweight that has the same effect. */
+ if (!per_cu->length_is_set ())
+ cutu_reader (*per_cu, *per_objfile, nullptr, nullptr, false,
+ language_minimal);
+
+ /* Now we can check if the target section offset is within PER_CU's range. */
+ if (target.offset < per_cu->sect_off ()
+ || target.offset >= per_cu->sect_off () + per_cu->length ())
+ error_out ();
+
+ return per_cu;
+}
+
+/* See read.h. */
+
+dwarf2_per_cu *
+dwarf2_find_unit (const section_and_offset &start, dwarf2_per_bfd *per_bfd)
+{
+ auto it = std::lower_bound (per_bfd->all_units.begin (),
+ per_bfd->all_units.end (), start,
+ [] (const dwarf2_per_cu_up &per_cu,
+ const section_and_offset &key)
+ {
+ return all_units_less_than (*per_cu, key);
+ });
+
+ if (it == per_bfd->all_units.end ())
+ return nullptr;
+
+ dwarf2_per_cu *per_cu = it->get ();
+
+ if (per_cu->section () != start.section
+ || per_cu->sect_off () != start.offset)
+ return nullptr;
+
+ return per_cu;
}
#if GDB_SELF_TEST
@@ -19376,59 +18808,55 @@ namespace find_containing_comp_unit {
static void
run_test ()
{
- char dummy_per_bfd;
- char dummy_section;
-
- const auto create_dummy_per_cu = [&] (sect_offset sect_off,
- unsigned int length,
- bool is_dwz)
- {
- auto per_bfd = reinterpret_cast<dwarf2_per_bfd *> (&dummy_per_bfd);
- auto section = reinterpret_cast<dwarf2_section_info *> (&dummy_section);
+ auto dummy_per_bfd = reinterpret_cast<dwarf2_per_bfd *> (0x3000);
+ auto &main_section = *reinterpret_cast<dwarf2_section_info *> (0x4000);
+ auto &dwz_section = *reinterpret_cast<dwarf2_section_info *> (0x5000);
+ std::vector<dwarf2_per_cu_up> units;
- return dwarf2_per_cu_up (new dwarf2_per_cu (per_bfd, section, sect_off,
- length, is_dwz));
+ /* Create one dummy unit, append it to UNITS, return a non-owning
+ reference. */
+ auto create_dummy_per_unit = [&] (dwarf2_section_info &section,
+ unsigned int sect_off, bool is_dwz)
+ -> dwarf2_per_cu &
+ {
+ /* Omit the length, because dwarf2_find_containing_unit does not consider
+ it. */
+ return *units.emplace_back (new dwarf2_per_cu (dummy_per_bfd, &section,
+ sect_offset (sect_off),
+ 0, is_dwz));
};
- /* Units in the main file. */
- dwarf2_per_cu_up one = create_dummy_per_cu (sect_offset (0), 5, false);
- dwarf2_per_cu *one_ptr = one.get ();
- dwarf2_per_cu_up two
- = create_dummy_per_cu (sect_offset (one->length ()), 7, false);
- dwarf2_per_cu *two_ptr = two.get ();
-
- /* Units in the supplementary (dwz) file. */
- dwarf2_per_cu_up three = create_dummy_per_cu (sect_offset (0), 5, true);
- dwarf2_per_cu *three_ptr = three.get ();
- dwarf2_per_cu_up four
- = create_dummy_per_cu (sect_offset (three->length ()), 7, true);
- dwarf2_per_cu *four_ptr = four.get ();
-
- std::vector<dwarf2_per_cu_up> units;
- units.push_back (std::move (one));
- units.push_back (std::move (two));
- units.push_back (std::move (three));
- units.push_back (std::move (four));
-
- int result;
+ /* Create 2 units in the main file and 2 units in the supplementary (dwz)
+ file. */
+ auto &main1 = create_dummy_per_unit (main_section, 10, false);
+ auto &main2 = create_dummy_per_unit (main_section, 20, false);
+ auto &dwz1 = create_dummy_per_unit (dwz_section, 10, false);
+ auto &dwz2 = create_dummy_per_unit (dwz_section, 20, false);
+
+ /* Check that looking up a unit at all offsets in the range [START,END[ in
+ section SECTION finds EXPECTED. */
+ auto check_range = [&units] (dwarf2_section_info &section, unsigned int start,
+ unsigned int end, dwarf2_per_cu *expected)
+ {
+ for (unsigned int sect_off = start; sect_off < end; ++sect_off)
+ {
+ section_and_offset target { &section, sect_offset (sect_off) };
+ dwarf2_per_cu *result = dwarf2_find_containing_unit (target, units);
- result = dwarf2_find_containing_comp_unit (sect_offset (0), 0, units);
- SELF_CHECK (units[result].get () == one_ptr);
- result = dwarf2_find_containing_comp_unit (sect_offset (3), 0, units);
- SELF_CHECK (units[result].get () == one_ptr);
- result = dwarf2_find_containing_comp_unit (sect_offset (5), 0, units);
- SELF_CHECK (units[result].get () == two_ptr);
+ SELF_CHECK (result == expected);
+ }
+ };
- result = dwarf2_find_containing_comp_unit (sect_offset (0), 1, units);
- SELF_CHECK (units[result].get () == three_ptr);
- result = dwarf2_find_containing_comp_unit (sect_offset (3), 1, units);
- SELF_CHECK (units[result].get () == three_ptr);
- result = dwarf2_find_containing_comp_unit (sect_offset (5), 1, units);
- SELF_CHECK (units[result].get () == four_ptr);
-}
+ check_range (main_section, 0, 10, nullptr);
+ check_range (main_section, 10, 20, &main1);
+ check_range (main_section, 20, 30, &main2);
+ check_range (dwz_section, 0, 10, nullptr);
+ check_range (dwz_section, 10, 20, &dwz1);
+ check_range (dwz_section, 20, 30, &dwz2);
}
-}
+} /* namespace find_containing_comp_unit */
+} /* namespace selftests */
#endif /* GDB_SELF_TEST */
@@ -19512,7 +18940,7 @@ cutu_reader::prepare_one_comp_unit (struct dwarf2_cu *cu,
default:
error (_(DWARF_ERROR_PREFIX "unexpected tag '%s' at offset %s"),
dwarf_tag_name (m_top_level_die->tag),
- sect_offset_str (cu->per_cu->sect_off));
+ sect_offset_str (cu->per_cu->sect_off ()));
}
cu->per_cu->set_lang (lang, dw_lang);
@@ -19577,7 +19005,7 @@ dwarf2_per_objfile::age_comp_units ()
if (!cu->is_marked ())
{
dwarf_read_debug_printf_v ("deleting old CU %s",
- sect_offset_str (cu->per_cu->sect_off));
+ sect_offset_str (cu->per_cu->sect_off ()));
it = m_dwarf2_cus.erase (it);
}
else
@@ -19723,9 +19151,7 @@ show_check_physname (struct ui_file *file, int from_tty,
value);
}
-void _initialize_dwarf2_read ();
-void
-_initialize_dwarf2_read ()
+INIT_GDB_FILE (dwarf2_read)
{
add_setshow_prefix_cmd ("dwarf", class_maintenance,
_("\