@@ -84,41 +84,52 @@ export void patchelf_walk(const std::filesystem::path& dir,
8484// xlings' home, not mcpp's sandbox glibc — binaries would fail to exec.
8585//
8686// Mcpp does a post-install spec rewrite:
87- // - Dynamically detects the baked-in lib dir from the specs file
88- // - Replaces the dynamic-linker path with <glibc_lib64>/ld-linux-x86-64.so.2
89- // - Replaces the rpath with <glibc_lib64 >:<gcc_lib64>
87+ // - Dynamically detects the baked-in loader path from the specs file
88+ // - Replaces it with the sandbox glibc payload's loader
89+ // - Replaces the rpath with <glibc_lib >:<gcc_lib64>
9090// Idempotent — skips if already pointing at the correct glibc.
91- // Extract the baked-in lib directory from a gcc specs file by finding
92- // the dynamic-linker path that ends with `/ld-linux-x86-64.so.2`.
93- // xim bakes the installing user's XLINGS_HOME into specs at install
94- // time, so the path varies per machine — we cannot hardcode it .
95- std::string detect_baked_lib_dir (const std::string& specsContent) {
96- constexpr std::string_view kLoader = " /ld-linux-x86-64.so.2 " ;
97- auto pos = specsContent.find (kLoader );
91+ // Extract the baked-in glibc loader path (".../ld-linux-<arch>.so.N") from a
92+ // gcc specs file. xim bakes the installing user's XLINGS_HOME into specs at
93+ // install time, so the DIR varies per machine, and the loader NAME varies
94+ // per arch — detect both instead of hardcoding either .
95+ std::string detect_baked_loader (const std::string& specsContent) {
96+ constexpr std::string_view kLoaderMark = " /ld-linux-" ;
97+ auto pos = specsContent.find (kLoaderMark );
9898 if (pos == std::string::npos) return " " ;
99- // Walk backwards to find start of the absolute path
99+ // Walk backwards to find start of the absolute path…
100100 auto start = pos;
101101 while (start > 0 && specsContent[start - 1 ] != ' '
102102 && specsContent[start - 1 ] != ' :'
103103 && specsContent[start - 1 ] != ' ;'
104104 && specsContent[start - 1 ] != ' \n ' ) {
105105 --start;
106106 }
107- auto dir = specsContent.substr (start, pos - start);
108- // Sanity: must be absolute
109- if (dir.empty () || dir[0 ] != ' /' ) return " " ;
110- // Skip if it already points to the target glibc (no fixup needed)
111- return dir;
107+ // …and forwards to its end.
108+ auto end = pos + kLoaderMark .size ();
109+ while (end < specsContent.size ()
110+ && !std::isspace (static_cast <unsigned char >(specsContent[end]))
111+ && specsContent[end] != ' :' && specsContent[end] != ' ;' ) {
112+ ++end;
113+ }
114+ auto loader = specsContent.substr (start, end - start);
115+ if (loader.empty () || loader[0 ] != ' /' ) return " " ;
116+ return loader;
112117}
113118
114119void fixup_gcc_specs (const std::filesystem::path& gccPkgRoot,
115120 const std::filesystem::path& glibcLibDir,
116121 const std::filesystem::path& gccLibDir)
117122{
118- auto specsParent = gccPkgRoot / " lib" / " gcc" / " x86_64-linux-gnu" ;
119- if (!std::filesystem::exists (specsParent)) return ;
123+ std::filesystem::path specsParent;
124+ std::error_code ec;
125+ for (auto it = std::filesystem::directory_iterator (gccPkgRoot / " lib" / " gcc" , ec);
126+ !ec && it != std::filesystem::directory_iterator{}; it.increment (ec)) {
127+ if (it->is_directory (ec)) { specsParent = it->path (); break ; }
128+ }
129+ if (specsParent.empty ()) return ;
120130
121- auto loaderReplacement = (glibcLibDir / " ld-linux-x86-64.so.2" ).string ();
131+ auto loaderReplacement = resolve_loader (glibcLibDir, /* targetTriple=*/ {}).string ();
132+ if (loaderReplacement.empty ()) return ;
122133 auto rpathReplacement = std::format (" {}:{}" ,
123134 glibcLibDir.string (),
124135 gccLibDir.string ());
@@ -141,13 +152,12 @@ void fixup_gcc_specs(const std::filesystem::path& gccPkgRoot,
141152 std::stringstream ss; ss << is.rdbuf ();
142153 std::string content = ss.str ();
143154
144- auto bakedDir = detect_baked_lib_dir (content);
145- if (bakedDir.empty ()) continue ;
155+ auto bakedLoader = detect_baked_loader (content);
156+ if (bakedLoader.empty ()) continue ;
157+ auto bakedDir = std::filesystem::path (bakedLoader).parent_path ().string ();
146158 // Already pointing at the right place — no fixup needed.
147159 if (bakedDir == glibcLibDir.string ()) continue ;
148160
149- auto bakedLoader = bakedDir + " /ld-linux-x86-64.so.2" ;
150-
151161 // Order matters: replace the full loader file path first so the
152162 // shorter dir pattern doesn't eat its prefix.
153163 replace_all (content, bakedLoader, loaderReplacement);
0 commit comments