mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
elf: Iterate over headers w/o need for allocator
This commit is contained in:
parent
0d31877444
commit
cf15b4c269
@ -46,9 +46,10 @@ const BinaryElfOutput = struct {
|
||||
.segments = ArrayList(*BinaryElfSegment).init(allocator),
|
||||
.sections = ArrayList(*BinaryElfSection).init(allocator),
|
||||
};
|
||||
const elf_hdrs = try std.elf.readAllHeaders(allocator, elf_file);
|
||||
const elf_hdr = try std.elf.readHeader(elf_file);
|
||||
|
||||
for (elf_hdrs.section_headers) |section, i| {
|
||||
var section_headers = elf_hdr.section_header_iterator(elf_file);
|
||||
while (try section_headers.next()) |section| {
|
||||
if (sectionValidForOutput(section)) {
|
||||
const newSection = try allocator.create(BinaryElfSection);
|
||||
|
||||
@ -61,7 +62,8 @@ const BinaryElfOutput = struct {
|
||||
}
|
||||
}
|
||||
|
||||
for (elf_hdrs.program_headers) |phdr, i| {
|
||||
var program_headers = elf_hdr.program_header_iterator(elf_file);
|
||||
while (try program_headers.next()) |phdr| {
|
||||
if (phdr.p_type == elf.PT_LOAD) {
|
||||
const newSegment = try allocator.create(BinaryElfSegment);
|
||||
|
||||
|
||||
265
lib/std/elf.zig
265
lib/std/elf.zig
@ -341,6 +341,20 @@ const Header = struct {
|
||||
shentsize: u16,
|
||||
shnum: u16,
|
||||
shstrndx: u16,
|
||||
|
||||
pub fn program_header_iterator(self: Header, file: File) ProgramHeaderIterator {
|
||||
return .{
|
||||
.elf_header = self,
|
||||
.file = file,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn section_header_iterator(self: Header, file: File) SectionHeaderIterator {
|
||||
return .{
|
||||
.elf_header = self,
|
||||
.file = file,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn readHeader(file: File) !Header {
|
||||
@ -378,144 +392,137 @@ pub fn readHeader(file: File) !Header {
|
||||
});
|
||||
}
|
||||
|
||||
/// All integers are native endian.
|
||||
pub const AllHeaders = struct {
|
||||
header: Header,
|
||||
section_headers: []Elf64_Shdr,
|
||||
program_headers: []Elf64_Phdr,
|
||||
allocator: *mem.Allocator,
|
||||
pub const ProgramHeaderIterator = struct {
|
||||
elf_header: Header,
|
||||
file: File,
|
||||
index: usize = 0,
|
||||
|
||||
pub fn next(self: *ProgramHeaderIterator) !?Elf64_Phdr {
|
||||
if (self.index >= self.elf_header.phnum) return null;
|
||||
defer self.index += 1;
|
||||
|
||||
if (self.elf_header.is_64) {
|
||||
var phdr: Elf64_Phdr = undefined;
|
||||
const offset = self.elf_header.phoff + @sizeOf(@TypeOf(phdr)) * self.index;
|
||||
try preadNoEof(self.file, mem.asBytes(&phdr), offset);
|
||||
|
||||
// ELF endianness matches native endianness.
|
||||
if (self.elf_header.endian == std.builtin.endian) return phdr;
|
||||
|
||||
// Convert fields to native endianness.
|
||||
return Elf64_Phdr{
|
||||
.p_type = @byteSwap(@TypeOf(phdr.p_type), phdr.p_type),
|
||||
.p_offset = @byteSwap(@TypeOf(phdr.p_offset), phdr.p_offset),
|
||||
.p_vaddr = @byteSwap(@TypeOf(phdr.p_vaddr), phdr.p_vaddr),
|
||||
.p_paddr = @byteSwap(@TypeOf(phdr.p_paddr), phdr.p_paddr),
|
||||
.p_filesz = @byteSwap(@TypeOf(phdr.p_filesz), phdr.p_filesz),
|
||||
.p_memsz = @byteSwap(@TypeOf(phdr.p_memsz), phdr.p_memsz),
|
||||
.p_flags = @byteSwap(@TypeOf(phdr.p_flags), phdr.p_flags),
|
||||
.p_align = @byteSwap(@TypeOf(phdr.p_align), phdr.p_align),
|
||||
};
|
||||
}
|
||||
|
||||
var phdr: Elf32_Phdr = undefined;
|
||||
const offset = self.elf_header.phoff + @sizeOf(@TypeOf(phdr)) * self.index;
|
||||
try preadNoEof(self.file, mem.asBytes(&phdr), offset);
|
||||
|
||||
// ELF endianness does NOT match native endianness.
|
||||
if (self.elf_header.endian != std.builtin.endian) {
|
||||
// Convert fields to native endianness.
|
||||
phdr = .{
|
||||
.p_type = @byteSwap(@TypeOf(phdr.p_type), phdr.p_type),
|
||||
.p_offset = @byteSwap(@TypeOf(phdr.p_offset), phdr.p_offset),
|
||||
.p_vaddr = @byteSwap(@TypeOf(phdr.p_vaddr), phdr.p_vaddr),
|
||||
.p_paddr = @byteSwap(@TypeOf(phdr.p_paddr), phdr.p_paddr),
|
||||
.p_filesz = @byteSwap(@TypeOf(phdr.p_filesz), phdr.p_filesz),
|
||||
.p_memsz = @byteSwap(@TypeOf(phdr.p_memsz), phdr.p_memsz),
|
||||
.p_flags = @byteSwap(@TypeOf(phdr.p_flags), phdr.p_flags),
|
||||
.p_align = @byteSwap(@TypeOf(phdr.p_align), phdr.p_align),
|
||||
};
|
||||
}
|
||||
|
||||
// Convert 32-bit header to 64-bit.
|
||||
return Elf64_Phdr{
|
||||
.p_type = phdr.p_type,
|
||||
.p_offset = phdr.p_offset,
|
||||
.p_vaddr = phdr.p_vaddr,
|
||||
.p_paddr = phdr.p_paddr,
|
||||
.p_filesz = phdr.p_filesz,
|
||||
.p_memsz = phdr.p_memsz,
|
||||
.p_flags = phdr.p_flags,
|
||||
.p_align = phdr.p_align,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn readAllHeaders(allocator: *mem.Allocator, file: File) !AllHeaders {
|
||||
var hdrs: AllHeaders = .{
|
||||
.allocator = allocator,
|
||||
.header = try readHeader(file),
|
||||
.section_headers = undefined,
|
||||
.program_headers = undefined,
|
||||
};
|
||||
const is_64 = hdrs.header.is_64;
|
||||
const need_bswap = hdrs.header.endian != std.builtin.endian;
|
||||
pub const SectionHeaderIterator = struct {
|
||||
elf_header: Header,
|
||||
file: File,
|
||||
index: usize = 0,
|
||||
|
||||
hdrs.section_headers = try allocator.alloc(Elf64_Shdr, hdrs.header.shnum);
|
||||
errdefer allocator.free(hdrs.section_headers);
|
||||
pub fn next(self: *SectionHeaderIterator) !?Elf64_Shdr {
|
||||
if (self.index >= self.elf_header.shnum) return null;
|
||||
defer self.index += 1;
|
||||
|
||||
hdrs.program_headers = try allocator.alloc(Elf64_Phdr, hdrs.header.phnum);
|
||||
errdefer allocator.free(hdrs.program_headers);
|
||||
if (self.elf_header.is_64) {
|
||||
var shdr: Elf64_Shdr = undefined;
|
||||
const offset = self.elf_header.phoff + @sizeOf(@TypeOf(shdr)) * self.index;
|
||||
try preadNoEof(self.file, mem.asBytes(&shdr), offset);
|
||||
|
||||
// If the ELF file is 64-bit and same-endianness, then all we have to do is
|
||||
// yeet the bytes into memory.
|
||||
// If only the endianness is different, they can be simply byte swapped.
|
||||
if (is_64) {
|
||||
const shdr_buf = std.mem.sliceAsBytes(hdrs.section_headers);
|
||||
const phdr_buf = std.mem.sliceAsBytes(hdrs.program_headers);
|
||||
try preadNoEof(file, shdr_buf, hdrs.header.shoff);
|
||||
try preadNoEof(file, phdr_buf, hdrs.header.phoff);
|
||||
// ELF endianness matches native endianness.
|
||||
if (self.elf_header.endian == std.builtin.endian) return shdr;
|
||||
|
||||
if (need_bswap) {
|
||||
for (hdrs.section_headers) |*shdr| {
|
||||
shdr.* = .{
|
||||
.sh_name = @byteSwap(@TypeOf(shdr.sh_name), shdr.sh_name),
|
||||
.sh_type = @byteSwap(@TypeOf(shdr.sh_type), shdr.sh_type),
|
||||
.sh_flags = @byteSwap(@TypeOf(shdr.sh_flags), shdr.sh_flags),
|
||||
.sh_addr = @byteSwap(@TypeOf(shdr.sh_addr), shdr.sh_addr),
|
||||
.sh_offset = @byteSwap(@TypeOf(shdr.sh_offset), shdr.sh_offset),
|
||||
.sh_size = @byteSwap(@TypeOf(shdr.sh_size), shdr.sh_size),
|
||||
.sh_link = @byteSwap(@TypeOf(shdr.sh_link), shdr.sh_link),
|
||||
.sh_info = @byteSwap(@TypeOf(shdr.sh_info), shdr.sh_info),
|
||||
.sh_addralign = @byteSwap(@TypeOf(shdr.sh_addralign), shdr.sh_addralign),
|
||||
.sh_entsize = @byteSwap(@TypeOf(shdr.sh_entsize), shdr.sh_entsize),
|
||||
};
|
||||
}
|
||||
for (hdrs.program_headers) |*phdr| {
|
||||
phdr.* = .{
|
||||
.p_type = @byteSwap(@TypeOf(phdr.p_type), phdr.p_type),
|
||||
.p_offset = @byteSwap(@TypeOf(phdr.p_offset), phdr.p_offset),
|
||||
.p_vaddr = @byteSwap(@TypeOf(phdr.p_vaddr), phdr.p_vaddr),
|
||||
.p_paddr = @byteSwap(@TypeOf(phdr.p_paddr), phdr.p_paddr),
|
||||
.p_filesz = @byteSwap(@TypeOf(phdr.p_filesz), phdr.p_filesz),
|
||||
.p_memsz = @byteSwap(@TypeOf(phdr.p_memsz), phdr.p_memsz),
|
||||
.p_flags = @byteSwap(@TypeOf(phdr.p_flags), phdr.p_flags),
|
||||
.p_align = @byteSwap(@TypeOf(phdr.p_align), phdr.p_align),
|
||||
};
|
||||
}
|
||||
// Convert fields to native endianness.
|
||||
return Elf64_Shdr{
|
||||
.sh_name = @byteSwap(@TypeOf(shdr.sh_name), shdr.sh_name),
|
||||
.sh_type = @byteSwap(@TypeOf(shdr.sh_type), shdr.sh_type),
|
||||
.sh_flags = @byteSwap(@TypeOf(shdr.sh_flags), shdr.sh_flags),
|
||||
.sh_addr = @byteSwap(@TypeOf(shdr.sh_addr), shdr.sh_addr),
|
||||
.sh_offset = @byteSwap(@TypeOf(shdr.sh_offset), shdr.sh_offset),
|
||||
.sh_size = @byteSwap(@TypeOf(shdr.sh_size), shdr.sh_size),
|
||||
.sh_link = @byteSwap(@TypeOf(shdr.sh_link), shdr.sh_link),
|
||||
.sh_info = @byteSwap(@TypeOf(shdr.sh_info), shdr.sh_info),
|
||||
.sh_addralign = @byteSwap(@TypeOf(shdr.sh_addralign), shdr.sh_addralign),
|
||||
.sh_entsize = @byteSwap(@TypeOf(shdr.sh_entsize), shdr.sh_entsize),
|
||||
};
|
||||
}
|
||||
|
||||
return hdrs;
|
||||
var shdr: Elf32_Shdr = undefined;
|
||||
const offset = self.elf_header.shoff + @sizeOf(@TypeOf(shdr)) * self.index;
|
||||
try preadNoEof(self.file, mem.asBytes(&shdr), offset);
|
||||
|
||||
// ELF endianness does NOT match native endianness.
|
||||
if (self.elf_header.endian != std.builtin.endian) {
|
||||
// Convert fields to native endianness.
|
||||
shdr = .{
|
||||
.sh_name = @byteSwap(@TypeOf(shdr.sh_name), shdr.sh_name),
|
||||
.sh_type = @byteSwap(@TypeOf(shdr.sh_type), shdr.sh_type),
|
||||
.sh_flags = @byteSwap(@TypeOf(shdr.sh_flags), shdr.sh_flags),
|
||||
.sh_addr = @byteSwap(@TypeOf(shdr.sh_addr), shdr.sh_addr),
|
||||
.sh_offset = @byteSwap(@TypeOf(shdr.sh_offset), shdr.sh_offset),
|
||||
.sh_size = @byteSwap(@TypeOf(shdr.sh_size), shdr.sh_size),
|
||||
.sh_link = @byteSwap(@TypeOf(shdr.sh_link), shdr.sh_link),
|
||||
.sh_info = @byteSwap(@TypeOf(shdr.sh_info), shdr.sh_info),
|
||||
.sh_addralign = @byteSwap(@TypeOf(shdr.sh_addralign), shdr.sh_addralign),
|
||||
.sh_entsize = @byteSwap(@TypeOf(shdr.sh_entsize), shdr.sh_entsize),
|
||||
};
|
||||
}
|
||||
|
||||
// Convert 32-bit header to 64-bit.
|
||||
return Elf64_Shdr{
|
||||
.sh_name = shdr.sh_name,
|
||||
.sh_type = shdr.sh_type,
|
||||
.sh_flags = shdr.sh_flags,
|
||||
.sh_addr = shdr.sh_addr,
|
||||
.sh_offset = shdr.sh_offset,
|
||||
.sh_size = shdr.sh_size,
|
||||
.sh_link = shdr.sh_link,
|
||||
.sh_info = shdr.sh_info,
|
||||
.sh_addralign = shdr.sh_addralign,
|
||||
.sh_entsize = shdr.sh_entsize,
|
||||
};
|
||||
}
|
||||
|
||||
const shdrs_32 = try allocator.alloc(Elf32_Shdr, hdrs.header.shnum);
|
||||
defer allocator.free(shdrs_32);
|
||||
|
||||
const phdrs_32 = try allocator.alloc(Elf32_Phdr, hdrs.header.phnum);
|
||||
defer allocator.free(phdrs_32);
|
||||
|
||||
const shdr_buf = std.mem.sliceAsBytes(shdrs_32);
|
||||
const phdr_buf = std.mem.sliceAsBytes(phdrs_32);
|
||||
try preadNoEof(file, shdr_buf, hdrs.header.shoff);
|
||||
try preadNoEof(file, phdr_buf, hdrs.header.phoff);
|
||||
|
||||
if (need_bswap) {
|
||||
for (hdrs.section_headers) |*shdr, i| {
|
||||
const o = shdrs_32[i];
|
||||
shdr.* = .{
|
||||
.sh_name = @byteSwap(@TypeOf(o.sh_name), o.sh_name),
|
||||
.sh_type = @byteSwap(@TypeOf(o.sh_type), o.sh_type),
|
||||
.sh_flags = @byteSwap(@TypeOf(o.sh_flags), o.sh_flags),
|
||||
.sh_addr = @byteSwap(@TypeOf(o.sh_addr), o.sh_addr),
|
||||
.sh_offset = @byteSwap(@TypeOf(o.sh_offset), o.sh_offset),
|
||||
.sh_size = @byteSwap(@TypeOf(o.sh_size), o.sh_size),
|
||||
.sh_link = @byteSwap(@TypeOf(o.sh_link), o.sh_link),
|
||||
.sh_info = @byteSwap(@TypeOf(o.sh_info), o.sh_info),
|
||||
.sh_addralign = @byteSwap(@TypeOf(o.sh_addralign), o.sh_addralign),
|
||||
.sh_entsize = @byteSwap(@TypeOf(o.sh_entsize), o.sh_entsize),
|
||||
};
|
||||
}
|
||||
for (hdrs.program_headers) |*phdr, i| {
|
||||
const o = phdrs_32[i];
|
||||
phdr.* = .{
|
||||
.p_type = @byteSwap(@TypeOf(o.p_type), o.p_type),
|
||||
.p_offset = @byteSwap(@TypeOf(o.p_offset), o.p_offset),
|
||||
.p_vaddr = @byteSwap(@TypeOf(o.p_vaddr), o.p_vaddr),
|
||||
.p_paddr = @byteSwap(@TypeOf(o.p_paddr), o.p_paddr),
|
||||
.p_filesz = @byteSwap(@TypeOf(o.p_filesz), o.p_filesz),
|
||||
.p_memsz = @byteSwap(@TypeOf(o.p_memsz), o.p_memsz),
|
||||
.p_flags = @byteSwap(@TypeOf(o.p_flags), o.p_flags),
|
||||
.p_align = @byteSwap(@TypeOf(o.p_align), o.p_align),
|
||||
};
|
||||
}
|
||||
} else {
|
||||
for (hdrs.section_headers) |*shdr, i| {
|
||||
const o = shdrs_32[i];
|
||||
shdr.* = .{
|
||||
.sh_name = o.sh_name,
|
||||
.sh_type = o.sh_type,
|
||||
.sh_flags = o.sh_flags,
|
||||
.sh_addr = o.sh_addr,
|
||||
.sh_offset = o.sh_offset,
|
||||
.sh_size = o.sh_size,
|
||||
.sh_link = o.sh_link,
|
||||
.sh_info = o.sh_info,
|
||||
.sh_addralign = o.sh_addralign,
|
||||
.sh_entsize = o.sh_entsize,
|
||||
};
|
||||
}
|
||||
for (hdrs.program_headers) |*phdr, i| {
|
||||
const o = phdrs_32[i];
|
||||
phdr.* = .{
|
||||
.p_type = o.p_type,
|
||||
.p_offset = o.p_offset,
|
||||
.p_vaddr = o.p_vaddr,
|
||||
.p_paddr = o.p_paddr,
|
||||
.p_filesz = o.p_filesz,
|
||||
.p_memsz = o.p_memsz,
|
||||
.p_flags = o.p_flags,
|
||||
.p_align = o.p_align,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return hdrs;
|
||||
}
|
||||
};
|
||||
|
||||
pub fn int(is_64: bool, need_bswap: bool, int_32: anytype, int_64: anytype) @TypeOf(int_64) {
|
||||
if (is_64) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user