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