Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In practice it quickly exhausts argument lengtth limit due to `gcc`
In practice it quickly exhausts argument length limit due to `gcc`

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Proposed the fix as #268923

deficiency: https://gcc.gnu.org/PR111527

Until it;s fixed let's hardcode header mangling if $NIX_STORE variable
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Until it;s fixed let's hardcode header mangling if $NIX_STORE variable
Until it's fixed let's hardcode header mangling if $NIX_STORE variable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Proposed the fix as #268923

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 */

Original file line number Diff line number Diff line change
@@ -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 */


4 changes: 2 additions & 2 deletions pkgs/development/compilers/gcc/patches/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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 ];
Expand Down