diff --git a/lib/std/build/CheckObjectStep.zig b/lib/std/build/CheckObjectStep.zig index 455f53eeb7..4ef350b418 100644 --- a/lib/std/build/CheckObjectStep.zig +++ b/lib/std/build/CheckObjectStep.zig @@ -126,7 +126,7 @@ const Action = struct { /// its reduced, computed value compares using `op` with the expected value, either /// a literal or another extracted variable. fn computeCmp(act: Action, gpa: Allocator, global_vars: anytype) !bool { - var op_stack = std.ArrayList(enum { add, sub, mod }).init(gpa); + var op_stack = std.ArrayList(enum { add, sub, mod, mul }).init(gpa); var values = std.ArrayList(u64).init(gpa); var it = mem.tokenize(u8, act.phrase, " "); @@ -137,6 +137,8 @@ const Action = struct { try op_stack.append(.sub); } else if (mem.eql(u8, next, "%")) { try op_stack.append(.mod); + } else if (mem.eql(u8, next, "*")) { + try op_stack.append(.mul); } else { const val = std.fmt.parseInt(u64, next, 0) catch blk: { break :blk global_vars.get(next) orelse { @@ -167,6 +169,9 @@ const Action = struct { .mod => { reduced %= other; }, + .mul => { + reduced *= other; + }, } op_i += 1; } diff --git a/test/link/macho/strict_validation/build.zig b/test/link/macho/strict_validation/build.zig index d5c00bffee..0ea150252c 100644 --- a/test/link/macho/strict_validation/build.zig +++ b/test/link/macho/strict_validation/build.zig @@ -32,13 +32,23 @@ pub fn build(b: *Builder) void { check_exe.checkNext("exportoff {exportoff}"); check_exe.checkNext("exportsize {exportsize}"); + check_exe.checkStart("cmd FUNCTION_STARTS"); + check_exe.checkNext("dataoff {fstartoff}"); + check_exe.checkNext("datasize {fstartsize}"); + + check_exe.checkStart("cmd DATA_IN_CODE"); + check_exe.checkNext("dataoff {diceoff}"); + check_exe.checkNext("datasize {dicesize}"); + check_exe.checkStart("cmd SYMTAB"); check_exe.checkNext("symoff {symoff}"); + check_exe.checkNext("nsyms {symnsyms}"); check_exe.checkNext("stroff {stroff}"); check_exe.checkNext("strsize {strsize}"); check_exe.checkStart("cmd DYSYMTAB"); check_exe.checkNext("indirectsymoff {dysymoff}"); + check_exe.checkNext("nindirectsyms {dysymnsyms}"); switch (builtin.cpu.arch) { .aarch64 => { @@ -50,42 +60,51 @@ pub fn build(b: *Builder) void { else => unreachable, } - // Next check: DYLD_INFO_ONLY subsections are in order: rebase < bind < lazy < export - check_exe.checkComputeCompare("rebaseoff ", .{ .op = .lt, .value = .{ .variable = "bindoff" } }); - check_exe.checkComputeCompare("bindoff", .{ .op = .lt, .value = .{ .variable = "lazybindoff" } }); - check_exe.checkComputeCompare("lazybindoff", .{ .op = .lt, .value = .{ .variable = "exportoff" } }); + // DYLD_INFO_ONLY subsections are in order: rebase < bind < lazy < export, + // and there are no gaps between them + check_exe.checkComputeCompare("rebaseoff rebasesize +", .{ .op = .eq, .value = .{ .variable = "bindoff" } }); + check_exe.checkComputeCompare("bindoff bindsize +", .{ .op = .eq, .value = .{ .variable = "lazybindoff" } }); + check_exe.checkComputeCompare("lazybindoff lazybindsize +", .{ .op = .eq, .value = .{ .variable = "exportoff" } }); - // Next check: DYLD_INFO_ONLY subsections do not overlap - check_exe.checkComputeCompare("rebaseoff rebasesize +", .{ .op = .lte, .value = .{ .variable = "bindoff" } }); - check_exe.checkComputeCompare("bindoff bindsize +", .{ .op = .lte, .value = .{ .variable = "lazybindoff" } }); - check_exe.checkComputeCompare("lazybindoff lazybindsize +", .{ .op = .lte, .value = .{ .variable = "exportoff" } }); + // FUNCTION_STARTS directly follows DYLD_INFO_ONLY (no gap) + check_exe.checkComputeCompare("exportoff exportsize +", .{ .op = .eq, .value = .{ .variable = "fstartoff" } }); - // Next check: we maintain order: symtab < dysymtab < strtab - check_exe.checkComputeCompare("symoff", .{ .op = .lt, .value = .{ .variable = "dysymoff" } }); - check_exe.checkComputeCompare("dysymoff", .{ .op = .lt, .value = .{ .variable = "stroff" } }); + // DATA_IN_CODE directly follows FUNCTION_STARTS (no gap) + check_exe.checkComputeCompare("fstartoff fstartsize +", .{ .op = .eq, .value = .{ .variable = "diceoff" } }); - // Next check: all LINKEDIT sections apart from CODE_SIGNATURE are 8-bytes aligned + // SYMTAB directly follows DATA_IN_CODE (no gap) + check_exe.checkComputeCompare("diceoff dicesize +", .{ .op = .eq, .value = .{ .variable = "symoff" } }); + + // DYSYMTAB directly follows SYMTAB (no gap) + check_exe.checkComputeCompare("symnsyms 16 symoff * +", .{ .op = .eq, .value = .{ .variable = "dysymoff" } }); + + // STRTAB follows DYSYMTAB with possible gap + check_exe.checkComputeCompare("dysymnsyms 4 dysymoff * +", .{ .op = .lte, .value = .{ .variable = "stroff" } }); + + // all LINKEDIT sections apart from CODE_SIGNATURE are 8-bytes aligned check_exe.checkComputeCompare("rebaseoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); check_exe.checkComputeCompare("bindoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); check_exe.checkComputeCompare("lazybindoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); check_exe.checkComputeCompare("exportoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); + check_exe.checkComputeCompare("fstartoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); + check_exe.checkComputeCompare("diceoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); check_exe.checkComputeCompare("symoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); check_exe.checkComputeCompare("stroff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); check_exe.checkComputeCompare("dysymoff 8 %", .{ .op = .eq, .value = .{ .literal = 0 } }); switch (builtin.cpu.arch) { .aarch64 => { - // Next check: LINKEDIT segment does not extend beyond, or does not include, CODE_SIGNATURE data + // LINKEDIT segment does not extend beyond, or does not include, CODE_SIGNATURE data check_exe.checkComputeCompare("fileoff filesz codesigoff codesigsize + - -", .{ .op = .eq, .value = .{ .literal = 0 }, }); - // Next check: CODE_SIGNATURE data offset is 16-bytes aligned + // CODE_SIGNATURE data offset is 16-bytes aligned check_exe.checkComputeCompare("codesigoff 16 %", .{ .op = .eq, .value = .{ .literal = 0 } }); }, .x86_64 => { - // Next check: LINKEDIT segment does not extend beyond, or does not include, strtab data + // LINKEDIT segment does not extend beyond, or does not include, strtab data check_exe.checkComputeCompare("fileoff filesz stroff strsize + - -", .{ .op = .eq, .value = .{ .literal = 0 },