From 30908556fece379ffd7c0da96c774d8bd297e459 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich 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 @@ -65,7 +65,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; @@ -76,7 +76,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 (mangle_nix_store && getenv("NIX_GCC_DONT_MANGLE_PREFIX_MAP") == NULL) + { + /* 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 (size_t 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; @@ -129,7 +153,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