@@ -505,6 +505,7 @@ pub const AbiAndDynamicLinkerFromFileError = error{
505
505
UnexpectedEndOfFile ,
506
506
NameTooLong ,
507
507
ProcessNotFound ,
508
+ StaticElfFile ,
508
509
};
509
510
510
511
pub fn abiAndDynamicLinkerFromFile (
@@ -550,6 +551,8 @@ pub fn abiAndDynamicLinkerFromFile(
550
551
if (phentsize > @sizeOf (elf .Elf64_Phdr )) return error .InvalidElfFile ;
551
552
552
553
var ph_i : u16 = 0 ;
554
+ var got_dyn_section : bool = false ;
555
+
553
556
while (ph_i < phnum ) {
554
557
// Reserve some bytes so that we can deref the 64-bit struct fields
555
558
// even when the ELF file is 32-bits.
@@ -565,61 +568,69 @@ pub fn abiAndDynamicLinkerFromFile(
565
568
const ph64 : * elf.Elf64_Phdr = @ptrCast (@alignCast (& ph_buf [ph_buf_i ]));
566
569
const p_type = elfInt (is_64 , need_bswap , ph32 .p_type , ph64 .p_type );
567
570
switch (p_type ) {
568
- elf .PT_INTERP = > if (look_for_ld ) {
569
- const p_offset = elfInt (is_64 , need_bswap , ph32 .p_offset , ph64 .p_offset );
570
- const p_filesz = elfInt (is_64 , need_bswap , ph32 .p_filesz , ph64 .p_filesz );
571
- if (p_filesz > result .dynamic_linker .buffer .len ) return error .NameTooLong ;
572
- const filesz : usize = @intCast (p_filesz );
573
- _ = try preadAtLeast (file , result .dynamic_linker .buffer [0.. filesz ], p_offset , filesz );
574
- // PT_INTERP includes a null byte in filesz.
575
- const len = filesz - 1 ;
576
- // dynamic_linker.max_byte is "max", not "len".
577
- // We know it will fit in u8 because we check against dynamic_linker.buffer.len above.
578
- result .dynamic_linker .len = @intCast (len );
579
-
580
- // Use it to determine ABI.
581
- const full_ld_path = result .dynamic_linker .buffer [0.. len ];
582
- for (ld_info_list ) | ld_info | {
583
- const standard_ld_basename = fs .path .basename (ld_info .ld .get ().? );
584
- if (std .mem .endsWith (u8 , full_ld_path , standard_ld_basename )) {
585
- result .abi = ld_info .abi ;
586
- break ;
571
+ elf .PT_INTERP = > {
572
+ got_dyn_section = true ;
573
+
574
+ if (look_for_ld ) {
575
+ const p_offset = elfInt (is_64 , need_bswap , ph32 .p_offset , ph64 .p_offset );
576
+ const p_filesz = elfInt (is_64 , need_bswap , ph32 .p_filesz , ph64 .p_filesz );
577
+ if (p_filesz > result .dynamic_linker .buffer .len ) return error .NameTooLong ;
578
+ const filesz : usize = @intCast (p_filesz );
579
+ _ = try preadAtLeast (file , result .dynamic_linker .buffer [0.. filesz ], p_offset , filesz );
580
+ // PT_INTERP includes a null byte in filesz.
581
+ const len = filesz - 1 ;
582
+ // dynamic_linker.max_byte is "max", not "len".
583
+ // We know it will fit in u8 because we check against dynamic_linker.buffer.len above.
584
+ result .dynamic_linker .len = @intCast (len );
585
+
586
+ // Use it to determine ABI.
587
+ const full_ld_path = result .dynamic_linker .buffer [0.. len ];
588
+ for (ld_info_list ) | ld_info | {
589
+ const standard_ld_basename = fs .path .basename (ld_info .ld .get ().? );
590
+ if (std .mem .endsWith (u8 , full_ld_path , standard_ld_basename )) {
591
+ result .abi = ld_info .abi ;
592
+ break ;
593
+ }
587
594
}
588
595
}
589
596
},
590
597
// We only need this for detecting glibc version.
591
- elf .PT_DYNAMIC = > if (builtin .target .os .tag == .linux and result .isGnuLibC () and
592
- query .glibc_version == null )
593
- {
594
- var dyn_off = elfInt (is_64 , need_bswap , ph32 .p_offset , ph64 .p_offset );
595
- const p_filesz = elfInt (is_64 , need_bswap , ph32 .p_filesz , ph64 .p_filesz );
596
- const dyn_size : usize = if (is_64 ) @sizeOf (elf .Elf64_Dyn ) else @sizeOf (elf .Elf32_Dyn );
597
- const dyn_num = p_filesz / dyn_size ;
598
- var dyn_buf : [16 * @sizeOf (elf .Elf64_Dyn )]u8 align (@alignOf (elf .Elf64_Dyn )) = undefined ;
599
- var dyn_i : usize = 0 ;
600
- dyn : while (dyn_i < dyn_num ) {
601
- // Reserve some bytes so that we can deref the 64-bit struct fields
602
- // even when the ELF file is 32-bits.
603
- const dyn_reserve : usize = @sizeOf (elf .Elf64_Dyn ) - @sizeOf (elf .Elf32_Dyn );
604
- const dyn_read_byte_len = try preadAtLeast (
605
- file ,
606
- dyn_buf [0 .. dyn_buf .len - dyn_reserve ],
607
- dyn_off ,
608
- dyn_size ,
609
- );
610
- var dyn_buf_i : usize = 0 ;
611
- while (dyn_buf_i < dyn_read_byte_len and dyn_i < dyn_num ) : ({
612
- dyn_i += 1 ;
613
- dyn_off += dyn_size ;
614
- dyn_buf_i += dyn_size ;
615
- }) {
616
- const dyn32 : * elf.Elf32_Dyn = @ptrCast (@alignCast (& dyn_buf [dyn_buf_i ]));
617
- const dyn64 : * elf.Elf64_Dyn = @ptrCast (@alignCast (& dyn_buf [dyn_buf_i ]));
618
- const tag = elfInt (is_64 , need_bswap , dyn32 .d_tag , dyn64 .d_tag );
619
- const val = elfInt (is_64 , need_bswap , dyn32 .d_val , dyn64 .d_val );
620
- if (tag == elf .DT_RUNPATH ) {
621
- rpath_offset = val ;
622
- break :dyn ;
598
+ elf .PT_DYNAMIC = > {
599
+ got_dyn_section = true ;
600
+
601
+ if (builtin .target .os .tag == .linux and result .isGnuLibC () and
602
+ query .glibc_version == null )
603
+ {
604
+ var dyn_off = elfInt (is_64 , need_bswap , ph32 .p_offset , ph64 .p_offset );
605
+ const p_filesz = elfInt (is_64 , need_bswap , ph32 .p_filesz , ph64 .p_filesz );
606
+ const dyn_size : usize = if (is_64 ) @sizeOf (elf .Elf64_Dyn ) else @sizeOf (elf .Elf32_Dyn );
607
+ const dyn_num = p_filesz / dyn_size ;
608
+ var dyn_buf : [16 * @sizeOf (elf .Elf64_Dyn )]u8 align (@alignOf (elf .Elf64_Dyn )) = undefined ;
609
+ var dyn_i : usize = 0 ;
610
+ dyn : while (dyn_i < dyn_num ) {
611
+ // Reserve some bytes so that we can deref the 64-bit struct fields
612
+ // even when the ELF file is 32-bits.
613
+ const dyn_reserve : usize = @sizeOf (elf .Elf64_Dyn ) - @sizeOf (elf .Elf32_Dyn );
614
+ const dyn_read_byte_len = try preadAtLeast (
615
+ file ,
616
+ dyn_buf [0 .. dyn_buf .len - dyn_reserve ],
617
+ dyn_off ,
618
+ dyn_size ,
619
+ );
620
+ var dyn_buf_i : usize = 0 ;
621
+ while (dyn_buf_i < dyn_read_byte_len and dyn_i < dyn_num ) : ({
622
+ dyn_i += 1 ;
623
+ dyn_off += dyn_size ;
624
+ dyn_buf_i += dyn_size ;
625
+ }) {
626
+ const dyn32 : * elf.Elf32_Dyn = @ptrCast (@alignCast (& dyn_buf [dyn_buf_i ]));
627
+ const dyn64 : * elf.Elf64_Dyn = @ptrCast (@alignCast (& dyn_buf [dyn_buf_i ]));
628
+ const tag = elfInt (is_64 , need_bswap , dyn32 .d_tag , dyn64 .d_tag );
629
+ const val = elfInt (is_64 , need_bswap , dyn32 .d_val , dyn64 .d_val );
630
+ if (tag == elf .DT_RUNPATH ) {
631
+ rpath_offset = val ;
632
+ break :dyn ;
633
+ }
623
634
}
624
635
}
625
636
}
@@ -629,6 +640,10 @@ pub fn abiAndDynamicLinkerFromFile(
629
640
}
630
641
}
631
642
643
+ if (! got_dyn_section ) {
644
+ return error .StaticElfFile ;
645
+ }
646
+
632
647
if (builtin .target .os .tag == .linux and result .isGnuLibC () and
633
648
query .glibc_version == null )
634
649
{
@@ -1208,6 +1223,7 @@ fn detectAbiAndDynamicLinker(
1208
1223
error .Unexpected ,
1209
1224
error .UnexpectedEndOfFile ,
1210
1225
error .NameTooLong ,
1226
+ error .StaticElfFile ,
1211
1227
// Finally, we fall back on the standard path.
1212
1228
= > | e | {
1213
1229
std .log .warn ("Encountered error: {s}, falling back to default ABI and dynamic linker." , .{@errorName (e )});
0 commit comments