diff options
Diffstat (limited to 'gdb/dwarf2/read.c')
-rw-r--r-- | gdb/dwarf2/read.c | 1646 |
1 files changed, 802 insertions, 844 deletions
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 6e96afe..2f27b7c 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -31,7 +31,7 @@ #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" @@ -52,6 +52,7 @@ #include "event-top.h" #include "exceptions.h" #include "gdbsupport/task-group.h" +#include "maint.h" #include "symtab.h" #include "gdbtypes.h" #include "objfiles.h" @@ -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,11 @@ struct dwp_file dwo_unit_set loaded_cus; dwo_unit_set loaded_tus; +#if CXX_STD_THREAD + /* Mutex to synchronize access to LOADED_CUS and LOADED_TUS. */ + std::mutex loaded_cutus_lock; +#endif + /* 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 +633,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 +744,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 +756,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 *, @@ -1039,14 +1053,7 @@ 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); -static struct dwp_file *get_dwp_file (dwarf2_per_objfile *per_objfile); - -static struct dwo_unit *lookup_dwo_comp_unit - (dwarf2_cu *cu, const char *dwo_name, const char *comp_dir, - ULONGEST signature); - -static struct dwo_unit *lookup_dwo_type_unit - (dwarf2_cu *cu, const char *dwo_name, const char *comp_dir); +static void open_and_init_dwp_file (dwarf2_per_objfile *per_objfile); static void queue_and_load_all_dwo_tus (dwarf2_cu *cu); @@ -1289,7 +1296,16 @@ 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) + { + warning (_("%s"), err.what ()); + } + + try + { + open_and_init_dwp_file (per_objfile); } catch (const gdb_exception_error &err) { @@ -1316,7 +1332,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)) @@ -1632,7 +1648,7 @@ dw2_do_instantiate_symtab (dwarf2_per_cu *per_cu, && per_objfile->per_bfd->index_table != NULL && !per_objfile->per_bfd->index_table->version_check () /* DWP files aren't supported yet. */ - && get_dwp_file (per_objfile) == NULL) + && per_objfile->per_bfd->dwp_file == nullptr) queue_and_load_all_dwo_tus (cu); } @@ -1885,13 +1901,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 @@ -2383,111 +2399,6 @@ read_abbrev_offset (dwarf2_per_objfile *per_objfile, return (sect_offset) read_offset (abfd, info_ptr, offset_size); } -/* A helper for create_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. */ - -static void -create_debug_type_hash_table (dwarf2_per_objfile *per_objfile, - dwo_file *dwo_file, dwarf2_section_info *section, - rcuh_kind section_kind) -{ - struct objfile *objfile = per_objfile->objfile; - 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 ()); - - section->read (objfile); - 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 (per_objfile, &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_objfile->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. - - Note: This function processes DWO files only, not DWP files. */ - -static void -create_debug_types_hash_table - (dwarf2_per_objfile *per_objfile, dwo_file *dwo_file, - gdb::array_view<dwarf2_section_info> type_sections) -{ - for (dwarf2_section_info §ion : type_sections) - create_debug_type_hash_table (per_objfile, dwo_file, §ion, - rcuh_kind::TYPE); -} - /* Add an entry for signature SIG to per_bfd->signatured_types. */ static signatured_type_set::iterator @@ -2586,7 +2497,7 @@ 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 ()) @@ -2610,7 +2521,7 @@ lookup_dwp_signatured_type (struct dwarf2_cu *cu, ULONGEST sig) { dwarf2_per_objfile *per_objfile = cu->per_objfile; dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; - struct dwp_file *dwp_file = get_dwp_file (per_objfile); + dwp_file *dwp_file = per_objfile->per_bfd->dwp_file.get (); gdb_assert (cu->dwo_unit); gdb_assert (dwp_file != NULL); @@ -2652,7 +2563,7 @@ lookup_signatured_type (struct dwarf2_cu *cu, ULONGEST sig) { /* We're in a DWO/DWP file, and we're using .gdb_index. These cases require special processing. */ - if (get_dwp_file (per_objfile) == NULL) + if (per_objfile->per_bfd->dwp_file == nullptr) return lookup_dwo_signatured_type (cu, sig); else return lookup_dwp_signatured_type (cu, sig); @@ -2712,9 +2623,8 @@ cutu_reader::read_cutu_die_from_dwo (dwarf2_cu *cu, dwo_unit *dwo_unit, die_info *stub_comp_unit_die, const char *stub_comp_dir) { - dwarf2_per_objfile *per_objfile = cu->per_objfile; dwarf2_per_cu *per_cu = cu->per_cu; - struct objfile *objfile = per_objfile->objfile; + struct objfile *objfile = cu->per_objfile->objfile; bfd *abfd; struct dwarf2_section_info *dwo_abbrev_section; @@ -2790,9 +2700,10 @@ cutu_reader::read_cutu_die_from_dwo (dwarf2_cu *cu, dwo_unit *dwo_unit, { signatured_type *sig_type = (struct signatured_type *) per_cu; - m_info_ptr = read_and_check_comp_unit_head (per_objfile, &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 +2719,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,10 +2728,9 @@ cutu_reader::read_cutu_die_from_dwo (dwarf2_cu *cu, dwo_unit *dwo_unit, } else { - m_info_ptr - = read_and_check_comp_unit_head (per_objfile, &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. */ @@ -2873,16 +2783,10 @@ lookup_dwo_id (struct dwarf2_cu *cu, struct die_info* comp_unit_die) Returns nullptr if the specified DWO unit cannot be found. */ -static struct dwo_unit * -lookup_dwo_unit (dwarf2_cu *cu, die_info *comp_unit_die, const char *dwo_name) +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; @@ -3037,26 +2941,26 @@ 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) { - m_info_ptr - = read_and_check_comp_unit_head (&per_objfile, &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); + == 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 @@ -3069,10 +2973,9 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu, } else { - m_info_ptr - = read_and_check_comp_unit_head (&per_objfile, &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); this_cu.set_length (cu->header.get_length_with_initial ()); @@ -3204,12 +3107,11 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu, 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 (&per_objfile, &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 +3185,130 @@ 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: + void do_reading () override; + + /* Print collected type unit statistics. */ + + 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); + } + + 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_units (size_t task_number, unit_iterator first, + unit_iterator end); + + /* 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); + process_type_unit (reader, storage); else if (reader->top_level_die ()->tag != DW_TAG_partial_unit) { bool nope = false; @@ -3322,11 +3321,9 @@ 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; @@ -3360,26 +3357,9 @@ 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; @@ -3445,38 +3425,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; @@ -3498,82 +3457,29 @@ process_skeletonless_type_unit (dwo_unit *dwo_unit, cutu_reader reader (**sig_type_it, *per_objfile, nullptr, nullptr, false, language_minimal); if (!reader.is_dummy ()) - build_type_psymtabs_reader (&reader, storage); + process_type_unit (&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) +void +cooked_index_worker_debug_info::process_skeletonless_type_units + (dwarf2_per_objfile *per_objfile, cooked_index_worker_result *storage) { + scoped_time_it time_it ("DWARF skeletonless type units", m_per_command_time); + /* Skeletonless TUs in DWP files without .gdb_index is not supported yet. */ - if (get_dwp_file (per_objfile) == nullptr) + 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); + for (const dwo_unit_up &unit : file->tus) + storage->catch_error ([&] () + { + process_skeletonless_type_unit (unit.get (), per_objfile, 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_units (size_t task_number, + unit_iterator first, + unit_iterator end) { SCOPE_EXIT { bfd_thread_cleanup (); }; @@ -3586,14 +3492,10 @@ cooked_index_worker_debug_info::process_cus (size_t task_number, { dwarf2_per_cu *per_cu = inner->get (); - try - { - process_psymtab_comp_unit (per_cu, m_per_objfile, &thread_storage); - } - catch (gdb_exception &except) + thread_storage.catch_error ([&] () { - thread_storage.note_error (std::move (except)); - } + process_unit (per_cu, m_per_objfile, &thread_storage); + }); } thread_storage.done_reading (complaint_handler.release ()); @@ -3618,7 +3520,7 @@ 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, @@ -3671,7 +3573,8 @@ cooked_index_worker_debug_info::do_reading () gdb_assert (iter != last); workers.add_task ([this, task_count, iter, last] () { - process_cus (task_count, iter, last); + scoped_time_it time_it ("DWARF indexing worker", m_per_command_time); + process_units (task_count, iter, last); }); ++task_count; @@ -3688,10 +3591,11 @@ 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; + dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; dwarf_read_debug_printf ("Reading %s for %s", section->get_name (), @@ -3707,23 +3611,22 @@ 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 (per_objfile, &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 (); /* Save the compilation unit for later lookup. */ if (cu_header.unit_type != DW_UT_type) - this_cu - = per_objfile->per_bfd->allocate_per_cu (section, sect_off, length, is_dwz); + this_cu = per_bfd->allocate_per_cu (section, sect_off, length, is_dwz); else { - auto sig_type = per_objfile->per_bfd->allocate_signatured_type - (section, sect_off, length, is_dwz, cu_header.signature); + auto sig_type + = 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; @@ -3737,7 +3640,7 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile, } info_ptr = info_ptr + this_cu->length (); - per_objfile->per_bfd->all_units.push_back (std::move (this_cu)); + per_bfd->all_units.push_back (std::move (this_cu)); } } @@ -3765,17 +3668,17 @@ create_all_units (dwarf2_per_objfile *per_objfile) 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 ()) { @@ -3896,11 +3799,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 +3818,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: @@ -5023,7 +4929,7 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu) if (attr != NULL) { sect_offset sect_off = attr->get_ref_die_offset (); - bool is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz); + bool is_dwz = attr->form_is_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, @@ -5952,7 +5858,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 ()))); } @@ -6299,80 +6205,158 @@ static dwo_file * lookup_dwo_file (dwarf2_per_bfd *per_bfd, const char *dwo_name, const char *comp_dir) { +#if CXX_STD_THREAD + std::lock_guard<std::mutex> guard (per_bfd->dwo_files_lock); +#endif + 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. -static void -create_cus_hash_table (dwarf2_cu *cu, dwo_file &dwo_file) + 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) { - dwarf2_per_objfile *per_objfile = cu->per_objfile; - struct objfile *objfile = per_objfile->objfile; - dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; - const gdb_byte *info_ptr, *end_ptr; - auto §ion = dwo_file.sections.info; +#if CXX_STD_THREAD + std::lock_guard<std::mutex> lock (per_bfd->dwo_files_lock); +#endif + + return per_bfd->dwo_files.emplace (std::move (dwo_file)).first->get (); +} + +void +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 = *skeleton_cu.per_objfile; + dwarf2_per_bfd &per_bfd = *per_objfile.per_bfd; - section.read (objfile); - 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); + unsigned int length = header.get_length_with_initial (); + info_ptr += length; - info_ptr += per_cu.length (); + /* Skip dummy units. */ + if (info_ptr_post_header >= info_ptr + || peek_abbrev_code (section.get_bfd_owner (), + info_ptr_post_header) == 0) + continue; - if (reader.is_dummy()) + 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; - dwarf_read_debug_printf (" offset %s, dwo_id %s", - sect_offset_str (sect_off), - hex_string (dwo_unit->signature)); + 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; + } - 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)); + case DW_UT_type: + case DW_UT_split_type: + { + dwo_unit->type_offset_in_tu = header.type_offset_in_tu; + + 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.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; + } + } } } @@ -6530,27 +6514,18 @@ create_cus_hash_table (dwarf2_cu *cu, dwo_file &dwo_file) Note: This function processes DWP files only, not DWO files. */ static struct dwp_hash_table * -create_dwp_hash_table (dwarf2_per_objfile *per_objfile, - struct dwp_file *dwp_file, int is_debug_types) +create_dwp_hash_table (dwarf2_per_bfd *per_bfd, struct dwp_file *dwp_file, + dwarf2_section_info &index) { - struct objfile *objfile = per_objfile->objfile; bfd *dbfd = dwp_file->dbfd.get (); - const gdb_byte *index_ptr, *index_end; - struct dwarf2_section_info *index; uint32_t version, nr_columns, nr_units, nr_slots; struct dwp_hash_table *htab; - if (is_debug_types) - index = &dwp_file->sections.tu_index; - else - index = &dwp_file->sections.cu_index; - - if (index->empty ()) + if (index.empty ()) return NULL; - index->read (objfile); - index_ptr = index->buffer; - index_end = index_ptr + index->size; + const gdb_byte *index_ptr = index.buffer; + const gdb_byte *index_end = index_ptr + index.size; /* For Version 5, the version is really 2 bytes of data & 2 bytes of padding. For now it's safe to just read 4 bytes (particularly as it's difficult to @@ -6581,7 +6556,7 @@ create_dwp_hash_table (dwarf2_per_objfile *per_objfile, pulongest (nr_slots), dwp_file->name); } - htab = OBSTACK_ZALLOC (&per_objfile->per_bfd->obstack, struct dwp_hash_table); + htab = OBSTACK_ZALLOC (&per_bfd->obstack, struct dwp_hash_table); htab->version = version; htab->nr_columns = nr_columns; htab->nr_units = nr_units; @@ -6853,7 +6828,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, @@ -6976,19 +6951,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. */ @@ -7046,7 +7019,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, @@ -7181,19 +7154,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 @@ -7211,7 +7182,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, @@ -7351,16 +7322,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 @@ -7391,9 +7359,15 @@ 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; + { +#if CXX_STD_THREAD + std::lock_guard<std::mutex> guard (dwp_file->loaded_cutus_lock); +#endif + + 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) @@ -7407,7 +7381,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 @@ -7422,9 +7396,14 @@ 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. */ +#if CXX_STD_THREAD + std::lock_guard<std::mutex> guard (dwp_file->loaded_cutus_lock); +#endif + + auto it = dwo_unit_set.emplace (std::move (dwo_unit)).first; + return it->get (); } if (signature_in_table == 0) @@ -7480,7 +7459,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)); @@ -7501,14 +7480,23 @@ 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; + { +#if CXX_STD_THREAD + /* The operations below are not thread-safe, use a lock to synchronize + concurrent accesses. */ + static std::mutex mutex; + std::lock_guard<std::mutex> lock (mutex); +#endif - /* 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; } @@ -7520,9 +7508,9 @@ try_open_dwop_file (dwarf2_per_bfd *per_bfd, const char *file_name, int is_dwp, Upon success, the canonicalized path of the file is stored in the bfd, same as symfile_bfd_open. */ -static gdb_bfd_ref_ptr -open_dwo_file (dwarf2_per_bfd *per_bfd, const char *file_name, - const char *comp_dir) +gdb_bfd_ref_ptr +cutu_reader::open_dwo_file (dwarf2_per_bfd *per_bfd, const char *file_name, + const char *comp_dir) { if (IS_ABSOLUTE_PATH (file_name)) return try_open_dwop_file (per_bfd, file_name, @@ -7557,48 +7545,67 @@ open_dwo_file (dwarf2_per_bfd *per_bfd, const char *file_name, /* This function is mapped across the sections and remembers the offset and size of each of the DWO debugging sections we are interested in. */ -static void -dwarf2_locate_dwo_sections (struct objfile *objfile, bfd *abfd, - asection *sectp, dwo_sections *dwo_sections) +void +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->readin); - 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,9 +7613,9 @@ dwarf2_locate_dwo_sections (struct objfile *objfile, bfd *abfd, by PER_CU. This is for the non-DWP case. The result is NULL if DWO_NAME can't be found. */ -static dwo_file_up -open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name, - const char *comp_dir) +dwo_file_up +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; @@ -7626,18 +7633,13 @@ 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)) - dwarf2_locate_dwo_sections (per_objfile->objfile, dwo_file->dbfd.get (), - sec, &dwo_file->sections); + this->locate_dwo_sections (per_objfile->objfile, *dwo_file); - create_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_debug_types_hash_table (per_objfile, dwo_file.get (), - dwo_file->sections.types); - else - create_debug_type_hash_table (per_objfile, 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); @@ -7673,6 +7675,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->readin); + dw_sect->s.section = sectp; dw_sect->size = bfd_section_size (sectp); dw_sect->read (objfile); @@ -7718,6 +7724,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->readin); + dw_sect->s.section = sectp; dw_sect->size = bfd_section_size (sectp); dw_sect->read (objfile); @@ -7761,6 +7771,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->readin); + dw_sect->s.section = sectp; dw_sect->size = bfd_section_size (sectp); dw_sect->read (objfile); @@ -7803,10 +7817,9 @@ open_dwp_file (dwarf2_per_bfd *per_bfd, const char *file_name) } /* Initialize the use of the DWP file for the current objfile. - By convention the name of the DWP file is ${objfile}.dwp. - The result is NULL if it can't be found. */ + By convention the name of the DWP file is ${objfile}.dwp. */ -static dwp_file_up +static void open_and_init_dwp_file (dwarf2_per_objfile *per_objfile) { struct objfile *objfile = per_objfile->objfile; @@ -7823,7 +7836,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; @@ -7844,7 +7857,7 @@ open_and_init_dwp_file (dwarf2_per_objfile *per_objfile) { dwarf_read_debug_printf ("DWP file not found: %s", dwp_name.c_str ()); - return dwp_file_up (); + return; } const char *name = bfd_get_filename (dbfd.get ()); @@ -7858,9 +7871,10 @@ open_and_init_dwp_file (dwarf2_per_objfile *per_objfile) dwarf2_locate_common_dwp_sections (objfile, dwp_file->dbfd.get (), sec, dwp_file.get ()); - dwp_file->cus = create_dwp_hash_table (per_objfile, dwp_file.get (), 0); - - dwp_file->tus = create_dwp_hash_table (per_objfile, dwp_file.get (), 1); + dwp_file->cus = create_dwp_hash_table (per_bfd, dwp_file.get (), + dwp_file->sections.cu_index); + dwp_file->tus = create_dwp_hash_table (per_bfd, dwp_file.get (), + dwp_file->sections.tu_index); /* The DWP file version is stored in the hash table. Oh well. */ if (dwp_file->cus && dwp_file->tus @@ -7900,20 +7914,8 @@ open_and_init_dwp_file (dwarf2_per_objfile *per_objfile) bfd_cache_close (dwp_file->dbfd.get ()); - return dwp_file; -} - -/* Wrapper around open_and_init_dwp_file, only open it once. */ - -static struct dwp_file * -get_dwp_file (dwarf2_per_objfile *per_objfile) -{ - if (!per_objfile->per_bfd->dwp_checked) - { - per_objfile->per_bfd->dwp_file = open_and_init_dwp_file (per_objfile); - per_objfile->per_bfd->dwp_checked = 1; - } - return per_objfile->per_bfd->dwp_file.get (); + /* Everything worked, install this dwp_file in the per_bfd. */ + per_objfile->per_bfd->dwp_file = std::move (dwp_file); } /* Subroutine of lookup_dwo_comp_unit, lookup_dwo_type_unit. @@ -7932,22 +7934,23 @@ get_dwp_file (dwarf2_per_objfile *per_objfile) The result is a pointer to the dwo_unit object or NULL if we didn't find it (dwo_id mismatch or couldn't find the DWO/DWP file). */ -static struct dwo_unit * -lookup_dwo_cutu (dwarf2_cu *cu, const char *dwo_name, const char *comp_dir, - ULONGEST signature, int is_debug_types) +dwo_unit * +cutu_reader::lookup_dwo_cutu (dwarf2_cu *cu, const char *dwo_name, + const char *comp_dir, ULONGEST signature, + int is_debug_types) { dwarf2_per_objfile *per_objfile = cu->per_objfile; dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; struct objfile *objfile = per_objfile->objfile; const char *kind = is_debug_types ? "TU" : "CU"; - struct dwp_file *dwp_file; /* First see if there's a DWP file. If we have a DWP file but didn't find the DWO inside it, don't look for the original DWO file. It makes gdb behave differently depending on whether one is debugging in the build tree. */ - dwp_file = get_dwp_file (per_objfile); + dwp_file *dwp_file = per_objfile->per_bfd->dwp_file.get (); + if (dwp_file != NULL) { const struct dwp_hash_table *dwp_htab = @@ -7983,12 +7986,7 @@ lookup_dwo_cutu (dwarf2_cu *cu, const char *dwo_name, const char *comp_dir, = 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) @@ -7999,13 +7997,13 @@ lookup_dwo_cutu (dwarf2_cu *cu, const char *dwo_name, const char *comp_dir, { 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) @@ -8048,9 +8046,9 @@ lookup_dwo_cutu (dwarf2_cu *cu, const char *dwo_name, const char *comp_dir, /* Lookup the DWO CU DWO_NAME/SIGNATURE referenced from THIS_CU. See lookup_dwo_cutu_unit for details. */ -static struct dwo_unit * -lookup_dwo_comp_unit (dwarf2_cu *cu, const char *dwo_name, const char *comp_dir, - ULONGEST signature) +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); @@ -8060,8 +8058,9 @@ lookup_dwo_comp_unit (dwarf2_cu *cu, const char *dwo_name, const char *comp_dir, /* Lookup the DWO TU DWO_NAME/SIGNATURE referenced from THIS_TU. See lookup_dwo_cutu_unit for details. */ -static struct dwo_unit * -lookup_dwo_type_unit (dwarf2_cu *cu, const char *dwo_name, const char *comp_dir) +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); @@ -8104,15 +8103,15 @@ queue_and_load_all_dwo_tus (dwarf2_cu *cu) gdb_assert (cu != nullptr); gdb_assert (!cu->per_cu->is_debug_types); - gdb_assert (get_dwp_file (cu->per_objfile) == nullptr); + gdb_assert (cu->per_objfile->per_bfd->dwp_file == nullptr); dwo_unit = cu->dwo_unit; gdb_assert (dwo_unit != NULL); 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. */ @@ -8788,7 +8787,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; @@ -8887,7 +8887,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 @@ -9255,7 +9255,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)); @@ -9911,54 +9911,6 @@ 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. */ - -static int -handle_member_location (struct die_info *die, struct dwarf2_cu *cu, - LONGEST *offset) -{ - struct attribute *attr; - - attr = dwarf2_attr (die, DW_AT_data_member_location, cu); - if (attr != NULL) - { - *offset = 0; - CORE_ADDR temp; - - /* 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)) - { - *offset = temp; - } - else - dwarf2_complex_location_expr_complaint (); - - 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. */ @@ -9971,9 +9923,28 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu, attr = dwarf2_attr (die, DW_AT_data_member_location, cu); if (attr != NULL) { + bool has_bit_offset = false; + LONGEST bit_offset = 0; + LONGEST anonymous_size = 0; + + attribute *attr2 = dwarf2_attr (die, DW_AT_bit_offset, cu); + if (attr2 != nullptr && attr2->form_is_constant ()) + { + has_bit_offset = true; + bit_offset = attr2->confused_constant ().value_or (0); + attr2 = dwarf2_attr (die, DW_AT_byte_size, cu); + if (attr2 != nullptr && attr2->form_is_constant ()) + { + /* The size of the anonymous object containing + the bit field is explicit, so use the + indicated size (in bytes). */ + anonymous_size = attr2->unsigned_constant ().value_or (0); + } + } + if (attr->form_is_constant ()) { - LONGEST offset = attr->constant_value (0); + LONGEST offset = attr->confused_constant ().value_or (0); /* Work around this GCC 11 bug, where it would erroneously use -1 data member locations, instead of 0: @@ -9988,9 +9959,9 @@ 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 ()) { CORE_ADDR offset; @@ -10000,9 +9971,20 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu, { 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); + 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 = attr->as_block ()->data; dlbaton->size = attr->as_block ()->size; /* When using this baton, we want to compute the address @@ -10012,28 +9994,71 @@ 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 (attr->form)); } else { attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu); if (attr != nullptr) - field->set_loc_bitpos (attr->constant_value (0)); + { + if (attr->form_is_constant ()) + field->set_loc_bitpos (attr->unsigned_constant ().value_or (0)); + else if (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 = attr->as_block ()->data; + dlbaton->size = 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 (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; @@ -10083,64 +10108,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); @@ -10279,13 +10247,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 @@ -11099,7 +11073,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; @@ -11244,12 +11218,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); @@ -11311,6 +11287,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 @@ -11575,25 +11566,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) @@ -11607,19 +11603,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); @@ -11628,13 +11631,10 @@ update_enumeration_type_from_children (struct die_info *die, if (!fields.empty ()) type->copy_fields (fields); else - flag_enum = 0; + flag_enum = false; - if (unsigned_enum) - type->set_is_unsigned (true); - - 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 @@ -11678,7 +11678,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); @@ -11692,6 +11692,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 @@ -11704,7 +11709,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 ()); @@ -11724,7 +11730,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; } @@ -12074,7 +12080,7 @@ 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. */ @@ -12289,7 +12295,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); @@ -12298,7 +12305,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 @@ -12595,7 +12602,7 @@ 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; @@ -12613,7 +12620,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; @@ -12709,7 +12717,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; @@ -12725,7 +12733,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); @@ -12889,9 +12898,7 @@ 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); } else @@ -12910,15 +12917,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 { @@ -13193,7 +13199,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. */ @@ -13227,10 +13233,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 @@ -13259,8 +13266,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 @@ -13409,14 +13416,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)); @@ -13616,7 +13623,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); @@ -13626,9 +13632,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")); @@ -13774,29 +13804,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; } } @@ -13937,17 +13959,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; } } @@ -14107,8 +14125,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. @@ -14195,7 +14218,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); @@ -14876,7 +14899,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; @@ -14927,10 +14950,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; @@ -14982,6 +15007,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 @@ -15181,8 +15207,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); @@ -15206,7 +15231,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 (); @@ -15339,9 +15364,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 @@ -16538,7 +16570,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 @@ -17171,40 +17203,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, @@ -17220,7 +17218,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); @@ -17244,7 +17242,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); @@ -17264,6 +17262,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 (); @@ -17287,25 +17286,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: @@ -17470,7 +17457,7 @@ 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 ()) { sect_offset sect_off = attr->get_ref_die_offset (); dwarf2_per_cu *per_cu @@ -18195,18 +18182,18 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz, "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)); + source_cu->header.offset_in_unit_p (sect_off)); 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 (sect_off)) return NULL; } else if (offset_in_dwz != source_cu->per_cu->is_dwz - || !source_cu->header.offset_in_cu_p (sect_off)) + || !source_cu->header.offset_in_unit_p (sect_off)) { dwarf2_per_cu *target_per_cu = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz, @@ -18238,8 +18225,7 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz, *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 (sect_off); } /* Follow reference attribute ATTR of SRC_DIE. @@ -18254,15 +18240,14 @@ follow_die_ref (struct die_info *src_die, const struct attribute *attr, struct dwarf2_cu *cu = *ref_cu; struct die_info *die; - 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), + attr->form_is_alt () || cu->per_cu->is_dwz, ref_cu); if (!die) error (_(DWARF_ERROR_PREFIX @@ -18473,6 +18458,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. */ { @@ -18498,47 +18484,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: @@ -18615,8 +18573,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. */ @@ -18625,7 +18583,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; @@ -19182,7 +19140,7 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym, /* .debug_loc{,.dwo} may not exist at all, or the offset may be outside the section. If so, fall through to the complaint in the other branch. */ - && attr->as_unsigned () < section->get_size (objfile)) + && attr->as_unsigned () < section->size) { struct dwarf2_loclist_baton *baton; @@ -19203,7 +19161,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); @@ -19235,7 +19194,7 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym, /* See read.h. */ -const comp_unit_head * +const unit_head * dwarf2_per_cu::get_header () const { if (!m_header_read_in) @@ -19243,8 +19202,7 @@ dwarf2_per_cu::get_header () const 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); + read_unit_head (&m_header, info_ptr, this->section, ruh_kind::COMPILE); m_header_read_in = true; } @@ -19273,7 +19231,7 @@ dwarf2_per_cu::offset_size () const int dwarf2_per_cu::ref_addr_size () const { - const comp_unit_head *header = this->get_header (); + const unit_head *header = this->get_header (); if (header->version == 2) return header->addr_size; |