From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id qPKtLwFSVGjG3hQAWB0awg (envelope-from ) for ; Thu, 19 Jun 2025 14:08:01 -0400 Authentication-Results: simark.ca; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=KTNtrWjI; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id B90A41E11C; Thu, 19 Jun 2025 14:08:01 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-8.8 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_INVALID,DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED,RCVD_IN_VALIDITY_RPBL,RCVD_IN_VALIDITY_SAFE autolearn=ham autolearn_force=no version=4.0.1 Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (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 3923B1E089 for ; Thu, 19 Jun 2025 14:08:00 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C6149383BDB3 for ; Thu, 19 Jun 2025 18:07:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C6149383BDB3 Authentication-Results: sourceware.org; dkim=fail reason="signature verification failed" (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=KTNtrWjI Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id BCFB5383BD94 for ; Thu, 19 Jun 2025 18:06:00 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org BCFB5383BD94 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 BCFB5383BD94 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750356360; cv=none; b=f9FuGxMbkQt4zep/yBM1quHuIib0Iuvz1Al7Mp011Bn6ZQkft0e4Jfi0cH3ogy6aRRuKxydjOBUtfWwruG0A+gzShiHb2fOVaosZjwK+0loKfnTF7xXTq0NNQ+DsJb0/OeYe1ZXTR5/e3vjLq60OEHRtRGiFE5QU8aobpcElARo= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750356360; c=relaxed/simple; bh=FZhkGTubre1z63+U9eDJRZDs8C/HOvLDumDjJYe1R40=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=aCW1oR3EOFEqW+Bz9/Psgoq7NuMZxcjhWM5fhlbFCLb7JTlJ6CeT0/Q8mPokifc+AyAH5Fnp3GKIsZ/7Y/Z68NKp4Sp60BAcRsU9QLWkMPMTOPm6LqW8crjtOO38PSC85g24OzZy3mgfIoim8QGU4hKzDI8OyjgSuhWLJivpMlU= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BCFB5383BD94 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1750356359; 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: in-reply-to:in-reply-to:references:references; bh=iKqljjEFKBBXUf7LtqJOaaarblv3XtUEP5ideYACnsA=; b=KTNtrWjI8sXvdBWqvAiAgajppRvajSbWPYI5uG4mnnxpAjPvxwedlMY3Rt5oLG2e8UMITl Wd3lo43uCUCOQugtV24TRhQBI0Y3FtYez2Hu9xJHi78CvmPn7iVdfdyY3VWhlbZEPfclP3 2wzfO3t/e76+x/Mu8V3wuUikrN1dY34= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-41-WgTFFljoP-2u6wA8n1W3VA-1; Thu, 19 Jun 2025 14:05:56 -0400 X-MC-Unique: WgTFFljoP-2u6wA8n1W3VA-1 X-Mimecast-MFC-AGG-ID: WgTFFljoP-2u6wA8n1W3VA_1750356355 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 976041956086 for ; Thu, 19 Jun 2025 18:05:55 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.96.134.45]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5C768180045B; Thu, 19 Jun 2025 18:05:53 +0000 (UTC) From: Guinevere Larsen To: gdb-patches@sourceware.org Cc: Guinevere Larsen Subject: [PATCH v3 1/3] gdb: make lookup_minimal_symbol_linkage work with linker namespaces Date: Thu, 19 Jun 2025 15:05:38 -0300 Message-ID: <20250619180540.2315103-2-guinevere@redhat.com> In-Reply-To: <20250619180540.2315103-1-guinevere@redhat.com> References: <20250619180540.2315103-1-guinevere@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: eCJmrY0yJcJSWKWnAhlveqW6d8WfiYVE51UoLysc0qI_1750356355 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 When a symbol found by GDB may have copy relocation, GDB calculates the address of the symbol by checking all the objfiles in the current program space for another instance of the same symbol, and returns the address of the first instance found. This works well when linker namespaces are not involved, but fails when a symbol is present in more than one namespace. That's because copy relocations respect linker namespace boundaries, and so if we're trying to find the symbol in namespace N, the symbol from a different namespace M may be returned, if the SO containing the symbol was loaded in M before N. To make the search work correctly, lookup_minimal_symbol_linkage would need to also respect linker namespace boundaries. However, to avoid leaking solib knowledge to minsyms, and because of how little information is passed to the function, this commit instead makes the function take a vector of objfiles to search, in place of the program space. This makes it so symbol::get_maybe_copied_address (and the equivalent of minimal_symbol) need to request the objfiles for the correct namespace, since they have enough context to figure out the namespace. Creating the vector is left as a function in solib.c Since minimal_symbol::get_maybe_copied_address only searches main_file objfiles, if we can guarantee that only one is loaded for each program space, we could avoid the work of constructing an std::vector that will be mostly ignored. However, I couldn't convince myself that that is the case, so I decided to keep the behavior exactly as is. Ideally, lookup_minimal_symbol_linkage would receive an iterator instead of a vector, but as of now it isn't possible to do forward declarations of nested types (we'd need program_space::objfiles_range) and progspace.h can't be included into minsyms.h, so we're stuck constructing a vector for it. Finally, as some minor refactoring, find_solib_for_objfile is moved to solib.c to simplify looking for which namespace contains the objfile where we found the symbol the user was looking for. --- gdb/dwarf2/ada-imported.c | 8 +++- gdb/minsyms.c | 11 ++++-- gdb/minsyms.h | 9 +++-- gdb/solib-svr4.c | 20 ---------- gdb/solib.c | 82 ++++++++++++++++++++++++++++++++++++++- gdb/solib.h | 19 +++++++++ gdb/symtab.c | 13 ++++++- 7 files changed, 130 insertions(+), 32 deletions(-) diff --git a/gdb/dwarf2/ada-imported.c b/gdb/dwarf2/ada-imported.c index 1e259663279..b883d735971 100644 --- a/gdb/dwarf2/ada-imported.c +++ b/gdb/dwarf2/ada-imported.c @@ -35,9 +35,13 @@ static struct value * ada_imported_read_variable (struct symbol *symbol, const frame_info_ptr &frame) { const char *name = get_imported_name (symbol); + + std::vector objfiles_to_search; + for (auto objf : symbol->objfile ()->pspace ()->objfiles ()) + objfiles_to_search.push_back (objf); + bound_minimal_symbol minsym - = lookup_minimal_symbol_linkage (symbol->objfile ()->pspace (), name, - true, false); + = lookup_minimal_symbol_linkage (objfiles_to_search, name, true, false); if (minsym.minsym == nullptr) error (_("could not find imported name %s"), name); return value_at (symbol->type (), minsym.value_address ()); diff --git a/gdb/minsyms.c b/gdb/minsyms.c index 4a6459a6f2d..3ac2bdf697a 100644 --- a/gdb/minsyms.c +++ b/gdb/minsyms.c @@ -55,6 +55,7 @@ #include "gdbsupport/gdb-safe-ctype.h" #include "gdbsupport/parallel-for.h" #include "inferior.h" +#include "solib.h" #if CXX_STD_THREAD #include @@ -589,12 +590,14 @@ lookup_minimal_symbol_linkage (const char *name, struct objfile *objf, /* See minsyms.h. */ bound_minimal_symbol -lookup_minimal_symbol_linkage (program_space *pspace, const char *name, - bool match_static_type, bool only_main) +lookup_minimal_symbol_linkage (gdb::array_view objfiles_to_search, + const char *name, bool match_static_type, + bool only_main) { - for (objfile *objfile : pspace->objfiles ()) + for (objfile *objfile : objfiles_to_search) { - if (objfile->separate_debug_objfile_backlink != nullptr) + if (objfile == nullptr + || objfile->separate_debug_objfile_backlink != nullptr) continue; if (only_main && (objfile->flags & OBJF_MAINLINE) == 0) diff --git a/gdb/minsyms.h b/gdb/minsyms.h index 709faa5e8f4..4bb2aca0b4c 100644 --- a/gdb/minsyms.h +++ b/gdb/minsyms.h @@ -237,11 +237,14 @@ extern bound_minimal_symbol lookup_minimal_symbol_linkage /* A variant of lookup_minimal_symbol_linkage that iterates over all objfiles of PSPACE. If ONLY_MAIN is true, then only an objfile with - OBJF_MAINLINE will be considered. */ + OBJF_MAINLINE will be considered. This function should receive a + program_space::objfile_ranges instead, but we can't include progspace.h + here, nor can we do forward declarations of nested types, so std::vector + will waste a bit of memory to work around that issue. */ extern bound_minimal_symbol lookup_minimal_symbol_linkage - (program_space *pspace, const char *name, bool match_static_type, - bool only_main) ATTRIBUTE_NONNULL (1); + (gdb::array_view objfiles_to_search, const char *name, + bool match_static_type, bool only_main); /* Look through all the current minimal symbol tables and find the first minimal symbol that matches NAME and PC. If OBJF is non-NULL, diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index e9430281bca..86cefc174d2 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -3549,26 +3549,6 @@ lp64_svr4_solib_ops::fetch_link_map_offsets () const } -/* Return the DSO matching OBJFILE or nullptr if none can be found. */ - -static const solib * -find_solib_for_objfile (struct objfile *objfile) -{ - if (objfile == nullptr) - return nullptr; - - /* If OBJFILE is a separate debug object file, look for the original - object file. */ - if (objfile->separate_debug_objfile_backlink != nullptr) - objfile = objfile->separate_debug_objfile_backlink; - - for (const solib &so : current_program_space->solibs ()) - if (so.objfile == objfile) - return &so; - - return nullptr; -} - /* Return the address of the r_debug object for the namespace containing SOLIB or zero if it cannot be found. This may happen when symbol files are added manually, for example, or with the main executable. diff --git a/gdb/solib.c b/gdb/solib.c index bea0534cb50..9eb961e8b52 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -1808,8 +1808,88 @@ remove_user_added_objfile (struct objfile *objfile) } } -/* Implementation of the linker_namespace convenience variable. +/* See solib.h. */ + +const solib * +find_solib_for_objfile (struct objfile *objfile) +{ + if (objfile == nullptr) + return nullptr; + + /* If OBJFILE is a separate debug object file, look for the original + object file. */ + if (objfile->separate_debug_objfile_backlink != nullptr) + objfile = objfile->separate_debug_objfile_backlink; + + for (const solib &so : objfile->pspace ()->solibs ()) + if (so.objfile == objfile) + return &so; + + return nullptr; +} + +/* See solib.h. */ + +std::vector +get_objfiles_in_linker_namespace (int nsid, program_space *pspace) +{ + std::vector objfiles_in_ns; + const solib_ops *ops = pspace->solib_ops (); + + gdb_assert (ops->supports_namespaces ()); + + /* If we're looking at the default namespace, we also need + to add the mainline objfiles by hand, since there is no + solib associated with those files. We add them first + because if we're searching for copy relocations, they + should be in the main file, so we'll find it faster. */ + if (nsid == 0) + for (objfile *objf : pspace->objfiles ()) + if ((objf->flags & OBJF_MAINLINE) != 0) + objfiles_in_ns.push_back (objf); + + std::vector solibs = ops->get_solibs_in_ns (nsid); + /* Reserve for efficiency. */ + objfiles_in_ns.reserve (solibs.size () + objfiles_in_ns.size ()); + for (const solib *so : solibs) + objfiles_in_ns.push_back (so->objfile); + + return objfiles_in_ns; +} + +/* See solib.h. */ + +std::vector +get_objfiles_in_linker_namespace (objfile *objfile) +{ + program_space *pspace = objfile->pspace (); + const solib_ops *ops = pspace->solib_ops (); + const solib *so = find_solib_for_objfile (objfile); + + if (ops->supports_namespaces () + /* If we're searching for a symbol from the linker, we'll reach here + before having any namespaces. Return all objfiles since the + boundaries haven't been setup yet. */ + && ops->num_active_namespaces () > 0 + /* When trying to load libthread_db, we can search for a symbol in an + objfile with no associated solib. In that case, again, we should + return all objfiles. */ + && so != nullptr) + { + return get_objfiles_in_linker_namespace (ops->find_solib_ns (*so), + pspace); + } + + /* If any of the previous conditions isn't satisfied, we return + the full list of objfiles in the inferior. */ + std::vector found_objfiles; + for (struct objfile *objf : objfile->pspace ()->objfiles ()) + found_objfiles.push_back (objf); + return found_objfiles; +} + +/* Implementation of the linker_namespace convenience variable. This returns the GDB internal identifier of the linker namespace, for the selected frame, as an integer. If the inferior doesn't support linker namespaces, this always returns 0. */ diff --git a/gdb/solib.h b/gdb/solib.h index a3104e47e40..0c5b26c7ad0 100644 --- a/gdb/solib.h +++ b/gdb/solib.h @@ -20,6 +20,9 @@ #ifndef GDB_SOLIB_H #define GDB_SOLIB_H +/* Forward decl's for prototypes */ +struct objfile; + #include "gdb_bfd.h" #include "gdbsupport/function-view.h" #include "gdbsupport/intrusive_list.h" @@ -373,4 +376,20 @@ extern void update_solib_breakpoints (void); extern void handle_solib_event (void); +/* Return a vector with pointers of all objfiles in the namespace + NSID. This version assumes that the inferior supports namespaces. */ + +std::vector get_objfiles_in_linker_namespace + (int nsid, program_space *pspace); + +/* Return a vector with pointers of all objfiles in the same namespace + as OBJFILE. If the inferior doesn't support namespaces, return all + objfiles in the program_space. */ + +std::vector get_objfiles_in_linker_namespace (objfile *objfile); + +/* Return the DSO matching OBJFILE or nullptr if none can be found. */ + +const solib *find_solib_for_objfile (struct objfile *objfile); + #endif /* GDB_SOLIB_H */ diff --git a/gdb/symtab.c b/gdb/symtab.c index b2de990143d..7b125bfd006 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -75,6 +75,7 @@ #include "gdbsupport/common-utils.h" #include #include "gdbsupport/unordered_set.h" +#include "solib.h" /* Forward declarations for local functions. */ @@ -6779,8 +6780,12 @@ symbol::get_maybe_copied_address () const gdb_assert (this->aclass () == LOC_STATIC); const char *linkage_name = this->linkage_name (); + + std::vector objfiles_to_search + (get_objfiles_in_linker_namespace (this->objfile ())); + bound_minimal_symbol minsym - = lookup_minimal_symbol_linkage (this->objfile ()->pspace (), linkage_name, + = lookup_minimal_symbol_linkage (objfiles_to_search, linkage_name, false, false); if (minsym.minsym != nullptr) return minsym.value_address (); @@ -6797,8 +6802,12 @@ minimal_symbol::get_maybe_copied_address (objfile *objf) const gdb_assert ((objf->flags & OBJF_MAINLINE) == 0); const char *linkage_name = this->linkage_name (); + + std::vector objfiles_to_search + (get_objfiles_in_linker_namespace (objf)); + bound_minimal_symbol found - = lookup_minimal_symbol_linkage (objf->pspace (), linkage_name, + = lookup_minimal_symbol_linkage (objfiles_to_search, linkage_name, false, true); if (found.minsym != nullptr) return found.value_address (); -- 2.49.0