This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 2/2] Fix source file not found when part of the path does not exist but that a canonicalized path exists.


ping..

On 02/03/2015 03:19 PM, Antoine Tremblay wrote:
For example if you have an executable with debug symbols with a path that
looks like /build-server/program/build/../file.c  and try to insert a
breakpoint by using the CLI "b /build-server/program/file.c" gdb would fail
to find that file.

This patch makes gdb try to open a source file with its canonical path
even if parts of that path do not exist.

In this example when trying to open  /build-server/program/build/../file.c
we search for /build-server/program/file.c. even if the "build" directory
is not present on the system.

Also, since in general we do not need the full uncanonicalised path
to be present on the system and that we validate that the file exist
after a call to gdb_realpath with a subsequent call to open,
gdb_realpath was changed to accept that parts of the path or the whole
path be missing from the system.

This is done using canonicalize_filename_mode (filename, CAN_MISSING);

To make this behavior easy to adapt to multiple situations inside gdb
in the future, a new option to openp was added :

OPF_TRY_REALPATH = 0x08

This will try the canonicalized path when using the openp function.
As used in find_and_open_source to allow this feature.

Also added a small test case to verify the issue.

gdb/ChangeLog:

	PR breakpoints/17497
	* defs.h: Add OPF_TRY_REALPATH.
	* source.c (openp): Add OPF_TRY_REALPATH option.
	(find_and_open_source): Use OPF_TRY_REALPATH option to find a file.
	* utils.c (gdb_realpath): Change canonicalize_file_name
	to canonicalize_filename_mode with CAN_MISSING flag.

gdb/testsuite/ChangeLog:

	PR breakpoints/17497
	* gdb.base/Makefile.in: Add tryrealpath test.
	* gdb.base/break-canonical-path.c: New test.
	* gdb.base/break-canonical-path.exp: New file.
---
  gdb/defs.h                                      |    7 +-
  gdb/source.c                                    |   37 ++++++++--
  gdb/testsuite/gdb.base/Makefile.in              |    4 +-
  gdb/testsuite/gdb.base/break-canonical-path.c   |   22 ++++++
  gdb/testsuite/gdb.base/break-canonical-path.exp |   83 +++++++++++++++++++++++
  gdb/utils.c                                     |    3 +-
  6 files changed, 146 insertions(+), 10 deletions(-)
  create mode 100644 gdb/testsuite/gdb.base/break-canonical-path.c
  create mode 100644 gdb/testsuite/gdb.base/break-canonical-path.exp

diff --git a/gdb/defs.h b/gdb/defs.h
index a1cd45f..fac9b2c 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -310,9 +310,10 @@ extern const char *pc_prefix (CORE_ADDR);
  /* From source.c */

  /* See openp function definition for their description.  */
-#define OPF_TRY_CWD_FIRST     0x01
-#define OPF_SEARCH_IN_PATH    0x02
-#define OPF_RETURN_REALPATH   0x04
+#define OPF_TRY_CWD_FIRST   0x01
+#define OPF_SEARCH_IN_PATH  0x02
+#define OPF_RETURN_REALPATH 0x04
+#define OPF_TRY_REALPATH    0x08

  extern int openp (const char *, int, const char *, int, char **);

