@@ -28,11 +28,6 @@ const REQUIRED_RUNTIME_FILES: RuntimeFileSpec[] = [
2828 targetRelativePath : "bin/kmod" ,
2929 mode : 0o755 ,
3030 } ,
31- {
32- sourcePathInRootfs : "/lib/ld-musl-aarch64.so.1" ,
33- targetRelativePath : "lib/ld-musl-aarch64.so.1" ,
34- mode : 0o755 ,
35- } ,
3631 {
3732 sourcePathInRootfs : "/usr/lib/libcrypto.so.3" ,
3833 targetRelativePath : "usr/lib/libcrypto.so.3" ,
@@ -70,6 +65,8 @@ const REQUIRED_RUNTIME_FILES: RuntimeFileSpec[] = [
7065 } ,
7166] ;
7267
68+ const LOADER_CANDIDATE_PATHS = [ "/lib/ld-musl-aarch64.so.1" , "/lib/ld-musl-x86_64.so.1" ] ;
69+
7370const REQUIRED_RUNTIME_DIRECTORIES : RuntimeDirectorySpec [ ] = [
7471 {
7572 sourcePathInRootfs : "/lib/modules" ,
@@ -136,6 +133,23 @@ export async function injectGondolinRuntime(rootfsDir: string): Promise<RuntimeI
136133 const injectedFiles : string [ ] = [ ] ;
137134 const injectedDirectories : string [ ] = [ ] ;
138135
136+ const loaderSourcePath = resolveExistingPathInExt4 (
137+ debugfsCmd ,
138+ baseRootfsPath ,
139+ LOADER_CANDIDATE_PATHS ,
140+ "musl dynamic loader" ,
141+ ) ;
142+ const loaderFileName = path . posix . basename ( loaderSourcePath ) ;
143+
144+ const runtimeFiles : RuntimeFileSpec [ ] = [
145+ ...REQUIRED_RUNTIME_FILES ,
146+ {
147+ sourcePathInRootfs : loaderSourcePath ,
148+ targetRelativePath : `lib/${ loaderFileName } ` ,
149+ mode : 0o755 ,
150+ } ,
151+ ] ;
152+
139153 for ( const runtimeDirectory of REQUIRED_RUNTIME_DIRECTORIES ) {
140154 const finalPath = path . join ( rootfsDir , runtimeDirectory . targetRelativePath ) ;
141155 dumpDirectoryFromExt4 (
@@ -148,7 +162,7 @@ export async function injectGondolinRuntime(rootfsDir: string): Promise<RuntimeI
148162 injectedDirectories . push ( finalPath ) ;
149163 }
150164
151- for ( const runtimeFile of REQUIRED_RUNTIME_FILES ) {
165+ for ( const runtimeFile of runtimeFiles ) {
152166 const finalPath = path . join ( rootfsDir , runtimeFile . targetRelativePath ) ;
153167 ensureParentDirectory ( rootfsDir , path . dirname ( finalPath ) ) ;
154168
@@ -167,7 +181,12 @@ export async function injectGondolinRuntime(rootfsDir: string): Promise<RuntimeI
167181
168182 ensureSymlink ( rootfsDir , "sbin/modprobe" , "../bin/kmod" ) ;
169183 ensureSymlink ( rootfsDir , "sbin/insmod" , "../bin/kmod" ) ;
170- ensureSymlink ( rootfsDir , "lib/libc.musl-aarch64.so.1" , "ld-musl-aarch64.so.1" ) ;
184+
185+ const muslLibcSymlinkName = deriveMuslLibcSymlinkName ( loaderFileName ) ;
186+ if ( muslLibcSymlinkName ) {
187+ ensureSymlink ( rootfsDir , `lib/${ muslLibcSymlinkName } ` , loaderFileName ) ;
188+ }
189+
171190 ensureSymlink ( rootfsDir , "usr/lib/liblzma.so.5" , "liblzma.so.5.8.2" ) ;
172191 ensureSymlink ( rootfsDir , "usr/lib/libz.so.1" , "libz.so.1.3.1" ) ;
173192 ensureSymlink ( rootfsDir , "usr/lib/libzstd.so.1" , "libzstd.so.1.5.7" ) ;
@@ -179,6 +198,43 @@ export async function injectGondolinRuntime(rootfsDir: string): Promise<RuntimeI
179198 } ;
180199}
181200
201+ function resolveExistingPathInExt4 (
202+ debugfsCmd : string ,
203+ ext4Path : string ,
204+ candidates : string [ ] ,
205+ label : string ,
206+ ) : string {
207+ for ( const candidate of candidates ) {
208+ if ( pathExistsInExt4 ( debugfsCmd , ext4Path , candidate ) ) {
209+ return candidate ;
210+ }
211+ }
212+
213+ throw new CliUsageError ( `Failed to locate required ${ label } in base rootfs.` , [
214+ `Searched paths: ${ candidates . join ( ", " ) } ` ,
215+ `Base rootfs: ${ ext4Path } ` ,
216+ "Ensure gondolin guest assets are complete for your host architecture." ,
217+ ] ) ;
218+ }
219+
220+ function pathExistsInExt4 ( debugfsCmd : string , ext4Path : string , sourcePath : string ) : boolean {
221+ const result = spawnSync ( debugfsCmd , [ "-R" , `stat ${ sourcePath } ` , ext4Path ] , {
222+ encoding : "utf8" ,
223+ stdio : [ "ignore" , "pipe" , "pipe" ] ,
224+ } ) ;
225+
226+ return result . status === 0 ;
227+ }
228+
229+ function deriveMuslLibcSymlinkName ( loaderFileName : string ) : string | undefined {
230+ const match = / ^ l d - m u s l - ( .+ ) \. s o \. 1 $ / . exec ( loaderFileName ) ;
231+ if ( ! match ) {
232+ return undefined ;
233+ }
234+
235+ return `libc.musl-${ match [ 1 ] } .so.1` ;
236+ }
237+
182238function dumpDirectoryFromExt4 (
183239 debugfsCmd : string ,
184240 ext4Path : string ,
0 commit comments