lld: add code signature to lld output
This commit is contained in:
parent
545721ccd1
commit
c25b3593e7
@ -812,28 +812,23 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
|
|||||||
try parser.parseFile(out_file);
|
try parser.parseFile(out_file);
|
||||||
// Pad out space for code signature
|
// Pad out space for code signature
|
||||||
const text_cmd = parser.load_commands.items[parser.text_cmd_index.?].Segment.inner;
|
const text_cmd = parser.load_commands.items[parser.text_cmd_index.?].Segment.inner;
|
||||||
std.debug.print("end_pos={},text_fileoff={},text_filesize={}\n", .{
|
|
||||||
parser.end_pos,
|
|
||||||
text_cmd.fileoff,
|
|
||||||
text_cmd.filesize,
|
|
||||||
});
|
|
||||||
const dataoff = @intCast(u32, mem.alignForward(parser.end_pos.?, @sizeOf(u64)));
|
const dataoff = @intCast(u32, mem.alignForward(parser.end_pos.?, @sizeOf(u64)));
|
||||||
|
const datasize = 0x1000;
|
||||||
const code_sig = macho.linkedit_data_command{
|
const code_sig = macho.linkedit_data_command{
|
||||||
.cmd = macho.LC_CODE_SIGNATURE,
|
.cmd = macho.LC_CODE_SIGNATURE,
|
||||||
.cmdsize = @sizeOf(macho.linkedit_data_command),
|
.cmdsize = @sizeOf(macho.linkedit_data_command),
|
||||||
.dataoff = dataoff,
|
.dataoff = dataoff,
|
||||||
.datasize = 0x1000,
|
.datasize = datasize,
|
||||||
};
|
};
|
||||||
|
|
||||||
const linkedit_seg = parser.load_commands.items[parser.linkedit_cmd_index.?].Segment.inner;
|
const linkedit_seg = parser.load_commands.items[parser.linkedit_cmd_index.?].Segment.inner;
|
||||||
const linkedit = macho.segment_command_64{
|
const linkedit = macho.segment_command_64{
|
||||||
.cmd = linkedit_seg.cmd,
|
.cmd = linkedit_seg.cmd,
|
||||||
.cmdsize = linkedit_seg.cmdsize,
|
.cmdsize = linkedit_seg.cmdsize,
|
||||||
.segname = linkedit_seg.segname,
|
.segname = linkedit_seg.segname,
|
||||||
.vmaddr = linkedit_seg.vmaddr,
|
.vmaddr = linkedit_seg.vmaddr,
|
||||||
.vmsize = mem.alignForwardGeneric(u64, linkedit_seg.vmsize + 0x1000, self.page_size),
|
.vmsize = mem.alignForwardGeneric(u64, linkedit_seg.vmsize + datasize, self.page_size),
|
||||||
.fileoff = linkedit_seg.fileoff,
|
.fileoff = linkedit_seg.fileoff,
|
||||||
.filesize = linkedit_seg.filesize + (dataoff - parser.end_pos.?) + 0x1000,
|
.filesize = linkedit_seg.filesize + (dataoff - parser.end_pos.?) + datasize,
|
||||||
.maxprot = linkedit_seg.maxprot,
|
.maxprot = linkedit_seg.maxprot,
|
||||||
.initprot = linkedit_seg.initprot,
|
.initprot = linkedit_seg.initprot,
|
||||||
.nsects = linkedit_seg.nsects,
|
.nsects = linkedit_seg.nsects,
|
||||||
@ -854,6 +849,20 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
|
|||||||
try out_file.pwriteAll(mem.sliceAsBytes(&[_]macho.linkedit_data_command{code_sig}), parser.code_sig_cmd_offset.?);
|
try out_file.pwriteAll(mem.sliceAsBytes(&[_]macho.linkedit_data_command{code_sig}), parser.code_sig_cmd_offset.?);
|
||||||
try out_file.pwriteAll(mem.sliceAsBytes(&[_]macho.segment_command_64{linkedit}), parser.linkedit_cmd_offset.?);
|
try out_file.pwriteAll(mem.sliceAsBytes(&[_]macho.segment_command_64{linkedit}), parser.linkedit_cmd_offset.?);
|
||||||
try out_file.pwriteAll(mem.sliceAsBytes(&[_]macho.mach_header_64{header}), 0);
|
try out_file.pwriteAll(mem.sliceAsBytes(&[_]macho.mach_header_64{header}), 0);
|
||||||
|
// Generate adhoc code signature
|
||||||
|
var signature = CodeSignature.init(self.base.allocator);
|
||||||
|
defer signature.deinit();
|
||||||
|
try signature.calcAdhocSignatureFile(
|
||||||
|
out_file,
|
||||||
|
self.base.options.emit.?.sub_path,
|
||||||
|
text_cmd,
|
||||||
|
code_sig,
|
||||||
|
self.base.options.output_mode,
|
||||||
|
);
|
||||||
|
var buffer = try self.base.allocator.alloc(u8, signature.size());
|
||||||
|
defer self.base.allocator.free(buffer);
|
||||||
|
signature.write(buffer);
|
||||||
|
try out_file.pwriteAll(buffer, code_sig.dataoff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ const CodeSignature = @This();
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
const fs = std.fs;
|
||||||
const log = std.log.scoped(.link);
|
const log = std.log.scoped(.link);
|
||||||
const macho = std.macho;
|
const macho = std.macho;
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
@ -65,6 +66,82 @@ pub fn init(alloc: *Allocator) CodeSignature {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn calcAdhocSignatureFile(
|
||||||
|
self: *CodeSignature,
|
||||||
|
file: fs.File,
|
||||||
|
id: []const u8,
|
||||||
|
text_segment: macho.segment_command_64,
|
||||||
|
code_sig_cmd: macho.linkedit_data_command,
|
||||||
|
output_mode: std.builtin.OutputMode,
|
||||||
|
) !void {
|
||||||
|
const execSegBase: u64 = text_segment.fileoff;
|
||||||
|
const execSegLimit: u64 = text_segment.filesize;
|
||||||
|
const execSegFlags: u64 = if (output_mode == .Exe) macho.CS_EXECSEG_MAIN_BINARY else 0;
|
||||||
|
const file_size = code_sig_cmd.dataoff;
|
||||||
|
var cdir = CodeDirectory{
|
||||||
|
.inner = .{
|
||||||
|
.magic = macho.CSMAGIC_CODEDIRECTORY,
|
||||||
|
.length = @sizeOf(macho.CodeDirectory),
|
||||||
|
.version = macho.CS_SUPPORTSEXECSEG,
|
||||||
|
.flags = macho.CS_ADHOC,
|
||||||
|
.hashOffset = 0,
|
||||||
|
.identOffset = 0,
|
||||||
|
.nSpecialSlots = 0,
|
||||||
|
.nCodeSlots = 0,
|
||||||
|
.codeLimit = @intCast(u32, file_size),
|
||||||
|
.hashSize = hash_size,
|
||||||
|
.hashType = macho.CS_HASHTYPE_SHA256,
|
||||||
|
.platform = 0,
|
||||||
|
.pageSize = @truncate(u8, std.math.log2(page_size)),
|
||||||
|
.spare2 = 0,
|
||||||
|
.scatterOffset = 0,
|
||||||
|
.teamOffset = 0,
|
||||||
|
.spare3 = 0,
|
||||||
|
.codeLimit64 = 0,
|
||||||
|
.execSegBase = execSegBase,
|
||||||
|
.execSegLimit = execSegLimit,
|
||||||
|
.execSegFlags = execSegFlags,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const total_pages = mem.alignForward(file_size, page_size) / page_size;
|
||||||
|
|
||||||
|
var hash: [hash_size]u8 = undefined;
|
||||||
|
var buffer = try self.alloc.alloc(u8, page_size);
|
||||||
|
defer self.alloc.free(buffer);
|
||||||
|
|
||||||
|
try cdir.data.ensureCapacity(self.alloc, total_pages * hash_size + id.len + 1);
|
||||||
|
|
||||||
|
// 1. Save the identifier and update offsets
|
||||||
|
cdir.inner.identOffset = cdir.inner.length;
|
||||||
|
cdir.data.appendSliceAssumeCapacity(id);
|
||||||
|
cdir.data.appendAssumeCapacity(0);
|
||||||
|
|
||||||
|
// 2. Calculate hash for each page (in file) and write it to the buffer
|
||||||
|
// TODO figure out how we can cache several hashes since we won't update
|
||||||
|
// every page during incremental linking
|
||||||
|
cdir.inner.hashOffset = cdir.inner.identOffset + @intCast(u32, id.len) + 1;
|
||||||
|
var i: usize = 0;
|
||||||
|
while (i < total_pages) : (i += 1) {
|
||||||
|
const fstart = i * page_size;
|
||||||
|
const fsize = if (fstart + page_size > file_size) file_size - fstart else page_size;
|
||||||
|
const len = try file.preadAll(buffer, fstart);
|
||||||
|
assert(fsize <= len);
|
||||||
|
|
||||||
|
Sha256.hash(buffer[0..fsize], &hash, .{});
|
||||||
|
|
||||||
|
cdir.data.appendSliceAssumeCapacity(hash[0..]);
|
||||||
|
cdir.inner.nCodeSlots += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Update CodeDirectory length
|
||||||
|
cdir.inner.length += @intCast(u32, cdir.data.items.len);
|
||||||
|
|
||||||
|
self.inner.length += @sizeOf(macho.BlobIndex) + cdir.size();
|
||||||
|
self.inner.count = 1;
|
||||||
|
self.cdir = cdir;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn calcAdhocSignature(self: *CodeSignature, bin_file: *const MachO) !void {
|
pub fn calcAdhocSignature(self: *CodeSignature, bin_file: *const MachO) !void {
|
||||||
const text_segment = bin_file.load_commands.items[bin_file.text_segment_cmd_index.?].Segment;
|
const text_segment = bin_file.load_commands.items[bin_file.text_segment_cmd_index.?].Segment;
|
||||||
const code_sig_cmd = bin_file.load_commands.items[bin_file.code_signature_cmd_index.?].LinkeditData;
|
const code_sig_cmd = bin_file.load_commands.items[bin_file.code_signature_cmd_index.?].LinkeditData;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user