@@ -388,6 +388,7 @@ fn detectAbiAndDynamicLinker(
388
388
error .Unexpected ,
389
389
error .UnexpectedEndOfFile ,
390
390
error .NameTooLong ,
391
+ error .StaticElfFile ,
391
392
// Finally, we fall back on the standard path.
392
393
= > | e | {
393
394
std .log .warn ("Encountered error: {s}, falling back to default ABI and dynamic linker.\n " , .{@errorName (e )});
@@ -607,6 +608,7 @@ pub const AbiAndDynamicLinkerFromFileError = error{
607
608
Unexpected ,
608
609
UnexpectedEndOfFile ,
609
610
NameTooLong ,
611
+ StaticElfFile ,
610
612
};
611
613
612
614
pub fn abiAndDynamicLinkerFromFile (
@@ -654,6 +656,8 @@ pub fn abiAndDynamicLinkerFromFile(
654
656
if (phentsize > @sizeOf (elf .Elf64_Phdr )) return error .InvalidElfFile ;
655
657
656
658
var ph_i : u16 = 0 ;
659
+ var got_dyn_section : bool = false ;
660
+
657
661
while (ph_i < phnum ) {
658
662
// Reserve some bytes so that we can deref the 64-bit struct fields
659
663
// even when the ELF file is 32-bits.
@@ -669,61 +673,69 @@ pub fn abiAndDynamicLinkerFromFile(
669
673
const ph64 : * elf.Elf64_Phdr = @ptrCast (@alignCast (& ph_buf [ph_buf_i ]));
670
674
const p_type = elfInt (is_64 , need_bswap , ph32 .p_type , ph64 .p_type );
671
675
switch (p_type ) {
672
- elf .PT_INTERP = > if (look_for_ld ) {
673
- const p_offset = elfInt (is_64 , need_bswap , ph32 .p_offset , ph64 .p_offset );
674
- const p_filesz = elfInt (is_64 , need_bswap , ph32 .p_filesz , ph64 .p_filesz );
675
- if (p_filesz > result .dynamic_linker .buffer .len ) return error .NameTooLong ;
676
- const filesz = @as (usize , @intCast (p_filesz ));
677
- _ = try preadMin (file , result .dynamic_linker .buffer [0.. filesz ], p_offset , filesz );
678
- // PT_INTERP includes a null byte in filesz.
679
- const len = filesz - 1 ;
680
- // dynamic_linker.max_byte is "max", not "len".
681
- // We know it will fit in u8 because we check against dynamic_linker.buffer.len above.
682
- result .dynamic_linker .max_byte = @as (u8 , @intCast (len - 1 ));
683
-
684
- // Use it to determine ABI.
685
- const full_ld_path = result .dynamic_linker .buffer [0.. len ];
686
- for (ld_info_list ) | ld_info | {
687
- const standard_ld_basename = fs .path .basename (ld_info .ld .get ().? );
688
- if (std .mem .endsWith (u8 , full_ld_path , standard_ld_basename )) {
689
- result .target .abi = ld_info .abi ;
690
- break ;
676
+ elf .PT_INTERP = > {
677
+ got_dyn_section = true ;
678
+
679
+ if (look_for_ld ) {
680
+ const p_offset = elfInt (is_64 , need_bswap , ph32 .p_offset , ph64 .p_offset );
681
+ const p_filesz = elfInt (is_64 , need_bswap , ph32 .p_filesz , ph64 .p_filesz );
682
+ if (p_filesz > result .dynamic_linker .buffer .len ) return error .NameTooLong ;
683
+ const filesz = @as (usize , @intCast (p_filesz ));
684
+ _ = try preadMin (file , result .dynamic_linker .buffer [0.. filesz ], p_offset , filesz );
685
+ // PT_INTERP includes a null byte in filesz.
686
+ const len = filesz - 1 ;
687
+ // dynamic_linker.max_byte is "max", not "len".
688
+ // We know it will fit in u8 because we check against dynamic_linker.buffer.len above.
689
+ result .dynamic_linker .max_byte = @as (u8 , @intCast (len - 1 ));
690
+
691
+ // Use it to determine ABI.
692
+ const full_ld_path = result .dynamic_linker .buffer [0.. len ];
693
+ for (ld_info_list ) | ld_info | {
694
+ const standard_ld_basename = fs .path .basename (ld_info .ld .get ().? );
695
+ if (std .mem .endsWith (u8 , full_ld_path , standard_ld_basename )) {
696
+ result .target .abi = ld_info .abi ;
697
+ break ;
698
+ }
691
699
}
692
700
}
693
701
},
694
702
// We only need this for detecting glibc version.
695
- elf .PT_DYNAMIC = > if (builtin .target .os .tag == .linux and result .target .isGnuLibC () and
696
- cross_target .glibc_version == null )
697
- {
698
- var dyn_off = elfInt (is_64 , need_bswap , ph32 .p_offset , ph64 .p_offset );
699
- const p_filesz = elfInt (is_64 , need_bswap , ph32 .p_filesz , ph64 .p_filesz );
700
- const dyn_size : usize = if (is_64 ) @sizeOf (elf .Elf64_Dyn ) else @sizeOf (elf .Elf32_Dyn );
701
- const dyn_num = p_filesz / dyn_size ;
702
- var dyn_buf : [16 * @sizeOf (elf .Elf64_Dyn )]u8 align (@alignOf (elf .Elf64_Dyn )) = undefined ;
703
- var dyn_i : usize = 0 ;
704
- dyn : while (dyn_i < dyn_num ) {
705
- // Reserve some bytes so that we can deref the 64-bit struct fields
706
- // even when the ELF file is 32-bits.
707
- const dyn_reserve : usize = @sizeOf (elf .Elf64_Dyn ) - @sizeOf (elf .Elf32_Dyn );
708
- const dyn_read_byte_len = try preadMin (
709
- file ,
710
- dyn_buf [0 .. dyn_buf .len - dyn_reserve ],
711
- dyn_off ,
712
- dyn_size ,
713
- );
714
- var dyn_buf_i : usize = 0 ;
715
- while (dyn_buf_i < dyn_read_byte_len and dyn_i < dyn_num ) : ({
716
- dyn_i += 1 ;
717
- dyn_off += dyn_size ;
718
- dyn_buf_i += dyn_size ;
719
- }) {
720
- const dyn32 : * elf.Elf32_Dyn = @ptrCast (@alignCast (& dyn_buf [dyn_buf_i ]));
721
- const dyn64 : * elf.Elf64_Dyn = @ptrCast (@alignCast (& dyn_buf [dyn_buf_i ]));
722
- const tag = elfInt (is_64 , need_bswap , dyn32 .d_tag , dyn64 .d_tag );
723
- const val = elfInt (is_64 , need_bswap , dyn32 .d_val , dyn64 .d_val );
724
- if (tag == elf .DT_RUNPATH ) {
725
- rpath_offset = val ;
726
- break :dyn ;
703
+ elf .PT_DYNAMIC = > {
704
+ got_dyn_section = true ;
705
+
706
+ if (builtin .target .os .tag == .linux and result .target .isGnuLibC () and
707
+ cross_target .glibc_version == null )
708
+ {
709
+ var dyn_off = elfInt (is_64 , need_bswap , ph32 .p_offset , ph64 .p_offset );
710
+ const p_filesz = elfInt (is_64 , need_bswap , ph32 .p_filesz , ph64 .p_filesz );
711
+ const dyn_size : usize = if (is_64 ) @sizeOf (elf .Elf64_Dyn ) else @sizeOf (elf .Elf32_Dyn );
712
+ const dyn_num = p_filesz / dyn_size ;
713
+ var dyn_buf : [16 * @sizeOf (elf .Elf64_Dyn )]u8 align (@alignOf (elf .Elf64_Dyn )) = undefined ;
714
+ var dyn_i : usize = 0 ;
715
+ dyn : while (dyn_i < dyn_num ) {
716
+ // Reserve some bytes so that we can deref the 64-bit struct fields
717
+ // even when the ELF file is 32-bits.
718
+ const dyn_reserve : usize = @sizeOf (elf .Elf64_Dyn ) - @sizeOf (elf .Elf32_Dyn );
719
+ const dyn_read_byte_len = try preadMin (
720
+ file ,
721
+ dyn_buf [0 .. dyn_buf .len - dyn_reserve ],
722
+ dyn_off ,
723
+ dyn_size ,
724
+ );
725
+ var dyn_buf_i : usize = 0 ;
726
+ while (dyn_buf_i < dyn_read_byte_len and dyn_i < dyn_num ) : ({
727
+ dyn_i += 1 ;
728
+ dyn_off += dyn_size ;
729
+ dyn_buf_i += dyn_size ;
730
+ }) {
731
+ const dyn32 : * elf.Elf32_Dyn = @ptrCast (@alignCast (& dyn_buf [dyn_buf_i ]));
732
+ const dyn64 : * elf.Elf64_Dyn = @ptrCast (@alignCast (& dyn_buf [dyn_buf_i ]));
733
+ const tag = elfInt (is_64 , need_bswap , dyn32 .d_tag , dyn64 .d_tag );
734
+ const val = elfInt (is_64 , need_bswap , dyn32 .d_val , dyn64 .d_val );
735
+ if (tag == elf .DT_RUNPATH ) {
736
+ rpath_offset = val ;
737
+ break :dyn ;
738
+ }
727
739
}
728
740
}
729
741
}
@@ -733,6 +745,10 @@ pub fn abiAndDynamicLinkerFromFile(
733
745
}
734
746
}
735
747
748
+ if (! got_dyn_section ) {
749
+ return error .StaticElfFile ;
750
+ }
751
+
736
752
if (builtin .target .os .tag == .linux and result .target .isGnuLibC () and
737
753
cross_target .glibc_version == null )
738
754
{
0 commit comments