@@ -436,6 +436,7 @@ pub const AbiAndDynamicLinkerFromFileError = error{
436
436
Unexpected ,
437
437
UnexpectedEndOfFile ,
438
438
NameTooLong ,
439
+ StaticElfFile ,
439
440
};
440
441
441
442
pub fn abiAndDynamicLinkerFromFile (
@@ -481,6 +482,8 @@ pub fn abiAndDynamicLinkerFromFile(
481
482
if (phentsize > @sizeOf (elf .Elf64_Phdr )) return error .InvalidElfFile ;
482
483
483
484
var ph_i : u16 = 0 ;
485
+ var got_dyn_section : bool = false ;
486
+
484
487
while (ph_i < phnum ) {
485
488
// Reserve some bytes so that we can deref the 64-bit struct fields
486
489
// even when the ELF file is 32-bits.
@@ -496,61 +499,69 @@ pub fn abiAndDynamicLinkerFromFile(
496
499
const ph64 : * elf.Elf64_Phdr = @ptrCast (@alignCast (& ph_buf [ph_buf_i ]));
497
500
const p_type = elfInt (is_64 , need_bswap , ph32 .p_type , ph64 .p_type );
498
501
switch (p_type ) {
499
- elf .PT_INTERP = > if (look_for_ld ) {
500
- const p_offset = elfInt (is_64 , need_bswap , ph32 .p_offset , ph64 .p_offset );
501
- const p_filesz = elfInt (is_64 , need_bswap , ph32 .p_filesz , ph64 .p_filesz );
502
- if (p_filesz > result .dynamic_linker .buffer .len ) return error .NameTooLong ;
503
- const filesz : usize = @intCast (p_filesz );
504
- _ = try preadAtLeast (file , result .dynamic_linker .buffer [0.. filesz ], p_offset , filesz );
505
- // PT_INTERP includes a null byte in filesz.
506
- const len = filesz - 1 ;
507
- // dynamic_linker.max_byte is "max", not "len".
508
- // We know it will fit in u8 because we check against dynamic_linker.buffer.len above.
509
- result .dynamic_linker .len = @intCast (len );
510
-
511
- // Use it to determine ABI.
512
- const full_ld_path = result .dynamic_linker .buffer [0.. len ];
513
- for (ld_info_list ) | ld_info | {
514
- const standard_ld_basename = fs .path .basename (ld_info .ld .get ().? );
515
- if (std .mem .endsWith (u8 , full_ld_path , standard_ld_basename )) {
516
- result .abi = ld_info .abi ;
517
- break ;
502
+ elf .PT_INTERP = > {
503
+ got_dyn_section = true ;
504
+
505
+ if (look_for_ld ) {
506
+ const p_offset = elfInt (is_64 , need_bswap , ph32 .p_offset , ph64 .p_offset );
507
+ const p_filesz = elfInt (is_64 , need_bswap , ph32 .p_filesz , ph64 .p_filesz );
508
+ if (p_filesz > result .dynamic_linker .buffer .len ) return error .NameTooLong ;
509
+ const filesz : usize = @intCast (p_filesz );
510
+ _ = try preadAtLeast (file , result .dynamic_linker .buffer [0.. filesz ], p_offset , filesz );
511
+ // PT_INTERP includes a null byte in filesz.
512
+ const len = filesz - 1 ;
513
+ // dynamic_linker.max_byte is "max", not "len".
514
+ // We know it will fit in u8 because we check against dynamic_linker.buffer.len above.
515
+ result .dynamic_linker .len = @intCast (len );
516
+
517
+ // Use it to determine ABI.
518
+ const full_ld_path = result .dynamic_linker .buffer [0.. len ];
519
+ for (ld_info_list ) | ld_info | {
520
+ const standard_ld_basename = fs .path .basename (ld_info .ld .get ().? );
521
+ if (std .mem .endsWith (u8 , full_ld_path , standard_ld_basename )) {
522
+ result .abi = ld_info .abi ;
523
+ break ;
524
+ }
518
525
}
519
526
}
520
527
},
521
528
// We only need this for detecting glibc version.
522
- elf .PT_DYNAMIC = > if (builtin .target .os .tag == .linux and result .isGnuLibC () and
523
- query .glibc_version == null )
524
- {
525
- var dyn_off = elfInt (is_64 , need_bswap , ph32 .p_offset , ph64 .p_offset );
526
- const p_filesz = elfInt (is_64 , need_bswap , ph32 .p_filesz , ph64 .p_filesz );
527
- const dyn_size : usize = if (is_64 ) @sizeOf (elf .Elf64_Dyn ) else @sizeOf (elf .Elf32_Dyn );
528
- const dyn_num = p_filesz / dyn_size ;
529
- var dyn_buf : [16 * @sizeOf (elf .Elf64_Dyn )]u8 align (@alignOf (elf .Elf64_Dyn )) = undefined ;
530
- var dyn_i : usize = 0 ;
531
- dyn : while (dyn_i < dyn_num ) {
532
- // Reserve some bytes so that we can deref the 64-bit struct fields
533
- // even when the ELF file is 32-bits.
534
- const dyn_reserve : usize = @sizeOf (elf .Elf64_Dyn ) - @sizeOf (elf .Elf32_Dyn );
535
- const dyn_read_byte_len = try preadAtLeast (
536
- file ,
537
- dyn_buf [0 .. dyn_buf .len - dyn_reserve ],
538
- dyn_off ,
539
- dyn_size ,
540
- );
541
- var dyn_buf_i : usize = 0 ;
542
- while (dyn_buf_i < dyn_read_byte_len and dyn_i < dyn_num ) : ({
543
- dyn_i += 1 ;
544
- dyn_off += dyn_size ;
545
- dyn_buf_i += dyn_size ;
546
- }) {
547
- const dyn32 : * elf.Elf32_Dyn = @ptrCast (@alignCast (& dyn_buf [dyn_buf_i ]));
548
- const dyn64 : * elf.Elf64_Dyn = @ptrCast (@alignCast (& dyn_buf [dyn_buf_i ]));
549
- const tag = elfInt (is_64 , need_bswap , dyn32 .d_tag , dyn64 .d_tag );
550
- const val = elfInt (is_64 , need_bswap , dyn32 .d_val , dyn64 .d_val );
551
- if (tag == elf .DT_RUNPATH ) {
552
- rpath_offset = val ;
553
- break :dyn ;
529
+ elf .PT_DYNAMIC = > {
530
+ got_dyn_section = true ;
531
+
532
+ if (builtin .target .os .tag == .linux and result .isGnuLibC () and
533
+ query .glibc_version == null )
534
+ {
535
+ var dyn_off = elfInt (is_64 , need_bswap , ph32 .p_offset , ph64 .p_offset );
536
+ const p_filesz = elfInt (is_64 , need_bswap , ph32 .p_filesz , ph64 .p_filesz );
537
+ const dyn_size : usize = if (is_64 ) @sizeOf (elf .Elf64_Dyn ) else @sizeOf (elf .Elf32_Dyn );
538
+ const dyn_num = p_filesz / dyn_size ;
539
+ var dyn_buf : [16 * @sizeOf (elf .Elf64_Dyn )]u8 align (@alignOf (elf .Elf64_Dyn )) = undefined ;
540
+ var dyn_i : usize = 0 ;
541
+ dyn : while (dyn_i < dyn_num ) {
542
+ // Reserve some bytes so that we can deref the 64-bit struct fields
543
+ // even when the ELF file is 32-bits.
544
+ const dyn_reserve : usize = @sizeOf (elf .Elf64_Dyn ) - @sizeOf (elf .Elf32_Dyn );
545
+ const dyn_read_byte_len = try preadAtLeast (
546
+ file ,
547
+ dyn_buf [0 .. dyn_buf .len - dyn_reserve ],
548
+ dyn_off ,
549
+ dyn_size ,
550
+ );
551
+ var dyn_buf_i : usize = 0 ;
552
+ while (dyn_buf_i < dyn_read_byte_len and dyn_i < dyn_num ) : ({
553
+ dyn_i += 1 ;
554
+ dyn_off += dyn_size ;
555
+ dyn_buf_i += dyn_size ;
556
+ }) {
557
+ const dyn32 : * elf.Elf32_Dyn = @ptrCast (@alignCast (& dyn_buf [dyn_buf_i ]));
558
+ const dyn64 : * elf.Elf64_Dyn = @ptrCast (@alignCast (& dyn_buf [dyn_buf_i ]));
559
+ const tag = elfInt (is_64 , need_bswap , dyn32 .d_tag , dyn64 .d_tag );
560
+ const val = elfInt (is_64 , need_bswap , dyn32 .d_val , dyn64 .d_val );
561
+ if (tag == elf .DT_RUNPATH ) {
562
+ rpath_offset = val ;
563
+ break :dyn ;
564
+ }
554
565
}
555
566
}
556
567
}
@@ -560,6 +571,10 @@ pub fn abiAndDynamicLinkerFromFile(
560
571
}
561
572
}
562
573
574
+ if (! got_dyn_section ) {
575
+ return error .StaticElfFile ;
576
+ }
577
+
563
578
if (builtin .target .os .tag == .linux and result .isGnuLibC () and
564
579
query .glibc_version == null )
565
580
{
@@ -1124,6 +1139,7 @@ fn detectAbiAndDynamicLinker(
1124
1139
error .Unexpected ,
1125
1140
error .UnexpectedEndOfFile ,
1126
1141
error .NameTooLong ,
1142
+ error .StaticElfFile ,
1127
1143
// Finally, we fall back on the standard path.
1128
1144
= > | e | {
1129
1145
std .log .warn ("Encountered error: {s}, falling back to default ABI and dynamic linker." , .{@errorName (e )});
0 commit comments