diff options
Diffstat (limited to 'gdb/dwarf2/read.c')
| -rw-r--r-- | gdb/dwarf2/read.c | 3708 |
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 §ion : type_sections) - create_dwo_debug_type_hash_table (per_bfd, dwo_file, §ion, - 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 §ion : per_objfile->per_bfd->infos) read_comp_units_from_section (per_objfile, §ion, &per_objfile->per_bfd->abbrev, 0, sig_types, - rcuh_kind::COMPILE); + ruh_kind::COMPILE); for (dwarf2_section_info §ion : per_objfile->per_bfd->types) read_comp_units_from_section (per_objfile, §ion, &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 §ion = 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 ({ §ion, 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 §ion, + 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 §ion = 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, §ion, 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, §ion, 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, §ion, 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 = §ion; 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 §ion : 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 §ion : 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 §ion = get_section_for_ref (*type_attr, + orig.cu); + result.die = follow_die_offset ({ §ion, 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 §ion = 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 ({ §ion, 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 §ion = get_section_for_ref (*attr, src_cu); + die_info *die = follow_die_offset ({ §ion, 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 §ion, + 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, §ion, + 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 §ion, 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 { §ion, 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, _("\ |
