From patchwork Sun Dec 10 16:45:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 81825 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B00BD385843A for ; Sun, 10 Dec 2023 16:46:53 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from omta40.uswest2.a.cloudfilter.net (omta40.uswest2.a.cloudfilter.net [35.89.44.39]) by sourceware.org (Postfix) with ESMTPS id D58F03858294 for ; Sun, 10 Dec 2023 16:45:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D58F03858294 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=tromey.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tromey.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D58F03858294 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=35.89.44.39 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1702226714; cv=none; b=pPTDcxKa4lXkvkVs5mtFUobftSm76xdKG23u3WVJChER2EuHJmF12mnHk21tnZKyz0ZmJInyfiCBRbn0ILYIbSJ9vE2X7ZZXFelYUGKA0/Ey2cAPHek/8JAYRTckPAXmfdIw4PSPqZp+4TCUX1BqCjUcmR2qYOm0ym3uaGhhi4I= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1702226714; c=relaxed/simple; bh=7PAdm79jO+GP8HQneFDLHxyuGr9PqWL1vM9OkzxZqG8=; h=DKIM-Signature:From:Date:Subject:MIME-Version:Message-Id:To; b=P73Q7Yez1jra+g3lKdiqCkv28DLPow/Hs+NyyaYbD2BONKnUz8h6sPbQyNbdlOto2YrKrE1STkg3hNC1ghRPjkfwd93yOlVJCdgSXcltYBrPFPrw/S1t07xS8waPfn3pnzSm5Ly377raYWFcbSX+4XEnhflwpFyR2AT8m7XV/LE= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from eig-obgw-5002a.ext.cloudfilter.net ([10.0.29.215]) by cmsmtp with ESMTPS id Bw03r89NmL9AgCMvSrXN73; Sun, 10 Dec 2023 16:45:07 +0000 Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with ESMTPS id CMvRr5tD5RQmiCMvRrSJ22; Sun, 10 Dec 2023 16:45:06 +0000 X-Authority-Analysis: v=2.4 cv=CdcbWZnl c=1 sm=1 tr=0 ts=6575eb12 a=ApxJNpeYhEAb1aAlGBBbmA==:117 a=ApxJNpeYhEAb1aAlGBBbmA==:17 a=OWjo9vPv0XrRhIrVQ50Ab3nP57M=:19 a=dLZJa+xiwSxG16/P+YVxDGlgEgI=:19 a=IkcTkHD0fZMA:10 a=e2cXIFwxEfEA:10 a=Qbun_eYptAEA:10 a=CCpqsmhAAAAA:8 a=iHJ3fu4ErVreHP7NR04A:9 a=QEXdDO2ut3YA:10 a=ul9cdbp4aOFLsgKbc677:22 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tromey.com; s=default; h=To:In-Reply-To:References:Message-Id:Content-Transfer-Encoding: Content-Type:MIME-Version:Subject:Date:From:Sender:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=O3rNqugGREHV7lH74TWLyrBa82+C/5XKOjO8mi9zPwo=; b=OyyVjqjw6JnpwjlFBNKJ4+nz+M yMqUqQT1//SHeSiZJp1I7NabBambhQA2WJ2dJGAh7aMoh3Rkc1jN+hQWnmrS/SVgXAqEKvBhXorr1 scLo2zrFX7zcgJRqhR1XGaRv5; Received: from [198.59.47.65] (port=52394 helo=[192.168.131.83]) by box5379.bluehost.com with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96.2) (envelope-from ) id 1rCMvR-001rpu-0s for gdb-patches@sourceware.org; Sun, 10 Dec 2023 09:45:05 -0700 From: Tom Tromey Date: Sun, 10 Dec 2023 09:45:06 -0700 Subject: [PATCH 17/17] Rewrite .debug_names writer MIME-Version: 1.0 Message-Id: <20231210-debug-names-fix-v1-17-a8f6d2525018@tromey.com> References: <20231210-debug-names-fix-v1-0-a8f6d2525018@tromey.com> In-Reply-To: <20231210-debug-names-fix-v1-0-a8f6d2525018@tromey.com> To: gdb-patches@sourceware.org X-Mailer: b4 0.12.4 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - box5379.bluehost.com X-AntiAbuse: Original Domain - sourceware.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - tromey.com X-BWhitelist: no X-Source-IP: 198.59.47.65 X-Source-L: No X-Exim-ID: 1rCMvR-001rpu-0s X-Source: X-Source-Args: X-Source-Dir: X-Source-Sender: ([192.168.131.83]) [198.59.47.65]:52394 X-Source-Auth: tom+tromey.com X-Email-Count: 18 X-Org: HG=bhshared;ORG=bluehost; X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTM3OS5ibHVlaG9zdC5jb20= X-Local-Domain: yes X-CMAE-Envelope: MS4xfCGCsfu5yr+HHjmJtu+G19l75Cl2+0dD3snJOLE+cQBbpptf9dWy1QOtMPO4Vqgm55CclWEkVCRU7tLjRnnJj84UCSiSwL+DXdvS1TCgGMNDjXUG/F/l 1cJRpQj1ty2/n6PQ1AQa9IrTzCD67n1m4YUxWe7dSp/y7RbOF82ZkyB8dPStD3OCfNdw86E//xgGnjk/olI1l705b/B8V7PQEuQ= X-Spam-Status: No, score=-3024.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, JMQ_SPF_NEUTRAL, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org This rewrites GDB's .debug_names writer. It is now closer to the form imagined in the DWARF spec. In particular, names are emitted exactly as they appear in the original DWARF. In order to make the reader work nicely, some extensions were needed. These were all documented in an earlier patch. Note that in particular this writer solves the "main name" problem by putting a flag into the table. GDB does not use the .debug_names hash table, so it also does not write one. I consider this hash table to be essentially useless in general, due to the name canonicalization problem -- while DWARF says that writers should use the system demangling style, (1) this style varies across systems, so it can't truly be relied on; and (2) at least GCC and one other compiler don't actually follow this part of the spec anyway. It's important to note, though, that even if the hash was somehow useful, GDB probably still would not use it -- a sorted list of names is needed for completion and performs reasonably well for other lookups, so a hash table is just overhead, IMO. String emission is also simplified. There's no need in this writer to ingest the contents of .debug_str. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=24820 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=24549 --- gdb/dwarf2/index-write.c | 395 +++++++++++++++++++---------------------------- 1 file changed, 156 insertions(+), 239 deletions(-) diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c index c23fa25e021..940c58e59bd 100644 --- a/gdb/dwarf2/index-write.c +++ b/gdb/dwarf2/index-write.c @@ -40,10 +40,12 @@ #include "ada-lang.h" #include "dwarf2/tag.h" #include "gdbsupport/gdb_tilde_expand.h" +#include "dwarf2/read-debug-names.h" #include #include #include +#include #include #include #include @@ -672,66 +674,15 @@ class debug_names /* Insert one symbol. */ void insert (const cooked_index_entry *entry) { - const auto it = m_cu_index_htab.find (entry->per_cu); - gdb_assert (it != m_cu_index_htab.cend ()); - const char *name = entry->full_name (&m_string_obstack); - - /* This is incorrect but it mirrors gdb's historical behavior; and - because the current .debug_names generation is also incorrect, - it seems better to follow what was done before, rather than - introduce a mismatch between the newer and older gdb. */ - dwarf_tag tag = entry->tag; - if (tag != DW_TAG_typedef && tag_is_type (tag)) - tag = DW_TAG_structure_type; - else if (tag == DW_TAG_enumerator || tag == DW_TAG_constant) - tag = DW_TAG_variable; - - int cu_index = it->second; - bool is_static = (entry->flags & IS_STATIC) != 0; - unit_kind kind = (entry->per_cu->is_debug_types - ? unit_kind::tu - : unit_kind::cu); - - if (entry->per_cu->lang () == language_ada) - { - /* We want to ensure that the Ada main function's name appears - verbatim in the index. However, this name will be of the - form "_ada_mumble", and will be rewritten by ada_decode. - So, recognize it specially here and add it to the index by - hand. */ - if (strcmp (main_name (), name) == 0) - { - const auto insertpair - = m_name_to_value_set.emplace (c_str_view (name), - std::set ()); - std::set &value_set = insertpair.first->second; - value_set.emplace (symbol_value (tag, cu_index, is_static, kind)); - } - - /* In order for the index to work when read back into gdb, it - has to supply a funny form of the name: it should be the - encoded name, with any suffixes stripped. Using the - ordinary encoded name will not work properly with the - searching logic in find_name_components_bounds; nor will - using the decoded name. Furthermore, an Ada "verbatim" - name (of the form "") must be entered without the - angle brackets. Note that the current index is unusual, - see PR symtab/24820 for details. */ - std::string decoded = ada_decode (name); - if (decoded[0] == '<') - name = (char *) obstack_copy0 (&m_string_obstack, - decoded.c_str () + 1, - decoded.length () - 2); - else - name = obstack_strdup (&m_string_obstack, - ada_encode (decoded.c_str ())); - } + /* These entries are synthesized by the reader, and so should not + be written. */ + if (entry->lang == language_ada && entry->tag == DW_TAG_namespace) + return; const auto insertpair - = m_name_to_value_set.emplace (c_str_view (name), - std::set ()); - std::set &value_set = insertpair.first->second; - value_set.emplace (symbol_value (tag, cu_index, is_static, kind)); + = m_name_to_value_set.try_emplace (c_str_view (entry->name)); + entry_list &elist = insertpair.first->second; + elist.entries.push_back (entry); } /* Build all the tables. All symbols must be already inserted. @@ -742,127 +693,137 @@ class debug_names /* Verify the build method has not be called twice. */ gdb_assert (m_abbrev_table.empty ()); const size_t name_count = m_name_to_value_set.size (); - m_bucket_table.resize - (std::pow (2, std::ceil (std::log2 (name_count * 4 / 3)))); - m_hash_table.reserve (name_count); m_name_table_string_offs.reserve (name_count); m_name_table_entry_offs.reserve (name_count); - /* Map each hash of symbol to its name and value. */ - struct hash_it_pair - { - uint32_t hash; - decltype (m_name_to_value_set)::const_iterator it; - }; - std::vector> bucket_hash; - bucket_hash.resize (m_bucket_table.size ()); - for (decltype (m_name_to_value_set)::const_iterator it - = m_name_to_value_set.cbegin (); - it != m_name_to_value_set.cend (); - ++it) - { - const char *const name = it->first.c_str (); - const uint32_t hash = dwarf5_djb_hash (name); - hash_it_pair hashitpair; - hashitpair.hash = hash; - hashitpair.it = it; - auto &slot = bucket_hash[hash % bucket_hash.size()]; - slot.push_front (std::move (hashitpair)); - } - for (size_t bucket_ix = 0; bucket_ix < bucket_hash.size (); ++bucket_ix) + /* The name table is indexed from 1. The numbers are needed here + so that parent entries can be handled correctly. */ + int next_name = 1; + for (auto &item : m_name_to_value_set) + item.second.index = next_name++; + + /* The next available abbrev number. */ + int next_abbrev = 1; + + for (auto &item : m_name_to_value_set) { - std::forward_list &hashitlist = bucket_hash[bucket_ix]; - if (hashitlist.empty ()) - continue; + const c_str_view &name = item.first; + entry_list &these_entries = item.second; /* Sort the items within each bucket. This ensures that the generated index files will be the same no matter the order in which symbols were added into the index. */ - hashitlist.sort ([] (const hash_it_pair &a, const hash_it_pair &b) - { - return a.it->first < b.it->first; - }); - - uint32_t &bucket_slot = m_bucket_table[bucket_ix]; - /* The hashes array is indexed starting at 1. */ - store_unsigned_integer (reinterpret_cast (&bucket_slot), - sizeof (bucket_slot), m_dwarf5_byte_order, - m_hash_table.size () + 1); - for (const hash_it_pair &hashitpair : hashitlist) + std::sort (these_entries.entries.begin (), + these_entries.entries.end (), + [] (const cooked_index_entry *a, + const cooked_index_entry *b) + { + /* Sort first by CU. */ + if (a->per_cu->index != b->per_cu->index) + return a->per_cu->index < b->per_cu->index; + /* Then by DIE in the CU. */ + if (a->die_offset != b->die_offset) + return a->die_offset < b->die_offset; + /* We might have two entries for a DIE because + the linkage name is entered separately. So, + sort by flags. */ + return a->flags < b->flags; + }); + + m_name_table_string_offs.push_back_reorder + (m_debugstrlookup.lookup (name.c_str ())); /* ??? */ + m_name_table_entry_offs.push_back_reorder (m_entry_pool.size ()); + + for (const cooked_index_entry *entry : these_entries.entries) { - m_hash_table.push_back (0); - store_unsigned_integer (reinterpret_cast - (&m_hash_table.back ()), - sizeof (m_hash_table.back ()), - m_dwarf5_byte_order, hashitpair.hash); - const c_str_view &name = hashitpair.it->first; - const std::set &value_set = hashitpair.it->second; - m_name_table_string_offs.push_back_reorder - (m_debugstrlookup.lookup (name.c_str ())); - m_name_table_entry_offs.push_back_reorder (m_entry_pool.size ()); - gdb_assert (!value_set.empty ()); - for (const symbol_value &value : value_set) + unit_kind kind = (entry->per_cu->is_debug_types + ? unit_kind::tu + : unit_kind::cu); + /* Currently Ada parentage is synthesized by the + reader and so must be ignored here. */ + const cooked_index_entry *parent = (entry->lang == language_ada + ? nullptr + : entry->parent_entry); + + int &idx = m_indexkey_to_idx[index_key (entry->tag, + kind, + entry->flags, + entry->lang, + parent != nullptr)]; + if (idx == 0) { - int &idx = m_indexkey_to_idx[index_key (value.dwarf_tag, - value.is_static, - value.kind)]; - if (idx == 0) + idx = next_abbrev++; + m_abbrev_table.append_unsigned_leb128 (idx); + m_abbrev_table.append_unsigned_leb128 (entry->tag); + m_abbrev_table.append_unsigned_leb128 + (kind == unit_kind::cu + ? DW_IDX_compile_unit + : DW_IDX_type_unit); + m_abbrev_table.append_unsigned_leb128 (DW_FORM_udata); + m_abbrev_table.append_unsigned_leb128 (DW_IDX_die_offset); + m_abbrev_table.append_unsigned_leb128 (DW_FORM_udata); + m_abbrev_table.append_unsigned_leb128 (DW_IDX_GNU_language); + m_abbrev_table.append_unsigned_leb128 (DW_FORM_udata); + if ((entry->flags & IS_STATIC) != 0) { - idx = m_idx_next++; - m_abbrev_table.append_unsigned_leb128 (idx); - m_abbrev_table.append_unsigned_leb128 (value.dwarf_tag); - m_abbrev_table.append_unsigned_leb128 - (value.kind == unit_kind::cu ? DW_IDX_compile_unit - : DW_IDX_type_unit); - m_abbrev_table.append_unsigned_leb128 (DW_FORM_udata); - m_abbrev_table.append_unsigned_leb128 (value.is_static - ? DW_IDX_GNU_internal - : DW_IDX_GNU_external); + m_abbrev_table.append_unsigned_leb128 (DW_IDX_GNU_internal); m_abbrev_table.append_unsigned_leb128 (DW_FORM_flag_present); - - /* Terminate attributes list. */ - m_abbrev_table.append_unsigned_leb128 (0); - m_abbrev_table.append_unsigned_leb128 (0); + } + if ((entry->flags & IS_MAIN) != 0) + { + m_abbrev_table.append_unsigned_leb128 (DW_IDX_GNU_main); + m_abbrev_table.append_unsigned_leb128 (DW_FORM_flag_present); + } + if ((entry->flags & IS_LINKAGE) != 0) + { + m_abbrev_table.append_unsigned_leb128 (DW_IDX_GNU_linkage_name); + m_abbrev_table.append_unsigned_leb128 (DW_FORM_flag_present); + } + if (parent != nullptr) + { + m_abbrev_table.append_unsigned_leb128 (DW_IDX_parent); + m_abbrev_table.append_unsigned_leb128 (DW_FORM_udata); } - m_entry_pool.append_unsigned_leb128 (idx); - m_entry_pool.append_unsigned_leb128 (value.cu_index); + /* Terminate attributes list. */ + m_abbrev_table.append_unsigned_leb128 (0); + m_abbrev_table.append_unsigned_leb128 (0); } - /* Terminate the list of CUs. */ - m_entry_pool.append_unsigned_leb128 (0); + m_entry_pool.append_unsigned_leb128 (idx); + + const auto it = m_cu_index_htab.find (entry->per_cu); + gdb_assert (it != m_cu_index_htab.cend ()); + m_entry_pool.append_unsigned_leb128 (it->second); + + m_entry_pool.append_unsigned_leb128 (to_underlying (entry->die_offset)); + m_entry_pool.append_unsigned_leb128 (entry->per_cu->dw_lang ()); + + if (parent != nullptr) + { + c_str_view par_name (parent->name); + auto name_iter = m_name_to_value_set.find (par_name); + gdb_assert (name_iter != m_name_to_value_set.end ()); + gdb_assert (name_iter->second.index != 0); + m_entry_pool.append_unsigned_leb128 (name_iter->second.index); + } } + + /* Terminate the list of entries. */ + m_entry_pool.append_unsigned_leb128 (0); } - gdb_assert (m_hash_table.size () == name_count); /* Terminate tags list. */ m_abbrev_table.append_unsigned_leb128 (0); } - /* Return .debug_names bucket count. This must be called only after - calling the build method. */ - uint32_t bucket_count () const - { - /* Verify the build method has been already called. */ - gdb_assert (!m_abbrev_table.empty ()); - const uint32_t retval = m_bucket_table.size (); - - /* Check for overflow. */ - gdb_assert (retval == m_bucket_table.size ()); - return retval; - } - /* Return .debug_names names count. This must be called only after calling the build method. */ uint32_t name_count () const { /* Verify the build method has been already called. */ gdb_assert (!m_abbrev_table.empty ()); - const uint32_t retval = m_hash_table.size (); - - /* Check for overflow. */ - gdb_assert (retval == m_hash_table.size ()); - return retval; + return m_name_to_value_set.size (); } /* Return number of bytes of .debug_names abbreviation table. This @@ -880,8 +841,6 @@ class debug_names /* Verify the build method has been already called. */ gdb_assert (!m_abbrev_table.empty ()); size_t expected_bytes = 0; - expected_bytes += m_bucket_table.size () * sizeof (m_bucket_table[0]); - expected_bytes += m_hash_table.size () * sizeof (m_hash_table[0]); expected_bytes += m_name_table_string_offs.bytes (); expected_bytes += m_name_table_entry_offs.bytes (); expected_bytes += m_abbrev_table.size (); @@ -896,8 +855,6 @@ class debug_names { /* Verify the build method has been already called. */ gdb_assert (!m_abbrev_table.empty ()); - ::file_write (file_names, m_bucket_table); - ::file_write (file_names, m_hash_table); m_name_table_string_offs.file_write (file_names); m_name_table_entry_offs.file_write (file_names); m_abbrev_table.file_write (file_names); @@ -918,29 +875,11 @@ class debug_names { public: - /* Object constructor to be called for current DWARF2_PER_BFD. - All .debug_str section strings are automatically stored. */ + /* Object constructor to be called for current DWARF2_PER_BFD. */ debug_str_lookup (dwarf2_per_bfd *per_bfd) : m_abfd (per_bfd->obfd), m_per_bfd (per_bfd) { - gdb_assert (per_bfd->str.readin); - if (per_bfd->str.buffer == NULL) - return; - for (const gdb_byte *data = per_bfd->str.buffer; - data < (per_bfd->str.buffer - + per_bfd->str.size);) - { - const char *const s = reinterpret_cast (data); - const auto insertpair - = m_str_table.emplace (c_str_view (s), - data - per_bfd->str.buffer); - if (!insertpair.second) - complaint (_("Duplicate string \"%s\" in " - ".debug_str section [in module %s]"), - s, bfd_get_filename (m_abfd)); - data += strlen (s) + 1; - } } /* Return offset of symbol name S in the .debug_str section. Add @@ -948,6 +887,13 @@ class debug_names yet. */ size_t lookup (const char *s) { + /* Most strings will have come from the string table + already. */ + const gdb_byte *b = (const gdb_byte *) s; + if (b >= m_per_bfd->str.buffer + && b < m_per_bfd->str.buffer + m_per_bfd->str.size) + return b - m_per_bfd->str.buffer; + const auto it = m_str_table.find (c_str_view (s)); if (it != m_str_table.end ()) return it->second; @@ -978,66 +924,41 @@ class debug_names class index_key { public: - index_key (int dwarf_tag_, bool is_static_, unit_kind kind_) - : dwarf_tag (dwarf_tag_), is_static (is_static_), kind (kind_) + index_key (dwarf_tag tag_, unit_kind kind_, cooked_index_flag flags_, + enum language lang_, bool has_parent_) + : tag (tag_), + kind (kind_), + flags (flags_ & ~IS_TYPE_DECLARATION), + lang (lang_), + has_parent (has_parent_) { } - bool - operator== (const index_key &other) const + bool operator== (const index_key &other) const { - return (dwarf_tag == other.dwarf_tag && is_static == other.is_static - && kind == other.kind); + return (tag == other.tag + && kind == other.kind + && flags == other.flags + && lang == other.lang + && has_parent == other.has_parent); } - const int dwarf_tag; - const bool is_static; + const dwarf_tag tag; const unit_kind kind; + const cooked_index_flag flags; + const enum language lang; + const bool has_parent; }; /* Provide std::unordered_map::hasher for index_key. */ class index_key_hasher { public: - size_t - operator () (const index_key &key) const - { - return (std::hash() (key.dwarf_tag) << 1) | key.is_static; - } - }; - - /* Parameters of one symbol entry. */ - class symbol_value - { - public: - const int dwarf_tag, cu_index; - const bool is_static; - const unit_kind kind; - - symbol_value (int dwarf_tag_, int cu_index_, bool is_static_, - unit_kind kind_) - : dwarf_tag (dwarf_tag_), cu_index (cu_index_), is_static (is_static_), - kind (kind_) - {} - - bool - operator< (const symbol_value &other) const + size_t operator () (const index_key &key) const { -#define X(n) \ - do \ - { \ - if (n < other.n) \ - return true; \ - if (n > other.n) \ - return false; \ - } \ - while (0) - X (dwarf_tag); - X (is_static); - X (kind); - X (cu_index); -#undef X - return false; + return (std::hash() (key.tag) + ^ std::hash() (key.flags) + ^ std::hash() (key.lang)); } }; @@ -1139,14 +1060,15 @@ class debug_names offset_vec_tmpl m_name_table_entry_offs; }; - /* Store value of each symbol. */ - std::unordered_map, c_str_view_hasher> - m_name_to_value_set; + struct entry_list + { + unsigned index = 0; + std::vector entries; + }; - /* Tables of DWARF-5 .debug_names. They are in object file byte - order. */ - std::vector m_bucket_table; - std::vector m_hash_table; + /* Store value of each symbol. Note that we rely on the sorting + behavior of map to make the output stable. */ + std::map m_name_to_value_set; const bfd_endian m_dwarf5_byte_order; dwarf_tmpl m_dwarf32; @@ -1159,10 +1081,6 @@ class debug_names index value. */ std::unordered_map m_indexkey_to_idx; - /* Next unused .debug_names abbreviation tag for - m_indexkey_to_idx. */ - int m_idx_next = 1; - /* .debug_names abbreviation table. */ data_buf m_abbrev_table; @@ -1441,9 +1359,6 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table, gdb_assert (dwz_cu_list.empty ()); } -/* DWARF-5 augmentation string for GDB's DW_IDX_GNU_* extension. */ -static const gdb_byte dwarf5_gdb_augmentation[] = { 'G', 'D', 'B', 0 }; - /* Write a new .debug_names section for OBJFILE into OUT_FILE, write needed addition to .debug_str section to OUT_FILE_STR. Return how many bytes were expected to be written into OUT_FILE. */ @@ -1492,7 +1407,7 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table, const offset_type bytes_of_header = ((dwarf5_is_dwarf64 ? 12 : 4) + 2 + 2 + 7 * 4 - + sizeof (dwarf5_gdb_augmentation)); + + sizeof (dwarf5_augmentation)); size_t expected_bytes = 0; expected_bytes += bytes_of_header; expected_bytes += cu_list.size (); @@ -1530,8 +1445,10 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table, header.append_uint (4, dwarf5_byte_order, 0); /* bucket_count - The number of hash buckets in the hash lookup - table. */ - header.append_uint (4, dwarf5_byte_order, nametable.bucket_count ()); + table. GDB does not use the hash table, so there's also no need + to write it -- plus, the hash table is broken as defined due to + the lack of name canonicalization. */ + header.append_uint (4, dwarf5_byte_order, 0); /* name_count - The number of unique names in the index. */ header.append_uint (4, dwarf5_byte_order, nametable.name_count ()); @@ -1542,9 +1459,9 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table, /* augmentation_string_size - The size in bytes of the augmentation string. This value is rounded up to a multiple of 4. */ - static_assert (sizeof (dwarf5_gdb_augmentation) % 4 == 0, ""); - header.append_uint (4, dwarf5_byte_order, sizeof (dwarf5_gdb_augmentation)); - header.append_array (dwarf5_gdb_augmentation); + static_assert (sizeof (dwarf5_augmentation) % 4 == 0); + header.append_uint (4, dwarf5_byte_order, sizeof (dwarf5_augmentation)); + header.append_array (dwarf5_augmentation); gdb_assert (header.size () == bytes_of_header);