Jan Nieuwenhuizen writes: >>> Usage: guix build gcc-dcc >>> >>> Building gcc-dcc tests the diverse double compilation property >>> of the gcc that Guix is using. >>> >>> * gnu/packages/bootstrappable.scm: New file. >>> * gnu/local.mk (GNU_SYSTEM_MODULES): Add it. >> >> Awesome! Does it build fine out-of-the-box? I didn’t expect it to be >> “this easy.” :-) > > I got very positive feedback from a slightly guix-sceptic person saying > something like: you lisp guys can do quite a lot with very little code. > > However, all this patch adds is a test that fails: gcc built with gcc is > not bit-for-bit the same as gcc built with clang. > > Since then I have included the build-path-prefix-map patch, use -rpath > $ORIGIN instead of -rpath "-lib", switched to gcc-7.2.0. Still, no > bit-reproducibility. > > I'll be sending updated patches soon.
Well, that took more time than I expected. I switched from 7.2.0 to 4.7.4 as the first target for diverse double compilation as it seems that 7.2 uses some non-reproducible hash map that I cannot track down _and_ 4.7.x is the latest bootstrappable gcc. Finally, I succeeded in building repro-gcc@4.7.4 using $ORIGIN for rpath. However, gcc-ddc@4.7.4 still shows that some absolute file names are embedded in bin/gcc (yes, I know cpp, cc1 and ../lib* hold most of the functionality): /gnu/store/zw672zcmykdwzm4x7l098hb94c34ak85-repro-gcc-4.7.4/bin/ /gnu/store/zw672zcmykdwzm4x7l098hb94c34ak85-repro-gcc-4.7.4/lib/gcc/ /gnu/store/zw672zcmykdwzm4x7l098hb94c34ak85repro-gcc-4.7.4._ROOT the first one most probably comes from static const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX; I haven't looked a the other two yet. I'm attaching the diffoscope diff and the new patch. Could do with some help here. Thanks, janneke
>From 761ec12aa3a34cd3b95a1c3d828d8bb45558d383 Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen <jann...@gnu.org> Date: Thu, 2 Nov 2017 06:52:46 +0100 Subject: [PATCH] gnu: Add clang-gcc, gcc-ddc. WIP Usage: guix build gcc-dcc Building gcc-dcc tests the diverse double compilation property of the gcc that Guix is using. gcc-dcc is a meta-package that depends on repro-gcc-4.7.4 and on clang-gcc-4.7.4 (the same GCC built with clang). The builder checks if both gcc's are bit-by-bit identical and fails if they differ. * gnu/packages/patches/gcc-4-build-path-prefix-map.patch: New file. * gnu/packages/patches/gcc-7-build-path-prefix-map.patch: New file. * gnu/packages/bootstrappable.scm: New file. * gnu/local.mk (GNU_SYSTEM_MODULES,dist_patch_DATA): Add them. --- gnu/local.mk | 2 + gnu/packages/bootstrappable.scm | 356 ++++++++ .../patches/gcc-4-build-path-prefix-map.patch | 780 +++++++++++++++++ ...fns-fix-mismatch-in-gnu_inline-attributes.patch | 65 ++ .../gcc-5-reproducibility-drop-profile.patch | 36 + .../patches/gcc-7-build-path-prefix-map.patch | 934 +++++++++++++++++++++ 6 files changed, 2173 insertions(+) create mode 100644 gnu/packages/bootstrappable.scm create mode 100644 gnu/packages/patches/gcc-4-build-path-prefix-map.patch create mode 100644 gnu/packages/patches/gcc-4-cfns-fix-mismatch-in-gnu_inline-attributes.patch create mode 100644 gnu/packages/patches/gcc-5-reproducibility-drop-profile.patch create mode 100644 gnu/packages/patches/gcc-7-build-path-prefix-map.patch diff --git a/gnu/local.mk b/gnu/local.mk index 71392d86c..335678160 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -79,6 +79,7 @@ GNU_SYSTEM_MODULES = \ %D%/packages/boost.scm \ %D%/packages/bootloaders.scm \ %D%/packages/bootstrap.scm \ + %D%/packages/bootstrappable.scm \ %D%/packages/build-tools.scm \ %D%/packages/busybox.scm \ %D%/packages/c.scm \ @@ -646,6 +647,7 @@ dist_patch_DATA = \ %D%/packages/patches/gcc-5-source-date-epoch-2.patch \ %D%/packages/patches/gcc-6-arm-none-eabi-multilib.patch \ %D%/packages/patches/gcc-6-cross-environment-variables.patch \ + %D%/packages/patches/gcc-7-build-path-prefix-map.patch \ %D%/packages/patches/gcr-disable-failing-tests.patch \ %D%/packages/patches/gcr-fix-collection-tests-to-work-with-gpg-21.patch \ %D%/packages/patches/gd-fix-tests-on-i686.patch \ diff --git a/gnu/packages/bootstrappable.scm b/gnu/packages/bootstrappable.scm new file mode 100644 index 000000000..cbd7592db --- /dev/null +++ b/gnu/packages/bootstrappable.scm @@ -0,0 +1,356 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2017 Jan Nieuwenhuizen <jann...@gnu.org> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix 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 GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (gnu packages bootstrappable) + #:use-module ((guix licenses) + #:select (gpl3+)) + #:use-module (gnu packages) + #:use-module (gnu packages bootstrap) ; glibc-dynamic-linker + #:use-module (gnu packages gcc) + #:use-module (gnu packages llvm) + + #:use-module (gnu packages package-management) ; diffosscope + #:use-module (gnu packages acl) ; diffosscope->getfacl + #:use-module (gnu packages base) ; diffoscope->cmp + #:use-module (gnu packages vim) ; diffosscope->xxd + + #:use-module (guix download) + #:use-module (guix packages) + #:use-module (guix build-system trivial) + #:use-module (guix utils) + #:use-module (srfi srfi-1)) + + +(define-public gcc-1.4 + (package + (inherit hello) + (name "gcc") + (version "1.40") + (source (origin + (method url-fetch) + (uri (string-append "http://ftp.gnu.org/pub/old-gnu/gcc/gcc-" + version "/gcc-" version ".tar.bz2")) + (sha256 + (base32 + "0z4wzpc3cdlzn35iwkc8xsykcxz23msxgsc96r8f5s124rncadd8")))) + (arguments + `(#:make-flags ("CC=gcc") + #:phases + (modify-phases %standard-phases + (delete 'configure)))))) + +(define-public gcc-4.7-$ORIGIN + (package + (inherit gcc-4.7) + (name "gcc-$ORIGIN") + ;; Using $ORIGIN we cannot have a separate "lib" output + ;; so let's remove lib output + (outputs '("out" ;commands, etc. (60+ MiB) + "debug")) ;debug symbols of run-time libraries + (arguments + (substitute-keyword-arguments (package-arguments gcc-4.7) + ((#:configure-flags original-flags) + ;;--with-stage1-ldflags="-Wl,-rpath,/path/to/isl/lib,-rpath,/path/to/cloog/lib,-rpath,/path/to/gmp/lib" + ;;`(cons "--with-boot-ldflags=-Wl,-rpath,\\$ORIGIN/../lib" ,original-flags) + `(cons* "--enable-languages=c" + "--enable-relocatable" + "--disable-nls" + "--disable-rpath" + ;;"--with-boot-ldflags=-Wl,-rpath,\\$$\\$$ORIGIN/../lib -Wl,-rpath,../lib -Wl,-rpath=../prev-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/" + (delete "--enable-languages=c,c++" ,original-flags))) + ((#:phases original-phases) + `(modify-phases ,original-phases + (replace 'pre-configure + (lambda* (#:key inputs outputs #:allow-other-keys) + (let* ((libdir-suffix (or ,(%current-target-system) "")) + (libdir (string-append + (assoc-ref outputs "out") + libdir-suffix)) + (origin-libdir (string-append "$ORIGIN/.." libdir-suffix)) + (libc (assoc-ref inputs "libc"))) + (when libc + ;; The following is not performed for `--without-headers' + ;; cross-compiler builds. + + ;; Join multi-line definitions of GLIBC_DYNAMIC_LINKER* into a + ;; single line, to allow the next step to work properly. + (for-each + (lambda (x) + (substitute* (find-files "gcc/config" + "^(linux|gnu|sysv4)(64|-elf|-eabi)?\\.h$") + (("(#define (GLIBC|GNU_USER)_DYNAMIC_LINKER.*)\\\\\n$" _ line) + line))) + '(1 2 3)) + + ;; Fix the dynamic linker's file name. + (substitute* (find-files "gcc/config" + "^(linux|gnu|sysv4)(64|-elf|-eabi)?\\.h$") + (("#define (GLIBC|GNU_USER)_DYNAMIC_LINKER([^ \t]*).*$" + _ gnu-user suffix) + (format #f "#define ~a_DYNAMIC_LINKER~a \"~a\"~%" + gnu-user suffix + (string-append libc ,(glibc-dynamic-linker))))) + + ;; Tell where to find libstdc++, libc, and `?crt*.o', except + ;; `crt{begin,end}.o', which come with GCC. + (substitute* (find-files "gcc/config" + "^gnu-user.*\\.h$") + (("#define GNU_USER_TARGET_LIB_SPEC (.*)$" _ suffix) + ;; Help libgcc_s.so be found (see also below.) Always use + ;; '-lgcc_s' so that libgcc_s.so is always found by those + ;; programs that use 'pthread_cancel' (glibc dlopens + ;; libgcc_s.so when pthread_cancel support is needed, but + ;; having it in the application's RUNPATH isn't enough; see + ;; <http://sourceware.org/ml/libc-help/2013-11/msg00023.html>.) + ;; + ;; NOTE: The '-lgcc_s' added below needs to be removed in a + ;; later phase of %gcc-static. If you change the string + ;; below, make sure to update the relevant code in + ;; %gcc-static package as needed. + (format #f "#define GNU_USER_TARGET_LIB_SPEC \ +\"-L~a/lib %{!static:-rpath=~a/lib %{!static-libgcc:\ +-rpath=~a/lib \ +-rpath=~a/gcc \ +-rpath=~a/../lib \ +-rpath=~a/../gcc \ +-rpath=~a/../../lib \ +-rpath=~a/../../../lib \ +-rpath=~a/../../../../lib \ +-lgcc_s}} \" ~a" + libc libc + origin-libdir origin-libdir origin-libdir origin-libdir + origin-libdir origin-libdir origin-libdir + suffix)) + (("#define GNU_USER_TARGET_STARTFILE_SPEC.*$" line) + (format #f "#define STANDARD_STARTFILE_PREFIX_1 \"~a/lib\" +#define STANDARD_STARTFILE_PREFIX_2 \"\" +~a" + libc line))) + + ;; The rs6000 (a.k.a. powerpc) config in GCC does not use + ;; GNU_USER_* defines. Do the above for this case. + (substitute* + "gcc/config/rs6000/sysv4.h" + (("#define LIB_LINUX_SPEC (.*)$" _ suffix) + (format #f "#define LIB_LINUX_SPEC \ +\"-L~a/lib %{!static:-rpath=~a/lib %{!static-libgcc:-rpath=~a/lib -lgcc_s}} \" ~a" + libc libc origin-libdir suffix)) + (("#define STARTFILE_LINUX_SPEC.*$" line) + (format #f "#define STANDARD_STARTFILE_PREFIX_1 \"~a/lib\" +#define STANDARD_STARTFILE_PREFIX_2 \"\" +~a" + libc line)))) + + ;; Don't retain a dependency on the build-time sed. + (substitute* "fixincludes/fixincl.x" + (("static char const sed_cmd_z\\[\\] =.*;") + "static char const sed_cmd_z[] = \"sed\";")) + + ;; Aarch64 support didn't land in GCC until the 4.8 series. + (when (file-exists? "gcc/config/aarch64") + ;; Force Aarch64 libdir to be /lib and not /lib64 + (substitute* "gcc/config/aarch64/t-aarch64-linux" + (("lib64") "lib"))) + + (when (file-exists? "libbacktrace") + ;; GCC 4.8+ comes with libbacktrace. By default it builds + ;; with -Werror, which fails with a -Wcast-qual error in glibc + ;; 2.21's stdlib-bsearch.h. Remove -Werror. + (substitute* "libbacktrace/configure" + (("WARN_FLAGS=(.*)-Werror" _ flags) + (string-append "WARN_FLAGS=" flags))) + + (when (file-exists? "libsanitizer/libbacktrace") + ;; Same in libsanitizer's bundled copy (!) found in 4.9+. + (substitute* "libsanitizer/libbacktrace/Makefile.in" + (("-Werror") + "")))) + + ;; Add a RUNPATH to libstdc++.so so that it finds libgcc_s. + ;; See <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=32354> + ;; and <http://bugs.gnu.org/20358>. + (substitute* "libstdc++-v3/src/Makefile.in" + (("^OPT_LDFLAGS = ") + ;;"OPT_LDFLAGS = -Wl,-rpath=$(libdir) " + (string-append "OPT_LDFLAGS =" + " '-Wl,-rpath=$" origin-libdir "//lib'" + " '-Wl,-rpath=$" origin-libdir "//gcc'" + " '-Wl,-rpath=$" origin-libdir "//../lib'" + " '-Wl,-rpath=$" origin-libdir "//../gcc' " + " '-Wl,-rpath=$" origin-libdir "//../lib'" + ;; FIXME? +;;; /gnu/store/qxwsck61dm7h3n1pgzzs2psj06ihsslj-repro-gcc-4.7.4/libexec/gcc/x86_64-unknown-linux-gnu/4.7.4/install-tools/fixincl: error: depends on 'libgcc_s.so.1' + " '-Wl,-rpath=$" origin-libdir "//../../lib'" + " '-Wl,-rpath=$" origin-libdir "//../../../lib'" + + ))) + + ;; Move libstdc++*-gdb.py to the "lib" output to avoid a + ;; circularity between "out" and "lib". (Note: + ;; --with-python-dir is useless because it imposes $(prefix) as + ;; the parent directory.) + (substitute* "libstdc++-v3/python/Makefile.in" + (("pythondir = .*$") + (string-append "pythondir = " libdir "/share" + "/gcc-$(gcc_version)/python\n"))) + + ;; Avoid another circularity between the outputs: this #define + ;; ends up in auto-host.h in the "lib" output, referring to + ;; "out". (This variable is used to augment cpp's search path, + ;; but there's nothing useful to look for here.) + (substitute* "gcc/config.in" + (("PREFIX_INCLUDE_DIR") + "PREFIX_INCLUDE_DIR_isnt_necessary_here"))))) + + (replace 'post-configure + (lambda _ + ;; Don't store configure flags, to avoid retaining references to + ;; build-time dependencies---e.g., `--with-ppl=/gnu/store/xxx'. + (substitute* "Makefile" + (("^TOPLEVEL_CONFIGURE_ARGUMENTS=(.*)$" _ rest) + "TOPLEVEL_CONFIGURE_ARGUMENTS=\n")))))))))) + + +(define-public repro-gcc-4.7 + (package + (inherit gcc-4.7-$ORIGIN) + (source + (origin + (inherit (package-source gcc-4.7-$ORIGIN)) + (patches (append ((compose origin-patches package-source) gcc-4.7) + (search-patches "gcc-5-reproducibility-drop-profile.patch" + ;;"gcc-4-compile-with-gcc-5.patch" + "gcc-4-build-path-prefix-map.patch"))))) + (name "repro-gcc") + (version "4.7.4") + (arguments + (substitute-keyword-arguments (package-arguments gcc-4.7-$ORIGIN) + ((#:phases original-phases) + `(modify-phases ,original-phases + (add-before 'configure 'build-prefix-path + (lambda* (#:key inputs #:allow-other-keys) + (setenv "BUILD_PATH_PREFIX_MAP" + (string-append "gcc" "-" ,version "=" (getcwd))) + (format (current-error-port) + "BUILD_PATH_PREFIX_MAP=~s\n" + (getenv "BUILD_PATH_PREFIX_MAP")))))))))) + +(define-public repr2-gcc-4.7 + (package + (inherit repro-gcc-4.7) + (name "repr2-gcc"))) + +(define-public repro-gcc-7 + (package + (inherit gcc-4.7-$ORIGIN) + (source + (origin + (inherit (package-source gcc-7)) + (patches (append (search-patches "gcc-5-reproducibility-drop-profile.patch" + "gcc-7-build-path-prefix-map.patch") + ((compose origin-patches package-source) gcc-7))))) + (name "repro-gcc") + (version "7.2.0") + (arguments + (substitute-keyword-arguments (package-arguments gcc-4.7-$ORIGIN) + ((#:phases original-phases) + `(modify-phases ,original-phases + (add-before 'configure 'build-prefix-path + (lambda* (#:key inputs #:allow-other-keys) + (setenv "BUILD_PATH_PREFIX_MAP" + (string-append "gcc" "-" ,version "=" (getcwd))) + (format (current-error-port) + "BUILD_PATH_PREFIX_MAP=~s\n" + (getenv "BUILD_PATH_PREFIX_MAP")))))))))) + +(define-public repr2-gcc-7 + (package + (inherit repro-gcc-7) + (name "repr2-gcc"))) + +(define-public clang-gcc-7 + (package + (inherit repro-gcc-7) + (name "clang-gcc") + (native-inputs `(("clang" ,clang) + ,@(alist-delete "gcc" (package-native-inputs gcc-7)))) + (arguments + (substitute-keyword-arguments (package-arguments repro-gcc-7) + ((#:phases original-phases) + `(modify-phases ,original-phases + (add-before 'configure 'setenv + (lambda* (#:key inputs #:allow-other-keys) + (let ((clang (assoc-ref inputs "clang"))) + (setenv "CC" (string-append clang "/bin/clang")) + (setenv "CXX "(string-append clang "/bin/clang++"))))))))))) + +(define-public gcc-ddc-gcc+clang + (package + (name "gcc-ddc") + (version "4.7.4") + (source #f) + (native-inputs `(;;("clang-gcc" ,clang-gcc-7) + ("clang-gcc" ,repr2-gcc-4.7) + ("gcc" ,repro-gcc-4.7) + + ("diffoscope" ,diffoscope) + ("acl" ,acl) ; For diffoscope + ("binutils" ,binutils) + ("coreutils" ,coreutils) + ("diffutils" ,diffutils) + ("xxd" ,xxd))) + (build-system trivial-build-system) + (arguments + `(#:modules ((guix build utils)) + #:builder + (begin + (use-modules (guix build utils)) + (let* ((diffoscope (assoc-ref %build-inputs "diffoscope")) + (acl (assoc-ref %build-inputs "acl")) + (binutils (assoc-ref %build-inputs "binutils")) + (coreutils (assoc-ref %build-inputs "coreutils")) + (diffutils (assoc-ref %build-inputs "diffutils")) + (xxd (assoc-ref %build-inputs "xxd")) + (gcc (assoc-ref %build-inputs "gcc")) + (gcc/bin/gcc (string-append gcc "/bin/gcc")) + (clang-gcc (assoc-ref %build-inputs "clang-gcc")) + (clang-gcc/bin/gcc (string-append clang-gcc "/bin/gcc"))) + ;; diffoscope.exc.RequiredToolNotFound: cmp + ;; diffoscope.comparators.directory: 'stat' not found! Is PATH wrong? + ;; FileNotFoundError: [Errno 2] No such file or directory: 'readelf' + ;; diffoscope.comparators.directory: Unable to find 'getfacl' + (setenv "PATH" (string-append diffoscope "/bin:" + + acl "/acl:" + binutils "/bin:" + coreutils "/bin:" + diffutils "/bin:" + xxd "/bin:")) + ;; ?? xxd not available in path. Falling back to Python hexlify. + ;; diffoscope.presenters.formats: Console is unable to print Unicode characters. Set e.g. PYTHONIOENCODING=utf-8 + (setenv "PYTHONIOENCODING" "utf-8") + ;; for starters, only check the gcc binary + (zero? (system* "diffoscope" gcc/bin/gcc clang-gcc/bin/gcc)) + ;;(zero? (system* "diffoscope" gcc clang-gcc)) + )))) + (synopsis "test gcc+clang DDC property for gcc-7.2.0") + (description "gcc-dcc is a meta-package that depends on repro-gcc-7.2.0 +and on clang-gcc-7.2.0 (the same GCC built with clang). The builder checks if +both gcc's are bit-for-bit identical and fails if they differ.") + (home-page "http://bootstrappable.org") + (license gpl3+))) diff --git a/gnu/packages/patches/gcc-4-build-path-prefix-map.patch b/gnu/packages/patches/gcc-4-build-path-prefix-map.patch new file mode 100644 index 000000000..738a59c8d --- /dev/null +++ b/gnu/packages/patches/gcc-4-build-path-prefix-map.patch @@ -0,0 +1,780 @@ +From 1bfd15d4f07f7d76ec399b1a45bc16c404f1465a Mon Sep 17 00:00:00 2001 +From: Jan Nieuwenhuizen <jann...@gnu.org> +Date: Mon, 6 Nov 2017 07:35:24 +0100 +Subject: [PATCH] backport build path prefix map. WIP + +--- + gcc/c-family/c-common.c | 20 ++ + gcc/c-family/c-common.h | 5 + + gcc/c-family/c-lex.c | 1 + + gcc/cp/cfns.gperf | 2 +- + gcc/debug.h | 1 + + gcc/final.c | 54 +++-- + gcc/opts-global.c | 2 + + gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-1.c | 11 + + gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-2.c | 12 ++ + .../gcc.dg/debug/dwarf2/build_path_prefix_map-1.c | 9 + + .../gcc.dg/debug/dwarf2/build_path_prefix_map-2.c | 8 + + include/prefix-map.h | 108 ++++++++++ + libcpp/include/cpplib.h | 3 + + libcpp/init.c | 3 + + libcpp/internal.h | 5 + + libcpp/macro.c | 16 ++ + libiberty/Makefile.in | 14 +- + libiberty/prefix-map.c | 226 +++++++++++++++++++++ + 18 files changed, 467 insertions(+), 33 deletions(-) + create mode 100644 gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-1.c + create mode 100644 gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-2.c + create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-1.c + create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-2.c + create mode 100644 include/prefix-map.h + create mode 100644 libiberty/prefix-map.c + +diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c +index 82a2b8d6c..b4ca42b73 100644 +--- a/gcc/c-family/c-common.c ++++ b/gcc/c-family/c-common.c +@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see + + #include "config.h" + #include "system.h" ++#include "prefix-map.h" + #include "coretypes.h" + #include "tm.h" + #include "intl.h" +@@ -10736,4 +10737,23 @@ build_userdef_literal (tree suffix_id, tree value, tree num_string) + return literal; + } + ++/* 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. */ ++ ++struct prefix_map ** ++cb_get_build_path_prefix_map (cpp_reader *pfile ATTRIBUTE_UNUSED) ++{ ++ struct prefix_map **map = XCNEW (struct 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" +diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h +index 835b13bbc..7591bd6b0 100644 +--- a/gcc/c-family/c-common.h ++++ b/gcc/c-family/c-common.h +@@ -1116,4 +1116,9 @@ struct GTY(()) tree_userdef_literal { + + extern tree build_userdef_literal (tree suffix_id, tree value, tree num_string); + ++/* 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 struct prefix_map **cb_get_build_path_prefix_map (cpp_reader *pfile); ++ + #endif /* ! GCC_C_COMMON_H */ +diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c +index 7e2029ce0..8cef0f2a8 100644 +--- a/gcc/c-family/c-lex.c ++++ b/gcc/c-family/c-lex.c +@@ -84,6 +84,7 @@ init_c_lex (void) + cb->def_pragma = cb_def_pragma; + cb->valid_pch = c_common_valid_pch; + cb->read_pch = c_common_read_pch; ++ 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 +diff --git a/gcc/cp/cfns.gperf b/gcc/cp/cfns.gperf +index ba0c487a6..0f9a79ac7 100644 +--- a/gcc/cp/cfns.gperf ++++ b/gcc/cp/cfns.gperf +@@ -26,7 +26,7 @@ __inline + __attribute__ ((__gnu_inline__)) + #endif + #endif +-const char * libc_name_p (const char *, unsigned int); ++inline const char * libc_name_p (const char *, unsigned int); + %} + %% + # The standard C library functions, for feeding to gperf; the result is used +diff --git a/gcc/debug.h b/gcc/debug.h +index 828ede230..1f9a69e56 100644 +--- a/gcc/debug.h ++++ b/gcc/debug.h +@@ -187,6 +187,7 @@ extern void dwarf2out_switch_text_section (void); + + 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. */ + +diff --git a/gcc/final.c b/gcc/final.c +index 718caf154..d72dec2e5 100644 +--- a/gcc/final.c ++++ b/gcc/final.c +@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see + #include "config.h" + #include "system.h" + #include "coretypes.h" ++#include "prefix-map.h" + #include "tm.h" + + #include "tree.h" +@@ -1435,22 +1436,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. */ +-typedef 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; +-} debug_prefix_map; +- +-/* Linked list of such structures. */ +-debug_prefix_map *debug_prefix_maps; + ++/* Linked list of `struct prefix_map'. */ ++static struct 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. */ +@@ -1458,7 +1446,7 @@ debug_prefix_map *debug_prefix_maps; + void + add_debug_prefix_map (const char *arg) + { +- debug_prefix_map *map; ++ struct prefix_map *map; + const char *p; + + p = strchr (arg, '='); +@@ -1467,7 +1455,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 (struct prefix_map); + map->old_prefix = xstrndup (arg, p - arg); + map->old_len = p - arg; + p++; +@@ -1477,28 +1465,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; ++ const char *name = prefix_map_remap_alloca (debug_prefix_maps, filename); + +- for (map = debug_prefix_maps; map; map = map->next) +- if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0) +- break; +- if (!map) ++ 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. */ +diff --git a/gcc/opts-global.c b/gcc/opts-global.c +index b93d56fcd..f3c653bc1 100644 +--- a/gcc/opts-global.c ++++ b/gcc/opts-global.c +@@ -322,6 +322,8 @@ handle_common_deferred_options (void) + if (flag_dump_all_passed) + enable_rtl_dump_file (); + ++ add_debug_prefix_map_from_envvar (); ++ + FOR_EACH_VEC_ELT (cl_deferred_option, vec, i, opt) + { + switch (opt->opt_index) +diff --git a/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-1.c b/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-1.c +new file mode 100644 +index 000000000..960503813 +--- /dev/null ++++ b/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; ++} +diff --git a/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-2.c b/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-2.c +new file mode 100644 +index 000000000..4b0aacd5e +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-2.c +@@ -0,0 +1,12 @@ ++/* __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 } */ ++/* { dg-set-compiler-env-var BUILD_PATH_PREFIX_MAP } */ ++ ++int ++main () ++{ ++ if (__builtin_strcmp (__FILE__, "./gcc.dg/cpp/build_path_prefix_map-2.c") == 0) ++ __builtin_abort (); ++ return 0; ++} +diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-1.c b/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-1.c +new file mode 100644 +index 000000000..af2b0ed33 +--- /dev/null ++++ b/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) ++{ ++} +diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-2.c b/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-2.c +new file mode 100644 +index 000000000..4c66bf521 +--- /dev/null ++++ b/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/include/prefix-map.h b/include/prefix-map.h +new file mode 100644 +index 000000000..f8edb547e +--- /dev/null ++++ b/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 */ +diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h +index bf59d0162..082770d04 100644 +--- a/libcpp/include/cpplib.h ++++ b/libcpp/include/cpplib.h +@@ -541,6 +541,9 @@ struct cpp_callbacks + + /* Callback that can change a user builtin into normal macro. */ + bool (*user_builtin_macro) (cpp_reader *, cpp_hashnode *); ++ ++ /* Callback to parse BUILD_PATH_PREFIX_MAP from environment. */ ++ struct prefix_map **(*get_build_path_prefix_map) (cpp_reader *); + }; + + #ifdef VMS +diff --git a/libcpp/init.c b/libcpp/init.c +index 5fa82ca9c..270d42b95 100644 +--- a/libcpp/init.c ++++ b/libcpp/init.c +@@ -231,6 +231,9 @@ cpp_create_reader (enum c_lang lang, hash_table *table, + /* Do not force token locations by default. */ + pfile->forced_token_location_p = NULL; + ++ /* 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); + +diff --git a/libcpp/internal.h b/libcpp/internal.h +index 5b3731bba..5b09bf1a4 100644 +--- a/libcpp/internal.h ++++ b/libcpp/internal.h +@@ -485,6 +485,11 @@ struct cpp_reader + const unsigned char *date; + const unsigned char *time; + ++ /* 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; +diff --git a/libcpp/macro.c b/libcpp/macro.c +index 54de3e3fc..6cdd1e5d3 100644 +--- a/libcpp/macro.c ++++ b/libcpp/macro.c +@@ -28,6 +28,7 @@ along with this program; see the file COPYING3. If not see + #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 +@@ -271,7 +272,17 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node) + unsigned int len; + const char *name; + uchar *buf; ++ struct 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); +@@ -281,6 +292,11 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node) + 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; +diff --git a/libiberty/Makefile.in b/libiberty/Makefile.in +index 5280bc158..bc098496a 100644 +--- a/libiberty/Makefile.in ++++ b/libiberty/Makefile.in +@@ -143,6 +143,7 @@ CFILES = alloca.c argv.c asprintf.c atexit.c \ + 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 \ + safe-ctype.c setenv.c setproctitle.c sha1.c sigsetmask.c \ + simple-object.c simple-object-coff.c simple-object-elf.c \ +@@ -179,6 +180,7 @@ REQUIRED_OFILES = \ + ./partition.$(objext) ./pexecute.$(objext) ./physmem.$(objext) \ + ./pex-common.$(objext) ./pex-one.$(objext) \ + ./@pexecute@.$(objext) \ ++ ./prefix-map.$(objext) \ + ./safe-ctype.$(objext) \ + ./simple-object.$(objext) ./simple-object-coff.$(objext) \ + ./simple-object-elf.$(objext) ./simple-object-mach-o.$(objext) \ +@@ -887,7 +889,8 @@ $(CONFIGURED_OFILES): stamp-picdir + $(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)/libiberty.h \ ++ $(srcdir)/pex-common.h + if [ x"$(PICFLAG)" != x ]; then \ + $(COMPILE.c) $(PICFLAG) $(srcdir)/pex-unix.c -o pic/$@; \ + else true; fi +@@ -914,6 +917,15 @@ $(CONFIGURED_OFILES): stamp-picdir + 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/$@; \ +diff --git a/libiberty/prefix-map.c b/libiberty/prefix-map.c +new file mode 100644 +index 000000000..ecb408856 +--- /dev/null ++++ b/libiberty/prefix-map.c +@@ -0,0 +1,226 @@ ++/* 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) ++{ ++ size_t len; ++ ++ for (; map; map = map->next) ++ { ++ 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; ++} ++ ++/* 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) ++{ ++ char *dest; ++ for (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; ++} +-- +Jan Nieuwenhuizen <jann...@gnu.org> | GNU LilyPond http://lilypond.org +Freelance IT http://JoyofSource.com | Avatar® http://AvatarAcademy.com + diff --git a/gnu/packages/patches/gcc-4-cfns-fix-mismatch-in-gnu_inline-attributes.patch b/gnu/packages/patches/gcc-4-cfns-fix-mismatch-in-gnu_inline-attributes.patch new file mode 100644 index 000000000..861cd4857 --- /dev/null +++ b/gnu/packages/patches/gcc-4-cfns-fix-mismatch-in-gnu_inline-attributes.patch @@ -0,0 +1,65 @@ +Taken from https://gcc.gnu.org/cgi-bin/get-raw-msg?listname=gcc-patches&date=2016-01&msgid=1451802493-17406-1-git-send-email-vapier%40gentoo.org + +Since the 3.0.3 release of gperf (made in May 2007), the generated func +has had the gnu_inline attribute applied to it. The gcc source however +has not been updated to include that which has lead to a mismatch. + +In practice, this hasn't been an issue for two reasons: +(1) Before gcc-5, the default standard was (gnu) C89, and gcc does not +warn or throw an error in this mode. +(2) Starting with gcc-4.8, the compiler driver used to build gcc was +changed to C++, and g++ does not warn or throw an error in this mode. + +This error does show up though when using gcc-5 to build gcc-4.7 or +older as then the default is (gnu) C11 and the C compiler driver is +used. That failure looks like: +In file included from .../gcc-4.7.4/gcc/cp/except.c:990:0: +cfns.gperf: At top level: +cfns.gperf:101:1: error: 'gnu_inline' attribute present on 'libc_name_p' +cfns.gperf:26:14: error: but not here + +Whether the compiler should always emit this error regardless of the +active standard or compiler driver is debatable (I think it should be +consistent -- either always do it or never do it). + +2015-08-06 Mike Frysinger <vap...@gentoo.org> + + * cfns.gperf [__GNUC__, __GNUC_STDC_INLINE__]: Apply the + __gnu_inline__ attribute. + * cfns.h: Regenerated. +--- + gcc/cp/cfns.gperf | 3 +++ + gcc/cp/cfns.h | 3 +++ + 2 files changed, 6 insertions(+) + +diff --git a/gcc/cp/cfns.gperf b/gcc/cp/cfns.gperf +index 68acd3d..953262f 100644 +--- a/gcc/cp/cfns.gperf ++++ b/gcc/cp/cfns.gperf +@@ -22,6 +22,9 @@ __inline + static unsigned int hash (const char *, unsigned int); + #ifdef __GNUC__ + __inline ++#ifdef __GNUC_STDC_INLINE__ ++__attribute__ ((__gnu_inline__)) ++#endif + #endif + const char * libc_name_p (const char *, unsigned int); + %} +diff --git a/gcc/cp/cfns.h b/gcc/cp/cfns.h +index 1c6665d..6d00c0e 100644 +--- a/gcc/cp/cfns.h ++++ b/gcc/cp/cfns.h +@@ -53,6 +53,9 @@ __inline + static unsigned int hash (const char *, unsigned int); + #ifdef __GNUC__ + __inline ++#ifdef __GNUC_STDC_INLINE__ ++__attribute__ ((__gnu_inline__)) ++#endif + #endif + const char * libc_name_p (const char *, unsigned int); + /* maximum key range = 391, duplicates = 0 */ +-- +2.6.2 + diff --git a/gnu/packages/patches/gcc-5-reproducibility-drop-profile.patch b/gnu/packages/patches/gcc-5-reproducibility-drop-profile.patch new file mode 100644 index 000000000..a3974ad8d --- /dev/null +++ b/gnu/packages/patches/gcc-5-reproducibility-drop-profile.patch @@ -0,0 +1,36 @@ +Courtesy "Bernhard M. Wiedemann" <bernhard...@lsmod.de> + +Removing -fprofile-generate, -fprofile-use makes gcc build bit-for-bit reproducible. + +diff -purN gcc-5.4.0.orig/Makefile.in gcc-5.4.0/Makefile.in +--- gcc-5.4.0.orig/Makefile.in 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-5.4.0/Makefile.in 2017-11-03 15:34:56.415033525 +0100 +@@ -502,10 +502,10 @@ STAGE1_CONFIGURE_FLAGS = --disable-inter + --disable-coverage --enable-languages="$(STAGE1_LANGUAGES)" \ + --disable-build-format-warnings + +-STAGEprofile_CFLAGS = $(STAGE2_CFLAGS) -fprofile-generate ++STAGEprofile_CFLAGS = $(STAGE2_CFLAGS) + STAGEprofile_TFLAGS = $(STAGE2_TFLAGS) + +-STAGEfeedback_CFLAGS = $(STAGE3_CFLAGS) -fprofile-use ++STAGEfeedback_CFLAGS = $(STAGE3_CFLAGS) + STAGEfeedback_TFLAGS = $(STAGE3_TFLAGS) + + do-compare = @do_compare@ +diff -purN gcc-5.4.0.orig/Makefile.tpl gcc-5.4.0/Makefile.tpl +--- gcc-5.4.0.orig/Makefile.tpl 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-5.4.0/Makefile.tpl 2017-11-03 15:34:27.146557384 +0100 +@@ -455,10 +455,10 @@ STAGE1_CONFIGURE_FLAGS = --disable-inter + --disable-coverage --enable-languages="$(STAGE1_LANGUAGES)" \ + --disable-build-format-warnings + +-STAGEprofile_CFLAGS = $(STAGE2_CFLAGS) -fprofile-generate ++STAGEprofile_CFLAGS = $(STAGE2_CFLAGS) + STAGEprofile_TFLAGS = $(STAGE2_TFLAGS) + +-STAGEfeedback_CFLAGS = $(STAGE3_CFLAGS) -fprofile-use ++STAGEfeedback_CFLAGS = $(STAGE3_CFLAGS) + STAGEfeedback_TFLAGS = $(STAGE3_TFLAGS) + + do-compare = @do_compare@ diff --git a/gnu/packages/patches/gcc-7-build-path-prefix-map.patch b/gnu/packages/patches/gcc-7-build-path-prefix-map.patch new file mode 100644 index 000000000..098cbbd41 --- /dev/null +++ b/gnu/packages/patches/gcc-7-build-path-prefix-map.patch @@ -0,0 +1,934 @@ +This is the combined BUILD_PATH_PREFIX_MAP patch set. Only using this here as +a proof of concept to reach bit-by-bit reproducibility for diverse double +compilation. It will be reworked to meet the needs of GNU GCC upstream. + +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 <infini...@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 <infini...@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 <infini...@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 <infini...@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/include/prefix-map.h +=================================================================== +--- /dev/null ++++ b/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/libiberty/Makefile.in +=================================================================== +--- a/libiberty/Makefile.in ++++ b/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@.$(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/libiberty/prefix-map.c +=================================================================== +--- /dev/null ++++ b/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/gcc/debug.h +=================================================================== +--- a/gcc/debug.h ++++ b/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/gcc/final.c +=================================================================== +--- a/gcc/final.c ++++ b/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/gcc/opts-global.c +=================================================================== +--- a/gcc/opts-global.c ++++ b/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/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-1.c +=================================================================== +--- /dev/null ++++ b/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/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-2.c +=================================================================== +--- /dev/null ++++ b/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) ++{ ++} +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 <dh...@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-07-21 Ximin Luo <infini...@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-07-21 Ximin Luo <infini...@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-07-21 Ximin Luo <infini...@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/gcc/c-family/c-common.c +=================================================================== +--- a/gcc/c-family/c-common.c ++++ b/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" +@@ -7905,6 +7906,25 @@ 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; ++} ++ + /* Callback for libcpp for offering spelling suggestions for misspelled + directives. GOAL is an unrecognized string; CANDIDATES is a + NULL-terminated array of candidate strings. Return the closest +Index: b/gcc/c-family/c-common.h +=================================================================== +--- a/gcc/c-family/c-common.h ++++ b/gcc/c-family/c-common.h +@@ -1084,6 +1084,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); ++ + /* Callback for libcpp for offering spelling suggestions for misspelled + directives. */ + extern const char *cb_get_suggestion (cpp_reader *, const char *, +Index: b/gcc/c-family/c-lex.c +=================================================================== +--- a/gcc/c-family/c-lex.c ++++ b/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; + cb->get_suggestion = cb_get_suggestion; + + /* Set the debug callbacks if we can use them. */ +Index: b/libcpp/include/cpplib.h +=================================================================== +--- a/libcpp/include/cpplib.h ++++ b/libcpp/include/cpplib.h +@@ -607,6 +607,9 @@ 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 *); ++ + /* Callback for providing suggestions for misspelled directives. */ + const char *(*get_suggestion) (cpp_reader *, const char *, const char *const *); + +Index: b/libcpp/init.c +=================================================================== +--- a/libcpp/init.c ++++ b/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/libcpp/internal.h +=================================================================== +--- a/libcpp/internal.h ++++ b/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/libcpp/macro.c +=================================================================== +--- a/libcpp/macro.c ++++ b/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/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-1.c +=================================================================== +--- /dev/null ++++ b/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/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-2.c +=================================================================== +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-2.c +@@ -0,0 +1,12 @@ ++/* __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 } */ ++/* { dg-set-compiler-env-var BUILD_PATH_PREFIX_MAP } */ ++ ++int ++main () ++{ ++ if (__builtin_strcmp (__FILE__, "./gcc.dg/cpp/build_path_prefix_map-2.c") == 0) ++ __builtin_abort (); ++ return 0; ++} +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 <infini...@pwned.gg> + + * doc/invoke.texi (Environment Variables): Document form and behaviour + of BUILD_PATH_PREFIX_MAP. + +libiberty/ChangeLog: + +2017-03-27 Ximin Luo <infini...@pwned.gg> + + * prefix-map.c: When remapping paths, only match whole path components. + +Index: b/libiberty/prefix-map.c +=================================================================== +--- a/libiberty/prefix-map.c ++++ b/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; + } -- Jan Nieuwenhuizen <jann...@gnu.org> | GNU LilyPond http://lilypond.org Freelance IT http://JoyofSource.com | Avatar® http://AvatarAcademy.com
$ ./pre-inst-env guix build gcc-ddc@4.7.4 process 11900 acquired build slot '/var/guix/offload/192.168.32.121/0' load on machine '192.168.32.121' is 0.0 (normalized: 0.0) process 11900 acquired build slot '/var/guix/offload/192.168.32.122/0' load on machine '192.168.32.122' is 0.07 (normalized: 0.023333333333333334) @ build-started /gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv - x86_64-linux /var/log/guix/drvs/sb//9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv.bz2 sending 0 store items to '192.168.32.121'... offloading '/gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv' to '192.168.32.121'... @ build-remote /gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv 192.168.32.121 substitute: updating list of substitutes from 'http://guix2.oban.verum.com:8181'... 100.0% substitute: updating list of substitutes from 'https://mirror.guixsd.org'... 100.0% @ build-started /gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv - x86_64-linux /var/log/guix/drvs/sb//9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv.bz2 --- /gnu/store/zw672zcmykdwzm4x7l098hb94c34ak85-repro-gcc-4.7.4/bin/gcc +++ /gnu/store/jhcf91y94nfnr5hmmxj7jn3whq1gm009-repr2-gcc-4.7.4/bin/gcc ??? objdump --line-numbers --disassemble --demangle --section=.text {} ? @@ -363,31 +363,31 @@ ? 402da3: 0f 84 50 0e 00 00 je 403bf9 <main+0x1429> ? 402da9: 4c 8b 25 a0 51 28 00 mov 0x2851a0(%rip),%r12 ? 402db0: 4c 89 e7 mov %r12,%rdi ? 402db3: e8 08 f5 ff ff callq 4022c0 <strlen@plt> ? 402db8: 48 83 c0 68 add $0x68,%rax ? 402dbc: 49 b8 2f 67 6e 75 2f movabs $0x6f74732f756e672f,%r8 ? 402dc3: 73 74 6f ? - 402dc6: 49 b9 72 65 2f 7a 77 movabs $0x323736777a2f6572,%r9 ? - 402dcd: 36 37 32 ? + 402dc6: 49 b9 72 65 2f 6a 68 movabs $0x396663686a2f6572,%r9 ? + 402dcd: 63 66 39 ? 402dd0: 48 83 e0 f0 and $0xfffffffffffffff0,%rax ? - 402dd4: 48 bf 6b 38 35 2d 72 movabs $0x727065722d35386b,%rdi ? + 402dd4: 48 bf 30 30 39 2d 72 movabs $0x727065722d393030,%rdi ? 402ddb: 65 70 72 ? - 402dde: 48 ba 6d 34 78 37 6c movabs $0x3839306c3778346d,%rdx ? - 402de5: 30 39 38 ? + 402dde: 48 ba 35 68 6d 6d 78 movabs $0x6a376a786d6d6835,%rdx ? + 402de5: 6a 37 6a ? 402de8: 48 29 c4 sub %rax,%rsp ? - 402deb: 48 be 68 62 39 34 63 movabs $0x6134336334396268,%rsi ? - 402df2: 33 34 61 ? - 402df5: 48 b8 7a 63 6d 79 6b movabs $0x7a77646b796d637a,%rax ? - 402dfc: 64 77 7a ? + 402deb: 48 be 6e 33 77 68 71 movabs $0x6d6731716877336e,%rsi ? + 402df2: 31 67 6d ? + 402df5: 48 b8 31 79 39 34 6e movabs $0x726e666e34397931,%rax ? + 402dfc: 66 6e 72 ? 402dff: 48 8d 5c 24 0f lea 0xf(%rsp),%rbx ? 402e04: 48 83 e3 f0 and $0xfffffffffffffff0,%rbx ? 402e08: 4c 89 03 mov %r8,(%rbx) ? 402e0b: 4c 89 4b 08 mov %r9,0x8(%rbx) ? - 402e0f: 49 b8 6f 2d 67 63 63 movabs $0x2e342d6363672d6f,%r8 ? + 402e0f: 49 b8 32 2d 67 63 63 movabs $0x2e342d6363672d32,%r8 ? 402e16: 2d 34 2e ? 402e19: 49 b9 37 2e 34 2f 6c movabs $0x2f62696c2f342e37,%r9 ? 402e20: 69 62 2f ? 402e23: 48 89 7b 28 mov %rdi,0x28(%rbx) ? 402e27: 48 8d 7b 44 lea 0x44(%rbx),%rdi ? 402e2b: 48 89 53 18 mov %rdx,0x18(%rbx) ? 402e2f: 48 89 73 20 mov %rsi,0x20(%rbx) ??? readelf --wide --decompress --hex-dump=.rodata {} ? @@ -48,27 +48,27 @@ ? 0x0043e990 653d2a3a 253e6d74 756e653d 6e617469 e=*:%>mtune=nati ? 0x0043e9a0 76652025 3a6c6f63 616c5f63 70755f64 ve %:local_cpu_d ? 0x0043e9b0 65746563 74287475 6e65297d 7d20257b etect(tune)}} %{ ? 0x0043e9c0 6d74756e 653d6e61 74697665 3a253e6d mtune=native:%>m ? 0x0043e9d0 74756e65 3d6e6174 69766520 253a6c6f tune=native %:lo ? 0x0043e9e0 63616c5f 6370755f 64657465 63742874 cal_cpu_detect(t ? 0x0043e9f0 756e6529 7d000000 2f676e75 2f73746f ? - 0x0043ea00 72652f7a 77363732 7a636d79 6b64777a ? - 0x0043ea10 6d347837 6c303938 68623934 63333461 ? - 0x0043ea20 6b38352d 72657072 6f2d6763 632d342e ? + 0x0043ea00 72652f6a 68636639 31793934 6e666e72 re/jhcf91y94nfnr ? + 0x0043ea10 35686d6d 786a376a 6e337768 7131676d 5hmmxj7jn3whq1gm ? + 0x0043ea20 3030392d 72657072 322d6763 632d342e 009-repr2-gcc-4. ? 0x0043ea30 372e342f 6c69622f 6763632f 00000000 7.4/lib/gcc/.... ? - 0x0043ea40 2f676e75 2f73746f 72652f7a 77363732 /gnu/store/zw672 ? - 0x0043ea50 7a636d79 6b64777a 6d347837 6c303938 zcmykdwzm4x7l098 ? - 0x0043ea60 68623934 63333461 6b38352d 72657072 hb94c34ak85-repr ? - 0x0043ea70 6f2d6763 632d342e 372e342f 6c696265 o-gcc-4.7.4/libe ? + 0x0043ea40 2f676e75 2f73746f 72652f6a 68636639 /gnu/store/jhcf9 ? + 0x0043ea50 31793934 6e666e72 35686d6d 786a376a 1y94nfnr5hmmxj7j ? + 0x0043ea60 6e337768 7131676d 3030392d 72657072 n3whq1gm009-repr ? + 0x0043ea70 322d6763 632d342e 372e342f 6c696265 2-gcc-4.7.4/libe ? 0x0043ea80 7865632f 6763632f 00000000 00000000 xec/gcc/........ ? - 0x0043ea90 2f676e75 2f73746f 72652f7a 77363732 ? - 0x0043eaa0 7a636d79 6b64777a 6d347837 6c303938 ? - 0x0043eab0 68623934 63333461 6b38352d 72657072 ? - 0x0043eac0 6f2d6763 632d342e 372e342f 62696e2f ? + 0x0043ea90 2f676e75 2f73746f 72652f6a 68636639 /gnu/store/jhcf9 ? + 0x0043eaa0 31793934 6e666e72 35686d6d 786a376a 1y94nfnr5hmmxj7j ? + 0x0043eab0 6e337768 7131676d 3030392d 72657072 n3whq1gm009-repr ? + 0x0043eac0 322d6763 632d342e 372e342f 62696e2f 2-gcc-4.7.4/bin/ ? 0x0043ead0 00000000 00000000 2d706970 65206967 ........-pipe ig ? 0x0043eae0 6e6f7265 64206265 63617573 65202d73 nored because -s ? 0x0043eaf0 6176652d 74656d70 73207370 65636966 ave-temps specif ? 0x0043eb00 69656400 00000000 253c2d78 20257325 ied.....%<-x %s% ? 0x0043eb10 3e206166 74657220 6c617374 20696e70 > after last inp ? 0x0043eb20 75742066 696c6520 68617320 6e6f2065 ut file has no e ? 0x0043eb30 66666563 74000000 25717320 69732061 ffect...%qs is a ? @@ -1553,18 +1553,18 @@ ? 0x004447a0 bffc4000 00000000 f6fd4000 00000000 ..@.......@..... ? 0x004447b0 bffc4000 00000000 bffc4000 00000000 ..@.......@..... ? 0x004447c0 bffc4000 00000000 f6fd4000 00000000 ..@.......@..... ? 0x004447d0 00000000 00000000 00000000 00000000 ................ ? 0x004447e0 01000000 02000000 03000000 0e000000 ................ ? 0x004447f0 0e000000 0e000000 0e000000 0e000000 ................ ? 0x00444800 0e000000 0e000000 0e000000 07000000 ................ ? - 0x00444810 2f676e75 2f73746f 72652f7a 77363732 /gnu/store/zw672 ? - 0x00444820 7a636d79 6b64777a 6d347837 6c303938 zcmykdwzm4x7l098 ? - 0x00444830 68623934 63333461 6b38352d 72657072 hb94c34ak85-repr ? - 0x00444840 6f2d6763 632d342e 372e3400 5f524f4f o-gcc-4.7.4._ROO ? + 0x00444810 2f676e75 2f73746f 72652f6a 68636639 /gnu/store/jhcf9 ? + 0x00444820 31793934 6e666e72 35686d6d 786a376a 1y94nfnr5hmmxj7j ? + 0x00444830 6e337768 7131676d 3030392d 72657072 n3whq1gm009-repr ? + 0x00444840 322d6763 632d342e 372e3400 5f524f4f 2-gcc-4.7.4._ROO ? 0x00444850 54002e2e 2f2e2e2f 6763632d 342e372e T.../../gcc-4.7. ? 0x00444860 342f6763 632f7061 72616d73 2e630069 4/gcc/params.c.i ? 0x00444870 6e76616c 69642070 6172616d 65746572 nvalid parameter ? 0x00444880 20257173 00707265 64696374 61626c65 %qs.predictable ? 0x00444890 2d627261 6e63682d 6f757463 6f6d6500 -branch-outcome. ? 0x004448a0 6d61782d 696e6c69 6e652d69 6e736e73 max-inline-insns ? 0x004448b0 2d73696e 676c6500 6d61782d 696e6c69 -single.max-inli builder for `/gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv' failed with exit code 1 @ build-failed /gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv - 1 builder for `/gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv' failed with exit code 1 derivation '/gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv' offloaded to '192.168.32.121' failed: build of `/gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv' failed @ build-failed /gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv - 1 builder for `/gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv' failed with exit code 100 guix build: error: build failed: build of `/gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv' failed
-- Jan Nieuwenhuizen <jann...@gnu.org> | GNU LilyPond http://lilypond.org Freelance IT http://JoyofSource.com | Avatar® http://AvatarAcademy.com