697 lines
27 KiB
Zig
697 lines
27 KiB
Zig
const std = @import("std");
|
|
const Allocator = std.mem.Allocator;
|
|
const assert = std.debug.assert;
|
|
const equal = std.mem.eql;
|
|
|
|
const Compilation = @import("../Compilation.zig");
|
|
|
|
const data_structures = @import("../data_structures.zig");
|
|
const ArrayList = data_structures.ArrayList;
|
|
const mmap = data_structures.mmap;
|
|
|
|
const Header = extern struct {
|
|
magic: u32 = magic,
|
|
cpu_type: CpuType,
|
|
cpu_subtype: extern union {
|
|
arm: ArmSubType,
|
|
x86: X86SubType,
|
|
},
|
|
file_type: FileType,
|
|
load_command_count: u32,
|
|
load_command_size: u32,
|
|
flags: Flags,
|
|
reserved: u32 = 0,
|
|
|
|
const magic = 0xfeedfacf;
|
|
|
|
const CpuType = enum(u32) {
|
|
VAX = 0x00000001,
|
|
ROMP = 0x00000002,
|
|
NS32032 = 0x00000004,
|
|
NS32332 = 0x00000005,
|
|
MC680x0 = 0x00000006,
|
|
x86 = 0x00000007,
|
|
MIPS = 0x00000008,
|
|
NS32352 = 0x00000009,
|
|
MC98000 = 0x0000000A,
|
|
HPPA = 0x0000000B,
|
|
ARM = 0x0000000C,
|
|
MC88000 = 0x0000000D,
|
|
SPARC = 0x0000000E,
|
|
i860be = 0x0000000F,
|
|
i860_le = 0x00000010,
|
|
RS6000 = 0x00000011,
|
|
PowerPC = 0x00000012,
|
|
arm64 = 0x0000000C | abi64,
|
|
x86_64 = 0x00000007 | abi64,
|
|
|
|
const abi64 = 0x01000000;
|
|
};
|
|
|
|
const ArmSubType = enum(u32) {
|
|
all = 0x00000000,
|
|
ARM_A500_ARCH = 0x00000001,
|
|
ARM_A500 = 0x00000002,
|
|
ARM_A440 = 0x00000003,
|
|
ARM_M4 = 0x00000004,
|
|
ARM_V4T = 0x00000005,
|
|
ARM_V6 = 0x00000006,
|
|
ARM_V5TEJ = 0x00000007,
|
|
ARM_XSCALE = 0x00000008,
|
|
ARM_V7 = 0x00000009,
|
|
ARM_V7F = 0x0000000A,
|
|
ARM_V7S = 0x0000000B,
|
|
ARM_V7K = 0x0000000C,
|
|
ARM_V8 = 0x0000000D,
|
|
ARM_V6M = 0x0000000E,
|
|
ARM_V7M = 0x0000000F,
|
|
ARM_V7EM = 0x00000010,
|
|
_,
|
|
};
|
|
|
|
const X86SubType = enum(u32) {
|
|
All = 0x00000003,
|
|
@"486" = 0x00000004,
|
|
@"486SX" = 0x00000084,
|
|
Pentium_M5 = 0x00000056,
|
|
Celeron = 0x00000067,
|
|
Celeron_Mobile = 0x00000077,
|
|
Pentium_3 = 0x00000008,
|
|
Pentium_3_M = 0x00000018,
|
|
Pentium_3_XEON = 0x00000028,
|
|
Pentium_4 = 0x0000000A,
|
|
Itanium = 0x0000000B,
|
|
Itanium_2 = 0x0000001B,
|
|
XEON = 0x0000000C,
|
|
XEON_MP = 0x0000001C,
|
|
_,
|
|
};
|
|
|
|
const FileType = enum(u32) {
|
|
relocatable_object = 0x00000001,
|
|
demand_paged_executable = 0x00000002,
|
|
fixed_vm_shared_library = 0x00000003,
|
|
core = 0x00000004,
|
|
preloaded_executable = 0x00000005,
|
|
dynamic_shared_library = 0x00000006,
|
|
dynamic_link_editor = 0x00000007,
|
|
dynamic_bundle = 0x00000008,
|
|
shared_library_stub = 0x00000009,
|
|
debug_companion = 0x0000000A,
|
|
x86_64_kext = 0x0000000B,
|
|
archive = 0x0000000C,
|
|
};
|
|
|
|
const Flags = packed struct(u32) {
|
|
no_undefined_references: bool = true,
|
|
incrementally_linked: bool = false,
|
|
dynamic_linker_input: bool = true,
|
|
dynamic_linker_bound_undefined_references: bool = false,
|
|
prebound_dynamic_undefined_references: bool = false,
|
|
split_ro_and_rw_segments: bool = false,
|
|
_: bool = false,
|
|
two_level_namespace_bindings: bool = true,
|
|
no_symbol_multiple_definition_in_subimages: bool = false,
|
|
no_dyld_prebinding_agent_notification: bool = false,
|
|
can_redo_prebinding: bool = false,
|
|
bind_two_level_namespaces_to_libraries: bool = false,
|
|
safe_to_split_sections_for_dead_code_stripping: bool = false,
|
|
canonicalized_by_unprebinding: bool = false,
|
|
final_external_weak_symbols: bool = false,
|
|
final_weak_symbols: bool = false,
|
|
all_stacks_execute_protected: bool = false,
|
|
safe_for_zero_uid: bool = false,
|
|
safe_for_ugid: bool = false,
|
|
no_check_dependent_dylibs_for_reexport: bool = false,
|
|
load_at_random_address: bool = false,
|
|
no_load_command_for_unreferenced_dylib: bool = true,
|
|
thread_local_variable_section: bool = false,
|
|
run_with_non_executable_heap: bool = false,
|
|
code_linked_for_application_use: bool = false,
|
|
nlist_external_symbols_not_all_dyld_info_symbols: bool = false,
|
|
allow_lc_min_version_macos_lc_build_version: bool = false,
|
|
reserved: u4 = 0,
|
|
dylib_only: bool = false,
|
|
};
|
|
};
|
|
|
|
const UniversalHeader = extern struct {
|
|
magic: u32 = magic,
|
|
binary_count: u32,
|
|
|
|
const magic = 0xcafebabe;
|
|
};
|
|
|
|
const LoadCommand = extern struct {
|
|
type: Type,
|
|
size: u32,
|
|
|
|
const Type = enum(u32) {
|
|
segment32 = 0x01,
|
|
symbol_table = 0x02,
|
|
symbol_table_information = 0x0b,
|
|
load_dylib = 0x0c,
|
|
id_dylib = 0x0d,
|
|
load_dylinker = 0x0e,
|
|
id_dylinker = 0x0f,
|
|
optional_dynamic_library = 0x18,
|
|
segment64 = 0x19,
|
|
uuid_number = 0x1b,
|
|
code_signature = 0x1d,
|
|
compressed_linkedit_table = 0x22,
|
|
function_starts = 0x26,
|
|
data_in_code = 0x29,
|
|
source_version = 0x2a,
|
|
minimum_os_version = 0x32,
|
|
dyld_exports_trie = 0x80000033,
|
|
dyld_chained_fixups = 0x80000034,
|
|
dyld_main_entry_point = 0x80000028,
|
|
};
|
|
|
|
const Segment64 = extern struct {
|
|
type: Type = .segment64,
|
|
size: u32,
|
|
name: [16]u8,
|
|
address: u64,
|
|
address_size: u64,
|
|
file_offset: u64,
|
|
file_size: u64,
|
|
maximum_virtual_memory_protections: VirtualMemoryProtection,
|
|
initial_virtual_memory_protections: VirtualMemoryProtection,
|
|
section_count: u32,
|
|
flags: Flags,
|
|
|
|
const VirtualMemoryProtection = packed struct(u32) {
|
|
read: bool,
|
|
write: bool,
|
|
execute: bool,
|
|
reserved: u29 = 0,
|
|
};
|
|
|
|
const Flags = packed struct(u32) {
|
|
vm_space_high_part: bool = false,
|
|
vm_fixed_library: bool = false,
|
|
no_relocation: bool = false,
|
|
protected_segment: bool = false,
|
|
read_only_after_relocations: bool = false,
|
|
reserved: u27 = 0,
|
|
};
|
|
|
|
const Section = extern struct {
|
|
name: [16]u8,
|
|
segment_name: [16]u8,
|
|
address: u64,
|
|
size: u64,
|
|
file_offset: u32,
|
|
alignment: u32,
|
|
relocation_file_offset: u32,
|
|
relocation_count: u32,
|
|
type: Section.Type,
|
|
reserved: u8 = 0,
|
|
flags: Section.Flags,
|
|
reserved0: u32 = 0,
|
|
reserved1: u32 = 0,
|
|
reserved2: u32 = 0,
|
|
|
|
comptime {
|
|
assert(@sizeOf(Section) == 80);
|
|
}
|
|
|
|
const Type = enum(u8) {
|
|
regular = 0,
|
|
only_non_lazy_symbol_pointers = 0b110,
|
|
only_lazy_symbol_pointers_only_symbol_stubs = 0b111,
|
|
zero_fill_on_demand_section = 0b1100,
|
|
only_lazy_pointers_to_lazy_loaded_dylibs = 0b10000,
|
|
};
|
|
|
|
const Flags = packed struct(u16) {
|
|
local_relocations: bool = false,
|
|
external_relocations: bool = false,
|
|
some_machine_instructions: bool = false,
|
|
reserved: u5 = 0,
|
|
reserved2: u1 = 0,
|
|
debug_section: bool = false,
|
|
i386_code_stubs: bool = false,
|
|
live_blocks_if_reference_live_blocks: bool = false,
|
|
no_dead_stripping: bool = false,
|
|
strip_static_symbols_dyldlink_flag: bool = false,
|
|
coalesced_symbols: bool = false,
|
|
only_machine_instructions: bool = false,
|
|
};
|
|
};
|
|
|
|
fn getSize(section_count: u32) u32 {
|
|
return @sizeOf(LoadCommand.Segment64) + section_count * @sizeOf(LoadCommand.Segment64.Section);
|
|
}
|
|
};
|
|
|
|
const LinkeditData = extern struct {
|
|
type: Type,
|
|
size: u32 = 16,
|
|
data_offset: u32,
|
|
data_size: u32,
|
|
};
|
|
|
|
const SymbolTable = extern struct {
|
|
type: Type,
|
|
size: u32 = 24,
|
|
symbol_offset: u32,
|
|
symbol_count: u32,
|
|
string_table_offset: u32,
|
|
string_table_size: u32,
|
|
};
|
|
|
|
const SymbolTableInformation = extern struct {
|
|
type: Type,
|
|
size: u32 = 80,
|
|
local_symbol_index: u32,
|
|
local_symbol_count: u32,
|
|
external_symbol_index: u32,
|
|
external_symbol_count: u32,
|
|
undefined_symbol_index: u32,
|
|
undefined_symbol_count: u32,
|
|
content_table_offset: u32,
|
|
content_table_entry_count: u32,
|
|
module_table_offset: u32,
|
|
module_table_entry_count: u32,
|
|
referenced_symbol_table_offset: u32,
|
|
referenced_symbol_table_entry_count: u32,
|
|
indirect_symbol_table_offset: u32,
|
|
indirect_symbol_table_entry_count: u32,
|
|
external_relocation_offset: u32,
|
|
external_relocation_entry_count: u32,
|
|
local_relocation_offset: u32,
|
|
local_relocation_entry_count: u32,
|
|
};
|
|
|
|
const Dylinker = extern struct {
|
|
type: Type,
|
|
size: u32,
|
|
name_offset: u32 = 12,
|
|
};
|
|
|
|
const Dylib = extern struct {
|
|
type: Type,
|
|
size: u32,
|
|
name_offset: u32,
|
|
timestamp: u32,
|
|
current_version: u32,
|
|
compatibility_version: u32,
|
|
};
|
|
|
|
const Uuid = extern struct {
|
|
type: Type,
|
|
size: u32,
|
|
uuid: [16]u8,
|
|
};
|
|
|
|
const MinimumVersion = extern struct {
|
|
type: Type,
|
|
size: u32,
|
|
version: u32,
|
|
sdk: u32,
|
|
};
|
|
|
|
const SourceVersion = extern struct {
|
|
type: Type,
|
|
size: u32,
|
|
version: u64,
|
|
};
|
|
|
|
const EntryPoint = extern struct {
|
|
type: Type,
|
|
size: u32,
|
|
entry_offset: u64,
|
|
stack_size: u64,
|
|
};
|
|
};
|
|
|
|
const Writer = struct {
|
|
items: []u8,
|
|
index: usize = 0,
|
|
address_offset: usize = 0,
|
|
file_offset: usize = 0,
|
|
load_command_size: u32,
|
|
segment_count: u16,
|
|
segment_index: u16 = 0,
|
|
segment_offset: u16 = @sizeOf(Header),
|
|
linkedit_segment_address_offset: u64 = 0,
|
|
linkedit_segment_file_offset: u64 = 0,
|
|
linkedit_segment_size: u32 = 0,
|
|
|
|
fn getWrittenBytes(writer: *const Writer) []const u8 {
|
|
return writer.items[0..writer.index];
|
|
}
|
|
|
|
fn append(writer: *Writer, bytes: []const u8) void {
|
|
writer.writeBytesAt(bytes, writer.index);
|
|
writer.index += bytes.len;
|
|
}
|
|
|
|
fn writeBytesAt(writer: *Writer, bytes: []const u8, offset: usize) void {
|
|
@memcpy(writer.items[offset..][0..bytes.len], bytes);
|
|
}
|
|
|
|
const SegmentCreation = struct {
|
|
name: []const u8,
|
|
sections: []const SectionCreation,
|
|
protection: LoadCommand.Segment64.VirtualMemoryProtection,
|
|
};
|
|
|
|
const SectionCreation = struct {
|
|
name: []const u8,
|
|
bytes: []const u8,
|
|
alignment: u32 = 1,
|
|
flags: LoadCommand.Segment64.Section.Flags,
|
|
};
|
|
|
|
fn writeSegment(writer: *Writer, descriptor: SegmentCreation) void {
|
|
assert(writer.segment_index < writer.segment_count);
|
|
defer writer.segment_index += 1;
|
|
|
|
const segment_name = blk: {
|
|
var result = [1]u8{0} ** 16;
|
|
@memcpy(result[0..descriptor.name.len], descriptor.name);
|
|
break :blk result;
|
|
};
|
|
|
|
if (equal(u8, descriptor.name, "__PAGEZERO")) {
|
|
assert(writer.segment_offset == @sizeOf(Header));
|
|
const address_size = 4 * 1024 * 1024 * 1024;
|
|
writer.writeBytesAt(std.mem.asBytes(&LoadCommand.Segment64{
|
|
.size = @sizeOf(LoadCommand.Segment64),
|
|
.name = segment_name,
|
|
.address = 0,
|
|
.address_size = address_size,
|
|
.file_offset = 0,
|
|
.file_size = 0,
|
|
.maximum_virtual_memory_protections = descriptor.protection,
|
|
.initial_virtual_memory_protections = descriptor.protection,
|
|
.section_count = @intCast(descriptor.sections.len),
|
|
.flags = .{},
|
|
}), writer.segment_offset);
|
|
|
|
writer.address_offset += address_size;
|
|
writer.segment_offset += @sizeOf(LoadCommand.Segment64);
|
|
} else if (equal(u8, descriptor.name, "__TEXT")) {
|
|
const original_offset = writer.segment_offset;
|
|
assert(original_offset == @sizeOf(Header) + @sizeOf(LoadCommand.Segment64));
|
|
writer.segment_offset += @sizeOf(LoadCommand.Segment64);
|
|
|
|
const text_metadata_offset = @sizeOf(Header) + writer.load_command_size;
|
|
var section_address_offset = writer.address_offset + text_metadata_offset;
|
|
var section_file_offset = writer.file_offset + text_metadata_offset;
|
|
|
|
for (descriptor.sections) |section| {
|
|
section_address_offset = std.mem.alignForward(usize, section_address_offset, section.alignment);
|
|
section_file_offset = std.mem.alignForward(usize, section_file_offset, section.alignment);
|
|
|
|
writer.writeBytesAt(std.mem.asBytes(&LoadCommand.Segment64.Section{
|
|
.name = blk: {
|
|
var result = [1]u8{0} ** 16;
|
|
@memcpy(result[0..section.name.len], section.name);
|
|
break :blk result;
|
|
},
|
|
.segment_name = segment_name,
|
|
.address = section_address_offset,
|
|
.size = section.bytes.len,
|
|
.file_offset = @intCast(section_file_offset),
|
|
.alignment = std.math.log2(section.alignment),
|
|
.relocation_file_offset = 0,
|
|
.relocation_count = 0,
|
|
.type = .regular,
|
|
.flags = section.flags,
|
|
}), writer.segment_offset);
|
|
|
|
@memcpy(writer.items[section_file_offset..][0..section.bytes.len], section.bytes);
|
|
|
|
section_address_offset += section.bytes.len;
|
|
section_file_offset += section.bytes.len;
|
|
|
|
writer.segment_offset += @sizeOf(LoadCommand.Segment64.Section);
|
|
}
|
|
|
|
const end_segment_offset = writer.segment_offset;
|
|
writer.segment_offset = original_offset;
|
|
|
|
const size = end_segment_offset - writer.file_offset;
|
|
const aligned_size = std.mem.alignForward(usize, size, 16 * 1024);
|
|
|
|
writer.append(std.mem.asBytes(&LoadCommand.Segment64{
|
|
.size = @sizeOf(LoadCommand.Segment64),
|
|
.name = segment_name,
|
|
.address = writer.address_offset,
|
|
.address_size = aligned_size,
|
|
.file_offset = writer.file_offset,
|
|
.file_size = aligned_size,
|
|
.maximum_virtual_memory_protections = descriptor.protection,
|
|
.initial_virtual_memory_protections = descriptor.protection,
|
|
.section_count = @intCast(descriptor.sections.len),
|
|
.flags = .{},
|
|
}));
|
|
|
|
writer.segment_offset = end_segment_offset;
|
|
|
|
writer.address_offset += aligned_size;
|
|
writer.file_offset += aligned_size;
|
|
} else {
|
|
unreachable;
|
|
}
|
|
}
|
|
|
|
fn writeLinkeditData(writer: *Writer, bytes: []const u8, load_command_type: LoadCommand.Type) void {
|
|
if (writer.linkedit_segment_size == 0) {
|
|
writer.linkedit_segment_address_offset = writer.address_offset;
|
|
writer.linkedit_segment_file_offset = writer.file_offset;
|
|
}
|
|
|
|
const data_size: u32 = @intCast(bytes.len);
|
|
@memcpy(writer.items[writer.file_offset..][0..data_size], bytes);
|
|
|
|
writer.append(std.mem.asBytes(&LoadCommand.LinkeditData{
|
|
.type = load_command_type,
|
|
.data_offset = @intCast(writer.linkedit_segment_file_offset),
|
|
.data_size = data_size,
|
|
}));
|
|
|
|
writer.address_offset += data_size;
|
|
writer.file_offset += data_size;
|
|
|
|
writer.linkedit_segment_size += data_size;
|
|
}
|
|
};
|
|
|
|
pub fn interpretFile(allocator: Allocator, descriptor: Compilation.Module.Descriptor, file: []const u8) !void {
|
|
_ = allocator;
|
|
_ = descriptor;
|
|
const header: *const Header = @ptrCast(@alignCast(file.ptr));
|
|
//print("Header : {}", .{header});
|
|
assert(header.magic == Header.magic);
|
|
|
|
var text_segment: LoadCommand.Segment64 = undefined;
|
|
const load_command_start: *const LoadCommand = @ptrCast(@alignCast(file[@sizeOf(Header)..].ptr));
|
|
var load_command_ptr = load_command_start;
|
|
|
|
for (0..header.load_command_count) |_| {
|
|
const load_command = load_command_ptr.*;
|
|
switch (load_command.type) {
|
|
.segment64 => {
|
|
const segment_load_command: *const LoadCommand.Segment64 = @ptrCast(@alignCast(load_command_ptr));
|
|
const text_segment_name = "__TEXT";
|
|
if (equal(u8, segment_load_command.name[0..text_segment_name.len], text_segment_name)) {
|
|
text_segment = segment_load_command.*;
|
|
}
|
|
//print("SLC: {}", .{segment_load_command});
|
|
//print("segment name: {s}", .{segment_load_command.name});
|
|
const section_ptr: [*]const LoadCommand.Segment64.Section = @ptrFromInt(@intFromPtr(segment_load_command) + @sizeOf(LoadCommand.Segment64));
|
|
const sections = section_ptr[0..segment_load_command.section_count];
|
|
for (sections) |section| {
|
|
_ = section;
|
|
//print("{}", .{section});
|
|
//print("Section name: {s}. Segment name: {s}", .{ section.name, section.segment_name });
|
|
}
|
|
},
|
|
.dyld_chained_fixups => {
|
|
const command: *const LoadCommand.LinkeditData = @ptrCast(@alignCast(load_command_ptr));
|
|
_ = command;
|
|
//print("command: {}", .{command});
|
|
},
|
|
.dyld_exports_trie => {
|
|
const command: *const LoadCommand.LinkeditData = @ptrCast(@alignCast(load_command_ptr));
|
|
_ = command;
|
|
//print("command: {}", .{command});
|
|
},
|
|
.symbol_table => {
|
|
const command: *const LoadCommand.SymbolTable = @ptrCast(@alignCast(load_command_ptr));
|
|
_ = command;
|
|
//print("command: {}", .{command});
|
|
},
|
|
.symbol_table_information => {
|
|
const command: *const LoadCommand.SymbolTableInformation = @ptrCast(@alignCast(load_command_ptr));
|
|
_ = command;
|
|
//print("command: {}", .{command});
|
|
},
|
|
.load_dylinker => {
|
|
const command: *const LoadCommand.Dylinker = @ptrCast(@alignCast(load_command_ptr));
|
|
//print("command: {}", .{command});
|
|
const name: [*:0]const u8 = @ptrFromInt(@intFromPtr(command) + command.name_offset);
|
|
_ = name;
|
|
//print("Name: {s}", .{name});
|
|
},
|
|
.uuid_number => {
|
|
const command: *const LoadCommand.Uuid = @ptrCast(@alignCast(load_command_ptr));
|
|
_ = command;
|
|
//print("command: {}", .{command});
|
|
},
|
|
.minimum_os_version => {
|
|
const command: *const LoadCommand.MinimumVersion = @ptrCast(@alignCast(load_command_ptr));
|
|
_ = command;
|
|
//print("command: {}", .{command});
|
|
},
|
|
.source_version => {
|
|
const command: *const LoadCommand.SourceVersion = @ptrCast(@alignCast(load_command_ptr));
|
|
_ = command;
|
|
//print("command: {}", .{command});
|
|
},
|
|
.dyld_main_entry_point => {
|
|
const command: *const LoadCommand.EntryPoint = @ptrCast(@alignCast(load_command_ptr));
|
|
_ = command;
|
|
//print("command: {}", .{command});
|
|
},
|
|
.load_dylib => {
|
|
const command: *const LoadCommand.Dylib = @ptrCast(@alignCast(load_command_ptr));
|
|
_ = command;
|
|
//print("command: {}", .{command});
|
|
//print("Dylib: {s}", .{@as([*:0]const u8, @ptrFromInt(@intFromPtr(load_command_ptr) + @sizeOf(LoadCommand.Dylib)))});
|
|
},
|
|
.function_starts => {
|
|
const command: *const LoadCommand.LinkeditData = @ptrCast(@alignCast(load_command_ptr));
|
|
_ = command;
|
|
//print("command: {}", .{command});
|
|
},
|
|
.data_in_code => {
|
|
const command: *const LoadCommand.LinkeditData = @ptrCast(@alignCast(load_command_ptr));
|
|
_ = command;
|
|
//print("command: {}", .{command});
|
|
},
|
|
.code_signature => {
|
|
const command: *const LoadCommand.LinkeditData = @ptrCast(@alignCast(load_command_ptr));
|
|
_ = command;
|
|
//print("command: {}", .{command});
|
|
},
|
|
else => |t| @panic(@tagName(t)),
|
|
}
|
|
|
|
load_command_ptr = @ptrFromInt(@intFromPtr(load_command_ptr) + load_command.size);
|
|
}
|
|
|
|
// const load_command_end = load_command_ptr;
|
|
// const load_command_size = @intFromPtr(load_command_end) - @intFromPtr(load_command_start);
|
|
// assert(load_command_size == header.load_command_size);
|
|
|
|
const segment_count = 3;
|
|
var writer = Writer{
|
|
.items = try mmap(0x100000, .{}),
|
|
.load_command_size = segment_count * @sizeOf(LoadCommand.Segment64) +
|
|
2 * @sizeOf(LoadCommand.Segment64.Section) +
|
|
@sizeOf(LoadCommand.LinkeditData) +
|
|
@sizeOf(LoadCommand.LinkeditData) +
|
|
@sizeOf(LoadCommand.SymbolTable) +
|
|
@sizeOf(LoadCommand.SymbolTableInformation) +
|
|
@sizeOf(LoadCommand.Dylinker) + std.mem.alignForward(u32, "/usr/lib/dyld".len, 8) +
|
|
@sizeOf(LoadCommand.Uuid) +
|
|
@sizeOf(LoadCommand.MinimumVersion) +
|
|
@sizeOf(LoadCommand.EntryPoint) +
|
|
@sizeOf(LoadCommand.Dylib) + std.mem.alignForward(u32, "/usr/lib/libSystem.B.dylib".len, 8) +
|
|
3 * @sizeOf(LoadCommand.LinkeditData),
|
|
.segment_count = segment_count,
|
|
};
|
|
writer.index = @sizeOf(Header);
|
|
writer.writeSegment(.{
|
|
.name = "__PAGEZERO",
|
|
.sections = &.{},
|
|
.protection = .{
|
|
.read = false,
|
|
.write = false,
|
|
.execute = false,
|
|
},
|
|
});
|
|
writer.writeSegment(.{
|
|
.name = "__TEXT",
|
|
.sections = &.{
|
|
.{
|
|
.name = "__text",
|
|
.bytes = &.{
|
|
0x00, 0x00, 0x80, 0x52,
|
|
0xc0, 0x03, 0x5f, 0xd6,
|
|
},
|
|
.alignment = 4,
|
|
.flags = .{
|
|
.only_machine_instructions = true,
|
|
},
|
|
},
|
|
.{
|
|
.name = "__unwind_info",
|
|
.bytes = &.{
|
|
0x01, 0x00, 0x00, 0x00,
|
|
0x1c, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00,
|
|
0x1c, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00,
|
|
0x1c, 0x00, 0x00, 0x00,
|
|
0x02, 0x00, 0x00, 0x00,
|
|
0xb0, 0x3f, 0x00, 0x00,
|
|
0x34, 0x00, 0x00, 0x00,
|
|
0x34, 0x00, 0x00, 0x00,
|
|
0xb9, 0x3f, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00,
|
|
0x34, 0x00, 0x00, 0x00,
|
|
0x03, 0x00, 0x00, 0x00,
|
|
0x0c, 0x00, 0x01, 0x00,
|
|
0x10, 0x00, 0x01, 0x00,
|
|
0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x02,
|
|
},
|
|
.alignment = 4,
|
|
.flags = .{},
|
|
},
|
|
},
|
|
.protection = .{
|
|
.read = true,
|
|
.write = false,
|
|
.execute = true,
|
|
},
|
|
});
|
|
|
|
// TODO: write this later
|
|
|
|
// writer.writeSegment(.{
|
|
// .name = "__LINKEDIT",
|
|
// .sections = &.{},
|
|
// .protection = .{
|
|
// .read = true,
|
|
// .write = false,
|
|
// .execute = false,
|
|
// },
|
|
// });
|
|
assert(writer.segment_index == writer.segment_count - 1);
|
|
writer.index = writer.segment_offset + @sizeOf(LoadCommand.Segment64);
|
|
|
|
for (file[16384 + 56 ..][0..48]) |b| {
|
|
_ = b;
|
|
//print("0x{x}, ", .{b});
|
|
}
|
|
|
|
const chained_fixup_bytes = &.{ 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
|
|
writer.writeLinkeditData(chained_fixup_bytes, .dyld_chained_fixups);
|
|
const export_trie_bytes = &.{ 0x0, 0x1, 0x5f, 0x0, 0x9, 0x2, 0x0, 0x0, 0x0, 0x0, 0x2, 0x5f, 0x6d, 0x68, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x0, 0x5, 0x6d, 0x61, 0x69, 0x6e, 0x0, 0x25, 0x3, 0x0, 0xb0, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
|
|
writer.writeLinkeditData(export_trie_bytes, .dyld_exports_trie);
|
|
unreachable;
|
|
// writer.writeSymbolTable(
|
|
}
|
|
|
|
// .bytes = &.{
|
|
// 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5f, 0x0, 0x9, 0x2, 0x0, 0x0, 0x0, 0x0, 0x2, 0x5f, 0x6d, 0x68, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x0, 0x5, 0x6d, 0x61, 0x69, 0x6e, 0x0, 0x25, 0x3, 0x0, 0xb0, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb0, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0xf, 0x1, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xf, 0x1, 0x0, 0x0, 0xb0, 0x3f, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x20, 0x0, 0x5f, 0x5f, 0x6d, 0x68, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x0, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa, 0xde, 0xc, 0xc0, 0x0, 0x0, 0x1, 0x11, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0xfa, 0xde, 0xc, 0x2, 0x0, 0x0, 0x0, 0xfd, 0x0, 0x2, 0x4, 0x0, 0x0, 0x2, 0x0, 0x2, 0x0, 0x0, 0x0, 0x5d, 0x0, 0x0, 0x0, 0x58, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x40, 0xb0, 0x20, 0x2, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6d, 0x61, 0x69, 0x6e, 0x0, 0xb2, 0x2a, 0x3, 0x79, 0x1b, 0x82, 0xf4, 0x71, 0xf1, 0xae, 0xfa, 0x44, 0x53, 0xe0, 0xc2, 0x78, 0x1e, 0x56, 0xd1, 0x9b, 0x36, 0x37, 0x7b, 0x7e, 0x61, 0xf5, 0x8a, 0x59, 0xc4, 0xf0, 0x64, 0x56, 0xad, 0x7f, 0xac, 0xb2, 0x58, 0x6f, 0xc6, 0xe9, 0x66, 0xc0, 0x4, 0xd7, 0xd1, 0xd1, 0x6b, 0x2, 0x4f, 0x58, 0x5, 0xff, 0x7c, 0xb4, 0x7c, 0x7a, 0x85, 0xda, 0xbd, 0x8b, 0x48, 0x89, 0x2c, 0xa7, 0xad, 0x7f, 0xac, 0xb2, 0x58, 0x6f, 0xc6, 0xe9, 0x66, 0xc0, 0x4, 0xd7, 0xd1, 0xd1, 0x6b, 0x2, 0x4f, 0x58, 0x5, 0xff, 0x7c, 0xb4, 0x7c, 0x7a, 0x85, 0xda, 0xbd, 0x8b, 0x48, 0x89, 0x2c, 0xa7, 0x8, 0xdb, 0xee, 0xf5, 0x95, 0x71, 0x3e, 0xcb, 0x29, 0xff, 0x3f, 0x28, 0x46, 0xf0, 0xdc, 0x97, 0xbf, 0x2d, 0x3, 0xf2, 0xec, 0xc, 0x84, 0xa, 0x44, 0x90, 0xf, 0xe0, 0xf4, 0xea, 0x67, 0x97, 0x6b, 0xb0, 0x22, 0x2, 0x0, 0xa7, 0xed, 0x94, 0xb2, 0x3d, 0x86, 0x4d, 0x13, 0xd6, 0xa4, 0xe, 0x1c, 0x1a, 0x6b, 0x9b, 0x82, 0xa0, 0xeb, 0x28, 0x23, 0xfe, 0x8a, 0x51, 0x2a, 0xe5, 0xf9, 0x39,
|
|
// },
|