| ... | ... | @@ -559,6 +559,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 559 | 559 | |
| 560 | 560 | if (build_options.enable_logging) { |
| 561 | 561 | self.logSymtab(); |
| 562 | self.logSections(); |
| 562 | 563 | self.logAtoms(); |
| 563 | 564 | } |
| 564 | 565 | |
| ... | ... | @@ -1140,7 +1141,6 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) |
| 1140 | 1141 | try self.resolveSymbolsInArchives(); |
| 1141 | 1142 | try self.resolveDyldStubBinder(); |
| 1142 | 1143 | try self.createDyldPrivateAtom(); |
| 1143 | | try self.createStubHelperPreambleAtom(); |
| 1144 | 1144 | try self.resolveSymbolsInDylibs(); |
| 1145 | 1145 | try self.createMhExecuteHeaderSymbol(); |
| 1146 | 1146 | try self.createDsoHandleSymbol(); |
| ... | ... | @@ -1156,6 +1156,11 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) |
| 1156 | 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 | 1164 | try self.createTentativeDefAtoms(); |
| 1160 | 1165 | |
| 1161 | 1166 | for (self.objects.items) |*object, object_id| { |
| ... | ... | @@ -1166,14 +1171,14 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) |
| 1166 | 1171 | try dead_strip.gcAtoms(self); |
| 1167 | 1172 | } |
| 1168 | 1173 | |
| 1169 | | try self.pruneAndSortSections(); |
| 1170 | 1174 | try self.allocateSegments(); |
| 1171 | 1175 | try self.allocateSymbols(); |
| 1172 | 1176 | |
| 1173 | 1177 | try self.allocateSpecialSymbols(); |
| 1174 | 1178 | |
| 1175 | | if (build_options.enable_logging) { |
| 1179 | if (build_options.enable_logging or true) { |
| 1176 | 1180 | self.logSymtab(); |
| 1181 | self.logSections(); |
| 1177 | 1182 | self.logAtoms(); |
| 1178 | 1183 | } |
| 1179 | 1184 | |
| ... | ... | @@ -1691,7 +1696,7 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 { |
| 1691 | 1696 | const segname = sect.segName(); |
| 1692 | 1697 | const sectname = sect.sectName(); |
| 1693 | 1698 | const res: ?u8 = blk: { |
| 1694 | | switch (sect.type_()) { |
| 1699 | switch (sect.@"type"()) { |
| 1695 | 1700 | macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => { |
| 1696 | 1701 | if (self.text_const_section_index == null) { |
| 1697 | 1702 | self.text_const_section_index = try self.initSection( |
| ... | ... | @@ -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 | 2205 | fn allocateSpecialSymbols(self: *MachO) !void { |
| 2222 | 2206 | for (&[_][]const u8{ |
| 2223 | 2207 | "___dso_handle", |
| ... | ... | @@ -2245,9 +2229,10 @@ fn writeAtomsOneShot(self: *MachO) !void { |
| 2245 | 2229 | |
| 2246 | 2230 | for (slice.items(.last_atom)) |last_atom, sect_id| { |
| 2247 | 2231 | const header = slice.items(.header)[sect_id]; |
| 2232 | if (header.size == 0) continue; |
| 2248 | 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 | 2237 | var buffer = std.ArrayList(u8).init(gpa); |
| 2253 | 2238 | defer buffer.deinit(); |
| ... | ... | @@ -2334,8 +2319,7 @@ fn writeAtomsIncremental(self: *MachO) !void { |
| 2334 | 2319 | const sect_i = @intCast(u8, i); |
| 2335 | 2320 | const header = slice.items(.header)[sect_i]; |
| 2336 | 2321 | |
| 2337 | | // TODO handle zerofill in stage2 |
| 2338 | | // if (sect.flags == macho.S_ZEROFILL or sect.flags == macho.S_THREAD_LOCAL_ZEROFILL) continue; |
| 2322 | if (header.isZerofill()) continue; |
| 2339 | 2323 | |
| 2340 | 2324 | log.debug("writing atoms in {s},{s}", .{ header.segName(), header.sectName() }); |
| 2341 | 2325 | |
| ... | ... | @@ -3904,7 +3888,12 @@ fn getOutputSectionAtom( |
| 3904 | 3888 | // TODO finish and audit this function |
| 3905 | 3889 | if (val.isUndefDeep()) { |
| 3906 | 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 | 3897 | } else { |
| 3909 | 3898 | break :blk self.data_section_index.?; |
| 3910 | 3899 | } |
| ... | ... | @@ -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 | 4480 | if (self.linkedit_segment_cmd_index == null) { |
| 4560 | 4481 | self.linkedit_segment_cmd_index = @intCast(u8, self.segments.items.len); |
| 4561 | 4482 | var vmaddr: u64 = 0; |
| ... | ... | @@ -4690,18 +4611,19 @@ fn allocateSegments(self: *MachO) !void { |
| 4690 | 4611 | }, try self.calcMinHeaderPad()); |
| 4691 | 4612 | |
| 4692 | 4613 | if (self.text_segment_cmd_index) |index| blk: { |
| 4693 | | const seg = &self.segments.items[index]; |
| 4694 | | if (seg.nsects == 0) break :blk; |
| 4614 | const indexes = self.getSectionIndexes(index); |
| 4615 | if (indexes.start == indexes.end) break :blk; |
| 4616 | const seg = self.segments.items[index]; |
| 4695 | 4617 | |
| 4696 | 4618 | // Shift all sections to the back to minimize jump size between __TEXT and __DATA segments. |
| 4697 | 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 | 4621 | const alignment = try math.powi(u32, 2, header.@"align"); |
| 4700 | 4622 | min_alignment = math.max(min_alignment, alignment); |
| 4701 | 4623 | } |
| 4702 | 4624 | |
| 4703 | 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 | 4627 | const shift: u32 = shift: { |
| 4706 | 4628 | const diff = seg.filesize - last_header.offset - last_header.size; |
| 4707 | 4629 | const factor = @divTrunc(diff, min_alignment); |
| ... | ... | @@ -4709,7 +4631,7 @@ fn allocateSegments(self: *MachO) !void { |
| 4709 | 4631 | }; |
| 4710 | 4632 | |
| 4711 | 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 | 4635 | header.offset += shift; |
| 4714 | 4636 | header.addr += shift; |
| 4715 | 4637 | } |
| ... | ... | @@ -4746,16 +4668,14 @@ fn allocateSegment(self: *MachO, maybe_index: ?u8, indices: []const ?u8, init_si |
| 4746 | 4668 | seg.vmsize = init_size; |
| 4747 | 4669 | |
| 4748 | 4670 | // Allocate the sections according to their alignment at the beginning of the segment. |
| 4671 | const indexes = self.getSectionIndexes(index); |
| 4749 | 4672 | var start = init_size; |
| 4750 | 4673 | const slice = self.sections.slice(); |
| 4751 | | for (slice.items(.header)) |*header, sect_id| { |
| 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; |
| 4674 | for (slice.items(.header)[indexes.start..indexes.end]) |*header| { |
| 4755 | 4675 | const alignment = try math.powi(u32, 2, header.@"align"); |
| 4756 | 4676 | const start_aligned = mem.alignForwardGeneric(u64, start, alignment); |
| 4757 | 4677 | |
| 4758 | | header.offset = if (is_zerofill) |
| 4678 | header.offset = if (header.isZerofill()) |
| 4759 | 4679 | 0 |
| 4760 | 4680 | else |
| 4761 | 4681 | @intCast(u32, seg.fileoff + start_aligned); |
| ... | ... | @@ -4763,7 +4683,7 @@ fn allocateSegment(self: *MachO, maybe_index: ?u8, indices: []const ?u8, init_si |
| 4763 | 4683 | |
| 4764 | 4684 | start = start_aligned + header.size; |
| 4765 | 4685 | |
| 4766 | | if (!is_zerofill) { |
| 4686 | if (!header.isZerofill()) { |
| 4767 | 4687 | seg.filesize = start; |
| 4768 | 4688 | } |
| 4769 | 4689 | seg.vmsize = start; |
| ... | ... | @@ -4788,7 +4708,7 @@ fn initSection( |
| 4788 | 4708 | opts: InitSectionOpts, |
| 4789 | 4709 | ) !u8 { |
| 4790 | 4710 | const seg = &self.segments.items[segment_id]; |
| 4791 | | var header = macho.section_64{ |
| 4711 | const index = try self.insertSection(segment_id, .{ |
| 4792 | 4712 | .sectname = makeStaticString(sectname), |
| 4793 | 4713 | .segname = seg.segname, |
| 4794 | 4714 | .size = if (self.mode == .incremental) @intCast(u32, size) else 0, |
| ... | ... | @@ -4796,40 +4716,162 @@ fn initSection( |
| 4796 | 4716 | .flags = opts.flags, |
| 4797 | 4717 | .reserved1 = opts.reserved1, |
| 4798 | 4718 | .reserved2 = opts.reserved2, |
| 4799 | | }; |
| 4719 | }); |
| 4720 | seg.cmdsize += @sizeOf(macho.section_64); |
| 4721 | seg.nsects += 1; |
| 4800 | 4722 | |
| 4801 | 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 | 4732 | const alignment_pow_2 = try math.powi(u32, 2, alignment); |
| 4803 | | const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) |
| 4804 | | try self.calcMinHeaderPad() |
| 4805 | | else |
| 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 | | }); |
| 4733 | const padding: u64 = if (index == 0) try self.calcMinHeaderPad() else 0; |
| 4734 | const off = mem.alignForwardGeneric(u64, padding + prev_end_off, alignment_pow_2); |
| 4735 | log.debug("allocating {s},{s} section at 0x{x}", .{ header.segName(), header.sectName(), off }); |
| 4814 | 4736 | |
| 4815 | 4737 | header.addr = seg.vmaddr + off - seg.fileoff; |
| 4816 | 4738 | |
| 4817 | | // TODO handle zerofill in stage2 |
| 4818 | | // const is_zerofill = opts.flags == macho.S_ZEROFILL or opts.flags == macho.S_THREAD_LOCAL_ZEROFILL; |
| 4819 | | header.offset = @intCast(u32, off); |
| 4739 | if (!header.isZerofill()) { |
| 4740 | 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); |
| 4825 | | try self.sections.append(self.base.allocator, .{ |
| 4826 | | .segment_index = segment_id, |
| 4771 | fn insertSection(self: *MachO, segment_index: u8, header: macho.section_64) !u8 { |
| 4772 | const precedence = getSectionPrecedence(header); |
| 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 | 4824 | .header = header, |
| 4828 | 4825 | }); |
| 4829 | | seg.cmdsize += @sizeOf(macho.section_64); |
| 4830 | | seg.nsects += 1; |
| 4826 | return insertion_index; |
| 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 | 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 | 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 | 5226 | pub fn writeSegmentHeaders(self: *MachO, start: usize, end: usize, ncmds: *u32, writer: anytype) !void { |
| 5320 | | var count: usize = 0; |
| 5321 | | for (self.segments.items[start..end]) |seg| { |
| 5322 | | if (seg.cmd == .NONE) continue; |
| 5227 | for (self.segments.items[start..end]) |seg, i| { |
| 5228 | if (seg.nsects == 0 and |
| 5229 | (mem.eql(u8, seg.segName(), "__DATA_CONST") or |
| 5230 | mem.eql(u8, seg.segName(), "__DATA"))) continue; |
| 5323 | 5231 | try writer.writeStruct(seg); |
| 5324 | 5232 | |
| 5325 | | // TODO |
| 5326 | | for (self.sections.items(.header)[count..][0..seg.nsects]) |header| { |
| 5233 | const indexes = self.getSectionIndexes(@intCast(u8, start + i)); |
| 5234 | for (self.sections.items(.header)[indexes.start..indexes.end]) |header| { |
| 5327 | 5235 | try writer.writeStruct(header); |
| 5328 | 5236 | } |
| 5329 | 5237 | |
| 5330 | | count += seg.nsects; |
| 5331 | 5238 | ncmds.* += 1; |
| 5332 | 5239 | } |
| 5333 | 5240 | } |
| ... | ... | @@ -6644,6 +6551,19 @@ fn generateSymbolStabsForSymbol( |
| 6644 | 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 | 6567 | fn logSymAttributes(sym: macho.nlist_64, buf: *[9]u8) []const u8 { |
| 6648 | 6568 | mem.set(u8, buf[0..4], '_'); |
| 6649 | 6569 | mem.set(u8, buf[4..], ' '); |