authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-07-09 14:30:09-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-07-09 15:51:28-04:00
log30713514345f4416f7e68342be5555734e55410e
treeac1daa130d44409a30e05914229ae06b3596d14b
parenta03711b1e3921b2e088e4ee05277497e6143355c

MappedFile: rework add node fixes

This code was attempting to work around an assertion which trips when an invalid offset is chosen for a new node, but it duplicates logic from later in the function, so instead start with an initial offset and alignment that are always valid and use the already existing helper function to meet the requested alignment, similar to how the requested size is met.

3 files changed, 71 insertions(+), 67 deletions(-)

src/link/Coff.zig+2-2
......@@ -3602,13 +3602,13 @@ fn objectSectionMapIndex(
36023602 const parent_alignment = parent_ni.alignment(&coff.mf);
36033603 if (alignment.compare(.gt, parent_alignment)) {
36043604 log.debug("realignParent({s}, {d}) {d}->{d}", .{ name.toSlice(coff), parent_ni, parent_alignment, alignment });
3605 try parent_ni.realign(&coff.mf, gpa, alignment, .{ .set_alignment = true });
3605 try parent_ni.realign(&coff.mf, gpa, alignment, .{ .try_backwards = true });
36063606 }
36073607
36083608 const old_alignment = sym.ni.alignment(&coff.mf);
36093609 if (alignment.compare(.gt, old_alignment)) {
36103610 log.debug("realignObject({s}) {d}->{d}", .{ name.toSlice(coff), old_alignment, alignment });
3611 try sym.ni.realign(&coff.mf, gpa, alignment, .{ .set_alignment = true });
3611 try sym.ni.realign(&coff.mf, gpa, alignment, .{ .try_backwards = true });
36123612 }
36133613
36143614 try coff.verifyParentSectionAttributes(
src/link/Elf2.zig+3-3
......@@ -4659,7 +4659,7 @@ fn mapInputSection(elf: *Elf, opts: struct {
46594659 const new_alignment: std.mem.Alignment = .fromByteUnits(
46604660 std.math.ceilPowerOfTwoAssert(usize, @intCast(opts.addralign)),
46614661 );
4662 try existing_shndx.get(elf).ni.realign(&elf.mf, gpa, new_alignment, .{ .set_alignment = true });
4662 try existing_shndx.get(elf).ni.realign(&elf.mf, gpa, new_alignment, .{});
46634663 }
46644664 // ...and update the shdr as needed.
46654665 switch (elf.shdrPtr(existing_shndx)) {
......@@ -4822,7 +4822,7 @@ fn uavMapIndex(
48224822 } else {
48234823 const node = uav_gop.value_ptr.lsi.index().ptr(elf).node;
48244824 if (resolved_align.toStdMem().order(node.alignment(&elf.mf)).compare(.gt)) {
4825 try node.realign(&elf.mf, gpa, resolved_align.toStdMem(), .{ .set_alignment = true });
4825 try node.realign(&elf.mf, gpa, resolved_align.toStdMem(), .{});
48264826 }
48274827 }
48284828 return umi;
......@@ -5551,7 +5551,7 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadPars
55515551 // We have a copy relocation for this global, but the amount of space we
55525552 // reserved for it could be too small or underaligned!
55535553 try copied_global.node.resize(&elf.mf, gpa, gop.value_ptr.size);
5554 try copied_global.node.realign(&elf.mf, gpa, gop.value_ptr.alignment, .{ .set_alignment = true });
5554 try copied_global.node.realign(&elf.mf, gpa, gop.value_ptr.alignment, .{});
55555555 const global_ptr = elf.globalByName(name).?;
55565556 switch (elf.symPtr(global_ptr.symtab_index)) {
55575557 inline else => |sym_ptr| elf.targetStore(&sym_ptr.size, @intCast(gop.value_ptr.size)),
src/link/MappedFile.zig+66-62
......@@ -95,14 +95,11 @@ pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) (Allocator.Error || I
9595 .fallocate_punch_hole_unsupported = false,
9696 };
9797 try mf.nodes.ensureUnusedCapacity(gpa, 1);
98 const root_ni = mf.addNode(gpa, .{ .add_node = .{
98 const root_ni = try mf.addNode(gpa, .{ .add_node = .{
9999 .size = size,
100100 .alignment = mf.flags.block_size,
101101 .fixed = true,
102 } }) catch |err| switch (err) {
103 error.MappedFileIo => return mf.io_err.?,
104 else => |e| return e,
105 };
102 } });
106103 assert(root_ni == Node.Index.root);
107104 try mf.ensureTotalCapacityInner(@intCast(size));
108105 return mf;
......@@ -355,9 +352,7 @@ pub const Node = extern struct {
355352
356353 pub const RealignNodeOptions = struct {
357354 /// Shift the node backwards if possible
358 try_backwards: bool = true,
359 /// If `set, persists `new_alignment` as the node's alignment for future operations.
360 set_alignment: bool = true,
355 try_backwards: bool = false,
361356 };
362357
363358 /// Moves and expands a node such that its offset and size are aligned to `new_alignment`.
......@@ -378,11 +373,7 @@ pub const Node = extern struct {
378373 return error.MappedFileIo;
379374 },
380375 };
381 var writers_it = mf.writers.first;
382 while (writers_it) |writer_node| : (writers_it = writer_node.next) {
383 const w: *Node.Writer = @fieldParentPtr("writer_node", writer_node);
384 w.interface.buffer = w.ni.slice(mf);
385 }
376 mf.updateWriters();
386377 }
387378
388379 /// Shrink a node to `size`, exactly.
......@@ -398,11 +389,7 @@ pub const Node = extern struct {
398389 shift_next: bool,
399390 ) Error!void {
400391 try mf.shrinkNode(gpa, ni, size, shift_next);
401 var writers_it = mf.writers.first;
402 while (writers_it) |writer_node| : (writers_it = writer_node.next) {
403 const w: *Node.Writer = @fieldParentPtr("writer_node", writer_node);
404 w.interface.buffer = w.ni.slice(mf);
405 }
392 mf.updateWriters();
406393 }
407394
408395 pub fn writer(ni: Node.Index, mf: *MappedFile, gpa: std.mem.Allocator, w: *Writer) void {
......@@ -562,34 +549,15 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
562549 next: Node.Index = .none,
563550 offset: u64 = 0,
564551 add_node: AddNodeOptions,
565}) Error!Node.Index {
552}) (Allocator.Error || Io.Cancelable || IoError)!Node.Index {
566553 if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1);
567554 mf.nodes_lock.assertUnlocked();
568 const offset = opts.add_node.alignment.forward(@intCast(opts.offset));
569 if (opts.parent != .none) {
570 const new_end = offset + opts.add_node.size;
571 switch (opts.next) {
572 .none => {
573 _, const parent_size = opts.parent.location(mf).resolve(mf);
574 if (new_end > parent_size)
575 try opts.parent.resize(mf, gpa, new_end +| new_end / growth_factor);
576 },
577 else => |next_ni| {
578 const next_offset, _ = next_ni.location(mf).resolve(mf);
579 if (new_end > next_offset)
580 try next_ni.realign(mf, gpa, opts.add_node.alignment, .{
581 .try_backwards = false,
582 .set_alignment = false,
583 });
584 },
585 }
586 }
587555 const location_tag: Node.Location.Tag, const location_payload: Node.Location.Payload = location: {
588 if (std.math.cast(u32, offset)) |small_offset| break :location .{ .small, .{
556 if (std.math.cast(u32, opts.offset)) |small_offset| break :location .{ .small, .{
589557 .small = .{ .offset = small_offset, .size = 0 },
590558 } };
591559 try mf.large.ensureUnusedCapacity(gpa, 2);
592 defer mf.large.appendSliceAssumeCapacity(&.{ offset, 0 });
560 defer mf.large.appendSliceAssumeCapacity(&.{ opts.offset, 0 });
593561 break :location .{ .large, .{ .large = .{ .index = mf.large.items.len } } };
594562 };
595563 const free_ni: Node.Index, const free_node = free: switch (mf.free_ni) {
......@@ -616,7 +584,7 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
616584 .last = .none,
617585 .flags = .{
618586 .location_tag = location_tag,
619 .alignment = opts.add_node.alignment,
587 .alignment = .@"1",
620588 .fixed = opts.add_node.fixed,
621589 .moved = true,
622590 .resized = true,
......@@ -627,13 +595,15 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
627595 };
628596
629597 {
630 try free_ni.resize(mf, gpa, opts.add_node.size);
598 try mf.realignNode(gpa, free_ni, opts.add_node.alignment, .{});
599 try mf.resizeNode(gpa, free_ni, opts.add_node.size);
631600 if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1);
632601 free_node.flags.moved = false;
633602 free_node.flags.resized = false;
634603 }
635604 if (opts.add_node.moved) free_ni.movedAssumeCapacity(mf);
636605 if (opts.add_node.resized) free_ni.resizedAssumeCapacity(mf);
606 mf.updateWriters();
637607 return free_ni;
638608}
639609
......@@ -658,7 +628,15 @@ pub fn addOnlyChildNode(
658628 return mf.addNode(gpa, .{
659629 .parent = parent_ni,
660630 .add_node = opts,
661 });
631 }) catch |err| switch (err) {
632 error.OutOfMemory,
633 error.Canceled,
634 => |e| return e,
635 else => |e| {
636 mf.io_err = e;
637 return error.MappedFileIo;
638 },
639 };
662640}
663641
664642pub fn addFirstChildNode(
......@@ -673,7 +651,15 @@ pub fn addFirstChildNode(
673651 .parent = parent_ni,
674652 .next = parent.first,
675653 .add_node = opts,
676 });
654 }) catch |err| switch (err) {
655 error.OutOfMemory,
656 error.Canceled,
657 => |e| return e,
658 else => |e| {
659 mf.io_err = e;
660 return error.MappedFileIo;
661 },
662 };
677663}
678664
679665pub fn addLastChildNode(
......@@ -695,7 +681,15 @@ pub fn addLastChildNode(
695681 },
696682 },
697683 .add_node = opts,
698 });
684 }) catch |err| switch (err) {
685 error.OutOfMemory,
686 error.Canceled,
687 => |e| return e,
688 else => |e| {
689 mf.io_err = e;
690 return error.MappedFileIo;
691 },
692 };
699693}
700694
701695pub fn addNodeAfter(
......@@ -714,7 +708,15 @@ pub fn addNodeAfter(
714708 .next = prev.next,
715709 .offset = prev_offset + prev_size,
716710 .add_node = opts,
717 });
711 }) catch |err| switch (err) {
712 error.OutOfMemory,
713 error.Canceled,
714 => |e| return e,
715 else => |e| {
716 mf.io_err = e;
717 return error.MappedFileIo;
718 },
719 };
718720}
719721
720722fn shrinkNode(
......@@ -1043,26 +1045,20 @@ fn realignNode(
10431045 new_alignment: std.mem.Alignment,
10441046 opts: Node.Index.RealignNodeOptions,
10451047) (Allocator.Error || Io.Cancelable || IoError)!void {
1046 assert(ni != Node.Index.root); // currently unsupported
10471048 mf.nodes_lock.assertUnlocked();
10481049
10491050 const node = ni.get(mf);
1050 const old_offset, const size = node.location().resolve(mf);
1051
1052 assert(new_alignment.compare(.gt, node.flags.alignment));
1053
1054 const prev_alignment = node.flags.alignment;
1055 node.flags.alignment = new_alignment;
1056 defer {
1057 // alignment needs to be temporarily set for the resizes below
1058 if (!opts.set_alignment) node.flags.alignment = prev_alignment;
1051 {
1052 const prev_alignment = node.flags.alignment;
1053 node.flags.alignment = new_alignment;
1054 if (new_alignment.compare(.lte, prev_alignment)) return;
10591055 }
10601056
1061 const new_size = node.flags.alignment.forward(@intCast(size));
1062 if (new_alignment.check(@intCast(old_offset))) {
1063 if (new_size > size) try mf.resizeNode(gpa, ni, new_size);
1064 return;
1065 }
1057 const old_offset, const size = node.location().resolve(mf);
1058 if (ni == Node.Index.root) return mf.resizeNode(gpa, ni, size);
1059
1060 const new_size = new_alignment.forward(@intCast(size));
1061 if (new_alignment.check(@intCast(old_offset))) return mf.resizeNode(gpa, ni, new_size);
10661062
10671063 _, const parent_size = node.parent.location(mf).resolve(mf);
10681064 const trailing_end = trailing_end: switch (node.next) {
......@@ -1122,7 +1118,7 @@ fn realignNode(
11221118
11231119 ni.setLocationAssumeCapacity(mf, forward_offset, new_size);
11241120 } else {
1125 const temp_size = node.flags.alignment.forward(@intCast(new_size + 1));
1121 const temp_size = new_alignment.forward(@intCast(new_size + 1));
11261122 try mf.resizeNode(gpa, ni, temp_size);
11271123 const new_offset, _ = ni.location(mf).resolve(mf);
11281124
......@@ -1148,6 +1144,14 @@ fn realignNode(
11481144 }
11491145}
11501146
1147fn updateWriters(mf: *MappedFile) void {
1148 var writers_it = mf.writers.first;
1149 while (writers_it) |writer_node| : (writers_it = writer_node.next) {
1150 const w: *Node.Writer = @fieldParentPtr("writer_node", writer_node);
1151 w.interface.buffer = w.ni.slice(mf);
1152 }
1153}
1154
11511155fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size: u64) (Io.Cancelable || IoError)!void {
11521156 // make a copy of this node at the new location
11531157 try mf.copyRange(old_file_offset, new_file_offset, size);