about summary refs log tree commit diff
path: root/nixpkgs/pkgs/development/compilers/gcc/patches/12/mangle-NIX_STORE-in-__FILE__.patch
blob: 51078925eeb84cbf7192913b23e7fb7033ed8d56 (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 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`.

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...` but those paths are also used for debug symbols. It is
handy to be able to invert the transformation to go back to the original
store path for debuginfod servers. 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.
--- 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,31 @@ 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 the 32 characters after $NIX_STORE/ 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 = 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 (int i = nix_store_len + 1; i < nix_store_len + 1 + 32; i++) {
+		 s[i] = TOUPPER(s[i]);
+	       }
+	       return s;
+	    }
+	}
+      return filename;
+    }
   name = filename + map->old_len;
   name_len = strlen (name) + 1;
 
@@ -90,7 +117,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  */