From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id FLJGFLp/hWraUzAAWB0awg (envelope-from ) for ; Wed, 19 Aug 2026 06:04:42 -0400 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Y8LuO/x4; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 3FDD61E033; Wed, 19 Aug 2026 06:04:42 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-6.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [IPv6:2620:52:6:3111::32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 996301E033 for ; Wed, 19 Aug 2026 06:04:40 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 527764BA9029 for ; Wed, 19 Aug 2026 10:04:38 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 527764BA9029 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Y8LuO/x4 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id BB1C94BA79AF for ; Wed, 19 Aug 2026 10:03:18 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org BB1C94BA79AF Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org BB1C94BA79AF Authentication-Results: sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1787133799; cv=none; b=AhSQSajJMolNOzgehjgrva2hGdtvwoC0r0yRFRmtlmOXPHN+fAb4b2ZSlV+d5u60MgdAvQ/KSGUVpi2MOd3wQJx3nxWPCpA5Sgf2eJUOe8mqyn+ZRI0ZaYWDKk/0N0qNw7uBWB9ZO0l8yxmIToac17ky15bAmc8BZb3FljWBVCw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1787133799; c=relaxed/simple; bh=k241TNCSM/FasUzoOXe8eUzYhZ4guQeK7ZfFIe+fV3c=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=k2vQwnt+WMc8E8d+YXMutp2cTjECG5IoMA/iriZp9CiwMzTQ8t+BLYZla3L1LJCrtjhW6Su8+Tp1pnOc4vVnEK5dD/MrrSAWCM0+dpodP+aZDgzNnm4/GX14Y4amwO5PeUfLp7j2Xc+lQTmlGTAqq4JVnVhDfa0C44CvmJ0HKYs= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Y8LuO/x4 DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BB1C94BA79AF DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787133797; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=w8FtcJwbEm05wxwlsUQFNZ6/rjsSF7ZsoFrU6Q6kzwQ=; b=Y8LuO/x44koQBTPEV5E+purPtEStl5gi40L5AItDiisv4U5wrHytso5o9kwFEi+5tQncNi ASOW601QcNsIWQlbWnEhmiPtIYGKavVAZC+4amMDnVoheQhJezVnKCHJWv+XUKCS1XmShq wu0dY4NwJ8UL5s2jFQtX9x3dgD0XsWc= Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-588-2vJL5mnlND2z9ErgJcAsag-1; Wed, 19 Aug 2026 06:03:11 -0400 X-MC-Unique: 2vJL5mnlND2z9ErgJcAsag-1 X-Mimecast-MFC-AGG-ID: 2vJL5mnlND2z9ErgJcAsag_1787133791 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-49545071724so8853955e9.0 for ; Wed, 19 Aug 2026 03:03:11 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787133790; x=1787738590; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=w8FtcJwbEm05wxwlsUQFNZ6/rjsSF7ZsoFrU6Q6kzwQ=; b=mvE3LvQXYmKurPqSgSQ8OyOskWURwG0Xj3Bd7ynNE/mVCxqwMigWuc0G0Tj2eIXOML BENiwyFDpP7yKzIMrqyRyWKd1XyaPoTi/3cAz6yZ8zaVg14QBDu5VG0oRJ3o5hVKJsVn W2wdeA3OEIu6R8iQlSmvZdPchplpGYho3lk1sDpTWwK47QsGm5c3tMeDoRBKs4Z5Xz/g cl0RYaVPHtCS/GSW0eONM5qL9m6Oig3rkIcMGbjw8feVH+WCYf5vSyBabWU5kC58nuY9 DyPFZlFe24PbAswS7DEZgjAujUQQg8utlBrDe6O1yySkiYGzACsXndfm+PGFHANQUl+s f8PQ== X-Gm-Message-State: AOJu0YymZqZNhq8jq4irZo0wjIq4TW5K64Tl+3VpT77qBqBfuFIcuVxu mh6VlVr8qdmx8ze+2dnwDGToqmPvf6TjShgLDgkW+v8OjeLqQAre0RiWx5nWAUyTx2xX4SDUKpu nFOXI0n6W/Z3EpIfABqsx9uQnHXDE29C24KktdjnUX9/4qSAFInADwV55N+U2xsMHhS095FVbcd 70zYPIWtVWcQHVadfZ7tnjXPCOA0+JWZQYBMmEr67QHbyuCeQ= X-Gm-Gg: AR+sD109SEZ1ywHsS0vs33htO9wpYlM93Mf0tXA4RzdQRnc7Ae3SpmmBm1mEfvXoymE 5l+x/5/NKuJdfkZRG5wFwnSOn9bhF+NpD/VwFNX/pvKhg6ne6k2NYDlhWux7oXHVDYvzA7K7zs3 oqJGKLO0KUKj9+4v1nOey4GKc1c9mFX6DAkCBN8AoCuoEFid3cQV8R7mbcbpIgP4QWAv95Zoy1e RytLLviK24FjMiSrnz0jW+8bmhwRkUArV6/jLEHdle5A7Lw+JlPd9T7NB0Ym8GaOh2fMIneGuhJ U23hLBgOwavv5iQSOWAvnKB9xCQKpkvec+9Lke7FsdCz3IZokGz60gsLjCdfvUZRejyJzvzliV0 Wo46le6naZAvGrKg2p5w= X-Received: by 2002:a05:600c:4e47:b0:499:a0f3:9d5c with SMTP id 5b1f17b1804b1-499aa14a711mr66560295e9.3.1787133790006; Wed, 19 Aug 2026 03:03:10 -0700 (PDT) X-Received: by 2002:a05:600c:4e47:b0:499:a0f3:9d5c with SMTP id 5b1f17b1804b1-499aa14a711mr66557305e9.3.1787133788767; Wed, 19 Aug 2026 03:03:08 -0700 (PDT) Received: from localhost (67.72.115.87.dyn.plus.net. [87.115.72.67]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-482b1441753sm5109332f8f.5.2026.08.19.03.03.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Aug 2026 03:03:08 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCH] [GDB 18] gdb: resolve class name via DW_AT_signature in cooked index Date: Wed, 19 Aug 2026 11:03:06 +0100 Message-Id: <3ea45eb5b7eba98d5b0261a7648720a56fe6d578.1787133721.git.aburgess@redhat.com> X-Mailer: git-send-email 2.25.4 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 8p_C0Sqz6qs_881RwYtYksvvCm99EVz535RCqBNdQC4_1787133791 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit content-type: text/plain; charset="US-ASCII"; x-default=true 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~public-inbox=simark.ca@sourceware.org This patch fixes a regression that appeared since GDB 17, so if/when approved I plan to merge this to both master and gdb-18-branch. Thanks, Andrew --- This commit fixes PR gdb/33447, an issue where looking up qualified member function names was not working for C++ binaries compiled with Clang when using the -fdebug-types-section flag. Before this commit we would see this behaviour: (gdb) print base1::a_function There is no field named a_function When what we expect to see is: (gdb) print base1::a_function $1 = {void (const base1 * const)} 0x403060 The problem is that the cooked index is unable to determine the name of the parent class `base1` in this case, and so decides not to index any of the member functions. The problem was discovered by running gdb.cp/cpexprs-debug-types.exp with Clang: make check-gdb TESTS=gdb.cp/cpexprs-debug-types.exp \ RUNTESTFLAGS='CXX_FOR_TARGET=clang++ CC_FOR_TARGET=clang' The cpexprs-debug-types.exp test forces use of the '-fdebug-types-section' flag, which is not on by default. With this flag, class definitions are placed in type units, and the compile unit contains only a declaration stub for each class. Both clang++ and g++ emit these stubs, but they differ in one detail: GCC includes DW_AT_name on the stub, while clang++ does not, the stub carries only DW_AT_declaration and DW_AT_signature. The class name is only available in the type unit, reachable by following the signature. For example, Clang emits this in a CU: <1><2e7d>: DW_TAG_class_type DW_AT_declaration : 1 DW_AT_signature : 0x3abb... <2><2eac>: DW_TAG_subprogram DW_AT_name : a_function DW_AT_declaration : 1 The definition for a_function is elsewhere in the same CU: <1><3142>: DW_TAG_subprogram DW_AT_specification: <0x2eac> And in a TU elsewhere: Compilation Unit @ offset 0xd2e: ... snip ... Signature: 0x3abb... <0>: Abbrev Number: 1 (DW_TAG_type_unit) ... snip ... <1>: Abbrev Number: 30 (DW_TAG_class_type) ... snip ... DW_AT_name : (indexed string: 0xaa): base1 To find the DW_AT_name the cooked index needs to look up the type within the TU. Without the name the cooked indexer would skip the children of `base1`. This look up used to work; it works in GDB 17. PR gdb/33447 incorrectly identifies commit c879f4dc3e317cf6353a45a803ecf00d577a13d8 as the commit that introduced the regression. This is actually the last working commit. The problem was introduced by the next commit in the same series: commit 86ac8c546235a67d6a6bb29476a3a9ac8f7a620a (HEAD) Date: Thu Jan 2 15:28:18 2025 -0700 Convert lookup_symbol_in_objfile Prior to this commit GDB's symbol lookup had two phases, a search through already expanded symtabs, and a search via lookup_symbol_via_quick_fns. After the above commit only lookup_symbol_via_quick_fns remains. The lookup_symbol_via_quick_fns lookup, which relies on the indexer, was always broken, but the first phase, search via expanded symtabs, could correctly find the type name via the signature. The fix has three parts: 1. abbrev.c: Add DW_AT_signature to the set of attributes that mark a DIE as "interesting" in has_specification_or_origin. Without this, the unnamed class stub was classified as uninteresting at the abbreviation level and scan_attributes was never called for it. 2. cooked-indexer.c (scan_attributes): Handle DW_AT_signature by looking up the signatured_type via lookup_signatured_type and constructing a section_and_offset origin pointing to the type DIE in the type unit. Restructure the is_declaration / origin- following control flow: change the "else if (origin)" to a standalone "if" so that class declaration stubs marked with IS_TYPE_DECLARATION can still follow their origin to retrieve the class name from the type unit. Add origin.reset() in the other declaration paths to preserve the original behaviour for non-class declarations and Ada imports. 3. read.c/read.h: Make lookup_signatured_type externally visible so it can be called from cooked-indexer.c. A new DWARF assembler test gdb.dwarf2/sig-type-unnamed-class.exp reproduces the problem case, there's a nameless declaration stub that references its full type via DW_AT_signature. To match the Clang output as much as possible the member function definition is separate and makes use of DW_AT_specification. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33447 --- gdb/dwarf2/abbrev.c | 1 + gdb/dwarf2/cooked-indexer.c | 27 ++++- gdb/dwarf2/read.c | 6 +- gdb/dwarf2/read.h | 7 ++ .../gdb.dwarf2/sig-type-unnamed-class.exp | 106 ++++++++++++++++++ 5 files changed, 138 insertions(+), 9 deletions(-) create mode 100644 gdb/testsuite/gdb.dwarf2/sig-type-unnamed-class.exp diff --git a/gdb/dwarf2/abbrev.c b/gdb/dwarf2/abbrev.c index 44d5c87a5f7..e99acc5e752 100644 --- a/gdb/dwarf2/abbrev.c +++ b/gdb/dwarf2/abbrev.c @@ -160,6 +160,7 @@ abbrev_table::read (struct dwarf2_section_info *section, case DW_AT_specification: case DW_AT_abstract_origin: case DW_AT_extension: + case DW_AT_signature: has_specification_or_origin = true; break; diff --git a/gdb/dwarf2/cooked-indexer.c b/gdb/dwarf2/cooked-indexer.c index f55efc5e3a0..68222a95c49 100644 --- a/gdb/dwarf2/cooked-indexer.c +++ b/gdb/dwarf2/cooked-indexer.c @@ -234,6 +234,19 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu, attr.get_ref_die_offset () }; break; + case DW_AT_signature: + { + ULONGEST signature = attr.as_signature (); + signatured_type *sig_type = lookup_signatured_type (reader->cu (), + signature); + if (sig_type == nullptr) + complaint (_("cannot find DW_AT_signature type %s [in module %s]"), + hex_string (signature), bfd_get_filename (reader->abfd ())); + else + origin = { sig_type->section (), sig_type->type_offset_in_section }; + } + break; + case DW_AT_external: if (attr.as_boolean ()) *flags &= ~IS_STATIC; @@ -325,13 +338,17 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu, { *linkage_name = nullptr; *name = nullptr; + origin.reset (); } + else + origin.reset (); } - else if ((*name == nullptr - || (*linkage_name == nullptr - && tag_can_have_linkage_name (abbrev->tag)) - || (*parent_entry == nullptr && m_language != language_c)) - && origin.has_value ()) + + if ((*name == nullptr + || (*linkage_name == nullptr + && tag_can_have_linkage_name (abbrev->tag)) + || (*parent_entry == nullptr && m_language != language_c)) + && origin.has_value ()) { cutu_reader *new_reader = ensure_cu_exists (reader, *origin, false); diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index ca475f53745..f69d34d51a2 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -2382,11 +2382,9 @@ lookup_dwp_signatured_type (struct dwarf2_cu *cu, ULONGEST sig) return *sig_type_it; } -/* Lookup a signature based type for DW_FORM_ref_sig8. - Returns NULL if signature SIG is not present in the table. - It is up to the caller to complain about this. */ +/* See dwarf2/read.h. */ -static struct signatured_type * +struct signatured_type * lookup_signatured_type (struct dwarf2_cu *cu, ULONGEST sig) { dwarf2_per_objfile *per_objfile = cu->per_objfile; diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h index 15dd2abf3a1..d3e2d9fb198 100644 --- a/gdb/dwarf2/read.h +++ b/gdb/dwarf2/read.h @@ -1489,4 +1489,11 @@ extern struct dwarf2_section_info *get_debug_line_section extern bool is_ada_import_or_export (dwarf2_cu *cu, const char *name, const char *linkagename); +/* Lookup a signature based type for DW_FORM_ref_sig8. Returns NULL + if signature SIG is not present in the table of CU. It is up to + the caller to complain about this. */ + +extern struct signatured_type *lookup_signatured_type (struct dwarf2_cu *cu, + ULONGEST sig); + #endif /* GDB_DWARF2_READ_H */ diff --git a/gdb/testsuite/gdb.dwarf2/sig-type-unnamed-class.exp b/gdb/testsuite/gdb.dwarf2/sig-type-unnamed-class.exp new file mode 100644 index 00000000000..6f39e2c823d --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/sig-type-unnamed-class.exp @@ -0,0 +1,106 @@ +# Copyright 2026 Free Software Foundation, Inc. +# +# 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 . + +# Check that the cooked index correctly resolves the parent of a member +# function when the class declaration stub in the compile unit has +# DW_AT_signature but no DW_AT_name. +# +# This replicates what Clang emits with -fdebug-types-section. The +# compile unit contains an unnamed DW_TAG_class_type declaration with +# only DW_AT_declaration, DW_AT_signature, and child member function +# declarations. +# +# The class name must be resolved by following the signature to the +# type unit. Without this, the member function definitions (which use +# DW_AT_specification to point at the child declarations) end up with +# no parent, and qualified lookup fails. + +load_lib dwarf.exp + +# This test can only be run on targets which support DWARF-2 and use gas. +require dwarf2_support + +standard_testfile main-foo.c .S + +# Build the test program using VERSION for the CU/TU DWARF version. +proc run_test { version } { + # Create the DWARF. + set asm_file [standard_output_file $::srcfile2] + Dwarf::assemble { + filename $asm_file + add_dummy_cus 0 + } { + upvar version version + + get_func_info foo + get_func_info main + + declare_labels method_decl + + tu { version $version } 0xdeadbeef01234567 the_type { + DW_TAG_type_unit { + DW_AT_language @DW_LANG_C_plus_plus + } { + the_type: DW_TAG_class_type { + DW_AT_name the_type + DW_AT_byte_size 1 sdata + } + } + } + + cu { version $version } { + compile_unit { + DW_AT_language @DW_LANG_C_plus_plus + } { + DW_TAG_class_type { + DW_AT_declaration 1 flag + DW_AT_signature 0xdeadbeef01234567 ref_sig8 + } { + method_decl: DW_TAG_subprogram { + DW_AT_name method + DW_AT_linkage_name _ZN8the_type6methodEv + DW_AT_declaration 1 flag + } + } + + DW_TAG_subprogram { + DW_AT_specification %$method_decl + DW_AT_low_pc $foo_start DW_FORM_addr + DW_AT_high_pc $foo_end DW_FORM_addr + } + + DW_TAG_subprogram { + DW_AT_name main + DW_AT_low_pc $main_start DW_FORM_addr + DW_AT_high_pc $main_end DW_FORM_addr + } + } + } + } + + if { [prepare_for_testing "failed to prepare" ${::testfile}-${version} \ + [list $asm_file $::srcfile] {nodebug}] } { + return + } + + # Check that GDB was able to find the parent for "method", and as + # a result, can correctly find this field of "the_type". + gdb_test "print the_type::method" \ + [string_to_regexp " "] +} + +foreach_with_prefix version { 4 5 } { + run_test $version +} base-commit: afa6db16e6508d8ea269557085bc7c301e824382 -- 2.25.4