authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-18 17:20:43+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-29 11:39:34+02:00
log69193a4ae421a1d69481addbba03e459df8d2a14
tree724107c10677635720784671b110ab136be69d78
parente6891b2422522d8e572cc5f57fe6dbbfc7b34cb5

macho: remove page_size field as it can be computed when and where required


3 files changed, 46 insertions(+), 41 deletions(-)

src/link/MachO.zig+28-24
......@@ -103,10 +103,6 @@ llvm_object: ?*LlvmObject = null,
103103/// Debug symbols bundle (or dSym).
104104d_sym: ?DebugSymbols = null,
105105
106/// Page size is dependent on the target cpu architecture.
107/// For x86_64 that's 4KB, whereas for aarch64, that's 16KB.
108page_size: u16,
109
110106mode: Mode,
111107
112108dyld_info_cmd: macho.dyld_info_command = .{},
......@@ -396,7 +392,6 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
396392 .allocator = allocator,
397393 .dwarf = link.File.Dwarf.init(allocator, &self.base, options.target),
398394 .file = d_sym_file,
399 .page_size = self.page_size,
400395 };
401396 }
402397
......@@ -413,16 +408,13 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
413408 try self.populateMissingMetadata();
414409
415410 if (self.d_sym) |*d_sym| {
416 try d_sym.populateMissingMetadata();
411 try d_sym.populateMissingMetadata(self);
417412 }
418413
419414 return self;
420415}
421416
422417pub 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
426418 const self = try gpa.create(MachO);
427419 errdefer gpa.destroy(self);
428420
......@@ -433,7 +425,6 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO {
433425 .allocator = gpa,
434426 .file = null,
435427 },
436 .page_size = page_size,
437428 .mode = if (options.use_llvm or options.module == null or options.cache_mode == .whole)
438429 .zld
439430 else
......@@ -698,7 +689,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
698689 // written out to the file.
699690 // The most important here is to have the correct vm and filesize of the __LINKEDIT segment
700691 // 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));
702693 codesig.code_directory.ident = self.base.options.emit.?.sub_path;
703694 if (self.base.options.entitlements) |path| {
704695 try codesig.addEntitlements(self.base.allocator, path);
......@@ -2526,7 +2517,7 @@ fn populateMissingMetadata(self: *MachO) !void {
25262517 // The first __TEXT segment is immovable and covers MachO header and load commands.
25272518 self.header_segment_cmd_index = @as(u8, @intCast(self.segments.items.len));
25282519 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));
25302521
25312522 log.debug("found __TEXT segment (header-only) free space 0x{x} to 0x{x}", .{ 0, needed_size });
25322523
......@@ -2663,7 +2654,8 @@ fn populateMissingMetadata(self: *MachO) !void {
26632654
26642655fn calcPagezeroSize(self: *MachO) u64 {
26652656 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);
26672659 if (self.base.options.output_mode == .Lib) return 0;
26682660 if (aligned_pagezero_vmsize == 0) return 0;
26692661 if (aligned_pagezero_vmsize != pagezero_vmsize) {
......@@ -2681,17 +2673,18 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts
26812673 reserved2: u32 = 0,
26822674}) !u8 {
26832675 const gpa = self.base.allocator;
2676 const page_size = getPageSize(self.base.options.target.cpu.arch);
26842677 // In incremental context, we create one section per segment pairing. This way,
26852678 // we can move the segment in raw file as we please.
26862679 const segment_id = @as(u8, @intCast(self.segments.items.len));
26872680 const section_id = @as(u8, @intCast(self.sections.slice().len));
26882681 const vmaddr = blk: {
26892682 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);
26912684 };
26922685 // 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);
26952688
26962689 log.debug("found {s},{s} free space 0x{x} to 0x{x} (0x{x} - 0x{x})", .{
26972690 segname,
......@@ -2740,9 +2733,10 @@ fn growSection(self: *MachO, sect_id: u8, needed_size: u64) !void {
27402733 const segment = &self.segments.items[segment_index];
27412734 const maybe_last_atom_index = self.sections.items(.last_atom_index)[sect_id];
27422735 const sect_capacity = self.allocatedSize(header.offset);
2736 const page_size = getPageSize(self.base.options.target.cpu.arch);
27432737
27442738 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);
27462740 const current_size = if (maybe_last_atom_index) |last_atom_index| blk: {
27472741 const last_atom = self.getAtom(last_atom_index);
27482742 const sym = last_atom.getSymbol(self);
......@@ -2774,16 +2768,17 @@ fn growSection(self: *MachO, sect_id: u8, needed_size: u64) !void {
27742768 }
27752769
27762770 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);
27792773}
27802774
27812775fn growSectionVirtualMemory(self: *MachO, sect_id: u8, needed_size: u64) !void {
2776 const page_size = getPageSize(self.base.options.target.cpu.arch);
27822777 const header = &self.sections.items(.header)[sect_id];
27832778 const segment = self.getSegmentPtr(sect_id);
27842779 const increased_size = padToIdeal(needed_size);
27852780 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);
27872782 const diff = new_aligned_end - old_aligned_end;
27882783 log.debug("shifting every segment after {s},{s} in virtual memory by {x}", .{
27892784 header.segName(),
......@@ -2955,6 +2950,7 @@ fn writeSegmentHeaders(self: *MachO, writer: anytype) !void {
29552950}
29562951
29572952fn writeLinkeditSegmentData(self: *MachO) !void {
2953 const page_size = getPageSize(self.base.options.target.cpu.arch);
29582954 const seg = self.getLinkeditSegmentPtr();
29592955 seg.filesize = 0;
29602956 seg.vmsize = 0;
......@@ -2962,17 +2958,17 @@ fn writeLinkeditSegmentData(self: *MachO) !void {
29622958 for (self.segments.items, 0..) |segment, id| {
29632959 if (self.linkedit_segment_cmd_index.? == @as(u8, @intCast(id))) continue;
29642960 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);
29662962 }
29672963 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);
29692965 }
29702966 }
29712967
29722968 try self.writeDyldInfoData();
29732969 try self.writeSymtabs();
29742970
2975 seg.vmsize = mem.alignForward(u64, seg.filesize, self.page_size);
2971 seg.vmsize = mem.alignForward(u64, seg.filesize, page_size);
29762972}
29772973
29782974fn collectRebaseDataFromTableSection(self: *MachO, sect_id: u8, rebase: *Rebase, table: anytype) !void {
......@@ -3456,7 +3452,7 @@ fn writeCodeSignaturePadding(self: *MachO, code_sig: *CodeSignature) !void {
34563452 const offset = mem.alignForward(u64, seg.fileoff + seg.filesize, 16);
34573453 const needed_size = code_sig.estimateSize(offset);
34583454 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));
34603456 log.debug("writing code signature padding from 0x{x} to 0x{x}", .{ offset, offset + needed_size });
34613457 // Pad out the space. We need to do this to calculate valid hashes for everything in the file
34623458 // except for code signature data.
......@@ -3781,6 +3777,14 @@ pub fn getDebugSymbols(self: *MachO) ?*DebugSymbols {
37813777 return &self.d_sym.?;
37823778}
37833779
3780pub 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
37843788pub fn findFirst(comptime T: type, haystack: []align(1) const T, start: usize, predicate: anytype) usize {
37853789 if (!@hasDecl(@TypeOf(predicate), "predicate"))
37863790 @compileError("Predicate is required to define fn predicate(@This(), T) bool");
src/link/MachO/DebugSymbols.zig+10-8
......@@ -24,7 +24,6 @@ const Type = @import("../../type.zig").Type;
2424allocator: Allocator,
2525dwarf: Dwarf,
2626file: fs.File,
27page_size: u16,
2827
2928symtab_cmd: macho.symtab_command = .{},
3029
......@@ -62,13 +61,14 @@ pub const Reloc = struct {
6261
6362/// You must call this function *after* `MachO.populateMissingMetadata()`
6463/// has been called to get a viable debug symbols output.
65pub fn populateMissingMetadata(self: *DebugSymbols) !void {
64pub fn populateMissingMetadata(self: *DebugSymbols, macho_file: *MachO) !void {
6665 if (self.dwarf_segment_cmd_index == null) {
6766 self.dwarf_segment_cmd_index = @as(u8, @intCast(self.segments.items.len));
6867
69 const off = @as(u64, @intCast(self.page_size));
68 const page_size = MachO.getPageSize(macho_file.base.options.target.cpu.arch);
69 const off = @as(u64, @intCast(page_size));
7070 const ideal_size: u16 = 200 + 128 + 160 + 250;
71 const needed_size = mem.alignForward(u64, padToIdeal(ideal_size), self.page_size);
71 const needed_size = mem.alignForward(u64, padToIdeal(ideal_size), page_size);
7272
7373 log.debug("found __DWARF segment free space 0x{x} to 0x{x}", .{ off, off + needed_size });
7474
......@@ -355,7 +355,8 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {
355355 file_size = @max(file_size, header.offset + header.size);
356356 }
357357
358 const aligned_size = mem.alignForward(u64, file_size, self.page_size);
358 const page_size = MachO.getPageSize(macho_file.base.options.target.cpu.arch);
359 const aligned_size = mem.alignForward(u64, file_size, page_size);
359360 dwarf_segment.vmaddr = base_vmaddr;
360361 dwarf_segment.filesize = aligned_size;
361362 dwarf_segment.vmsize = aligned_size;
......@@ -364,12 +365,12 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {
364365 linkedit.vmaddr = mem.alignForward(
365366 u64,
366367 dwarf_segment.vmaddr + aligned_size,
367 self.page_size,
368 page_size,
368369 );
369370 linkedit.fileoff = mem.alignForward(
370371 u64,
371372 dwarf_segment.fileoff + aligned_size,
372 self.page_size,
373 page_size,
373374 );
374375 log.debug("found __LINKEDIT segment free space at 0x{x}", .{linkedit.fileoff});
375376}
......@@ -457,8 +458,9 @@ fn writeLinkeditSegmentData(self: *DebugSymbols, macho_file: *MachO) !void {
457458 try self.writeSymtab(macho_file);
458459 try self.writeStrtab();
459460
461 const page_size = MachO.getPageSize(macho_file.base.options.target.cpu.arch);
460462 const seg = &self.segments.items[self.linkedit_segment_cmd_index.?];
461 const aligned_size = mem.alignForward(u64, seg.filesize, self.page_size);
463 const aligned_size = mem.alignForward(u64, seg.filesize, page_size);
462464 seg.vmsize = aligned_size;
463465}
464466
src/link/MachO/zld.zig+8-9
......@@ -42,7 +42,6 @@ const Rebase = @import("dyld_info/Rebase.zig");
4242pub const Zld = struct {
4343 gpa: Allocator,
4444 file: fs.File,
45 page_size: u16,
4645 options: *const link.Options,
4746
4847 dyld_info_cmd: macho.dyld_info_command = .{},
......@@ -1208,7 +1207,8 @@ pub const Zld = struct {
12081207
12091208 fn createSegments(self: *Zld) !void {
12101209 const pagezero_vmsize = self.options.pagezero_size orelse MachO.default_pagezero_vmsize;
1211 const aligned_pagezero_vmsize = mem.alignBackward(u64, pagezero_vmsize, self.page_size);
1210 const page_size = MachO.getPageSize(self.options.target.cpu.arch);
1211 const aligned_pagezero_vmsize = mem.alignBackward(u64, pagezero_vmsize, page_size);
12121212 if (self.options.output_mode != .Lib and aligned_pagezero_vmsize > 0) {
12131213 if (aligned_pagezero_vmsize != pagezero_vmsize) {
12141214 log.warn("requested __PAGEZERO size (0x{x}) is not page aligned", .{pagezero_vmsize});
......@@ -1635,8 +1635,9 @@ pub const Zld = struct {
16351635 segment.vmsize = start;
16361636 }
16371637
1638 segment.filesize = mem.alignForward(u64, segment.filesize, self.page_size);
1639 segment.vmsize = mem.alignForward(u64, segment.vmsize, self.page_size);
1638 const page_size = MachO.getPageSize(self.options.target.cpu.arch);
1639 segment.filesize = mem.alignForward(u64, segment.filesize, page_size);
1640 segment.vmsize = mem.alignForward(u64, segment.vmsize, page_size);
16401641 }
16411642
16421643 const InitSectionOpts = struct {
......@@ -1746,7 +1747,7 @@ pub const Zld = struct {
17461747 try self.writeSymtabs();
17471748
17481749 const seg = self.getLinkeditSegmentPtr();
1749 seg.vmsize = mem.alignForward(u64, seg.filesize, self.page_size);
1750 seg.vmsize = mem.alignForward(u64, seg.filesize, MachO.getPageSize(self.options.target.cpu.arch));
17501751 }
17511752
17521753 fn collectRebaseDataFromContainer(
......@@ -2630,7 +2631,7 @@ pub const Zld = struct {
26302631 const offset = mem.alignForward(u64, seg.fileoff + seg.filesize, 16);
26312632 const needed_size = code_sig.estimateSize(offset);
26322633 seg.filesize = offset + needed_size - seg.fileoff;
2633 seg.vmsize = mem.alignForward(u64, seg.filesize, self.page_size);
2634 seg.vmsize = mem.alignForward(u64, seg.filesize, MachO.getPageSize(self.options.target.cpu.arch));
26342635 log.debug("writing code signature padding from 0x{x} to 0x{x}", .{ offset, offset + needed_size });
26352636 // Pad out the space. We need to do this to calculate valid hashes for everything in the file
26362637 // except for code signature data.
......@@ -3491,7 +3492,6 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
34913492 try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{});
34923493 }
34933494 } else {
3494 const page_size = macho_file.page_size;
34953495 const sub_path = options.emit.?.sub_path;
34963496
34973497 const file = try directory.handle.createFile(sub_path, .{
......@@ -3504,7 +3504,6 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
35043504 var zld = Zld{
35053505 .gpa = gpa,
35063506 .file = file,
3507 .page_size = macho_file.page_size,
35083507 .options = options,
35093508 };
35103509 defer zld.deinit();
......@@ -3818,7 +3817,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
38183817 // written out to the file.
38193818 // The most important here is to have the correct vm and filesize of the __LINKEDIT segment
38203819 // where the code signature goes into.
3821 var codesig = CodeSignature.init(page_size);
3820 var codesig = CodeSignature.init(MachO.getPageSize(zld.options.target.cpu.arch));
38223821 codesig.code_directory.ident = fs.path.basename(full_out_path);
38233822 if (options.entitlements) |path| {
38243823 try codesig.addEntitlements(zld.gpa, path);