From patchwork Sun Oct 27 09:10:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 99673 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 6CC423858403 for ; Sun, 27 Oct 2024 09:13:53 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org 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 70EFA385840D for ; Sun, 27 Oct 2024 09:11:13 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 70EFA385840D Authentication-Results: sourceware.org; dmarc=pass (p=none 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 70EFA385840D 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=1730020280; cv=none; b=SXAonV6GxF+/FrFTQxaR45q+O2fKlFdm5KXOM4EZ9gaeFxl450SHOqFkEtsGgia+x3S8KyfGVGZdEVbiJxbS1g8rR8OPXLmkNyTNbPVZO4fuoRHUkUKMKmQo1tjwtM8KCxJx+1Oger9t8OnUVWq6cYs9a9kOJi4/773CliuE5GA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730020280; c=relaxed/simple; bh=UgmV8gV3SwokTzQeq2Dr7VzDIxbNM61/iNiBr6EVIbE=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=jirtREurx+M8vndgAb0Xci9fbtAIltGPyo14ZpxgK9VxOHvMIhdlHIrgxrhzxwnzo8DhQKSshaKH1jzWZWkKlJbGV9Kgu6MBjKmhwFHQpTynBuZs+t3zbF1LC/pb1ppc2CWfoxYSZq6TZRSS5GC2uP7czMX+Mqv4yLAI3BZ7YA0= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1730020273; 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=bWKRMoDCSR5HBMty5tJzC1SywY0VO0Cbvgx78RkaeIc=; b=YNiq9dpU2IpuA4tga2Ttv6xqI0uw+6f7eP590AF6KtaHvvXie252WGumAvCVqlMsXsiAdz 8JVv4LdGqB11qMWRgbR917z7txIReqbF5YTSi1MlxhxHUmUrAgzqIf5GK6YokVQbVRM/ck 7lErrJK6uMrJ+008KME/tLD01+E/Qkk= Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-591-lTlEpD-jNK2D3-tnVUHbZQ-1; Sun, 27 Oct 2024 05:11:07 -0400 X-MC-Unique: lTlEpD-jNK2D3-tnVUHbZQ-1 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-37d5a3afa84so1859270f8f.3 for ; Sun, 27 Oct 2024 02:11:06 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730020265; x=1730625065; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=bWKRMoDCSR5HBMty5tJzC1SywY0VO0Cbvgx78RkaeIc=; b=bHpDtKqL+DuSj+t+jt9Lc3y+tOjBumgsFHk+xuxITlHvwxMAO64Tuo49yoEJ1cAfSr YqmcHQo2E/aejZO1IJj+aQXVPK2AcExE1654UbAg62zZHWT9zmZ6kocIebujcUytQl3A azkdqo9JlznjMdlYC1sw0HRvcGT4wHkdV6Otu6Y0Tjic3u4GNRPBW3GxvDhLavo7lKOQ 8o26/zCCk7cdo9aoumNVPFxgwqDnZQkSaN6Al8Mn9M9YKPEMjUPdxW7zxKnMUUHIznSZ tWo6dtbjZ3LAgmiW6R1ZnioOyhFj1i7qRl+L89PCk5MZPOrrTKekV5LiMfMO6YUFHpA6 pC4A== X-Gm-Message-State: AOJu0YxCUH2d9Zyup/j1B85/FIFl6HQvOmPAulOh60NnUuziLF3dwYxo FoYEhk7HLqwdSUeSSiLbZL2aRXu3K6/eABQwEsqqd3zTeVjDQfy2Yv6Sv/TCIgLPzZ3zQKZES/F CiG+otJMfXjsf1YyZCIKC0lhusPMhwWYrnbspvJYMqgxaDap6Y6xK12U4l55JysFDwMcOWA/a4+ FcaDIIxkqvDBHC47zauEcj07VlbEtNrR0fLG+vDbF/kPs= X-Received: by 2002:adf:a348:0:b0:37d:4e20:9be0 with SMTP id ffacd0b85a97d-380611f5e23mr3131589f8f.51.1730020265294; Sun, 27 Oct 2024 02:11:05 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEmme7l0Lje8jC+KbI+dFm1FLC6aecquvRddPNm3OT3auM++K+pZ2PzW38uh3oJDGKyPdPoWg== X-Received: by 2002:adf:a348:0:b0:37d:4e20:9be0 with SMTP id ffacd0b85a97d-380611f5e23mr3131566f8f.51.1730020264795; Sun, 27 Oct 2024 02:11:04 -0700 (PDT) Received: from localhost (197.209.200.146.dyn.plus.net. [146.200.209.197]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43193595baesm69180415e9.17.2024.10.27.02.11.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 27 Oct 2024 02:11:03 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess , Tom Tromey Subject: [PATCHv2 3/4] gdb: add extension hook ext_lang_find_objfile_from_buildid Date: Sun, 27 Oct 2024 09:10:54 +0000 Message-Id: <2b5bd393b94fdfff7844ecea6e168ee07c46f5af.1730020155.git.aburgess@redhat.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP 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 Add a new ext_lang_find_objfile_from_buildid function which is called from find_objfile_by_build_id and gives extension languages a chance to find missing objfiles. This commit adds the ext_lang_find_objfile_from_buildid function and the extension_language_ops::find_objfile_from_buildid() hook, but does not implement the hook for any extension languages, that will come in the next commit. This commit does rewrite find_objfile_by_build_id (build-id.c) to call the new hook though. The basic steps of find_objfile_by_build_id are now this: 1. Try to find the missing objfile using the build-id by looking in the debug-file-directory's .build-id/ sub-directory. If we find the file then we're done. 2. Ask debuginfod to download the missing file for us. If we download the file successfully then we're done. 3. Ask the extension language hook to find the file for us. If the extension language asks us to try again then we repeat step (1) only and if we still don't have the file, we move to step (4). If the extension language told us where the file is then we use that file and we're done. 4. We didn't find the file. Carry on without it. Only step (3) is new in this logic, everything else was already done. There are no tests added here as we can't currently write an extension language callback. The next commit will add the tests. Approved-By: Tom Tromey --- gdb/build-id.c | 88 ++++++++++++++++++++++++++++++++------------ gdb/build-id.h | 3 +- gdb/corelow.c | 6 ++- gdb/extension-priv.h | 13 +++++++ gdb/extension.c | 22 +++++++++++ gdb/extension.h | 20 ++++++++++ gdb/solib.c | 3 +- 7 files changed, 128 insertions(+), 27 deletions(-) diff --git a/gdb/build-id.c b/gdb/build-id.c index 6266be1bd6d..9d4b005489d 100644 --- a/gdb/build-id.c +++ b/gdb/build-id.c @@ -28,6 +28,7 @@ #include "cli/cli-style.h" #include "gdbsupport/scoped_fd.h" #include "debuginfod-support.h" +#include "extension.h" /* See build-id.h. */ @@ -343,32 +344,73 @@ find_separate_debug_file_by_buildid (struct objfile *objfile, /* See build-id.h. */ gdb_bfd_ref_ptr -find_objfile_by_build_id (const bfd_build_id *build_id, +find_objfile_by_build_id (program_space *pspace, + const bfd_build_id *build_id, const char *expected_filename) { - /* Try to find the executable (or shared object) by looking for a - (sym)link on disk from the build-id to the object file. */ - gdb_bfd_ref_ptr abfd = build_id_to_exec_bfd (build_id->size, - build_id->data); - - if (abfd != nullptr) - return abfd; - - /* Attempt to query debuginfod for the executable. */ - gdb::unique_xmalloc_ptr path; - scoped_fd fd = debuginfod_exec_query (build_id->data, build_id->size, - expected_filename, &path); - if (fd.get () >= 0) + gdb_bfd_ref_ptr abfd; + + for (unsigned attempt = 0, max_attempts = 1; + attempt < max_attempts && abfd == nullptr; + ++attempt) { - abfd = gdb_bfd_open (path.get (), gnutarget); - - if (abfd == nullptr) - warning (_("\"%ps\" from debuginfod cannot be opened as bfd: %s"), - styled_string (file_name_style.style (), path.get ()), - gdb_bfd_errmsg (bfd_get_error (), nullptr).c_str ()); - else if (!build_id_verify (abfd.get (), build_id->size, - build_id->data)) - abfd = nullptr; + /* Try to find the executable (or shared object) by looking for a + (sym)link on disk from the build-id to the object file. */ + abfd = build_id_to_exec_bfd (build_id->size, build_id->data); + + if (abfd != nullptr || attempt > 0) + break; + + /* Attempt to query debuginfod for the executable. This will only + get run during the first attempt, if an extension language hook + (see below) asked for a second attempt then we will have already + broken out of the loop above. */ + gdb::unique_xmalloc_ptr path; + scoped_fd fd = debuginfod_exec_query (build_id->data, build_id->size, + expected_filename, &path); + if (fd.get () >= 0) + { + abfd = gdb_bfd_open (path.get (), gnutarget); + + if (abfd == nullptr) + warning (_("\"%ps\" from debuginfod cannot be opened as bfd: %s"), + styled_string (file_name_style.style (), path.get ()), + gdb_bfd_errmsg (bfd_get_error (), nullptr).c_str ()); + else if (!build_id_verify (abfd.get (), build_id->size, + build_id->data)) + abfd = nullptr; + } + + if (abfd != nullptr) + break; + + ext_lang_missing_file_result ext_result + = ext_lang_find_objfile_from_buildid (pspace, build_id, + expected_filename); + if (!ext_result.filename ().empty ()) + { + /* The extension identified the file for us. */ + abfd = gdb_bfd_open (ext_result.filename ().c_str (), gnutarget); + if (abfd == nullptr) + { + warning (_("\"%ps\" from extension cannot be opened as bfd: %s"), + styled_string (file_name_style.style (), + ext_result.filename ().c_str ()), + gdb_bfd_errmsg (bfd_get_error (), nullptr).c_str ()); + break; + } + + /* If the extension gave us a path to a file then we always + assume that it is the correct file, we do no additional check + of its build-id. */ + } + else if (ext_result.try_again ()) + { + /* The extension might have installed the file in the expected + location, we should try again. */ + max_attempts = 2; + continue; + } } return abfd; diff --git a/gdb/build-id.h b/gdb/build-id.h index 1d2e7891f34..0174412c5bd 100644 --- a/gdb/build-id.h +++ b/gdb/build-id.h @@ -66,7 +66,8 @@ extern std::string find_separate_debug_file_by_buildid should be the file we were looking for but couldn't find. */ extern gdb_bfd_ref_ptr find_objfile_by_build_id - (const bfd_build_id *build_id, const char *expected_filename); + (struct program_space *pspace, const bfd_build_id *build_id, + const char *expected_filename); /* Return an hex-string representation of BUILD_ID. */ diff --git a/gdb/corelow.c b/gdb/corelow.c index 87ce04d6852..25de755a1dd 100644 --- a/gdb/corelow.c +++ b/gdb/corelow.c @@ -506,7 +506,8 @@ core_target::build_file_mappings () || !bfd_check_format (abfd.get (), bfd_object)) && file_data.build_id != nullptr) { - abfd = find_objfile_by_build_id (file_data.build_id, + abfd = find_objfile_by_build_id (current_program_space, + file_data.build_id, filename.c_str ()); if (abfd != nullptr) @@ -892,7 +893,8 @@ locate_exec_from_corefile_build_id (bfd *abfd, core_target *target, } gdb_bfd_ref_ptr execbfd - = find_objfile_by_build_id (build_id, filename.c_str ()); + = find_objfile_by_build_id (current_program_space, build_id, + filename.c_str ()); if (execbfd != nullptr) { diff --git a/gdb/extension-priv.h b/gdb/extension-priv.h index 90810e4bbc8..a31283f831c 100644 --- a/gdb/extension-priv.h +++ b/gdb/extension-priv.h @@ -295,6 +295,19 @@ struct extension_language_ops ext_lang_missing_file_result (*handle_missing_debuginfo) (const struct extension_language_defn *, struct objfile *objfile); + + /* Give extension languages a chance to deal with missing objfiles. + PSPACE is the program space in which GDB is searching for a missing + objfile, and will not be NULL. BUILD_ID is the build-id of the + objfile we're looking for, and will not be NULL. FILENAME is the name + of the file we're looking for, and will not be NULL. See + ext_lang_find_objfile_from_buildid for some additional information + about the meaning of FILENAME. */ + ext_lang_missing_file_result + (*find_objfile_from_buildid) (const struct extension_language_defn *, + program_space *pspace, + const struct bfd_build_id *build_id, + const char *filename); }; /* State necessary to restore a signal handler to its previous value. */ diff --git a/gdb/extension.c b/gdb/extension.c index 15e1f11d619..ec1aa138872 100644 --- a/gdb/extension.c +++ b/gdb/extension.c @@ -1070,6 +1070,28 @@ ext_lang_handle_missing_debuginfo (struct objfile *objfile) return {}; } +/* See extension.h. */ + +ext_lang_missing_file_result +ext_lang_find_objfile_from_buildid (program_space *pspace, + const struct bfd_build_id *build_id, + const char *filename) +{ + for (const struct extension_language_defn *extlang : extension_languages) + { + if (extlang->ops == nullptr + || extlang->ops->find_objfile_from_buildid == nullptr) + continue; + ext_lang_missing_file_result result + = extlang->ops->find_objfile_from_buildid (extlang, pspace, build_id, + filename); + if (!result.filename ().empty () || result.try_again ()) + return result; + } + + return {}; +} + /* Called via an observer before gdb prints its prompt. Iterate over the extension languages giving them a chance to change the prompt. The first one to change the prompt wins, diff --git a/gdb/extension.h b/gdb/extension.h index 2a749161508..ad3b4e6102d 100644 --- a/gdb/extension.h +++ b/gdb/extension.h @@ -36,6 +36,7 @@ struct ui_file; struct ui_out; struct value; struct value_print_options; +struct program_space; /* A function to load and process a script file. The file has been opened and is ready to be read from the beginning. @@ -410,6 +411,25 @@ struct ext_lang_missing_file_result extern ext_lang_missing_file_result ext_lang_handle_missing_debuginfo (struct objfile *objfile); +/* Called when GDB opens a core-file to find any object files for which a + build-id could be extracted from the core-file, but the matching file + could not otherwise be found by GDB. + + PSPACE is the program space in which GDB is opening the core-file and + is looking for a missing object file. BUILD_ID is the build-id of the + file being looked for, and will not be NULL. FILENAME is the name of + the file GDB is looking for, this will not be NULL. The FILENAME is + provided only for creating helpful messages for the user. FILENAME + might already exist on disk but have the wrong build-id, of FILENAME + might not exist on disk. If the missing objfile can be found then it + does not have to be placed at the location FILENAME. + + The returned object indicates if the file could be found or not. */ + +extern ext_lang_missing_file_result ext_lang_find_objfile_from_buildid + (program_space *pspace, const struct bfd_build_id *build_id, + const char *filename); + #if GDB_SELF_TEST namespace selftests { extern void (*hook_set_active_ext_lang) (); diff --git a/gdb/solib.c b/gdb/solib.c index 5c926def715..dfcee4309bd 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -525,7 +525,8 @@ solib_map_sections (solib &so) abfd = nullptr; if (abfd == nullptr) - abfd = find_objfile_by_build_id (mapped_file_info->build_id (), + abfd = find_objfile_by_build_id (current_program_space, + mapped_file_info->build_id (), so.so_name.c_str ()); if (abfd == nullptr && mismatch)