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

login
register
mail settings
Submitter Antoine Tremblay
Date Feb. 3, 2015, 8:19 p.m.
Message ID <1422994793-9861-2-git-send-email-antoine.tremblay@ericsson.com>
Download mbox | patch
Permalink /patch/4904/
State New
Headers show

Comments

Antoine Tremblay - Feb. 3, 2015, 8:19 p.m.
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
Antoine Tremblay - Feb. 3, 2015, 8:28 p.m.
Hi,
   Unfortunately the 1/2 patch of this patchset failed because it's 
about 1M , and mailman is only accepting < 400k emails...

   The patch is large since I'm replacing canonicalize-lgpl from 
binutils with canonicalize and that triggers a few dependencies..

   Any ideas on how I should proceed ?

   I could send a patch with only the change to the update-gnulib.sh maybe ?

Regards,

Antoine Tremblay


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;
Antoine Tremblay - Feb. 11, 2015, 1:27 p.m.
Hi,
    I have attached the 1/2 patch of this patchset as a bzip2 compressed 
patch so can it can be posted for review, hope it's ok...

Regards,

Antoine Tremblay

On 02/03/2015 03:28 PM, Antoine Tremblay wrote:
> Hi,
>   Unfortunately the 1/2 patch of this patchset failed because it's 
> about 1M , and mailman is only accepting < 400k emails...
>
>   The patch is large since I'm replacing canonicalize-lgpl from 
> binutils with canonicalize and that triggers a few dependencies..
>
>   Any ideas on how I should proceed ?
>
>   I could send a patch with only the change to the update-gnulib.sh 
> maybe ?
>
> Regards,
>
> Antoine Tremblay
>
>
> 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;
>
Antoine Tremblay - March 24, 2015, 3:11 p.m.
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;
>
Pedro Alves - March 27, 2015, 12:24 p.m.
On 02/03/2015 08:28 PM, Antoine Tremblay wrote:
> Hi,
>    Unfortunately the 1/2 patch of this patchset failed because it's 
> about 1M , and mailman is only accepting < 400k emails...
> 
>    The patch is large since I'm replacing canonicalize-lgpl from 
> binutils with canonicalize and that triggers a few dependencies..

Eh, so large...  What is it exactly pulling?

> 
>    Any ideas on how I should proceed ?
> 
>    I could send a patch with only the change to the update-gnulib.sh maybe ?

Yes, please, along with any other changes outside import/.
I assume you'll need to change gdb/gnulib/Makefile.in too.
And be sure to explain why canonicalize-lgpl doesn't work
for what we need.

Could you push the patches as a branch somewhere?  That'd
make it trivial to pull/try them.

Thanks,
Pedro Alves

Patch

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;