authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-04 11:56:31-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-03-04 11:56:31-08:00
logffb2568a9f0d038a94a23bfe776602ac9099e2a0
tree44d937a66f97457b40a2bff3183d762cd7bc2ea3
parent34ca6b7b449f065fd0f65f8cfad82140cafe4c7d
parentaffb57aad97240bf183015e6acba7eab4a9276bb
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #7763 from kivikakk/zig-elf-parse

std.elf: expose parsing decoupled from std.fs.File

3 files changed, 178 insertions(+), 187 deletions(-)

lib/std/build/emit_raw.zig+3-3
...@@ -51,9 +51,9 @@ const BinaryElfOutput = struct {...@@ -51,9 +51,9 @@ const BinaryElfOutput = struct {
51 .segments = ArrayList(*BinaryElfSegment).init(allocator),51 .segments = ArrayList(*BinaryElfSegment).init(allocator),
52 .sections = ArrayList(*BinaryElfSection).init(allocator),52 .sections = ArrayList(*BinaryElfSection).init(allocator),
53 };53 };
54 const elf_hdr = try std.elf.readHeader(elf_file);54 const elf_hdr = try std.elf.Header.read(&elf_file);
5555
56 var section_headers = elf_hdr.section_header_iterator(elf_file);56 var section_headers = elf_hdr.section_header_iterator(&elf_file);
57 while (try section_headers.next()) |section| {57 while (try section_headers.next()) |section| {
58 if (sectionValidForOutput(section)) {58 if (sectionValidForOutput(section)) {
59 const newSection = try allocator.create(BinaryElfSection);59 const newSection = try allocator.create(BinaryElfSection);
...@@ -67,7 +67,7 @@ const BinaryElfOutput = struct {...@@ -67,7 +67,7 @@ const BinaryElfOutput = struct {
67 }67 }
68 }68 }
6969
70 var program_headers = elf_hdr.program_header_iterator(elf_file);70 var program_headers = elf_hdr.program_header_iterator(&elf_file);
71 while (try program_headers.next()) |phdr| {71 while (try program_headers.next()) |phdr| {
72 if (phdr.p_type == elf.PT_LOAD) {72 if (phdr.p_type == elf.PT_LOAD) {
73 const newSegment = try allocator.create(BinaryElfSegment);73 const newSegment = try allocator.create(BinaryElfSegment);
lib/std/elf.zig+173-182
...@@ -335,7 +335,7 @@ pub const ET = extern enum(u16) {...@@ -335,7 +335,7 @@ pub const ET = extern enum(u16) {
335};335};
336336
337/// All integers are native endian.337/// All integers are native endian.
338const Header = struct {338pub const Header = struct {
339 endian: builtin.Endian,339 endian: builtin.Endian,
340 is_64: bool,340 is_64: bool,
341 entry: u64,341 entry: u64,
...@@ -347,187 +347,200 @@ const Header = struct {...@@ -347,187 +347,200 @@ const Header = struct {
347 shnum: u16,347 shnum: u16,
348 shstrndx: u16,348 shstrndx: u16,
349349
350 pub fn program_header_iterator(self: Header, file: File) ProgramHeaderIterator {350 pub fn program_header_iterator(self: Header, parse_source: anytype) ProgramHeaderIterator(@TypeOf(parse_source)) {
351 return .{351 return ProgramHeaderIterator(@TypeOf(parse_source)){
352 .elf_header = self,352 .elf_header = self,
353 .file = file,353 .parse_source = parse_source,
354 };354 };
355 }355 }
356356
357 pub fn section_header_iterator(self: Header, file: File) SectionHeaderIterator {357 pub fn section_header_iterator(self: Header, parse_source: anytype) SectionHeaderIterator(@TypeOf(parse_source)) {
358 return .{358 return SectionHeaderIterator(@TypeOf(parse_source)){
359 .elf_header = self,359 .elf_header = self,
360 .file = file,360 .parse_source = parse_source,
361 };361 };
362 }362 }
363};
364363
365pub fn readHeader(file: File) !Header {364 pub fn read(parse_source: anytype) !Header {
366 var hdr_buf: [@sizeOf(Elf64_Ehdr)]u8 align(@alignOf(Elf64_Ehdr)) = undefined;365 var hdr_buf: [@sizeOf(Elf64_Ehdr)]u8 align(@alignOf(Elf64_Ehdr)) = undefined;
367 try preadNoEof(file, &hdr_buf, 0);366 try parse_source.seekableStream().seekTo(0);
368 const hdr32 = @ptrCast(*Elf32_Ehdr, &hdr_buf);367 try parse_source.reader().readNoEof(&hdr_buf);
369 const hdr64 = @ptrCast(*Elf64_Ehdr, &hdr_buf);368 return Header.parse(&hdr_buf);
370 if (!mem.eql(u8, hdr32.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic;369 }
371 if (hdr32.e_ident[EI_VERSION] != 1) return error.InvalidElfVersion;
372
373 const endian: std.builtin.Endian = switch (hdr32.e_ident[EI_DATA]) {
374 ELFDATA2LSB => .Little,
375 ELFDATA2MSB => .Big,
376 else => return error.InvalidElfEndian,
377 };
378 const need_bswap = endian != std.builtin.endian;
379370
380 const is_64 = switch (hdr32.e_ident[EI_CLASS]) {371 pub fn parse(hdr_buf: *align(@alignOf(Elf64_Ehdr)) const [@sizeOf(Elf64_Ehdr)]u8) !Header {
381 ELFCLASS32 => false,372 const hdr32 = @ptrCast(*const Elf32_Ehdr, hdr_buf);
382 ELFCLASS64 => true,373 const hdr64 = @ptrCast(*const Elf64_Ehdr, hdr_buf);
383 else => return error.InvalidElfClass,374 if (!mem.eql(u8, hdr32.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic;
384 };375 if (hdr32.e_ident[EI_VERSION] != 1) return error.InvalidElfVersion;
385376
386 return @as(Header, .{377 const endian: std.builtin.Endian = switch (hdr32.e_ident[EI_DATA]) {
387 .endian = endian,378 ELFDATA2LSB => .Little,
388 .is_64 = is_64,379 ELFDATA2MSB => .Big,
389 .entry = int(is_64, need_bswap, hdr32.e_entry, hdr64.e_entry),380 else => return error.InvalidElfEndian,
390 .phoff = int(is_64, need_bswap, hdr32.e_phoff, hdr64.e_phoff),381 };
391 .shoff = int(is_64, need_bswap, hdr32.e_shoff, hdr64.e_shoff),382 const need_bswap = endian != std.builtin.endian;
392 .phentsize = int(is_64, need_bswap, hdr32.e_phentsize, hdr64.e_phentsize),
393 .phnum = int(is_64, need_bswap, hdr32.e_phnum, hdr64.e_phnum),
394 .shentsize = int(is_64, need_bswap, hdr32.e_shentsize, hdr64.e_shentsize),
395 .shnum = int(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum),
396 .shstrndx = int(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx),
397 });
398}
399383
400pub const ProgramHeaderIterator = struct {384 const is_64 = switch (hdr32.e_ident[EI_CLASS]) {
401 elf_header: Header,385 ELFCLASS32 => false,
402 file: File,386 ELFCLASS64 => true,
403 index: usize = 0,387 else => return error.InvalidElfClass,
388 };
404389
405 pub fn next(self: *ProgramHeaderIterator) !?Elf64_Phdr {390 return @as(Header, .{
406 if (self.index >= self.elf_header.phnum) return null;391 .endian = endian,
407 defer self.index += 1;392 .is_64 = is_64,
393 .entry = int(is_64, need_bswap, hdr32.e_entry, hdr64.e_entry),
394 .phoff = int(is_64, need_bswap, hdr32.e_phoff, hdr64.e_phoff),
395 .shoff = int(is_64, need_bswap, hdr32.e_shoff, hdr64.e_shoff),
396 .phentsize = int(is_64, need_bswap, hdr32.e_phentsize, hdr64.e_phentsize),
397 .phnum = int(is_64, need_bswap, hdr32.e_phnum, hdr64.e_phnum),
398 .shentsize = int(is_64, need_bswap, hdr32.e_shentsize, hdr64.e_shentsize),
399 .shnum = int(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum),
400 .shstrndx = int(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx),
401 });
402 }
403};
408404
409 if (self.elf_header.is_64) {405pub fn ProgramHeaderIterator(ParseSource: anytype) type {
410 var phdr: Elf64_Phdr = undefined;406 return struct {
407 elf_header: Header,
408 parse_source: ParseSource,
409 index: usize = 0,
410
411 pub fn next(self: *@This()) !?Elf64_Phdr {
412 if (self.index >= self.elf_header.phnum) return null;
413 defer self.index += 1;
414
415 if (self.elf_header.is_64) {
416 var phdr: Elf64_Phdr = undefined;
417 const offset = self.elf_header.phoff + @sizeOf(@TypeOf(phdr)) * self.index;
418 try self.parse_source.seekableStream().seekTo(offset);
419 try self.parse_source.reader().readNoEof(mem.asBytes(&phdr));
420
421 // ELF endianness matches native endianness.
422 if (self.elf_header.endian == std.builtin.endian) return phdr;
423
424 // Convert fields to native endianness.
425 return Elf64_Phdr{
426 .p_type = @byteSwap(@TypeOf(phdr.p_type), phdr.p_type),
427 .p_offset = @byteSwap(@TypeOf(phdr.p_offset), phdr.p_offset),
428 .p_vaddr = @byteSwap(@TypeOf(phdr.p_vaddr), phdr.p_vaddr),
429 .p_paddr = @byteSwap(@TypeOf(phdr.p_paddr), phdr.p_paddr),
430 .p_filesz = @byteSwap(@TypeOf(phdr.p_filesz), phdr.p_filesz),
431 .p_memsz = @byteSwap(@TypeOf(phdr.p_memsz), phdr.p_memsz),
432 .p_flags = @byteSwap(@TypeOf(phdr.p_flags), phdr.p_flags),
433 .p_align = @byteSwap(@TypeOf(phdr.p_align), phdr.p_align),
434 };
435 }
436
437 var phdr: Elf32_Phdr = undefined;
411 const offset = self.elf_header.phoff + @sizeOf(@TypeOf(phdr)) * self.index;438 const offset = self.elf_header.phoff + @sizeOf(@TypeOf(phdr)) * self.index;
412 try preadNoEof(self.file, mem.asBytes(&phdr), offset);439 try self.parse_source.seekableStream().seekTo(offset);
413440 try self.parse_source.reader().readNoEof(mem.asBytes(&phdr));
414 // ELF endianness matches native endianness.441
415 if (self.elf_header.endian == std.builtin.endian) return phdr;442 // ELF endianness does NOT match native endianness.
416443 if (self.elf_header.endian != std.builtin.endian) {
417 // Convert fields to native endianness.444 // Convert fields to native endianness.
445 phdr = .{
446 .p_type = @byteSwap(@TypeOf(phdr.p_type), phdr.p_type),
447 .p_offset = @byteSwap(@TypeOf(phdr.p_offset), phdr.p_offset),
448 .p_vaddr = @byteSwap(@TypeOf(phdr.p_vaddr), phdr.p_vaddr),
449 .p_paddr = @byteSwap(@TypeOf(phdr.p_paddr), phdr.p_paddr),
450 .p_filesz = @byteSwap(@TypeOf(phdr.p_filesz), phdr.p_filesz),
451 .p_memsz = @byteSwap(@TypeOf(phdr.p_memsz), phdr.p_memsz),
452 .p_flags = @byteSwap(@TypeOf(phdr.p_flags), phdr.p_flags),
453 .p_align = @byteSwap(@TypeOf(phdr.p_align), phdr.p_align),
454 };
455 }
456
457 // Convert 32-bit header to 64-bit.
418 return Elf64_Phdr{458 return Elf64_Phdr{
419 .p_type = @byteSwap(@TypeOf(phdr.p_type), phdr.p_type),459 .p_type = phdr.p_type,
420 .p_offset = @byteSwap(@TypeOf(phdr.p_offset), phdr.p_offset),460 .p_offset = phdr.p_offset,
421 .p_vaddr = @byteSwap(@TypeOf(phdr.p_vaddr), phdr.p_vaddr),461 .p_vaddr = phdr.p_vaddr,
422 .p_paddr = @byteSwap(@TypeOf(phdr.p_paddr), phdr.p_paddr),462 .p_paddr = phdr.p_paddr,
423 .p_filesz = @byteSwap(@TypeOf(phdr.p_filesz), phdr.p_filesz),463 .p_filesz = phdr.p_filesz,
424 .p_memsz = @byteSwap(@TypeOf(phdr.p_memsz), phdr.p_memsz),464 .p_memsz = phdr.p_memsz,
425 .p_flags = @byteSwap(@TypeOf(phdr.p_flags), phdr.p_flags),465 .p_flags = phdr.p_flags,
426 .p_align = @byteSwap(@TypeOf(phdr.p_align), phdr.p_align),466 .p_align = phdr.p_align,
427 };467 };
428 }468 }
469 };
470}
429471
430 var phdr: Elf32_Phdr = undefined;472pub fn SectionHeaderIterator(ParseSource: anytype) type {
431 const offset = self.elf_header.phoff + @sizeOf(@TypeOf(phdr)) * self.index;473 return struct {
432 try preadNoEof(self.file, mem.asBytes(&phdr), offset);474 elf_header: Header,
433475 parse_source: ParseSource,
434 // ELF endianness does NOT match native endianness.476 index: usize = 0,
435 if (self.elf_header.endian != std.builtin.endian) {477
436 // Convert fields to native endianness.478 pub fn next(self: *@This()) !?Elf64_Shdr {
437 phdr = .{479 if (self.index >= self.elf_header.shnum) return null;
438 .p_type = @byteSwap(@TypeOf(phdr.p_type), phdr.p_type),480 defer self.index += 1;
439 .p_offset = @byteSwap(@TypeOf(phdr.p_offset), phdr.p_offset),481
440 .p_vaddr = @byteSwap(@TypeOf(phdr.p_vaddr), phdr.p_vaddr),482 if (self.elf_header.is_64) {
441 .p_paddr = @byteSwap(@TypeOf(phdr.p_paddr), phdr.p_paddr),483 var shdr: Elf64_Shdr = undefined;
442 .p_filesz = @byteSwap(@TypeOf(phdr.p_filesz), phdr.p_filesz),484 const offset = self.elf_header.shoff + @sizeOf(@TypeOf(shdr)) * self.index;
443 .p_memsz = @byteSwap(@TypeOf(phdr.p_memsz), phdr.p_memsz),485 try self.parse_source.seekableStream().seekTo(offset);
444 .p_flags = @byteSwap(@TypeOf(phdr.p_flags), phdr.p_flags),486 try self.parse_source.reader().readNoEof(mem.asBytes(&shdr));
445 .p_align = @byteSwap(@TypeOf(phdr.p_align), phdr.p_align),487
446 };488 // ELF endianness matches native endianness.
447 }489 if (self.elf_header.endian == std.builtin.endian) return shdr;
448490
449 // Convert 32-bit header to 64-bit.491 // Convert fields to native endianness.
450 return Elf64_Phdr{492 return Elf64_Shdr{
451 .p_type = phdr.p_type,493 .sh_name = @byteSwap(@TypeOf(shdr.sh_name), shdr.sh_name),
452 .p_offset = phdr.p_offset,494 .sh_type = @byteSwap(@TypeOf(shdr.sh_type), shdr.sh_type),
453 .p_vaddr = phdr.p_vaddr,495 .sh_flags = @byteSwap(@TypeOf(shdr.sh_flags), shdr.sh_flags),
454 .p_paddr = phdr.p_paddr,496 .sh_addr = @byteSwap(@TypeOf(shdr.sh_addr), shdr.sh_addr),
455 .p_filesz = phdr.p_filesz,497 .sh_offset = @byteSwap(@TypeOf(shdr.sh_offset), shdr.sh_offset),
456 .p_memsz = phdr.p_memsz,498 .sh_size = @byteSwap(@TypeOf(shdr.sh_size), shdr.sh_size),
457 .p_flags = phdr.p_flags,499 .sh_link = @byteSwap(@TypeOf(shdr.sh_link), shdr.sh_link),
458 .p_align = phdr.p_align,500 .sh_info = @byteSwap(@TypeOf(shdr.sh_info), shdr.sh_info),
459 };501 .sh_addralign = @byteSwap(@TypeOf(shdr.sh_addralign), shdr.sh_addralign),
460 }502 .sh_entsize = @byteSwap(@TypeOf(shdr.sh_entsize), shdr.sh_entsize),
461};503 };
462504 }
463pub const SectionHeaderIterator = struct {505
464 elf_header: Header,506 var shdr: Elf32_Shdr = undefined;
465 file: File,
466 index: usize = 0,
467
468 pub fn next(self: *SectionHeaderIterator) !?Elf64_Shdr {
469 if (self.index >= self.elf_header.shnum) return null;
470 defer self.index += 1;
471
472 if (self.elf_header.is_64) {
473 var shdr: Elf64_Shdr = undefined;
474 const offset = self.elf_header.shoff + @sizeOf(@TypeOf(shdr)) * self.index;507 const offset = self.elf_header.shoff + @sizeOf(@TypeOf(shdr)) * self.index;
475 try preadNoEof(self.file, mem.asBytes(&shdr), offset);508 try self.parse_source.seekableStream().seekTo(offset);
476509 try self.parse_source.reader().readNoEof(mem.asBytes(&shdr));
477 // ELF endianness matches native endianness.510
478 if (self.elf_header.endian == std.builtin.endian) return shdr;511 // ELF endianness does NOT match native endianness.
479512 if (self.elf_header.endian != std.builtin.endian) {
480 // Convert fields to native endianness.513 // Convert fields to native endianness.
514 shdr = .{
515 .sh_name = @byteSwap(@TypeOf(shdr.sh_name), shdr.sh_name),
516 .sh_type = @byteSwap(@TypeOf(shdr.sh_type), shdr.sh_type),
517 .sh_flags = @byteSwap(@TypeOf(shdr.sh_flags), shdr.sh_flags),
518 .sh_addr = @byteSwap(@TypeOf(shdr.sh_addr), shdr.sh_addr),
519 .sh_offset = @byteSwap(@TypeOf(shdr.sh_offset), shdr.sh_offset),
520 .sh_size = @byteSwap(@TypeOf(shdr.sh_size), shdr.sh_size),
521 .sh_link = @byteSwap(@TypeOf(shdr.sh_link), shdr.sh_link),
522 .sh_info = @byteSwap(@TypeOf(shdr.sh_info), shdr.sh_info),
523 .sh_addralign = @byteSwap(@TypeOf(shdr.sh_addralign), shdr.sh_addralign),
524 .sh_entsize = @byteSwap(@TypeOf(shdr.sh_entsize), shdr.sh_entsize),
525 };
526 }
527
528 // Convert 32-bit header to 64-bit.
481 return Elf64_Shdr{529 return Elf64_Shdr{
482 .sh_name = @byteSwap(@TypeOf(shdr.sh_name), shdr.sh_name),530 .sh_name = shdr.sh_name,
483 .sh_type = @byteSwap(@TypeOf(shdr.sh_type), shdr.sh_type),531 .sh_type = shdr.sh_type,
484 .sh_flags = @byteSwap(@TypeOf(shdr.sh_flags), shdr.sh_flags),532 .sh_flags = shdr.sh_flags,
485 .sh_addr = @byteSwap(@TypeOf(shdr.sh_addr), shdr.sh_addr),533 .sh_addr = shdr.sh_addr,
486 .sh_offset = @byteSwap(@TypeOf(shdr.sh_offset), shdr.sh_offset),534 .sh_offset = shdr.sh_offset,
487 .sh_size = @byteSwap(@TypeOf(shdr.sh_size), shdr.sh_size),535 .sh_size = shdr.sh_size,
488 .sh_link = @byteSwap(@TypeOf(shdr.sh_link), shdr.sh_link),536 .sh_link = shdr.sh_link,
489 .sh_info = @byteSwap(@TypeOf(shdr.sh_info), shdr.sh_info),537 .sh_info = shdr.sh_info,
490 .sh_addralign = @byteSwap(@TypeOf(shdr.sh_addralign), shdr.sh_addralign),538 .sh_addralign = shdr.sh_addralign,
491 .sh_entsize = @byteSwap(@TypeOf(shdr.sh_entsize), shdr.sh_entsize),539 .sh_entsize = shdr.sh_entsize,
492 };540 };
493 }541 }
494542 };
495 var shdr: Elf32_Shdr = undefined;543}
496 const offset = self.elf_header.shoff + @sizeOf(@TypeOf(shdr)) * self.index;
497 try preadNoEof(self.file, mem.asBytes(&shdr), offset);
498
499 // ELF endianness does NOT match native endianness.
500 if (self.elf_header.endian != std.builtin.endian) {
501 // Convert fields to native endianness.
502 shdr = .{
503 .sh_name = @byteSwap(@TypeOf(shdr.sh_name), shdr.sh_name),
504 .sh_type = @byteSwap(@TypeOf(shdr.sh_type), shdr.sh_type),
505 .sh_flags = @byteSwap(@TypeOf(shdr.sh_flags), shdr.sh_flags),
506 .sh_addr = @byteSwap(@TypeOf(shdr.sh_addr), shdr.sh_addr),
507 .sh_offset = @byteSwap(@TypeOf(shdr.sh_offset), shdr.sh_offset),
508 .sh_size = @byteSwap(@TypeOf(shdr.sh_size), shdr.sh_size),
509 .sh_link = @byteSwap(@TypeOf(shdr.sh_link), shdr.sh_link),
510 .sh_info = @byteSwap(@TypeOf(shdr.sh_info), shdr.sh_info),
511 .sh_addralign = @byteSwap(@TypeOf(shdr.sh_addralign), shdr.sh_addralign),
512 .sh_entsize = @byteSwap(@TypeOf(shdr.sh_entsize), shdr.sh_entsize),
513 };
514 }
515
516 // Convert 32-bit header to 64-bit.
517 return Elf64_Shdr{
518 .sh_name = shdr.sh_name,
519 .sh_type = shdr.sh_type,
520 .sh_flags = shdr.sh_flags,
521 .sh_addr = shdr.sh_addr,
522 .sh_offset = shdr.sh_offset,
523 .sh_size = shdr.sh_size,
524 .sh_link = shdr.sh_link,
525 .sh_info = shdr.sh_info,
526 .sh_addralign = shdr.sh_addralign,
527 .sh_entsize = shdr.sh_entsize,
528 };
529 }
530};
531544
532pub fn int(is_64: bool, need_bswap: bool, int_32: anytype, int_64: anytype) @TypeOf(int_64) {545pub fn int(is_64: bool, need_bswap: bool, int_32: anytype, int_64: anytype) @TypeOf(int_64) {
533 if (is_64) {546 if (is_64) {
...@@ -549,28 +562,6 @@ pub fn int32(need_bswap: bool, int_32: anytype, comptime Int64: anytype) Int64 {...@@ -549,28 +562,6 @@ pub fn int32(need_bswap: bool, int_32: anytype, comptime Int64: anytype) Int64 {
549 }562 }
550}563}
551564
552fn preadNoEof(file: std.fs.File, buf: []u8, offset: u64) !void {
553 var i: usize = 0;
554 while (i < buf.len) {
555 const len = file.pread(buf[i .. buf.len - i], offset + i) catch |err| switch (err) {
556 error.SystemResources => return error.SystemResources,
557 error.IsDir => return error.UnableToReadElfFile,
558 error.OperationAborted => return error.UnableToReadElfFile,
559 error.BrokenPipe => return error.UnableToReadElfFile,
560 error.Unseekable => return error.UnableToReadElfFile,
561 error.ConnectionResetByPeer => return error.UnableToReadElfFile,
562 error.ConnectionTimedOut => return error.UnableToReadElfFile,
563 error.InputOutput => return error.FileSystem,
564 error.Unexpected => return error.Unexpected,
565 error.WouldBlock => return error.Unexpected,
566 error.NotOpenForReading => return error.Unexpected,
567 error.AccessDenied => return error.Unexpected,
568 };
569 if (len == 0) return error.UnexpectedEndOfFile;
570 i += len;
571 }
572}
573
574pub const EI_NIDENT = 16;565pub const EI_NIDENT = 16;
575566
576pub const EI_CLASS = 4;567pub const EI_CLASS = 4;
src/test.zig+2-2
...@@ -1030,8 +1030,8 @@ pub const TestContext = struct {...@@ -1030,8 +1030,8 @@ pub const TestContext = struct {
1030 var file = try tmp_dir.openFile(bin_name, .{ .read = true });1030 var file = try tmp_dir.openFile(bin_name, .{ .read = true });
1031 defer file.close();1031 defer file.close();
10321032
1033 const header = try std.elf.readHeader(file);1033 const header = try std.elf.Header.read(&file);
1034 var iterator = header.program_header_iterator(file);1034 var iterator = header.program_header_iterator(&file);
10351035
1036 var none_loaded = true;1036 var none_loaded = true;
10371037