authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-02 22:55:30+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-03 09:28:30+01:00
log9fc1685c1caa4c1d093fa8936a5602f54121dd50
tree95aa99d2c97d48bc0f2715ec1d05ee64b99539f2
parente10a2018a7b6a51243589ec95842d2cef2da45ac

macho: make atom address relative wrt defining section


5 files changed, 69 insertions(+), 54 deletions(-)

src/link/MachO.zig+37-29
...@@ -636,7 +636,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node...@@ -636,7 +636,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
636 return error.FlushFailure;636 return error.FlushFailure;
637 },637 },
638 };638 };
639 const file_offset = sect.offset + atom.value - sect.addr;639 const file_offset = sect.offset + atom.value;
640 atom.resolveRelocs(self, code) catch |err| switch (err) {640 atom.resolveRelocs(self, code) catch |err| switch (err) {
641 error.ResolveFailed => has_resolve_error = true,641 error.ResolveFailed => has_resolve_error = true,
642 else => |e| {642 else => |e| {
...@@ -2393,16 +2393,7 @@ fn allocateSegments(self: *MachO) void {...@@ -2393,16 +2393,7 @@ fn allocateSegments(self: *MachO) void {
2393}2393}
23942394
2395pub fn allocateAtoms(self: *MachO) void {2395pub fn allocateAtoms(self: *MachO) void {
2396 const slice = self.sections.slice();2396 // TODO: redo this like atoms
2397 for (slice.items(.header), slice.items(.atoms)) |header, atoms| {
2398 if (atoms.items.len == 0) continue;
2399 for (atoms.items) |atom_index| {
2400 const atom = self.getAtom(atom_index).?;
2401 assert(atom.flags.alive);
2402 atom.value += header.addr;
2403 }
2404 }
2405
2406 for (self.thunks.items) |*thunk| {2397 for (self.thunks.items) |*thunk| {
2407 const header = self.sections.items(.header)[thunk.out_n_sect];2398 const header = self.sections.items(.header)[thunk.out_n_sect];
2408 thunk.value += header.addr;2399 thunk.value += header.addr;
...@@ -2603,7 +2594,7 @@ fn writeAtoms(self: *MachO) !void {...@@ -2603,7 +2594,7 @@ fn writeAtoms(self: *MachO) !void {
2603 for (atoms.items) |atom_index| {2594 for (atoms.items) |atom_index| {
2604 const atom = self.getAtom(atom_index).?;2595 const atom = self.getAtom(atom_index).?;
2605 assert(atom.flags.alive);2596 assert(atom.flags.alive);
2606 const off = math.cast(usize, atom.value - header.addr) orelse return error.Overflow;2597 const off = math.cast(usize, atom.value) orelse return error.Overflow;
2607 const atom_size = math.cast(usize, atom.size) orelse return error.Overflow;2598 const atom_size = math.cast(usize, atom.size) orelse return error.Overflow;
2608 try atom.getData(self, buffer[off..][0..atom_size]);2599 try atom.getData(self, buffer[off..][0..atom_size]);
2609 atom.resolveRelocs(self, buffer[off..][0..atom_size]) catch |err| switch (err) {2600 atom.resolveRelocs(self, buffer[off..][0..atom_size]) catch |err| switch (err) {
...@@ -2825,7 +2816,7 @@ pub fn writeDataInCode(self: *MachO, base_address: u64, off: u32) !u32 {...@@ -2825,7 +2816,7 @@ pub fn writeDataInCode(self: *MachO, base_address: u64, off: u32) !u32 {
28252816
2826 if (atom.flags.alive) for (in_dices[start_dice..next_dice]) |dice| {2817 if (atom.flags.alive) for (in_dices[start_dice..next_dice]) |dice| {
2827 dices.appendAssumeCapacity(.{2818 dices.appendAssumeCapacity(.{
2828 .offset = @intCast(atom.value + dice.offset - start_off - base_address),2819 .offset = @intCast(atom.getAddress(self) + dice.offset - start_off - base_address),
2829 .length = dice.length,2820 .length = dice.length,
2830 .kind = dice.kind,2821 .kind = dice.kind,
2831 });2822 });
...@@ -3318,7 +3309,7 @@ fn allocatedSize(self: *MachO, start: u64) u64 {...@@ -3318,7 +3309,7 @@ fn allocatedSize(self: *MachO, start: u64) u64 {
3318 return min_pos - start;3309 return min_pos - start;
3319}3310}
33203311
3321fn allocatedVirtualSize(self: *MachO, start: u64) u64 {3312fn allocatedSizeVirtual(self: *MachO, start: u64) u64 {
3322 if (start == 0) return 0;3313 if (start == 0) return 0;
3323 var min_pos: u64 = std.math.maxInt(u64);3314 var min_pos: u64 = std.math.maxInt(u64);
3324 for (self.segments.items) |seg| {3315 for (self.segments.items) |seg| {
...@@ -3518,22 +3509,39 @@ pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {...@@ -3518,22 +3509,39 @@ pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {
3518 sect.size = 0;3509 sect.size = 0;
35193510
3520 // Must move the entire section.3511 // Must move the entire section.
3521 const alignment = if (self.base.isRelocatable())3512 if (self.base.isRelocatable()) {
3522 try math.powi(u32, 2, sect.@"align")3513 const alignment = try math.powi(u32, 2, sect.@"align");
3523 else3514 const new_offset = self.findFreeSpace(needed_size, alignment);
3524 self.getPageSize();3515 const new_addr = self.findFreeSpaceVirtual(needed_size, alignment);
3525 const new_offset = self.findFreeSpace(needed_size, alignment);
3526
3527 log.debug("new '{s},{s}' file offset 0x{x} to 0x{x}", .{
3528 sect.segName(),
3529 sect.sectName(),
3530 new_offset,
3531 new_offset + existing_size,
3532 });
35333516
3534 try self.copyRangeAllZeroOut(sect.offset, new_offset, existing_size);3517 log.debug("new '{s},{s}' file offset 0x{x} to 0x{x} (0x{x} - 0x{x})", .{
3518 sect.segName(),
3519 sect.sectName(),
3520 new_offset,
3521 new_offset + existing_size,
3522 new_addr,
3523 new_addr + existing_size,
3524 });
3525
3526 try self.copyRangeAll(sect.offset, new_offset, existing_size);
35353527
3536 sect.offset = @intCast(new_offset);3528 sect.offset = @intCast(new_offset);
3529 sect.addr = new_addr;
3530 } else {
3531 const alignment = self.getPageSize();
3532 const new_offset = self.findFreeSpace(needed_size, alignment);
3533
3534 log.debug("new '{s},{s}' file offset 0x{x} to 0x{x}", .{
3535 sect.segName(),
3536 sect.sectName(),
3537 new_offset,
3538 new_offset + existing_size,
3539 });
3540
3541 try self.copyRangeAllZeroOut(sect.offset, new_offset, existing_size);
3542
3543 sect.offset = @intCast(new_offset);
3544 }
3537 }3545 }
35383546
3539 sect.size = needed_size;3547 sect.size = needed_size;
...@@ -3547,7 +3555,7 @@ pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {...@@ -3547,7 +3555,7 @@ pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {
3547 seg.filesize = needed_size;3555 seg.filesize = needed_size;
3548 }3556 }
35493557
3550 const mem_capacity = self.allocatedVirtualSize(seg.vmaddr);3558 const mem_capacity = self.allocatedSizeVirtual(seg.vmaddr);
3551 if (needed_size > mem_capacity) {3559 if (needed_size > mem_capacity) {
3552 var err = try self.addErrorWithNotes(2);3560 var err = try self.addErrorWithNotes(2);
3553 try err.addMsg(self, "fatal linker error: cannot expand segment seg({d})({s}) in virtual memory", .{3561 try err.addMsg(self, "fatal linker error: cannot expand segment seg({d})({s}) in virtual memory", .{
src/link/MachO/Atom.zig+23-16
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1/// Address allocated for this Atom.1/// Address offset allocated for this Atom wrt to its section start address.
2value: u64 = 0,2value: u64 = 0,
33
4/// Name of this Atom.4/// Name of this Atom.
...@@ -84,6 +84,11 @@ pub fn getInputAddress(self: Atom, macho_file: *MachO) u64 {...@@ -84,6 +84,11 @@ pub fn getInputAddress(self: Atom, macho_file: *MachO) u64 {
84 return self.getInputSection(macho_file).addr + self.off;84 return self.getInputSection(macho_file).addr + self.off;
85}85}
8686
87pub fn getAddress(self: Atom, macho_file: *MachO) u64 {
88 const header = macho_file.sections.items(.header)[self.out_n_sect];
89 return header.addr + self.value;
90}
91
87pub fn getPriority(self: Atom, macho_file: *MachO) u64 {92pub fn getPriority(self: Atom, macho_file: *MachO) u64 {
88 const file = self.getFile(macho_file);93 const file = self.getFile(macho_file);
89 return (@as(u64, @intCast(file.getIndex())) << 32) | @as(u64, @intCast(self.n_sect));94 return (@as(u64, @intCast(file.getIndex())) << 32) | @as(u64, @intCast(self.n_sect));
...@@ -189,14 +194,17 @@ pub fn initOutputSection(sect: macho.section_64, macho_file: *MachO) !u8 {...@@ -189,14 +194,17 @@ pub fn initOutputSection(sect: macho.section_64, macho_file: *MachO) !u8 {
189/// File offset relocation happens transparently, so it is not included in194/// File offset relocation happens transparently, so it is not included in
190/// this calculation.195/// this calculation.
191pub fn capacity(self: Atom, macho_file: *MachO) u64 {196pub fn capacity(self: Atom, macho_file: *MachO) u64 {
192 const next_value = if (macho_file.getAtom(self.next_index)) |next| next.value else std.math.maxInt(u32);197 const next_addr = if (macho_file.getAtom(self.next_index)) |next|
193 return next_value - self.value;198 next.getAddress(macho_file)
199 else
200 std.math.maxInt(u32);
201 return next_addr - self.getAddress(macho_file);
194}202}
195203
196pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {204pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {
197 // No need to keep a free list node for the last block.205 // No need to keep a free list node for the last block.
198 const next = macho_file.getAtom(self.next_index) orelse return false;206 const next = macho_file.getAtom(self.next_index) orelse return false;
199 const cap = next.value - self.value;207 const cap = next.getAddress(macho_file) - self.getAddress(macho_file);
200 const ideal_cap = MachO.padToIdeal(self.size);208 const ideal_cap = MachO.padToIdeal(self.size);
201 if (cap <= ideal_cap) return false;209 if (cap <= ideal_cap) return false;
202 const surplus = cap - ideal_cap;210 const surplus = cap - ideal_cap;
...@@ -263,15 +271,15 @@ pub fn allocate(self: *Atom, macho_file: *MachO) !void {...@@ -263,15 +271,15 @@ pub fn allocate(self: *Atom, macho_file: *MachO) !void {
263 atom_placement = last.atom_index;271 atom_placement = last.atom_index;
264 break :blk new_start_vaddr;272 break :blk new_start_vaddr;
265 } else {273 } else {
266 break :blk sect.addr;274 break :blk 0;
267 }275 }
268 };276 };
269277
270 log.debug("allocated atom({d}) : '{s}' at 0x{x} to 0x{x}", .{278 log.debug("allocated atom({d}) : '{s}' at 0x{x} to 0x{x}", .{
271 self.atom_index,279 self.atom_index,
272 self.getName(macho_file),280 self.getName(macho_file),
273 self.value,281 self.getAddress(macho_file),
274 self.value + self.size,282 self.getAddress(macho_file) + self.size,
275 });283 });
276284
277 const expand_section = if (atom_placement) |placement_index|285 const expand_section = if (atom_placement) |placement_index|
...@@ -279,7 +287,7 @@ pub fn allocate(self: *Atom, macho_file: *MachO) !void {...@@ -279,7 +287,7 @@ pub fn allocate(self: *Atom, macho_file: *MachO) !void {
279 else287 else
280 true;288 true;
281 if (expand_section) {289 if (expand_section) {
282 const needed_size = (self.value + self.size) - sect.addr;290 const needed_size = self.value + self.size;
283 try macho_file.growSection(self.out_n_sect, needed_size);291 try macho_file.growSection(self.out_n_sect, needed_size);
284 last_atom_index.* = self.atom_index;292 last_atom_index.* = self.atom_index;
285293
...@@ -544,7 +552,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {...@@ -544,7 +552,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {
544 const name = self.getName(macho_file);552 const name = self.getName(macho_file);
545 const relocs = self.getRelocs(macho_file);553 const relocs = self.getRelocs(macho_file);
546554
547 relocs_log.debug("{x}: {s}", .{ self.value, name });555 relocs_log.debug("{x}: {s}", .{ self.getAddress(macho_file), name });
548556
549 var has_error = false;557 var has_error = false;
550 var stream = std.io.fixedBufferStream(buffer);558 var stream = std.io.fixedBufferStream(buffer);
...@@ -569,7 +577,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {...@@ -569,7 +577,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {
569 try macho_file.reportParseError2(577 try macho_file.reportParseError2(
570 file.getIndex(),578 file.getIndex(),
571 "{s}: 0x{x}: 0x{x}: failed to relax relocation: type {s}, target {s}",579 "{s}: 0x{x}: 0x{x}: failed to relax relocation: type {s}, target {s}",
572 .{ name, self.value, rel.offset, @tagName(rel.type), target },580 .{ name, self.getAddress(macho_file), rel.offset, @tagName(rel.type), target },
573 );581 );
574 has_error = true;582 has_error = true;
575 },583 },
...@@ -604,7 +612,7 @@ fn resolveRelocInner(...@@ -604,7 +612,7 @@ fn resolveRelocInner(
604 const rel_offset = math.cast(usize, rel.offset - self.off) orelse return error.Overflow;612 const rel_offset = math.cast(usize, rel.offset - self.off) orelse return error.Overflow;
605 const seg_id = macho_file.sections.items(.segment_id)[self.out_n_sect];613 const seg_id = macho_file.sections.items(.segment_id)[self.out_n_sect];
606 const seg = macho_file.segments.items[seg_id];614 const seg = macho_file.segments.items[seg_id];
607 const P = @as(i64, @intCast(self.value)) + @as(i64, @intCast(rel_offset));615 const P = @as(i64, @intCast(self.getAddress(macho_file))) + @as(i64, @intCast(rel_offset));
608 const A = rel.addend + rel.getRelocAddend(cpu_arch);616 const A = rel.addend + rel.getRelocAddend(cpu_arch);
609 const S: i64 = @intCast(rel.getTargetAddress(macho_file));617 const S: i64 = @intCast(rel.getTargetAddress(macho_file));
610 const G: i64 = @intCast(rel.getGotTargetAddress(macho_file));618 const G: i64 = @intCast(rel.getGotTargetAddress(macho_file));
...@@ -919,7 +927,7 @@ const x86_64 = struct {...@@ -919,7 +927,7 @@ const x86_64 = struct {
919 var err = try macho_file.addErrorWithNotes(2);927 var err = try macho_file.addErrorWithNotes(2);
920 try err.addMsg(macho_file, "{s}: 0x{x}: 0x{x}: failed to relax relocation of type {s}", .{928 try err.addMsg(macho_file, "{s}: 0x{x}: 0x{x}: failed to relax relocation of type {s}", .{
921 self.getName(macho_file),929 self.getName(macho_file),
922 self.value,930 self.getAddress(macho_file),
923 rel.offset,931 rel.offset,
924 @tagName(rel.type),932 @tagName(rel.type),
925 });933 });
...@@ -990,12 +998,11 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra...@@ -990,12 +998,11 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra
990998
991 const cpu_arch = macho_file.getTarget().cpu.arch;999 const cpu_arch = macho_file.getTarget().cpu.arch;
992 const relocs = self.getRelocs(macho_file);1000 const relocs = self.getRelocs(macho_file);
993 const sect = macho_file.sections.items(.header)[self.out_n_sect];
994 var stream = std.io.fixedBufferStream(code);1001 var stream = std.io.fixedBufferStream(code);
9951002
996 for (relocs) |rel| {1003 for (relocs) |rel| {
997 const rel_offset = rel.offset - self.off;1004 const rel_offset = rel.offset - self.off;
998 const r_address: i32 = math.cast(i32, self.value + rel_offset - sect.addr) orelse return error.Overflow;1005 const r_address: i32 = math.cast(i32, self.value + rel_offset) orelse return error.Overflow;
999 const r_symbolnum = r_symbolnum: {1006 const r_symbolnum = r_symbolnum: {
1000 const r_symbolnum: u32 = switch (rel.tag) {1007 const r_symbolnum: u32 = switch (rel.tag) {
1001 .local => rel.getTargetAtom(macho_file).out_n_sect + 1,1008 .local => rel.getTargetAtom(macho_file).out_n_sect + 1,
...@@ -1062,7 +1069,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra...@@ -1062,7 +1069,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra
1062 .x86_64 => {1069 .x86_64 => {
1063 if (rel.meta.pcrel) {1070 if (rel.meta.pcrel) {
1064 if (rel.tag == .local) {1071 if (rel.tag == .local) {
1065 addend -= @as(i64, @intCast(self.value + rel_offset));1072 addend -= @as(i64, @intCast(self.getAddress(macho_file) + rel_offset));
1066 } else {1073 } else {
1067 addend += 4;1074 addend += 4;
1068 }1075 }
...@@ -1144,7 +1151,7 @@ fn format2(...@@ -1144,7 +1151,7 @@ fn format2(
1144 const atom = ctx.atom;1151 const atom = ctx.atom;
1145 const macho_file = ctx.macho_file;1152 const macho_file = ctx.macho_file;
1146 try writer.print("atom({d}) : {s} : @{x} : sect({d}) : align({x}) : size({x}) : nreloc({d}) : thunk({d})", .{1153 try writer.print("atom({d}) : {s} : @{x} : sect({d}) : align({x}) : size({x}) : nreloc({d}) : thunk({d})", .{
1147 atom.atom_index, atom.getName(macho_file), atom.value,1154 atom.atom_index, atom.getName(macho_file), atom.getAddress(macho_file),
1148 atom.out_n_sect, atom.alignment, atom.size,1155 atom.out_n_sect, atom.alignment, atom.size,
1149 atom.getRelocs(macho_file).len, atom.thunk_index,1156 atom.getRelocs(macho_file).len, atom.thunk_index,
1150 });1157 });
src/link/MachO/Symbol.zig+2-2
...@@ -118,7 +118,7 @@ pub fn getAddress(symbol: Symbol, opts: struct {...@@ -118,7 +118,7 @@ pub fn getAddress(symbol: Symbol, opts: struct {
118 return symbol.getObjcStubsAddress(macho_file);118 return symbol.getObjcStubsAddress(macho_file);
119 }119 }
120 }120 }
121 if (symbol.getAtom(macho_file)) |atom| return atom.value + symbol.value;121 if (symbol.getAtom(macho_file)) |atom| return atom.getAddress(macho_file) + symbol.value;
122 return symbol.value;122 return symbol.value;
123}123}
124124
...@@ -145,7 +145,7 @@ pub fn getObjcSelrefsAddress(symbol: Symbol, macho_file: *MachO) u64 {...@@ -145,7 +145,7 @@ pub fn getObjcSelrefsAddress(symbol: Symbol, macho_file: *MachO) u64 {
145 const extra = symbol.getExtra(macho_file).?;145 const extra = symbol.getExtra(macho_file).?;
146 const atom = macho_file.getAtom(extra.objc_selrefs).?;146 const atom = macho_file.getAtom(extra.objc_selrefs).?;
147 assert(atom.flags.alive);147 assert(atom.flags.alive);
148 return atom.value;148 return atom.getAddress(macho_file);
149}149}
150150
151pub fn getTlvPtrAddress(symbol: Symbol, macho_file: *MachO) u64 {151pub fn getTlvPtrAddress(symbol: Symbol, macho_file: *MachO) u64 {
src/link/MachO/ZigObject.zig+5-5
...@@ -154,7 +154,7 @@ pub fn getAtomData(self: ZigObject, macho_file: *MachO, atom: Atom, buffer: []u8...@@ -154,7 +154,7 @@ pub fn getAtomData(self: ZigObject, macho_file: *MachO, atom: Atom, buffer: []u8
154 @memset(buffer, 0);154 @memset(buffer, 0);
155 },155 },
156 else => {156 else => {
157 const file_offset = sect.offset + atom.value - sect.addr;157 const file_offset = sect.offset + atom.value;
158 const amt = try macho_file.base.file.?.preadAll(buffer, file_offset);158 const amt = try macho_file.base.file.?.preadAll(buffer, file_offset);
159 if (amt != buffer.len) return error.InputOutput;159 if (amt != buffer.len) return error.InputOutput;
160 },160 },
...@@ -715,7 +715,7 @@ fn updateDeclCode(...@@ -715,7 +715,7 @@ fn updateDeclCode(
715 } else if (code.len < old_size) {715 } else if (code.len < old_size) {
716 atom.shrink(macho_file);716 atom.shrink(macho_file);
717 } else if (macho_file.getAtom(atom.next_index) == null) {717 } else if (macho_file.getAtom(atom.next_index) == null) {
718 const needed_size = atom.value + code.len - sect.addr;718 const needed_size = atom.value + code.len;
719 sect.size = needed_size;719 sect.size = needed_size;
720 }720 }
721 } else {721 } else {
...@@ -733,7 +733,7 @@ fn updateDeclCode(...@@ -733,7 +733,7 @@ fn updateDeclCode(
733 }733 }
734734
735 if (!sect.isZerofill()) {735 if (!sect.isZerofill()) {
736 const file_offset = sect.offset + atom.value - sect.addr;736 const file_offset = sect.offset + atom.value;
737 try macho_file.base.file.?.pwriteAll(code, file_offset);737 try macho_file.base.file.?.pwriteAll(code, file_offset);
738 }738 }
739}739}
...@@ -1036,7 +1036,7 @@ fn lowerConst(...@@ -1036,7 +1036,7 @@ fn lowerConst(
1036 nlist.n_value = 0;1036 nlist.n_value = 0;
10371037
1038 const sect = macho_file.sections.items(.header)[output_section_index];1038 const sect = macho_file.sections.items(.header)[output_section_index];
1039 const file_offset = sect.offset + atom.value - sect.addr;1039 const file_offset = sect.offset + atom.value;
1040 try macho_file.base.file.?.pwriteAll(code, file_offset);1040 try macho_file.base.file.?.pwriteAll(code, file_offset);
10411041
1042 return .{ .ok = sym_index };1042 return .{ .ok = sym_index };
...@@ -1213,7 +1213,7 @@ fn updateLazySymbol(...@@ -1213,7 +1213,7 @@ fn updateLazySymbol(
1213 }1213 }
12141214
1215 const sect = macho_file.sections.items(.header)[output_section_index];1215 const sect = macho_file.sections.items(.header)[output_section_index];
1216 const file_offset = sect.offset + atom.value - sect.addr;1216 const file_offset = sect.offset + atom.value;
1217 try macho_file.base.file.?.pwriteAll(code, file_offset);1217 try macho_file.base.file.?.pwriteAll(code, file_offset);
1218}1218}
12191219
src/link/MachO/relocatable.zig+2-2
...@@ -328,7 +328,7 @@ fn writeAtoms(macho_file: *MachO) !void {...@@ -328,7 +328,7 @@ fn writeAtoms(macho_file: *MachO) !void {
328 for (atoms.items) |atom_index| {328 for (atoms.items) |atom_index| {
329 const atom = macho_file.getAtom(atom_index).?;329 const atom = macho_file.getAtom(atom_index).?;
330 assert(atom.flags.alive);330 assert(atom.flags.alive);
331 const off = math.cast(usize, atom.value - header.addr) orelse return error.Overflow;331 const off = math.cast(usize, atom.value) orelse return error.Overflow;
332 const atom_size = math.cast(usize, atom.size) orelse return error.Overflow;332 const atom_size = math.cast(usize, atom.size) orelse return error.Overflow;
333 try atom.getData(macho_file, code[off..][0..atom_size]);333 try atom.getData(macho_file, code[off..][0..atom_size]);
334 try atom.writeRelocs(macho_file, code[off..][0..atom_size], &relocs);334 try atom.writeRelocs(macho_file, code[off..][0..atom_size], &relocs);
...@@ -386,7 +386,7 @@ fn writeAtoms(macho_file: *MachO) !void {...@@ -386,7 +386,7 @@ fn writeAtoms(macho_file: *MachO) !void {
386 return error.FlushFailure;386 return error.FlushFailure;
387 },387 },
388 };388 };
389 const file_offset = header.offset + atom.value - header.addr;389 const file_offset = header.offset + atom.value;
390 const rels = relocs.getPtr(atom.out_n_sect).?;390 const rels = relocs.getPtr(atom.out_n_sect).?;
391 try atom.writeRelocs(macho_file, code, rels);391 try atom.writeRelocs(macho_file, code, rels);
392 try macho_file.base.file.?.pwriteAll(code, file_offset);392 try macho_file.base.file.?.pwriteAll(code, file_offset);