mirror of
https://github.com/ziglang/zig.git
synced 2026-01-22 07:15:25 +00:00
131 lines
4.4 KiB
Zig
131 lines
4.4 KiB
Zig
const CodeSignature = @This();
|
|
|
|
const std = @import("std");
|
|
const assert = std.debug.assert;
|
|
const log = std.log.scoped(.link);
|
|
const macho = std.macho;
|
|
const mem = std.mem;
|
|
const testing = std.testing;
|
|
const Allocator = mem.Allocator;
|
|
|
|
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 = .{
|
|
.magic = macho.CSMAGIC_EMBEDDED_SIGNATURE,
|
|
.length = @sizeOf(macho.SuperBlob),
|
|
.count = 0,
|
|
},
|
|
blob: ?Blob = null,
|
|
|
|
pub fn init(alloc: *Allocator) CodeSignature {
|
|
return .{
|
|
.alloc = alloc,
|
|
};
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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 {
|
|
if (self.blob) |*b| {
|
|
b.data.deinit(self.alloc);
|
|
}
|
|
}
|
|
|
|
fn writeHeader(self: CodeSignature, buffer: []u8) void {
|
|
assert(buffer.len >= @sizeOf(macho.SuperBlob));
|
|
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.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..]));
|
|
}
|