diff --git a/gdb/source.c b/gdb/source.c
index 574d9fa..1a3fbf9 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -769,8 +769,18 @@ openp (const char *path, int opts, const char *string,

        if (is_regular_file (string))
  	{
-	  filename = alloca (strlen (string) + 1);
-	  strcpy (filename, string);
+	  if (opts & OPF_TRY_REALPATH)
+	    {
+	      char *real_path = gdb_realpath (string);
+	      filename = alloca (strlen (real_path) + 1);
+	      strcpy (filename, real_path);
+	      xfree (real_path);
+	    }
+	  else
+	    {
+	      filename = alloca (strlen (string) + 1);
+	      strcpy (filename, string);
+	    }
  	  fd = gdb_open_cloexec (filename, mode, 0);
  	  if (fd >= 0)
  	    goto done;
@@ -867,6 +877,25 @@ openp (const char *path, int opts, const char *string,
        strcat (filename + len, SLASH_STRING);
        strcat (filename, string);

+      /* Try the canonical path. */
+      if (opts & OPF_TRY_REALPATH)
+	{
+	  char *real_path;
+	  int newlen;
+
+	  real_path = gdb_realpath (filename);
+
+	  /* First, realloc the filename buffer if too short.  */
+	  newlen = len + strlen (real_path) + 1;
+	  if (newlen > alloclen)
+	    {
+	      alloclen = newlen;
+	      filename = alloca (alloclen);
+	    }
+	  strcpy (filename, real_path);
+	  xfree (real_path);
+	}
+
        if (is_regular_file (filename))
  	{
  	  fd = gdb_open_cloexec (filename, mode, 0);
@@ -1083,8 +1112,8 @@ find_and_open_source (const char *filename,
          }
      }

-  result = openp (path, OPF_SEARCH_IN_PATH | OPF_RETURN_REALPATH, filename,
-		  OPEN_MODE, fullname);
+  result = openp (path, OPF_SEARCH_IN_PATH | OPF_RETURN_REALPATH |
+		  OPF_TRY_REALPATH, filename, OPEN_MODE, fullname);
    if (result < 0)
      {
        /* Didn't work.  Try using just the basename.  */
diff --git a/gdb/testsuite/gdb.base/Makefile.in b/gdb/testsuite/gdb.base/Makefile.in
index dda3169..1c23bbd 100644
--- a/gdb/testsuite/gdb.base/Makefile.in
+++ b/gdb/testsuite/gdb.base/Makefile.in
@@ -4,8 +4,8 @@ srcdir = @srcdir@
  EXECUTABLES = a2-run advance all-types annota1 annota1-watch_thread_num \
  	annota3 anon args arrayidx async attach attach-pie-misread \
  	attach2 auxv bang\! bfp-test bigcore bitfields bitfields2 \
-	break break-always break-entry break-interp-test breako2 \
-	breakpoint-shadow break-on-linker-gcd-function \
+	break break-always break-canonical-path break-entry break-interp-test \
+	breako2 breakpoint-shadow break-on-linker-gcd-function \
  	call-ar-st call-rt-st call-sc-t* call-signals \
  	call-strs callexit callfuncs callfwmall charset checkpoint \
  	chng-syms code_elim1 code_elim2 commands compiler completion complex \
diff --git a/gdb/testsuite/gdb.base/break-canonical-path.c b/gdb/testsuite/gdb.base/break-canonical-path.c
new file mode 100644
index 0000000..7e362b2
--- /dev/null
+++ b/gdb/testsuite/gdb.base/break-canonical-path.c
@@ -0,0 +1,22 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015 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 <http://www.gnu.org/licenses/>.  */
+
+int
+main (void)
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/break-canonical-path.exp b/gdb/testsuite/gdb.base/break-canonical-path.exp
new file mode 100644
index 0000000..511acaa
--- /dev/null
+++ b/gdb/testsuite/gdb.base/break-canonical-path.exp
@@ -0,0 +1,83 @@
+# Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.
+
+# This file tests if we can set a breakpoint provided our path is the
+# canonicalized path of a longer path with some parts that are not
+# present on the fs.
+# See breakpoints/17497 for more information
+
+# main directory for compilation
+set canonical_tmp_dir "break-canonical-path-tmp"
+# this directory will be deleted before putting the breakpoint
+set canonical_relative_dir "tmp"
+set canonical_srcfile_basename "break-canonical-path.c"
+
+standard_testfile $canonical_tmp_dir/$canonical_relative_dir/../$canonical_srcfile_basename
+
+proc canonical_cleanup {rmsrcfile rmreldir rmtmpdir} {
+    global subdir
+    global canonical_tmp_dir
+    global canonical_relative_dir
+    global canonical_srcfile_basename
+
+    if { $rmsrcfile && [catch { file delete $subdir/$canonical_tmp_dir/$canonical_srcfile_basename }] } {
+	print "file delete $subdir/$canonical_tmp_dir/$canonical_srcfile_basename failed"
+    }
+    if { $rmreldir && [catch { file delete  $subdir/$canonical_tmp_dir/$canonical_relative_dir }] } {
+	print "file delete $subdir/$canonical_tmp_dir/$canonical_relative_dir failed"
+    }
+    if { $rmtmpdir && [catch { file delete  $subdir/$canonical_tmp_dir }] } {
+	print "file delete $subdir/$canonical_tmp_di failed"
+    }
+}
+
+if [is_remote host] {
+    unsupported "Compiling on a remote host does not support a filename with directory."
+    return 0
+}
+
+if [catch { file mkdir "$subdir/$canonical_tmp_dir/$canonical_relative_dir" }]  {
+    untested "file mkdir $subdir/$canonical_tmp_dir/$canonical_relative_dir failed"
+    canonical_cleanup false true true
+    return 0
+}
+
+if [catch { file copy $srcdir/$subdir/$canonical_srcfile_basename $subdir/$canonical_tmp_dir }] {
+    untested "file copy $srcdir/$subdir/$srcfile_basename $subdir/$canonical_tmp_dir failed"
+    canonical_cleanup false true true
+    return 0
+}
+
+#compile with the to be deleted directory so that it is in the debug info
+set err [gdb_compile "$subdir/$srcfile" $binfile executable {debug}]
+if { $err != "" } {
+    untested "${srcfile} compilation failed"
+    canonical_cleanup true true true
+    return -1
+}
+
+#remove the directory so that we can test after that we can break even if it's not there
+#using the canonicalized version of the path
+if [catch { file delete $subdir/$canonical_tmp_dir/$canonical_relative_dir }] {
+    untested "rmdir  $subdir/$canonical_tmp_dir/$canonical_relative_dir failed"
+    canonical_cleanup true true true
+    return 0
+}
+
+clean_restart ${testfile}
+
+gdb_breakpoint $subdir/$canonical_tmp_dir/$canonical_srcfile_basename:[gdb_get_line_number "main" $srcdir/$subdir/$canonical_srcfile_basename] {message}
+
+canonical_cleanup true true true
diff --git a/gdb/utils.c b/gdb/utils.c
index 909476b..c97ead3 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -68,6 +68,7 @@
  #include "gdb_usleep.h"
  #include "interps.h"
  #include "gdb_regex.h"
+#include "canonicalize.h"

  #if !HAVE_DECL_MALLOC
  extern PTR malloc ();		/* ARI: PTR */
@@ -2889,7 +2890,7 @@ gdb_realpath (const char *filename)
    }
  #else
    {
-    char *rp = canonicalize_file_name (filename);
+    char *rp = canonicalize_filename_mode (filename, CAN_MISSING);

      if (rp != NULL)
        return rp;



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]