@@ -482,6 +482,7 @@ pub const Header = struct {
482
482
is_64 : bool ,
483
483
endian : std.builtin.Endian ,
484
484
os_abi : OSABI ,
485
+ /// The meaning of this value depends on `os_abi`.
485
486
abi_version : u8 ,
486
487
type : ET ,
487
488
machine : EM ,
@@ -494,205 +495,135 @@ pub const Header = struct {
494
495
shnum : u16 ,
495
496
shstrndx : u16 ,
496
497
497
- pub fn program_header_iterator ( self : Header , parse_source : anytype ) ProgramHeaderIterator ( @TypeOf ( parse_source )) {
498
- return ProgramHeaderIterator ( @TypeOf ( parse_source )) {
499
- .elf_header = self ,
500
- .parse_source = parse_source ,
498
+ pub fn iterateProgramHeaders ( h : Header , file_reader : * std.fs.File.Reader ) ProgramHeaderIterator {
499
+ return . {
500
+ .elf_header = h ,
501
+ .file_reader = file_reader ,
501
502
};
502
503
}
503
504
504
- pub fn section_header_iterator ( self : Header , parse_source : anytype ) SectionHeaderIterator ( @TypeOf ( parse_source )) {
505
- return SectionHeaderIterator ( @TypeOf ( parse_source )) {
506
- .elf_header = self ,
507
- .parse_source = parse_source ,
505
+ pub fn iterateSectionHeaders ( h : Header , file_reader : * std.fs.File.Reader ) SectionHeaderIterator {
506
+ return . {
507
+ .elf_header = h ,
508
+ .file_reader = file_reader ,
508
509
};
509
510
}
510
511
511
- pub fn read ( parse_source : anytype ) ! Header {
512
- var hdr_buf : [ @sizeOf ( Elf64_Ehdr )] u8 align ( @alignOf ( Elf64_Ehdr )) = undefined ;
513
- try parse_source . seekableStream (). seekTo ( 0 );
514
- try parse_source . deprecatedReader (). readNoEof ( & hdr_buf );
515
- return Header . parse ( & hdr_buf );
516
- }
512
+ pub const ReadError = std . Io . Reader . Error || error {
513
+ InvalidElfMagic ,
514
+ InvalidElfVersion ,
515
+ InvalidElfClass ,
516
+ InvalidElfEndian ,
517
+ };
517
518
518
- pub fn parse (hdr_buf : * align (@alignOf (Elf64_Ehdr )) const [@sizeOf (Elf64_Ehdr )]u8 ) ! Header {
519
- const hdr32 = @as (* const Elf32_Ehdr , @ptrCast (hdr_buf ));
520
- const hdr64 = @as (* const Elf64_Ehdr , @ptrCast (hdr_buf ));
521
- if (! mem .eql (u8 , hdr32 .e_ident [0.. 4], MAGIC )) return error .InvalidElfMagic ;
522
- if (hdr32 .e_ident [EI_VERSION ] != 1 ) return error .InvalidElfVersion ;
519
+ pub fn read (r : * std.Io.Reader ) ReadError ! Header {
520
+ const buf = try r .peek (@sizeOf (Elf64_Ehdr ));
523
521
524
- const is_64 = switch (hdr32 .e_ident [EI_CLASS ]) {
525
- ELFCLASS32 = > false ,
526
- ELFCLASS64 = > true ,
527
- else = > return error .InvalidElfClass ,
528
- };
522
+ if (! mem .eql (u8 , buf [0.. 4], MAGIC )) return error .InvalidElfMagic ;
523
+ if (buf [EI_VERSION ] != 1 ) return error .InvalidElfVersion ;
529
524
530
- const endian : std.builtin.Endian = switch (hdr32 . e_ident [EI_DATA ]) {
525
+ const endian : std.builtin.Endian = switch (buf [EI_DATA ]) {
531
526
ELFDATA2LSB = > .little ,
532
527
ELFDATA2MSB = > .big ,
533
528
else = > return error .InvalidElfEndian ,
534
529
};
535
- const need_bswap = endian != native_endian ;
536
530
531
+ return switch (buf [EI_CLASS ]) {
532
+ ELFCLASS32 = > .init (try r .takeStruct (Elf32_Ehdr , endian ), endian ),
533
+ ELFCLASS64 = > .init (try r .takeStruct (Elf64_Ehdr , endian ), endian ),
534
+ else = > return error .InvalidElfClass ,
535
+ };
536
+ }
537
+
538
+ pub fn init (hdr : anytype , endian : std.builtin.Endian ) Header {
537
539
// Converting integers to exhaustive enums using `@enumFromInt` could cause a panic.
538
540
comptime assert (! @typeInfo (OSABI ).@"enum" .is_exhaustive );
539
- const os_abi : OSABI = @enumFromInt (hdr32 .e_ident [EI_OSABI ]);
541
+ return .{
542
+ .is_64 = switch (@TypeOf (hdr )) {
543
+ Elf32_Ehdr = > false ,
544
+ Elf64_Ehdr = > true ,
545
+ else = > @compileError ("bad type" ),
546
+ },
547
+ .endian = endian ,
548
+ .os_abi = @enumFromInt (hdr .e_ident [EI_OSABI ]),
549
+ .abi_version = hdr .e_ident [EI_ABIVERSION ],
550
+ .type = hdr .e_type ,
551
+ .machine = hdr .e_machine ,
552
+ .entry = hdr .e_entry ,
553
+ .phoff = hdr .e_phoff ,
554
+ .shoff = hdr .e_shoff ,
555
+ .phentsize = hdr .e_phentsize ,
556
+ .phnum = hdr .e_phnum ,
557
+ .shentsize = hdr .e_shentsize ,
558
+ .shnum = hdr .e_shnum ,
559
+ .shstrndx = hdr .e_shstrndx ,
560
+ };
561
+ }
562
+ };
540
563
541
- // The meaning of this value depends on `os_abi` so just make it available as `u8`.
542
- const abi_version = hdr32 .e_ident [EI_ABIVERSION ];
564
+ pub const ProgramHeaderIterator = struct {
565
+ elf_header : Header ,
566
+ file_reader : * std.fs.File.Reader ,
567
+ index : usize = 0 ,
543
568
544
- const @"type" = if (need_bswap ) blk : {
545
- comptime assert (! @typeInfo (ET ).@"enum" .is_exhaustive );
546
- const value = @intFromEnum (hdr32 .e_type );
547
- break :blk @as (ET , @enumFromInt (@byteSwap (value )));
548
- } else hdr32 .e_type ;
569
+ pub fn next (it : * ProgramHeaderIterator ) ! ? Elf64_Phdr {
570
+ if (it .index >= it .elf_header .phnum ) return null ;
571
+ defer it .index += 1 ;
549
572
550
- const machine = if (need_bswap ) blk : {
551
- comptime assert (! @typeInfo (EM ).@"enum" .is_exhaustive );
552
- const value = @intFromEnum (hdr32 .e_machine );
553
- break :blk @as (EM , @enumFromInt (@byteSwap (value )));
554
- } else hdr32 .e_machine ;
573
+ if (it .elf_header .is_64 ) {
574
+ const offset = it .elf_header .phoff + @sizeOf (Elf64_Phdr ) * it .index ;
575
+ try it .file_reader .seekTo (offset );
576
+ const phdr = try it .file_reader .interface .takeStruct (Elf64_Phdr , it .elf_header .endian );
577
+ return phdr ;
578
+ }
555
579
556
- return @as (Header , .{
557
- .is_64 = is_64 ,
558
- .endian = endian ,
559
- .os_abi = os_abi ,
560
- .abi_version = abi_version ,
561
- .type = @"type" ,
562
- .machine = machine ,
563
- .entry = int (is_64 , need_bswap , hdr32 .e_entry , hdr64 .e_entry ),
564
- .phoff = int (is_64 , need_bswap , hdr32 .e_phoff , hdr64 .e_phoff ),
565
- .shoff = int (is_64 , need_bswap , hdr32 .e_shoff , hdr64 .e_shoff ),
566
- .phentsize = int (is_64 , need_bswap , hdr32 .e_phentsize , hdr64 .e_phentsize ),
567
- .phnum = int (is_64 , need_bswap , hdr32 .e_phnum , hdr64 .e_phnum ),
568
- .shentsize = int (is_64 , need_bswap , hdr32 .e_shentsize , hdr64 .e_shentsize ),
569
- .shnum = int (is_64 , need_bswap , hdr32 .e_shnum , hdr64 .e_shnum ),
570
- .shstrndx = int (is_64 , need_bswap , hdr32 .e_shstrndx , hdr64 .e_shstrndx ),
571
- });
580
+ const offset = it .elf_header .phoff + @sizeOf (Elf32_Phdr ) * it .index ;
581
+ try it .file_reader .seekTo (offset );
582
+ const phdr = try it .file_reader .interface .takeStruct (Elf32_Phdr , it .elf_header .endian );
583
+ return .{
584
+ .p_type = phdr .p_type ,
585
+ .p_offset = phdr .p_offset ,
586
+ .p_vaddr = phdr .p_vaddr ,
587
+ .p_paddr = phdr .p_paddr ,
588
+ .p_filesz = phdr .p_filesz ,
589
+ .p_memsz = phdr .p_memsz ,
590
+ .p_flags = phdr .p_flags ,
591
+ .p_align = phdr .p_align ,
592
+ };
572
593
}
573
594
};
574
595
575
- pub fn ProgramHeaderIterator (comptime ParseSource : anytype ) type {
576
- return struct {
577
- elf_header : Header ,
578
- parse_source : ParseSource ,
579
- index : usize = 0 ,
580
-
581
- pub fn next (self : * @This ()) ! ? Elf64_Phdr {
582
- if (self .index >= self .elf_header .phnum ) return null ;
583
- defer self .index += 1 ;
584
-
585
- if (self .elf_header .is_64 ) {
586
- var phdr : Elf64_Phdr = undefined ;
587
- const offset = self .elf_header .phoff + @sizeOf (@TypeOf (phdr )) * self .index ;
588
- try self .parse_source .seekableStream ().seekTo (offset );
589
- try self .parse_source .deprecatedReader ().readNoEof (mem .asBytes (& phdr ));
590
-
591
- // ELF endianness matches native endianness.
592
- if (self .elf_header .endian == native_endian ) return phdr ;
593
-
594
- // Convert fields to native endianness.
595
- mem .byteSwapAllFields (Elf64_Phdr , & phdr );
596
- return phdr ;
597
- }
598
-
599
- var phdr : Elf32_Phdr = undefined ;
600
- const offset = self .elf_header .phoff + @sizeOf (@TypeOf (phdr )) * self .index ;
601
- try self .parse_source .seekableStream ().seekTo (offset );
602
- try self .parse_source .deprecatedReader ().readNoEof (mem .asBytes (& phdr ));
603
-
604
- // ELF endianness does NOT match native endianness.
605
- if (self .elf_header .endian != native_endian ) {
606
- // Convert fields to native endianness.
607
- mem .byteSwapAllFields (Elf32_Phdr , & phdr );
608
- }
609
-
610
- // Convert 32-bit header to 64-bit.
611
- return Elf64_Phdr {
612
- .p_type = phdr .p_type ,
613
- .p_offset = phdr .p_offset ,
614
- .p_vaddr = phdr .p_vaddr ,
615
- .p_paddr = phdr .p_paddr ,
616
- .p_filesz = phdr .p_filesz ,
617
- .p_memsz = phdr .p_memsz ,
618
- .p_flags = phdr .p_flags ,
619
- .p_align = phdr .p_align ,
620
- };
621
- }
622
- };
623
- }
596
+ pub const SectionHeaderIterator = struct {
597
+ elf_header : Header ,
598
+ file_reader : * std.fs.File.Reader ,
599
+ index : usize = 0 ,
624
600
625
- pub fn SectionHeaderIterator (comptime ParseSource : anytype ) type {
626
- return struct {
627
- elf_header : Header ,
628
- parse_source : ParseSource ,
629
- index : usize = 0 ,
630
-
631
- pub fn next (self : * @This ()) ! ? Elf64_Shdr {
632
- if (self .index >= self .elf_header .shnum ) return null ;
633
- defer self .index += 1 ;
634
-
635
- if (self .elf_header .is_64 ) {
636
- var shdr : Elf64_Shdr = undefined ;
637
- const offset = self .elf_header .shoff + @sizeOf (@TypeOf (shdr )) * self .index ;
638
- try self .parse_source .seekableStream ().seekTo (offset );
639
- try self .parse_source .deprecatedReader ().readNoEof (mem .asBytes (& shdr ));
640
-
641
- // ELF endianness matches native endianness.
642
- if (self .elf_header .endian == native_endian ) return shdr ;
643
-
644
- // Convert fields to native endianness.
645
- mem .byteSwapAllFields (Elf64_Shdr , & shdr );
646
- return shdr ;
647
- }
648
-
649
- var shdr : Elf32_Shdr = undefined ;
650
- const offset = self .elf_header .shoff + @sizeOf (@TypeOf (shdr )) * self .index ;
651
- try self .parse_source .seekableStream ().seekTo (offset );
652
- try self .parse_source .deprecatedReader ().readNoEof (mem .asBytes (& shdr ));
653
-
654
- // ELF endianness does NOT match native endianness.
655
- if (self .elf_header .endian != native_endian ) {
656
- // Convert fields to native endianness.
657
- mem .byteSwapAllFields (Elf32_Shdr , & shdr );
658
- }
659
-
660
- // Convert 32-bit header to 64-bit.
661
- return Elf64_Shdr {
662
- .sh_name = shdr .sh_name ,
663
- .sh_type = shdr .sh_type ,
664
- .sh_flags = shdr .sh_flags ,
665
- .sh_addr = shdr .sh_addr ,
666
- .sh_offset = shdr .sh_offset ,
667
- .sh_size = shdr .sh_size ,
668
- .sh_link = shdr .sh_link ,
669
- .sh_info = shdr .sh_info ,
670
- .sh_addralign = shdr .sh_addralign ,
671
- .sh_entsize = shdr .sh_entsize ,
672
- };
673
- }
674
- };
675
- }
601
+ pub fn next (it : * SectionHeaderIterator ) ! ? Elf64_Shdr {
602
+ if (it .index >= it .elf_header .shnum ) return null ;
603
+ defer it .index += 1 ;
676
604
677
- fn int (is_64 : bool , need_bswap : bool , int_32 : anytype , int_64 : anytype ) @TypeOf (int_64 ) {
678
- if (is_64 ) {
679
- if (need_bswap ) {
680
- return @byteSwap (int_64 );
681
- } else {
682
- return int_64 ;
605
+ if (it .elf_header .is_64 ) {
606
+ try it .file_reader .seekTo (it .elf_header .shoff + @sizeOf (Elf64_Shdr ) * it .index );
607
+ const shdr = try it .file_reader .interface .takeStruct (Elf64_Shdr , it .elf_header .endian );
608
+ return shdr ;
683
609
}
684
- } else {
685
- return int32 (need_bswap , int_32 , @TypeOf (int_64 ));
686
- }
687
- }
688
610
689
- fn int32 (need_bswap : bool , int_32 : anytype , comptime Int64 : anytype ) Int64 {
690
- if (need_bswap ) {
691
- return @byteSwap (int_32 );
692
- } else {
693
- return int_32 ;
611
+ try it .file_reader .seekTo (it .elf_header .shoff + @sizeOf (Elf32_Shdr ) * it .index );
612
+ const shdr = try it .file_reader .interface .takeStruct (Elf32_Shdr , it .elf_header .endian );
613
+ return .{
614
+ .sh_name = shdr .sh_name ,
615
+ .sh_type = shdr .sh_type ,
616
+ .sh_flags = shdr .sh_flags ,
617
+ .sh_addr = shdr .sh_addr ,
618
+ .sh_offset = shdr .sh_offset ,
619
+ .sh_size = shdr .sh_size ,
620
+ .sh_link = shdr .sh_link ,
621
+ .sh_info = shdr .sh_info ,
622
+ .sh_addralign = shdr .sh_addralign ,
623
+ .sh_entsize = shdr .sh_entsize ,
624
+ };
694
625
}
695
- }
626
+ };
696
627
697
628
pub const ELFCLASSNONE = 0 ;
698
629
pub const ELFCLASS32 = 1 ;
0 commit comments