file-prefix-map: Fix up -f*-prefix-map= [PR108464]

Message ID Y8qt0/yOySGsLEnt@tucnak
State New
Headers
Series file-prefix-map: Fix up -f*-prefix-map= [PR108464] |

Commit Message

Jakub Jelinek Jan. 20, 2023, 3:05 p.m. UTC
  Hi!

On Tue, Nov 01, 2022 at 01:46:20PM -0600, Jeff Law via Gcc-patches wrote:
> > This does cause a change of behaviour if users were previously relying upon
> > symlinks or absolute paths not being resolved.
> 
> I'm not too worried about this scenario.

As mentioned in the PR, this patch breaks e.g. ccache testsuite.

I strongly doubt most of the users want such a behavior, because it
makes all filenames absolute when -f*-prefix-map= options remap one
absolute path to another one.
Say if I'm in /tmp and /tmp is the canonical path and there is
src/test.c file, with -fdebug-prefix-map=/tmp=/blah
previously there would be DW_AT_comp_dir "/blah" and it is still there,
but DW_AT_name which was previouly "src/test.c" (relative against
DW_AT_comp_dir) is now "/blah/src/test.c" instead.

Even worse, the canonicalization is only done on the remap_filename
argument, but not on the old_prefix side.  That is e.g. what breaks
ccache.  If there is
/tmp/foobar1 directory and
ln -sf foobar1 /tmp/foobar2
cd /tmp/foobar2
then -fdebug-prefix-map=`pwd`:/blah will just not work, while
src/test.c will be canonicalized to /tmp/foobar1/src/test.c,
old_prefix is still what the user provided which is /tmp/foobar2.
User would need to change their uses to use -fdebug-prefix-map=`realpath $(pwd)`=/blah

I'm attaching 3 so far just compile tested patches.

The first patch just reverts the patch (and its follow-up patch).

The second introduces a new option, -f{,no}-canon-prefix-map which affects
the behavior of -f{file,macro,debug,profile}-prefix-map=, if on it
canonicalizes the old path of the prefix map option and compares that
against the canonicalized filename for absolute paths but not relative.

And last is like the second, but does that also for relative paths except
for filenames with no / (or / or \ on DOS based fs).  So, the third patch
gets an optional behavior of what has been on the trunk lately with the
difference that the old_prefix is canonicalized by the compiler.

Initially I've thought I'd just add some magic syntax to the OLD=NEW
argument of those options (because there are 4 of them), but as noted
in the comments, = is valid char in OLD (just not new), so it would
be hard to figure out some syntax.  So instead a new option, which one
can turn on and off for different -f*-prefix-map= options if needed.

-fdebug-prefix-map=/path1=/mypath1 -fcanon-prefix-map \
-fdebug-prefix-map=/path2=/mypath2 -fno-canon-prefix-map \
-fdebug-prefix-map=/path3=/mypath3

will use the old behavior for the /path1 and /path3 handling and
the new one only for /path2 handling.

Thoughts on this?

	Jakub
2023-01-20  Jakub Jelinek  <jakub@redhat.com>

	PR other/108464
	* file-prefix-map.cc (remap_filename): Revert 2022-11-01 and 2022-11-07
	changes.
2023-01-20  Jakub Jelinek  <jakub@redhat.com>

	PR other/108464
	* common.opt (fcanon-prefix-map): New option.
	* opts.cc: Include file-prefix-map.h.
	(flag_canon_prefix_map): New variable.
	(common_handle_option): Handle OPT_fcanon_prefix_map.
	(gen_command_line_string): Ignore OPT_fcanon_prefix_map.
	* file-prefix-map.h (flag_canon_prefix_map): Declare.
	* file-prefix-map.cc (struct file_prefix_map): Add canonicalize
	member.
	(add_prefix_map): Initialize canonicalize member from
	flag_canon_prefix_map, and if true and old_prefix is absolute
	pathname, canonicalize it using lrealpath.
	(remap_filename): Revert 2022-11-01 and 2022-11-07 changes,
	use lrealpath result only for absolute filenames and only for
	map->canonicalize map entries.
	* lto-opts.cc (lto_write_options): Ignore OPT_fcanon_prefix_map.
	* opts-global.cc (handle_common_deferred_options): Clear
	flag_canon_prefix_map at the start and handle OPT_fcanon_prefix_map.
	* doc/invoke.texi (-fcanon-prefix-map): Document.
	(-ffile-prefix-map, -fdebug-prefix-map, -fprofile-prefix-map): Add
	see also for -fcanon-prefix-map.
	* doc/cppopts.texi (-fmacro-prefix-map): Likewise.

--- gcc/common.opt.jj	2023-01-09 13:18:28.298019442 +0100
+++ gcc/common.opt	2023-01-20 12:43:17.152178057 +0100
@@ -1204,6 +1204,10 @@ fchecking=
 Common Joined RejectNegative UInteger Var(flag_checking)
 Perform internal consistency checkings.
 
+fcanon-prefix-map
+Common Var(common_deferred_options) Defer
+For -f*-prefix-map= options compare canonicalized pathnames rather than just strings.
+
 fcode-hoisting
 Common Var(flag_code_hoisting) Optimization
 Enable code hoisting.
--- gcc/opts.cc.jj	2023-01-02 09:32:52.073856323 +0100
+++ gcc/opts.cc	2023-01-20 13:54:53.526705571 +0100
@@ -34,10 +34,14 @@ along with GCC; see the file COPYING3.
 #include "diagnostic-color.h"
 #include "version.h"
 #include "selftest.h"
+#include "file-prefix-map.h"
 
 /* In this file all option sets are explicit.  */
 #undef OPTION_SET_P
 
+/* Set by -fcanon-prefix-map.  */
+bool flag_canon_prefix_map;
+
 static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff);
 
 /* Names of fundamental debug info formats indexed by enum
@@ -2812,6 +2816,10 @@ common_handle_option (struct gcc_options
       /* Deferred.  */
       break;
 
+    case OPT_fcanon_prefix_map:
+      flag_canon_prefix_map = value;
+      break;
+
     case OPT_fcallgraph_info:
       opts->x_flag_callgraph_info = CALLGRAPH_INFO_NAKED;
       break;
@@ -3718,6 +3726,7 @@ gen_command_line_string (cl_decoded_opti
       case OPT_fmacro_prefix_map_:
       case OPT_ffile_prefix_map_:
       case OPT_fprofile_prefix_map_:
+      case OPT_fcanon_prefix_map:
       case OPT_fcompare_debug:
       case OPT_fchecking:
       case OPT_fchecking_:
--- gcc/file-prefix-map.h.jj	2023-01-02 09:32:33.258128185 +0100
+++ gcc/file-prefix-map.h	2023-01-20 12:44:31.542094469 +0100
@@ -22,6 +22,7 @@ void add_macro_prefix_map (const char *)
 void add_debug_prefix_map (const char *);
 void add_file_prefix_map (const char *);
 void add_profile_prefix_map (const char *);
+extern bool flag_canon_prefix_map;
 
 const char *remap_macro_filename (const char *);
 const char *remap_debug_filename (const char *);
--- gcc/file-prefix-map.cc.jj	2023-01-02 09:32:52.787846007 +0100
+++ gcc/file-prefix-map.cc	2023-01-20 13:53:31.568896433 +0100
@@ -30,6 +30,7 @@ struct file_prefix_map
   const char *new_prefix;
   size_t old_len;
   size_t new_len;
+  bool canonicalize;
   struct file_prefix_map *next;
 };
 
@@ -51,8 +52,16 @@ add_prefix_map (file_prefix_map *&maps,
       return;
     }
   map = XNEW (file_prefix_map);
+  map->canonicalize = flag_canon_prefix_map;
   map->old_prefix = xstrndup (arg, p - arg);
   map->old_len = p - arg;
+  if (map->canonicalize && IS_ABSOLUTE_PATH (map->old_prefix))
+    {
+      char *realname = lrealpath (map->old_prefix);
+      free (const_cast <char *> (map->old_prefix));
+      map->old_prefix = realname;
+      map->old_len = strlen (realname);
+    }
   p++;
   map->new_prefix = xstrdup (p);
   map->new_len = strlen (p);
