authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-12-15 16:04:10+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-12-16 18:05:58+01:00
logb323e14b1c50d731b643180972361552f8e5f5ec
treeef79cdc6afcba81e76b01cd69d0e9a2daa9d19f1
parent660270b7a9c492dbd7c0b76a823bcba5a13da71c

macho: exclude linkedit and symtab/dysymtab load commands from the uuid calc


1 files changed, 66 insertions(+), 23 deletions(-)

src/link/MachO/zld.zig+66-23
......@@ -2675,7 +2675,11 @@ pub const Zld = struct {
26752675 self.dysymtab_cmd.nindirectsyms = nindirectsyms;
26762676 }
26772677
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 {
26792683 switch (self.options.optimize_mode) {
26802684 .Debug => {
26812685 // In Debug we don't really care about reproducibility, so put in a random value
......@@ -2691,8 +2695,24 @@ pub const Zld = struct {
26912695 var hashes = std.ArrayList([Md5.digest_length]u8).init(self.gpa);
26922696 defer hashes.deinit();
26932697
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
26942714 if (!self.options.strip) {
2695 // First exclusion region will comprise all symbol stabs.
2715 // Exclude region comprising all symbol stabs.
26962716 const nlocals = self.dysymtab_cmd.nlocalsym;
26972717
26982718 const locals_buf = try self.gpa.alloc(u8, nlocals * @sizeOf(macho.nlist_64));
......@@ -2706,26 +2726,40 @@ pub const Zld = struct {
27062726 if (local.stab()) break i;
27072727 } else locals.len;
27082728 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;
27262751 }
27272752 } 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);
27292763 }
27302764
27312765 const final_buffer = try self.gpa.alloc(u8, hashes.items.len * Md5.digest_length);
......@@ -2740,7 +2774,7 @@ pub const Zld = struct {
27402774 },
27412775 }
27422776
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);
27442778 try self.file.pwriteAll(&self.uuid_cmd.uuid, in_file);
27452779 }
27462780
......@@ -4057,11 +4091,16 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
40574091 const lc_writer = lc_buffer.writer();
40584092
40594093 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
40604096 try lc_writer.writeStruct(zld.dyld_info_cmd);
40614097 try lc_writer.writeStruct(zld.function_starts_cmd);
40624098 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);
40634101 try lc_writer.writeStruct(zld.symtab_cmd);
40644102 try lc_writer.writeStruct(zld.dysymtab_cmd);
4103
40654104 try load_commands.writeDylinkerLC(lc_writer);
40664105
40674106 if (zld.options.output_mode == .Exe) {
......@@ -4084,7 +4123,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
40844123 });
40854124 try load_commands.writeBuildVersionLC(zld.options, lc_writer);
40864125
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);
40884127 try lc_writer.writeStruct(zld.uuid_cmd);
40894128
40904129 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
41154154 try zld.file.pwriteAll(lc_buffer.items, @sizeOf(macho.mach_header_64));
41164155 try zld.writeHeader(ncmds, @intCast(u32, lc_buffer.items.len));
41174156
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 });
41194162
41204163 if (codesig) |*csig| {
41214164 try zld.writeCodeSignature(comp, csig); // code signing always comes last