| ... | @@ -559,6 +559,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -559,6 +559,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 559 | | 559 | |
| 560 | if (build_options.enable_logging) { | 560 | if (build_options.enable_logging) { |
| 561 | self.logSymtab(); | 561 | self.logSymtab(); |
| | 562 | self.logSections(); |
| 562 | self.logAtoms(); | 563 | self.logAtoms(); |
| 563 | } | 564 | } |
| 564 | | 565 | |
| ... | @@ -1140,7 +1141,6 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) | ... | @@ -1140,7 +1141,6 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) |
| 1140 | try self.resolveSymbolsInArchives(); | 1141 | try self.resolveSymbolsInArchives(); |
| 1141 | try self.resolveDyldStubBinder(); | 1142 | try self.resolveDyldStubBinder(); |
| 1142 | try self.createDyldPrivateAtom(); | 1143 | try self.createDyldPrivateAtom(); |
| 1143 | try self.createStubHelperPreambleAtom(); | | |
| 1144 | try self.resolveSymbolsInDylibs(); | 1144 | try self.resolveSymbolsInDylibs(); |
| 1145 | try self.createMhExecuteHeaderSymbol(); | 1145 | try self.createMhExecuteHeaderSymbol(); |
| 1146 | try self.createDsoHandleSymbol(); | 1146 | try self.createDsoHandleSymbol(); |
| ... | @@ -1156,6 +1156,11 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) | ... | @@ -1156,6 +1156,11 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) |
| 1156 | return error.FrameworkNotFound; | 1156 | return error.FrameworkNotFound; |
| 1157 | } | 1157 | } |
| 1158 | | 1158 | |
| | 1159 | for (self.objects.items) |*object| { |
| | 1160 | try object.scanInputSections(self); |
| | 1161 | } |
| | 1162 | |
| | 1163 | try self.createStubHelperPreambleAtom(); |
| 1159 | try self.createTentativeDefAtoms(); | 1164 | try self.createTentativeDefAtoms(); |
| 1160 | | 1165 | |
| 1161 | for (self.objects.items) |*object, object_id| { | 1166 | for (self.objects.items) |*object, object_id| { |
| ... | @@ -1166,14 +1171,14 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) | ... | @@ -1166,14 +1171,14 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) |
| 1166 | try dead_strip.gcAtoms(self); | 1171 | try dead_strip.gcAtoms(self); |
| 1167 | } | 1172 | } |
| 1168 | | 1173 | |
| 1169 | try self.pruneAndSortSections(); | | |
| 1170 | try self.allocateSegments(); | 1174 | try self.allocateSegments(); |
| 1171 | try self.allocateSymbols(); | 1175 | try self.allocateSymbols(); |
| 1172 | | 1176 | |
| 1173 | try self.allocateSpecialSymbols(); | 1177 | try self.allocateSpecialSymbols(); |
| 1174 | | 1178 | |
| 1175 | if (build_options.enable_logging) { | 1179 | if (build_options.enable_logging or true) { |
| 1176 | self.logSymtab(); | 1180 | self.logSymtab(); |
| | 1181 | self.logSections(); |
| 1177 | self.logAtoms(); | 1182 | self.logAtoms(); |
| 1178 | } | 1183 | } |
| 1179 | | 1184 | |
| ... | @@ -1691,7 +1696,7 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 { | ... | @@ -1691,7 +1696,7 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 { |
| 1691 | const segname = sect.segName(); | 1696 | const segname = sect.segName(); |
| 1692 | const sectname = sect.sectName(); | 1697 | const sectname = sect.sectName(); |
| 1693 | const res: ?u8 = blk: { | 1698 | const res: ?u8 = blk: { |
| 1694 | switch (sect.type_()) { | 1699 | switch (sect.@"type"()) { |
| 1695 | macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => { | 1700 | macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => { |
| 1696 | if (self.text_const_section_index == null) { | 1701 | if (self.text_const_section_index == null) { |
| 1697 | self.text_const_section_index = try self.initSection( | 1702 | self.text_const_section_index = try self.initSection( |
| ... | @@ -2197,27 +2202,6 @@ fn allocateSymbols(self: *MachO) !void { | ... | @@ -2197,27 +2202,6 @@ fn allocateSymbols(self: *MachO) !void { |
| 2197 | } | 2202 | } |
| 2198 | } | 2203 | } |
| 2199 | | 2204 | |
| 2200 | fn shiftLocalsByOffset(self: *MachO, sect_id: u8, offset: i64) !void { | | |
| 2201 | var atom = self.sections.items(.last_atom)[sect_id] orelse return; | | |
| 2202 | | | |
| 2203 | while (true) { | | |
| 2204 | const atom_sym = atom.getSymbolPtr(self); | | |
| 2205 | atom_sym.n_value = @intCast(u64, @intCast(i64, atom_sym.n_value) + offset); | | |
| 2206 | | | |
| 2207 | for (atom.contained.items) |sym_at_off| { | | |
| 2208 | const contained_sym = self.getSymbolPtr(.{ | | |
| 2209 | .sym_index = sym_at_off.sym_index, | | |
| 2210 | .file = atom.file, | | |
| 2211 | }); | | |
| 2212 | contained_sym.n_value = @intCast(u64, @intCast(i64, contained_sym.n_value) + offset); | | |
| 2213 | } | | |
| 2214 | | | |
| 2215 | if (atom.prev) |prev| { | | |
| 2216 | atom = prev; | | |
| 2217 | } else break; | | |
| 2218 | } | | |
| 2219 | } | | |
| 2220 | | | |
| 2221 | fn allocateSpecialSymbols(self: *MachO) !void { | 2205 | fn allocateSpecialSymbols(self: *MachO) !void { |
| 2222 | for (&[_][]const u8{ | 2206 | for (&[_][]const u8{ |
| 2223 | "___dso_handle", | 2207 | "___dso_handle", |
| ... | @@ -2245,9 +2229,10 @@ fn writeAtomsOneShot(self: *MachO) !void { | ... | @@ -2245,9 +2229,10 @@ fn writeAtomsOneShot(self: *MachO) !void { |
| 2245 | | 2229 | |
| 2246 | for (slice.items(.last_atom)) |last_atom, sect_id| { | 2230 | for (slice.items(.last_atom)) |last_atom, sect_id| { |
| 2247 | const header = slice.items(.header)[sect_id]; | 2231 | const header = slice.items(.header)[sect_id]; |
| | 2232 | if (header.size == 0) continue; |
| 2248 | var atom = last_atom.?; | 2233 | var atom = last_atom.?; |
| 2249 | | 2234 | |
| 2250 | if (header.flags == macho.S_ZEROFILL or header.flags == macho.S_THREAD_LOCAL_ZEROFILL) continue; | 2235 | if (header.isZerofill()) continue; |
| 2251 | | 2236 | |
| 2252 | var buffer = std.ArrayList(u8).init(gpa); | 2237 | var buffer = std.ArrayList(u8).init(gpa); |
| 2253 | defer buffer.deinit(); | 2238 | defer buffer.deinit(); |
| ... | @@ -2334,8 +2319,7 @@ fn writeAtomsIncremental(self: *MachO) !void { | ... | @@ -2334,8 +2319,7 @@ fn writeAtomsIncremental(self: *MachO) !void { |
| 2334 | const sect_i = @intCast(u8, i); | 2319 | const sect_i = @intCast(u8, i); |
| 2335 | const header = slice.items(.header)[sect_i]; | 2320 | const header = slice.items(.header)[sect_i]; |
| 2336 | | 2321 | |
| 2337 | // TODO handle zerofill in stage2 | 2322 | if (header.isZerofill()) continue; |
| 2338 | // if (sect.flags == macho.S_ZEROFILL or sect.flags == macho.S_THREAD_LOCAL_ZEROFILL) continue; | | |
| 2339 | | 2323 | |
| 2340 | log.debug("writing atoms in {s},{s}", .{ header.segName(), header.sectName() }); | 2324 | log.debug("writing atoms in {s},{s}", .{ header.segName(), header.sectName() }); |
| 2341 | | 2325 | |
| ... | @@ -3904,7 +3888,12 @@ fn getOutputSectionAtom( | ... | @@ -3904,7 +3888,12 @@ fn getOutputSectionAtom( |
| 3904 | // TODO finish and audit this function | 3888 | // TODO finish and audit this function |
| 3905 | if (val.isUndefDeep()) { | 3889 | if (val.isUndefDeep()) { |
| 3906 | if (mode == .ReleaseFast or mode == .ReleaseSmall) { | 3890 | if (mode == .ReleaseFast or mode == .ReleaseSmall) { |
| 3907 | break :blk self.bss_section_index.?; | 3891 | break :blk (try self.getOutputSection(.{ |
| | 3892 | .segname = makeStaticString("__DATA"), |
| | 3893 | .sectname = makeStaticString("__bss"), |
| | 3894 | .size = code.len, |
| | 3895 | .@"align" = align_log_2, |
| | 3896 | })).?; |
| 3908 | } else { | 3897 | } else { |
| 3909 | break :blk self.data_section_index.?; | 3898 | break :blk self.data_section_index.?; |
| 3910 | } | 3899 | } |
| ... | @@ -4488,74 +4477,6 @@ fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -4488,74 +4477,6 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4488 | ); | 4477 | ); |
| 4489 | } | 4478 | } |
| 4490 | | 4479 | |
| 4491 | if (self.tlv_section_index == null) { | | |
| 4492 | const needed_size = if (self.mode == .incremental) | | |
| 4493 | @sizeOf(u64) * self.base.options.symbol_count_hint | | |
| 4494 | else | | |
| 4495 | 0; | | |
| 4496 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) | | |
| 4497 | self.tlv_section_index = try self.initSection( | | |
| 4498 | self.data_segment_cmd_index.?, | | |
| 4499 | "__thread_vars", | | |
| 4500 | needed_size, | | |
| 4501 | alignment, | | |
| 4502 | .{ | | |
| 4503 | .flags = macho.S_THREAD_LOCAL_VARIABLES, | | |
| 4504 | }, | | |
| 4505 | ); | | |
| 4506 | } | | |
| 4507 | | | |
| 4508 | if (self.tlv_data_section_index == null) { | | |
| 4509 | const needed_size = if (self.mode == .incremental) | | |
| 4510 | @sizeOf(u64) * self.base.options.symbol_count_hint | | |
| 4511 | else | | |
| 4512 | 0; | | |
| 4513 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) | | |
| 4514 | self.tlv_data_section_index = try self.initSection( | | |
| 4515 | self.data_segment_cmd_index.?, | | |
| 4516 | "__thread_data", | | |
| 4517 | needed_size, | | |
| 4518 | alignment, | | |
| 4519 | .{ | | |
| 4520 | .flags = macho.S_THREAD_LOCAL_REGULAR, | | |
| 4521 | }, | | |
| 4522 | ); | | |
| 4523 | } | | |
| 4524 | | | |
| 4525 | if (self.tlv_bss_section_index == null) { | | |
| 4526 | const needed_size = if (self.mode == .incremental) | | |
| 4527 | @sizeOf(u64) * self.base.options.symbol_count_hint | | |
| 4528 | else | | |
| 4529 | 0; | | |
| 4530 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) | | |
| 4531 | self.tlv_bss_section_index = try self.initSection( | | |
| 4532 | self.data_segment_cmd_index.?, | | |
| 4533 | "__thread_bss", | | |
| 4534 | needed_size, | | |
| 4535 | alignment, | | |
| 4536 | .{ | | |
| 4537 | .flags = macho.S_THREAD_LOCAL_ZEROFILL, | | |
| 4538 | }, | | |
| 4539 | ); | | |
| 4540 | } | | |
| 4541 | | | |
| 4542 | if (self.bss_section_index == null) { | | |
| 4543 | const needed_size = if (self.mode == .incremental) | | |
| 4544 | @sizeOf(u64) * self.base.options.symbol_count_hint | | |
| 4545 | else | | |
| 4546 | 0; | | |
| 4547 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) | | |
| 4548 | self.bss_section_index = try self.initSection( | | |
| 4549 | self.data_segment_cmd_index.?, | | |
| 4550 | "__bss", | | |
| 4551 | needed_size, | | |
| 4552 | alignment, | | |
| 4553 | .{ | | |
| 4554 | .flags = macho.S_ZEROFILL, | | |
| 4555 | }, | | |
| 4556 | ); | | |
| 4557 | } | | |
| 4558 | | | |
| 4559 | if (self.linkedit_segment_cmd_index == null) { | 4480 | if (self.linkedit_segment_cmd_index == null) { |
| 4560 | self.linkedit_segment_cmd_index = @intCast(u8, self.segments.items.len); | 4481 | self.linkedit_segment_cmd_index = @intCast(u8, self.segments.items.len); |
| 4561 | var vmaddr: u64 = 0; | 4482 | var vmaddr: u64 = 0; |
| ... | @@ -4690,18 +4611,19 @@ fn allocateSegments(self: *MachO) !void { | ... | @@ -4690,18 +4611,19 @@ fn allocateSegments(self: *MachO) !void { |
| 4690 | }, try self.calcMinHeaderPad()); | 4611 | }, try self.calcMinHeaderPad()); |
| 4691 | | 4612 | |
| 4692 | if (self.text_segment_cmd_index) |index| blk: { | 4613 | if (self.text_segment_cmd_index) |index| blk: { |
| 4693 | const seg = &self.segments.items[index]; | 4614 | const indexes = self.getSectionIndexes(index); |
| 4694 | if (seg.nsects == 0) break :blk; | 4615 | if (indexes.start == indexes.end) break :blk; |
| | 4616 | const seg = self.segments.items[index]; |
| 4695 | | 4617 | |
| 4696 | // Shift all sections to the back to minimize jump size between __TEXT and __DATA segments. | 4618 | // Shift all sections to the back to minimize jump size between __TEXT and __DATA segments. |
| 4697 | var min_alignment: u32 = 0; | 4619 | var min_alignment: u32 = 0; |
| 4698 | for (self.sections.items(.header)[0..seg.nsects]) |header| { | 4620 | for (self.sections.items(.header)[indexes.start..indexes.end]) |header| { |
| 4699 | const alignment = try math.powi(u32, 2, header.@"align"); | 4621 | const alignment = try math.powi(u32, 2, header.@"align"); |
| 4700 | min_alignment = math.max(min_alignment, alignment); | 4622 | min_alignment = math.max(min_alignment, alignment); |
| 4701 | } | 4623 | } |
| 4702 | | 4624 | |
| 4703 | assert(min_alignment > 0); | 4625 | assert(min_alignment > 0); |
| 4704 | const last_header = self.sections.items(.header)[seg.nsects - 1]; | 4626 | const last_header = self.sections.items(.header)[indexes.end - 1]; |
| 4705 | const shift: u32 = shift: { | 4627 | const shift: u32 = shift: { |
| 4706 | const diff = seg.filesize - last_header.offset - last_header.size; | 4628 | const diff = seg.filesize - last_header.offset - last_header.size; |
| 4707 | const factor = @divTrunc(diff, min_alignment); | 4629 | const factor = @divTrunc(diff, min_alignment); |
| ... | @@ -4709,7 +4631,7 @@ fn allocateSegments(self: *MachO) !void { | ... | @@ -4709,7 +4631,7 @@ fn allocateSegments(self: *MachO) !void { |
| 4709 | }; | 4631 | }; |
| 4710 | | 4632 | |
| 4711 | if (shift > 0) { | 4633 | if (shift > 0) { |
| 4712 | for (self.sections.items(.header)[0..seg.nsects]) |*header| { | 4634 | for (self.sections.items(.header)[indexes.start..indexes.end]) |*header| { |
| 4713 | header.offset += shift; | 4635 | header.offset += shift; |
| 4714 | header.addr += shift; | 4636 | header.addr += shift; |
| 4715 | } | 4637 | } |
| ... | @@ -4746,16 +4668,14 @@ fn allocateSegment(self: *MachO, maybe_index: ?u8, indices: []const ?u8, init_si | ... | @@ -4746,16 +4668,14 @@ fn allocateSegment(self: *MachO, maybe_index: ?u8, indices: []const ?u8, init_si |
| 4746 | seg.vmsize = init_size; | 4668 | seg.vmsize = init_size; |
| 4747 | | 4669 | |
| 4748 | // Allocate the sections according to their alignment at the beginning of the segment. | 4670 | // Allocate the sections according to their alignment at the beginning of the segment. |
| | 4671 | const indexes = self.getSectionIndexes(index); |
| 4749 | var start = init_size; | 4672 | var start = init_size; |
| 4750 | const slice = self.sections.slice(); | 4673 | const slice = self.sections.slice(); |
| 4751 | for (slice.items(.header)) |*header, sect_id| { | 4674 | for (slice.items(.header)[indexes.start..indexes.end]) |*header| { |
| 4752 | const segment_index = slice.items(.segment_index)[sect_id]; | | |
| 4753 | if (segment_index != index) continue; | | |
| 4754 | const is_zerofill = header.flags == macho.S_ZEROFILL or header.flags == macho.S_THREAD_LOCAL_ZEROFILL; | | |
| 4755 | const alignment = try math.powi(u32, 2, header.@"align"); | 4675 | const alignment = try math.powi(u32, 2, header.@"align"); |
| 4756 | const start_aligned = mem.alignForwardGeneric(u64, start, alignment); | 4676 | const start_aligned = mem.alignForwardGeneric(u64, start, alignment); |
| 4757 | | 4677 | |
| 4758 | header.offset = if (is_zerofill) | 4678 | header.offset = if (header.isZerofill()) |
| 4759 | 0 | 4679 | 0 |
| 4760 | else | 4680 | else |
| 4761 | @intCast(u32, seg.fileoff + start_aligned); | 4681 | @intCast(u32, seg.fileoff + start_aligned); |
| ... | @@ -4763,7 +4683,7 @@ fn allocateSegment(self: *MachO, maybe_index: ?u8, indices: []const ?u8, init_si | ... | @@ -4763,7 +4683,7 @@ fn allocateSegment(self: *MachO, maybe_index: ?u8, indices: []const ?u8, init_si |
| 4763 | | 4683 | |
| 4764 | start = start_aligned + header.size; | 4684 | start = start_aligned + header.size; |
| 4765 | | 4685 | |
| 4766 | if (!is_zerofill) { | 4686 | if (!header.isZerofill()) { |
| 4767 | seg.filesize = start; | 4687 | seg.filesize = start; |
| 4768 | } | 4688 | } |
| 4769 | seg.vmsize = start; | 4689 | seg.vmsize = start; |
| ... | @@ -4788,7 +4708,7 @@ fn initSection( | ... | @@ -4788,7 +4708,7 @@ fn initSection( |
| 4788 | opts: InitSectionOpts, | 4708 | opts: InitSectionOpts, |
| 4789 | ) !u8 { | 4709 | ) !u8 { |
| 4790 | const seg = &self.segments.items[segment_id]; | 4710 | const seg = &self.segments.items[segment_id]; |
| 4791 | var header = macho.section_64{ | 4711 | const index = try self.insertSection(segment_id, .{ |
| 4792 | .sectname = makeStaticString(sectname), | 4712 | .sectname = makeStaticString(sectname), |
| 4793 | .segname = seg.segname, | 4713 | .segname = seg.segname, |
| 4794 | .size = if (self.mode == .incremental) @intCast(u32, size) else 0, | 4714 | .size = if (self.mode == .incremental) @intCast(u32, size) else 0, |
| ... | @@ -4796,40 +4716,162 @@ fn initSection( | ... | @@ -4796,40 +4716,162 @@ fn initSection( |
| 4796 | .flags = opts.flags, | 4716 | .flags = opts.flags, |
| 4797 | .reserved1 = opts.reserved1, | 4717 | .reserved1 = opts.reserved1, |
| 4798 | .reserved2 = opts.reserved2, | 4718 | .reserved2 = opts.reserved2, |
| 4799 | }; | 4719 | }); |
| | 4720 | seg.cmdsize += @sizeOf(macho.section_64); |
| | 4721 | seg.nsects += 1; |
| 4800 | | 4722 | |
| 4801 | if (self.mode == .incremental) { | 4723 | if (self.mode == .incremental) { |
| | 4724 | const header = &self.sections.items(.header)[index]; |
| | 4725 | const prev_end_off = if (index > 0) blk: { |
| | 4726 | const prev_section = self.sections.get(index - 1); |
| | 4727 | if (prev_section.segment_index == segment_id) { |
| | 4728 | const prev_header = prev_section.header; |
| | 4729 | break :blk prev_header.offset + padToIdeal(prev_header.size); |
| | 4730 | } else break :blk seg.fileoff; |
| | 4731 | } else 0; |
| 4802 | const alignment_pow_2 = try math.powi(u32, 2, alignment); | 4732 | const alignment_pow_2 = try math.powi(u32, 2, alignment); |
| 4803 | const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) | 4733 | const padding: u64 = if (index == 0) try self.calcMinHeaderPad() else 0; |
| 4804 | try self.calcMinHeaderPad() | 4734 | const off = mem.alignForwardGeneric(u64, padding + prev_end_off, alignment_pow_2); |
| 4805 | else | 4735 | log.debug("allocating {s},{s} section at 0x{x}", .{ header.segName(), header.sectName(), off }); |
| 4806 | null; | | |
| 4807 | const off = self.findFreeSpace(segment_id, alignment_pow_2, padding); | | |
| 4808 | log.debug("allocating {s},{s} section from 0x{x} to 0x{x}", .{ | | |
| 4809 | header.segName(), | | |
| 4810 | header.sectName(), | | |
| 4811 | off, | | |
| 4812 | off + size, | | |
| 4813 | }); | | |
| 4814 | | 4736 | |
| 4815 | header.addr = seg.vmaddr + off - seg.fileoff; | 4737 | header.addr = seg.vmaddr + off - seg.fileoff; |
| 4816 | | 4738 | |
| 4817 | // TODO handle zerofill in stage2 | 4739 | if (!header.isZerofill()) { |
| 4818 | // const is_zerofill = opts.flags == macho.S_ZEROFILL or opts.flags == macho.S_THREAD_LOCAL_ZEROFILL; | 4740 | header.offset = @intCast(u32, off); |
| 4819 | header.offset = @intCast(u32, off); | 4741 | } |
| | 4742 | |
| | 4743 | self.updateSectionOrdinals(index + 1); |
| | 4744 | } |
| | 4745 | |
| | 4746 | return index; |
| | 4747 | } |
| 4820 | | 4748 | |
| 4821 | try self.updateSectionOrdinals(); | 4749 | fn getSectionPrecedence(header: macho.section_64) u4 { |
| | 4750 | if (header.isCode()) { |
| | 4751 | if (mem.eql(u8, "__text", header.sectName())) return 0x0; |
| | 4752 | if (header.@"type"() == macho.S_SYMBOL_STUBS) return 0x1; |
| | 4753 | return 0x2; |
| | 4754 | } |
| | 4755 | switch (header.@"type"()) { |
| | 4756 | macho.S_NON_LAZY_SYMBOL_POINTERS, |
| | 4757 | macho.S_LAZY_SYMBOL_POINTERS, |
| | 4758 | => return 0x0, |
| | 4759 | macho.S_MOD_INIT_FUNC_POINTERS => return 0x1, |
| | 4760 | macho.S_MOD_TERM_FUNC_POINTERS => return 0x2, |
| | 4761 | macho.S_ZEROFILL => return 0xf, |
| | 4762 | macho.S_THREAD_LOCAL_REGULAR => return 0xd, |
| | 4763 | macho.S_THREAD_LOCAL_ZEROFILL => return 0xe, |
| | 4764 | else => if (mem.eql(u8, "__eh_frame", header.sectName())) |
| | 4765 | return 0xf |
| | 4766 | else |
| | 4767 | return 0x3, |
| 4822 | } | 4768 | } |
| | 4769 | } |
| 4823 | | 4770 | |
| 4824 | const index = @intCast(u8, self.sections.slice().len); | 4771 | fn insertSection(self: *MachO, segment_index: u8, header: macho.section_64) !u8 { |
| 4825 | try self.sections.append(self.base.allocator, .{ | 4772 | const precedence = getSectionPrecedence(header); |
| 4826 | .segment_index = segment_id, | 4773 | const indexes = self.getSectionIndexes(segment_index); |
| | 4774 | const insertion_index = for (self.sections.items(.header)[indexes.start..indexes.end]) |hdr, i| { |
| | 4775 | if (getSectionPrecedence(hdr) > precedence) break @intCast(u8, i + indexes.start); |
| | 4776 | } else indexes.end; |
| | 4777 | log.debug("inserting section '{s},{s}' at index {d}", .{ |
| | 4778 | header.segName(), |
| | 4779 | header.sectName(), |
| | 4780 | insertion_index, |
| | 4781 | }); |
| | 4782 | // TODO slim it down |
| | 4783 | for (&[_]*?u8{ |
| | 4784 | // __TEXT |
| | 4785 | &self.text_section_index, |
| | 4786 | &self.stubs_section_index, |
| | 4787 | &self.stub_helper_section_index, |
| | 4788 | &self.gcc_except_tab_section_index, |
| | 4789 | &self.cstring_section_index, |
| | 4790 | &self.ustring_section_index, |
| | 4791 | &self.text_const_section_index, |
| | 4792 | &self.objc_methlist_section_index, |
| | 4793 | &self.objc_methname_section_index, |
| | 4794 | &self.objc_methtype_section_index, |
| | 4795 | &self.objc_classname_section_index, |
| | 4796 | &self.eh_frame_section_index, |
| | 4797 | // __DATA_CONST |
| | 4798 | &self.got_section_index, |
| | 4799 | &self.mod_init_func_section_index, |
| | 4800 | &self.mod_term_func_section_index, |
| | 4801 | &self.data_const_section_index, |
| | 4802 | &self.objc_cfstring_section_index, |
| | 4803 | &self.objc_classlist_section_index, |
| | 4804 | &self.objc_imageinfo_section_index, |
| | 4805 | // __DATA |
| | 4806 | &self.rustc_section_index, |
| | 4807 | &self.la_symbol_ptr_section_index, |
| | 4808 | &self.objc_const_section_index, |
| | 4809 | &self.objc_selrefs_section_index, |
| | 4810 | &self.objc_classrefs_section_index, |
| | 4811 | &self.objc_data_section_index, |
| | 4812 | &self.data_section_index, |
| | 4813 | &self.tlv_section_index, |
| | 4814 | &self.tlv_ptrs_section_index, |
| | 4815 | &self.tlv_data_section_index, |
| | 4816 | &self.tlv_bss_section_index, |
| | 4817 | &self.bss_section_index, |
| | 4818 | }) |maybe_index| { |
| | 4819 | const index = maybe_index.* orelse continue; |
| | 4820 | if (insertion_index <= index) maybe_index.* = index + 1; |
| | 4821 | } |
| | 4822 | try self.sections.insert(self.base.allocator, insertion_index, .{ |
| | 4823 | .segment_index = segment_index, |
| 4827 | .header = header, | 4824 | .header = header, |
| 4828 | }); | 4825 | }); |
| 4829 | seg.cmdsize += @sizeOf(macho.section_64); | 4826 | return insertion_index; |
| 4830 | seg.nsects += 1; | 4827 | } |
| 4831 | | 4828 | |
| 4832 | return index; | 4829 | fn updateSectionOrdinals(self: *MachO, start: u8) void { |
| | 4830 | const tracy = trace(@src()); |
| | 4831 | defer tracy.end(); |
| | 4832 | |
| | 4833 | const slice = self.sections.slice(); |
| | 4834 | for (slice.items(.last_atom)[start..]) |last_atom| { |
| | 4835 | var atom = last_atom.?; |
| | 4836 | |
| | 4837 | while (true) { |
| | 4838 | const sym = atom.getSymbolPtr(self); |
| | 4839 | sym.n_sect = start + 1; |
| | 4840 | |
| | 4841 | for (atom.contained.items) |sym_at_off| { |
| | 4842 | const contained_sym = self.getSymbolPtr(.{ |
| | 4843 | .sym_index = sym_at_off.sym_index, |
| | 4844 | .file = atom.file, |
| | 4845 | }); |
| | 4846 | contained_sym.n_sect = start + 1; |
| | 4847 | } |
| | 4848 | |
| | 4849 | if (atom.prev) |prev| { |
| | 4850 | atom = prev; |
| | 4851 | } else break; |
| | 4852 | } |
| | 4853 | } |
| | 4854 | } |
| | 4855 | |
| | 4856 | fn shiftLocalsByOffset(self: *MachO, sect_id: u8, offset: i64) !void { |
| | 4857 | var atom = self.sections.items(.last_atom)[sect_id] orelse return; |
| | 4858 | |
| | 4859 | while (true) { |
| | 4860 | const atom_sym = atom.getSymbolPtr(self); |
| | 4861 | atom_sym.n_value = @intCast(u64, @intCast(i64, atom_sym.n_value) + offset); |
| | 4862 | |
| | 4863 | for (atom.contained.items) |sym_at_off| { |
| | 4864 | const contained_sym = self.getSymbolPtr(.{ |
| | 4865 | .sym_index = sym_at_off.sym_index, |
| | 4866 | .file = atom.file, |
| | 4867 | }); |
| | 4868 | contained_sym.n_value = @intCast(u64, @intCast(i64, contained_sym.n_value) + offset); |
| | 4869 | } |
| | 4870 | |
| | 4871 | if (atom.prev) |prev| { |
| | 4872 | atom = prev; |
| | 4873 | } else break; |
| | 4874 | } |
| 4833 | } | 4875 | } |
| 4834 | | 4876 | |
| 4835 | fn findFreeSpace(self: MachO, segment_id: u8, alignment: u64, start: ?u64) u64 { | 4877 | fn findFreeSpace(self: MachO, segment_id: u8, alignment: u64, start: ?u64) u64 { |
| ... | @@ -5181,153 +5223,18 @@ fn getSegmentAllocBase(self: MachO, indices: []const ?u8) struct { vmaddr: u64, | ... | @@ -5181,153 +5223,18 @@ fn getSegmentAllocBase(self: MachO, indices: []const ?u8) struct { vmaddr: u64, |
| 5181 | return .{ .vmaddr = 0, .fileoff = 0 }; | 5223 | return .{ .vmaddr = 0, .fileoff = 0 }; |
| 5182 | } | 5224 | } |
| 5183 | | 5225 | |
| 5184 | fn pruneAndSortSections(self: *MachO) !void { | | |
| 5185 | const gpa = self.base.allocator; | | |
| 5186 | | | |
| 5187 | var sections = self.sections.toOwnedSlice(); | | |
| 5188 | defer sections.deinit(gpa); | | |
| 5189 | try self.sections.ensureTotalCapacity(gpa, sections.len); | | |
| 5190 | | | |
| 5191 | for (&[_]*?u8{ | | |
| 5192 | // __TEXT | | |
| 5193 | &self.text_section_index, | | |
| 5194 | &self.stubs_section_index, | | |
| 5195 | &self.stub_helper_section_index, | | |
| 5196 | &self.gcc_except_tab_section_index, | | |
| 5197 | &self.cstring_section_index, | | |
| 5198 | &self.ustring_section_index, | | |
| 5199 | &self.text_const_section_index, | | |
| 5200 | &self.objc_methlist_section_index, | | |
| 5201 | &self.objc_methname_section_index, | | |
| 5202 | &self.objc_methtype_section_index, | | |
| 5203 | &self.objc_classname_section_index, | | |
| 5204 | &self.eh_frame_section_index, | | |
| 5205 | // __DATA_CONST | | |
| 5206 | &self.got_section_index, | | |
| 5207 | &self.mod_init_func_section_index, | | |
| 5208 | &self.mod_term_func_section_index, | | |
| 5209 | &self.data_const_section_index, | | |
| 5210 | &self.objc_cfstring_section_index, | | |
| 5211 | &self.objc_classlist_section_index, | | |
| 5212 | &self.objc_imageinfo_section_index, | | |
| 5213 | // __DATA | | |
| 5214 | &self.rustc_section_index, | | |
| 5215 | &self.la_symbol_ptr_section_index, | | |
| 5216 | &self.objc_const_section_index, | | |
| 5217 | &self.objc_selrefs_section_index, | | |
| 5218 | &self.objc_classrefs_section_index, | | |
| 5219 | &self.objc_data_section_index, | | |
| 5220 | &self.data_section_index, | | |
| 5221 | &self.tlv_section_index, | | |
| 5222 | &self.tlv_ptrs_section_index, | | |
| 5223 | &self.tlv_data_section_index, | | |
| 5224 | &self.tlv_bss_section_index, | | |
| 5225 | &self.bss_section_index, | | |
| 5226 | }) |maybe_index| { | | |
| 5227 | const old_idx = maybe_index.* orelse continue; | | |
| 5228 | const segment_index = sections.items(.segment_index)[old_idx]; | | |
| 5229 | const header = sections.items(.header)[old_idx]; | | |
| 5230 | const last_atom = sections.items(.last_atom)[old_idx]; | | |
| 5231 | if (header.size == 0) { | | |
| 5232 | log.debug("pruning section {s},{s}", .{ header.segName(), header.sectName() }); | | |
| 5233 | maybe_index.* = null; | | |
| 5234 | const seg = &self.segments.items[segment_index]; | | |
| 5235 | seg.cmdsize -= @sizeOf(macho.section_64); | | |
| 5236 | seg.nsects -= 1; | | |
| 5237 | } else { | | |
| 5238 | maybe_index.* = @intCast(u8, self.sections.slice().len); | | |
| 5239 | self.sections.appendAssumeCapacity(.{ | | |
| 5240 | .segment_index = segment_index, | | |
| 5241 | .header = header, | | |
| 5242 | .last_atom = last_atom, | | |
| 5243 | }); | | |
| 5244 | } | | |
| 5245 | } | | |
| 5246 | | | |
| 5247 | for (self.segments.items) |*seg| { | | |
| 5248 | const segname = seg.segName(); | | |
| 5249 | if (seg.nsects == 0 and | | |
| 5250 | !mem.eql(u8, "__TEXT", segname) and | | |
| 5251 | !mem.eql(u8, "__PAGEZERO", segname) and | | |
| 5252 | !mem.eql(u8, "__LINKEDIT", segname)) | | |
| 5253 | { | | |
| 5254 | // Segment has now become empty, so mark it as such | | |
| 5255 | log.debug("marking segment {s} as dead", .{seg.segName()}); | | |
| 5256 | seg.cmd = @intToEnum(macho.LC, 0); | | |
| 5257 | } | | |
| 5258 | } | | |
| 5259 | } | | |
| 5260 | | | |
| 5261 | fn updateSectionOrdinals(self: *MachO) !void { | | |
| 5262 | _ = self; | | |
| 5263 | const tracy = trace(@src()); | | |
| 5264 | defer tracy.end(); | | |
| 5265 | | | |
| 5266 | @panic("updating section ordinals"); | | |
| 5267 | | | |
| 5268 | // const gpa = self.base.allocator; | | |
| 5269 | | | |
| 5270 | // var ordinal_remap = std.AutoHashMap(u8, u8).init(gpa); | | |
| 5271 | // defer ordinal_remap.deinit(); | | |
| 5272 | // var ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{}; | | |
| 5273 | | | |
| 5274 | // var new_ordinal: u8 = 0; | | |
| 5275 | // for (&[_]?u16{ | | |
| 5276 | // self.text_segment_cmd_index, | | |
| 5277 | // self.data_const_segment_cmd_index, | | |
| 5278 | // self.data_segment_cmd_index, | | |
| 5279 | // }) |maybe_index| { | | |
| 5280 | // const index = maybe_index orelse continue; | | |
| 5281 | // const seg = self.load_commands.items[index].segment; | | |
| 5282 | // for (seg.sections.items) |sect, sect_id| { | | |
| 5283 | // const match = MatchingSection{ | | |
| 5284 | // .seg = @intCast(u16, index), | | |
| 5285 | // .sect = @intCast(u16, sect_id), | | |
| 5286 | // }; | | |
| 5287 | // const old_ordinal = self.getSectionOrdinal(match); | | |
| 5288 | // new_ordinal += 1; | | |
| 5289 | // log.debug("'{s},{s}': sect({d}, '_,_') => sect({d}, '_,_')", .{ | | |
| 5290 | // sect.segName(), | | |
| 5291 | // sect.sectName(), | | |
| 5292 | // old_ordinal, | | |
| 5293 | // new_ordinal, | | |
| 5294 | // }); | | |
| 5295 | // try ordinal_remap.putNoClobber(old_ordinal, new_ordinal); | | |
| 5296 | // try ordinals.putNoClobber(gpa, match, {}); | | |
| 5297 | // } | | |
| 5298 | // } | | |
| 5299 | | | |
| 5300 | // // FIXME Jakub | | |
| 5301 | // // TODO no need for duping work here; simply walk the atom graph | | |
| 5302 | // for (self.locals.items) |*sym| { | | |
| 5303 | // if (sym.undf()) continue; | | |
| 5304 | // if (sym.n_sect == 0) continue; | | |
| 5305 | // sym.n_sect = ordinal_remap.get(sym.n_sect).?; | | |
| 5306 | // } | | |
| 5307 | // for (self.objects.items) |*object| { | | |
| 5308 | // for (object.symtab.items) |*sym| { | | |
| 5309 | // if (sym.undf()) continue; | | |
| 5310 | // if (sym.n_sect == 0) continue; | | |
| 5311 | // sym.n_sect = ordinal_remap.get(sym.n_sect).?; | | |
| 5312 | // } | | |
| 5313 | // } | | |
| 5314 | | | |
| 5315 | // self.section_ordinals.deinit(gpa); | | |
| 5316 | // self.section_ordinals = ordinals; | | |
| 5317 | } | | |
| 5318 | | | |
| 5319 | pub fn writeSegmentHeaders(self: *MachO, start: usize, end: usize, ncmds: *u32, writer: anytype) !void { | 5226 | pub fn writeSegmentHeaders(self: *MachO, start: usize, end: usize, ncmds: *u32, writer: anytype) !void { |
| 5320 | var count: usize = 0; | 5227 | for (self.segments.items[start..end]) |seg, i| { |
| 5321 | for (self.segments.items[start..end]) |seg| { | 5228 | if (seg.nsects == 0 and |
| 5322 | if (seg.cmd == .NONE) continue; | 5229 | (mem.eql(u8, seg.segName(), "__DATA_CONST") or |
| | 5230 | mem.eql(u8, seg.segName(), "__DATA"))) continue; |
| 5323 | try writer.writeStruct(seg); | 5231 | try writer.writeStruct(seg); |
| 5324 | | 5232 | |
| 5325 | // TODO | 5233 | const indexes = self.getSectionIndexes(@intCast(u8, start + i)); |
| 5326 | for (self.sections.items(.header)[count..][0..seg.nsects]) |header| { | 5234 | for (self.sections.items(.header)[indexes.start..indexes.end]) |header| { |
| 5327 | try writer.writeStruct(header); | 5235 | try writer.writeStruct(header); |
| 5328 | } | 5236 | } |
| 5329 | | 5237 | |
| 5330 | count += seg.nsects; | | |
| 5331 | ncmds.* += 1; | 5238 | ncmds.* += 1; |
| 5332 | } | 5239 | } |
| 5333 | } | 5240 | } |
| ... | @@ -6644,6 +6551,19 @@ fn generateSymbolStabsForSymbol( | ... | @@ -6644,6 +6551,19 @@ fn generateSymbolStabsForSymbol( |
| 6644 | // try writer.writeByte(']'); | 6551 | // try writer.writeByte(']'); |
| 6645 | // } | 6552 | // } |
| 6646 | | 6553 | |
| | 6554 | fn logSections(self: *MachO) void { |
| | 6555 | log.debug("sections:", .{}); |
| | 6556 | for (self.sections.items(.header)) |header, i| { |
| | 6557 | log.debug(" sect({d}): {s},{s} @{x}, sizeof({x})", .{ |
| | 6558 | i + 1, |
| | 6559 | header.segName(), |
| | 6560 | header.sectName(), |
| | 6561 | header.offset, |
| | 6562 | header.size, |
| | 6563 | }); |
| | 6564 | } |
| | 6565 | } |
| | 6566 | |
| 6647 | fn logSymAttributes(sym: macho.nlist_64, buf: *[9]u8) []const u8 { | 6567 | fn logSymAttributes(sym: macho.nlist_64, buf: *[9]u8) []const u8 { |
| 6648 | mem.set(u8, buf[0..4], '_'); | 6568 | mem.set(u8, buf[0..4], '_'); |
| 6649 | mem.set(u8, buf[4..], ' '); | 6569 | mem.set(u8, buf[4..], ' '); |