From: Tom Tromey Date: Wed Apr 6 19:17:10 GMT 2022 Subject: [PATCH] Don't use realpath on objfile names Currently gdb uses realpath when finding an objfile. However, this yields surprising results when the given name is a symlink -- if the symlink is retargeted, re-running will not cause a change. This patch fixes the problem by changing gdb to compute the absolute path rather than the real path. This area has some history. PR gdb/15415 changed this area to try to preserve the basename of the executable, so that programs that check argv[0] will continue to work correctly. There's also PR gdb/15934, which proposes preserving the original name for use in argv[0] and in "info inferior". I haven't done this. The "info inferior" part might not be too difficult (unsure) but I wasn't sure how argv[0] could really be preserved given relative file names, the use of shell to startup, and the user's ability to change gdb's working directory. I think this patch does fix PR symtab/24143, which concerns finding separate debug files when symlinks are used. The included test does not test exactly this scenario, though. Regression tested on x86-64 Fedora 34. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=24143 --- gdb/exec.c | 14 ++----- gdb/symfile.c | 2 +- gdb/testsuite/gdb.base/symlink-exe.exp | 57 ++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 11 deletions(-) create mode 100644 gdb/testsuite/gdb.base/symlink-exe.exp diff --git a/gdb/exec.c b/gdb/exec.c index 84c36473abb..077db790ef6 100644 --- a/gdb/exec.c +++ b/gdb/exec.c @@ -386,7 +386,7 @@ exec_file_attach (const char *filename, int from_tty) else { int load_via_target = 0; - const char *scratch_pathname, *canonical_pathname; + const char *scratch_pathname; int scratch_chan; char **matching; @@ -398,7 +398,7 @@ exec_file_attach (const char *filename, int from_tty) load_via_target = 1; } - gdb::unique_xmalloc_ptr canonical_storage, scratch_storage; + gdb::unique_xmalloc_ptr scratch_storage; if (load_via_target) { /* gdb_bfd_fopen does not support "target:" filenames. */ @@ -409,7 +409,6 @@ exec_file_attach (const char *filename, int from_tty) scratch_pathname = filename; scratch_chan = -1; - canonical_pathname = scratch_pathname; } else { @@ -437,19 +436,14 @@ exec_file_attach (const char *filename, int from_tty) perror_with_name (filename); scratch_pathname = scratch_storage.get (); - - /* gdb_bfd_open (and its variants) prefers canonicalized - pathname for better BFD caching. */ - canonical_storage = gdb_realpath (scratch_pathname); - canonical_pathname = canonical_storage.get (); } gdb_bfd_ref_ptr temp; if (write_files && !load_via_target) - temp = gdb_bfd_fopen (canonical_pathname, gnutarget, + temp = gdb_bfd_fopen (scratch_pathname, gnutarget, FOPEN_RUB, scratch_chan); else - temp = gdb_bfd_open (canonical_pathname, gnutarget, scratch_chan); + temp = gdb_bfd_open (scratch_pathname, gnutarget, scratch_chan); current_program_space->set_exec_bfd (std::move (temp)); if (!current_program_space->exec_bfd ()) diff --git a/gdb/symfile.c b/gdb/symfile.c index dcd217c0a51..239513415ba 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -1707,7 +1707,7 @@ symfile_bfd_open (const char *name) /* Look down path for it, allocate 2nd new malloc'd copy. */ desc = openp (getenv ("PATH"), - OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, + OPF_TRY_CWD_FIRST, expanded_name.get (), O_RDONLY | O_BINARY, &absolute_name); #if defined(__GO32__) || defined(_WIN32) || defined (__CYGWIN__) if (desc < 0) diff --git a/gdb/testsuite/gdb.base/symlink-exe.exp b/gdb/testsuite/gdb.base/symlink-exe.exp new file mode 100644 index 00000000000..4a45f06b775 --- /dev/null +++ b/gdb/testsuite/gdb.base/symlink-exe.exp @@ -0,0 +1,57 @@ +# Copyright 2022 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 . */ + +if {![isnative]} { + unsupported "symlink-exe.exp not supported on non-native target" + return -1 +} + +if {[is_remote host]} { + unsupported "symlink-exe.exp not supported on remote host" + return -1 +} + +# We don't really care about the contents, but we're going to build +# two executables here and they need different source file names. +standard_testfile main.c argv0-symlink.c + +if {[build_executable ${testfile}.exp ${testfile}1 ${srcfile}] == -1} { + return -1 +} + +set status [remote_exec host \ + "ln -sf ${testfile}1 [standard_output_file ${testfile}]"] +if {[lindex $status 0] != 0} { + unsupported "symlink-exe.exp - host does not support symbolic links" + return -1 +} + +clean_restart $testfile +gdb_test "run" ".*" + +# Ensure the new file has a newer mtime. +sleep 1 +if {[build_executable ${testfile}.exp ${testfile}2 ${srcfile2}] == -1} { + return -1 +} +set status [remote_exec host \ + "ln -sf ${testfile}2 [standard_output_file ${testfile}]"] +if {[lindex $status 0] != 0} { + unsupported "symlink-exe.exp - host does not support symbolic links" + return -1 +} + +gdb_test "run" ".*${testfile}.* has changed; re-reading symbols.*" \ + "run and re-read symbols" -- 2.34.1