From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id MF8xJInf4WrtNj0AWB0awg (envelope-from ) for ; Wed, 28 Oct 2026 07:42:01 -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=X8z4BRDw; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 6BD8E378003; Wed, 28 Oct 2026 07:42: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=-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 1E812378002 for ; Wed, 28 Oct 2026 07:42:00 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2966B4BA23D9 for ; Wed, 28 Oct 2026 11:41:58 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2966B4BA23D9 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=X8z4BRDw 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 5CBE74BA2E3B for ; Wed, 28 Oct 2026 11:41:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 5CBE74BA2E3B 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 5CBE74BA2E3B 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=1793187674; cv=none; b=lM36U6B6fnPzNNyuWYH/UkqfkHHoNQxY9cufh17XN91QY9uy4R9NlOl6IhLNUvxcha0szBM0EIXEcAlvgTBimjszW/qxLv/1TewDi2EEBdW3QgaNrrp4RLTA2WNOToIpVBNA2+A2LlERxEnifKuFJ2DNHb4PMy53T3KwTK3HYBs= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1793187674; c=relaxed/simple; bh=Pd+tDGGXELmXuiihfHu5q0sRAV77qxFERl+V8P7nvg8=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=wtm12qRg7btTCW7whp/OtkFqBkVQPv2XF9haAq4sj6wPR3QV0RquMoFxu4Z93Qr8rpepn3ZdRwWo+isQJ1Pf5e0t0x3SA20DTW2g8nB13z1iQ/XWGyVEx4w6PKG/uxCeG5JopB/KMwBdEYnM/Egq56EUYaKWYumXVvBnue1mT6o= 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=X8z4BRDw DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 5CBE74BA2E3B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1793187673; 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=phEwVjOc95a2JCP2DRp2QlLYoBLDQ2fpj+5TKkK47y8=; b=X8z4BRDwX3dF32AHx+OH/L+kEAKPhkHoxrXt105baDyznr+sKPoxHnjQ+UPk60QK3ntH9g DAgB3UCmtLNZR0o+qSnwfKsG+3/xCTGQEkDdzgyCz/Yc1aBLx01X7KzfkX4qlMcEy4Suo7 aNStbsQeeabvVY2LKl5e32z69KBA7fM= Received: from mail-wr1-f72.google.com (mail-wr1-f72.google.com [209.85.221.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-260-1Fun8nc-NhyUylmNvS5Gsg-1; Wed, 28 Oct 2026 07:41:06 -0400 X-MC-Unique: 1Fun8nc-NhyUylmNvS5Gsg-1 X-Mimecast-MFC-AGG-ID: 1Fun8nc-NhyUylmNvS5Gsg_1793187665 Received: by mail-wr1-f72.google.com with SMTP id ffacd0b85a97d-48e0461e040so674831f8f.0 for ; Wed, 28 Oct 2026 04:41:06 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1793187665; x=1793792465; h=content-transfer-encoding:mime-version:references:in-reply-to :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=phEwVjOc95a2JCP2DRp2QlLYoBLDQ2fpj+5TKkK47y8=; b=o+0yPYvyx+qalIiRWKLKDhDPuuKSOlUCuwyRDYLKj/J7WvEjf4iwEd92GAp7L2J1tz 7bND8b3Assbq/BHwwGjQh0vgpkPxJZOaOdaWBzGwST7vJbzvPAvBjpua0vHPxbPq92RC sjRnYqpuMFQAd9kVpDsXWqncSp3VlCxFILrYqZv8kFijY6VOvyDJzLDGaK4m2qYu1ooT TscCffQRHLTrLbfYX7nv0KhJ1DbFtpf2tRR4uACMAgwQAG2umCtTt8j2HI1u95Z5Cx26 1OozRrNSTFncnoe6R/Gz8OmdszzQeTPKGmJAxrzhXMwQaB9tM0g9EhhyjDv2Fyxl7Teg j5DA== X-Gm-Message-State: AFq9FYIi9N5DBK7e81Qcxy+2zo/Kx5DqHg8mWXRdZVxURta9eFBfsFm7 lpApWoLTkbGejBS6Wev6tpGD125nXGLMEzQJD4hXd0kjEaqt1BG/TjNGeTzuUcDVQEIxe1A7iVZ NUe5yXy2Ytv5Nevewk63OPVOqEJHSdSF0JP8lLg+SbQsyXO3AGU1Sl/+mP72haui6zSnX1Wh+sV OdzZpVu6oRSF9Qw9+UdpAkG4TzPdUsadVf3se6Gixt+LuVD6A= X-Gm-Gg: AYBFou0dJIckCsD+GSOvh0V0o0eg7Mz2qI/dj6FdeTL8UJxbAJCH6QZmWwzvBrjtqJy EqlWeV31dT1muL1Fvp/TFq6Y9YP5P9OGSmu/5HWhnHYFT/6pwx8n8F9lI3Tqcf9EdzxDrG6otWe hvSqdFKoXEAJ/uFpTDoM3AIKkaSyVMPFL5m3l++/9vOwfrf1GydclB2uEhomuNgI0sx+mpSecRM N5TzfQ+oG+4T6LHPR5M4YgZcSPp1Sojxj0bkdLM0+5xzorKcgwaPyf0mfRGKUcqlAWZo59q/kjn pJ5Ozlvd2xeY6nfBhknWTIANbSSqow/r1nXg0ewK8JJdMP27o4VeaXneDoS/AcPGlnDbbaciIA1 zEW48mfJ8n/80F1uDhBRr5Z0BmODVZNa1YFm7i8iETSdIZ5w= X-Received: by 2002:a5d:67cc:0:b0:48e:870:7791 with SMTP id ffacd0b85a97d-48e5d45a4e2mr3671072f8f.26.1793187664801; Wed, 28 Oct 2026 04:41:04 -0700 (PDT) X-Received: by 2002:a5d:67cc:0:b0:48e:870:7791 with SMTP id ffacd0b85a97d-48e5d45a4e2mr3671002f8f.26.1793187664056; Wed, 28 Oct 2026 04:41:04 -0700 (PDT) Received: from localhost ([2a00:23c6:e11d:fb01:6748:4fce:3e30:6e23]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-48e3ecd3418sm25228890f8f.41.2026.10.28.04.41.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Oct 2026 04:41:03 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess , Tom Tromey Subject: [PATCHv2 1/2] gdb: check auto-load safe path after refreshing cached vector Date: Wed, 28 Oct 2026 11:40:56 +0000 Message-Id: <7a6aa52038b5b67884f684ab4d223dd6f43a70bb.1793187406.git.aburgess@redhat.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: References: <878q3oqmzp.fsf@tromey.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 6HezjJpHT6nCXFERSHMFtFWsvTBTIaXfQBSZTKglGbY_1793187665 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 commit fixes an issue that exists in the interaction between file_is_auto_load_safe and filename_is_in_auto_load_safe_path_vec. I believe that this issue has existed since the code was originally added in commit bccbefd2aab863e2. The file_is_auto_load_safe function takes a FILENAME and checks if that file is in the auto-load safe path. To avoid the expense of expanding the auto-load safe path on every check GDB pre-computes the expanded safe path in the global AUTO_LOAD_SAFE_PATH_VEC. The filename_is_in_auto_load_safe_path_vec checks if FILENAME is within the pre-computed vector or not. However, FILENAME might also be a symlink to another file. In this case, we also want to check if the real file is in the pre-computed vector. To do this we can call gdb_realpath on FILENAME and check this against the vector too. This work is also done in the filename_is_in_auto_load_safe_path_vec function. If filename_is_in_auto_load_safe_path_vec doesn't find FILENAME or the gdb_realpath equivalent in the auto-load safe path vector, then we need to consider that the vector might be out of date and needs recomputing. This recomputing is done in file_is_auto_load_safe with a call to the function auto_load_safe_path_vec_update. After this we can call filename_is_in_auto_load_safe_path_vec again to check against the updated vector. As both filename_is_in_auto_load_safe_path_vec calls might need to call gdb_realpath, and calling gdb_realpath is not cheap, the filename_is_in_auto_load_safe_path_vec allows the answer from the first call to be saved and reused in the second call. This also means that should the filesystem change under GDB's feet then the same real filename will be used by both filename_is_in_auto_load_safe_path_vec calls. This is the FILENAME_REALP argument that is passed to filename_is_in_auto_load_safe_path_vec; this is initially NULL, and might be set by the first call if FILENAME is not found in the auto-load safe path vector. There are some optimisations in place to try and avoid duplicate work. In filename_is_in_auto_load_safe_path_vec, if the computed FILENAME_REALP value is the same as the original FILENAME, then there is no need to check for FILENAME_REALP in AUTO_LOAD_SAFE_PATH_VEC. This will be a very common case and occurs when FILENAME is the actual file, not a symlink to some other file. However, there is another piece of code which I think is a similar idea, but is actually a mistake. The first check in filename_is_in_auto_load_safe_path_vec looks like this: for (const gdb::unique_xmalloc_ptr &p : auto_load_safe_path_vec) if (*filename_realp == NULL && filename_is_in_pattern (filename, p.get ())) { pattern = p.get (); break; } This is where we check if FILENAME is in AUTO_LOAD_SAFE_PATH_VEC. The first time that filename_is_in_auto_load_safe_path_vec is called the *FILENAME_REALP will always be NULL (see file_is_auto_load_safe to confirm this). But if the first filename_is_in_auto_load_safe_path_vec call returns false then gdb_realpath will have been called and *FILENAME_REALP will no longer be NULL. Only when the first call to filename_is_in_auto_load_safe_path_vec returns false do we make a second call to filename_is_in_auto_load_safe_path_vec. This means that for the second filename_is_in_auto_load_safe_path_vec call *FILENAME_REALP will never be NULL, and so based on the above code, which checks '*filename_realp == NULL', we will not check if FILENAME is in AUTO_LOAD_SAFE_PATH_VEC. But we already discussed the optimisation that avoids checking for FILENAME_REALP in AUTO_LOAD_SAFE_PATH_VEC when FILENAME and FILENAME_REALP are the same (which is often the case). So this means that, when FILENAME is a real file, one for which gdb_realpath returns the same filename unchanged, the second call to filename_is_in_auto_load_safe_path_vec will actually not perform any checks at all. This feels like it has to be a mistake. I think that this first '*filename_realp == NULL' check should be removed. Then, after we update the auto-load safe path vector, and make a second call to filename_is_in_auto_load_safe_path_vec, we will correctly check if FILENAME is in the now updated AUTO_LOAD_SAFE_PATH_VEC. --- gdb/auto-load.c | 2 +- .../auto-load-after-debug-dir-change-1.gdb | 17 +++ .../auto-load-after-debug-dir-change-2.gdb | 17 +++ .../auto-load-after-debug-dir-change.exp | 101 ++++++++++++++++++ 4 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 gdb/testsuite/gdb.base/auto-load-after-debug-dir-change-1.gdb create mode 100644 gdb/testsuite/gdb.base/auto-load-after-debug-dir-change-2.gdb create mode 100644 gdb/testsuite/gdb.base/auto-load-after-debug-dir-change.exp diff --git a/gdb/auto-load.c b/gdb/auto-load.c index ccbd091e1c2..371d24c2b37 100644 --- a/gdb/auto-load.c +++ b/gdb/auto-load.c @@ -457,7 +457,7 @@ filename_is_in_auto_load_safe_path_vec (const char *filename, const char *pattern = NULL; for (const gdb::unique_xmalloc_ptr &p : auto_load_safe_path_vec) - if (*filename_realp == NULL && filename_is_in_pattern (filename, p.get ())) + if (filename_is_in_pattern (filename, p.get ())) { pattern = p.get (); break; diff --git a/gdb/testsuite/gdb.base/auto-load-after-debug-dir-change-1.gdb b/gdb/testsuite/gdb.base/auto-load-after-debug-dir-change-1.gdb new file mode 100644 index 00000000000..05505085e7f --- /dev/null +++ b/gdb/testsuite/gdb.base/auto-load-after-debug-dir-change-1.gdb @@ -0,0 +1,17 @@ +# 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 . + +echo script_1_loaded\n +set $script_loaded=100 diff --git a/gdb/testsuite/gdb.base/auto-load-after-debug-dir-change-2.gdb b/gdb/testsuite/gdb.base/auto-load-after-debug-dir-change-2.gdb new file mode 100644 index 00000000000..92bfe0f6b18 --- /dev/null +++ b/gdb/testsuite/gdb.base/auto-load-after-debug-dir-change-2.gdb @@ -0,0 +1,17 @@ +# 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 . + +echo script_2_loaded\n +set $script_loaded=200 diff --git a/gdb/testsuite/gdb.base/auto-load-after-debug-dir-change.exp b/gdb/testsuite/gdb.base/auto-load-after-debug-dir-change.exp new file mode 100644 index 00000000000..6cb7a0a8432 --- /dev/null +++ b/gdb/testsuite/gdb.base/auto-load-after-debug-dir-change.exp @@ -0,0 +1,101 @@ +# 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 . + +# Test GDB's checking of the auto-load safe path via the $debugdir +# variable. +# +# The test changes the auto-load search-path and the +# debug-file-directory, and checks that GDB can keep up with these +# changes as the executable is repeatedly reloaded. + +require {!is_remote host} + +standard_testfile main.c -1.gdb -2.gdb + +if { [build_executable "build executable" ${testfile} ${srcfile}] } { + return +} + +set binfile_dir [file dirname $binfile] + +array set debug_dir {} +foreach i { 1 2 } { + set debug_dir($i) [file normalize [standard_output_file "debug_dir_$i"]] + remote_exec host "mkdir -p $debug_dir($i)" + remote_exec host "mkdir -p $debug_dir($i)/$binfile_dir" +} + +remote_exec host "cp $srcdir/$subdir/$srcfile2 $debug_dir(1)/$binfile_dir/$testfile-gdb.gdb" +remote_exec host "cp $srcdir/$subdir/$srcfile3 $debug_dir(2)/$binfile_dir/$testfile-gdb.gdb" + +clean_restart + +# Only load scripts from the debug file directory. +gdb_test_no_output "set auto-load safe-path \$debugdir" + +# Set the auto-load search path to be exactly the SEARCH_NUM entry in +# the global debug_dir array. +# +# Then set the debug file directory to the DEBUG_NUM entry in the +# global debug_dir array. As GDB's default auto-load search path +# includes '$debugdir', this means GDB will accept scripts found in +# this directory. +# +# Finally, load the executable, and check to see if the expected +# auto-load script was loaded. +# +# Every call to run_test_1 is done in the same GDB session so that any +# caching of the auto-load safe path will carry over between calls to +# this proc. +proc run_test_1 { search_num debug_num } { + global debug_dir + + gdb_test_no_output "set variable \$script_loaded = 0" \ + "reset script_loaded variable to a known value" + + # Where GDB should look for auto-load scripts. + gdb_test_no_output "set auto-load scripts-directory $debug_dir($search_num)" \ + "setup scripts directory" + + # The auto-load safe path is based on the debug file directory, + # which we setup here. + gdb_test_no_output "set debug-file-directory $debug_dir($debug_num)" \ + "set debug-file-directory" + + gdb_load ${::binfile} + + gdb_test {print $script_loaded} " = ${search_num}00" + + # Check that the expected script shows as auto-loaded in GDB's output. + gdb_assert {[regexp "script_${search_num}_loaded" $::gdb_file_cmd_msg]} \ + "expected script was loaded" + + # The '3 - SEARCH_NUM' converts: 2 => 1 and 1 => 2. This checks + # that the other script was not auto-loaded. + gdb_assert {![regexp "script_[expr {3 - $search_num}]_loaded" $::gdb_file_cmd_msg]} \ + "other script was not loaded" +} + +# Wrapper around run_test_1 which adds a test prefix. See run_test_1 +# for details. +proc run_test { search_num debug_num } { + with_test_prefix "search=$search_num, debug=$debug_num" { + run_test_1 $search_num $debug_num + } +} + +# Run the tests. +run_test 1 1 +run_test 2 2 -- 2.25.4