[gcc-6] 401/401: Support BUILD_PATH_PREFIX_MAP
Ximin Luo
infinity0 at debian.org
Wed Apr 5 15:50:45 UTC 2017
This is an automated email from the git hooks/post-receive script.
infinity0 pushed a commit to branch pu/reproducible_builds
in repository gcc-6.
commit 60f7e5a27f7eab24b97a6e8f5b43fe2d2cc8d148
Author: Ximin Luo <infinity0 at debian.org>
Date: Wed Apr 5 17:44:25 2017 +0200
Support BUILD_PATH_PREFIX_MAP
---
debian/changelog | 7 +
debian/patches/BPPM_env_FILE_macro.diff | 229 +++++++++
debian/patches/BPPM_env_debuginfo.diff | 625 ++++++++++++++++++++++++
debian/patches/remap_whole_path_components.diff | 72 +++
debian/rules.patch | 3 +
5 files changed, 936 insertions(+)
diff --git a/debian/changelog b/debian/changelog
index 02a2649..2885c50 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+gcc-6 (6.3.0-11.0~reproducible1) unstable; urgency=medium
+
+ * Non-maintainer upload.
+ * Support BUILD_PATH_PREFIX_MAP.
+
+ -- Ximin Luo <infinity0 at debian.org> Fri, 31 Mar 2017 19:13:44 -0400
+
gcc-6 (6.3.0-11) unstable; urgency=medium
* Fix PR target/78543 (PPC), taken from the gcc-6-branch. Closes: #856809.
diff --git a/debian/patches/BPPM_env_FILE_macro.diff b/debian/patches/BPPM_env_FILE_macro.diff
new file mode 100644
index 0000000..809a85c
--- /dev/null
+++ b/debian/patches/BPPM_env_FILE_macro.diff
@@ -0,0 +1,229 @@
+Subject: [PATCH 2/3] Use BUILD_PATH_PREFIX_MAP envvar to transform __FILE__
+
+Use the BUILD_PATH_PREFIX_MAP environment variable when expanding the __FILE__
+macro, in the same way that debug-prefix-map works for debugging symbol paths.
+
+This patch follows similar lines to the earlier patch for SOURCE_DATE_EPOCH.
+Specifically, we read the environment variable not in libcpp but via a hook
+which has an implementation defined in gcc/c-family. However, to achieve this
+is more complex than the earlier patch: we need to share the prefix_map data
+structure and associated functions between libcpp and c-family. Therefore, we
+need to move these to libiberty. (For comparison, the SOURCE_DATE_EPOCH patch
+did not need this because time_t et. al. are in the standard C library.)
+
+Acknowledgements
+----------------
+
+Dhole <dhole at openmailbox.org> who wrote the earlier patch for SOURCE_DATE_EPOCH
+which saved me a lot of time on figuring out what to edit.
+
+ChangeLogs
+----------
+
+gcc/c-family/ChangeLog:
+
+2017-03-27 Ximin Luo <infinity0 at pwned.gg>
+
+ * c-common.c (cb_get_build_path_prefix_map): Define new call target.
+ * c-common.h (cb_get_build_path_prefix_map): Declare call target.
+ * c-lex.c (init_c_lex): Set the get_build_path_prefix_map callback.
+
+libcpp/ChangeLog:
+
+2017-03-27 Ximin Luo <infinity0 at pwned.gg>
+
+ * include/cpplib.h (cpp_callbacks): Add get_build_path_prefix_map
+ callback.
+ * init.c (cpp_create_reader): Initialise build_path_prefix_map field.
+ * internal.h (cpp_reader): Add new field build_path_prefix_map.
+ * macro.c (_cpp_builtin_macro_text): Set the build_path_prefix_map
+ field if unset and apply it when expanding __FILE__ macros.
+
+gcc/testsuite/ChangeLog:
+
+2017-03-27 Ximin Luo <infinity0 at pwned.gg>
+
+ * gcc.dg/cpp/build_path_prefix_map-1.c: New test.
+ * gcc.dg/cpp/build_path_prefix_map-2.c: New test.
+
+Index: b/src/gcc/c-family/c-common.c
+===================================================================
+--- a/src/gcc/c-family/c-common.c
++++ b/src/gcc/c-family/c-common.c
+@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.
+
+ #include "config.h"
+ #include "system.h"
++#include "prefix-map.h"
+ #include "coretypes.h"
+ #include "target.h"
+ #include "function.h"
+@@ -8005,4 +8006,23 @@ cb_get_source_date_epoch (cpp_reader *pf
+ return (time_t) epoch;
+ }
+
++/* Read BUILD_PATH_PREFIX_MAP from environment to have deterministic relative
++ paths to replace embedded absolute paths to get reproducible results.
++ Returns NULL if BUILD_PATH_PREFIX_MAP is badly formed. */
++
++prefix_map **
++cb_get_build_path_prefix_map (cpp_reader *pfile ATTRIBUTE_UNUSED)
++{
++ prefix_map **map = XCNEW (prefix_map *);
++
++ const char *arg = getenv ("BUILD_PATH_PREFIX_MAP");
++ if (!arg || prefix_map_parse (map, arg))
++ return map;
++
++ free (map);
++ error_at (input_location, "environment variable BUILD_PATH_PREFIX_MAP is "
++ "not well formed; see the GCC documentation for more details.");
++ return NULL;
++}
++
+ #include "gt-c-family-c-common.h"
+Index: b/src/gcc/c-family/c-common.h
+===================================================================
+--- a/src/gcc/c-family/c-common.h
++++ b/src/gcc/c-family/c-common.h
+@@ -1085,6 +1085,11 @@ extern time_t cb_get_source_date_epoch (
+ __TIME__ can store. */
+ #define MAX_SOURCE_DATE_EPOCH HOST_WIDE_INT_C (253402300799)
+
++/* Read BUILD_PATH_PREFIX_MAP from environment to have deterministic relative
++ paths to replace embedded absolute paths to get reproducible results.
++ Returns NULL if BUILD_PATH_PREFIX_MAP is badly formed. */
++extern prefix_map **cb_get_build_path_prefix_map (cpp_reader *pfile);
++
+ /* In c-gimplify.c */
+ extern void c_genericize (tree);
+ extern int c_gimplify_expr (tree *, gimple_seq *, gimple_seq *);
+Index: b/src/gcc/c-family/c-lex.c
+===================================================================
+--- a/src/gcc/c-family/c-lex.c
++++ b/src/gcc/c-family/c-lex.c
+@@ -81,6 +81,7 @@ init_c_lex (void)
+ cb->read_pch = c_common_read_pch;
+ cb->has_attribute = c_common_has_attribute;
+ cb->get_source_date_epoch = cb_get_source_date_epoch;
++ cb->get_build_path_prefix_map = cb_get_build_path_prefix_map;
+
+ /* Set the debug callbacks if we can use them. */
+ if ((debug_info_level == DINFO_LEVEL_VERBOSE
+Index: b/src/libcpp/include/cpplib.h
+===================================================================
+--- a/src/libcpp/include/cpplib.h
++++ b/src/libcpp/include/cpplib.h
+@@ -607,5 +607,8 @@ struct cpp_callbacks
+ /* Callback to parse SOURCE_DATE_EPOCH from environment. */
+ time_t (*get_source_date_epoch) (cpp_reader *);
++
++ /* Callback to parse BUILD_PATH_PREFIX_MAP from environment. */
++ struct prefix_map **(*get_build_path_prefix_map) (cpp_reader *);
+ };
+
+ #ifdef VMS
+Index: b/src/libcpp/init.c
+===================================================================
+--- a/src/libcpp/init.c
++++ b/src/libcpp/init.c
+@@ -261,6 +261,9 @@ cpp_create_reader (enum c_lang lang, cpp
+ /* Initialize source_date_epoch to -2 (not yet set). */
+ pfile->source_date_epoch = (time_t) -2;
+
++ /* Initialize build_path_prefix_map to NULL (not yet set). */
++ pfile->build_path_prefix_map = NULL;
++
+ /* The expression parser stack. */
+ _cpp_expand_op_stack (pfile);
+
+Index: b/src/libcpp/internal.h
+===================================================================
+--- a/src/libcpp/internal.h
++++ b/src/libcpp/internal.h
+@@ -507,6 +507,11 @@ struct cpp_reader
+ set to -1 to disable it or to a non-negative value to enable it. */
+ time_t source_date_epoch;
+
++ /* Externally set prefix-map to transform absolute paths, useful for
++ reproducibility. It should be initialized to NULL (not yet set or
++ disabled) or to a `struct prefix_map` double pointer to enable it. */
++ struct prefix_map **build_path_prefix_map;
++
+ /* EOF token, and a token forcing paste avoidance. */
+ cpp_token avoid_paste;
+ cpp_token eof;
+Index: b/src/libcpp/macro.c
+===================================================================
+--- a/src/libcpp/macro.c
++++ b/src/libcpp/macro.c
+@@ -26,6 +26,7 @@ along with this program; see the file CO
+ #include "system.h"
+ #include "cpplib.h"
+ #include "internal.h"
++#include "prefix-map.h"
+
+ typedef struct macro_arg macro_arg;
+ /* This structure represents the tokens of a macro argument. These
+@@ -291,7 +292,17 @@ _cpp_builtin_macro_text (cpp_reader *pfi
+ unsigned int len;
+ const char *name;
+ uchar *buf;
++ prefix_map **map = pfile->build_path_prefix_map;
+
++ /* Set a prefix-map for __FILE__ if BUILD_PATH_PREFIX_MAP is defined. */
++ if (map == NULL && pfile->cb.get_build_path_prefix_map != NULL)
++ {
++ map = pfile->cb.get_build_path_prefix_map (pfile);
++ if (map == NULL)
++ abort ();
++ pfile->build_path_prefix_map = map;
++ }
++
+ if (node->value.builtin == BT_FILE)
+ name = linemap_get_expansion_filename (pfile->line_table,
+ pfile->line_table->highest_line);
+@@ -301,6 +312,11 @@ _cpp_builtin_macro_text (cpp_reader *pfi
+ if (!name)
+ abort ();
+ }
++
++ /* Apply the prefix-map for deterministic path output. */
++ if (map != NULL)
++ name = prefix_map_remap_alloca (*map, name);
++
+ len = strlen (name);
+ buf = _cpp_unaligned_alloc (pfile, len * 2 + 3);
+ result = buf;
+Index: b/src/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-1.c
+===================================================================
+--- /dev/null
++++ b/src/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-1.c
+@@ -0,0 +1,11 @@
++/* __FILE__ should strip BUILD_PATH_PREFIX_MAP if the latter is a prefix. */
++/* { dg-do run } */
++/* { dg-set-compiler-env-var BUILD_PATH_PREFIX_MAP "MACROTEST=$srcdir" } */
++
++int
++main ()
++{
++ if (__builtin_strcmp (__FILE__, "MACROTEST/gcc.dg/cpp/build_path_prefix_map-1.c") != 0)
++ __builtin_abort ();
++ return 0;
++}
+Index: b/src/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-2.c
+===================================================================
+--- /dev/null
++++ b/src/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-2.c
+@@ -0,0 +1,11 @@
++/* __FILE__ should not be relative if BUILD_PATH_PREFIX_MAP is not set, and gcc is
++ asked to compile an absolute filename as is the case with this test. */
++/* { dg-do run } */
++
++int
++main ()
++{
++ if (__builtin_strcmp (__FILE__, "./gcc.dg/cpp/build_path_prefix_map-1.c") == 0)
++ __builtin_abort ();
++ return 0;
++}
diff --git a/debian/patches/BPPM_env_debuginfo.diff b/debian/patches/BPPM_env_debuginfo.diff
new file mode 100644
index 0000000..bfa05fa
--- /dev/null
+++ b/debian/patches/BPPM_env_debuginfo.diff
@@ -0,0 +1,625 @@
+Subject: [PATCH 1/3] Use BUILD_PATH_PREFIX_MAP envvar for debug-prefix-map
+
+Define the BUILD_PATH_PREFIX_MAP environment variable, and treat it as implicit
+-fdebug-prefix-map CLI options specified before any explicit such options.
+
+Much of the generic code for applying and parsing prefix-maps is implemented in
+libiberty instead of the dwarf2 parts of the code, in order to make subsequent
+patches unrelated to debuginfo easier.
+
+Acknowledgements
+----------------
+
+Daniel Kahn Gillmor who wrote the patch for r231835, which saved me a lot of
+time figuring out what to edit.
+
+HW42 for discussion on the details of the proposal, and for suggesting that we
+retain the ability to map the prefix to something other than ".".
+
+Other contributors to the BUILD_PATH_PREFIX_MAP specification, see
+https://reproducible-builds.org/specs/build-path-prefix-map/
+
+ChangeLogs
+----------
+
+include/ChangeLog:
+
+2017-03-27 Ximin Luo <infinity0 at pwned.gg>
+
+ * prefix-map.h: New file implementing the BUILD_PATH_PREFIX_MAP
+ specification; includes code from /gcc/final.c and code adapted from
+ examples attached to the specification.
+
+libiberty/ChangeLog:
+
+2017-03-27 Ximin Luo <infinity0 at pwned.gg>
+
+ * prefix-map.c: New file implementing the BUILD_PATH_PREFIX_MAP
+ specification; includes code from /gcc/final.c and code adapted from
+ examples attached to the specification.
+ * Makefile.in: Update for new files.
+
+gcc/ChangeLog:
+
+2017-03-27 Ximin Luo <infinity0 at pwned.gg>
+
+ * debug.h: Declare add_debug_prefix_map_from_envvar.
+ * final.c: Define add_debug_prefix_map_from_envvar, and refactor
+ prefix-map utilities to use equivalent code from libiberty instead.
+ * opts-global.c: (handle_common_deferred_options): Call
+ add_debug_prefix_map_from_envvar before processing options.
+
+gcc/testsuite/ChangeLog:
+
+2017-03-27 Ximin Luo <infinity0 at pwned.gg>
+
+ * gcc.dg/debug/dwarf2/build_path_prefix_map-1.c: New test.
+ * gcc.dg/debug/dwarf2/build_path_prefix_map-2.c: New test.
+
+Index: b/src/include/prefix-map.h
+===================================================================
+--- /dev/null
++++ b/src/include/prefix-map.h
+@@ -0,0 +1,108 @@
++/* Declarations for manipulating filename prefixes.
++
++ Copyright (C) 2017 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 2, 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, write to the Free Software Foundation,
++ Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
++
++#ifndef _PREFIX_MAP_H
++#define _PREFIX_MAP_H
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#ifdef HAVE_STDLIB_H
++#include <stdlib.h>
++#endif
++
++/* Linked-list of mappings from old prefixes to new prefixes. */
++
++struct prefix_map
++{
++ const char *old_prefix;
++ const char *new_prefix;
++ size_t old_len;
++ size_t new_len;
++ struct prefix_map *next;
++};
++
++
++/* Find a mapping suitable for the given OLD_NAME in the linked list MAP.\
++
++ If a mapping is found, writes a pointer to the non-matching suffix part of
++ OLD_NAME in SUFFIX, and its length in SUF_LEN.
++
++ Returns NULL if there was no suitable mapping. */
++struct prefix_map *
++prefix_map_find (struct prefix_map *map, const char *old_name,
++ const char **suffix, size_t *suf_len);
++
++/* Prepend a prefix map before a given SUFFIX.
++
++ The remapped name is written to NEW_NAME and returned as a const pointer. No
++ allocations are performed; the caller must ensure it can hold at least
++ MAP->NEW_LEN + SUF_LEN + 1 characters. */
++const char *
++prefix_map_prepend (struct prefix_map *map, char *new_name,
++ const char *suffix, size_t suf_len);
++
++/* Remap a filename.
++
++ Returns OLD_NAME unchanged if there was no remapping, otherwise returns a
++ pointer to newly-allocated memory for the remapped filename. The memory is
++ allocated by the given ALLOC function, which also determines who is
++ responsible for freeing it. */
++#define prefix_map_remap_alloc_(map_head, old_name, alloc) \
++ __extension__ \
++ ({ \
++ const char *__suffix; \
++ size_t __suf_len; \
++ struct prefix_map *__map; \
++ (__map = prefix_map_find ((map_head), (old_name), &__suffix, &__suf_len)) \
++ ? prefix_map_prepend (__map, \
++ (char *) alloc (__map->new_len + __suf_len + 1), \
++ __suffix, __suf_len) \
++ : (old_name); \
++ })
++
++/* Remap a filename.
++
++ Returns OLD_NAME unchanged if there was no remapping, otherwise returns a
++ stack-allocated pointer to the newly-remapped filename. */
++#define prefix_map_remap_alloca(map_head, old_name) \
++ prefix_map_remap_alloc_ (map_head, old_name, alloca)
++
++
++/* Parse prefix-maps according to the BUILD_PATH_PREFIX_MAP standard.
++
++ The input string value is of the form
++
++ dst[0]=src[0]:dst[1]=src[1]...
++
++ Every dst[i] and src[i] has had "%", "=" and ":" characters replaced with
++ "%#", "%+", and "%." respectively; this function reverses this replacement.
++
++ Rightmost entries are stored at the head of the parsed structure.
++
++ Returns 0 on failure and 1 on success. */
++int
++prefix_map_parse (struct prefix_map **map_head, const char *arg);
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* _PREFIX_MAP_H */
+Index: b/src/libiberty/Makefile.in
+===================================================================
+--- a/src/libiberty/Makefile.in
++++ b/src/libiberty/Makefile.in
+@@ -143,6 +143,7 @@ CFILES = alloca.c argv.c asprintf.c atex
+ pex-common.c pex-djgpp.c pex-msdos.c pex-one.c \
+ pex-unix.c pex-win32.c \
+ physmem.c putenv.c \
++ prefix-map.c \
+ random.c regex.c rename.c rindex.c \
+ rust-demangle.c \
+ safe-ctype.c setenv.c setproctitle.c sha1.c sigsetmask.c \
+@@ -182,6 +183,7 @@ REQUIRED_OFILES = \
+ ./partition.$(objext) ./pexecute.$(objext) ./physmem.$(objext) \
+ ./pex-common.$(objext) ./pex-one.$(objext) \
+ ./@pexecute at .$(objext) ./vprintf-support.$(objext) \
++ ./prefix-map.$(objext) \
+ ./rust-demangle.$(objext) \
+ ./safe-ctype.$(objext) \
+ ./simple-object.$(objext) ./simple-object-coff.$(objext) \
+@@ -757,7 +759,7 @@ $(CONFIGURED_OFILES): stamp-picdir stamp
+ $(COMPILE.c) $(srcdir)/fibheap.c $(OUTPUT_OPTION)
+
+ ./filename_cmp.$(objext): $(srcdir)/filename_cmp.c config.h $(INCDIR)/ansidecl.h \
+- $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
++ $(INCDIR)/filenames.h $(INCDIR)/hashtab.h $(INCDIR)/libiberty.h \
+ $(INCDIR)/safe-ctype.h
+ if [ x"$(PICFLAG)" != x ]; then \
+ $(COMPILE.c) $(PICFLAG) $(srcdir)/filename_cmp.c -o pic/$@; \
+@@ -1104,7 +1106,8 @@ $(CONFIGURED_OFILES): stamp-picdir stamp
+ $(COMPILE.c) $(srcdir)/pex-one.c $(OUTPUT_OPTION)
+
+ ./pex-unix.$(objext): $(srcdir)/pex-unix.c config.h $(INCDIR)/ansidecl.h \
+- $(INCDIR)/libiberty.h $(srcdir)/pex-common.h
++ $(INCDIR)/environ.h $(INCDIR)/libiberty.h \
++ $(srcdir)/pex-common.h
+ if [ x"$(PICFLAG)" != x ]; then \
+ $(COMPILE.c) $(PICFLAG) $(srcdir)/pex-unix.c -o pic/$@; \
+ else true; fi
+@@ -1143,6 +1146,15 @@ $(CONFIGURED_OFILES): stamp-picdir stamp
+ else true; fi
+ $(COMPILE.c) $(srcdir)/physmem.c $(OUTPUT_OPTION)
+
++./prefix-map.$(objext): $(srcdir)/prefix-map.c config.h $(INCDIR)/prefix-map.h
++ if [ x"$(PICFLAG)" != x ]; then \
++ $(COMPILE.c) $(PICFLAG) $(srcdir)/prefix-map.c -o pic/$@; \
++ else true; fi
++ if [ x"$(NOASANFLAG)" != x ]; then \
++ $(COMPILE.c) $(PICFLAG) $(NOASANFLAG) $(srcdir)/prefix-map.c -o noasan/$@; \
++ else true; fi
++ $(COMPILE.c) $(srcdir)/prefix-map.c $(OUTPUT_OPTION)
++
+ ./putenv.$(objext): $(srcdir)/putenv.c config.h $(INCDIR)/ansidecl.h
+ if [ x"$(PICFLAG)" != x ]; then \
+ $(COMPILE.c) $(PICFLAG) $(srcdir)/putenv.c -o pic/$@; \
+@@ -1210,7 +1222,8 @@ $(CONFIGURED_OFILES): stamp-picdir stamp
+ else true; fi
+ $(COMPILE.c) $(srcdir)/safe-ctype.c $(OUTPUT_OPTION)
+
+-./setenv.$(objext): $(srcdir)/setenv.c config.h $(INCDIR)/ansidecl.h
++./setenv.$(objext): $(srcdir)/setenv.c config.h $(INCDIR)/ansidecl.h \
++ $(INCDIR)/environ.h
+ if [ x"$(PICFLAG)" != x ]; then \
+ $(COMPILE.c) $(PICFLAG) $(srcdir)/setenv.c -o pic/$@; \
+ else true; fi
+@@ -1661,7 +1674,7 @@ $(CONFIGURED_OFILES): stamp-picdir stamp
+ $(COMPILE.c) $(srcdir)/xexit.c $(OUTPUT_OPTION)
+
+ ./xmalloc.$(objext): $(srcdir)/xmalloc.c config.h $(INCDIR)/ansidecl.h \
+- $(INCDIR)/libiberty.h
++ $(INCDIR)/environ.h $(INCDIR)/libiberty.h
+ if [ x"$(PICFLAG)" != x ]; then \
+ $(COMPILE.c) $(PICFLAG) $(srcdir)/xmalloc.c -o pic/$@; \
+ else true; fi
+@@ -1719,3 +1732,4 @@ $(CONFIGURED_OFILES): stamp-picdir stamp
+ $(COMPILE.c) $(PICFLAG) $(NOASANFLAG) $(srcdir)/xvasprintf.c -o noasan/$@; \
+ else true; fi
+ $(COMPILE.c) $(srcdir)/xvasprintf.c $(OUTPUT_OPTION)
++
+Index: b/src/libiberty/prefix-map.c
+===================================================================
+--- /dev/null
++++ b/src/libiberty/prefix-map.c
+@@ -0,0 +1,215 @@
++/* Definitions for manipulating filename prefixes.
++
++ Copyright (C) 2017 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 2, 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, write to the Free Software Foundation,
++ Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#ifdef HAVE_STRING_H
++#include <string.h>
++#endif
++
++#ifdef HAVE_STDLIB_H
++#include <stdlib.h>
++#endif
++
++#include "filenames.h"
++#include "libiberty.h"
++#include "prefix-map.h"
++
++
++/* Add a new mapping.
++
++ The input strings are duplicated and a new prefix_map struct is allocated.
++ Ownership of the duplicates, as well as the new prefix_map, is the same as
++ the ownership of the old struct.
++
++ Returns 0 on failure and 1 on success. */
++int
++prefix_map_push (struct prefix_map **map_head,
++ const char *new_prefix, const char *old_prefix)
++{
++ struct prefix_map *map = XNEW (struct prefix_map);
++ if (!map)
++ goto rewind_0;
++
++ map->old_prefix = xstrdup (old_prefix);
++ if (!map->old_prefix)
++ goto rewind_1;
++ map->old_len = strlen (old_prefix);
++
++ map->new_prefix = xstrdup (new_prefix);
++ if (!map->new_prefix)
++ goto rewind_2;
++ map->new_len = strlen (new_prefix);
++
++ map->next = *map_head;
++ *map_head = map;
++ return 1;
++
++rewind_2:
++ free ((void *) map->old_prefix);
++rewind_1:
++ free (map);
++rewind_0:
++ return 0;
++}
++
++/* Rewind a prefix map.
++
++ Everything up to the given OLD_HEAD is freed. */
++void
++prefix_map_pop_until (struct prefix_map **map_head, struct prefix_map *old_head)
++{
++ struct prefix_map *map;
++ struct prefix_map *next;
++
++ for (map = *map_head; map != old_head; map = next)
++ {
++ free ((void *) map->old_prefix);
++ free ((void *) map->new_prefix);
++ next = map->next;
++ free (map);
++ }
++
++ *map_head = map;
++}
++
++
++/* Find a mapping suitable for the given OLD_NAME in the linked list MAP.\
++
++ If a mapping is found, writes a pointer to the non-matching suffix part of
++ OLD_NAME in SUFFIX, and its length in SUF_LEN.
++
++ Returns NULL if there was no suitable mapping. */
++struct prefix_map *
++prefix_map_find (struct prefix_map *map, const char *old_name,
++ const char **suffix, size_t *suf_len)
++{
++ for (; map; map = map->next)
++ if (filename_ncmp (old_name, map->old_prefix, map->old_len) == 0)
++ {
++ *suf_len = strlen (*suffix = old_name + map->old_len);
++ break;
++ }
++
++ return map;
++}
++
++/* Prepend a prefix map before a given SUFFIX.
++
++ The remapped name is written to NEW_NAME and returned as a const pointer. No
++ allocations are performed; the caller must ensure it can hold at least
++ MAP->NEW_LEN + SUF_LEN + 1 characters. */
++const char *
++prefix_map_prepend (struct prefix_map *map, char *new_name,
++ const char *suffix, size_t suf_len)
++{
++ memcpy (new_name, map->new_prefix, map->new_len);
++ memcpy (new_name + map->new_len, suffix, suf_len + 1);
++ return new_name;
++}
++
++
++/* Parse a single part of a single prefix-map pair.
++
++ Returns 0 on failure and 1 on success. */
++int
++prefix_map_parse_unquote (char *src)
++{
++ for (char *dest = src; 0 != (*dest = *src); ++dest, ++src)
++ switch (*src)
++ {
++ case ':':
++ case '=':
++ return 0; // should have been escaped
++ case '%':
++ switch (*(src + 1))
++ {
++ case '.':
++ *dest = ':';
++ goto unquoted;
++ case '+':
++ *dest = '=';
++ unquoted:
++ case '#':
++ ++src;
++ break;
++ default:
++ return 0; // invalid
++ }
++ }
++ return 1;
++}
++
++/* Parse a single prefix-map.
++
++ Returns 0 on failure and 1 on success. */
++int
++prefix_map_parse1 (struct prefix_map **map_head, char *arg)
++{
++ char *p;
++ p = strchr (arg, '=');
++ if (!p)
++ return 0;
++ *p = '\0';
++ if (!prefix_map_parse_unquote (arg))
++ return 0;
++ p++;
++ if (!prefix_map_parse_unquote (p))
++ return 0;
++
++ return prefix_map_push (map_head, arg, p);
++}
++
++/* Parse a prefix-map according to the BUILD_PATH_PREFIX_MAP standard.
++
++ The input string value is of the form
++
++ dst[0]=src[0]:dst[1]=src[1]...
++
++ Every dst[i] and src[i] has had "%", "=" and ":" characters replaced with
++ "%#", "%+", and "%." respectively; this function reverses this replacement.
++
++ Rightmost entries are stored at the head of the parsed structure.
++
++ Returns 0 on failure and 1 on success. */
++int
++prefix_map_parse (struct prefix_map **map_head, const char *arg)
++{
++ struct prefix_map *old_head = *map_head;
++
++ size_t len = strlen (arg);
++ char *copy = (char *) alloca (len + 1);
++ memcpy (copy, arg, len + 1);
++
++ const char *sep = ":";
++ char *end, *tok = strtok_r (copy, sep, &end);
++ while (tok != NULL)
++ {
++ if (!prefix_map_parse1 (map_head, tok))
++ {
++ prefix_map_pop_until (map_head, old_head);
++ return 0;
++ }
++
++ tok = strtok_r (NULL, sep, &end);
++ }
++
++ return 1;
++}
+Index: b/src/gcc/debug.h
+===================================================================
+--- a/src/gcc/debug.h
++++ b/src/gcc/debug.h
+@@ -236,6 +236,7 @@ extern void dwarf2out_switch_text_sectio
+
+ const char *remap_debug_filename (const char *);
+ void add_debug_prefix_map (const char *);
++void add_debug_prefix_map_from_envvar ();
+
+ /* For -fdump-go-spec. */
+
+Index: b/src/gcc/final.c
+===================================================================
+--- a/src/gcc/final.c
++++ b/src/gcc/final.c
+@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3.
+ #define INCLUDE_ALGORITHM /* reverse */
+ #include "system.h"
+ #include "coretypes.h"
++#include "prefix-map.h"
+ #include "backend.h"
+ #include "target.h"
+ #include "rtl.h"
+@@ -1506,22 +1507,9 @@ asm_str_count (const char *templ)
+ return count;
+ }
+
+-/* ??? This is probably the wrong place for these. */
+-/* Structure recording the mapping from source file and directory
+- names at compile time to those to be embedded in debug
+- information. */
+-struct debug_prefix_map
+-{
+- const char *old_prefix;
+- const char *new_prefix;
+- size_t old_len;
+- size_t new_len;
+- struct debug_prefix_map *next;
+-};
+-
+-/* Linked list of such structures. */
+-static debug_prefix_map *debug_prefix_maps;
+
++/* Linked list of `struct prefix_map'. */
++static prefix_map *debug_prefix_maps = NULL;
+
+ /* Record a debug file prefix mapping. ARG is the argument to
+ -fdebug-prefix-map and must be of the form OLD=NEW. */
+@@ -1529,7 +1517,7 @@ static debug_prefix_map *debug_prefix_ma
+ void
+ add_debug_prefix_map (const char *arg)
+ {
+- debug_prefix_map *map;
++ prefix_map *map;
+ const char *p;
+
+ p = strchr (arg, '=');
+@@ -1538,7 +1526,7 @@ add_debug_prefix_map (const char *arg)
+ error ("invalid argument %qs to -fdebug-prefix-map", arg);
+ return;
+ }
+- map = XNEW (debug_prefix_map);
++ map = XNEW (prefix_map);
+ map->old_prefix = xstrndup (arg, p - arg);
+ map->old_len = p - arg;
+ p++;
+@@ -1548,28 +1536,32 @@ add_debug_prefix_map (const char *arg)
+ debug_prefix_maps = map;
+ }
+
++/* Add debug-prefix-maps from BUILD_PATH_PREFIX_MAP environment variable. */
++
++void
++add_debug_prefix_map_from_envvar ()
++{
++ const char *arg = getenv ("BUILD_PATH_PREFIX_MAP");
++
++ if (!arg || prefix_map_parse (&debug_prefix_maps, arg))
++ return;
++
++ error ("environment variable BUILD_PATH_PREFIX_MAP is "
++ "not well formed; see the GCC documentation for more details.");
++}
++
+ /* Perform user-specified mapping of debug filename prefixes. Return
+ the new name corresponding to FILENAME. */
+
+ const char *
+ remap_debug_filename (const char *filename)
+ {
+- debug_prefix_map *map;
+- char *s;
+- const char *name;
+- size_t name_len;
+-
+- for (map = debug_prefix_maps; map; map = map->next)
+- if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
+- break;
+- if (!map)
++ const char *name = prefix_map_remap_alloca (debug_prefix_maps, filename);
++
++ if (name == filename)
+ return filename;
+- name = filename + map->old_len;
+- name_len = strlen (name) + 1;
+- s = (char *) alloca (name_len + map->new_len);
+- memcpy (s, map->new_prefix, map->new_len);
+- memcpy (s + map->new_len, name, name_len);
+- return ggc_strdup (s);
++
++ return ggc_strdup (name);
+ }
+
+ /* Return true if DWARF2 debug info can be emitted for DECL. */
+Index: b/src/gcc/opts-global.c
+===================================================================
+--- a/src/gcc/opts-global.c
++++ b/src/gcc/opts-global.c
+@@ -335,6 +335,8 @@ handle_common_deferred_options (void)
+ if (flag_opt_info)
+ opt_info_switch_p (NULL);
+
++ add_debug_prefix_map_from_envvar ();
++
+ FOR_EACH_VEC_ELT (v, i, opt)
+ {
+ switch (opt->opt_index)
+Index: b/src/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-1.c
+===================================================================
+--- /dev/null
++++ b/src/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-1.c
+@@ -0,0 +1,9 @@
++/* DW_AT_comp_dir should be relative if BUILD_PATH_PREFIX_MAP is a prefix of it. */
++/* { dg-do compile } */
++/* { dg-options "-gdwarf -dA" } */
++/* { dg-set-compiler-env-var BUILD_PATH_PREFIX_MAP "DWARF2TEST=[file dirname [pwd]]" } */
++/* { dg-final { scan-assembler "DW_AT_comp_dir: \"DWARF2TEST/gcc" } } */
++
++void func (void)
++{
++}
+Index: b/src/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-2.c
+===================================================================
+--- /dev/null
++++ b/src/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-2.c
+@@ -0,0 +1,8 @@
++/* DW_AT_comp_dir should be absolute if BUILD_PATH_PREFIX_MAP is not set. */
++/* { dg-do compile } */
++/* { dg-options "-gdwarf -dA" } */
++/* { dg-final { scan-assembler "DW_AT_comp_dir: \"/" } } */
++
++void func (void)
++{
++}
diff --git a/debian/patches/remap_whole_path_components.diff b/debian/patches/remap_whole_path_components.diff
new file mode 100644
index 0000000..580be24
--- /dev/null
+++ b/debian/patches/remap_whole_path_components.diff
@@ -0,0 +1,72 @@
+Subject: [PATCH 3/3] When remapping paths, only match whole path components
+
+Change the remapping algorithm so that each old_prefix only matches paths that
+have old_prefix as a whole path component prefix. (A whole path component is a
+part of a path that begins and ends at a directory separator or at either end
+of the path string.)
+
+This remapping algorithm is more predictable than the old algorithm, because
+there is no chance of mappings for one directory interfering with mappings for
+other directories. It contains less corner cases and is therefore nicer for
+clients to use. For these reasons, in our BUILD_PATH_PREFIX_MAP specification
+we recommend this algorithm, and it would be good for GCC to follow suit.
+
+This does technically break backwards compatibility but I don't think anyone
+would be reasonably depending on the corner cases of the previous algorithm,
+which are surprising and counterintuitive.
+
+Acknowledgements
+----------------
+
+Discussions with Michael Woerister and other members of the Rust compiler team
+on Github, and discussions with Daniel Shahaf on the rb-general@ mailing list
+on lists.reproducible-builds.org.
+
+ChangeLogs
+----------
+
+gcc/ChangeLog:
+
+2017-03-27 Ximin Luo <infinity0 at pwned.gg>
+
+ * doc/invoke.texi (Environment Variables): Document form and behaviour
+ of BUILD_PATH_PREFIX_MAP.
+
+libiberty/ChangeLog:
+
+2017-03-27 Ximin Luo <infinity0 at pwned.gg>
+
+ * prefix-map.c: When remapping paths, only match whole path components.
+
+Index: b/src/libiberty/prefix-map.c
+===================================================================
+--- a/src/libiberty/prefix-map.c
++++ b/src/libiberty/prefix-map.c
+@@ -101,12 +101,22 @@ struct prefix_map *
+ prefix_map_find (struct prefix_map *map, const char *old_name,
+ const char **suffix, size_t *suf_len)
+ {
++ size_t len;
++
+ for (; map; map = map->next)
+- if (filename_ncmp (old_name, map->old_prefix, map->old_len) == 0)
+- {
+- *suf_len = strlen (*suffix = old_name + map->old_len);
+- break;
+- }
++ {
++ len = map->old_len;
++ /* Ignore trailing path separators at the end of old_prefix */
++ while (len > 0 && IS_DIR_SEPARATOR (map->old_prefix[len-1])) len--;
++ /* Check if old_name matches old_prefix at a path component boundary */
++ if (! filename_ncmp (old_name, map->old_prefix, len)
++ && (IS_DIR_SEPARATOR (old_name[len])
++ || old_name[len] == '\0'))
++ {
++ *suf_len = strlen (*suffix = old_name + len);
++ break;
++ }
++ }
+
+ return map;
+ }
diff --git a/debian/rules.patch b/debian/rules.patch
index fae5f67..ef29ea2 100644
--- a/debian/rules.patch
+++ b/debian/rules.patch
@@ -86,6 +86,9 @@ debian_patches += \
libjit-ldflags \
gcc-SOURCE_DATE_EPOCH \
gcc-SOURCE_DATE_EPOCH-2 \
+ BPPM_env_debuginfo \
+ BPPM_env_FILE_macro \
+ remap_whole_path_components \
cmd-go-combine-gccgo-s-ld-and-ldShared-methods \
libjava-mips64el \
gccgo-issue16780 \
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/gcc-6.git
More information about the Reproducible-commits
mailing list