| author | |
| committer | |
| log | 601ab9a251a7952026fa9c72427344126bf62730 |
| tree | a111b9df535a32f13c584d78b6259812c960e7e8 |
| parent | 19056cb6821dd03612628e9220595576878aafe7 |
| parent | c0c5acf074a9eba01e892184489ac3e837d739bc |
| signature |
macho: ensure LINKEDIT layout follows Apple strict validation rules5 files changed, 197 insertions(+), 93 deletions(-)
lib/std/build/CheckObjectStep.zig+6-1| ... | @@ -126,7 +126,7 @@ const Action = struct { | ... | @@ -126,7 +126,7 @@ const Action = struct { |
| 126 | /// its reduced, computed value compares using `op` with the expected value, either | 126 | /// its reduced, computed value compares using `op` with the expected value, either |
| 127 | /// a literal or another extracted variable. | 127 | /// a literal or another extracted variable. |
| 128 | fn computeCmp(act: Action, gpa: Allocator, global_vars: anytype) !bool { | 128 | fn computeCmp(act: Action, gpa: Allocator, global_vars: anytype) !bool { |
| 129 | var op_stack = std.ArrayList(enum { add, sub, mod }).init(gpa); | 129 | var op_stack = std.ArrayList(enum { add, sub, mod, mul }).init(gpa); |
| 130 | var values = std.ArrayList(u64).init(gpa); | 130 | var values = std.ArrayList(u64).init(gpa); |
| 131 | 131 | ||
| 132 | var it = mem.tokenize(u8, act.phrase, " "); | 132 | var it = mem.tokenize(u8, act.phrase, " "); |
| ... | @@ -137,6 +137,8 @@ const Action = struct { | ... | @@ -137,6 +137,8 @@ const Action = struct { |
| 137 | try op_stack.append(.sub); | 137 | try op_stack.append(.sub); |
| 138 | } else if (mem.eql(u8, next, "%")) { | 138 | } else if (mem.eql(u8, next, "%")) { |
| 139 | try op_stack.append(.mod); | 139 | try op_stack.append(.mod); |
| 140 | } else if (mem.eql(u8, next, "*")) { | ||
| 141 | try op_stack.append(.mul); | ||
| 140 | } else { | 142 | } else { |
| 141 | const val = std.fmt.parseInt(u64, next, 0) catch blk: { | 143 | const val = std.fmt.parseInt(u64, next, 0) catch blk: { |
| 142 | break :blk global_vars.get(next) orelse { | 144 | break :blk global_vars.get(next) orelse { |
| ... | @@ -167,6 +169,9 @@ const Action = struct { | ... | @@ -167,6 +169,9 @@ const Action = struct { |
| 167 | .mod => { | 169 | .mod => { |
| 168 | reduced %= other; | 170 | reduced %= other; |
| 169 | }, | 171 | }, |
| 172 | .mul => { | ||
| 173 | reduced *= other; | ||
| 174 | }, | ||
| 170 | } | 175 | } |
| 171 | op_i += 1; | 176 | op_i += 1; |
| 172 | } | 177 | } |
src/link/MachO.zig+52-30| ... | @@ -3358,27 +3358,36 @@ fn writeDyldInfoData(self: *MachO) !void { | ... | @@ -3358,27 +3358,36 @@ fn writeDyldInfoData(self: *MachO) !void { |
| 3358 | try self.collectExportData(&trie); | 3358 | try self.collectExportData(&trie); |
| 3359 | 3359 | ||
| 3360 | const link_seg = self.getLinkeditSegmentPtr(); | 3360 | const link_seg = self.getLinkeditSegmentPtr(); |
| 3361 | const rebase_off = mem.alignForwardGeneric(u64, link_seg.fileoff, @alignOf(u64)); | 3361 | assert(mem.isAlignedGeneric(u64, link_seg.fileoff, @alignOf(u64))); |
| 3362 | assert(rebase_off == link_seg.fileoff); | 3362 | const rebase_off = link_seg.fileoff; |
| 3363 | const rebase_size = try bind.rebaseInfoSize(rebase_pointers.items); | 3363 | const rebase_size = try bind.rebaseInfoSize(rebase_pointers.items); |
| 3364 | log.debug("writing rebase info from 0x{x} to 0x{x}", .{ rebase_off, rebase_off + rebase_size }); | 3364 | const rebase_size_aligned = mem.alignForwardGeneric(u64, rebase_size, @alignOf(u64)); |
| 3365 | log.debug("writing rebase info from 0x{x} to 0x{x}", .{ rebase_off, rebase_off + rebase_size_aligned }); | ||
| 3365 | 3366 | ||
| 3366 | const bind_off = mem.alignForwardGeneric(u64, rebase_off + rebase_size, @alignOf(u64)); | 3367 | const bind_off = rebase_off + rebase_size_aligned; |
| 3367 | const bind_size = try bind.bindInfoSize(bind_pointers.items); | 3368 | const bind_size = try bind.bindInfoSize(bind_pointers.items); |
| 3368 | log.debug("writing bind info from 0x{x} to 0x{x}", .{ bind_off, bind_off + bind_size }); | 3369 | const bind_size_aligned = mem.alignForwardGeneric(u64, bind_size, @alignOf(u64)); |
| 3370 | log.debug("writing bind info from 0x{x} to 0x{x}", .{ bind_off, bind_off + bind_size_aligned }); | ||
| 3369 | 3371 | ||
| 3370 | const lazy_bind_off = mem.alignForwardGeneric(u64, bind_off + bind_size, @alignOf(u64)); | 3372 | const lazy_bind_off = bind_off + bind_size_aligned; |
| 3371 | const lazy_bind_size = try bind.lazyBindInfoSize(lazy_bind_pointers.items); | 3373 | const lazy_bind_size = try bind.lazyBindInfoSize(lazy_bind_pointers.items); |
| 3372 | log.debug("writing lazy bind info from 0x{x} to 0x{x}", .{ lazy_bind_off, lazy_bind_off + lazy_bind_size }); | 3374 | const lazy_bind_size_aligned = mem.alignForwardGeneric(u64, lazy_bind_size, @alignOf(u64)); |
| 3375 | log.debug("writing lazy bind info from 0x{x} to 0x{x}", .{ | ||
| 3376 | lazy_bind_off, | ||
| 3377 | lazy_bind_off + lazy_bind_size_aligned, | ||
| 3378 | }); | ||
| 3373 | 3379 | ||
| 3374 | const export_off = mem.alignForwardGeneric(u64, lazy_bind_off + lazy_bind_size, @alignOf(u64)); | 3380 | const export_off = lazy_bind_off + lazy_bind_size_aligned; |
| 3375 | const export_size = trie.size; | 3381 | const export_size = trie.size; |
| 3376 | log.debug("writing export trie from 0x{x} to 0x{x}", .{ export_off, export_off + export_size }); | 3382 | const export_size_aligned = mem.alignForwardGeneric(u64, export_size, @alignOf(u64)); |
| 3383 | log.debug("writing export trie from 0x{x} to 0x{x}", .{ export_off, export_off + export_size_aligned }); | ||
| 3377 | 3384 | ||
| 3378 | const needed_size = export_off + export_size - rebase_off; | 3385 | const needed_size = math.cast(usize, export_off + export_size_aligned - rebase_off) orelse |
| 3386 | return error.Overflow; | ||
| 3379 | link_seg.filesize = needed_size; | 3387 | link_seg.filesize = needed_size; |
| 3388 | assert(mem.isAlignedGeneric(u64, link_seg.fileoff + link_seg.filesize, @alignOf(u64))); | ||
| 3380 | 3389 | ||
| 3381 | var buffer = try gpa.alloc(u8, math.cast(usize, needed_size) orelse return error.Overflow); | 3390 | var buffer = try gpa.alloc(u8, needed_size); |
| 3382 | defer gpa.free(buffer); | 3391 | defer gpa.free(buffer); |
| 3383 | mem.set(u8, buffer, 0); | 3392 | mem.set(u8, buffer, 0); |
| 3384 | 3393 | ||
| ... | @@ -3407,13 +3416,13 @@ fn writeDyldInfoData(self: *MachO) !void { | ... | @@ -3407,13 +3416,13 @@ fn writeDyldInfoData(self: *MachO) !void { |
| 3407 | try self.populateLazyBindOffsetsInStubHelper(buffer[start..end]); | 3416 | try self.populateLazyBindOffsetsInStubHelper(buffer[start..end]); |
| 3408 | 3417 | ||
| 3409 | self.dyld_info_cmd.rebase_off = @intCast(u32, rebase_off); | 3418 | self.dyld_info_cmd.rebase_off = @intCast(u32, rebase_off); |
| 3410 | self.dyld_info_cmd.rebase_size = @intCast(u32, rebase_size); | 3419 | self.dyld_info_cmd.rebase_size = @intCast(u32, rebase_size_aligned); |
| 3411 | self.dyld_info_cmd.bind_off = @intCast(u32, bind_off); | 3420 | self.dyld_info_cmd.bind_off = @intCast(u32, bind_off); |
| 3412 | self.dyld_info_cmd.bind_size = @intCast(u32, bind_size); | 3421 | self.dyld_info_cmd.bind_size = @intCast(u32, bind_size_aligned); |
| 3413 | self.dyld_info_cmd.lazy_bind_off = @intCast(u32, lazy_bind_off); | 3422 | self.dyld_info_cmd.lazy_bind_off = @intCast(u32, lazy_bind_off); |
| 3414 | self.dyld_info_cmd.lazy_bind_size = @intCast(u32, lazy_bind_size); | 3423 | self.dyld_info_cmd.lazy_bind_size = @intCast(u32, lazy_bind_size_aligned); |
| 3415 | self.dyld_info_cmd.export_off = @intCast(u32, export_off); | 3424 | self.dyld_info_cmd.export_off = @intCast(u32, export_off); |
| 3416 | self.dyld_info_cmd.export_size = @intCast(u32, export_size); | 3425 | self.dyld_info_cmd.export_size = @intCast(u32, export_size_aligned); |
| 3417 | } | 3426 | } |
| 3418 | 3427 | ||
| 3419 | fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { | 3428 | fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { |
| ... | @@ -3569,13 +3578,11 @@ fn writeSymtab(self: *MachO) !SymtabCtx { | ... | @@ -3569,13 +3578,11 @@ fn writeSymtab(self: *MachO) !SymtabCtx { |
| 3569 | const nsyms = nlocals + nexports + nimports; | 3578 | const nsyms = nlocals + nexports + nimports; |
| 3570 | 3579 | ||
| 3571 | const seg = self.getLinkeditSegmentPtr(); | 3580 | const seg = self.getLinkeditSegmentPtr(); |
| 3572 | const offset = mem.alignForwardGeneric( | 3581 | const offset = seg.fileoff + seg.filesize; |
| 3573 | u64, | 3582 | assert(mem.isAlignedGeneric(u64, offset, @alignOf(u64))); |
| 3574 | seg.fileoff + seg.filesize, | ||
| 3575 | @alignOf(macho.nlist_64), | ||
| 3576 | ); | ||
| 3577 | const needed_size = nsyms * @sizeOf(macho.nlist_64); | 3583 | const needed_size = nsyms * @sizeOf(macho.nlist_64); |
| 3578 | seg.filesize = offset + needed_size - seg.fileoff; | 3584 | seg.filesize = offset + needed_size - seg.fileoff; |
| 3585 | assert(mem.isAlignedGeneric(u64, seg.fileoff + seg.filesize, @alignOf(u64))); | ||
| 3579 | 3586 | ||
| 3580 | var buffer = std.ArrayList(u8).init(gpa); | 3587 | var buffer = std.ArrayList(u8).init(gpa); |
| 3581 | defer buffer.deinit(); | 3588 | defer buffer.deinit(); |
| ... | @@ -3599,17 +3606,25 @@ fn writeSymtab(self: *MachO) !SymtabCtx { | ... | @@ -3599,17 +3606,25 @@ fn writeSymtab(self: *MachO) !SymtabCtx { |
| 3599 | } | 3606 | } |
| 3600 | 3607 | ||
| 3601 | fn writeStrtab(self: *MachO) !void { | 3608 | fn writeStrtab(self: *MachO) !void { |
| 3609 | const gpa = self.base.allocator; | ||
| 3602 | const seg = self.getLinkeditSegmentPtr(); | 3610 | const seg = self.getLinkeditSegmentPtr(); |
| 3603 | const offset = mem.alignForwardGeneric(u64, seg.fileoff + seg.filesize, @alignOf(u64)); | 3611 | const offset = seg.fileoff + seg.filesize; |
| 3612 | assert(mem.isAlignedGeneric(u64, offset, @alignOf(u64))); | ||
| 3604 | const needed_size = self.strtab.buffer.items.len; | 3613 | const needed_size = self.strtab.buffer.items.len; |
| 3605 | seg.filesize = offset + needed_size - seg.fileoff; | 3614 | const needed_size_aligned = mem.alignForwardGeneric(u64, needed_size, @alignOf(u64)); |
| 3615 | seg.filesize = offset + needed_size_aligned - seg.fileoff; | ||
| 3606 | 3616 | ||
| 3607 | log.debug("writing string table from 0x{x} to 0x{x}", .{ offset, offset + needed_size }); | 3617 | log.debug("writing string table from 0x{x} to 0x{x}", .{ offset, offset + needed_size_aligned }); |
| 3608 | 3618 | ||
| 3609 | try self.base.file.?.pwriteAll(self.strtab.buffer.items, offset); | 3619 | const buffer = try gpa.alloc(u8, math.cast(usize, needed_size_aligned) orelse return error.Overflow); |
| 3620 | defer gpa.free(buffer); | ||
| 3621 | mem.set(u8, buffer, 0); | ||
| 3622 | mem.copy(u8, buffer, self.strtab.buffer.items); | ||
| 3623 | |||
| 3624 | try self.base.file.?.pwriteAll(buffer, offset); | ||
| 3610 | 3625 | ||
| 3611 | self.symtab_cmd.stroff = @intCast(u32, offset); | 3626 | self.symtab_cmd.stroff = @intCast(u32, offset); |
| 3612 | self.symtab_cmd.strsize = @intCast(u32, needed_size); | 3627 | self.symtab_cmd.strsize = @intCast(u32, needed_size_aligned); |
| 3613 | } | 3628 | } |
| 3614 | 3629 | ||
| 3615 | const SymtabCtx = struct { | 3630 | const SymtabCtx = struct { |
| ... | @@ -3628,15 +3643,17 @@ fn writeDysymtab(self: *MachO, ctx: SymtabCtx) !void { | ... | @@ -3628,15 +3643,17 @@ fn writeDysymtab(self: *MachO, ctx: SymtabCtx) !void { |
| 3628 | const iundefsym = iextdefsym + ctx.nextdefsym; | 3643 | const iundefsym = iextdefsym + ctx.nextdefsym; |
| 3629 | 3644 | ||
| 3630 | const seg = self.getLinkeditSegmentPtr(); | 3645 | const seg = self.getLinkeditSegmentPtr(); |
| 3631 | const offset = mem.alignForwardGeneric(u64, seg.fileoff + seg.filesize, @alignOf(u64)); | 3646 | const offset = seg.fileoff + seg.filesize; |
| 3647 | assert(mem.isAlignedGeneric(u64, offset, @alignOf(u64))); | ||
| 3632 | const needed_size = nindirectsyms * @sizeOf(u32); | 3648 | const needed_size = nindirectsyms * @sizeOf(u32); |
| 3633 | seg.filesize = offset + needed_size - seg.fileoff; | 3649 | const needed_size_aligned = mem.alignForwardGeneric(u64, needed_size, @alignOf(u64)); |
| 3650 | seg.filesize = offset + needed_size_aligned - seg.fileoff; | ||
| 3634 | 3651 | ||
| 3635 | log.debug("writing indirect symbol table from 0x{x} to 0x{x}", .{ offset, offset + needed_size }); | 3652 | log.debug("writing indirect symbol table from 0x{x} to 0x{x}", .{ offset, offset + needed_size_aligned }); |
| 3636 | 3653 | ||
| 3637 | var buf = std.ArrayList(u8).init(gpa); | 3654 | var buf = std.ArrayList(u8).init(gpa); |
| 3638 | defer buf.deinit(); | 3655 | defer buf.deinit(); |
| 3639 | try buf.ensureTotalCapacity(needed_size); | 3656 | try buf.ensureTotalCapacity(math.cast(usize, needed_size_aligned) orelse return error.Overflow); |
| 3640 | const writer = buf.writer(); | 3657 | const writer = buf.writer(); |
| 3641 | 3658 | ||
| 3642 | if (self.stubs_section_index) |sect_id| { | 3659 | if (self.stubs_section_index) |sect_id| { |
| ... | @@ -3675,7 +3692,12 @@ fn writeDysymtab(self: *MachO, ctx: SymtabCtx) !void { | ... | @@ -3675,7 +3692,12 @@ fn writeDysymtab(self: *MachO, ctx: SymtabCtx) !void { |
| 3675 | } | 3692 | } |
| 3676 | } | 3693 | } |
| 3677 | 3694 | ||
| 3678 | assert(buf.items.len == needed_size); | 3695 | const padding = math.cast(usize, needed_size_aligned - needed_size) orelse return error.Overflow; |
| 3696 | if (padding > 0) { | ||
| 3697 | buf.appendNTimesAssumeCapacity(0, padding); | ||
| 3698 | } | ||
| 3699 | |||
| 3700 | assert(buf.items.len == needed_size_aligned); | ||
| 3679 | try self.base.file.?.pwriteAll(buf.items, offset); | 3701 | try self.base.file.?.pwriteAll(buf.items, offset); |
| 3680 | 3702 | ||
| 3681 | self.dysymtab_cmd.nlocalsym = ctx.nlocalsym; | 3703 | self.dysymtab_cmd.nlocalsym = ctx.nlocalsym; |
src/link/MachO/zld.zig+75-39| ... | @@ -2178,25 +2178,34 @@ pub const Zld = struct { | ... | @@ -2178,25 +2178,34 @@ pub const Zld = struct { |
| 2178 | try self.collectExportData(&trie); | 2178 | try self.collectExportData(&trie); |
| 2179 | 2179 | ||
| 2180 | const link_seg = self.getLinkeditSegmentPtr(); | 2180 | const link_seg = self.getLinkeditSegmentPtr(); |
| 2181 | const rebase_off = mem.alignForwardGeneric(u64, link_seg.fileoff, @alignOf(u64)); | 2181 | assert(mem.isAlignedGeneric(u64, link_seg.fileoff, @alignOf(u64))); |
| 2182 | assert(rebase_off == link_seg.fileoff); | 2182 | const rebase_off = link_seg.fileoff; |
| 2183 | const rebase_size = try bind.rebaseInfoSize(rebase_pointers.items); | 2183 | const rebase_size = try bind.rebaseInfoSize(rebase_pointers.items); |
| 2184 | log.debug("writing rebase info from 0x{x} to 0x{x}", .{ rebase_off, rebase_off + rebase_size }); | 2184 | const rebase_size_aligned = mem.alignForwardGeneric(u64, rebase_size, @alignOf(u64)); |
| 2185 | log.debug("writing rebase info from 0x{x} to 0x{x}", .{ rebase_off, rebase_off + rebase_size_aligned }); | ||
| 2185 | 2186 | ||
| 2186 | const bind_off = mem.alignForwardGeneric(u64, rebase_off + rebase_size, @alignOf(u64)); | 2187 | const bind_off = rebase_off + rebase_size_aligned; |
| 2187 | const bind_size = try bind.bindInfoSize(bind_pointers.items); | 2188 | const bind_size = try bind.bindInfoSize(bind_pointers.items); |
| 2188 | log.debug("writing bind info from 0x{x} to 0x{x}", .{ bind_off, bind_off + bind_size }); | 2189 | const bind_size_aligned = mem.alignForwardGeneric(u64, bind_size, @alignOf(u64)); |
| 2190 | log.debug("writing bind info from 0x{x} to 0x{x}", .{ bind_off, bind_off + bind_size_aligned }); | ||
| 2189 | 2191 | ||
| 2190 | const lazy_bind_off = mem.alignForwardGeneric(u64, bind_off + bind_size, @alignOf(u64)); | 2192 | const lazy_bind_off = bind_off + bind_size_aligned; |
| 2191 | const lazy_bind_size = try bind.lazyBindInfoSize(lazy_bind_pointers.items); | 2193 | const lazy_bind_size = try bind.lazyBindInfoSize(lazy_bind_pointers.items); |
| 2192 | log.debug("writing lazy bind info from 0x{x} to 0x{x}", .{ lazy_bind_off, lazy_bind_off + lazy_bind_size }); | 2194 | const lazy_bind_size_aligned = mem.alignForwardGeneric(u64, lazy_bind_size, @alignOf(u64)); |
| 2195 | log.debug("writing lazy bind info from 0x{x} to 0x{x}", .{ | ||
| 2196 | lazy_bind_off, | ||
| 2197 | lazy_bind_off + lazy_bind_size_aligned, | ||
| 2198 | }); | ||
| 2193 | 2199 | ||
| 2194 | const export_off = mem.alignForwardGeneric(u64, lazy_bind_off + lazy_bind_size, @alignOf(u64)); | 2200 | const export_off = lazy_bind_off + lazy_bind_size_aligned; |
| 2195 | const export_size = trie.size; | 2201 | const export_size = trie.size; |
| 2196 | log.debug("writing export trie from 0x{x} to 0x{x}", .{ export_off, export_off + export_size }); | 2202 | const export_size_aligned = mem.alignForwardGeneric(u64, export_size, @alignOf(u64)); |
| 2203 | log.debug("writing export trie from 0x{x} to 0x{x}", .{ export_off, export_off + export_size_aligned }); | ||
| 2197 | 2204 | ||
| 2198 | const needed_size = math.cast(usize, export_off + export_size - rebase_off) orelse return error.Overflow; | 2205 | const needed_size = math.cast(usize, export_off + export_size_aligned - rebase_off) orelse |
| 2206 | return error.Overflow; | ||
| 2199 | link_seg.filesize = needed_size; | 2207 | link_seg.filesize = needed_size; |
| 2208 | assert(mem.isAlignedGeneric(u64, link_seg.fileoff + link_seg.filesize, @alignOf(u64))); | ||
| 2200 | 2209 | ||
| 2201 | var buffer = try gpa.alloc(u8, needed_size); | 2210 | var buffer = try gpa.alloc(u8, needed_size); |
| 2202 | defer gpa.free(buffer); | 2211 | defer gpa.free(buffer); |
| ... | @@ -2228,13 +2237,13 @@ pub const Zld = struct { | ... | @@ -2228,13 +2237,13 @@ pub const Zld = struct { |
| 2228 | try self.populateLazyBindOffsetsInStubHelper(buffer[offset..][0..size]); | 2237 | try self.populateLazyBindOffsetsInStubHelper(buffer[offset..][0..size]); |
| 2229 | 2238 | ||
| 2230 | self.dyld_info_cmd.rebase_off = @intCast(u32, rebase_off); | 2239 | self.dyld_info_cmd.rebase_off = @intCast(u32, rebase_off); |
| 2231 | self.dyld_info_cmd.rebase_size = @intCast(u32, rebase_size); | 2240 | self.dyld_info_cmd.rebase_size = @intCast(u32, rebase_size_aligned); |
| 2232 | self.dyld_info_cmd.bind_off = @intCast(u32, bind_off); | 2241 | self.dyld_info_cmd.bind_off = @intCast(u32, bind_off); |
| 2233 | self.dyld_info_cmd.bind_size = @intCast(u32, bind_size); | 2242 | self.dyld_info_cmd.bind_size = @intCast(u32, bind_size_aligned); |
| 2234 | self.dyld_info_cmd.lazy_bind_off = @intCast(u32, lazy_bind_off); | 2243 | self.dyld_info_cmd.lazy_bind_off = @intCast(u32, lazy_bind_off); |
| 2235 | self.dyld_info_cmd.lazy_bind_size = @intCast(u32, lazy_bind_size); | 2244 | self.dyld_info_cmd.lazy_bind_size = @intCast(u32, lazy_bind_size_aligned); |
| 2236 | self.dyld_info_cmd.export_off = @intCast(u32, export_off); | 2245 | self.dyld_info_cmd.export_off = @intCast(u32, export_off); |
| 2237 | self.dyld_info_cmd.export_size = @intCast(u32, export_size); | 2246 | self.dyld_info_cmd.export_size = @intCast(u32, export_size_aligned); |
| 2238 | } | 2247 | } |
| 2239 | 2248 | ||
| 2240 | fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void { | 2249 | fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void { |
| ... | @@ -2403,16 +2412,23 @@ pub const Zld = struct { | ... | @@ -2403,16 +2412,23 @@ pub const Zld = struct { |
| 2403 | } | 2412 | } |
| 2404 | 2413 | ||
| 2405 | const link_seg = self.getLinkeditSegmentPtr(); | 2414 | const link_seg = self.getLinkeditSegmentPtr(); |
| 2406 | const offset = mem.alignForwardGeneric(u64, link_seg.fileoff + link_seg.filesize, @alignOf(u64)); | 2415 | const offset = link_seg.fileoff + link_seg.filesize; |
| 2416 | assert(mem.isAlignedGeneric(u64, offset, @alignOf(u64))); | ||
| 2407 | const needed_size = buffer.items.len; | 2417 | const needed_size = buffer.items.len; |
| 2408 | link_seg.filesize = offset + needed_size - link_seg.fileoff; | 2418 | const needed_size_aligned = mem.alignForwardGeneric(u64, needed_size, @alignOf(u64)); |
| 2419 | const padding = math.cast(usize, needed_size_aligned - needed_size) orelse return error.Overflow; | ||
| 2420 | if (padding > 0) { | ||
| 2421 | try buffer.ensureUnusedCapacity(padding); | ||
| 2422 | buffer.appendNTimesAssumeCapacity(0, padding); | ||
| 2423 | } | ||
| 2424 | link_seg.filesize = offset + needed_size_aligned - link_seg.fileoff; | ||
| 2409 | 2425 | ||
| 2410 | log.debug("writing function starts info from 0x{x} to 0x{x}", .{ offset, offset + needed_size }); | 2426 | log.debug("writing function starts info from 0x{x} to 0x{x}", .{ offset, offset + needed_size_aligned }); |
| 2411 | 2427 | ||
| 2412 | try self.file.pwriteAll(buffer.items, offset); | 2428 | try self.file.pwriteAll(buffer.items, offset); |
| 2413 | 2429 | ||
| 2414 | self.function_starts_cmd.dataoff = @intCast(u32, offset); | 2430 | self.function_starts_cmd.dataoff = @intCast(u32, offset); |
| 2415 | self.function_starts_cmd.datasize = @intCast(u32, needed_size); | 2431 | self.function_starts_cmd.datasize = @intCast(u32, needed_size_aligned); |
| 2416 | } | 2432 | } |
| 2417 | 2433 | ||
| 2418 | fn filterDataInCode( | 2434 | fn filterDataInCode( |
| ... | @@ -2477,16 +2493,23 @@ pub const Zld = struct { | ... | @@ -2477,16 +2493,23 @@ pub const Zld = struct { |
| 2477 | } | 2493 | } |
| 2478 | 2494 | ||
| 2479 | const seg = self.getLinkeditSegmentPtr(); | 2495 | const seg = self.getLinkeditSegmentPtr(); |
| 2480 | const offset = mem.alignForwardGeneric(u64, seg.fileoff + seg.filesize, @alignOf(u64)); | 2496 | const offset = seg.fileoff + seg.filesize; |
| 2497 | assert(mem.isAlignedGeneric(u64, offset, @alignOf(u64))); | ||
| 2481 | const needed_size = out_dice.items.len * @sizeOf(macho.data_in_code_entry); | 2498 | const needed_size = out_dice.items.len * @sizeOf(macho.data_in_code_entry); |
| 2482 | seg.filesize = offset + needed_size - seg.fileoff; | 2499 | const needed_size_aligned = mem.alignForwardGeneric(u64, needed_size, @alignOf(u64)); |
| 2500 | seg.filesize = offset + needed_size_aligned - seg.fileoff; | ||
| 2501 | |||
| 2502 | const buffer = try self.gpa.alloc(u8, math.cast(usize, needed_size_aligned) orelse return error.Overflow); | ||
| 2503 | defer self.gpa.free(buffer); | ||
| 2504 | mem.set(u8, buffer, 0); | ||
| 2505 | mem.copy(u8, buffer, mem.sliceAsBytes(out_dice.items)); | ||
| 2483 | 2506 | ||
| 2484 | log.debug("writing data-in-code from 0x{x} to 0x{x}", .{ offset, offset + needed_size }); | 2507 | log.debug("writing data-in-code from 0x{x} to 0x{x}", .{ offset, offset + needed_size_aligned }); |
| 2485 | 2508 | ||
| 2486 | try self.file.pwriteAll(mem.sliceAsBytes(out_dice.items), offset); | 2509 | try self.file.pwriteAll(buffer, offset); |
| 2487 | 2510 | ||
| 2488 | self.data_in_code_cmd.dataoff = @intCast(u32, offset); | 2511 | self.data_in_code_cmd.dataoff = @intCast(u32, offset); |
| 2489 | self.data_in_code_cmd.datasize = @intCast(u32, needed_size); | 2512 | self.data_in_code_cmd.datasize = @intCast(u32, needed_size_aligned); |
| 2490 | } | 2513 | } |
| 2491 | 2514 | ||
| 2492 | fn writeSymtabs(self: *Zld) !void { | 2515 | fn writeSymtabs(self: *Zld) !void { |
| ... | @@ -2561,13 +2584,11 @@ pub const Zld = struct { | ... | @@ -2561,13 +2584,11 @@ pub const Zld = struct { |
| 2561 | const nsyms = nlocals + nexports + nimports; | 2584 | const nsyms = nlocals + nexports + nimports; |
| 2562 | 2585 | ||
| 2563 | const seg = self.getLinkeditSegmentPtr(); | 2586 | const seg = self.getLinkeditSegmentPtr(); |
| 2564 | const offset = mem.alignForwardGeneric( | 2587 | const offset = seg.fileoff + seg.filesize; |
| 2565 | u64, | 2588 | assert(mem.isAlignedGeneric(u64, offset, @alignOf(u64))); |
| 2566 | seg.fileoff + seg.filesize, | ||
| 2567 | @alignOf(macho.nlist_64), | ||
| 2568 | ); | ||
| 2569 | const needed_size = nsyms * @sizeOf(macho.nlist_64); | 2589 | const needed_size = nsyms * @sizeOf(macho.nlist_64); |
| 2570 | seg.filesize = offset + needed_size - seg.fileoff; | 2590 | seg.filesize = offset + needed_size - seg.fileoff; |
| 2591 | assert(mem.isAlignedGeneric(u64, seg.fileoff + seg.filesize, @alignOf(u64))); | ||
| 2571 | 2592 | ||
| 2572 | var buffer = std.ArrayList(u8).init(gpa); | 2593 | var buffer = std.ArrayList(u8).init(gpa); |
| 2573 | defer buffer.deinit(); | 2594 | defer buffer.deinit(); |
| ... | @@ -2592,16 +2613,23 @@ pub const Zld = struct { | ... | @@ -2592,16 +2613,23 @@ pub const Zld = struct { |
| 2592 | 2613 | ||
| 2593 | fn writeStrtab(self: *Zld) !void { | 2614 | fn writeStrtab(self: *Zld) !void { |
| 2594 | const seg = self.getLinkeditSegmentPtr(); | 2615 | const seg = self.getLinkeditSegmentPtr(); |
| 2595 | const offset = mem.alignForwardGeneric(u64, seg.fileoff + seg.filesize, @alignOf(u64)); | 2616 | const offset = seg.fileoff + seg.filesize; |
| 2617 | assert(mem.isAlignedGeneric(u64, offset, @alignOf(u64))); | ||
| 2596 | const needed_size = self.strtab.buffer.items.len; | 2618 | const needed_size = self.strtab.buffer.items.len; |
| 2597 | seg.filesize = offset + needed_size - seg.fileoff; | 2619 | const needed_size_aligned = mem.alignForwardGeneric(u64, needed_size, @alignOf(u64)); |
| 2620 | seg.filesize = offset + needed_size_aligned - seg.fileoff; | ||
| 2621 | |||
| 2622 | log.debug("writing string table from 0x{x} to 0x{x}", .{ offset, offset + needed_size_aligned }); | ||
| 2598 | 2623 | ||
| 2599 | log.debug("writing string table from 0x{x} to 0x{x}", .{ offset, offset + needed_size }); | 2624 | const buffer = try self.gpa.alloc(u8, math.cast(usize, needed_size_aligned) orelse return error.Overflow); |
| 2625 | defer self.gpa.free(buffer); | ||
| 2626 | mem.set(u8, buffer, 0); | ||
| 2627 | mem.copy(u8, buffer, self.strtab.buffer.items); | ||
| 2600 | 2628 | ||
| 2601 | try self.file.pwriteAll(self.strtab.buffer.items, offset); | 2629 | try self.file.pwriteAll(buffer, offset); |
| 2602 | 2630 | ||
| 2603 | self.symtab_cmd.stroff = @intCast(u32, offset); | 2631 | self.symtab_cmd.stroff = @intCast(u32, offset); |
| 2604 | self.symtab_cmd.strsize = @intCast(u32, needed_size); | 2632 | self.symtab_cmd.strsize = @intCast(u32, needed_size_aligned); |
| 2605 | } | 2633 | } |
| 2606 | 2634 | ||
| 2607 | const SymtabCtx = struct { | 2635 | const SymtabCtx = struct { |
| ... | @@ -2620,15 +2648,17 @@ pub const Zld = struct { | ... | @@ -2620,15 +2648,17 @@ pub const Zld = struct { |
| 2620 | const iundefsym = iextdefsym + ctx.nextdefsym; | 2648 | const iundefsym = iextdefsym + ctx.nextdefsym; |
| 2621 | 2649 | ||
| 2622 | const seg = self.getLinkeditSegmentPtr(); | 2650 | const seg = self.getLinkeditSegmentPtr(); |
| 2623 | const offset = mem.alignForwardGeneric(u64, seg.fileoff + seg.filesize, @alignOf(u64)); | 2651 | const offset = seg.fileoff + seg.filesize; |
| 2652 | assert(mem.isAlignedGeneric(u64, offset, @alignOf(u64))); | ||
| 2624 | const needed_size = nindirectsyms * @sizeOf(u32); | 2653 | const needed_size = nindirectsyms * @sizeOf(u32); |
| 2625 | seg.filesize = offset + needed_size - seg.fileoff; | 2654 | const needed_size_aligned = mem.alignForwardGeneric(u64, needed_size, @alignOf(u64)); |
| 2655 | seg.filesize = offset + needed_size_aligned - seg.fileoff; | ||
| 2626 | 2656 | ||
| 2627 | log.debug("writing indirect symbol table from 0x{x} to 0x{x}", .{ offset, offset + needed_size }); | 2657 | log.debug("writing indirect symbol table from 0x{x} to 0x{x}", .{ offset, offset + needed_size_aligned }); |
| 2628 | 2658 | ||
| 2629 | var buf = std.ArrayList(u8).init(gpa); | 2659 | var buf = std.ArrayList(u8).init(gpa); |
| 2630 | defer buf.deinit(); | 2660 | defer buf.deinit(); |
| 2631 | try buf.ensureTotalCapacity(needed_size); | 2661 | try buf.ensureTotalCapacityPrecise(math.cast(usize, needed_size_aligned) orelse return error.Overflow); |
| 2632 | const writer = buf.writer(); | 2662 | const writer = buf.writer(); |
| 2633 | 2663 | ||
| 2634 | if (self.getSectionByName("__TEXT", "__stubs")) |sect_id| { | 2664 | if (self.getSectionByName("__TEXT", "__stubs")) |sect_id| { |
| ... | @@ -2664,7 +2694,12 @@ pub const Zld = struct { | ... | @@ -2664,7 +2694,12 @@ pub const Zld = struct { |
| 2664 | } | 2694 | } |
| 2665 | } | 2695 | } |
| 2666 | 2696 | ||
| 2667 | assert(buf.items.len == needed_size); | 2697 | const padding = math.cast(usize, needed_size_aligned - needed_size) orelse return error.Overflow; |
| 2698 | if (padding > 0) { | ||
| 2699 | buf.appendNTimesAssumeCapacity(0, padding); | ||
| 2700 | } | ||
| 2701 | |||
| 2702 | assert(buf.items.len == needed_size_aligned); | ||
| 2668 | try self.file.pwriteAll(buf.items, offset); | 2703 | try self.file.pwriteAll(buf.items, offset); |
| 2669 | 2704 | ||
| 2670 | self.dysymtab_cmd.nlocalsym = ctx.nlocalsym; | 2705 | self.dysymtab_cmd.nlocalsym = ctx.nlocalsym; |
| ... | @@ -2692,7 +2727,8 @@ pub const Zld = struct { | ... | @@ -2692,7 +2727,8 @@ pub const Zld = struct { |
| 2692 | conformUuid(&self.uuid_cmd.uuid); | 2727 | conformUuid(&self.uuid_cmd.uuid); |
| 2693 | }, | 2728 | }, |
| 2694 | else => { | 2729 | else => { |
| 2695 | const max_file_end = self.symtab_cmd.stroff + self.symtab_cmd.strsize; | 2730 | // We set the max file size to the actual strtab buffer length to exclude any strtab padding. |
| 2731 | const max_file_end = @intCast(u32, self.symtab_cmd.stroff + self.strtab.buffer.items.len); | ||
| 2696 | 2732 | ||
| 2697 | const FileSubsection = struct { | 2733 | const FileSubsection = struct { |
| 2698 | start: u32, | 2734 | start: u32, |
test/link/macho/strict_validation/build.zig+34-15| ... | @@ -32,13 +32,23 @@ pub fn build(b: *Builder) void { | ... | @@ -32,13 +32,23 @@ pub fn build(b: *Builder) void { |
| 32 | check_exe.checkNext("exportoff {exportoff}"); | 32 | check_exe.checkNext("exportoff {exportoff}"); |
| 33 | check_exe.checkNext("exportsize {exportsize}"); | 33 | check_exe.checkNext("exportsize {exportsize}"); |
| 34 | 34 | ||
| 35 | check_exe.checkStart("cmd FUNCTION_STARTS"); | ||
| 36 | check_exe.checkNext("dataoff {fstartoff}"); | ||
| 37 | check_exe.checkNext("datasize {fstartsize}"); | ||
| 38 | |||
| 39 | check_exe.checkStart("cmd DATA_IN_CODE"); | ||
| 40 | check_exe.checkNext("dataoff {diceoff}"); | ||
| 41 | check_exe.checkNext("datasize {dicesize}"); | ||
| 42 | |||
| 35 | check_exe.checkStart("cmd SYMTAB"); | 43 | check_exe.checkStart("cmd SYMTAB"); |
| 36 | check_exe.checkNext("symoff {symoff}"); | 44 | check_exe.checkNext("symoff {symoff}"); |
| 45 | check_exe.checkNext("nsyms {symnsyms}"); | ||
| 37 | check_exe.checkNext("stroff {stroff}"); | 46 | check_exe.checkNext("stroff {stroff}"); |
| 38 | check_exe.checkNext("strsize {strsize}"); | 47 | check_exe.checkNext("strsize {strsize}"); |
| 39 | 48 | ||
| 40 | check_exe.checkStart("cmd DYSYMTAB"); | 49 | check_exe.checkStart("cmd DYSYMTAB"); |
| 41 | check_exe.checkNext("indirectsymoff {dysymoff}"); | 50 | check_exe.checkNext("indirectsymoff {dysymoff}"); |
| 51 | check_exe.checkNext("nindirectsyms {dysymnsyms}"); | ||
| 42 | 52 | ||
| 43 | switch (builtin.cpu.arch) { | 53 | switch (builtin.cpu.arch) { |
| 44 | .aarch64 => { | 54 | .aarch64 => { |
| ... | @@ -50,42 +60,51 @@ pub fn build(b: *Builder) void { | ... | @@ -50,42 +60,51 @@ pub fn build(b: *Builder) void { |
| 50 | else => unreachable, | 60 | else => unreachable, |
| 51 | } | 61 | } |
| 52 | 62 | ||
| 53 | // Next check: DYLD_INFO_ONLY subsections are in order: rebase < bind < lazy < export | 63 | // DYLD_INFO_ONLY subsections are in order: rebase < bind < lazy < export, |
| 54 | check_exe.checkComputeCompare("rebaseoff ", .{ .op = .lt, .value = .{ .variable = "bindoff" } }); | 64 | // and there are no gaps between them |
| 55 | check_exe.checkComputeCompare("bindoff", .{ .op = .lt, .value = .{ .variable = "lazybindoff" } }); | 65 | check_exe.checkComputeCompare("rebaseoff rebasesize +", .{ .op = .eq, .value = .{ .variable = "bindoff" } }); |
| 56 | check_exe.checkComputeCompare("lazybindoff", .{ .op = .lt, .value = .{ .variable = "exportoff" } }); | 66 | check_exe.checkComputeCompare("bindoff bindsize +", .{ .op = .eq, .value = .{ .variable = "lazybindoff" } }); |
| 67 | check_exe.checkComputeCompare("lazybindoff lazybindsize +", .{ .op = .eq, .value = .{ .variable = "exportoff" } }); | ||
| 68 | |||
| 69 | // FUNCTION_STARTS directly follows DYLD_INFO_ONLY (no gap) | ||
| 70 | check_exe.checkComputeCompare("exportoff exportsize +", .{ .op = .eq, .value = .{ .variable = "fstartoff" } }); | ||
| 71 | |||
| 72 | // DATA_IN_CODE directly follows FUNCTION_STARTS (no gap) | ||
| 73 | check_exe.checkComputeCompare("fstartoff fstartsize +", .{ .op = .eq, .value = .{ .variable = "diceoff" } }); | ||
| 74 | |||
| 75 | // SYMTAB directly follows DATA_IN_CODE (no gap) | ||
| 76 | check_exe.checkComputeCompare("diceoff dicesize +", .{ .op = .eq, .value = .{ .variable = "symoff" } }); | ||
| 57 | 77 | ||
| 58 | // Next check: DYLD_INFO_ONLY subsections do not overlap | 78 | // DYSYMTAB directly follows SYMTAB (no gap) |
| 59 | check_exe.checkComputeCompare("rebaseoff rebasesize +", .{ .op = .lte, .value = .{ .variable = "bindoff" } }); | 79 | check_exe.checkComputeCompare("symnsyms 16 symoff * +", .{ .op = .eq, .value = .{ .variable = "dysymoff" } }); |
| 60 | check_exe.checkComputeCompare("bindoff bindsize +", .{ .op = .lte, .value = .{ .variable = "lazybindoff" } }); | ||
| 61 | check_exe.checkComputeCompare("lazybindoff lazybindsize +", .{ .op = .lte, .value = .{ .variable = "exportoff" } }); | ||
| 62 | 80 | ||
| 63 | // Next check: we maintain order: symtab < dysymtab < strtab | 81 | // STRTAB follows DYSYMTAB with possible gap |
| 64 | check_exe.checkComputeCompare("symoff", .{ .op = .lt, .value = .{ .variable = "dysymoff" } }); | 82 | check_exe.checkComputeCompare("dysymnsyms 4 dysymoff * +", .{ .op = .lte, .value = .{ .variable = "stroff" } }); |
| 65 | check_exe.checkComputeCompare("dysymoff", .{ .op = .lt, .value = .{ .variable = "stroff" } }); | ||
| 66 | 83 | ||
| 67 | // Next check: all LINKEDIT sections apart from CODE_SIGNATURE are 8-bytes aligned | 84 | // all LINKEDIT sections apart from CODE_SIGNATURE are 8-bytes aligned |
| 68 | check_exe.checkComputeCompare("rebaseoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); | 85 | check_exe.checkComputeCompare("rebaseoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); |
| 69 | check_exe.checkComputeCompare("bindoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); | 86 | check_exe.checkComputeCompare("bindoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); |
| 70 | check_exe.checkComputeCompare("lazybindoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); | 87 | check_exe.checkComputeCompare("lazybindoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); |
| 71 | check_exe.checkComputeCompare("exportoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); | 88 | check_exe.checkComputeCompare("exportoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); |
| 89 | check_exe.checkComputeCompare("fstartoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); | ||
| 90 | check_exe.checkComputeCompare("diceoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); | ||
| 72 | check_exe.checkComputeCompare("symoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); | 91 | check_exe.checkComputeCompare("symoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); |
| 73 | check_exe.checkComputeCompare("stroff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); | 92 | check_exe.checkComputeCompare("stroff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); |
| 74 | check_exe.checkComputeCompare("dysymoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); | 93 | check_exe.checkComputeCompare("dysymoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); |
| 75 | 94 | ||
| 76 | switch (builtin.cpu.arch) { | 95 | switch (builtin.cpu.arch) { |
| 77 | .aarch64 => { | 96 | .aarch64 => { |
| 78 | // Next check: LINKEDIT segment does not extend beyond, or does not include, CODE_SIGNATURE data | 97 | // LINKEDIT segment does not extend beyond, or does not include, CODE_SIGNATURE data |
| 79 | check_exe.checkComputeCompare("fileoff filesz codesigoff codesigsize + - -", .{ | 98 | check_exe.checkComputeCompare("fileoff filesz codesigoff codesigsize + - -", .{ |
| 80 | .op = .eq, | 99 | .op = .eq, |
| 81 | .value = .{ .literal = 0 }, | 100 | .value = .{ .literal = 0 }, |
| 82 | }); | 101 | }); |
| 83 | 102 | ||
| 84 | // Next check: CODE_SIGNATURE data offset is 16-bytes aligned | 103 | // CODE_SIGNATURE data offset is 16-bytes aligned |
| 85 | check_exe.checkComputeCompare("codesigoff 16 %", .{ .op = .eq, .value = .{ .literal = 0 } }); | 104 | check_exe.checkComputeCompare("codesigoff 16 %", .{ .op = .eq, .value = .{ .literal = 0 } }); |
| 86 | }, | 105 | }, |
| 87 | .x86_64 => { | 106 | .x86_64 => { |
| 88 | // Next check: LINKEDIT segment does not extend beyond, or does not include, strtab data | 107 | // LINKEDIT segment does not extend beyond, or does not include, strtab data |
| 89 | check_exe.checkComputeCompare("fileoff filesz stroff strsize + - -", .{ | 108 | check_exe.checkComputeCompare("fileoff filesz stroff strsize + - -", .{ |
| 90 | .op = .eq, | 109 | .op = .eq, |
| 91 | .value = .{ .literal = 0 }, | 110 | .value = .{ .literal = 0 }, |
test/link/macho/uuid/build.zig+30-8| ... | @@ -5,23 +5,45 @@ const LibExeObjectStep = std.build.LibExeObjStep; | ... | @@ -5,23 +5,45 @@ const LibExeObjectStep = std.build.LibExeObjStep; |
| 5 | pub fn build(b: *Builder) void { | 5 | pub fn build(b: *Builder) void { |
| 6 | const test_step = b.step("test", "Test"); | 6 | const test_step = b.step("test", "Test"); |
| 7 | test_step.dependOn(b.getInstallStep()); | 7 | test_step.dependOn(b.getInstallStep()); |
| 8 | testUuid(b, test_step, .ReleaseSafe, "eb1203019e453d808d4f1e71053af9af"); | 8 | |
| 9 | testUuid(b, test_step, .ReleaseFast, "eb1203019e453d808d4f1e71053af9af"); | 9 | // We force cross-compilation to ensure we always pick a generic CPU with constant set of CPU features. |
| 10 | testUuid(b, test_step, .ReleaseSmall, "eb1203019e453d808d4f1e71053af9af"); | 10 | const aarch64_macos = std.zig.CrossTarget{ |
| 11 | .cpu_arch = .aarch64, | ||
| 12 | .os_tag = .macos, | ||
| 13 | }; | ||
| 14 | |||
| 15 | testUuid(b, test_step, .ReleaseSafe, aarch64_macos, "46b333df88f5314686fc0cba3b939ca8"); | ||
| 16 | testUuid(b, test_step, .ReleaseFast, aarch64_macos, "46b333df88f5314686fc0cba3b939ca8"); | ||
| 17 | testUuid(b, test_step, .ReleaseSmall, aarch64_macos, "46b333df88f5314686fc0cba3b939ca8"); | ||
| 18 | |||
| 19 | const x86_64_macos = std.zig.CrossTarget{ | ||
| 20 | .cpu_arch = .x86_64, | ||
| 21 | .os_tag = .macos, | ||
| 22 | }; | ||
| 23 | |||
| 24 | testUuid(b, test_step, .ReleaseSafe, x86_64_macos, "342ac765194131e1bad5692b9e0e54a4"); | ||
| 25 | testUuid(b, test_step, .ReleaseFast, x86_64_macos, "342ac765194131e1bad5692b9e0e54a4"); | ||
| 26 | testUuid(b, test_step, .ReleaseSmall, x86_64_macos, "f119310e24773ecf8ec42e09d0379dad"); | ||
| 11 | } | 27 | } |
| 12 | 28 | ||
| 13 | fn testUuid(b: *Builder, test_step: *std.build.Step, mode: std.builtin.Mode, comptime exp: []const u8) void { | 29 | fn testUuid( |
| 30 | b: *Builder, | ||
| 31 | test_step: *std.build.Step, | ||
| 32 | mode: std.builtin.Mode, | ||
| 33 | target: std.zig.CrossTarget, | ||
| 34 | comptime exp: []const u8, | ||
| 35 | ) void { | ||
| 14 | // The calculated UUID value is independent of debug info and so it should | 36 | // The calculated UUID value is independent of debug info and so it should |
| 15 | // stay the same across builds. | 37 | // stay the same across builds. |
| 16 | { | 38 | { |
| 17 | const dylib = simpleDylib(b, mode); | 39 | const dylib = simpleDylib(b, mode, target); |
| 18 | const check_dylib = dylib.checkObject(.macho); | 40 | const check_dylib = dylib.checkObject(.macho); |
| 19 | check_dylib.checkStart("cmd UUID"); | 41 | check_dylib.checkStart("cmd UUID"); |
| 20 | check_dylib.checkNext("uuid " ++ exp); | 42 | check_dylib.checkNext("uuid " ++ exp); |
| 21 | test_step.dependOn(&check_dylib.step); | 43 | test_step.dependOn(&check_dylib.step); |
| 22 | } | 44 | } |
| 23 | { | 45 | { |
| 24 | const dylib = simpleDylib(b, mode); | 46 | const dylib = simpleDylib(b, mode, target); |
| 25 | dylib.strip = true; | 47 | dylib.strip = true; |
| 26 | const check_dylib = dylib.checkObject(.macho); | 48 | const check_dylib = dylib.checkObject(.macho); |
| 27 | check_dylib.checkStart("cmd UUID"); | 49 | check_dylib.checkStart("cmd UUID"); |
| ... | @@ -30,10 +52,10 @@ fn testUuid(b: *Builder, test_step: *std.build.Step, mode: std.builtin.Mode, com | ... | @@ -30,10 +52,10 @@ fn testUuid(b: *Builder, test_step: *std.build.Step, mode: std.builtin.Mode, com |
| 30 | } | 52 | } |
| 31 | } | 53 | } |
| 32 | 54 | ||
| 33 | fn simpleDylib(b: *Builder, mode: std.builtin.Mode) *LibExeObjectStep { | 55 | fn simpleDylib(b: *Builder, mode: std.builtin.Mode, target: std.zig.CrossTarget) *LibExeObjectStep { |
| 34 | const dylib = b.addSharedLibrary("test", null, b.version(1, 0, 0)); | 56 | const dylib = b.addSharedLibrary("test", null, b.version(1, 0, 0)); |
| 57 | dylib.setTarget(target); | ||
| 35 | dylib.setBuildMode(mode); | 58 | dylib.setBuildMode(mode); |
| 36 | dylib.setTarget(.{ .cpu_arch = .aarch64, .os_tag = .macos }); | ||
| 37 | dylib.addCSourceFile("test.c", &.{}); | 59 | dylib.addCSourceFile("test.c", &.{}); |
| 38 | dylib.linkLibC(); | 60 | dylib.linkLibC(); |
| 39 | return dylib; | 61 | return dylib; |