about summary refs log tree commit diff
path: root/pkgs/development/compilers/gcc/patches/13/mangle-NIX_STORE-in-__FILE__.patch
blob: 87613c28eb083b0d123423107ed56cc28ab34e59 (plain) (blame)
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
85
86
87
88
89
90
91
92
93
94
95
96
97
From e160a8cd4a704f4b7724df02b62394f677cc4198 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`.

For this reason we want to remove the occurrences of hashes in the
expansion of `__FILE__`. `nuke-references` does it by replacing hashes
by `eeeeee...`. It is handy to be able to invert the transformation to
go back to the original store path. The chosen solution is to make the
hash uppercase:
- it does not trigger runtime references (except for all digit hashes,
  which are unlikely enough)
- it visually looks like a bogus store path
- it is easy to find the original store path if required

Ideally we would like to use `-fmacro-prefix-map=` feature of `gcc` as:

  -fmacro-prefix-map=/nix/store/$hash1-nlohmann-json-ver=/nix/store/$HASH1-nlohmann-json-ver
  -fmacro-prefix-map=/nix/...

In practice it quickly exhausts argument length 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/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-pppppp-vvvvvvv\" \nconst char * f(void) { return __FILE__; }" | NIX_STORE=/nix/store ./gcc/xgcc -Bgcc -x c - -S -o -
    ...
    .string "/nix/store/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-pppppp-vvvvvvv"
    ...

Mangled successfully.

To reverse the effect of the mangle use new `NIX_GCC_DONT_MANGLE_PREFIX_MAP`
environment variable. It should not normally be needed.
--- a/gcc/file-prefix-map.cc
+++ b/gcc/file-prefix-map.cc
@@ -74,7 +74,7 @@ add_prefix_map (file_prefix_map *&maps, const char *arg, const char *opt)
    remapping was performed.  */
 
 static const char *
-remap_filename (file_prefix_map *maps, const char *filename)
+remap_filename (file_prefix_map *maps, const char *filename, bool mangle_nix_store = false)
 {
   file_prefix_map *map;
   char *s;
@@ -102,6 +102,30 @@ remap_filename (file_prefix_map *maps, const char *filename)
       break;
   if (!map)
     {
+      if (mangle_nix_store && getenv("NIX_GCC_DONT_MANGLE_PREFIX_MAP") == NULL)
+	{
+	  /* Remap all fo $NIX_STORE/.{32} paths to uppercase
+	   *
+	   * 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);
+		for (size_t i = nix_store_len + 1; i < nix_store_len + 1 + 32; i++) {
+		  s[i] = TOUPPER(s[i]);
+		}
+		if (realname != filename)
+		  free (const_cast <char *> (realname));
+		return s;
+	     }
+	}
       if (realname != filename)
 	free (const_cast <char *> (realname));
       return filename;
@@ -163,7 +187,7 @@ add_profile_prefix_map (const char *arg)
 const char *
 remap_macro_filename (const char *filename)
 {
-  return remap_filename (macro_prefix_maps, filename);
+  return remap_filename (macro_prefix_maps, filename, true);
 }
 
 /* Remap using -fdebug-prefix-map.  Return the GC-allocated new name