| ... | @@ -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 }, |