Commit 79381dc4fb

Jakub Konka <kubkon@jakubkonka.com>
2020-11-20 11:05:16
stage2 macho: add empty CodeDirectory blob
1 parent d14cd59
Changed files (2)
lib
src
lib/std/macho.zig
@@ -1446,6 +1446,18 @@ pub const CodeDirectory = extern struct {
     /// Unused (must be zero)
     spare2: u32,
 
+    ///
+    scatterOffset: u32,
+
+    ///
+    teamOffset: u32,
+
+    ///
+    spare3: u32,
+
+    ///
+    codeLimit64: u64,
+
     /// Offset of executable segment
     execSegBase: u64,
 
@@ -1453,9 +1465,7 @@ pub const CodeDirectory = extern struct {
     execSegLimit: u64,
 
     /// Executable segment flags
-    execSegFlags,
-
-    // end_withExecSeg: [*]u8,
+    execSegFlags: u64,
 };
 
 /// Structure of an embedded-signature SuperBlob
src/link/MachO/CodeSignature.zig
@@ -8,11 +8,39 @@ const mem = std.mem;
 const testing = std.testing;
 const Allocator = mem.Allocator;
 
-// pub const Blob = union(enum) {
-//     Signature: struct{
-//         inner:
-//     }
-// };
+const Blob = struct {
+    inner: macho.CodeDirectory,
+    data: std.ArrayListUnmanaged(u8) = .{},
+
+    fn size(self: Blob) u32 {
+        return self.inner.length;
+    }
+
+    fn write(self: Blob, buffer: []u8) void {
+        assert(buffer.len >= self.inner.length);
+        mem.writeIntBig(u32, buffer[0..4], self.inner.magic);
+        mem.writeIntBig(u32, buffer[4..8], self.inner.length);
+        mem.writeIntBig(u32, buffer[8..12], self.inner.version);
+        mem.writeIntBig(u32, buffer[12..16], self.inner.flags);
+        mem.writeIntBig(u32, buffer[16..20], self.inner.hashOffset);
+        mem.writeIntBig(u32, buffer[20..24], self.inner.identOffset);
+        mem.writeIntBig(u32, buffer[24..28], self.inner.nSpecialSlots);
+        mem.writeIntBig(u32, buffer[28..32], self.inner.nCodeSlots);
+        mem.writeIntBig(u32, buffer[32..36], self.inner.codeLimit);
+        mem.writeIntBig(u8, buffer[36..37], self.inner.hashSize);
+        mem.writeIntBig(u8, buffer[37..38], self.inner.hashType);
+        mem.writeIntBig(u8, buffer[38..39], self.inner.platform);
+        mem.writeIntBig(u8, buffer[39..40], self.inner.pageSize);
+        mem.writeIntBig(u32, buffer[40..44], self.inner.spare2);
+        mem.writeIntBig(u32, buffer[44..48], self.inner.scatterOffset);
+        mem.writeIntBig(u32, buffer[48..52], self.inner.teamOffset);
+        mem.writeIntBig(u32, buffer[52..56], self.inner.spare3);
+        mem.writeIntBig(u64, buffer[56..64], self.inner.codeLimit64);
+        mem.writeIntBig(u64, buffer[64..72], self.inner.execSegBase);
+        mem.writeIntBig(u64, buffer[72..80], self.inner.execSegLimit);
+        mem.writeIntBig(u64, buffer[80..88], self.inner.execSegFlags);
+    }
+};
 
 alloc: *Allocator,
 inner: macho.SuperBlob = .{
@@ -20,16 +48,44 @@ inner: macho.SuperBlob = .{
     .length = @sizeOf(macho.SuperBlob),
     .count = 0,
 },
-// blobs: std.ArrayList(Blob),
+blob: ?Blob = null,
 
 pub fn init(alloc: *Allocator) CodeSignature {
     return .{
         .alloc = alloc,
-        // .indices = std.ArrayList(Blob).init(alloc),
     };
 }
 
-pub fn calcAdhocSignature(self: *CodeSignature) !void {}
+pub fn calcAdhocSignature(self: *CodeSignature) !void {
+    var blob = Blob{
+        .inner = .{
+            .magic = macho.CSMAGIC_CODEDIRECTORY,
+            .length = @sizeOf(macho.CodeDirectory),
+            .version = 0x20400,
+            .flags = 0,
+            .hashOffset = 0,
+            .identOffset = 0,
+            .nSpecialSlots = 0,
+            .nCodeSlots = 0,
+            .codeLimit = 0,
+            .hashSize = 0,
+            .hashType = 0,
+            .platform = 0,
+            .pageSize = 0,
+            .spare2 = 0,
+            .scatterOffset = 0,
+            .teamOffset = 0,
+            .spare3 = 0,
+            .codeLimit64 = 0,
+            .execSegBase = 0,
+            .execSegLimit = 0,
+            .execSegFlags = 0,
+        },
+    };
+    self.inner.length += @sizeOf(macho.BlobIndex) + blob.size();
+    self.inner.count = 1;
+    self.blob = blob;
+}
 
 pub fn size(self: CodeSignature) u32 {
     return self.inner.length;
@@ -38,9 +94,16 @@ pub fn size(self: CodeSignature) u32 {
 pub fn write(self: CodeSignature, buffer: []u8) void {
     assert(buffer.len >= self.inner.length);
     self.writeHeader(buffer);
+    const offset: u32 = @sizeOf(macho.SuperBlob) + @sizeOf(macho.BlobIndex);
+    writeBlobIndex(macho.CSSLOT_CODEDIRECTORY, offset, buffer[@sizeOf(macho.SuperBlob)..]);
+    self.blob.?.write(buffer[offset..]);
 }
 
-pub fn deinit(self: *CodeSignature) void {}
+pub fn deinit(self: *CodeSignature) void {
+    if (self.blob) |*b| {
+        b.data.deinit(self.alloc);
+    }
+}
 
 fn writeHeader(self: CodeSignature, buffer: []u8) void {
     assert(buffer.len >= @sizeOf(macho.SuperBlob));
@@ -49,11 +112,19 @@ fn writeHeader(self: CodeSignature, buffer: []u8) void {
     mem.writeIntBig(u32, buffer[8..12], self.inner.count);
 }
 
+fn writeBlobIndex(tt: u32, offset: u32, buffer: []u8) void {
+    assert(buffer.len >= @sizeOf(macho.BlobIndex));
+    mem.writeIntBig(u32, buffer[0..4], tt);
+    mem.writeIntBig(u32, buffer[4..8], offset);
+}
+
 test "CodeSignature header" {
     var code_sig = CodeSignature.init(testing.allocator);
     defer code_sig.deinit();
+
     var buffer: [@sizeOf(macho.SuperBlob)]u8 = undefined;
     code_sig.writeHeader(buffer[0..]);
+
     const expected = &[_]u8{ 0xfa, 0xde, 0x0c, 0xc0, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0 };
     testing.expect(mem.eql(u8, expected[0..], buffer[0..]));
 }