From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from AUS01-SY4-obe.outbound.protection.outlook.com (mail-sy4aus01olkn2183.outbound.protection.outlook.com [40.92.62.183]) by sourceware.org (Postfix) with ESMTPS id 11A6C3858D3C for ; Thu, 14 Apr 2022 05:33:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 11A6C3858D3C ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=gctdRYSFHWgUbxtG+qXYTAhKc20qmZOOm99QcBMRWmKD4pqOzCQVkMwb8qP3Syr5cu5ljT0MS/0tmNIUktsd+sjj0dQr5lGyPjaDNNh6e9ftha1JCYSTcaW0IW5OpYGw6bCvxiw2NexBbHnFeBy5R37CKwlHCIdjgbIgXxElXFYqKs6IJKZFo7qa5RDkzRa6eSDx1jiqKKu9kwtLwkFcDMIqJY0ueZmRZIIErQN9D6lyiTY0mFIK4KRaN4L8HRN9sgHkBIuO44ivbNFFYvnqYh9GuW1T73hb811KSAaHlNmW/bxPBcqkfDClGJOY6iiGxO22CE/BmGZg7G0eSjqZXA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=A7c01AJLZQK1OiMG+DtiKI5xOk88ktQKtyPrZPb+WwY=; b=mN7DWOs063g0ck4PyJy8jA2bqOJd5mUr1YHhWxrq5RyidSoZGMi/YucDZhxaJ7u31fspJpGj94kWGiMrB6gS0PhI+eahyX/6trcKe6JTkc2hf3o8oYjzjAcdoTOtFpgmtHnrpbl3IUli7atAQ/wC3ryXX5F56vEfn5wZ4GnF3JF9qsrjQ1GGnKpB27Wi7T6e7krJPO0ITFTLF/sF+Mh56SSNNMyzDAWNtFTVP6tCWBedM2ad5FFMhyziMilfi1PZGn1yNvuCNEywFcyb50hwatDshUYVeRFFEL7z3DFyT23e8pnrXV0tjmFZQyibEQOZBcvITCR+xfSP87w95fZHbg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none Received: from MEAP282MB0293.AUSP282.PROD.OUTLOOK.COM (2603:10c6:220:71::10) by MEYP282MB3261.AUSP282.PROD.OUTLOOK.COM (2603:10c6:220:161::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5164.18; Thu, 14 Apr 2022 05:33:02 +0000 Received: from MEAP282MB0293.AUSP282.PROD.OUTLOOK.COM ([fe80::5804:c2bb:bc94:3cec]) by MEAP282MB0293.AUSP282.PROD.OUTLOOK.COM ([fe80::5804:c2bb:bc94:3cec%6]) with mapi id 15.20.5144.030; Thu, 14 Apr 2022 05:32:56 +0000 Message-ID: Subject: Re: [PATCH v4 18/34] Introduce the new DWARF index class From: Enze Li To: Tom Tromey Cc: gdb-patches@sourceware.org Date: Thu, 14 Apr 2022 13:32:39 +0800 In-Reply-To: <20220404195335.2111906-19-tom@tromey.com> References: <20220404195335.2111906-1-tom@tromey.com> <20220404195335.2111906-19-tom@tromey.com> Content-Type: text/plain; charset="UTF-8" User-Agent: Evolution 3.36.5-0ubuntu1 Content-Transfer-Encoding: 7bit X-TMN: [sgsp1wSAKYBulkDKN9bliSDgT11JhEUn] X-ClientProxiedBy: HKAPR04CA0010.apcprd04.prod.outlook.com (2603:1096:203:d0::20) To MEAP282MB0293.AUSP282.PROD.OUTLOOK.COM (2603:10c6:220:71::10) X-Microsoft-Original-Message-ID: <62a028e30be751afe942e2962dad7eddd68fa40a.camel@hotmail.com> MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 7cded1a8-fc6b-41a8-e61c-08da1dd83a6c X-MS-TrafficTypeDiagnostic: MEYP282MB3261:EE_ X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: zYbXlw0RmGtLU60CVlBePbgRSnPO2ZTlupOt0MW0JsDtvchsJ9jWPz0MP9paFsJmjjaBVo1OrkWdbGgNDZDow7UmM1hlmMOzPiCrdsrfHcV5nqb30NOtLjHgNyYB3oklOaVK79guPFOF9whCzSP+VHGT1AKFW2D837UEYSYMalIyOQR1n/HgBY4kdqwCOdLznbG88kDET5uBI9YNIWN96M3lSZPS+GNihulCsMiIJk8tz3LgIs1s1PzTa7zSbNU/jh/6/9pDlYupOqaygv3EAbXeLRZHngkQxyjrOC0HonW0Z7O1krZxAA59hslNWvXCQZzmWeivSmLs4NBk47RwOSB9ZQzwQjZQ36VbiUwsNCb6dWKf+4lrr2PyslZhUI1gR/CmhOaZnwtHaesNIS8FYiCXecJAUbmk4CR/h6WLyJcYs1AaV+SHac52ioTa3aTI/RJszv2/yUEafCtR9r8Ad9XsNv1qUp7U+X0XuPNmxw0v1cON8StsHw7BlTpUksc14QpHbXkETcYIaZ0qfZPZbLLd6i8kw38NJnBpHpiKZPqp9FfPkPOfiqldWWj38sPt5yzfKxU0a2DB7Gz83Gbtg9zQnf0huGDSg+mwBZ/IqE4BXG/CG0UySPZcqSK3ZVaO X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?MGlQdkw4dllJcHZ4MnhITUNnTjZnWGRXWXl3Z1o1Q3QrcGNTbXJ4RmtRZXdq?= =?utf-8?B?RW5mNG9YK3ZmSGZUTHB6eUxKUDBHbnV3blFsWm1aK2RxSnYrdG1HR2tIQS9B?= =?utf-8?B?Wmx0WGNHYy9icFN0QzRBVGpyWUVnMndRZU5OanRwbVlCMWgySGxDRDVIUFVt?= =?utf-8?B?dk1iMWp6RXBwYlU2SVZteUl4bElzd083S0xicDFSbWhlbHJ0MzBQNlloUUVW?= =?utf-8?B?elVNeGZjWHRwZlNzR1FJTUJ2V00xb21Ub1c2QS8zZXNqV2VIY25aMjIwV1Y5?= =?utf-8?B?SERMeVZUVmFYNFhQblR2bnIvaWRYTDhxNk1ocjh4TFZhUFM2U0ltVjk1Vllo?= =?utf-8?B?NEw4UTZPQ2hMTXBseFdra21lejJ5MlErcGxaWjFCR2YxNTRFam9PN0pJVjV4?= =?utf-8?B?ZlpZYlhYVUlWK0lkSWlObytlbUxEdFhPbVNTNmlDRitpQ1VpM2E1NG05OGho?= =?utf-8?B?ckl3RHM4dUY4Q242eCtMKzBqdmRBNE1ONFkydTVWWjd5SWRORGFnYWYxVURZ?= =?utf-8?B?bXlsc2hiTEYyclZOelhaS01wd2dORStpSi81enNDQXlXaVRTekZKTS9uZXVZ?= =?utf-8?B?WWtIYmtvQkF5MjUrS0ZGVGU4ODUwUG9UT2dYaTFZSzhLenJRQmVmOHBzczVn?= =?utf-8?B?SDFGTFRFbEl6cXBwc3VyMGszRWJHMnlUcXlqYTdxQUdZaTIvNC9oWTV6RTFu?= =?utf-8?B?T09Kd25wcmhJSWI2bEIyL3A4cm56N2N2Zi8vd3BqU2pVZ2V0MjdWNmdZVXVj?= =?utf-8?B?VDNpODFSMmdRcTlpcFR3OXhMRFRSZjdmaE5pSW5aN0NGanRIc0phd1Nac0cw?= =?utf-8?B?bkc5OUtOOTFQbE0vK1JjN01leHlvNnlKMkpPSWRYc3BidlBuYllVMXBmRDlB?= =?utf-8?B?RFZoZUV5RHE0RmM1WFBDMEthNlZLSWJGdnZlYy9abDJERGhSSmZ5bGxkVUtL?= =?utf-8?B?S1FFV1JrQkhRb0FRM3hucURnTktROWRHZG9zc3kzRG1hZVJpaDNjUk9weTI4?= =?utf-8?B?dW9RT0YyYTliT1dUZ0JlbGpmWWlySEZaUEp1VjdyeGJyZjliSGdGbzFycFFR?= =?utf-8?B?cDQxci9wY29VZHhrekZjNllBbFRCTEJrUXpiQkhSSXd4Z1huU21NZ2tlTG5i?= =?utf-8?B?RDRFVjU0MnBuYjloRHlGU05uM2ZoNTV5S0JveEplNWQ5QjVTVmozbFpYck9a?= =?utf-8?B?T3VhYnV4R1dPcHVzSHYyMGJrMDdEcWx0QUtWQThCUnhrNmhPUCtmMUFoL1Rw?= =?utf-8?B?TUxMck4zc0RDQmx5S0NJcHVjT2RkaEljdEd1YTNLQnJWaFJPajdWQWl5U01R?= =?utf-8?B?Tm9mcnF0eDNVTUdQMnNTeFdFSXVmSGxLcnF2aTlubU9vZ2FwYXZDSW9xQ3N5?= =?utf-8?B?MFlRNG1lU1EzbStiMVcxbzh4bU4rM2hHYitxbWEzeE5FNm56RVV5bHBmRWtS?= =?utf-8?B?RVVDQnRGMFlpV1FYWC9NODBrR0ZycmhadjY2RDd4czNxYW9YN0hzWmtjSDBM?= =?utf-8?B?UzRsLzRNSStUUVVJYzdLaU5LUWc1SXJQVDVNOExnTkZib0EwTjZ0TTdqRE1l?= =?utf-8?B?cEdDQkRjTDZCa2tka1Q5SThjS2pOTmVUNi9JY2ZuOWJmTUh5RWxDR0o5Y3Rh?= =?utf-8?B?L3JSS2xhUkJGTVZ2Mlh4TDgwQnJFNWtFTjgvOEVzeXQ3RllWeFp6UzYrbWNs?= =?utf-8?B?dDRIeWZDNHczM3hOeHZPZk9QNXpXM2pEajZjblcvWktKN2RhTUdWU3kyQ1BV?= =?utf-8?B?c0NBUHNRVG9JTC8rZ2FnaUp3MjQxRzFUSnRjUU5uUGRpSFBzQmVWWWtGK2pp?= =?utf-8?B?Qk85cDFBSXcrY2d0V1diNitkNG5ZRFRZbFlIU2pFOTV4QmdaOHJndXpZV0tx?= =?utf-8?B?eTd5ZTBkbU9IUE1pcjZYSzBOUGZONjhkVUdwbDd2RHJPcStBVkpvdGxZclZa?= =?utf-8?Q?RSc8dZFAW+U=3D?= X-OriginatorOrg: sct-15-20-4755-11-msonline-outlook-746f3.templateTenant X-MS-Exchange-CrossTenant-Network-Message-Id: 7cded1a8-fc6b-41a8-e61c-08da1dd83a6c X-MS-Exchange-CrossTenant-AuthSource: MEAP282MB0293.AUSP282.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 14 Apr 2022 05:32:56.9514 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: MEYP282MB3261 X-Spam-Status: No, score=-10.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, GIT_PATCH_0, KAM_ASCII_DIVIDERS, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 14 Apr 2022 05:33:11 -0000 Hi Tom, >From this commit 51f5a4b8e93("Introduce the new DWARF index class"), I ran into this error: =================================================================== CXX dwarf2/cooked-index.o In file included from dwarf2/cooked-index.c:21: ./dwarf2/cooked-index.h:169:12: error: explicitly defaulted move constructor is implicitly deleted [-Werror,-Wdefaulted-function- deleted] explicit cooked_index (cooked_index &&other) = default; ^ ./dwarf2/cooked-index.h:247:16: note: move constructor of 'cooked_index' is implicitly deleted because field 'm_storage' has a deleted move constructor auto_obstack m_storage; ^ ./../gdbsupport/gdb_obstack.h:128:28: note: 'auto_obstack' has been explicitly marked deleted here DISABLE_COPY_AND_ASSIGN (auto_obstack); ^ In file included from dwarf2/cooked-index.c:21: ./dwarf2/cooked-index.h:171:17: error: explicitly defaulted move assignment operator is implicitly deleted [-Werror,-Wdefaulted- function-deleted] cooked_index &operator= (cooked_index &&other) = default; ^ ./dwarf2/cooked-index.h:247:16: note: move assignment operator of 'cooked_index' is implicitly deleted because field 'm_storage' has a deleted move assignment operator auto_obstack m_storage; ^ ./../gdbsupport/gdb_obstack.h:128:3: note: 'operator=' has been explicitly marked deleted here DISABLE_COPY_AND_ASSIGN (auto_obstack); ^ ./../include/ansidecl.h:425:8: note: expanded from macro 'DISABLE_COPY_AND_ASSIGN' void operator= (const TYPE &) = delete ^ 2 errors generated. make[2]: *** [Makefile:1892: dwarf2/cooked-index.o] Error 1 =================================================================== This happens on Fedora 35 with clang13 and Ubuntu 22.04 with clang14. Thanks, Enze On Mon, 2022-04-04 at 13:53 -0600, Tom Tromey wrote: > This patch introduces the new DWARF index class. It is called > "cooked" to contrast against a "raw" index, which is mapped from disk > without extra effort. > > Nothing constructs a cooked index yet. The essential idea here is > that index entries are created via the "add" method; then when all > the > entries have been read, they are "finalize"d -- name canonicalization > is performed and the entries are added to a sorted vector. > > Entries use the DWARF name (DW_AT_name) or linkage name, not the full > name as is done for partial symbols. > > These two facets -- the short name and the deferred canonicalization > -- help improve the performance of this approach. This will become > clear in later patches, when parallelization is added. > > Some special code is needed for Ada, because GNAT only emits mangled > ("encoded", in the Ada lingo) names, and so we reconstruct the > hierarchical structure after the fact. This is also done in the > finalization phase. > > One other aspect worth noting is that the way the "main" function is > found is different in the new code. Currently gdb will notice > DW_AT_main_subprogram, but won't recognize "main" during reading -- > this is done later, via explicit symbol lookup. This is done > differently in the new code so that finalization can be done in the > background without then requiring a synchronization to look up the > symbol. > --- > gdb/Makefile.in | 2 + > gdb/dwarf2/cooked-index.c | 274 > ++++++++++++++++++++++++++++++++++++++ > gdb/dwarf2/cooked-index.h | 260 ++++++++++++++++++++++++++++++++++++ > 3 files changed, 536 insertions(+) > create mode 100644 gdb/dwarf2/cooked-index.c > create mode 100644 gdb/dwarf2/cooked-index.h > > diff --git a/gdb/Makefile.in b/gdb/Makefile.in > index ab1bdd1d28a..cbae7803813 100644 > --- a/gdb/Makefile.in > +++ b/gdb/Makefile.in > @@ -1047,6 +1047,7 @@ COMMON_SFILES = \ > dwarf2/abbrev-cache.c \ > dwarf2/attribute.c \ > dwarf2/comp-unit-head.c \ > + dwarf2/cooked-index.c \ > dwarf2/cu.c \ > dwarf2/dwz.c \ > dwarf2/expr.c \ > @@ -1293,6 +1294,7 @@ HFILES_NO_SRCDIR = \ > dictionary.h \ > disasm.h \ > dummy-frame.h \ > + dwarf2/cooked-index.h \ > dwarf2/cu.h \ > dwarf2/frame-tailcall.h \ > dwarf2/frame.h \ > diff --git a/gdb/dwarf2/cooked-index.c b/gdb/dwarf2/cooked-index.c > new file mode 100644 > index 00000000000..374540f09da > --- /dev/null > +++ b/gdb/dwarf2/cooked-index.c > @@ -0,0 +1,274 @@ > +/* DIE indexing > + > + Copyright (C) 2021 Free Software Foundation, Inc. > + > + This file is part of GDB. > + > + This program is free software; you can redistribute it and/or > modify > + it under the terms of the GNU General Public License as published > by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see < > http://www.gnu.org/licenses/>;. */ > + > +#include "defs.h" > +#include "dwarf2/cooked-index.h" > +#include "dwarf2/read.h" > +#include "cp-support.h" > +#include "ada-lang.h" > +#include "split-name.h" > +#include > + > +/* Hash function for cooked_index_entry. */ > + > +static hashval_t > +hash_entry (const void *e) > +{ > + const cooked_index_entry *entry = (const cooked_index_entry *) e; > + return dwarf5_djb_hash (entry->canonical); > +} > + > +/* Equality function for cooked_index_entry. */ > + > +static int > +eq_entry (const void *a, const void *b) > +{ > + const cooked_index_entry *ae = (const cooked_index_entry *) a; > + const gdb::string_view *sv = (const gdb::string_view *) b; > + return (strlen (ae->canonical) == sv->length () > + && strncasecmp (ae->canonical, sv->data (), sv->length ()) == > 0); > +} > + > +/* See cooked-index.h. */ > + > +const char * > +cooked_index_entry::full_name (struct obstack *storage) const > +{ > + if ((flags & IS_LINKAGE) != 0) > + return canonical; > + > + const char *sep = nullptr; > + switch (per_cu->lang) > + { > + case language_cplus: > + case language_rust: > + sep = "::"; > + break; > + > + case language_go: > + case language_d: > + case language_ada: > + sep = "."; > + break; > + } > + > + if (sep == nullptr) > + return canonical; > + > + const cooked_index_entry *parent = parent_entry; > + if (tag == DW_TAG_enumeration_type && (flags & IS_ENUM_CLASS) == > 0) > + parent = parent->parent_entry; > + > + if (parent != nullptr) > + parent->write_scope (storage, sep); > + obstack_grow0 (storage, canonical, strlen (canonical)); > + return (const char *) obstack_finish (storage); > +} > + > +/* See cooked-index.h. */ > + > +void > +cooked_index_entry::write_scope (struct obstack *storage, > + const char *sep) const > +{ > + if (parent_entry != nullptr) > + parent_entry->write_scope (storage, sep); > + obstack_grow (storage, canonical, strlen (canonical)); > + obstack_grow (storage, sep, strlen (sep)); > +} > + > +/* See cooked-index.h. */ > + > +const cooked_index_entry * > +cooked_index::add (sect_offset die_offset, enum dwarf_tag tag, > + cooked_index_flag flags, const char *name, > + const cooked_index_entry *parent_entry, > + dwarf2_per_cu_data *per_cu) > +{ > + cooked_index_entry *result = create (die_offset, tag, flags, name, > + parent_entry, per_cu); > + m_entries.push_back (result); > + > + /* An explicitly-tagged main program should always override the > + implicit "main" discovery. */ > + if ((flags & IS_MAIN) != 0) > + m_main = result; > + else if (per_cu->lang != language_ada > + && m_main == nullptr > + && strcmp (name, "main") == 0) > + m_main = result; > + > + return result; > +} > + > +/* See cooked-index.h. */ > + > +cooked_index::range > +cooked_index::find (gdb::string_view name, bool completing) > +{ > + auto lower = std::lower_bound (m_entries.begin (), m_entries.end > (), > + name, > + [=] (const cooked_index_entry *entry, > + const gdb::string_view &n) > + { > + int cmp = strncasecmp (entry->canonical, n.data (), n.length > ()); > + if (cmp != 0 || completing) > + return cmp < 0; > + return strlen (entry->canonical) < n.length (); > + }); > + > + auto upper = std::upper_bound (m_entries.begin (), m_entries.end > (), > + name, > + [=] (const gdb::string_view &n, > + const cooked_index_entry *entry) > + { > + int cmp = strncasecmp (n.data (), entry->canonical, n.length > ()); > + if (cmp != 0 || completing) > + return cmp < 0; > + return n.length () < strlen (entry->canonical); > + }); > + > + return range (lower, upper); > +} > + > +/* See cooked-index.h. */ > + > +gdb::unique_xmalloc_ptr > +cooked_index::handle_gnat_encoded_entry (cooked_index_entry *entry, > + htab_t gnat_entries) > +{ > + std::string canonical = ada_decode (entry->name, false, false); > + if (canonical.empty ()) > + return {}; > + std::vector names = split_name (canonical.c_str > (), > + split_style::DOT); > + gdb::string_view tail = names.back (); > + names.pop_back (); > + > + const cooked_index_entry *parent = nullptr; > + for (const auto &name : names) > + { > + uint32_t hashval = dwarf5_djb_hash (name); > + void **slot = htab_find_slot_with_hash (gnat_entries, &name, > + hashval, INSERT); > + /* CUs are processed in order, so we only need to check the > most > + recent entry. */ > + cooked_index_entry *last = (cooked_index_entry *) *slot; > + if (last == nullptr || last->per_cu != entry->per_cu) > + { > + gdb::unique_xmalloc_ptr new_name > + = make_unique_xstrndup (name.data (), name.length ()); > + last = create (entry->die_offset, DW_TAG_namespace, > + 0, new_name.get (), parent, > + entry->per_cu); > + last->canonical = last->name; > + m_names.push_back (std::move (new_name)); > + *slot = last; > + } > + > + parent = last; > + } > + > + entry->parent_entry = parent; > + return make_unique_xstrndup (tail.data (), tail.length ()); > +} > + > +/* See cooked-index.h. */ > + > +void > +cooked_index::finalize () > +{ > + auto hash_name_ptr = [] (const void *p) > + { > + const cooked_index_entry *entry = (const cooked_index_entry *) > p; > + return htab_hash_pointer (entry->name); > + }; > + > + auto eq_name_ptr = [] (const void *a, const void *b) -> int > + { > + const cooked_index_entry *ea = (const cooked_index_entry *) a; > + const cooked_index_entry *eb = (const cooked_index_entry *) b; > + return ea->name == eb->name; > + }; > + > + /* We can use pointer equality here because names come from > + .debug_str, which will normally be unique-ified by the linker. > + Also, duplicates are relatively harmless -- they just mean a > bit > + of extra memory is used. */ > + htab_up seen_names (htab_create_alloc (10, hash_name_ptr, > eq_name_ptr, > + nullptr, xcalloc, xfree)); > + > + htab_up gnat_entries (htab_create_alloc (10, hash_entry, eq_entry, > + nullptr, xcalloc, xfree)); > + > + for (cooked_index_entry *entry : m_entries) > + { > + gdb_assert (entry->canonical == nullptr); > + if ((entry->per_cu->lang != language_cplus > + && entry->per_cu->lang != language_ada) > + || (entry->flags & IS_LINKAGE) != 0) > + entry->canonical = entry->name; > + else > + { > + if (entry->per_cu->lang == language_ada) > + { > + gdb::unique_xmalloc_ptr canon_name > + = handle_gnat_encoded_entry (entry, gnat_entries.get > ()); > + if (canon_name == nullptr) > + entry->canonical = entry->name; > + else > + { > + entry->canonical = canon_name.get (); > + m_names.push_back (std::move (canon_name)); > + } > + } > + else > + { > + void **slot = htab_find_slot (seen_names.get (), entry, > + INSERT); > + if (*slot == nullptr) > + { > + gdb::unique_xmalloc_ptr canon_name > + = cp_canonicalize_string (entry->name); > + if (canon_name == nullptr) > + entry->canonical = entry->name; > + else > + { > + entry->canonical = canon_name.get (); > + m_names.push_back (std::move (canon_name)); > + } > + } > + else > + { > + const cooked_index_entry *other > + = (const cooked_index_entry *) *slot; > + entry->canonical = other->canonical; > + } > + } > + } > + } > + > + m_names.shrink_to_fit (); > + m_entries.shrink_to_fit (); > + std::sort (m_entries.begin (), m_entries.end (), > + [] (const cooked_index_entry *a, const cooked_index_entry > *b) > + { > + return *a < *b; > + }); > +} > diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h > new file mode 100644 > index 00000000000..691f6348148 > --- /dev/null > +++ b/gdb/dwarf2/cooked-index.h > @@ -0,0 +1,260 @@ > +/* DIE indexing > + > + Copyright (C) 2021 Free Software Foundation, Inc. > + > + This file is part of GDB. > + > + This program is free software; you can redistribute it and/or > modify > + it under the terms of the GNU General Public License as published > by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see < > http://www.gnu.org/licenses/>;. */ > + > +#ifndef GDB_DWARF2_COOKED_INDEX_H > +#define GDB_DWARF2_COOKED_INDEX_H > + > +#include "dwarf2.h" > +#include "gdbtypes.h" > +#include "symtab.h" > +#include "hashtab.h" > +#include "dwarf2/index-common.h" > +#include "gdbsupport/gdb_string_view.h" > +#include "quick-symbol.h" > +#include "gdbsupport/gdb_obstack.h" > +#include "addrmap.h" > +#include "gdbsupport/iterator-range.h" > + > +struct dwarf2_per_cu_data; > + > +/* Flags that describe an entry in the index. */ > +enum cooked_index_flag_enum : unsigned char > +{ > + /* True if this entry is the program's "main". */ > + IS_MAIN = 1, > + /* True if this entry represents a "static" object. */ > + IS_STATIC = 2, > + /* True if this entry is an "enum class". */ > + IS_ENUM_CLASS = 4, > + /* True if this entry uses the linkage name. */ > + IS_LINKAGE = 8, > +}; > +DEF_ENUM_FLAGS_TYPE (enum cooked_index_flag_enum, > cooked_index_flag); > + > +/* A cooked_index_entry represents a single item in the index. Note > + that two entries can be created for the same DIE -- one using the > + name, and another one using the linkage name, if any. > + > + This is an "open" class and the members are all directly > + accessible. It is read-only after the index has been fully read > + and processed. */ > +struct cooked_index_entry : public allocate_on_obstack > +{ > + cooked_index_entry (sect_offset die_offset_, enum dwarf_tag tag_, > + cooked_index_flag flags_, const char *name_, > + const cooked_index_entry *parent_entry_, > + dwarf2_per_cu_data *per_cu_) > + : name (name_), > + tag (tag_), > + flags (flags_), > + die_offset (die_offset_), > + parent_entry (parent_entry_), > + per_cu (per_cu_) > + { > + } > + > + /* Return true if this entry matches SEARCH_FLAGS. */ > + bool matches (block_search_flags search_flags) const > + { > + if ((search_flags & SEARCH_STATIC_BLOCK) != 0 > + && (flags & IS_STATIC) != 0) > + return true; > + if ((search_flags & SEARCH_GLOBAL_BLOCK) != 0 > + && (flags & IS_STATIC) == 0) > + return true; > + return false; > + } > + > + /* Return true if this entry matches DOMAIN. */ > + bool matches (domain_enum domain) const > + { > + switch (domain) > + { > + case LABEL_DOMAIN: > + return false; > + > + case MODULE_DOMAIN: > + return tag == DW_TAG_module; > + > + case COMMON_BLOCK_DOMAIN: > + return tag == DW_TAG_common_block; > + } > + > + return true; > + } > + > + /* Return true if this entry matches KIND. */ > + bool matches (enum search_domain kind) const > + { > + switch (kind) > + { > + case VARIABLES_DOMAIN: > + return tag == DW_TAG_variable; > + case FUNCTIONS_DOMAIN: > + return tag == DW_TAG_subprogram; > + case TYPES_DOMAIN: > + return tag == DW_TAG_typedef || tag == DW_TAG_structure_type; > + case MODULES_DOMAIN: > + return tag == DW_TAG_module; > + } > + > + return true; > + } > + > + /* Construct the fully-qualified name of this entry and return a > + pointer to it. If allocation is needed, it will be done on > + STORAGE. */ > + const char *full_name (struct obstack *storage) const; > + > + /* Entries must be sorted case-insensitively; this compares two > + entries. */ > + bool operator< (const cooked_index_entry &other) const > + { > + return strcasecmp (canonical, other.canonical) < 0; > + } > + > + /* The name as it appears in DWARF. This always points into one > of > + the mapped DWARF sections. Note that this may be the name or > the > + linkage name -- two entries are created for DIEs which have > both > + attributes. */ > + const char *name; > + /* The canonical name. For C++ names, this may differ from NAME. > + In all other cases, this is equal to NAME. */ > + const char *canonical = nullptr; > + /* The DWARF tag. */ > + enum dwarf_tag tag; > + /* Any flags attached to this entry. */ > + cooked_index_flag flags; > + /* The offset of this DIE. */ > + sect_offset die_offset; > + /* The parent entry. This is NULL for top-level entries. > + Otherwise, it points to the parent entry, such as a namespace > or > + class. */ > + const cooked_index_entry *parent_entry; > + /* The CU from which this entry originates. */ > + dwarf2_per_cu_data *per_cu; > + > +private: > + > + void write_scope (struct obstack *storage, const char *sep) const; > +}; > + > +/* An index of interesting DIEs. This is "cooked", in contrast to a > + mapped .debug_names or .gdb_index, which are "raw". An entry in > + the index is of type cooked_index_entry. > + > + Operations on the index are described below. They are chosen to > + make it relatively simple to implement the symtab "quick" > + methods. */ > +class cooked_index > +{ > +public: > + cooked_index () = default; > + explicit cooked_index (cooked_index &&other) = default; > + DISABLE_COPY_AND_ASSIGN (cooked_index); > + cooked_index &operator= (cooked_index &&other) = default; > + > + /* Create a new cooked_index_entry and register it with this > object. > + Entries are owned by this object. The new item is > returned. */ > + const cooked_index_entry *add (sect_offset die_offset, enum > dwarf_tag tag, > + cooked_index_flag flags, > + const char *name, > + const cooked_index_entry > *parent_entry, > + dwarf2_per_cu_data *per_cu); > + > + /* Return the entry that is believed to represent the program's > + "main". This will return NULL if no such entry is > available. */ > + const cooked_index_entry *get_main () const > + { > + return m_main; > + } > + > + /* Install a new fixed addrmap from the given mutable addrmap. */ > + void install_addrmap (addrmap *map) > + { > + gdb_assert (m_addrmap == nullptr); > + m_addrmap = addrmap_create_fixed (map, &m_storage); > + } > + > + /* Look up ADDR in the address map, and return either the > + corresponding CU, or nullptr if the address could not be > + found. */ > + dwarf2_per_cu_data *lookup (CORE_ADDR addr) > + { > + return (dwarf2_per_cu_data *) addrmap_find (m_addrmap, addr); > + } > + > + /* Finalize the index. This should be called a single time, when > + the index has been fully populated. It enters all the entries > + into the internal hash table. */ > + void finalize (); > + > + /* A simple range over part of m_entries. */ > + typedef iterator_range *>::iterator> range; > + > + /* Look up an entry by name. Returns a range of all matching > + results. If COMPLETING is true, then a larger range, suitable > + for completion, will be returned. */ > + range find (gdb::string_view name, bool completing); > + > + /* Return a range of all the entries. */ > + range all_entries () > + { > + return { m_entries.begin (), m_entries.end () }; > + } > + > +private: > + > + /* GNAT only emits mangled ("encoded") names in the DWARF, and > does > + not emit the module structure. However, we need this structure > + to do lookups. This function recreates that structure for an > + existing entry. It returns the base name (last element) of the > + full decoded name. */ > + gdb::unique_xmalloc_ptr handle_gnat_encoded_entry > + (cooked_index_entry *entry, htab_t gnat_entries); > + > + /* Create a new cooked_index_entry and register it with this > object. > + Entries are owned by this object. The new item is > returned. */ > + cooked_index_entry *create (sect_offset die_offset, > + enum dwarf_tag tag, > + cooked_index_flag flags, > + const char *name, > + const cooked_index_entry *parent_entry, > + dwarf2_per_cu_data *per_cu) > + { > + return new (&m_storage) cooked_index_entry (die_offset, tag, > flags, > + name, parent_entry, > + per_cu); > + } > + > + /* Storage for the entries. */ > + auto_obstack m_storage; > + /* List of all entries. */ > + std::vector m_entries; > + /* If we found "main" or an entry with 'is_main' set, store it > + here. */ > + cooked_index_entry *m_main = nullptr; > + /* Storage for canonical names. */ > + std::vector> m_names; > + /* The addrmap. This maps address ranges to dwarf2_per_cu_data > + objects. */ > + addrmap *m_addrmap = nullptr; > +}; > + > +#endif /* GDB_DWARF2_COOKED_INDEX_H */