| ... | ... | @@ -103,10 +103,6 @@ llvm_object: ?*LlvmObject = null, |
| 103 | 103 | /// Debug symbols bundle (or dSym). |
| 104 | 104 | d_sym: ?DebugSymbols = null, |
| 105 | 105 | |
| 106 | | /// Page size is dependent on the target cpu architecture. |
| 107 | | /// For x86_64 that's 4KB, whereas for aarch64, that's 16KB. |
| 108 | | page_size: u16, |
| 109 | | |
| 110 | 106 | mode: Mode, |
| 111 | 107 | |
| 112 | 108 | dyld_info_cmd: macho.dyld_info_command = .{}, |
| ... | ... | @@ -396,7 +392,6 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO { |
| 396 | 392 | .allocator = allocator, |
| 397 | 393 | .dwarf = link.File.Dwarf.init(allocator, &self.base, options.target), |
| 398 | 394 | .file = d_sym_file, |
| 399 | | .page_size = self.page_size, |
| 400 | 395 | }; |
| 401 | 396 | } |
| 402 | 397 | |
| ... | ... | @@ -413,16 +408,13 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO { |
| 413 | 408 | try self.populateMissingMetadata(); |
| 414 | 409 | |
| 415 | 410 | if (self.d_sym) |*d_sym| { |
| 416 | | try d_sym.populateMissingMetadata(); |
| 411 | try d_sym.populateMissingMetadata(self); |
| 417 | 412 | } |
| 418 | 413 | |
| 419 | 414 | return self; |
| 420 | 415 | } |
| 421 | 416 | |
| 422 | 417 | pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO { |
| 423 | | const cpu_arch = options.target.cpu.arch; |
| 424 | | const page_size: u16 = if (cpu_arch == .aarch64) 0x4000 else 0x1000; |
| 425 | | |
| 426 | 418 | const self = try gpa.create(MachO); |
| 427 | 419 | errdefer gpa.destroy(self); |
| 428 | 420 | |
| ... | ... | @@ -433,7 +425,6 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO { |
| 433 | 425 | .allocator = gpa, |
| 434 | 426 | .file = null, |
| 435 | 427 | }, |
| 436 | | .page_size = page_size, |
| 437 | 428 | .mode = if (options.use_llvm or options.module == null or options.cache_mode == .whole) |
| 438 | 429 | .zld |
| 439 | 430 | else |
| ... | ... | @@ -698,7 +689,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 698 | 689 | // written out to the file. |
| 699 | 690 | // The most important here is to have the correct vm and filesize of the __LINKEDIT segment |
| 700 | 691 | // where the code signature goes into. |
| 701 | | var codesig = CodeSignature.init(self.page_size); |
| 692 | var codesig = CodeSignature.init(getPageSize(self.base.options.target.cpu.arch)); |
| 702 | 693 | codesig.code_directory.ident = self.base.options.emit.?.sub_path; |
| 703 | 694 | if (self.base.options.entitlements) |path| { |
| 704 | 695 | try codesig.addEntitlements(self.base.allocator, path); |
| ... | ... | @@ -2526,7 +2517,7 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 2526 | 2517 | // The first __TEXT segment is immovable and covers MachO header and load commands. |
| 2527 | 2518 | self.header_segment_cmd_index = @as(u8, @intCast(self.segments.items.len)); |
| 2528 | 2519 | const ideal_size = @max(self.base.options.headerpad_size orelse 0, default_headerpad_size); |
| 2529 | | const needed_size = mem.alignForward(u64, padToIdeal(ideal_size), self.page_size); |
| 2520 | const needed_size = mem.alignForward(u64, padToIdeal(ideal_size), getPageSize(self.base.options.target.cpu.arch)); |
| 2530 | 2521 | |
| 2531 | 2522 | log.debug("found __TEXT segment (header-only) free space 0x{x} to 0x{x}", .{ 0, needed_size }); |
| 2532 | 2523 | |
| ... | ... | @@ -2663,7 +2654,8 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 2663 | 2654 | |
| 2664 | 2655 | fn calcPagezeroSize(self: *MachO) u64 { |
| 2665 | 2656 | const pagezero_vmsize = self.base.options.pagezero_size orelse default_pagezero_vmsize; |
| 2666 | | const aligned_pagezero_vmsize = mem.alignBackward(u64, pagezero_vmsize, self.page_size); |
| 2657 | const page_size = getPageSize(self.base.options.target.cpu.arch); |
| 2658 | const aligned_pagezero_vmsize = mem.alignBackward(u64, pagezero_vmsize, page_size); |
| 2667 | 2659 | if (self.base.options.output_mode == .Lib) return 0; |
| 2668 | 2660 | if (aligned_pagezero_vmsize == 0) return 0; |
| 2669 | 2661 | if (aligned_pagezero_vmsize != pagezero_vmsize) { |
| ... | ... | @@ -2681,17 +2673,18 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts |
| 2681 | 2673 | reserved2: u32 = 0, |
| 2682 | 2674 | }) !u8 { |
| 2683 | 2675 | const gpa = self.base.allocator; |
| 2676 | const page_size = getPageSize(self.base.options.target.cpu.arch); |
| 2684 | 2677 | // In incremental context, we create one section per segment pairing. This way, |
| 2685 | 2678 | // we can move the segment in raw file as we please. |
| 2686 | 2679 | const segment_id = @as(u8, @intCast(self.segments.items.len)); |
| 2687 | 2680 | const section_id = @as(u8, @intCast(self.sections.slice().len)); |
| 2688 | 2681 | const vmaddr = blk: { |
| 2689 | 2682 | const prev_segment = self.segments.items[segment_id - 1]; |
| 2690 | | break :blk mem.alignForward(u64, prev_segment.vmaddr + prev_segment.vmsize, self.page_size); |
| 2683 | break :blk mem.alignForward(u64, prev_segment.vmaddr + prev_segment.vmsize, page_size); |
| 2691 | 2684 | }; |
| 2692 | 2685 | // We commit more memory than needed upfront so that we don't have to reallocate too soon. |
| 2693 | | const vmsize = mem.alignForward(u64, opts.size, self.page_size); |
| 2694 | | const off = self.findFreeSpace(opts.size, self.page_size); |
| 2686 | const vmsize = mem.alignForward(u64, opts.size, page_size); |
| 2687 | const off = self.findFreeSpace(opts.size, page_size); |
| 2695 | 2688 | |
| 2696 | 2689 | log.debug("found {s},{s} free space 0x{x} to 0x{x} (0x{x} - 0x{x})", .{ |
| 2697 | 2690 | segname, |
| ... | ... | @@ -2740,9 +2733,10 @@ fn growSection(self: *MachO, sect_id: u8, needed_size: u64) !void { |
| 2740 | 2733 | const segment = &self.segments.items[segment_index]; |
| 2741 | 2734 | const maybe_last_atom_index = self.sections.items(.last_atom_index)[sect_id]; |
| 2742 | 2735 | const sect_capacity = self.allocatedSize(header.offset); |
| 2736 | const page_size = getPageSize(self.base.options.target.cpu.arch); |
| 2743 | 2737 | |
| 2744 | 2738 | if (needed_size > sect_capacity) { |
| 2745 | | const new_offset = self.findFreeSpace(needed_size, self.page_size); |
| 2739 | const new_offset = self.findFreeSpace(needed_size, page_size); |
| 2746 | 2740 | const current_size = if (maybe_last_atom_index) |last_atom_index| blk: { |
| 2747 | 2741 | const last_atom = self.getAtom(last_atom_index); |
| 2748 | 2742 | const sym = last_atom.getSymbol(self); |
| ... | ... | @@ -2774,16 +2768,17 @@ fn growSection(self: *MachO, sect_id: u8, needed_size: u64) !void { |
| 2774 | 2768 | } |
| 2775 | 2769 | |
| 2776 | 2770 | header.size = needed_size; |
| 2777 | | segment.filesize = mem.alignForward(u64, needed_size, self.page_size); |
| 2778 | | segment.vmsize = mem.alignForward(u64, needed_size, self.page_size); |
| 2771 | segment.filesize = mem.alignForward(u64, needed_size, page_size); |
| 2772 | segment.vmsize = mem.alignForward(u64, needed_size, page_size); |
| 2779 | 2773 | } |
| 2780 | 2774 | |
| 2781 | 2775 | fn growSectionVirtualMemory(self: *MachO, sect_id: u8, needed_size: u64) !void { |
| 2776 | const page_size = getPageSize(self.base.options.target.cpu.arch); |
| 2782 | 2777 | const header = &self.sections.items(.header)[sect_id]; |
| 2783 | 2778 | const segment = self.getSegmentPtr(sect_id); |
| 2784 | 2779 | const increased_size = padToIdeal(needed_size); |
| 2785 | 2780 | const old_aligned_end = segment.vmaddr + segment.vmsize; |
| 2786 | | const new_aligned_end = segment.vmaddr + mem.alignForward(u64, increased_size, self.page_size); |
| 2781 | const new_aligned_end = segment.vmaddr + mem.alignForward(u64, increased_size, page_size); |
| 2787 | 2782 | const diff = new_aligned_end - old_aligned_end; |
| 2788 | 2783 | log.debug("shifting every segment after {s},{s} in virtual memory by {x}", .{ |
| 2789 | 2784 | header.segName(), |
| ... | ... | @@ -2955,6 +2950,7 @@ fn writeSegmentHeaders(self: *MachO, writer: anytype) !void { |
| 2955 | 2950 | } |
| 2956 | 2951 | |
| 2957 | 2952 | fn writeLinkeditSegmentData(self: *MachO) !void { |
| 2953 | const page_size = getPageSize(self.base.options.target.cpu.arch); |
| 2958 | 2954 | const seg = self.getLinkeditSegmentPtr(); |
| 2959 | 2955 | seg.filesize = 0; |
| 2960 | 2956 | seg.vmsize = 0; |
| ... | ... | @@ -2962,17 +2958,17 @@ fn writeLinkeditSegmentData(self: *MachO) !void { |
| 2962 | 2958 | for (self.segments.items, 0..) |segment, id| { |
| 2963 | 2959 | if (self.linkedit_segment_cmd_index.? == @as(u8, @intCast(id))) continue; |
| 2964 | 2960 | if (seg.vmaddr < segment.vmaddr + segment.vmsize) { |
| 2965 | | seg.vmaddr = mem.alignForward(u64, segment.vmaddr + segment.vmsize, self.page_size); |
| 2961 | seg.vmaddr = mem.alignForward(u64, segment.vmaddr + segment.vmsize, page_size); |
| 2966 | 2962 | } |
| 2967 | 2963 | if (seg.fileoff < segment.fileoff + segment.filesize) { |
| 2968 | | seg.fileoff = mem.alignForward(u64, segment.fileoff + segment.filesize, self.page_size); |
| 2964 | seg.fileoff = mem.alignForward(u64, segment.fileoff + segment.filesize, page_size); |
| 2969 | 2965 | } |
| 2970 | 2966 | } |
| 2971 | 2967 | |
| 2972 | 2968 | try self.writeDyldInfoData(); |
| 2973 | 2969 | try self.writeSymtabs(); |
| 2974 | 2970 | |
| 2975 | | seg.vmsize = mem.alignForward(u64, seg.filesize, self.page_size); |
| 2971 | seg.vmsize = mem.alignForward(u64, seg.filesize, page_size); |
| 2976 | 2972 | } |
| 2977 | 2973 | |
| 2978 | 2974 | fn collectRebaseDataFromTableSection(self: *MachO, sect_id: u8, rebase: *Rebase, table: anytype) !void { |
| ... | ... | @@ -3456,7 +3452,7 @@ fn writeCodeSignaturePadding(self: *MachO, code_sig: *CodeSignature) !void { |
| 3456 | 3452 | const offset = mem.alignForward(u64, seg.fileoff + seg.filesize, 16); |
| 3457 | 3453 | const needed_size = code_sig.estimateSize(offset); |
| 3458 | 3454 | seg.filesize = offset + needed_size - seg.fileoff; |
| 3459 | | seg.vmsize = mem.alignForward(u64, seg.filesize, self.page_size); |
| 3455 | seg.vmsize = mem.alignForward(u64, seg.filesize, getPageSize(self.base.options.target.cpu.arch)); |
| 3460 | 3456 | log.debug("writing code signature padding from 0x{x} to 0x{x}", .{ offset, offset + needed_size }); |
| 3461 | 3457 | // Pad out the space. We need to do this to calculate valid hashes for everything in the file |
| 3462 | 3458 | // except for code signature data. |
| ... | ... | @@ -3781,6 +3777,14 @@ pub fn getDebugSymbols(self: *MachO) ?*DebugSymbols { |
| 3781 | 3777 | return &self.d_sym.?; |
| 3782 | 3778 | } |
| 3783 | 3779 | |
| 3780 | pub inline fn getPageSize(cpu_arch: std.Target.Cpu.Arch) u16 { |
| 3781 | return switch (cpu_arch) { |
| 3782 | .aarch64 => 0x4000, |
| 3783 | .x86_64 => 0x1000, |
| 3784 | else => unreachable, |
| 3785 | }; |
| 3786 | } |
| 3787 | |
| 3784 | 3788 | pub fn findFirst(comptime T: type, haystack: []align(1) const T, start: usize, predicate: anytype) usize { |
| 3785 | 3789 | if (!@hasDecl(@TypeOf(predicate), "predicate")) |
| 3786 | 3790 | @compileError("Predicate is required to define fn predicate(@This(), T) bool"); |