@@ -399,17 +399,38 @@ pub const NativeTargetInfo = struct {
399
399
return result ;
400
400
}
401
401
402
+ const env_file = std .fs .openFileAbsoluteC ("/usr/bin/env" , .{}) catch | err | switch (err ) {
403
+ error .NoSpaceLeft = > unreachable ,
404
+ error .NameTooLong = > unreachable ,
405
+ error .PathAlreadyExists = > unreachable ,
406
+ error .SharingViolation = > unreachable ,
407
+ error .InvalidUtf8 = > unreachable ,
408
+ error .BadPathName = > unreachable ,
409
+ error .PipeBusy = > unreachable ,
410
+
411
+ error .IsDir ,
412
+ error .NotDir ,
413
+ error .AccessDenied ,
414
+ error .NoDevice ,
415
+ error .FileNotFound ,
416
+ error .FileTooBig ,
417
+ error .Unexpected ,
418
+ = > return defaultAbiAndDynamicLinker (cpu , os , cross_target ),
419
+
420
+ else = > | e | return e ,
421
+ };
422
+ defer env_file .close ();
423
+
402
424
// If Zig is statically linked, such as via distributed binary static builds, the above
403
425
// trick won't work. The next thing we fall back to is the same thing, but for /usr/bin/env.
404
426
// Since that path is hard-coded into the shebang line of many portable scripts, it's a
405
427
// reasonably reliable path to check for.
406
- return abiAndDynamicLinkerFromUsrBinEnv ( cpu , os , ld_info_list , cross_target ) catch | err | switch (err ) {
428
+ return abiAndDynamicLinkerFromFile ( env_file , cpu , os , ld_info_list , cross_target ) catch | err | switch (err ) {
407
429
error .FileSystem ,
408
430
error .SystemResources ,
409
431
error .SymLinkLoop ,
410
432
error .ProcessFdQuotaExceeded ,
411
433
error .SystemFdQuotaExceeded ,
412
- error .DeviceBusy ,
413
434
= > | e | return e ,
414
435
415
436
error .UnableToReadElfFile ,
@@ -418,7 +439,6 @@ pub const NativeTargetInfo = struct {
418
439
error .InvalidElfEndian ,
419
440
error .InvalidElfFile ,
420
441
error .InvalidElfMagic ,
421
- error .UsrBinEnvNotAvailable ,
422
442
error .Unexpected ,
423
443
error .UnexpectedEndOfFile ,
424
444
error .NameTooLong ,
@@ -461,32 +481,15 @@ pub const NativeTargetInfo = struct {
461
481
};
462
482
}
463
483
464
- fn abiAndDynamicLinkerFromUsrBinEnv (
484
+ pub fn abiAndDynamicLinkerFromFile (
485
+ file : fs.File ,
465
486
cpu : Target.Cpu ,
466
487
os : Target.Os ,
467
488
ld_info_list : []const LdInfo ,
468
489
cross_target : CrossTarget ,
469
490
) ! NativeTargetInfo {
470
- const env_file = std .fs .openFileAbsoluteC ("/usr/bin/env" , .{}) catch | err | switch (err ) {
471
- error .NoSpaceLeft = > unreachable ,
472
- error .NameTooLong = > unreachable ,
473
- error .PathAlreadyExists = > unreachable ,
474
- error .SharingViolation = > unreachable ,
475
- error .InvalidUtf8 = > unreachable ,
476
- error .BadPathName = > unreachable ,
477
- error .PipeBusy = > unreachable ,
478
-
479
- error .IsDir = > return error .UsrBinEnvNotAvailable ,
480
- error .NotDir = > return error .UsrBinEnvNotAvailable ,
481
- error .AccessDenied = > return error .UsrBinEnvNotAvailable ,
482
- error .NoDevice = > return error .UsrBinEnvNotAvailable ,
483
- error .FileNotFound = > return error .UsrBinEnvNotAvailable ,
484
- error .FileTooBig = > return error .UsrBinEnvNotAvailable ,
485
-
486
- else = > | e | return e ,
487
- };
488
491
var hdr_buf : [@sizeOf (elf .Elf64_Ehdr )]u8 align (@alignOf (elf .Elf64_Ehdr )) = undefined ;
489
- _ = try preadFull (env_file , & hdr_buf , 0 , hdr_buf .len );
492
+ _ = try preadFull (file , & hdr_buf , 0 , hdr_buf .len );
490
493
const hdr32 = @ptrCast (* elf .Elf32_Ehdr , & hdr_buf );
491
494
const hdr64 = @ptrCast (* elf .Elf64_Ehdr , & hdr_buf );
492
495
if (! mem .eql (u8 , hdr32 .e_ident [0.. 4], "\x7f ELF" )) return error .InvalidElfMagic ;
@@ -526,7 +529,7 @@ pub const NativeTargetInfo = struct {
526
529
// Reserve some bytes so that we can deref the 64-bit struct fields
527
530
// even when the ELF file is 32-bits.
528
531
const ph_reserve : usize = @sizeOf (elf .Elf64_Phdr ) - @sizeOf (elf .Elf32_Phdr );
529
- const ph_read_byte_len = try preadFull (env_file , ph_buf [0 .. ph_buf .len - ph_reserve ], phoff , phentsize );
532
+ const ph_read_byte_len = try preadFull (file , ph_buf [0 .. ph_buf .len - ph_reserve ], phoff , phentsize );
530
533
var ph_buf_i : usize = 0 ;
531
534
while (ph_buf_i < ph_read_byte_len and ph_i < phnum ) : ({
532
535
ph_i += 1 ;
@@ -541,7 +544,7 @@ pub const NativeTargetInfo = struct {
541
544
const p_offset = elfInt (is_64 , need_bswap , ph32 .p_offset , ph64 .p_offset );
542
545
const p_filesz = elfInt (is_64 , need_bswap , ph32 .p_filesz , ph64 .p_filesz );
543
546
if (p_filesz > result .dynamic_linker .buffer .len ) return error .NameTooLong ;
544
- _ = try preadFull (env_file , result .dynamic_linker .buffer [0.. p_filesz ], p_offset , p_filesz );
547
+ _ = try preadFull (file , result .dynamic_linker .buffer [0.. p_filesz ], p_offset , p_filesz );
545
548
// PT_INTERP includes a null byte in p_filesz.
546
549
const len = p_filesz - 1 ;
547
550
// dynamic_linker.max_byte is "max", not "len".
@@ -573,7 +576,7 @@ pub const NativeTargetInfo = struct {
573
576
// even when the ELF file is 32-bits.
574
577
const dyn_reserve : usize = @sizeOf (elf .Elf64_Dyn ) - @sizeOf (elf .Elf32_Dyn );
575
578
const dyn_read_byte_len = try preadFull (
576
- env_file ,
579
+ file ,
577
580
dyn_buf [0 .. dyn_buf .len - dyn_reserve ],
578
581
dyn_off ,
579
582
dyn_size ,
@@ -617,14 +620,14 @@ pub const NativeTargetInfo = struct {
617
620
var sh_buf : [16 * @sizeOf (elf .Elf64_Shdr )]u8 align (@alignOf (elf .Elf64_Shdr )) = undefined ;
618
621
if (sh_buf .len < shentsize ) return error .InvalidElfFile ;
619
622
620
- _ = try preadFull (env_file , & sh_buf , str_section_off , shentsize );
623
+ _ = try preadFull (file , & sh_buf , str_section_off , shentsize );
621
624
const shstr32 = @ptrCast (* elf .Elf32_Shdr , @alignCast (@alignOf (elf .Elf32_Shdr ), & sh_buf ));
622
625
const shstr64 = @ptrCast (* elf .Elf64_Shdr , @alignCast (@alignOf (elf .Elf64_Shdr ), & sh_buf ));
623
626
const shstrtab_off = elfInt (is_64 , need_bswap , shstr32 .sh_offset , shstr64 .sh_offset );
624
627
const shstrtab_size = elfInt (is_64 , need_bswap , shstr32 .sh_size , shstr64 .sh_size );
625
628
var strtab_buf : [4096 :0 ]u8 = undefined ;
626
629
const shstrtab_len = std .math .min (shstrtab_size , strtab_buf .len );
627
- const shstrtab_read_len = try preadFull (env_file , & strtab_buf , shstrtab_off , shstrtab_len );
630
+ const shstrtab_read_len = try preadFull (file , & strtab_buf , shstrtab_off , shstrtab_len );
628
631
const shstrtab = strtab_buf [0.. shstrtab_read_len ];
629
632
630
633
const shnum = elfInt (is_64 , need_bswap , hdr32 .e_shnum , hdr64 .e_shnum );
@@ -634,7 +637,7 @@ pub const NativeTargetInfo = struct {
634
637
// even when the ELF file is 32-bits.
635
638
const sh_reserve : usize = @sizeOf (elf .Elf64_Shdr ) - @sizeOf (elf .Elf32_Shdr );
636
639
const sh_read_byte_len = try preadFull (
637
- env_file ,
640
+ file ,
638
641
sh_buf [0 .. sh_buf .len - sh_reserve ],
639
642
shoff ,
640
643
shentsize ,
@@ -667,7 +670,7 @@ pub const NativeTargetInfo = struct {
667
670
668
671
if (dynstr ) | ds | {
669
672
const strtab_len = std .math .min (ds .size , strtab_buf .len );
670
- const strtab_read_len = try preadFull (env_file , & strtab_buf , ds .offset , shstrtab_len );
673
+ const strtab_read_len = try preadFull (file , & strtab_buf , ds .offset , shstrtab_len );
671
674
const strtab = strtab_buf [0.. strtab_read_len ];
672
675
// TODO this pointer cast should not be necessary
673
676
const rpath_list = mem .toSliceConst (u8 , @ptrCast ([* :0 ]u8 , strtab [rpoff .. ].ptr ));
@@ -763,7 +766,7 @@ pub const NativeTargetInfo = struct {
763
766
};
764
767
}
765
768
766
- const LdInfo = struct {
769
+ pub const LdInfo = struct {
767
770
ld : DynamicLinker ,
768
771
abi : Target.Abi ,
769
772
};
0 commit comments