| ... | ... | @@ -2675,7 +2675,11 @@ pub const Zld = struct { |
| 2675 | 2675 | self.dysymtab_cmd.nindirectsyms = nindirectsyms; |
| 2676 | 2676 | } |
| 2677 | 2677 | |
| 2678 | | fn writeUuid(self: *Zld, comp: *const Compilation, offset: u32) !void { |
| 2678 | fn writeUuid(self: *Zld, comp: *const Compilation, args: struct { |
| 2679 | linkedit_cmd_offset: u32, |
| 2680 | symtab_cmd_offset: u32, |
| 2681 | uuid_cmd_offset: u32, |
| 2682 | }) !void { |
| 2679 | 2683 | switch (self.options.optimize_mode) { |
| 2680 | 2684 | .Debug => { |
| 2681 | 2685 | // In Debug we don't really care about reproducibility, so put in a random value |
| ... | ... | @@ -2691,8 +2695,24 @@ pub const Zld = struct { |
| 2691 | 2695 | var hashes = std.ArrayList([Md5.digest_length]u8).init(self.gpa); |
| 2692 | 2696 | defer hashes.deinit(); |
| 2693 | 2697 | |
| 2698 | var subsections: [4]FileSubsection = undefined; |
| 2699 | var count: usize = 2; |
| 2700 | |
| 2701 | // Exclude LINKEDIT segment command as it contains file size that includes stabs contribution |
| 2702 | // and code signature. |
| 2703 | subsections[0] = .{ |
| 2704 | .start = 0, |
| 2705 | .end = args.linkedit_cmd_offset, |
| 2706 | }; |
| 2707 | |
| 2708 | // Exclude SYMTAB and DYSYMTAB commands for the same reason. |
| 2709 | subsections[1] = .{ |
| 2710 | .start = args.linkedit_cmd_offset + @sizeOf(macho.segment_command_64), |
| 2711 | .end = args.symtab_cmd_offset, |
| 2712 | }; |
| 2713 | |
| 2694 | 2714 | if (!self.options.strip) { |
| 2695 | | // First exclusion region will comprise all symbol stabs. |
| 2715 | // Exclude region comprising all symbol stabs. |
| 2696 | 2716 | const nlocals = self.dysymtab_cmd.nlocalsym; |
| 2697 | 2717 | |
| 2698 | 2718 | const locals_buf = try self.gpa.alloc(u8, nlocals * @sizeOf(macho.nlist_64)); |
| ... | ... | @@ -2706,26 +2726,40 @@ pub const Zld = struct { |
| 2706 | 2726 | if (local.stab()) break i; |
| 2707 | 2727 | } else locals.len; |
| 2708 | 2728 | const nstabs = locals.len - istab; |
| 2709 | | |
| 2710 | | // Next, a subsection of the strtab. |
| 2711 | | // We do not care about anything succeeding strtab as it is the code signature data which is |
| 2712 | | // not part of the UUID calculation anyway. |
| 2713 | | const stab_stroff = locals[istab].n_strx; |
| 2714 | | |
| 2715 | | const first_cut = FileSubsection{ |
| 2716 | | .start = 0, |
| 2717 | | .end = @intCast(u32, self.symtab_cmd.symoff + istab * @sizeOf(macho.nlist_64)), |
| 2718 | | }; |
| 2719 | | const second_cut = FileSubsection{ |
| 2720 | | .start = first_cut.end + @intCast(u32, nstabs * @sizeOf(macho.nlist_64)), |
| 2721 | | .end = self.symtab_cmd.stroff + stab_stroff, |
| 2722 | | }; |
| 2723 | | |
| 2724 | | for (&[_]FileSubsection{ first_cut, second_cut }) |cut| { |
| 2725 | | try self.calcUuidHashes(comp, cut, &hashes); |
| 2729 | if (nstabs == 0) { |
| 2730 | subsections[2] = .{ |
| 2731 | .start = args.symtab_cmd_offset + @sizeOf(macho.symtab_command) + @sizeOf(macho.dysymtab_command), |
| 2732 | .end = max_file_size, |
| 2733 | }; |
| 2734 | count += 1; |
| 2735 | } else { |
| 2736 | // Exclude a subsection of the strtab with names of the stabs. |
| 2737 | // We do not care about anything succeeding strtab as it is the code signature data which is |
| 2738 | // not part of the UUID calculation anyway. |
| 2739 | const stab_stroff = locals[istab].n_strx; |
| 2740 | |
| 2741 | subsections[2] = .{ |
| 2742 | .start = args.symtab_cmd_offset + @sizeOf(macho.symtab_command) + @sizeOf(macho.dysymtab_command), |
| 2743 | .end = @intCast(u32, self.symtab_cmd.symoff + istab * @sizeOf(macho.nlist_64)), |
| 2744 | }; |
| 2745 | subsections[3] = .{ |
| 2746 | .start = subsections[2].end + @intCast(u32, nstabs * @sizeOf(macho.nlist_64)), |
| 2747 | .end = self.symtab_cmd.stroff + stab_stroff, |
| 2748 | }; |
| 2749 | |
| 2750 | count += 2; |
| 2726 | 2751 | } |
| 2727 | 2752 | } else { |
| 2728 | | try self.calcUuidHashes(comp, .{ .start = 0, .end = max_file_size }, &hashes); |
| 2753 | subsections[2] = .{ |
| 2754 | .start = args.symtab_cmd_offset + @sizeOf(macho.symtab_command) + @sizeOf(macho.dysymtab_command), |
| 2755 | .end = max_file_size, |
| 2756 | }; |
| 2757 | count += 1; |
| 2758 | } |
| 2759 | |
| 2760 | for (subsections[0..count]) |cut| { |
| 2761 | std.debug.print("{x} - {x}\n", .{ cut.start, cut.end }); |
| 2762 | try self.calcUuidHashes(comp, cut, &hashes); |
| 2729 | 2763 | } |
| 2730 | 2764 | |
| 2731 | 2765 | const final_buffer = try self.gpa.alloc(u8, hashes.items.len * Md5.digest_length); |
| ... | ... | @@ -2740,7 +2774,7 @@ pub const Zld = struct { |
| 2740 | 2774 | }, |
| 2741 | 2775 | } |
| 2742 | 2776 | |
| 2743 | | const in_file = @sizeOf(macho.mach_header_64) + offset + @sizeOf(macho.load_command); |
| 2777 | const in_file = args.uuid_cmd_offset + @sizeOf(macho.load_command); |
| 2744 | 2778 | try self.file.pwriteAll(&self.uuid_cmd.uuid, in_file); |
| 2745 | 2779 | } |
| 2746 | 2780 | |
| ... | ... | @@ -4057,11 +4091,16 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr |
| 4057 | 4091 | const lc_writer = lc_buffer.writer(); |
| 4058 | 4092 | |
| 4059 | 4093 | try zld.writeSegmentHeaders(lc_writer); |
| 4094 | const linkedit_cmd_offset = @sizeOf(macho.mach_header_64) + @intCast(u32, lc_buffer.items.len - @sizeOf(macho.segment_command_64)); |
| 4095 | |
| 4060 | 4096 | try lc_writer.writeStruct(zld.dyld_info_cmd); |
| 4061 | 4097 | try lc_writer.writeStruct(zld.function_starts_cmd); |
| 4062 | 4098 | try lc_writer.writeStruct(zld.data_in_code_cmd); |
| 4099 | |
| 4100 | const symtab_cmd_offset = @sizeOf(macho.mach_header_64) + @intCast(u32, lc_buffer.items.len); |
| 4063 | 4101 | try lc_writer.writeStruct(zld.symtab_cmd); |
| 4064 | 4102 | try lc_writer.writeStruct(zld.dysymtab_cmd); |
| 4103 | |
| 4065 | 4104 | try load_commands.writeDylinkerLC(lc_writer); |
| 4066 | 4105 | |
| 4067 | 4106 | if (zld.options.output_mode == .Exe) { |
| ... | ... | @@ -4084,7 +4123,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr |
| 4084 | 4123 | }); |
| 4085 | 4124 | try load_commands.writeBuildVersionLC(zld.options, lc_writer); |
| 4086 | 4125 | |
| 4087 | | const uuid_offset = @intCast(u32, lc_buffer.items.len); |
| 4126 | const uuid_cmd_offset = @sizeOf(macho.mach_header_64) + @intCast(u32, lc_buffer.items.len); |
| 4088 | 4127 | try lc_writer.writeStruct(zld.uuid_cmd); |
| 4089 | 4128 | |
| 4090 | 4129 | try load_commands.writeLoadDylibLCs(zld.dylibs.items, zld.referenced_dylibs.keys(), lc_writer); |
| ... | ... | @@ -4115,7 +4154,11 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr |
| 4115 | 4154 | try zld.file.pwriteAll(lc_buffer.items, @sizeOf(macho.mach_header_64)); |
| 4116 | 4155 | try zld.writeHeader(ncmds, @intCast(u32, lc_buffer.items.len)); |
| 4117 | 4156 | |
| 4118 | | try zld.writeUuid(comp, uuid_offset); |
| 4157 | try zld.writeUuid(comp, .{ |
| 4158 | .linkedit_cmd_offset = linkedit_cmd_offset, |
| 4159 | .symtab_cmd_offset = symtab_cmd_offset, |
| 4160 | .uuid_cmd_offset = uuid_cmd_offset, |
| 4161 | }); |
| 4119 | 4162 | |
| 4120 | 4163 | if (codesig) |*csig| { |
| 4121 | 4164 | try zld.writeCodeSignature(comp, csig); // code signing always comes last |