1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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 */
|