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