aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-12-14 13:56:52 +0100
committerJakub Konka <kubkon@jakubkonka.com>2022-12-16 00:01:04 +0100
commitec40c6b28fb1612f401db3c43b68aba670327e2e (patch)
tree984df1c4af912f44c2e19e822539c79dc94e5c6c
parentdb2052bc3588c1c52494eef32ef66c5cf3e09d96 (diff)
downloadzig-ec40c6b28fb1612f401db3c43b68aba670327e2e.tar.gz
zig-ec40c6b28fb1612f401db3c43b68aba670327e2e.zip
macho: calculate UUID as a streaming MD5 hash of the file contents
-rw-r--r--CMakeLists.txt1
-rw-r--r--src/link/MachO/load_commands.zig9
-rw-r--r--src/link/MachO/zld.zig28
3 files changed, 29 insertions, 9 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8e8c66d374..31d72a34d6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -593,6 +593,7 @@ set(ZIG_STAGE2_SOURCES
"${CMAKE_SOURCE_DIR}/src/link/MachO/fat.zig"
"${CMAKE_SOURCE_DIR}/src/link/MachO/load_commands.zig"
"${CMAKE_SOURCE_DIR}/src/link/MachO/thunks.zig"
+ "${CMAKE_SOURCE_DIR}/src/link/MachO/uuid.zig"
"${CMAKE_SOURCE_DIR}/src/link/MachO/zld.zig"
"${CMAKE_SOURCE_DIR}/src/link/Plan9.zig"
"${CMAKE_SOURCE_DIR}/src/link/Plan9/aout.zig"
diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig
index 9b0e61e919..c4e565928b 100644
--- a/src/link/MachO/load_commands.zig
+++ b/src/link/MachO/load_commands.zig
@@ -323,3 +323,12 @@ pub fn writeSourceVersionLC(ncmds: *u32, lc_writer: anytype) !void {
});
ncmds.* += 1;
}
+
+pub fn writeUuidLC(uuid: *const [16]u8, ncmds: *u32, lc_writer: anytype) !void {
+ var uuid_lc = macho.uuid_command{
+ .cmdsize = @sizeOf(macho.uuid_command),
+ .uuid = uuid.*,
+ };
+ try lc_writer.writeStruct(uuid_lc);
+ ncmds.* += 1;
+}
diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig
index 7bffc10e85..9a66d76e1a 100644
--- a/src/link/MachO/zld.zig
+++ b/src/link/MachO/zld.zig
@@ -16,6 +16,7 @@ const link = @import("../../link.zig");
const load_commands = @import("load_commands.zig");
const thunks = @import("thunks.zig");
const trace = @import("../../tracy.zig").trace;
+const uuid = @import("uuid.zig");
const Allocator = mem.Allocator;
const Archive = @import("Archive.zig");
@@ -3986,6 +3987,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
var lc_buffer = std.ArrayList(u8).init(arena);
const lc_writer = lc_buffer.writer();
+
var ncmds: u32 = 0;
try zld.writeLinkeditSegmentData(&ncmds, lc_writer, reverse_lookups);
@@ -4030,15 +4032,14 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
try load_commands.writeSourceVersionLC(&ncmds, lc_writer);
try load_commands.writeBuildVersionLC(zld.options, &ncmds, lc_writer);
- {
- var uuid_lc = macho.uuid_command{
- .cmdsize = @sizeOf(macho.uuid_command),
- .uuid = undefined,
- };
- std.crypto.random.bytes(&uuid_lc.uuid);
- try lc_writer.writeStruct(uuid_lc);
- ncmds += 1;
- }
+ // Looking forward into the future, we will want to offer `-no_uuid` support in which case
+ // there will be nothing to backpatch.
+ const uuid_offset_backpatch: ?usize = blk: {
+ const index = lc_buffer.items.len;
+ var uuid_buf: [16]u8 = [_]u8{0} ** 16;
+ try load_commands.writeUuidLC(&uuid_buf, &ncmds, lc_writer);
+ break :blk index;
+ };
try load_commands.writeLoadDylibLCs(zld.dylibs.items, zld.referenced_dylibs.keys(), &ncmds, lc_writer);
@@ -4071,6 +4072,15 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
try zld.file.pwriteAll(lc_buffer.items, @sizeOf(macho.mach_header_64) + headers_buf.items.len);
try zld.writeHeader(ncmds, @intCast(u32, lc_buffer.items.len + headers_buf.items.len));
+ if (uuid_offset_backpatch) |backpatch| {
+ const seg = zld.getLinkeditSegmentPtr();
+ const file_size = seg.fileoff + seg.filesize;
+ var uuid_buf: [16]u8 = undefined;
+ try uuid.calcMd5Hash(zld.gpa, zld.file, file_size, &uuid_buf);
+ const offset = @sizeOf(macho.mach_header_64) + headers_buf.items.len + backpatch + @sizeOf(macho.load_command);
+ try zld.file.pwriteAll(&uuid_buf, offset);
+ }
+
if (codesig) |*csig| {
try zld.writeCodeSignature(comp, csig, codesig_offset.?); // code signing always comes last
}