| ... | @@ -1137,11 +1137,10 @@ pub fn allocateSpecialSymbols(self: *MachO) !void { | ... | @@ -1137,11 +1137,10 @@ pub fn allocateSpecialSymbols(self: *MachO) !void { |
| 1137 | const global = self.getGlobal(name) orelse continue; | 1137 | const global = self.getGlobal(name) orelse continue; |
| 1138 | if (global.file != null) continue; | 1138 | if (global.file != null) continue; |
| 1139 | const sym = self.getSymbolPtr(global); | 1139 | const sym = self.getSymbolPtr(global); |
| 1140 | const seg_id = switch (self.mode) { | 1140 | const seg = switch (self.mode) { |
| 1141 | .incremental => self.sections.items(.segment_index)[self.text_section_index.?], | 1141 | .incremental => self.getSegment(self.text_section_index.?), |
| 1142 | .one_shot => self.text_segment_cmd_index.?, | 1142 | .one_shot => self.segments.items[self.text_segment_cmd_index.?], |
| 1143 | }; | 1143 | }; |
| 1144 | const seg = self.segments.items[seg_id]; | | |
| 1145 | sym.n_sect = 1; | 1144 | sym.n_sect = 1; |
| 1146 | sym.n_value = seg.vmaddr; | 1145 | sym.n_value = seg.vmaddr; |
| 1147 | | 1146 | |
| ... | @@ -2239,7 +2238,6 @@ pub fn writeMainLC(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { | ... | @@ -2239,7 +2238,6 @@ pub fn writeMainLC(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 2239 | if (self.base.options.output_mode != .Exe) return; | 2238 | if (self.base.options.output_mode != .Exe) return; |
| 2240 | const seg_id = switch (self.mode) { | 2239 | const seg_id = switch (self.mode) { |
| 2241 | .incremental => self.header_segment_cmd_index.?, | 2240 | .incremental => self.header_segment_cmd_index.?, |
| 2242 | // .incremental => self.sections.items(.segment_index)[self.text_section_index.?], | | |
| 2243 | .one_shot => self.text_segment_cmd_index.?, | 2241 | .one_shot => self.text_segment_cmd_index.?, |
| 2244 | }; | 2242 | }; |
| 2245 | const seg = self.segments.items[seg_id]; | 2243 | const seg = self.segments.items[seg_id]; |
| ... | @@ -3713,9 +3711,9 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts | ... | @@ -3713,9 +3711,9 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts |
| 3713 | return section_id; | 3711 | return section_id; |
| 3714 | } | 3712 | } |
| 3715 | | 3713 | |
| 3716 | fn moveSectionInVirtualMemory(self: *MachO, sect_id: u32, needed_size: u64) !void { | 3714 | fn moveSectionInVirtualMemory(self: *MachO, sect_id: u8, needed_size: u64) !void { |
| 3717 | const header = &self.sections.items(.header)[sect_id]; | 3715 | const header = &self.sections.items(.header)[sect_id]; |
| 3718 | const segment = &self.segments.items[self.sections.items(.segment_index)[sect_id]]; | 3716 | const segment = self.getSegmentPtr(sect_id); |
| 3719 | const increased_size = padToIdeal(needed_size); | 3717 | const increased_size = padToIdeal(needed_size); |
| 3720 | const old_aligned_end = segment.vmaddr + segment.vmsize; | 3718 | const old_aligned_end = segment.vmaddr + segment.vmsize; |
| 3721 | const new_aligned_end = segment.vmaddr + mem.alignForwardGeneric(u64, increased_size, self.page_size); | 3719 | const new_aligned_end = segment.vmaddr + mem.alignForwardGeneric(u64, increased_size, self.page_size); |
| ... | @@ -3728,9 +3726,9 @@ fn moveSectionInVirtualMemory(self: *MachO, sect_id: u32, needed_size: u64) !voi | ... | @@ -3728,9 +3726,9 @@ fn moveSectionInVirtualMemory(self: *MachO, sect_id: u32, needed_size: u64) !voi |
| 3728 | | 3726 | |
| 3729 | // TODO: enforce order by increasing VM addresses in self.sections container. | 3727 | // TODO: enforce order by increasing VM addresses in self.sections container. |
| 3730 | for (self.sections.items(.header)[sect_id + 1 ..]) |*next_header, next_sect_id| { | 3728 | for (self.sections.items(.header)[sect_id + 1 ..]) |*next_header, next_sect_id| { |
| 3731 | const index = sect_id + 1 + next_sect_id; | 3729 | const index = @intCast(u8, sect_id + 1 + next_sect_id); |
| 3732 | const maybe_last_atom = &self.sections.items(.last_atom)[index]; | 3730 | const maybe_last_atom = &self.sections.items(.last_atom)[index]; |
| 3733 | const next_segment = &self.segments.items[self.sections.items(.segment_index)[index]]; | 3731 | const next_segment = self.getSegmentPtr(index); |
| 3734 | next_header.addr += diff; | 3732 | next_header.addr += diff; |
| 3735 | next_segment.vmaddr += diff; | 3733 | next_segment.vmaddr += diff; |
| 3736 | | 3734 | |
| ... | @@ -3753,7 +3751,7 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) ! | ... | @@ -3753,7 +3751,7 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) ! |
| 3753 | defer tracy.end(); | 3751 | defer tracy.end(); |
| 3754 | | 3752 | |
| 3755 | const sect_id = atom.getSymbol(self).n_sect - 1; | 3753 | const sect_id = atom.getSymbol(self).n_sect - 1; |
| 3756 | const segment = &self.segments.items[self.sections.items(.segment_index)[sect_id]]; | 3754 | const segment = self.getSegmentPtr(sect_id); |
| 3757 | const header = &self.sections.items(.header)[sect_id]; | 3755 | const header = &self.sections.items(.header)[sect_id]; |
| 3758 | const free_list = &self.sections.items(.free_list)[sect_id]; | 3756 | const free_list = &self.sections.items(.free_list)[sect_id]; |
| 3759 | const maybe_last_atom = &self.sections.items(.last_atom)[sect_id]; | 3757 | const maybe_last_atom = &self.sections.items(.last_atom)[sect_id]; |
| ... | @@ -4017,7 +4015,7 @@ fn writeSegmentHeaders(self: *MachO, ncmds: *u32, writer: anytype) !void { | ... | @@ -4017,7 +4015,7 @@ fn writeSegmentHeaders(self: *MachO, ncmds: *u32, writer: anytype) !void { |
| 4017 | } | 4015 | } |
| 4018 | | 4016 | |
| 4019 | fn writeLinkeditSegmentData(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { | 4017 | fn writeLinkeditSegmentData(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 4020 | const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; | 4018 | const seg = self.getLinkeditSegmentPtr(); |
| 4021 | seg.filesize = 0; | 4019 | seg.filesize = 0; |
| 4022 | seg.vmsize = 0; | 4020 | seg.vmsize = 0; |
| 4023 | | 4021 | |
| ... | @@ -4061,15 +4059,14 @@ fn writeDyldInfoData(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { | ... | @@ -4061,15 +4059,14 @@ fn writeDyldInfoData(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 4061 | const slice = self.sections.slice(); | 4059 | const slice = self.sections.slice(); |
| 4062 | for (slice.items(.last_atom)) |last_atom, sect_id| { | 4060 | for (slice.items(.last_atom)) |last_atom, sect_id| { |
| 4063 | var atom = last_atom orelse continue; | 4061 | var atom = last_atom orelse continue; |
| 4064 | const segment_index = slice.items(.segment_index)[sect_id]; | | |
| 4065 | const header = slice.items(.header)[sect_id]; | 4062 | const header = slice.items(.header)[sect_id]; |
| | 4063 | const segment_index = slice.items(.segment_index)[sect_id]; |
| | 4064 | const seg = self.getSegment(@intCast(u8, sect_id)); |
| 4066 | | 4065 | |
| 4067 | if (mem.eql(u8, header.segName(), "__TEXT")) continue; // __TEXT is non-writable | 4066 | if (mem.eql(u8, header.segName(), "__TEXT")) continue; // __TEXT is non-writable |
| 4068 | | 4067 | |
| 4069 | log.debug("dyld info for {s},{s}", .{ header.segName(), header.sectName() }); | 4068 | log.debug("dyld info for {s},{s}", .{ header.segName(), header.sectName() }); |
| 4070 | | 4069 | |
| 4071 | const seg = self.segments.items[segment_index]; | | |
| 4072 | | | |
| 4073 | while (true) { | 4070 | while (true) { |
| 4074 | log.debug(" ATOM(%{d}, '{s}')", .{ atom.sym_index, atom.getName(self) }); | 4071 | log.debug(" ATOM(%{d}, '{s}')", .{ atom.sym_index, atom.getName(self) }); |
| 4075 | const sym = atom.getSymbol(self); | 4072 | const sym = atom.getSymbol(self); |
| ... | @@ -4193,7 +4190,7 @@ fn writeDyldInfoData(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { | ... | @@ -4193,7 +4190,7 @@ fn writeDyldInfoData(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 4193 | try trie.finalize(gpa); | 4190 | try trie.finalize(gpa); |
| 4194 | } | 4191 | } |
| 4195 | | 4192 | |
| 4196 | const link_seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; | 4193 | const link_seg = self.getLinkeditSegmentPtr(); |
| 4197 | const rebase_off = mem.alignForwardGeneric(u64, link_seg.fileoff, @alignOf(u64)); | 4194 | const rebase_off = mem.alignForwardGeneric(u64, link_seg.fileoff, @alignOf(u64)); |
| 4198 | assert(rebase_off == link_seg.fileoff); | 4195 | assert(rebase_off == link_seg.fileoff); |
| 4199 | const rebase_size = try bind.rebaseInfoSize(rebase_pointers.items); | 4196 | const rebase_size = try bind.rebaseInfoSize(rebase_pointers.items); |
| ... | @@ -4275,11 +4272,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { | ... | @@ -4275,11 +4272,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { |
| 4275 | { | 4272 | { |
| 4276 | var stub_atom = last_atom; | 4273 | var stub_atom = last_atom; |
| 4277 | var laptr_atom = self.sections.items(.last_atom)[self.la_symbol_ptr_section_index.?].?; | 4274 | var laptr_atom = self.sections.items(.last_atom)[self.la_symbol_ptr_section_index.?].?; |
| 4278 | const base_addr = blk: { | 4275 | const base_addr = self.getSegment(self.la_symbol_ptr_section_index.?).vmaddr; |
| 4279 | const seg_id = self.sections.items(.segment_index)[self.la_symbol_ptr_section_index.?]; | | |
| 4280 | const seg = self.segments.items[seg_id]; | | |
| 4281 | break :blk seg.vmaddr; | | |
| 4282 | }; | | |
| 4283 | | 4276 | |
| 4284 | while (true) { | 4277 | while (true) { |
| 4285 | const laptr_off = blk: { | 4278 | const laptr_off = blk: { |
| ... | @@ -4461,7 +4454,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx { | ... | @@ -4461,7 +4454,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx { |
| 4461 | const nimports = @intCast(u32, imports.items.len); | 4454 | const nimports = @intCast(u32, imports.items.len); |
| 4462 | const nsyms = nlocals + nexports + nimports; | 4455 | const nsyms = nlocals + nexports + nimports; |
| 4463 | | 4456 | |
| 4464 | const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; | 4457 | const seg = self.getLinkeditSegmentPtr(); |
| 4465 | const offset = mem.alignForwardGeneric( | 4458 | const offset = mem.alignForwardGeneric( |
| 4466 | u64, | 4459 | u64, |
| 4467 | seg.fileoff + seg.filesize, | 4460 | seg.fileoff + seg.filesize, |
| ... | @@ -4492,7 +4485,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx { | ... | @@ -4492,7 +4485,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx { |
| 4492 | } | 4485 | } |
| 4493 | | 4486 | |
| 4494 | fn writeStrtab(self: *MachO, lc: *macho.symtab_command) !void { | 4487 | fn writeStrtab(self: *MachO, lc: *macho.symtab_command) !void { |
| 4495 | const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; | 4488 | const seg = self.getLinkeditSegmentPtr(); |
| 4496 | const offset = mem.alignForwardGeneric(u64, seg.fileoff + seg.filesize, @alignOf(u64)); | 4489 | const offset = mem.alignForwardGeneric(u64, seg.fileoff + seg.filesize, @alignOf(u64)); |
| 4497 | const needed_size = self.strtab.buffer.items.len; | 4490 | const needed_size = self.strtab.buffer.items.len; |
| 4498 | seg.filesize = offset + needed_size - seg.fileoff; | 4491 | seg.filesize = offset + needed_size - seg.fileoff; |
| ... | @@ -4520,7 +4513,7 @@ fn writeDysymtab(self: *MachO, ctx: SymtabCtx, lc: *macho.dysymtab_command) !voi | ... | @@ -4520,7 +4513,7 @@ fn writeDysymtab(self: *MachO, ctx: SymtabCtx, lc: *macho.dysymtab_command) !voi |
| 4520 | const iextdefsym = ctx.nlocalsym; | 4513 | const iextdefsym = ctx.nlocalsym; |
| 4521 | const iundefsym = iextdefsym + ctx.nextdefsym; | 4514 | const iundefsym = iextdefsym + ctx.nextdefsym; |
| 4522 | | 4515 | |
| 4523 | const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; | 4516 | const seg = self.getLinkeditSegmentPtr(); |
| 4524 | const offset = mem.alignForwardGeneric(u64, seg.fileoff + seg.filesize, @alignOf(u64)); | 4517 | const offset = mem.alignForwardGeneric(u64, seg.fileoff + seg.filesize, @alignOf(u64)); |
| 4525 | const needed_size = nindirectsyms * @sizeOf(u32); | 4518 | const needed_size = nindirectsyms * @sizeOf(u32); |
| 4526 | seg.filesize = offset + needed_size - seg.fileoff; | 4519 | seg.filesize = offset + needed_size - seg.fileoff; |
| ... | @@ -4592,7 +4585,7 @@ fn writeCodeSignaturePadding( | ... | @@ -4592,7 +4585,7 @@ fn writeCodeSignaturePadding( |
| 4592 | ncmds: *u32, | 4585 | ncmds: *u32, |
| 4593 | lc_writer: anytype, | 4586 | lc_writer: anytype, |
| 4594 | ) !u32 { | 4587 | ) !u32 { |
| 4595 | const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; | 4588 | const seg = self.getLinkeditSegmentPtr(); |
| 4596 | // Code signature data has to be 16-bytes aligned for Apple tools to recognize the file | 4589 | // Code signature data has to be 16-bytes aligned for Apple tools to recognize the file |
| 4597 | // https://github.com/opensource-apple/cctools/blob/fdb4825f303fd5c0751be524babd32958181b3ed/libstuff/checkout.c#L271 | 4590 | // https://github.com/opensource-apple/cctools/blob/fdb4825f303fd5c0751be524babd32958181b3ed/libstuff/checkout.c#L271 |
| 4598 | const offset = mem.alignForwardGeneric(u64, seg.fileoff + seg.filesize, 16); | 4591 | const offset = mem.alignForwardGeneric(u64, seg.fileoff + seg.filesize, 16); |
| ... | @@ -4616,8 +4609,7 @@ fn writeCodeSignaturePadding( | ... | @@ -4616,8 +4609,7 @@ fn writeCodeSignaturePadding( |
| 4616 | } | 4609 | } |
| 4617 | | 4610 | |
| 4618 | fn writeCodeSignature(self: *MachO, code_sig: *CodeSignature, offset: u32) !void { | 4611 | fn writeCodeSignature(self: *MachO, code_sig: *CodeSignature, offset: u32) !void { |
| 4619 | const seg_id = self.sections.items(.segment_index)[self.text_section_index.?]; | 4612 | const seg = self.getSegment(self.text_section_index.?); |
| 4620 | const seg = self.segments.items[seg_id]; | | |
| 4621 | | 4613 | |
| 4622 | var buffer = std.ArrayList(u8).init(self.base.allocator); | 4614 | var buffer = std.ArrayList(u8).init(self.base.allocator); |
| 4623 | defer buffer.deinit(); | 4615 | defer buffer.deinit(); |
| ... | @@ -4696,11 +4688,12 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) ?u64 { | ... | @@ -4696,11 +4688,12 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) ?u64 { |
| 4696 | | 4688 | |
| 4697 | const end = start + padToIdeal(size); | 4689 | const end = start + padToIdeal(size); |
| 4698 | | 4690 | |
| 4699 | for (self.sections.items(.header)) |header| { | 4691 | for (self.sections.items(.segment_index)) |segment_index| { |
| 4700 | const tight_size = header.size; | 4692 | const segment = self.segments.items[segment_index]; |
| | 4693 | const tight_size = segment.filesize; |
| 4701 | const increased_size = padToIdeal(tight_size); | 4694 | const increased_size = padToIdeal(tight_size); |
| 4702 | const test_end = header.offset + increased_size; | 4695 | const test_end = segment.fileoff + increased_size; |
| 4703 | if (end > header.offset and start < test_end) { | 4696 | if (end > segment.fileoff and start < test_end) { |
| 4704 | return test_end; | 4697 | return test_end; |
| 4705 | } | 4698 | } |
| 4706 | } | 4699 | } |
| ... | @@ -4712,9 +4705,10 @@ fn allocatedSize(self: *MachO, start: u64) u64 { | ... | @@ -4712,9 +4705,10 @@ fn allocatedSize(self: *MachO, start: u64) u64 { |
| 4712 | if (start == 0) | 4705 | if (start == 0) |
| 4713 | return 0; | 4706 | return 0; |
| 4714 | var min_pos: u64 = std.math.maxInt(u64); | 4707 | var min_pos: u64 = std.math.maxInt(u64); |
| 4715 | for (self.sections.items(.header)) |header| { | 4708 | for (self.sections.items(.segment_index)) |segment_index| { |
| 4716 | if (header.offset <= start) continue; | 4709 | const segment = self.segments.items[segment_index]; |
| 4717 | if (header.offset < min_pos) min_pos = header.offset; | 4710 | if (segment.fileoff <= start) continue; |
| | 4711 | if (segment.fileoff < min_pos) min_pos = segment.fileoff; |
| 4718 | } | 4712 | } |
| 4719 | return min_pos - start; | 4713 | return min_pos - start; |
| 4720 | } | 4714 | } |
| ... | @@ -4752,6 +4746,21 @@ fn getSegmentByName(self: MachO, segname: []const u8) ?u8 { | ... | @@ -4752,6 +4746,21 @@ fn getSegmentByName(self: MachO, segname: []const u8) ?u8 { |
| 4752 | } else return null; | 4746 | } else return null; |
| 4753 | } | 4747 | } |
| 4754 | | 4748 | |
| | 4749 | pub fn getSegment(self: MachO, sect_id: u8) macho.segment_command_64 { |
| | 4750 | const index = self.sections.items(.segment_index)[sect_id]; |
| | 4751 | return self.segments.items[index]; |
| | 4752 | } |
| | 4753 | |
| | 4754 | pub fn getSegmentPtr(self: *MachO, sect_id: u8) *macho.segment_command_64 { |
| | 4755 | const index = self.sections.items(.segment_index)[sect_id]; |
| | 4756 | return &self.segments.items[index]; |
| | 4757 | } |
| | 4758 | |
| | 4759 | pub fn getLinkeditSegmentPtr(self: *MachO) *macho.segment_command_64 { |
| | 4760 | const index = self.linkedit_segment_cmd_index.?; |
| | 4761 | return &self.segments.items[index]; |
| | 4762 | } |
| | 4763 | |
| 4755 | pub fn getSectionByName(self: MachO, segname: []const u8, sectname: []const u8) ?u8 { | 4764 | pub fn getSectionByName(self: MachO, segname: []const u8, sectname: []const u8) ?u8 { |
| 4756 | // TODO investigate caching with a hashmap | 4765 | // TODO investigate caching with a hashmap |
| 4757 | for (self.sections.items(.header)) |header, i| { | 4766 | for (self.sections.items(.header)) |header, i| { |