diff options
author | Sergei Trofimovich <slyich@gmail.com> | 2023-09-23 20:17:11 +0100 |
---|---|---|
committer | Sergei Trofimovich <slyich@gmail.com> | 2023-10-04 21:16:13 +0100 |
commit | 537176760c8fab063ba1389d83b7b2da3857ee99 (patch) | |
tree | 46c5c8618871e7a26a8a69eefaa21429a3451c62 /pkgs/development/compilers/gcc | |
parent | 9155f8dc6e9bfbe77a8552735ae0b9d74a72714f (diff) |
gcc12, gcc13: always mangle __FILE__ into invalid store path
Without the change `__FILE__` used in static inline functions in headers embed paths to header files into executable images. For local headers it's not a problem, but for headers in `/nix/store` this causes `-dev` inputs to be retained in runtime closure. Typical examples are `nix` -> `nlonhmann_json` and `pipewire` -> `lttng-ust.dev`. Ideally we would like to use `-fmacro-prefix-map=` feature of `gcc` as: -fmacro-prefix-map=/nix/store/$hash1-nlohmann-json-ver=/nix/store/eeee.eee-nlohmann-json-ver -fmacro-prefix-map=/nix/... In practice it quickly exhausts argument lengtth limit due to `gcc` deficiency: https://gcc.gnu.org/PR111527 Until it;s fixed let's hardcode header mangling if $NIX_STORE variable is present in the environment. Tested as: $ printf "# 0 \"/nix/store/01234567890123456789012345678901-pppppp-vvvvvvv\" \nconst char * f(void) { return __FILE__; }" | NIX_STORE=/nix/store ./gcc/xgcc -Bgcc -x c - -S -o - ... .string "/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-pppppp-vvvvvvv" ... Mangled successfully.
Diffstat (limited to 'pkgs/development/compilers/gcc')
3 files changed, 171 insertions, 2 deletions
diff --git a/pkgs/development/compilers/gcc/patches/12/mangle-NIX_STORE-in-__FILE__.patch b/pkgs/development/compilers/gcc/patches/12/mangle-NIX_STORE-in-__FILE__.patch new file mode 100644 index 0000000000000..d938d67a2d068 --- /dev/null +++ b/pkgs/development/compilers/gcc/patches/12/mangle-NIX_STORE-in-__FILE__.patch @@ -0,0 +1,85 @@ +From b10785c1be469319a09b10bc69db21159b0599ee Mon Sep 17 00:00:00 2001 +From: Sergei Trofimovich <siarheit@google.com> +Date: Fri, 22 Sep 2023 22:41:49 +0100 +Subject: [PATCH] gcc/file-prefix-map.cc: always mangle __FILE__ into invalid + store path + +Without the change `__FILE__` used in static inline functions in headers +embed paths to header files into executable images. For local headers +it's not a problem, but for headers in `/nix/store` this causes `-dev` +inputs to be retained in runtime closure. + +Typical examples are `nix` -> `nlohmann_json` and `pipewire` -> +`lttng-ust.dev`. + +Ideally we would like to use `-fmacro-prefix-map=` feature of `gcc` as: + + -fmacro-prefix-map=/nix/store/$hash1-nlohmann-json-ver=/nix/store/eeee.eee-nlohmann-json-ver + -fmacro-prefix-map=/nix/... + +In practice it quickly exhausts argument lengtth limit due to `gcc` +deficiency: https://gcc.gnu.org/PR111527 + +Until it;s fixed let's hardcode header mangling if $NIX_STORE variable +is present in the environment. + +Tested as: + + $ printf "# 0 \"/nix/store/01234567890123456789012345678901-pppppp-vvvvvvv\" \nconst char * f(void) { return __FILE__; }" | NIX_STORE=/nix/store ./gcc/xgcc -Bgcc -x c - -S -o - + ... + .string "/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-pppppp-vvvvvvv" + ... + +Mangled successfully. +--- a/gcc/file-prefix-map.cc ++++ b/gcc/file-prefix-map.cc +@@ -60,6 +60,9 @@ add_prefix_map (file_prefix_map *&maps, const char *arg, const char *opt) + maps = map; + } + ++/* Forward declaration for a $NIX_STORE remap hack below. */ ++static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map */ ++ + /* Perform user-specified mapping of filename prefixes. Return the + GC-allocated new name corresponding to FILENAME or FILENAME if no + remapping was performed. */ +@@ -76,7 +79,30 @@ remap_filename (file_prefix_map *maps, const char *filename) + if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0) + break; + if (!map) +- return filename; ++ { ++ if (maps == macro_prefix_maps) ++ { ++ /* Remap all fo $NIX_STORE/.{32} paths to ++ * equivalent $NIX_STORE/e{32}. ++ * ++ * That way we avoid argument parameters explosion ++ * and still avoid embedding headers into runtime closure: ++ * https://gcc.gnu.org/PR111527 ++ */ ++ char * nix_store = getenv("NIX_STORE"); ++ size_t nix_store_len = nix_store ? strlen(nix_store) : 0; ++ const char * name = filename; ++ size_t name_len = strlen(name); ++ if (nix_store && name_len >= nix_store_len + 1 + 32 && memcmp(name, nix_store, nix_store_len) == 0) ++ { ++ s = (char *) ggc_alloc_atomic (name_len + 1); ++ memcpy(s, name, name_len + 1); ++ memset(s + nix_store_len + 1, 'e', 32); ++ return s; ++ } ++ } ++ return filename; ++ } + name = filename + map->old_len; + name_len = strlen (name) + 1; + +@@ -90,7 +116,6 @@ remap_filename (file_prefix_map *maps, const char *filename) + ignore it in DW_AT_producer (dwarf2out.cc). */ + + /* Linked lists of file_prefix_map structures. */ +-static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map */ + static file_prefix_map *debug_prefix_maps; /* -fdebug-prefix-map */ + static file_prefix_map *profile_prefix_maps; /* -fprofile-prefix-map */ + diff --git a/pkgs/development/compilers/gcc/patches/13/mangle-NIX_STORE-in-__FILE__.patch b/pkgs/development/compilers/gcc/patches/13/mangle-NIX_STORE-in-__FILE__.patch new file mode 100644 index 0000000000000..57ae2111f020a --- /dev/null +++ b/pkgs/development/compilers/gcc/patches/13/mangle-NIX_STORE-in-__FILE__.patch @@ -0,0 +1,84 @@ +From b10785c1be469319a09b10bc69db21159b0599ee Mon Sep 17 00:00:00 2001 +From: Sergei Trofimovich <siarheit@google.com> +Date: Fri, 22 Sep 2023 22:41:49 +0100 +Subject: [PATCH] gcc/file-prefix-map.cc: always mangle __FILE__ into invalid + store path + +Without the change `__FILE__` used in static inline functions in headers +embed paths to header files into executable images. For local headers +it's not a problem, but for headers in `/nix/store` this causes `-dev` +inputs to be retained in runtime closure. + +Typical examples are `nix` -> `nlohmann_json` and `pipewire` -> +`lttng-ust.dev`. + +Ideally we would like to use `-fmacro-prefix-map=` feature of `gcc` as: + + -fmacro-prefix-map=/nix/store/$hash1-nlohmann-json-ver=/nix/store/eeee.eee-nlohmann-json-ver + -fmacro-prefix-map=/nix/... + +In practice it quickly exhausts argument lengtth limit due to `gcc` +deficiency: https://gcc.gnu.org/PR111527 + +Until it;s fixed let's hardcode header mangling if $NIX_STORE variable +is present in the environment. + +Tested as: + + $ printf "# 0 \"/nix/store/01234567890123456789012345678901-pppppp-vvvvvvv\" \nconst char * f(void) { return __FILE__; }" | NIX_STORE=/nix/store ./gcc/xgcc -Bgcc -x c - -S -o - + ... + .string "/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-pppppp-vvvvvvv" + ... + +Mangled successfully. +--- a/gcc/file-prefix-map.cc ++++ b/gcc/file-prefix-map.cc +@@ -69,6 +69,9 @@ add_prefix_map (file_prefix_map *&maps, const char *arg, const char *opt) + maps = map; + } + ++/* Forward declaration for a $NIX_STORE remap hack below. */ ++static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map */ ++ + /* Perform user-specified mapping of filename prefixes. Return the + GC-allocated new name corresponding to FILENAME or FILENAME if no + remapping was performed. */ +@@ -102,6 +105,29 @@ remap_filename (file_prefix_map *maps, const char *filename) + break; + if (!map) + { ++ if (maps == macro_prefix_maps) ++ { ++ /* Remap all fo $NIX_STORE/.{32} paths to ++ * equivalent $NIX_STORE/e{32}. ++ * ++ * That way we avoid argument parameters explosion ++ * and still avoid embedding headers into runtime closure: ++ * https://gcc.gnu.org/PR111527 ++ */ ++ char * nix_store = getenv("NIX_STORE"); ++ size_t nix_store_len = nix_store ? strlen(nix_store) : 0; ++ const char * name = realname ? realname : filename; ++ size_t name_len = strlen(name); ++ if (nix_store && name_len >= nix_store_len + 1 + 32 && memcmp(name, nix_store, nix_store_len) == 0) ++ { ++ s = (char *) ggc_alloc_atomic (name_len + 1); ++ memcpy(s, name, name_len + 1); ++ memset(s + nix_store_len + 1, 'e', 32); ++ if (realname != filename) ++ free (const_cast <char *> (realname)); ++ return s; ++ } ++ } + if (realname != filename) + free (const_cast <char *> (realname)); + return filename; +@@ -124,7 +150,6 @@ remap_filename (file_prefix_map *maps, const char *filename) + ignore it in DW_AT_producer (gen_command_line_string in opts.cc). */ + + /* Linked lists of file_prefix_map structures. */ +-static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map */ + static file_prefix_map *debug_prefix_maps; /* -fdebug-prefix-map */ + static file_prefix_map *profile_prefix_maps; /* -fprofile-prefix-map */ + + diff --git a/pkgs/development/compilers/gcc/patches/default.nix b/pkgs/development/compilers/gcc/patches/default.nix index 0afc6586511a6..4491c3fde47d5 100644 --- a/pkgs/development/compilers/gcc/patches/default.nix +++ b/pkgs/development/compilers/gcc/patches/default.nix @@ -63,8 +63,8 @@ in ++ optionals (noSysDirs) ( [(if atLeast12 then ./gcc-12-no-sys-dirs.patch else ./no-sys-dirs.patch)] ++ ({ - "13" = [ ./13/no-sys-dirs-riscv.patch ]; - "12" = [ ./no-sys-dirs-riscv.patch ]; + "13" = [ ./13/no-sys-dirs-riscv.patch ./13/mangle-NIX_STORE-in-__FILE__.patch ]; + "12" = [ ./no-sys-dirs-riscv.patch ./12/mangle-NIX_STORE-in-__FILE__.patch ]; "11" = [ ./no-sys-dirs-riscv.patch ]; "10" = [ ./no-sys-dirs-riscv.patch ]; "9" = [ ./no-sys-dirs-riscv-gcc9.patch ]; |