Skip to content

Commit 3914eaf

Browse files
std.elf: buffer header iterator API (#24691)
Closes #24666.
1 parent 82961a8 commit 3914eaf

File tree

1 file changed

+92
-38
lines changed

1 file changed

+92
-38
lines changed

lib/std/elf.zig

Lines changed: 92 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -502,13 +502,27 @@ pub const Header = struct {
502502
};
503503
}
504504

505+
pub fn iterateProgramHeadersBuffer(h: Header, buf: []const u8) ProgramHeaderBufferIterator {
506+
return .{
507+
.elf_header = h,
508+
.buf = buf,
509+
};
510+
}
511+
505512
pub fn iterateSectionHeaders(h: Header, file_reader: *std.fs.File.Reader) SectionHeaderIterator {
506513
return .{
507514
.elf_header = h,
508515
.file_reader = file_reader,
509516
};
510517
}
511518

519+
pub fn iterateSectionHeadersBuffer(h: Header, buf: []const u8) SectionHeaderBufferIterator {
520+
return .{
521+
.elf_header = h,
522+
.buf = buf,
523+
};
524+
}
525+
512526
pub const ReadError = std.Io.Reader.Error || error{
513527
InvalidElfMagic,
514528
InvalidElfVersion,
@@ -570,29 +584,48 @@ pub const ProgramHeaderIterator = struct {
570584
if (it.index >= it.elf_header.phnum) return null;
571585
defer it.index += 1;
572586

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-
}
579-
580-
const offset = it.elf_header.phoff + @sizeOf(Elf32_Phdr) * it.index;
587+
const offset = it.elf_header.phoff + if (it.elf_header.is_64) @sizeOf(Elf64_Phdr) else @sizeOf(Elf32_Phdr) * it.index;
581588
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-
};
589+
590+
return takePhdr(&it.file_reader.interface, it.elf_header);
591+
}
592+
};
593+
594+
pub const ProgramHeaderBufferIterator = struct {
595+
elf_header: Header,
596+
buf: []const u8,
597+
index: usize = 0,
598+
599+
pub fn next(it: *ProgramHeaderBufferIterator) !?Elf64_Phdr {
600+
if (it.index >= it.elf_header.phnum) return null;
601+
defer it.index += 1;
602+
603+
const offset = it.elf_header.phoff + if (it.elf_header.is_64) @sizeOf(Elf64_Phdr) else @sizeOf(Elf32_Phdr) * it.index;
604+
var reader = std.Io.Reader.fixed(it.buf[offset..]);
605+
606+
return takePhdr(&reader, it.elf_header);
593607
}
594608
};
595609

610+
fn takePhdr(reader: *std.io.Reader, elf_header: Header) !?Elf64_Phdr {
611+
if (elf_header.is_64) {
612+
const phdr = try reader.takeStruct(Elf64_Phdr, elf_header.endian);
613+
return phdr;
614+
}
615+
616+
const phdr = try reader.takeStruct(Elf32_Phdr, elf_header.endian);
617+
return .{
618+
.p_type = phdr.p_type,
619+
.p_offset = phdr.p_offset,
620+
.p_vaddr = phdr.p_vaddr,
621+
.p_paddr = phdr.p_paddr,
622+
.p_filesz = phdr.p_filesz,
623+
.p_memsz = phdr.p_memsz,
624+
.p_flags = phdr.p_flags,
625+
.p_align = phdr.p_align,
626+
};
627+
}
628+
596629
pub const SectionHeaderIterator = struct {
597630
elf_header: Header,
598631
file_reader: *std.fs.File.Reader,
@@ -602,29 +635,50 @@ pub const SectionHeaderIterator = struct {
602635
if (it.index >= it.elf_header.shnum) return null;
603636
defer it.index += 1;
604637

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;
609-
}
638+
const offset = it.elf_header.shoff + if (it.elf_header.is_64) @sizeOf(Elf64_Shdr) else @sizeOf(Elf32_Shdr) * it.index;
639+
try it.file_reader.seekTo(offset);
610640

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-
};
641+
return takeShdr(&it.file_reader.interface, it.elf_header);
642+
}
643+
};
644+
645+
pub const SectionHeaderBufferIterator = struct {
646+
elf_header: Header,
647+
buf: []const u8,
648+
index: usize = 0,
649+
650+
pub fn next(it: *SectionHeaderBufferIterator) !?Elf64_Shdr {
651+
if (it.index >= it.elf_header.shnum) return null;
652+
defer it.index += 1;
653+
654+
const offset = it.elf_header.shoff + if (it.elf_header.is_64) @sizeOf(Elf64_Shdr) else @sizeOf(Elf32_Shdr) * it.index;
655+
var reader = std.Io.Reader.fixed(it.buf[offset..]);
656+
657+
return takeShdr(&reader, it.elf_header);
625658
}
626659
};
627660

661+
fn takeShdr(reader: *std.Io.Reader, elf_header: Header) !?Elf64_Shdr {
662+
if (elf_header.is_64) {
663+
const shdr = try reader.takeStruct(Elf64_Shdr, elf_header.endian);
664+
return shdr;
665+
}
666+
667+
const shdr = try reader.takeStruct(Elf32_Shdr, elf_header.endian);
668+
return .{
669+
.sh_name = shdr.sh_name,
670+
.sh_type = shdr.sh_type,
671+
.sh_flags = shdr.sh_flags,
672+
.sh_addr = shdr.sh_addr,
673+
.sh_offset = shdr.sh_offset,
674+
.sh_size = shdr.sh_size,
675+
.sh_link = shdr.sh_link,
676+
.sh_info = shdr.sh_info,
677+
.sh_addralign = shdr.sh_addralign,
678+
.sh_entsize = shdr.sh_entsize,
679+
};
680+
}
681+
628682
pub const ELFCLASSNONE = 0;
629683
pub const ELFCLASS32 = 1;
630684
pub const ELFCLASS64 = 2;

0 commit comments

Comments
 (0)