authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-04-03 04:55:15-04:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-03 17:45:17+02:00
logf0d13489f819ecd1c0d1c23914127c225f507241
treea14472bbe681872457f85811ebecd7bdf671b945
parentcd24ab7f6e56c8365896a9b2dfc506a787346ecb

Elf: add program headers for the program header table


6 files changed, 184 insertions(+), 128 deletions(-)

lib/std/start.zig-1
...@@ -19,7 +19,6 @@ const start_sym_name = if (native_arch.isMIPS()) "__start" else "_start";...@@ -19,7 +19,6 @@ const start_sym_name = if (native_arch.isMIPS()) "__start" else "_start";
19// self-hosted is capable enough to handle all of the real start.zig logic.19// self-hosted is capable enough to handle all of the real start.zig logic.
20pub const simplified_logic =20pub const simplified_logic =
21 builtin.zig_backend == .stage2_wasm or21 builtin.zig_backend == .stage2_wasm or
22 builtin.zig_backend == .stage2_x86_64 or
23 builtin.zig_backend == .stage2_x86 or22 builtin.zig_backend == .stage2_x86 or
24 builtin.zig_backend == .stage2_aarch64 or23 builtin.zig_backend == .stage2_aarch64 or
25 builtin.zig_backend == .stage2_arm or24 builtin.zig_backend == .stage2_arm or
src/link/Elf.zig+180-123
...@@ -106,7 +106,12 @@ shdr_table_offset: ?u64 = null,...@@ -106,7 +106,12 @@ shdr_table_offset: ?u64 = null,
106/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.106/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
107/// Same order as in the file.107/// Same order as in the file.
108program_headers: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .{},108program_headers: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .{},
109phdr_table_offset: ?u64 = null,109/// The index into the program headers of the PT_PHDR program header
110phdr_table_index: ?u16 = null,
111/// The index into the program headers of the PT_LOAD program header containing the phdr
112/// Most linkers would merge this with phdr_load_ro_index,
113/// but hot swap means we can't ensure they are consecutive.
114phdr_table_load_index: ?u16 = null,
110/// The index into the program headers of a PT_LOAD program header with Read and Execute flags115/// The index into the program headers of a PT_LOAD program header with Read and Execute flags
111phdr_load_re_index: ?u16 = null,116phdr_load_re_index: ?u16 = null,
112/// The index into the program headers of the global offset table.117/// The index into the program headers of the global offset table.
...@@ -386,9 +391,10 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {...@@ -386,9 +391,10 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {
386391
387 const end = start + padToIdeal(size);392 const end = start + padToIdeal(size);
388393
389 if (self.shdr_table_offset) |off| {394 if (self.phdr_table_index) |index| {
390 const shdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Shdr) else @sizeOf(elf.Elf64_Shdr);395 const off = self.program_headers.items[index].p_offset;
391 const tight_size = self.sections.slice().len * shdr_size;396 const phdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Phdr) else @sizeOf(elf.Elf64_Phdr);
397 const tight_size = self.program_headers.items.len * phdr_size;
392 const increased_size = padToIdeal(tight_size);398 const increased_size = padToIdeal(tight_size);
393 const test_end = off + increased_size;399 const test_end = off + increased_size;
394 if (end > off and start < test_end) {400 if (end > off and start < test_end) {
...@@ -396,9 +402,9 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {...@@ -396,9 +402,9 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {
396 }402 }
397 }403 }
398404
399 if (self.phdr_table_offset) |off| {405 if (self.shdr_table_offset) |off| {
400 const phdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Phdr) else @sizeOf(elf.Elf64_Phdr);406 const shdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Shdr) else @sizeOf(elf.Elf64_Shdr);
401 const tight_size = self.sections.slice().len * phdr_size;407 const tight_size = self.sections.slice().len * shdr_size;
402 const increased_size = padToIdeal(tight_size);408 const increased_size = padToIdeal(tight_size);
403 const test_end = off + increased_size;409 const test_end = off + increased_size;
404 if (end > off and start < test_end) {410 if (end > off and start < test_end) {
...@@ -427,10 +433,11 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 {...@@ -427,10 +433,11 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 {
427 if (start == 0)433 if (start == 0)
428 return 0;434 return 0;
429 var min_pos: u64 = std.math.maxInt(u64);435 var min_pos: u64 = std.math.maxInt(u64);
430 if (self.shdr_table_offset) |off| {436 if (self.phdr_table_index) |index| {
437 const off = self.program_headers.items[index].p_offset;
431 if (off > start and off < min_pos) min_pos = off;438 if (off > start and off < min_pos) min_pos = off;
432 }439 }
433 if (self.phdr_table_offset) |off| {440 if (self.shdr_table_offset) |off| {
434 if (off > start and off < min_pos) min_pos = off;441 if (off > start and off < min_pos) min_pos = off;
435 }442 }
436 for (self.sections.items(.shdr)) |section| {443 for (self.sections.items(.shdr)) |section| {
...@@ -462,96 +469,146 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -462,96 +469,146 @@ pub fn populateMissingMetadata(self: *Elf) !void {
462 };469 };
463 const ptr_size: u8 = self.ptrWidthBytes();470 const ptr_size: u8 = self.ptrWidthBytes();
464471
465 if (self.phdr_load_re_index == null) {472 { // Program Headers
466 self.phdr_load_re_index = @intCast(u16, self.program_headers.items.len);473 var new_phdr_table_index: ?u16 = null;
467 const file_size = self.base.options.program_code_size_hint;474 if (self.phdr_table_index == null) {
468 const p_align = self.page_size;475 new_phdr_table_index = @intCast(u16, self.program_headers.items.len);
469 const off = self.findFreeSpace(file_size, p_align);476 const phalign: u16 = switch (self.ptr_width) {
470 log.debug("found PT_LOAD RE free space 0x{x} to 0x{x}", .{ off, off + file_size });477 .p32 => @alignOf(elf.Elf32_Phdr),
471 const entry_addr: u64 = self.entry_addr orelse if (self.base.options.target.cpu.arch == .spu_2) @as(u64, 0) else default_entry_addr;478 .p64 => @alignOf(elf.Elf64_Phdr),
472 try self.program_headers.append(gpa, .{479 };
473 .p_type = elf.PT_LOAD,480 try self.program_headers.append(gpa, .{
474 .p_offset = off,481 .p_type = elf.PT_PHDR,
475 .p_filesz = file_size,482 .p_offset = undefined,
476 .p_vaddr = entry_addr,483 .p_filesz = undefined,
477 .p_paddr = entry_addr,484 .p_vaddr = undefined,
478 .p_memsz = file_size,485 .p_paddr = undefined,
479 .p_align = p_align,486 .p_memsz = undefined,
480 .p_flags = elf.PF_X | elf.PF_R | elf.PF_W,487 .p_align = phalign,
481 });488 .p_flags = elf.PF_R,
482 self.entry_addr = null;489 });
483 self.phdr_table_dirty = true;490 self.phdr_table_dirty = true;
484 }491 }
485492
486 if (self.phdr_got_index == null) {493 if (self.phdr_table_load_index == null) {
487 self.phdr_got_index = @intCast(u16, self.program_headers.items.len);494 self.phdr_table_load_index = @intCast(u16, self.program_headers.items.len);
488 const file_size = @as(u64, ptr_size) * self.base.options.symbol_count_hint;495 // TODO Same as for GOT
489 // We really only need ptr alignment but since we are using PROGBITS, linux requires496 const phdr_addr: u64 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0x1000000 else 0x1000;
490 // page align.497 try self.program_headers.append(gpa, .{
491 const p_align = if (self.base.options.target.os.tag == .linux) self.page_size else @as(u16, ptr_size);498 .p_type = elf.PT_LOAD,
492 const off = self.findFreeSpace(file_size, p_align);499 .p_offset = undefined,
493 log.debug("found PT_LOAD GOT free space 0x{x} to 0x{x}", .{ off, off + file_size });500 .p_filesz = undefined,
494 // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at.501 .p_vaddr = phdr_addr,
495 // we'll need to re-use that function anyway, in case the GOT grows and overlaps something502 .p_paddr = phdr_addr,
496 // else in virtual memory.503 .p_memsz = undefined,
497 const got_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0x4000000 else 0x8000;504 .p_align = self.page_size,
498 try self.program_headers.append(gpa, .{505 .p_flags = elf.PF_R,
499 .p_type = elf.PT_LOAD,506 });
500 .p_offset = off,507 self.phdr_table_dirty = true;
501 .p_filesz = file_size,508 }
502 .p_vaddr = got_addr,509
503 .p_paddr = got_addr,510 if (self.phdr_load_re_index == null) {
504 .p_memsz = file_size,511 self.phdr_load_re_index = @intCast(u16, self.program_headers.items.len);
505 .p_align = p_align,512 const file_size = self.base.options.program_code_size_hint;
506 .p_flags = elf.PF_R | elf.PF_W,513 const p_align = self.page_size;
507 });514 const off = self.findFreeSpace(file_size, p_align);
508 self.phdr_table_dirty = true;515 log.debug("found PT_LOAD RE free space 0x{x} to 0x{x}", .{ off, off + file_size });
509 }516 const entry_addr: u64 = self.entry_addr orelse if (self.base.options.target.cpu.arch == .spu_2) @as(u64, 0) else default_entry_addr;
510517 try self.program_headers.append(gpa, .{
511 if (self.phdr_load_ro_index == null) {518 .p_type = elf.PT_LOAD,
512 self.phdr_load_ro_index = @intCast(u16, self.program_headers.items.len);519 .p_offset = off,
513 // TODO Find a hint about how much data need to be in rodata ?520 .p_filesz = file_size,
514 const file_size = 1024;521 .p_vaddr = entry_addr,
515 // Same reason as for GOT522 .p_paddr = entry_addr,
516 const p_align = if (self.base.options.target.os.tag == .linux) self.page_size else @as(u16, ptr_size);523 .p_memsz = file_size,
517 const off = self.findFreeSpace(file_size, p_align);524 .p_align = p_align,
518 log.debug("found PT_LOAD RO free space 0x{x} to 0x{x}", .{ off, off + file_size });525 .p_flags = elf.PF_X | elf.PF_R | elf.PF_W,
519 // TODO Same as for GOT526 });
520 const rodata_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0xc000000 else 0xa000;527 self.entry_addr = null;
521 try self.program_headers.append(gpa, .{528 self.phdr_table_dirty = true;
522 .p_type = elf.PT_LOAD,529 }
523 .p_offset = off,530
524 .p_filesz = file_size,531 if (self.phdr_got_index == null) {
525 .p_vaddr = rodata_addr,532 self.phdr_got_index = @intCast(u16, self.program_headers.items.len);
526 .p_paddr = rodata_addr,533 const file_size = @as(u64, ptr_size) * self.base.options.symbol_count_hint;
527 .p_memsz = file_size,534 // We really only need ptr alignment but since we are using PROGBITS, linux requires
528 .p_align = p_align,535 // page align.
529 .p_flags = elf.PF_R | elf.PF_W,536 const p_align = if (self.base.options.target.os.tag == .linux) self.page_size else @as(u16, ptr_size);
530 });537 const off = self.findFreeSpace(file_size, p_align);
531 self.phdr_table_dirty = true;538 log.debug("found PT_LOAD GOT free space 0x{x} to 0x{x}", .{ off, off + file_size });
532 }539 // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at.
533540 // we'll need to re-use that function anyway, in case the GOT grows and overlaps something
534 if (self.phdr_load_rw_index == null) {541 // else in virtual memory.
535 self.phdr_load_rw_index = @intCast(u16, self.program_headers.items.len);542 const got_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0x4000000 else 0x8000;
536 // TODO Find a hint about how much data need to be in data ?543 try self.program_headers.append(gpa, .{
537 const file_size = 1024;544 .p_type = elf.PT_LOAD,
538 // Same reason as for GOT545 .p_offset = off,
539 const p_align = if (self.base.options.target.os.tag == .linux) self.page_size else @as(u16, ptr_size);546 .p_filesz = file_size,
540 const off = self.findFreeSpace(file_size, p_align);547 .p_vaddr = got_addr,
541 log.debug("found PT_LOAD RW free space 0x{x} to 0x{x}", .{ off, off + file_size });548 .p_paddr = got_addr,
542 // TODO Same as for GOT549 .p_memsz = file_size,
543 const rwdata_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0x10000000 else 0xc000;550 .p_align = p_align,
544 try self.program_headers.append(gpa, .{551 .p_flags = elf.PF_R | elf.PF_W,
545 .p_type = elf.PT_LOAD,552 });
546 .p_offset = off,553 self.phdr_table_dirty = true;
547 .p_filesz = file_size,554 }
548 .p_vaddr = rwdata_addr,555
549 .p_paddr = rwdata_addr,556 if (self.phdr_load_ro_index == null) {
550 .p_memsz = file_size,557 self.phdr_load_ro_index = @intCast(u16, self.program_headers.items.len);
551 .p_align = p_align,558 // TODO Find a hint about how much data need to be in rodata ?
552 .p_flags = elf.PF_R | elf.PF_W,559 const file_size = 1024;
553 });560 // Same reason as for GOT
554 self.phdr_table_dirty = true;561 const p_align = if (self.base.options.target.os.tag == .linux) self.page_size else @as(u16, ptr_size);
562 const off = self.findFreeSpace(file_size, p_align);
563 log.debug("found PT_LOAD RO free space 0x{x} to 0x{x}", .{ off, off + file_size });
564 // TODO Same as for GOT
565 const rodata_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0xc000000 else 0xa000;
566 try self.program_headers.append(gpa, .{
567 .p_type = elf.PT_LOAD,
568 .p_offset = off,
569 .p_filesz = file_size,
570 .p_vaddr = rodata_addr,
571 .p_paddr = rodata_addr,
572 .p_memsz = file_size,
573 .p_align = p_align,
574 .p_flags = elf.PF_R | elf.PF_W,
575 });
576 self.phdr_table_dirty = true;
577 }
578
579 if (self.phdr_load_rw_index == null) {
580 self.phdr_load_rw_index = @intCast(u16, self.program_headers.items.len);
581 // TODO Find a hint about how much data need to be in data ?
582 const file_size = 1024;
583 // Same reason as for GOT
584 const p_align = if (self.base.options.target.os.tag == .linux) self.page_size else @as(u16, ptr_size);
585 const off = self.findFreeSpace(file_size, p_align);
586 log.debug("found PT_LOAD RW free space 0x{x} to 0x{x}", .{ off, off + file_size });
587 // TODO Same as for GOT
588 const rwdata_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0x10000000 else 0xc000;
589 try self.program_headers.append(gpa, .{
590 .p_type = elf.PT_LOAD,
591 .p_offset = off,
592 .p_filesz = file_size,
593 .p_vaddr = rwdata_addr,
594 .p_paddr = rwdata_addr,
595 .p_memsz = file_size,
596 .p_align = p_align,
597 .p_flags = elf.PF_R | elf.PF_W,
598 });
599 self.phdr_table_dirty = true;
600 }
601
602 if (new_phdr_table_index) |index| {
603 const phsize: u64 = switch (self.ptr_width) {
604 .p32 => @sizeOf(elf.Elf32_Phdr),
605 .p64 => @sizeOf(elf.Elf64_Phdr),
606 };
607 const phdr_table = &self.program_headers.items[index];
608 phdr_table.p_offset = self.findFreeSpace(self.program_headers.items.len * phsize, @intCast(u32, phdr_table.p_align));
609 self.phdr_table_index = index;
610 self.phdr_table_dirty = true;
611 }
555 }612 }
556613
557 if (self.shstrtab_index == null) {614 if (self.shstrtab_index == null) {
...@@ -849,19 +906,6 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -849,19 +906,6 @@ pub fn populateMissingMetadata(self: *Elf) !void {
849 self.shdr_table_dirty = true;906 self.shdr_table_dirty = true;
850 }907 }
851908
852 const phsize: u64 = switch (self.ptr_width) {
853 .p32 => @sizeOf(elf.Elf32_Phdr),
854 .p64 => @sizeOf(elf.Elf64_Phdr),
855 };
856 const phalign: u16 = switch (self.ptr_width) {
857 .p32 => @alignOf(elf.Elf32_Phdr),
858 .p64 => @alignOf(elf.Elf64_Phdr),
859 };
860 if (self.phdr_table_offset == null) {
861 self.phdr_table_offset = self.findFreeSpace(self.program_headers.items.len * phsize, phalign);
862 self.phdr_table_dirty = true;
863 }
864
865 {909 {
866 // Iterate over symbols, populating free_list and last_text_block.910 // Iterate over symbols, populating free_list and last_text_block.
867 if (self.local_symbols.items.len != 1) {911 if (self.local_symbols.items.len != 1) {
...@@ -1132,18 +1176,30 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1132,18 +1176,30 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1132 .p32 => @sizeOf(elf.Elf32_Phdr),1176 .p32 => @sizeOf(elf.Elf32_Phdr),
1133 .p64 => @sizeOf(elf.Elf64_Phdr),1177 .p64 => @sizeOf(elf.Elf64_Phdr),
1134 };1178 };
1135 const phalign: u16 = switch (self.ptr_width) {1179
1136 .p32 => @alignOf(elf.Elf32_Phdr),1180 const phdr_table_index = self.phdr_table_index.?;
1137 .p64 => @alignOf(elf.Elf64_Phdr),1181 const phdr_table = &self.program_headers.items[phdr_table_index];
1138 };1182 const phdr_table_load = &self.program_headers.items[self.phdr_table_load_index.?];
1139 const allocated_size = self.allocatedSize(self.phdr_table_offset.?);1183
1184 const allocated_size = self.allocatedSize(phdr_table.p_offset);
1140 const needed_size = self.program_headers.items.len * phsize;1185 const needed_size = self.program_headers.items.len * phsize;
11411186
1142 if (needed_size > allocated_size) {1187 if (needed_size > allocated_size) {
1143 self.phdr_table_offset = null; // free the space1188 self.phdr_table_index = null; // free the space
1144 self.phdr_table_offset = self.findFreeSpace(needed_size, phalign);1189 defer self.phdr_table_index = phdr_table_index;
1190 phdr_table.p_offset = self.findFreeSpace(needed_size, @intCast(u32, phdr_table.p_align));
1145 }1191 }
11461192
1193 phdr_table_load.p_offset = mem.alignBackwardGeneric(u64, phdr_table.p_offset, phdr_table_load.p_align);
1194 const load_align_offset = phdr_table.p_offset - phdr_table_load.p_offset;
1195 phdr_table_load.p_filesz = load_align_offset + needed_size;
1196 phdr_table_load.p_memsz = load_align_offset + needed_size;
1197
1198 phdr_table.p_filesz = needed_size;
1199 phdr_table.p_vaddr = phdr_table_load.p_vaddr + load_align_offset;
1200 phdr_table.p_paddr = phdr_table_load.p_paddr + load_align_offset;
1201 phdr_table.p_memsz = needed_size;
1202
1147 switch (self.ptr_width) {1203 switch (self.ptr_width) {
1148 .p32 => {1204 .p32 => {
1149 const buf = try gpa.alloc(elf.Elf32_Phdr, self.program_headers.items.len);1205 const buf = try gpa.alloc(elf.Elf32_Phdr, self.program_headers.items.len);
...@@ -1155,7 +1211,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1155,7 +1211,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1155 mem.byteSwapAllFields(elf.Elf32_Phdr, phdr);1211 mem.byteSwapAllFields(elf.Elf32_Phdr, phdr);
1156 }1212 }
1157 }1213 }
1158 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);1214 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);
1159 },1215 },
1160 .p64 => {1216 .p64 => {
1161 const buf = try gpa.alloc(elf.Elf64_Phdr, self.program_headers.items.len);1217 const buf = try gpa.alloc(elf.Elf64_Phdr, self.program_headers.items.len);
...@@ -1167,7 +1223,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1167,7 +1223,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1167 mem.byteSwapAllFields(elf.Elf64_Phdr, phdr);1223 mem.byteSwapAllFields(elf.Elf64_Phdr, phdr);
1168 }1224 }
1169 }1225 }
1170 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);1226 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);
1171 },1227 },
1172 }1228 }
1173 self.phdr_table_dirty = false;1229 self.phdr_table_dirty = false;
...@@ -1992,13 +2048,14 @@ fn writeElfHeader(self: *Elf) !void {...@@ -1992,13 +2048,14 @@ fn writeElfHeader(self: *Elf) !void {
19922048
1993 const e_entry = if (elf_type == .REL) 0 else self.entry_addr.?;2049 const e_entry = if (elf_type == .REL) 0 else self.entry_addr.?;
19942050
2051 const phdr_table_offset = self.program_headers.items[self.phdr_table_index.?].p_offset;
1995 switch (self.ptr_width) {2052 switch (self.ptr_width) {
1996 .p32 => {2053 .p32 => {
1997 mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(u32, e_entry), endian);2054 mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(u32, e_entry), endian);
1998 index += 4;2055 index += 4;
19992056
2000 // e_phoff2057 // e_phoff
2001 mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(u32, self.phdr_table_offset.?), endian);2058 mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(u32, phdr_table_offset), endian);
2002 index += 4;2059 index += 4;
20032060
2004 // e_shoff2061 // e_shoff
...@@ -2011,7 +2068,7 @@ fn writeElfHeader(self: *Elf) !void {...@@ -2011,7 +2068,7 @@ fn writeElfHeader(self: *Elf) !void {
2011 index += 8;2068 index += 8;
20122069
2013 // e_phoff2070 // e_phoff
2014 mem.writeInt(u64, hdr_buf[index..][0..8], self.phdr_table_offset.?, endian);2071 mem.writeInt(u64, hdr_buf[index..][0..8], phdr_table_offset, endian);
2015 index += 8;2072 index += 8;
20162073
2017 // e_shoff2074 // e_shoff
test/cases/aarch64-macos/hello_world_with_updates.0.zig+1-1
...@@ -2,4 +2,4 @@...@@ -2,4 +2,4 @@
2// output_mode=Exe2// output_mode=Exe
3// target=aarch64-macos3// target=aarch64-macos
4//4//
5// :110:9: error: root struct of file 'tmp' has no member named 'main'5// :109:9: error: root struct of file 'tmp' has no member named 'main'
test/cases/x86_64-linux/hello_world_with_updates.0.zig+1-1
...@@ -2,4 +2,4 @@...@@ -2,4 +2,4 @@
2// output_mode=Exe2// output_mode=Exe
3// target=x86_64-linux3// target=x86_64-linux
4//4//
5// :110:9: error: root struct of file 'tmp' has no member named 'main'5// :109:9: error: root struct of file 'tmp' has no member named 'main'
test/cases/x86_64-macos/hello_world_with_updates.0.zig+1-1
...@@ -2,4 +2,4 @@...@@ -2,4 +2,4 @@
2// output_mode=Exe2// output_mode=Exe
3// target=x86_64-macos3// target=x86_64-macos
4//4//
5// :110:9: error: root struct of file 'tmp' has no member named 'main'5// :109:9: error: root struct of file 'tmp' has no member named 'main'
test/cases/x86_64-windows/hello_world_with_updates.0.zig+1-1
...@@ -2,4 +2,4 @@...@@ -2,4 +2,4 @@
2// output_mode=Exe2// output_mode=Exe
3// target=x86_64-windows3// target=x86_64-windows
4//4//
5// :131:9: error: root struct of file 'tmp' has no member named 'main'5// :130:9: error: root struct of file 'tmp' has no member named 'main'