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

Antoine Tremblay antoine.tremblay@ericsson.com
Wed Feb 11 13:27:00 GMT 2015


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;
>

-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Replaced-binutils-module-canonicalize-lgpl-with-cano.patch.bz2
Type: application/x-bzip
Size: 139229 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/gdb-patches/attachments/20150211/4e82a1b0/attachment.bin>


More information about the Gdb-patches mailing list