@@ -70,23 +79,32 @@ remap_filename (file_prefix_map *maps, c
   file_prefix_map *map;
   char *s;
   const char *name;
-  char *realname;
+  char *realname = NULL;
   size_t name_len;
 
-  if (!filename || lbasename (filename) == filename)
+  if (!filename)
     return filename;
 
-  realname = lrealpath (filename);
-
+  bool absolute = IS_ABSOLUTE_PATH (filename);
   for (map = maps; map; map = map->next)
-    if (filename_ncmp (realname, map->old_prefix, map->old_len) == 0)
+    if (map->canonicalize && absolute)
+      {
+	if (realname == NULL)
+	  realname = lrealpath (filename);
+	if (filename_ncmp (realname, map->old_prefix, map->old_len) == 0)
+	  break;
+      }
+    else if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
       break;
   if (!map)
     {
       free (realname);
       return filename;
     }
-  name = realname + map->old_len;
+  if (map->canonicalize && absolute)
+    name = realname + map->old_len;
+  else
+    name = filename + map->old_len;
   name_len = strlen (name) + 1;
 
   s = (char *) ggc_alloc_atomic (name_len + map->new_len);
@@ -97,7 +115,7 @@ remap_filename (file_prefix_map *maps, c
 }
 
 /* NOTE: if adding another -f*-prefix-map option then don't forget to
-   ignore it in DW_AT_producer (dwarf2out.cc).  */
+   ignore it in DW_AT_producer (gen_command_line_string in opts.cc).  */
 
 /* Linked lists of file_prefix_map structures.  */
 static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map  */
--- gcc/lto-opts.cc.jj	2023-01-02 09:32:29.547181803 +0100
+++ gcc/lto-opts.cc	2023-01-20 13:55:35.010102584 +0100
@@ -150,6 +150,7 @@ lto_write_options (void)
 	case OPT_ffile_prefix_map_:
 	case OPT_fmacro_prefix_map_:
 	case OPT_fprofile_prefix_map_:
+	case OPT_fcanon_prefix_map:
 	case OPT_fwhole_program:
 	  continue;
 
--- gcc/opts-global.cc.jj	2023-01-02 09:32:35.169100574 +0100
+++ gcc/opts-global.cc	2023-01-20 13:38:31.174977423 +0100
@@ -364,6 +364,7 @@ handle_common_deferred_options (void)
   if (flag_opt_info)
     opt_info_switch_p (NULL);
 
+  flag_canon_prefix_map = false;
   FOR_EACH_VEC_ELT (v, i, opt)
     {
       switch (opt->opt_index)
@@ -392,6 +393,10 @@ handle_common_deferred_options (void)
 	  add_profile_prefix_map (opt->arg);
 	  break;
 
+	case OPT_fcanon_prefix_map:
+	  flag_canon_prefix_map = opt->value;
+	  break;
+
 	case OPT_fdump_:
 	  g->get_dumps ()->dump_switch_p (opt->arg);
 	  break;
--- gcc/doc/invoke.texi.jj	2023-01-16 11:52:16.115733593 +0100
+++ gcc/doc/invoke.texi	2023-01-20 14:44:47.514203801 +0100
@@ -191,7 +191,7 @@ in the following sections.
 -dumpdir @var{dumppfx}  -x @var{language}  @gol
 -v  -###  --help@r{[}=@var{class}@r{[},@dots{}@r{]]}  --target-help  --version @gol
 -pass-exit-codes  -pipe  -specs=@var{file}  -wrapper  @gol
-@@@var{file}  -ffile-prefix-map=@var{old}=@var{new}  @gol
+@@@var{file}  -ffile-prefix-map=@var{old}=@var{new}  -fcanon-prefix-map  @gol
 -fplugin=@var{file}  -fplugin-arg-@var{name}=@var{arg}  @gol
 -fdump-ada-spec@r{[}-slim@r{]}  -fada-spec-parent=@var{unit}  -fdump-go-spec=@var{file}}
 
@@ -2203,9 +2203,20 @@ files resided in directory @file{@var{ne
 option is equivalent to specifying all the individual
 @option{-f*-prefix-map} options.  This can be used to make reproducible
 builds that are location independent.  Directories referenced by
-directives are not affected by these options. See also
-@option{-fmacro-prefix-map}, @option{-fdebug-prefix-map} and
-@option{-fprofile-prefix-map}.
+directives are not affected by these options.  See also
+@option{-fmacro-prefix-map}, @option{-fdebug-prefix-map},
+@option{-fprofile-prefix-map} and @option{-fcanon-prefix-map}.
+
+@item -fcanon-prefix-map
+@opindex fcanon-prefix-map
+For the @option{-f*-prefix-map} options normally comparison
+of @file{@var{old}} prefix against the filename that would be normally
+referenced in the result of the compilation is done using textual
+comparison of the prefixes, or ignoring character case for case insensitive
+filesystems and considering slashes and backslashes as equal on DOS based
+filesystems.  The @option{-fcanon-prefix-map} causes such comparisons
+to be done for absolute pathnames on canonicalized paths of @file{@var{old}}
+and the referenced filename.
 
 @item -fplugin=@var{name}.so
 @opindex fplugin
@@ -11289,7 +11300,8 @@ build-time path with an install-time pat
 also be used to change an absolute path to a relative path by using
 @file{.} for @var{new}.  This can give more reproducible builds, which
 are location independent, but may require an extra command to tell GDB
-where to find the source files. See also @option{-ffile-prefix-map}.
+where to find the source files. See also @option{-ffile-prefix-map}
+and @option{-fcanon-prefix-map}.
 
 @item -fvar-tracking
 @opindex fvar-tracking
@@ -16466,7 +16478,7 @@ When compiling files residing in directo
 profiling information (with @option{--coverage})
 describing them as if the files resided in
 directory @file{@var{new}} instead.
-See also @option{-ffile-prefix-map}.
+See also @option{-ffile-prefix-map} and @option{-fcanon-prefix-map}.
 
 @item -fprofile-update=@var{method}
 @opindex fprofile-update
--- gcc/doc/cppopts.texi.jj	2023-01-16 11:52:16.102733784 +0100
+++ gcc/doc/cppopts.texi	2023-01-20 14:45:09.106890233 +0100
@@ -305,7 +305,7 @@ to change an absolute path to a relative
 @var{new} which can result in more reproducible builds that are
 location independent.  This option also affects
 @code{__builtin_FILE()} during compilation.  See also
-@option{-ffile-prefix-map}.
+@option{-ffile-prefix-map} and @option{-fcanon-prefix-map}.
 
 @item -fexec-charset=@var{charset}
 @opindex fexec-charset
2023-01-20  Jakub Jelinek  <jakub@redhat.com>

	PR other/108464
	* common.opt (fcanon-prefix-map): New option.
	* opts.cc: Include file-prefix-map.h.
	(flag_canon_prefix_map): New variable.
	(common_handle_option): Handle OPT_fcanon_prefix_map.
	(gen_command_line_string): Ignore OPT_fcanon_prefix_map.
	* file-prefix-map.h (flag_canon_prefix_map): Declare.
	* file-prefix-map.cc (struct file_prefix_map): Add canonicalize
	member.
	(add_prefix_map): Initialize canonicalize member from
	flag_canon_prefix_map, and if true canonicalize it using lrealpath.
	(remap_filename): Revert 2022-11-01 and 2022-11-07 changes,
	use lrealpath result only for map->canonicalize map entries.
	* lto-opts.cc (lto_write_options): Ignore OPT_fcanon_prefix_map.
	* opts-global.cc (handle_common_deferred_options): Clear
	flag_canon_prefix_map at the start and handle OPT_fcanon_prefix_map.
	* doc/invoke.texi (-fcanon-prefix-map): Document.
	(-ffile-prefix-map, -fdebug-prefix-map, -fprofile-prefix-map): Add
	see also for -fcanon-prefix-map.
	* doc/cppopts.texi (-fmacro-prefix-map): Likewise.

--- gcc/common.opt.jj	2023-01-09 13:18:28.298019442 +0100
+++ gcc/common.opt	2023-01-20 12:43:17.152178057 +0100
@@ -1204,6 +1204,10 @@ fchecking=
 Common Joined RejectNegative UInteger Var(flag_checking)
 Perform internal consistency checkings.
 
+fcanon-prefix-map
+Common Var(common_deferred_options) Defer
+For -f*-prefix-map= options compare canonicalized pathnames rather than just strings.
+
 fcode-hoisting
 Common Var(flag_code_hoisting) Optimization
 Enable code hoisting.
--- gcc/opts.cc.jj	2023-01-02 09:32:52.073856323 +0100
+++ gcc/opts.cc	2023-01-20 13:54:53.526705571 +0100
@@ -34,10 +34,14 @@ along with GCC; see the file COPYING3.
 #include "diagnostic-color.h"
 #include "version.h"
 #include "selftest.h"
+#include "file-prefix-map.h"
 
 /* In this file all option sets are explicit.  */
 #undef OPTION_SET_P
 
+/* Set by -fcanon-prefix-map.  */
+bool flag_canon_prefix_map;
+
 static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff);
 
 /* Names of fundamental debug info formats indexed by enum
@@ -2812,6 +2816,10 @@ common_handle_option (struct gcc_options
       /* Deferred.  */
       break;
 
+    case OPT_fcanon_prefix_map:
+      flag_canon_prefix_map = value;
+      break;
+
     case OPT_fcallgraph_info:
       opts->x_flag_callgraph_info = CALLGRAPH_INFO_NAKED;
       break;
@@ -3718,6 +3726,7 @@ gen_command_line_string (cl_decoded_opti
       case OPT_fmacro_prefix_map_:
       case OPT_ffile_prefix_map_:
       case OPT_fprofile_prefix_map_:
+      case OPT_fcanon_prefix_map:
       case OPT_fcompare_debug:
       case OPT_fchecking:
       case OPT_fchecking_:
--- gcc/file-prefix-map.h.jj	2023-01-02 09:32:33.258128185 +0100
+++ gcc/file-prefix-map.h	2023-01-20 12:44:31.542094469 +0100
@@ -22,6 +22,7 @@ void add_macro_prefix_map (const char *)
 void add_debug_prefix_map (const char *);
 void add_file_prefix_map (const char *);
 void add_profile_prefix_map (const char *);
+extern bool flag_canon_prefix_map;
 
 const char *remap_macro_filename (const char *);
 const char *remap_debug_filename (const char *);
--- gcc/file-prefix-map.cc.jj	2023-01-02 09:32:52.787846007 +0100
+++ gcc/file-prefix-map.cc	2023-01-20 15:42:30.661088219 +0100
@@ -30,6 +30,7 @@ struct file_prefix_map
   const char *new_prefix;
   size_t old_len;
   size_t new_len;
+  bool canonicalize;
   struct file_prefix_map *next;
 };
 
@@ -51,8 +52,16 @@ add_prefix_map (file_prefix_map *&maps,
       return;
     }
   map = XNEW (file_prefix_map);
+  map->canonicalize = flag_canon_prefix_map;
   map->old_prefix = xstrndup (arg, p - arg);
   map->old_len = p - arg;
+  if (map->canonicalize)
+    {
+      char *realname = lrealpath (map->old_prefix);
+      free (const_cast <char *> (map->old_prefix));
+      map->old_prefix = realname;
+      map->old_len = strlen (realname);
+    }
   p++;
   map->new_prefix = xstrdup (p);
   map->new_len = strlen (p);
@@ -70,34 +79,49 @@ remap_filename (file_prefix_map *maps, c
   file_prefix_map *map;
   char *s;
   const char *name;
-  char *realname;
+  const char *realname = NULL;
   size_t name_len;
 
-  if (!filename || lbasename (filename) == filename)
+  if (!filename)
     return filename;
 
-  realname = lrealpath (filename);
-
   for (map = maps; map; map = map->next)
-    if (filename_ncmp (realname, map->old_prefix, map->old_len) == 0)
+    if (map->canonicalize)
+      {
+	if (realname == NULL)
+	  {
+	    if (lbasename (filename) == filename)
+	      realname = filename;
+	    else
+	      realname = lrealpath (filename);
+	  }
+	if (filename_ncmp (realname, map->old_prefix, map->old_len) == 0)
+	  break;
+      }
+    else if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
       break;
   if (!map)
     {
-      free (realname);
+      if (realname != filename)
+	free (const_cast <char *> (realname));
       return filename;
     }
-  name = realname + map->old_len;
+  if (map->canonicalize)
+    name = realname + map->old_len;
+  else
+    name = filename + map->old_len;
   name_len = strlen (name) + 1;
 
   s = (char *) ggc_alloc_atomic (name_len + map->new_len);
   memcpy (s, map->new_prefix, map->new_len);
   memcpy (s + map->new_len, name, name_len);
-  free (realname);
+  if (realname != filename)
+    free (const_cast <char *> (realname));
   return s;
 }
 
 /* NOTE: if adding another -f*-prefix-map option then don't forget to
-   ignore it in DW_AT_producer (dwarf2out.cc).  */
+   ignore it in DW_AT_producer (gen_command_line_string in opts.cc).  */
 
 /* Linked lists of file_prefix_map structures.  */
 static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map  */
--- gcc/lto-opts.cc.jj	2023-01-02 09:32:29.547181803 +0100
+++ gcc/lto-opts.cc	2023-01-20 13:55:35.010102584 +0100
@@ -150,6 +150,7 @@ lto_write_options (void)
 	case OPT_ffile_prefix_map_:
 	case OPT_fmacro_prefix_map_:
 	case OPT_fprofile_prefix_map_:
+	case OPT_fcanon_prefix_map:
 	case OPT_fwhole_program:
 	  continue;
 
--- gcc/opts-global.cc.jj	2023-01-02 09:32:35.169100574 +0100
+++ gcc/opts-global.cc	2023-01-20 13:38:31.174977423 +0100
@@ -364,6 +364,7 @@ handle_common_deferred_options (void)
   if (flag_opt_info)
     opt_info_switch_p (NULL);
 
+  flag_canon_prefix_map = false;
   FOR_EACH_VEC_ELT (v, i, opt)
     {
       switch (opt->opt_index)
@@ -392,6 +393,10 @@ handle_common_deferred_options (void)
 	  add_profile_prefix_map (opt->arg);
 	  break;
 
+	case OPT_fcanon_prefix_map:
+	  flag_canon_prefix_map = opt->value;
+	  break;
+
 	case OPT_fdump_:
 	  g->get_dumps ()->dump_switch_p (opt->arg);
 	  break;
--- gcc/doc/invoke.texi.jj	2023-01-16 11:52:16.115733593 +0100
+++ gcc/doc/invoke.texi	2023-01-20 14:44:47.514203801 +0100
@@ -191,7 +191,7 @@ in the following sections.
 -dumpdir @var{dumppfx}  -x @var{language}  @gol
 -v  -###  --help@r{[}=@var{class}@r{[},@dots{}@r{]]}  --target-help  --version @gol
 -pass-exit-codes  -pipe  -specs=@var{file}  -wrapper  @gol
-@@@var{file}  -ffile-prefix-map=@var{old}=@var{new}  @gol
+@@@var{file}  -ffile-prefix-map=@var{old}=@var{new}  -fcanon-prefix-map  @gol
 -fplugin=@var{file}  -fplugin-arg-@var{name}=@var{arg}  @gol
 -fdump-ada-spec@r{[}-slim@r{]}  -fada-spec-parent=@var{unit}  -fdump-go-spec=@var{file}}
 
@@ -2203,9 +2203,20 @@ files resided in directory @file{@var{ne
 option is equivalent to specifying all the individual
 @option{-f*-prefix-map} options.  This can be used to make reproducible
 builds that are location independent.  Directories referenced by
-directives are not affected by these options. See also
-@option{-fmacro-prefix-map}, @option{-fdebug-prefix-map} and
-@option{-fprofile-prefix-map}.
+directives are not affected by these options.  See also
+@option{-fmacro-prefix-map}, @option{-fdebug-prefix-map},
+@option{-fprofile-prefix-map} and @option{-fcanon-prefix-map}.
+
+@item -fcanon-prefix-map
+@opindex fcanon-prefix-map
+For the @option{-f*-prefix-map} options normally comparison
+of @file{@var{old}} prefix against the filename that would be normally
+referenced in the result of the compilation is done using textual
+comparison of the prefixes, or ignoring character case for case insensitive
+filesystems and considering slashes and backslashes as equal on DOS based
+filesystems.  The @option{-fcanon-prefix-map} causes such comparisons
+to be done on canonicalized paths of @file{@var{old}}
+and the referenced filename.
 
 @item -fplugin=@var{name}.so
 @opindex fplugin
@@ -11289,7 +11300,8 @@ build-time path with an install-time pat
 also be used to change an absolute path to a relative path by using
 @file{.} for @var{new}.  This can give more reproducible builds, which
 are location independent, but may require an extra command to tell GDB
-where to find the source files. See also @option{-ffile-prefix-map}.
+where to find the source files. See also @option{-ffile-prefix-map}
+and @option{-fcanon-prefix-map}.
 
 @item -fvar-tracking
 @opindex fvar-tracking
@@ -16466,7 +16478,7 @@ When compiling files residing in directo
 profiling information (with @option{--coverage})
 describing them as if the files resided in
 directory @file{@var{new}} instead.
-See also @option{-ffile-prefix-map}.
+See also @option{-ffile-prefix-map} and @option{-fcanon-prefix-map}.
 
 @item -fprofile-update=@var{method}
 @opindex fprofile-update
--- gcc/doc/cppopts.texi.jj	2023-01-16 11:52:16.102733784 +0100
+++ gcc/doc/cppopts.texi	2023-01-20 14:45:09.106890233 +0100
@@ -305,7 +305,7 @@ to change an absolute path to a relative
 @var{new} which can result in more reproducible builds that are
 location independent.  This option also affects
 @code{__builtin_FILE()} during compilation.  See also
-@option{-ffile-prefix-map}.
+@option{-ffile-prefix-map} and @option{-fcanon-prefix-map}.
 
 @item -fexec-charset=@var{charset}
 @opindex fexec-charset
  

Comments

Jakub Jelinek Jan. 23, 2023, 3:39 p.m. UTC | #1
On Fri, Jan 20, 2023 at 04:05:55PM +0100, Jakub Jelinek via Gcc-patches wrote:
> I'm attaching 3 so far just compile tested patches.

So far successfully bootstrapped/regtested the first and third patches,
both on x86_64-linux and i686-linux.

	Jakub
  
Jakub Jelinek March 10, 2023, 8:49 a.m. UTC | #2
Hi!

I'd like to ping these patches.  All 3 variants have been
bootstrapped/regtested on x86_64-linux and i686-linux, the last
one is my preference I guess.  The current state breaks e.g. ccache.

https://gcc.gnu.org/pipermail/gcc-patches/2023-January/610285.html
  - PR108464 - P1 - file-prefix-map: Fix up -f*-prefix-map= (3 variants)

Thanks
	Jakub

On Fri, Jan 20, 2023 at 04:05:55PM +0100, Jakub Jelinek via Gcc-patches wrote:
> On Tue, Nov 01, 2022 at 01:46:20PM -0600, Jeff Law via Gcc-patches wrote:
> > > This does cause a change of behaviour if users were previously relying upon
> > > symlinks or absolute paths not being resolved.
> > 
> > I'm not too worried about this scenario.
> 
> As mentioned in the PR, this patch breaks e.g. ccache testsuite.
> 
> I strongly doubt most of the users want such a behavior, because it
> makes all filenames absolute when -f*-prefix-map= options remap one
> absolute path to another one.
> Say if I'm in /tmp and /tmp is the canonical path and there is
> src/test.c file, with -fdebug-prefix-map=/tmp=/blah
> previously there would be DW_AT_comp_dir "/blah" and it is still there,
> but DW_AT_name which was previouly "src/test.c" (relative against
> DW_AT_comp_dir) is now "/blah/src/test.c" instead.
> 
> Even worse, the canonicalization is only done on the remap_filename
> argument, but not on the old_prefix side.  That is e.g. what breaks
> ccache.  If there is
> /tmp/foobar1 directory and
> ln -sf foobar1 /tmp/foobar2
> cd /tmp/foobar2
> then -fdebug-prefix-map=`pwd`:/blah will just not work, while
> src/test.c will be canonicalized to /tmp/foobar1/src/test.c,
> old_prefix is still what the user provided which is /tmp/foobar2.
> User would need to change their uses to use -fdebug-prefix-map=`realpath $(pwd)`=/blah
> 
> I'm attaching 3 so far just compile tested patches.
> 
> The first patch just reverts the patch (and its follow-up patch).
> 
> The second introduces a new option, -f{,no}-canon-prefix-map which affects
> the behavior of -f{file,macro,debug,profile}-prefix-map=, if on it
> canonicalizes the old path of the prefix map option and compares that
> against the canonicalized filename for absolute paths but not relative.
> 
> And last is like the second, but does that also for relative paths except
> for filenames with no / (or / or \ on DOS based fs).  So, the third patch
> gets an optional behavior of what has been on the trunk lately with the
> difference that the old_prefix is canonicalized by the compiler.
> 
> Initially I've thought I'd just add some magic syntax to the OLD=NEW
> argument of those options (because there are 4 of them), but as noted
> in the comments, = is valid char in OLD (just not new), so it would
> be hard to figure out some syntax.  So instead a new option, which one
> can turn on and off for different -f*-prefix-map= options if needed.
> 
> -fdebug-prefix-map=/path1=/mypath1 -fcanon-prefix-map \
> -fdebug-prefix-map=/path2=/mypath2 -fno-canon-prefix-map \
> -fdebug-prefix-map=/path3=/mypath3
> 
> will use the old behavior for the /path1 and /path3 handling and
> the new one only for /path2 handling.
> 
> Thoughts on this?
> 
> 	Jakub

> 2023-01-20  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR other/108464
> 	* file-prefix-map.cc (remap_filename): Revert 2022-11-01 and 2022-11-07
> 	changes.
> 
> --- gcc/file-prefix-map.cc
> +++ gcc/file-prefix-map.cc
> @@ -70,29 +70,19 @@ remap_filename (file_prefix_map *maps, const char *filename)
>    file_prefix_map *map;
>    char *s;
>    const char *name;
> -  char *realname;
>    size_t name_len;
>  
> -  if (!filename || lbasename (filename) == filename)
> -    return filename;
> -
> -  realname = lrealpath (filename);
> -
>    for (map = maps; map; map = map->next)
> -    if (filename_ncmp (realname, map->old_prefix, map->old_len) == 0)
> +    if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
>        break;
>    if (!map)
> -    {
> -      free (realname);
> -      return filename;
> -    }
> -  name = realname + map->old_len;
> +    return filename;
> +  name = filename + map->old_len;
>    name_len = strlen (name) + 1;
>  
>    s = (char *) ggc_alloc_atomic (name_len + map->new_len);
>    memcpy (s, map->new_prefix, map->new_len);
>    memcpy (s + map->new_len, name, name_len);
> -  free (realname);
>    return s;
>  }
>  

> 2023-01-20  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR other/108464
> 	* common.opt (fcanon-prefix-map): New option.
> 	* opts.cc: Include file-prefix-map.h.
> 	(flag_canon_prefix_map): New variable.
> 	(common_handle_option): Handle OPT_fcanon_prefix_map.
> 	(gen_command_line_string): Ignore OPT_fcanon_prefix_map.
> 	* file-prefix-map.h (flag_canon_prefix_map): Declare.
> 	* file-prefix-map.cc (struct file_prefix_map): Add canonicalize
> 	member.
> 	(add_prefix_map): Initialize canonicalize member from
> 	flag_canon_prefix_map, and if true and old_prefix is absolute
> 	pathname, canonicalize it using lrealpath.
> 	(remap_filename): Revert 2022-11-01 and 2022-11-07 changes,
> 	use lrealpath result only for absolute filenames and only for
> 	map->canonicalize map entries.
> 	* lto-opts.cc (lto_write_options): Ignore OPT_fcanon_prefix_map.
> 	* opts-global.cc (handle_common_deferred_options): Clear
> 	flag_canon_prefix_map at the start and handle OPT_fcanon_prefix_map.
> 	* doc/invoke.texi (-fcanon-prefix-map): Document.
> 	(-ffile-prefix-map, -fdebug-prefix-map, -fprofile-prefix-map): Add
> 	see also for -fcanon-prefix-map.
> 	* doc/cppopts.texi (-fmacro-prefix-map): Likewise.
> 
> --- gcc/common.opt.jj	2023-01-09 13:18:28.298019442 +0100
> +++ gcc/common.opt	2023-01-20 12:43:17.152178057 +0100
> @@ -1204,6 +1204,10 @@ fchecking=
>  Common Joined RejectNegative UInteger Var(flag_checking)
>  Perform internal consistency checkings.
>  
> +fcanon-prefix-map
> +Common Var(common_deferred_options) Defer
> +For -f*-prefix-map= options compare canonicalized pathnames rather than just strings.
> +
>  fcode-hoisting
>  Common Var(flag_code_hoisting) Optimization
>  Enable code hoisting.
> --- gcc/opts.cc.jj	2023-01-02 09:32:52.073856323 +0100
> +++ gcc/opts.cc	2023-01-20 13:54:53.526705571 +0100
> @@ -34,10 +34,14 @@ along with GCC; see the file COPYING3.
>  #include "diagnostic-color.h"
>  #include "version.h"
>  #include "selftest.h"
> +#include "file-prefix-map.h"
>  
>  /* In this file all option sets are explicit.  */
>  #undef OPTION_SET_P
>  
> +/* Set by -fcanon-prefix-map.  */
> +bool flag_canon_prefix_map;
> +
>  static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff);
>  
>  /* Names of fundamental debug info formats indexed by enum
> @@ -2812,6 +2816,10 @@ common_handle_option (struct gcc_options
>        /* Deferred.  */
>        break;
>  
> +    case OPT_fcanon_prefix_map:
> +      flag_canon_prefix_map = value;
> +      break;
> +
>      case OPT_fcallgraph_info:
>        opts->x_flag_callgraph_info = CALLGRAPH_INFO_NAKED;
>        break;
> @@ -3718,6 +3726,7 @@ gen_command_line_string (cl_decoded_opti
>        case OPT_fmacro_prefix_map_:
>        case OPT_ffile_prefix_map_:
>        case OPT_fprofile_prefix_map_:
> +      case OPT_fcanon_prefix_map:
>        case OPT_fcompare_debug:
>        case OPT_fchecking:
>        case OPT_fchecking_:
> --- gcc/file-prefix-map.h.jj	2023-01-02 09:32:33.258128185 +0100
> +++ gcc/file-prefix-map.h	2023-01-20 12:44:31.542094469 +0100
> @@ -22,6 +22,7 @@ void add_macro_prefix_map (const char *)
>  void add_debug_prefix_map (const char *);
>  void add_file_prefix_map (const char *);
>  void add_profile_prefix_map (const char *);
> +extern bool flag_canon_prefix_map;
>  
>  const char *remap_macro_filename (const char *);
>  const char *remap_debug_filename (const char *);
> --- gcc/file-prefix-map.cc.jj	2023-01-02 09:32:52.787846007 +0100
> +++ gcc/file-prefix-map.cc	2023-01-20 13:53:31.568896433 +0100
> @@ -30,6 +30,7 @@ struct file_prefix_map
>    const char *new_prefix;
>    size_t old_len;
>    size_t new_len;
> +  bool canonicalize;
>    struct file_prefix_map *next;
>  };
>  
> @@ -51,8 +52,16 @@ add_prefix_map (file_prefix_map *&maps,
>        return;
>      }
>    map = XNEW (file_prefix_map);
> +  map->canonicalize = flag_canon_prefix_map;
>    map->old_prefix = xstrndup (arg, p - arg);
>    map->old_len = p - arg;
> +  if (map->canonicalize && IS_ABSOLUTE_PATH (map->old_prefix))
> +    {
> +      char *realname = lrealpath (map->old_prefix);
> +      free (const_cast <char *> (map->old_prefix));
> +      map->old_prefix = realname;
> +      map->old_len = strlen (realname);
> +    }
>    p++;
>    map->new_prefix = xstrdup (p);
>    map->new_len = strlen (p);
> @@ -70,23 +79,32 @@ remap_filename (file_prefix_map *maps, c
>    file_prefix_map *map;
>    char *s;
>    const char *name;
> -  char *realname;
> +  char *realname = NULL;
>    size_t name_len;
>  
> -  if (!filename || lbasename (filename) == filename)
> +  if (!filename)
>      return filename;
>  
> -  realname = lrealpath (filename);
> -
> +  bool absolute = IS_ABSOLUTE_PATH (filename);
>    for (map = maps; map; map = map->next)
> -    if (filename_ncmp (realname, map->old_prefix, map->old_len) == 0)
> +    if (map->canonicalize && absolute)
> +      {
> +	if (realname == NULL)
> +	  realname = lrealpath (filename);
> +	if (filename_ncmp (realname, map->old_prefix, map->old_len) == 0)
> +	  break;
> +      }
> +    else if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
>        break;
>    if (!map)
>      {
>        free (realname);
>        return filename;
>      }
> -  name = realname + map->old_len;
> +  if (map->canonicalize && absolute)
> +    name = realname + map->old_len;
> +  else
> +    name = filename + map->old_len;
>    name_len = strlen (name) + 1;
>  
>    s = (char *) ggc_alloc_atomic (name_len + map->new_len);
> @@ -97,7 +115,7 @@ remap_filename (file_prefix_map *maps, c
>  }
>  
>  /* NOTE: if adding another -f*-prefix-map option then don't forget to
> -   ignore it in DW_AT_producer (dwarf2out.cc).  */
> +   ignore it in DW_AT_producer (gen_command_line_string in opts.cc).  */
>  
>  /* Linked lists of file_prefix_map structures.  */
>  static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map  */
> --- gcc/lto-opts.cc.jj	2023-01-02 09:32:29.547181803 +0100
> +++ gcc/lto-opts.cc	2023-01-20 13:55:35.010102584 +0100
> @@ -150,6 +150,7 @@ lto_write_options (void)
>  	case OPT_ffile_prefix_map_:
>  	case OPT_fmacro_prefix_map_:
>  	case OPT_fprofile_prefix_map_:
> +	case OPT_fcanon_prefix_map:
>  	case OPT_fwhole_program:
>  	  continue;
>  
> --- gcc/opts-global.cc.jj	2023-01-02 09:32:35.169100574 +0100
> +++ gcc/opts-global.cc	2023-01-20 13:38:31.174977423 +0100
> @@ -364,6 +364,7 @@ handle_common_deferred_options (void)
>    if (flag_opt_info)
>      opt_info_switch_p (NULL);
>  
> +  flag_canon_prefix_map = false;
>    FOR_EACH_VEC_ELT (v, i, opt)
>      {
>        switch (opt->opt_index)
> @@ -392,6 +393,10 @@ handle_common_deferred_options (void)
>  	  add_profile_prefix_map (opt->arg);
>  	  break;
>  
> +	case OPT_fcanon_prefix_map:
> +	  flag_canon_prefix_map = opt->value;
> +	  break;
> +
>  	case OPT_fdump_:
>  	  g->get_dumps ()->dump_switch_p (opt->arg);
>  	  break;
> --- gcc/doc/invoke.texi.jj	2023-01-16 11:52:16.115733593 +0100
> +++ gcc/doc/invoke.texi	2023-01-20 14:44:47.514203801 +0100
> @@ -191,7 +191,7 @@ in the following sections.
>  -dumpdir @var{dumppfx}  -x @var{language}  @gol
>  -v  -###  --help@r{[}=@var{class}@r{[},@dots{}@r{]]}  --target-help  --version @gol
>  -pass-exit-codes  -pipe  -specs=@var{file}  -wrapper  @gol
> -@@@var{file}  -ffile-prefix-map=@var{old}=@var{new}  @gol
> +@@@var{file}  -ffile-prefix-map=@var{old}=@var{new}  -fcanon-prefix-map  @gol
>  -fplugin=@var{file}  -fplugin-arg-@var{name}=@var{arg}  @gol
>  -fdump-ada-spec@r{[}-slim@r{]}  -fada-spec-parent=@var{unit}  -fdump-go-spec=@var{file}}
>  
> @@ -2203,9 +2203,20 @@ files resided in directory @file{@var{ne
>  option is equivalent to specifying all the individual
>  @option{-f*-prefix-map} options.  This can be used to make reproducible
>  builds that are location independent.  Directories referenced by
> -directives are not affected by these options. See also
> -@option{-fmacro-prefix-map}, @option{-fdebug-prefix-map} and
> -@option{-fprofile-prefix-map}.
> +directives are not affected by these options.  See also
> +@option{-fmacro-prefix-map}, @option{-fdebug-prefix-map},
> +@option{-fprofile-prefix-map} and @option{-fcanon-prefix-map}.
> +
> +@item -fcanon-prefix-map
> +@opindex fcanon-prefix-map
> +For the @option{-f*-prefix-map} options normally comparison
> +of @file{@var{old}} prefix against the filename that would be normally
> +referenced in the result of the compilation is done using textual
> +comparison of the prefixes, or ignoring character case for case insensitive
> +filesystems and considering slashes and backslashes as equal on DOS based
> +filesystems.  The @option{-fcanon-prefix-map} causes such comparisons
> +to be done for absolute pathnames on canonicalized paths of @file{@var{old}}
> +and the referenced filename.
>  
>  @item -fplugin=@var{name}.so
>  @opindex fplugin
> @@ -11289,7 +11300,8 @@ build-time path with an install-time pat
>  also be used to change an absolute path to a relative path by using
>  @file{.} for @var{new}.  This can give more reproducible builds, which
>  are location independent, but may require an extra command to tell GDB
> -where to find the source files. See also @option{-ffile-prefix-map}.
> +where to find the source files. See also @option{-ffile-prefix-map}
> +and @option{-fcanon-prefix-map}.
>  
>  @item -fvar-tracking
>  @opindex fvar-tracking
> @@ -16466,7 +16478,7 @@ When compiling files residing in directo
>  profiling information (with @option{--coverage})
>  describing them as if the files resided in
>  directory @file{@var{new}} instead.
> -See also @option{-ffile-prefix-map}.
> +See also @option{-ffile-prefix-map} and @option{-fcanon-prefix-map}.
>  
>  @item -fprofile-update=@var{method}
>  @opindex fprofile-update
> --- gcc/doc/cppopts.texi.jj	2023-01-16 11:52:16.102733784 +0100
> +++ gcc/doc/cppopts.texi	2023-01-20 14:45:09.106890233 +0100
> @@ -305,7 +305,7 @@ to change an absolute path to a relative
>  @var{new} which can result in more reproducible builds that are
>  location independent.  This option also affects
>  @code{__builtin_FILE()} during compilation.  See also
> -@option{-ffile-prefix-map}.
> +@option{-ffile-prefix-map} and @option{-fcanon-prefix-map}.
>  
>  @item -fexec-charset=@var{charset}
>  @opindex fexec-charset

> 2023-01-20  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR other/108464
> 	* common.opt (fcanon-prefix-map): New option.
> 	* opts.cc: Include file-prefix-map.h.
> 	(flag_canon_prefix_map): New variable.
> 	(common_handle_option): Handle OPT_fcanon_prefix_map.
> 	(gen_command_line_string): Ignore OPT_fcanon_prefix_map.
> 	* file-prefix-map.h (flag_canon_prefix_map): Declare.
> 	* file-prefix-map.cc (struct file_prefix_map): Add canonicalize
> 	member.
> 	(add_prefix_map): Initialize canonicalize member from
> 	flag_canon_prefix_map, and if true canonicalize it using lrealpath.
> 	(remap_filename): Revert 2022-11-01 and 2022-11-07 changes,
> 	use lrealpath result only for map->canonicalize map entries.
> 	* lto-opts.cc (lto_write_options): Ignore OPT_fcanon_prefix_map.
> 	* opts-global.cc (handle_common_deferred_options): Clear
> 	flag_canon_prefix_map at the start and handle OPT_fcanon_prefix_map.
> 	* doc/invoke.texi (-fcanon-prefix-map): Document.
> 	(-ffile-prefix-map, -fdebug-prefix-map, -fprofile-prefix-map): Add
> 	see also for -fcanon-prefix-map.
> 	* doc/cppopts.texi (-fmacro-prefix-map): Likewise.
> 
> --- gcc/common.opt.jj	2023-01-09 13:18:28.298019442 +0100
> +++ gcc/common.opt	2023-01-20 12:43:17.152178057 +0100
> @@ -1204,6 +1204,10 @@ fchecking=
>  Common Joined RejectNegative UInteger Var(flag_checking)
>  Perform internal consistency checkings.
>  
> +fcanon-prefix-map
> +Common Var(common_deferred_options) Defer
> +For -f*-prefix-map= options compare canonicalized pathnames rather than just strings.
> +
>  fcode-hoisting
>  Common Var(flag_code_hoisting) Optimization
>  Enable code hoisting.
> --- gcc/opts.cc.jj	2023-01-02 09:32:52.073856323 +0100
> +++ gcc/opts.cc	2023-01-20 13:54:53.526705571 +0100
> @@ -34,10 +34,14 @@ along with GCC; see the file COPYING3.
>  #include "diagnostic-color.h"
>  #include "version.h"
>  #include "selftest.h"
> +#include "file-prefix-map.h"
>  
>  /* In this file all option sets are explicit.  */
>  #undef OPTION_SET_P
>  
> +/* Set by -fcanon-prefix-map.  */
> +bool flag_canon_prefix_map;
> +
>  static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff);
>  
>  /* Names of fundamental debug info formats indexed by enum
> @@ -2812,6 +2816,10 @@ common_handle_option (struct gcc_options
>        /* Deferred.  */
>        break;
>  
> +    case OPT_fcanon_prefix_map:
> +      flag_canon_prefix_map = value;
> +      break;
> +
>      case OPT_fcallgraph_info:
>        opts->x_flag_callgraph_info = CALLGRAPH_INFO_NAKED;
>        break;
> @@ -3718,6 +3726,7 @@ gen_command_line_string (cl_decoded_opti
>        case OPT_fmacro_prefix_map_:
>        case OPT_ffile_prefix_map_:
>        case OPT_fprofile_prefix_map_:
> +      case OPT_fcanon_prefix_map:
>        case OPT_fcompare_debug:
>        case OPT_fchecking:
>        case OPT_fchecking_:
> --- gcc/file-prefix-map.h.jj	2023-01-02 09:32:33.258128185 +0100
> +++ gcc/file-prefix-map.h	2023-01-20 12:44:31.542094469 +0100
> @@ -22,6 +22,7 @@ void add_macro_prefix_map (const char *)
>  void add_debug_prefix_map (const char *);
>  void add_file_prefix_map (const char *);
>  void add_profile_prefix_map (const char *);
> +extern bool flag_canon_prefix_map;
>  
>  const char *remap_macro_filename (const char *);
>  const char *remap_debug_filename (const char *);
> --- gcc/file-prefix-map.cc.jj	2023-01-02 09:32:52.787846007 +0100
> +++ gcc/file-prefix-map.cc	2023-01-20 15:42:30.661088219 +0100
> @@ -30,6 +30,7 @@ struct file_prefix_map
>    const char *new_prefix;
>    size_t old_len;
>    size_t new_len;
> +  bool canonicalize;
>    struct file_prefix_map *next;
>  };
>  
> @@ -51,8 +52,16 @@ add_prefix_map (file_prefix_map *&maps,
>        return;
>      }
>    map = XNEW (file_prefix_map);
> +  map->canonicalize = flag_canon_prefix_map;
>    map->old_prefix = xstrndup (arg, p - arg);
>    map->old_len = p - arg;
> +  if (map->canonicalize)
> +    {
> +      char *realname = lrealpath (map->old_prefix);
> +      free (const_cast <char *> (map->old_prefix));
> +      map->old_prefix = realname;
> +      map->old_len = strlen (realname);
> +    }
>    p++;
>    map->new_prefix = xstrdup (p);
>    map->new_len = strlen (p);
> @@ -70,34 +79,49 @@ remap_filename (file_prefix_map *maps, c
>    file_prefix_map *map;
>    char *s;
>    const char *name;
> -  char *realname;
> +  const char *realname = NULL;
>    size_t name_len;
>  
> -  if (!filename || lbasename (filename) == filename)
> +  if (!filename)
>      return filename;
>  
> -  realname = lrealpath (filename);
> -
>    for (map = maps; map; map = map->next)
> -    if (filename_ncmp (realname, map->old_prefix, map->old_len) == 0)
> +    if (map->canonicalize)
> +      {
> +	if (realname == NULL)
> +	  {
> +	    if (lbasename (filename) == filename)
> +	      realname = filename;
> +	    else
> +	      realname = lrealpath (filename);
> +	  }
> +	if (filename_ncmp (realname, map->old_prefix, map->old_len) == 0)
> +	  break;
> +      }
> +    else if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
>        break;
>    if (!map)
>      {
> -      free (realname);
> +      if (realname != filename)
> +	free (const_cast <char *> (realname));
>        return filename;
>      }
> -  name = realname + map->old_len;
> +  if (map->canonicalize)
> +    name = realname + map->old_len;
> +  else
> +    name = filename + map->old_len;
>    name_len = strlen (name) + 1;
>  
>    s = (char *) ggc_alloc_atomic (name_len + map->new_len);
>    memcpy (s, map->new_prefix, map->new_len);
>    memcpy (s + map->new_len, name, name_len);
> -  free (realname);
> +  if (realname != filename)
> +    free (const_cast <char *> (realname));
>    return s;
>  }
>  
>  /* NOTE: if adding another -f*-prefix-map option then don't forget to
> -   ignore it in DW_AT_producer (dwarf2out.cc).  */
> +   ignore it in DW_AT_producer (gen_command_line_string in opts.cc).  */
>  
>  /* Linked lists of file_prefix_map structures.  */
>  static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map  */
> --- gcc/lto-opts.cc.jj	2023-01-02 09:32:29.547181803 +0100
> +++ gcc/lto-opts.cc	2023-01-20 13:55:35.010102584 +0100
> @@ -150,6 +150,7 @@ lto_write_options (void)
>  	case OPT_ffile_prefix_map_:
>  	case OPT_fmacro_prefix_map_:
>  	case OPT_fprofile_prefix_map_:
> +	case OPT_fcanon_prefix_map:
>  	case OPT_fwhole_program:
>  	  continue;
>  
> --- gcc/opts-global.cc.jj	2023-01-02 09:32:35.169100574 +0100
> +++ gcc/opts-global.cc	2023-01-20 13:38:31.174977423 +0100
> @@ -364,6 +364,7 @@ handle_common_deferred_options (void)
>    if (flag_opt_info)
>      opt_info_switch_p (NULL);
>  
> +  flag_canon_prefix_map = false;
>    FOR_EACH_VEC_ELT (v, i, opt)
>      {
>        switch (opt->opt_index)
> @@ -392,6 +393,10 @@ handle_common_deferred_options (void)
>  	  add_profile_prefix_map (opt->arg);
>  	  break;
>  
> +	case OPT_fcanon_prefix_map:
> +	  flag_canon_prefix_map = opt->value;
> +	  break;
> +
>  	case OPT_fdump_:
>  	  g->get_dumps ()->dump_switch_p (opt->arg);
>  	  break;
> --- gcc/doc/invoke.texi.jj	2023-01-16 11:52:16.115733593 +0100
> +++ gcc/doc/invoke.texi	2023-01-20 14:44:47.514203801 +0100
> @@ -191,7 +191,7 @@ in the following sections.
>  -dumpdir @var{dumppfx}  -x @var{language}  @gol
>  -v  -###  --help@r{[}=@var{class}@r{[},@dots{}@r{]]}  --target-help  --version @gol
>  -pass-exit-codes  -pipe  -specs=@var{file}  -wrapper  @gol
> -@@@var{file}  -ffile-prefix-map=@var{old}=@var{new}  @gol
> +@@@var{file}  -ffile-prefix-map=@var{old}=@var{new}  -fcanon-prefix-map  @gol
>  -fplugin=@var{file}  -fplugin-arg-@var{name}=@var{arg}  @gol
>  -fdump-ada-spec@r{[}-slim@r{]}  -fada-spec-parent=@var{unit}  -fdump-go-spec=@var{file}}
>  
> @@ -2203,9 +2203,20 @@ files resided in directory @file{@var{ne
>  option is equivalent to specifying all the individual
>  @option{-f*-prefix-map} options.  This can be used to make reproducible
>  builds that are location independent.  Directories referenced by
> -directives are not affected by these options. See also
> -@option{-fmacro-prefix-map}, @option{-fdebug-prefix-map} and
> -@option{-fprofile-prefix-map}.
> +directives are not affected by these options.  See also
> +@option{-fmacro-prefix-map}, @option{-fdebug-prefix-map},
> +@option{-fprofile-prefix-map} and @option{-fcanon-prefix-map}.
> +
> +@item -fcanon-prefix-map
> +@opindex fcanon-prefix-map
> +For the @option{-f*-prefix-map} options normally comparison
> +of @file{@var{old}} prefix against the filename that would be normally
> +referenced in the result of the compilation is done using textual
> +comparison of the prefixes, or ignoring character case for case insensitive
> +filesystems and considering slashes and backslashes as equal on DOS based
> +filesystems.  The @option{-fcanon-prefix-map} causes such comparisons
> +to be done on canonicalized paths of @file{@var{old}}
> +and the referenced filename.
>  
>  @item -fplugin=@var{name}.so
>  @opindex fplugin
> @@ -11289,7 +11300,8 @@ build-time path with an install-time pat
>  also be used to change an absolute path to a relative path by using
>  @file{.} for @var{new}.  This can give more reproducible builds, which
>  are location independent, but may require an extra command to tell GDB
> -where to find the source files. See also @option{-ffile-prefix-map}.
> +where to find the source files. See also @option{-ffile-prefix-map}
> +and @option{-fcanon-prefix-map}.
>  
>  @item -fvar-tracking
>  @opindex fvar-tracking
> @@ -16466,7 +16478,7 @@ When compiling files residing in directo
>  profiling information (with @option{--coverage})
>  describing them as if the files resided in
>  directory @file{@var{new}} instead.
> -See also @option{-ffile-prefix-map}.
> +See also @option{-ffile-prefix-map} and @option{-fcanon-prefix-map}.
>  
>  @item -fprofile-update=@var{method}
>  @opindex fprofile-update
> --- gcc/doc/cppopts.texi.jj	2023-01-16 11:52:16.102733784 +0100
> +++ gcc/doc/cppopts.texi	2023-01-20 14:45:09.106890233 +0100
> @@ -305,7 +305,7 @@ to change an absolute path to a relative
>  @var{new} which can result in more reproducible builds that are
>  location independent.  This option also affects
>  @code{__builtin_FILE()} during compilation.  See also
> -@option{-ffile-prefix-map}.
> +@option{-ffile-prefix-map} and @option{-fcanon-prefix-map}.
>  
>  @item -fexec-charset=@var{charset}
>  @opindex fexec-charset
  
Richard Biener March 10, 2023, 9:05 a.m. UTC | #3
On Fri, 10 Mar 2023, Jakub Jelinek wrote:

> Hi!
> 
> I'd like to ping these patches.  All 3 variants have been
> bootstrapped/regtested on x86_64-linux and i686-linux, the last
> one is my preference I guess.  The current state breaks e.g. ccache.
> 
> https://gcc.gnu.org/pipermail/gcc-patches/2023-January/610285.html
>   - PR108464 - P1 - file-prefix-map: Fix up -f*-prefix-map= (3 variants)

Let's go with your preference - I was hoping on comments from Richard 
Purdie as of his preference but then ..

Thanks,
Richard.

> Thanks
> 	Jakub
> 
> On Fri, Jan 20, 2023 at 04:05:55PM +0100, Jakub Jelinek via Gcc-patches wrote:
> > On Tue, Nov 01, 2022 at 01:46:20PM -0600, Jeff Law via Gcc-patches wrote:
> > > > This does cause a change of behaviour if users were previously relying upon
> > > > symlinks or absolute paths not being resolved.
> > > 
> > > I'm not too worried about this scenario.
> > 
> > As mentioned in the PR, this patch breaks e.g. ccache testsuite.
> > 
> > I strongly doubt most of the users want such a behavior, because it
> > makes all filenames absolute when -f*-prefix-map= options remap one
> > absolute path to another one.
> > Say if I'm in /tmp and /tmp is the canonical path and there is
> > src/test.c file, with -fdebug-prefix-map=/tmp=/blah
> > previously there would be DW_AT_comp_dir "/blah" and it is still there,
> > but DW_AT_name which was previouly "src/test.c" (relative against
> > DW_AT_comp_dir) is now "/blah/src/test.c" instead.
> > 
> > Even worse, the canonicalization is only done on the remap_filename
> > argument, but not on the old_prefix side.  That is e.g. what breaks
> > ccache.  If there is
> > /tmp/foobar1 directory and
> > ln -sf foobar1 /tmp/foobar2
> > cd /tmp/foobar2
> > then -fdebug-prefix-map=`pwd`:/blah will just not work, while
> > src/test.c will be canonicalized to /tmp/foobar1/src/test.c,
> > old_prefix is still what the user provided which is /tmp/foobar2.
> > User would need to change their uses to use -fdebug-prefix-map=`realpath $(pwd)`=/blah
> > 
> > I'm attaching 3 so far just compile tested patches.
> > 
> > The first patch just reverts the patch (and its follow-up patch).
> > 
> > The second introduces a new option, -f{,no}-canon-prefix-map which affects
> > the behavior of -f{file,macro,debug,profile}-prefix-map=, if on it
> > canonicalizes the old path of the prefix map option and compares that
> > against the canonicalized filename for absolute paths but not relative.
> > 
> > And last is like the second, but does that also for relative paths except
> > for filenames with no / (or / or \ on DOS based fs).  So, the third patch
> > gets an optional behavior of what has been on the trunk lately with the
> > difference that the old_prefix is canonicalized by the compiler.
> > 
> > Initially I've thought I'd just add some magic syntax to the OLD=NEW
> > argument of those options (because there are 4 of them), but as noted
> > in the comments, = is valid char in OLD (just not new), so it would
> > be hard to figure out some syntax.  So instead a new option, which one
> > can turn on and off for different -f*-prefix-map= options if needed.
> > 
> > -fdebug-prefix-map=/path1=/mypath1 -fcanon-prefix-map \
> > -fdebug-prefix-map=/path2=/mypath2 -fno-canon-prefix-map \
> > -fdebug-prefix-map=/path3=/mypath3
> > 
> > will use the old behavior for the /path1 and /path3 handling and
> > the new one only for /path2 handling.
> > 
> > Thoughts on this?
> > 
> > 	Jakub
> 
> > 2023-01-20  Jakub Jelinek  <jakub@redhat.com>
> > 
> > 	PR other/108464
> > 	* file-prefix-map.cc (remap_filename): Revert 2022-11-01 and 2022-11-07
> > 	changes.
> > 
> > --- gcc/file-prefix-map.cc
> > +++ gcc/file-prefix-map.cc
> > @@ -70,29 +70,19 @@ remap_filename (file_prefix_map *maps, const char *filename)
> >    file_prefix_map *map;
> >    char *s;
> >    const char *name;
> > -  char *realname;
> >    size_t name_len;
> >  
> > -  if (!filename || lbasename (filename) == filename)
> > -    return filename;
> > -
> > -  realname = lrealpath (filename);
> > -
> >    for (map = maps; map; map = map->next)
> > -    if (filename_ncmp (realname, map->old_prefix, map->old_len) == 0)
> > +    if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
> >        break;
> >    if (!map)
> > -    {
> > -      free (realname);
> > -      return filename;
> > -    }
> > -  name = realname + map->old_len;
> > +    return filename;
> > +  name = filename + map->old_len;
> >    name_len = strlen (name) + 1;
> >  
> >    s = (char *) ggc_alloc_atomic (name_len + map->new_len);
> >    memcpy (s, map->new_prefix, map->new_len);
> >    memcpy (s + map->new_len, name, name_len);
> > -  free (realname);
> >    return s;
> >  }
> >  
> 
> > 2023-01-20  Jakub Jelinek  <jakub@redhat.com>
> > 
> > 	PR other/108464
> > 	* common.opt (fcanon-prefix-map): New option.
> > 	* opts.cc: Include file-prefix-map.h.
> > 	(flag_canon_prefix_map): New variable.
> > 	(common_handle_option): Handle OPT_fcanon_prefix_map.
> > 	(gen_command_line_string): Ignore OPT_fcanon_prefix_map.
> > 	* file-prefix-map.h (flag_canon_prefix_map): Declare.
> > 	* file-prefix-map.cc (struct file_prefix_map): Add canonicalize
> > 	member.
> > 	(add_prefix_map): Initialize canonicalize member from
> > 	flag_canon_prefix_map, and if true and old_prefix is absolute
> > 	pathname, canonicalize it using lrealpath.
> > 	(remap_filename): Revert 2022-11-01 and 2022-11-07 changes,
> > 	use lrealpath result only for absolute filenames and only for
> > 	map->canonicalize map entries.
> > 	* lto-opts.cc (lto_write_options): Ignore OPT_fcanon_prefix_map.
> > 	* opts-global.cc (handle_common_deferred_options): Clear
> > 	flag_canon_prefix_map at the start and handle OPT_fcanon_prefix_map.
> > 	* doc/invoke.texi (-fcanon-prefix-map): Document.
> > 	(-ffile-prefix-map, -fdebug-prefix-map, -fprofile-prefix-map): Add
> > 	see also for -fcanon-prefix-map.
> > 	* doc/cppopts.texi (-fmacro-prefix-map): Likewise.
> > 
> > --- gcc/common.opt.jj	2023-01-09 13:18:28.298019442 +0100
> > +++ gcc/common.opt	2023-01-20 12:43:17.152178057 +0100
> > @@ -1204,6 +1204,10 @@ fchecking=
> >  Common Joined RejectNegative UInteger Var(flag_checking)
> >  Perform internal consistency checkings.
> >  
> > +fcanon-prefix-map
> > +Common Var(common_deferred_options) Defer
> > +For -f*-prefix-map= options compare canonicalized pathnames rather than just strings.
> > +
> >  fcode-hoisting
> >  Common Var(flag_code_hoisting) Optimization
> >  Enable code hoisting.
> > --- gcc/opts.cc.jj	2023-01-02 09:32:52.073856323 +0100
> > +++ gcc/opts.cc	2023-01-20 13:54:53.526705571 +0100
> > @@ -34,10 +34,14 @@ along with GCC; see the file COPYING3.
> >  #include "diagnostic-color.h"
> >  #include "version.h"
> >  #include "selftest.h"
> > +#include "file-prefix-map.h"
> >  
> >  /* In this file all option sets are explicit.  */
> >  #undef OPTION_SET_P
> >  
> > +/* Set by -fcanon-prefix-map.  */
> > +bool flag_canon_prefix_map;
> > +
> >  static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff);
> >  
> >  /* Names of fundamental debug info formats indexed by enum
> > @@ -2812,6 +2816,10 @@ common_handle_option (struct gcc_options
> >        /* Deferred.  */
> >        break;
> >  
> > +    case OPT_fcanon_prefix_map:
> > +      flag_canon_prefix_map = value;
> > +      break;
> > +
> >      case OPT_fcallgraph_info:
> >        opts->x_flag_callgraph_info = CALLGRAPH_INFO_NAKED;
> >        break;
> > @@ -3718,6 +3726,7 @@ gen_command_line_string (cl_decoded_opti
> >        case OPT_fmacro_prefix_map_:
> >        case OPT_ffile_prefix_map_:
> >        case OPT_fprofile_prefix_map_:
> > +      case OPT_fcanon_prefix_map:
> >        case OPT_fcompare_debug:
> >        case OPT_fchecking:
> >        case OPT_fchecking_:
> > --- gcc/file-prefix-map.h.jj	2023-01-02 09:32:33.258128185 +0100
> > +++ gcc/file-prefix-map.h	2023-01-20 12:44:31.542094469 +0100
> > @@ -22,6 +22,7 @@ void add_macro_prefix_map (const char *)
> >  void add_debug_prefix_map (const char *);
> >  void add_file_prefix_map (const char *);
> >  void add_profile_prefix_map (const char *);
> > +extern bool flag_canon_prefix_map;
> >  
> >  const char *remap_macro_filename (const char *);
> >  const char *remap_debug_filename (const char *);
> > --- gcc/file-prefix-map.cc.jj	2023-01-02 09:32:52.787846007 +0100
> > +++ gcc/file-prefix-map.cc	2023-01-20 13:53:31.568896433 +0100
> > @@ -30,6 +30,7 @@ struct file_prefix_map
> >    const char *new_prefix;
> >    size_t old_len;
> >    size_t new_len;
> > +  bool canonicalize;
> >    struct file_prefix_map *next;
> >  };
> >  
> > @@ -51,8 +52,16 @@ add_prefix_map (file_prefix_map *&maps,
> >        return;
> >      }
> >    map = XNEW (file_prefix_map);
> > +  map->canonicalize = flag_canon_prefix_map;
> >    map->old_prefix = xstrndup (arg, p - arg);
> >    map->old_len = p - arg;
> > +  if (map->canonicalize && IS_ABSOLUTE_PATH (map->old_prefix))
> > +    {
> > +      char *realname = lrealpath (map->old_prefix);
> > +      free (const_cast <char *> (map->old_prefix));
> > +      map->old_prefix = realname;
> > +      map->old_len = strlen (realname);
> > +    }
> >    p++;
> >    map->new_prefix = xstrdup (p);
> >    map->new_len = strlen (p);
> > @@ -70,23 +79,32 @@ remap_filename (file_prefix_map *maps, c
> >    file_prefix_map *map;
> >    char *s;
> >    const char *name;
> > -  char *realname;
> > +  char *realname = NULL;
> >    size_t name_len;
> >  
> > -  if (!filename || lbasename (filename) == filename)
> > +  if (!filename)
> >      return filename;
> >  
> > -  realname = lrealpath (filename);
> > -
> > +  bool absolute = IS_ABSOLUTE_PATH (filename);
> >    for (map = maps; map; map = map->next)
> > -    if (filename_ncmp (realname, map->old_prefix, map->old_len) == 0)
> > +    if (map->canonicalize && absolute)
> > +      {
> > +	if (realname == NULL)
> > +	  realname = lrealpath (filename);
> > +	if (filename_ncmp (realname, map->old_prefix, map->old_len) == 0)
> > +	  break;
> > +      }
> > +    else if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
> >        break;
> >    if (!map)
> >      {
> >        free (realname);
> >        return filename;
> >      }
> > -  name = realname + map->old_len;
> > +  if (map->canonicalize && absolute)
> > +    name = realname + map->old_len;
> > +  else
> > +    name = filename + map->old_len;
> >    name_len = strlen (name) + 1;
> >  
> >    s = (char *) ggc_alloc_atomic (name_len + map->new_len);
> > @@ -97,7 +115,7 @@ remap_filename (file_prefix_map *maps, c
> >  }
> >  
> >  /* NOTE: if adding another -f*-prefix-map option then don't forget to
> > -   ignore it in DW_AT_producer (dwarf2out.cc).  */
> > +   ignore it in DW_AT_producer (gen_command_line_string in opts.cc).  */
> >  
> >  /* Linked lists of file_prefix_map structures.  */
> >  static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map  */
> > --- gcc/lto-opts.cc.jj	2023-01-02 09:32:29.547181803 +0100
> > +++ gcc/lto-opts.cc	2023-01-20 13:55:35.010102584 +0100
> > @@ -150,6 +150,7 @@ lto_write_options (void)
> >  	case OPT_ffile_prefix_map_:
> >  	case OPT_fmacro_prefix_map_:
> >  	case OPT_fprofile_prefix_map_:
> > +	case OPT_fcanon_prefix_map:
> >  	case OPT_fwhole_program:
> >  	  continue;
> >  
> > --- gcc/opts-global.cc.jj	2023-01-02 09:32:35.169100574 +0100
> > +++ gcc/opts-global.cc	2023-01-20 13:38:31.174977423 +0100
> > @@ -364,6 +364,7 @@ handle_common_deferred_options (void)
> >    if (flag_opt_info)
> >      opt_info_switch_p (NULL);
> >  
> > +  flag_canon_prefix_map = false;
> >    FOR_EACH_VEC_ELT (v, i, opt)
> >      {
> >        switch (opt->opt_index)
> > @@ -392,6 +393,10 @@ handle_common_deferred_options (void)
> >  	  add_profile_prefix_map (opt->arg);
> >  	  break;
> >  
> > +	case OPT_fcanon_prefix_map:
> > +	  flag_canon_prefix_map = opt->value;
> > +	  break;
> > +
> >  	case OPT_fdump_:
> >  	  g->get_dumps ()->dump_switch_p (opt->arg);
> >  	  break;
> > --- gcc/doc/invoke.texi.jj	2023-01-16 11:52:16.115733593 +0100
> > +++ gcc/doc/invoke.texi	2023-01-20 14:44:47.514203801 +0100
> > @@ -191,7 +191,7 @@ in the following sections.
> >  -dumpdir @var{dumppfx}  -x @var{language}  @gol
> >  -v  -###  --help@r{[}=@var{class}@r{[},@dots{}@r{]]}  --target-help  --version @gol
> >  -pass-exit-codes  -pipe  -specs=@var{file}  -wrapper  @gol
> > -@@@var{file}  -ffile-prefix-map=@var{old}=@var{new}  @gol
> > +@@@var{file}  -ffile-prefix-map=@var{old}=@var{new}  -fcanon-prefix-map  @gol
> >  -fplugin=@var{file}  -fplugin-arg-@var{name}=@var{arg}  @gol
> >  -fdump-ada-spec@r{[}-slim@r{]}  -fada-spec-parent=@var{unit}  -fdump-go-spec=@var{file}}
> >  
> > @@ -2203,9 +2203,20 @@ files resided in directory @file{@var{ne
> >  option is equivalent to specifying all the individual
> >  @option{-f*-prefix-map} options.  This can be used to make reproducible
> >  builds that are location independent.  Directories referenced by
> > -directives are not affected by these options. See also
> > -@option{-fmacro-prefix-map}, @option{-fdebug-prefix-map} and
> > -@option{-fprofile-prefix-map}.
> > +directives are not affected by these options.  See also
> > +@option{-fmacro-prefix-map}, @option{-fdebug-prefix-map},
> > +@option{-fprofile-prefix-map} and @option{-fcanon-prefix-map}.
> > +
> > +@item -fcanon-prefix-map
> > +@opindex fcanon-prefix-map
> > +For the @option{-f*-prefix-map} options normally comparison
> > +of @file{@var{old}} prefix against the filename that would be normally
> > +referenced in the result of the compilation is done using textual
> > +comparison of the prefixes, or ignoring character case for case insensitive
> > +filesystems and considering slashes and backslashes as equal on DOS based
> > +filesystems.  The @option{-fcanon-prefix-map} causes such comparisons
> > +to be done for absolute pathnames on canonicalized paths of @file{@var{old}}
> > +and the referenced filename.
> >  
> >  @item -fplugin=@var{name}.so
> >  @opindex fplugin
> > @@ -11289,7 +11300,8 @@ build-time path with an install-time pat
> >  also be used to change an absolute path to a relative path by using
> >  @file{.} for @var{new}.  This can give more reproducible builds, which
> >  are location independent, but may require an extra command to tell GDB
> > -where to find the source files. See also @option{-ffile-prefix-map}.
> > +where to find the source files. See also @option{-ffile-prefix-map}
> > +and @option{-fcanon-prefix-map}.
> >  
> >  @item -fvar-tracking
> >  @opindex fvar-tracking
> > @@ -16466,7 +16478,7 @@ When compiling files residing in directo
> >  profiling information (with @option{--coverage})
> >  describing them as if the files resided in
> >  directory @file{@var{new}} instead.
> > -See also @option{-ffile-prefix-map}.
> > +See also @option{-ffile-prefix-map} and @option{-fcanon-prefix-map}.
> >  
> >  @item -fprofile-update=@var{method}
> >  @opindex fprofile-update
> > --- gcc/doc/cppopts.texi.jj	2023-01-16 11:52:16.102733784 +0100
> > +++ gcc/doc/cppopts.texi	2023-01-20 14:45:09.106890233 +0100
> > @@ -305,7 +305,7 @@ to change an absolute path to a relative
> >  @var{new} which can result in more reproducible builds that are
> >  location independent.  This option also affects
> >  @code{__builtin_FILE()} during compilation.  See also
> > -@option{-ffile-prefix-map}.
> > +@option{-ffile-prefix-map} and @option{-fcanon-prefix-map}.
> >  
> >  @item -fexec-charset=@var{charset}
> >  @opindex fexec-charset
> 
> > 2023-01-20  Jakub Jelinek  <jakub@redhat.com>
> > 
> > 	PR other/108464
> > 	* common.opt (fcanon-prefix-map): New option.
> > 	* opts.cc: Include file-prefix-map.h.
> > 	(flag_canon_prefix_map): New variable.
> > 	(common_handle_option): Handle OPT_fcanon_prefix_map.
> > 	(gen_command_line_string): Ignore OPT_fcanon_prefix_map.
> > 	* file-prefix-map.h (flag_canon_prefix_map): Declare.
> > 	* file-prefix-map.cc (struct file_prefix_map): Add canonicalize
> > 	member.
> > 	(add_prefix_map): Initialize canonicalize member from
> > 	flag_canon_prefix_map, and if true canonicalize it using lrealpath.
> > 	(remap_filename): Revert 2022-11-01 and 2022-11-07 changes,
> > 	use lrealpath result only for map->canonicalize map entries.
> > 	* lto-opts.cc (lto_write_options): Ignore OPT_fcanon_prefix_map.
> > 	* opts-global.cc (handle_common_deferred_options): Clear
> > 	flag_canon_prefix_map at the start and handle OPT_fcanon_prefix_map.
> > 	* doc/invoke.texi (-fcanon-prefix-map): Document.
> > 	(-ffile-prefix-map, -fdebug-prefix-map, -fprofile-prefix-map): Add
> > 	see also for -fcanon-prefix-map.
> > 	* doc/cppopts.texi (-fmacro-prefix-map): Likewise.
> > 
> > --- gcc/common.opt.jj	2023-01-09 13:18:28.298019442 +0100
> > +++ gcc/common.opt	2023-01-20 12:43:17.152178057 +0100
> > @@ -1204,6 +1204,10 @@ fchecking=
> >  Common Joined RejectNegative UInteger Var(flag_checking)
> >  Perform internal consistency checkings.
> >  
> > +fcanon-prefix-map
> > +Common Var(common_deferred_options) Defer
> > +For -f*-prefix-map= options compare canonicalized pathnames rather than just strings.
> > +
> >  fcode-hoisting
> >  Common Var(flag_code_hoisting) Optimization
> >  Enable code hoisting.
> > --- gcc/opts.cc.jj	2023-01-02 09:32:52.073856323 +0100
> > +++ gcc/opts.cc	2023-01-20 13:54:53.526705571 +0100
> > @@ -34,10 +34,14 @@ along with GCC; see the file COPYING3.
> >  #include "diagnostic-color.h"
> >  #include "version.h"
> >  #include "selftest.h"
> > +#include "file-prefix-map.h"
> >  
> >  /* In this file all option sets are explicit.  */
> >  #undef OPTION_SET_P
> >  
> > +/* Set by -fcanon-prefix-map.  */
> > +bool flag_canon_prefix_map;
> > +
> >  static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff);
> >  
> >  /* Names of fundamental debug info formats indexed by enum
> > @@ -2812,6 +2816,10 @@ common_handle_option (struct gcc_options
> >        /* Deferred.  */
> >        break;
> >  
> > +    case OPT_fcanon_prefix_map:
> > +      flag_canon_prefix_map = value;
> > +      break;
> > +
> >      case OPT_fcallgraph_info:
> >        opts->x_flag_callgraph_info = CALLGRAPH_INFO_NAKED;
> >        break;
> > @@ -3718,6 +3726,7 @@ gen_command_line_string (cl_decoded_opti
> >        case OPT_fmacro_prefix_map_:
> >        case OPT_ffile_prefix_map_:
> >        case OPT_fprofile_prefix_map_:
> > +      case OPT_fcanon_prefix_map:
> >        case OPT_fcompare_debug:
> >        case OPT_fchecking:
> >        case OPT_fchecking_:
> > --- gcc/file-prefix-map.h.jj	2023-01-02 09:32:33.258128185 +0100
> > +++ gcc/file-prefix-map.h	2023-01-20 12:44:31.542094469 +0100
> > @@ -22,6 +22,7 @@ void add_macro_prefix_map (const char *)
> >  void add_debug_prefix_map (const char *);
> >  void add_file_prefix_map (const char *);
> >  void add_profile_prefix_map (const char *);
> > +extern bool flag_canon_prefix_map;
> >  
> >  const char *remap_macro_filename (const char *);
> >  const char *remap_debug_filename (const char *);
> > --- gcc/file-prefix-map.cc.jj	2023-01-02 09:32:52.787846007 +0100
> > +++ gcc/file-prefix-map.cc	2023-01-20 15:42:30.661088219 +0100
> > @@ -30,6 +30,7 @@ struct file_prefix_map
> >    const char *new_prefix;
> >    size_t old_len;
> >    size_t new_len;
> > +  bool canonicalize;
> >    struct file_prefix_map *next;
> >  };
> >  
> > @@ -51,8 +52,16 @@ add_prefix_map (file_prefix_map *&maps,
> >        return;
> >      }
> >    map = XNEW (file_prefix_map);
> > +  map->canonicalize = flag_canon_prefix_map;
> >    map->old_prefix = xstrndup (arg, p - arg);
> >    map->old_len = p - arg;
> > +  if (map->canonicalize)
> > +    {
> > +      char *realname = lrealpath (map->old_prefix);
> > +      free (const_cast <char *> (map->old_prefix));
> > +      map->old_prefix = realname;
> > +      map->old_len = strlen (realname);
> > +    }
> >    p++;
> >    map->new_prefix = xstrdup (p);
> >    map->new_len = strlen (p);
> > @@ -70,34 +79,49 @@ remap_filename (file_prefix_map *maps, c
> >    file_prefix_map *map;
> >    char *s;
> >    const char *name;
> > -  char *realname;
> > +  const char *realname = NULL;
> >    size_t name_len;
> >  
> > -  if (!filename || lbasename (filename) == filename)
> > +  if (!filename)
> >      return filename;
> >  
> > -  realname = lrealpath (filename);
> > -
> >    for (map = maps; map; map = map->next)
> > -    if (filename_ncmp (realname, map->old_prefix, map->old_len) == 0)
> > +    if (map->canonicalize)
> > +      {
> > +	if (realname == NULL)
> > +	  {
> > +	    if (lbasename (filename) == filename)
> > +	      realname = filename;
> > +	    else
> > +	      realname = lrealpath (filename);
> > +	  }
> > +	if (filename_ncmp (realname, map->old_prefix, map->old_len) == 0)
> > +	  break;
> > +      }
> > +    else if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
> >        break;
> >    if (!map)
> >      {
> > -      free (realname);
> > +      if (realname != filename)
> > +	free (const_cast <char *> (realname));
> >        return filename;
> >      }
> > -  name = realname + map->old_len;
> > +  if (map->canonicalize)
> > +    name = realname + map->old_len;
> > +  else
> > +    name = filename + map->old_len;
> >    name_len = strlen (name) + 1;
> >  
> >    s = (char *) ggc_alloc_atomic (name_len + map->new_len);
> >    memcpy (s, map->new_prefix, map->new_len);
> >    memcpy (s + map->new_len, name, name_len);
> > -  free (realname);
> > +  if (realname != filename)
> > +    free (const_cast <char *> (realname));
> >    return s;
> >  }
> >  
> >  /* NOTE: if adding another -f*-prefix-map option then don't forget to
> > -   ignore it in DW_AT_producer (dwarf2out.cc).  */
> > +   ignore it in DW_AT_producer (gen_command_line_string in opts.cc).  */
> >  
> >  /* Linked lists of file_prefix_map structures.  */
> >  static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map  */
> > --- gcc/lto-opts.cc.jj	2023-01-02 09:32:29.547181803 +0100
> > +++ gcc/lto-opts.cc	2023-01-20 13:55:35.010102584 +0100
> > @@ -150,6 +150,7 @@ lto_write_options (void)
> >  	case OPT_ffile_prefix_map_:
> >  	case OPT_fmacro_prefix_map_:
> >  	case OPT_fprofile_prefix_map_:
> > +	case OPT_fcanon_prefix_map:
> >  	case OPT_fwhole_program:
> >  	  continue;
> >  
> > --- gcc/opts-global.cc.jj	2023-01-02 09:32:35.169100574 +0100
> > +++ gcc/opts-global.cc	2023-01-20 13:38:31.174977423 +0100
> > @@ -364,6 +364,7 @@ handle_common_deferred_options (void)
> >    if (flag_opt_info)
> >      opt_info_switch_p (NULL);
> >  
> > +  flag_canon_prefix_map = false;
> >    FOR_EACH_VEC_ELT (v, i, opt)
> >      {
> >        switch (opt->opt_index)
> > @@ -392,6 +393,10 @@ handle_common_deferred_options (void)
> >  	  add_profile_prefix_map (opt->arg);
> >  	  break;
> >  
> > +	case OPT_fcanon_prefix_map:
> > +	  flag_canon_prefix_map = opt->value;
> > +	  break;
> > +
> >  	case OPT_fdump_:
> >  	  g->get_dumps ()->dump_switch_p (opt->arg);
> >  	  break;
> > --- gcc/doc/invoke.texi.jj	2023-01-16 11:52:16.115733593 +0100
> > +++ gcc/doc/invoke.texi	2023-01-20 14:44:47.514203801 +0100
> > @@ -191,7 +191,7 @@ in the following sections.
> >  -dumpdir @var{dumppfx}  -x @var{language}  @gol
> >  -v  -###  --help@r{[}=@var{class}@r{[},@dots{}@r{]]}  --target-help  --version @gol
> >  -pass-exit-codes  -pipe  -specs=@var{file}  -wrapper  @gol
> > -@@@var{file}  -ffile-prefix-map=@var{old}=@var{new}  @gol
> > +@@@var{file}  -ffile-prefix-map=@var{old}=@var{new}  -fcanon-prefix-map  @gol
> >  -fplugin=@var{file}  -fplugin-arg-@var{name}=@var{arg}  @gol
> >  -fdump-ada-spec@r{[}-slim@r{]}  -fada-spec-parent=@var{unit}  -fdump-go-spec=@var{file}}
> >  
> > @@ -2203,9 +2203,20 @@ files resided in directory @file{@var{ne
> >  option is equivalent to specifying all the individual
> >  @option{-f*-prefix-map} options.  This can be used to make reproducible
> >  builds that are location independent.  Directories referenced by
> > -directives are not affected by these options. See also
> > -@option{-fmacro-prefix-map}, @option{-fdebug-prefix-map} and
> > -@option{-fprofile-prefix-map}.
> > +directives are not affected by these options.  See also
> > +@option{-fmacro-prefix-map}, @option{-fdebug-prefix-map},
> > +@option{-fprofile-prefix-map} and @option{-fcanon-prefix-map}.
> > +
> > +@item -fcanon-prefix-map
> > +@opindex fcanon-prefix-map
> > +For the @option{-f*-prefix-map} options normally comparison
> > +of @file{@var{old}} prefix against the filename that would be normally
> > +referenced in the result of the compilation is done using textual
> > +comparison of the prefixes, or ignoring character case for case insensitive
> > +filesystems and considering slashes and backslashes as equal on DOS based
> > +filesystems.  The @option{-fcanon-prefix-map} causes such comparisons
> > +to be done on canonicalized paths of @file{@var{old}}
> > +and the referenced filename.
> >  
> >  @item -fplugin=@var{name}.so
> >  @opindex fplugin
> > @@ -11289,7 +11300,8 @@ build-time path with an install-time pat
> >  also be used to change an absolute path to a relative path by using
> >  @file{.} for @var{new}.  This can give more reproducible builds, which
> >  are location independent, but may require an extra command to tell GDB
> > -where to find the source files. See also @option{-ffile-prefix-map}.
> > +where to find the source files. See also @option{-ffile-prefix-map}
> > +and @option{-fcanon-prefix-map}.
> >  
> >  @item -fvar-tracking
> >  @opindex fvar-tracking
> > @@ -16466,7 +16478,7 @@ When compiling files residing in directo
> >  profiling information (with @option{--coverage})
> >  describing them as if the files resided in
> >  directory @file{@var{new}} instead.
> > -See also @option{-ffile-prefix-map}.
> > +See also @option{-ffile-prefix-map} and @option{-fcanon-prefix-map}.
> >  
> >  @item -fprofile-update=@var{method}
> >  @opindex fprofile-update
> > --- gcc/doc/cppopts.texi.jj	2023-01-16 11:52:16.102733784 +0100
> > +++ gcc/doc/cppopts.texi	2023-01-20 14:45:09.106890233 +0100
> > @@ -305,7 +305,7 @@ to change an absolute path to a relative
> >  @var{new} which can result in more reproducible builds that are
> >  location independent.  This option also affects
> >  @code{__builtin_FILE()} during compilation.  See also
> > -@option{-ffile-prefix-map}.
> > +@option{-ffile-prefix-map} and @option{-fcanon-prefix-map}.
> >  
> >  @item -fexec-charset=@var{charset}
> >  @opindex fexec-charset
> 
>
  
Richard Purdie March 10, 2023, 10:14 a.m. UTC | #4
On Fri, 2023-03-10 at 09:05 +0000, Richard Biener wrote:
> On Fri, 10 Mar 2023, Jakub Jelinek wrote:
> 
> > Hi!
> > 
> > I'd like to ping these patches.  All 3 variants have been
> > bootstrapped/regtested on x86_64-linux and i686-linux, the last
> > one is my preference I guess.  The current state breaks e.g. ccache.
> > 
> > https://gcc.gnu.org/pipermail/gcc-patches/2023-January/610285.html
> >   - PR108464 - P1 - file-prefix-map: Fix up -f*-prefix-map= (3 variants)
> 
> Let's go with your preference - I was hoping on comments from Richard 
> Purdie as of his preference but then ..
> > 

Sorry, I hadn't realised you were waiting on me :(. 

I'd commented on the bug and thought that covered things. We should be
fine with the third option, sorry about the issue and thanks for
resolving it!

Cheers,

Richard
  

Patch

--- gcc/file-prefix-map.cc
+++ gcc/file-prefix-map.cc
@@ -70,29 +70,19 @@  remap_filename (file_prefix_map *maps, const char *filename)
   file_prefix_map *map;
   char *s;
   const char *name;
-  char *realname;
   size_t name_len;
 
-  if (!filename || lbasename (filename) == filename)
-    return filename;
-
-  realname = lrealpath (filename);
-
   for (map = maps; map; map = map->next)
-    if (filename_ncmp (realname, map->old_prefix, map->old_len) == 0)
+    if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
       break;
   if (!map)
-    {
-      free (realname);
-      return filename;
-    }
-  name = realname + map->old_len;
+    return filename;
+  name = filename + map->old_len;
   name_len = strlen (name) + 1;
 
   s = (char *) ggc_alloc_atomic (name_len + map->new_len);
   memcpy (s, map->new_prefix, map->new_len);
   memcpy (s + map->new_len, name, name_len);
-  free (realname);
   return s;
 }