authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-16 19:15:04+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-16 19:15:04+02:00
loga51edc978f90fa3b96e4b1d4886030848f97a7b0
treed41aefb6f0a64379ed263394ce45cf96986a9917
parent4c90c1ff63883c2bb8d2baa40e952674daba6814

macho: converge populateMetadata with populateMissingMetadata


1 files changed, 127 insertions(+), 420 deletions(-)

src/link/MachO.zig+127-420
......@@ -386,6 +386,36 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
386386 try self.populateMissingMetadata();
387387 try self.writeLocalSymbol(0);
388388
389 if (!self.strtab_dir.containsAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{
390 .strtab = &self.strtab,
391 })) {
392 const import_sym_index = @intCast(u32, self.undefs.items.len);
393 const n_strx = try self.makeString("dyld_stub_binder");
394 try self.undefs.append(self.base.allocator, .{
395 .n_strx = n_strx,
396 .n_type = macho.N_UNDF | macho.N_EXT,
397 .n_sect = 0,
398 .n_desc = @intCast(u8, 1) * macho.N_SYMBOL_RESOLVER,
399 .n_value = 0,
400 });
401 try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{
402 .where = .undef,
403 .where_index = import_sym_index,
404 });
405 const got_key = GotIndirectionKey{
406 .where = .undef,
407 .where_index = import_sym_index,
408 };
409 const got_index = @intCast(u32, self.got_entries.items.len);
410 try self.got_entries.append(self.base.allocator, got_key);
411 try self.got_entries_map.putNoClobber(self.base.allocator, got_key, got_index);
412 try self.writeGotEntry(got_index);
413 self.binding_info_dirty = true;
414 }
415 if (self.stub_helper_stubs_start_off == null) {
416 try self.writeStubHelperPreamble();
417 }
418
389419 if (self.d_sym) |*ds| {
390420 try ds.populateMissingMetadata(allocator);
391421 try ds.writeLocalSymbol(0);
......@@ -556,7 +586,7 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
556586 .read = true,
557587 .mode = link.determineMode(self.base.options),
558588 });
559 try self.populateMetadata();
589 try self.populateMissingMetadata();
560590
561591 // TODO mimicking insertion of null symbol from incremental linker.
562592 // This will need to moved.
......@@ -798,6 +828,17 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
798828 try self.allocateTextBlocks();
799829 try self.flushZld();
800830 } else {
831 // TODO this is just a temp; libsystem load command will be autoresolved when parsing libSystem from
832 // the linker line and actually referencing symbols.
833 if (self.libsystem_cmd_index == null) {
834 self.libsystem_cmd_index = @intCast(u16, self.load_commands.items.len);
835 var dylib_cmd = try commands.createLoadDylibCommand(self.base.allocator, mem.spanZ(LIB_SYSTEM_PATH), 2, 0, 0);
836 errdefer dylib_cmd.deinit(self.base.allocator);
837 try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd });
838 self.load_commands_dirty = true;
839 }
840 try self.addDataInCodeLC();
841 try self.addCodeSignatureLC();
801842 try self.flushModule(comp);
802843 }
803844 }
......@@ -2503,328 +2544,6 @@ fn parseTextBlocks(self: *MachO) !void {
25032544 }
25042545}
25052546
2506fn populateMetadata(self: *MachO) !void {
2507 if (self.pagezero_segment_cmd_index == null) {
2508 self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
2509 try self.load_commands.append(self.base.allocator, .{
2510 .Segment = SegmentCommand.empty("__PAGEZERO", .{
2511 .vmsize = 0x100000000, // size always set to 4GB
2512 }),
2513 });
2514 }
2515
2516 if (self.text_segment_cmd_index == null) {
2517 self.text_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
2518 try self.load_commands.append(self.base.allocator, .{
2519 .Segment = SegmentCommand.empty("__TEXT", .{
2520 .vmaddr = 0x100000000, // always starts at 4GB
2521 .maxprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE,
2522 .initprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE,
2523 }),
2524 });
2525 }
2526
2527 if (self.text_section_index == null) {
2528 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2529 self.text_section_index = @intCast(u16, text_seg.sections.items.len);
2530 const alignment: u2 = switch (self.base.options.target.cpu.arch) {
2531 .x86_64 => 0,
2532 .aarch64 => 2,
2533 else => unreachable, // unhandled architecture type
2534 };
2535 try text_seg.addSection(self.base.allocator, "__text", .{
2536 .@"align" = alignment,
2537 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
2538 });
2539 _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
2540 .seg = self.text_segment_cmd_index.?,
2541 .sect = self.text_section_index.?,
2542 });
2543 }
2544
2545 if (self.stubs_section_index == null) {
2546 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2547 self.stubs_section_index = @intCast(u16, text_seg.sections.items.len);
2548 const alignment: u2 = switch (self.base.options.target.cpu.arch) {
2549 .x86_64 => 0,
2550 .aarch64 => 2,
2551 else => unreachable, // unhandled architecture type
2552 };
2553 const stub_size: u4 = switch (self.base.options.target.cpu.arch) {
2554 .x86_64 => 6,
2555 .aarch64 => 3 * @sizeOf(u32),
2556 else => unreachable, // unhandled architecture type
2557 };
2558 try text_seg.addSection(self.base.allocator, "__stubs", .{
2559 .@"align" = alignment,
2560 .flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
2561 .reserved2 = stub_size,
2562 });
2563 _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
2564 .seg = self.text_segment_cmd_index.?,
2565 .sect = self.stubs_section_index.?,
2566 });
2567 }
2568
2569 if (self.stub_helper_section_index == null) {
2570 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2571 self.stub_helper_section_index = @intCast(u16, text_seg.sections.items.len);
2572 const alignment: u2 = switch (self.base.options.target.cpu.arch) {
2573 .x86_64 => 0,
2574 .aarch64 => 2,
2575 else => unreachable, // unhandled architecture type
2576 };
2577 const stub_helper_size: u6 = switch (self.base.options.target.cpu.arch) {
2578 .x86_64 => 15,
2579 .aarch64 => 6 * @sizeOf(u32),
2580 else => unreachable,
2581 };
2582 try text_seg.addSection(self.base.allocator, "__stub_helper", .{
2583 .size = stub_helper_size,
2584 .@"align" = alignment,
2585 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
2586 });
2587 _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
2588 .seg = self.text_segment_cmd_index.?,
2589 .sect = self.stub_helper_section_index.?,
2590 });
2591 }
2592
2593 if (self.data_const_segment_cmd_index == null) {
2594 self.data_const_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
2595 try self.load_commands.append(self.base.allocator, .{
2596 .Segment = SegmentCommand.empty("__DATA_CONST", .{
2597 .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
2598 .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
2599 }),
2600 });
2601 }
2602
2603 if (self.got_section_index == null) {
2604 const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
2605 self.got_section_index = @intCast(u16, data_const_seg.sections.items.len);
2606 try data_const_seg.addSection(self.base.allocator, "__got", .{
2607 .@"align" = 3, // 2^3 = @sizeOf(u64)
2608 .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
2609 });
2610 _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
2611 .seg = self.data_const_segment_cmd_index.?,
2612 .sect = self.got_section_index.?,
2613 });
2614 }
2615
2616 if (self.data_segment_cmd_index == null) {
2617 self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
2618 try self.load_commands.append(self.base.allocator, .{
2619 .Segment = SegmentCommand.empty("__DATA", .{
2620 .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
2621 .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
2622 }),
2623 });
2624 }
2625
2626 if (self.la_symbol_ptr_section_index == null) {
2627 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2628 self.la_symbol_ptr_section_index = @intCast(u16, data_seg.sections.items.len);
2629 try data_seg.addSection(self.base.allocator, "__la_symbol_ptr", .{
2630 .@"align" = 3, // 2^3 = @sizeOf(u64)
2631 .flags = macho.S_LAZY_SYMBOL_POINTERS,
2632 });
2633 _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
2634 .seg = self.data_segment_cmd_index.?,
2635 .sect = self.la_symbol_ptr_section_index.?,
2636 });
2637 }
2638
2639 if (self.data_section_index == null) {
2640 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2641 self.data_section_index = @intCast(u16, data_seg.sections.items.len);
2642 try data_seg.addSection(self.base.allocator, "__data", .{
2643 .@"align" = 3, // 2^3 = @sizeOf(u64)
2644 });
2645 _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
2646 .seg = self.data_segment_cmd_index.?,
2647 .sect = self.data_section_index.?,
2648 });
2649 }
2650
2651 if (self.linkedit_segment_cmd_index == null) {
2652 self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
2653 try self.load_commands.append(self.base.allocator, .{
2654 .Segment = SegmentCommand.empty("__LINKEDIT", .{
2655 .maxprot = macho.VM_PROT_READ,
2656 .initprot = macho.VM_PROT_READ,
2657 }),
2658 });
2659 }
2660
2661 if (self.dyld_info_cmd_index == null) {
2662 self.dyld_info_cmd_index = @intCast(u16, self.load_commands.items.len);
2663 try self.load_commands.append(self.base.allocator, .{
2664 .DyldInfoOnly = .{
2665 .cmd = macho.LC_DYLD_INFO_ONLY,
2666 .cmdsize = @sizeOf(macho.dyld_info_command),
2667 .rebase_off = 0,
2668 .rebase_size = 0,
2669 .bind_off = 0,
2670 .bind_size = 0,
2671 .weak_bind_off = 0,
2672 .weak_bind_size = 0,
2673 .lazy_bind_off = 0,
2674 .lazy_bind_size = 0,
2675 .export_off = 0,
2676 .export_size = 0,
2677 },
2678 });
2679 }
2680
2681 if (self.symtab_cmd_index == null) {
2682 self.symtab_cmd_index = @intCast(u16, self.load_commands.items.len);
2683 try self.load_commands.append(self.base.allocator, .{
2684 .Symtab = .{
2685 .cmd = macho.LC_SYMTAB,
2686 .cmdsize = @sizeOf(macho.symtab_command),
2687 .symoff = 0,
2688 .nsyms = 0,
2689 .stroff = 0,
2690 .strsize = 0,
2691 },
2692 });
2693 }
2694
2695 if (self.dysymtab_cmd_index == null) {
2696 self.dysymtab_cmd_index = @intCast(u16, self.load_commands.items.len);
2697 try self.load_commands.append(self.base.allocator, .{
2698 .Dysymtab = .{
2699 .cmd = macho.LC_DYSYMTAB,
2700 .cmdsize = @sizeOf(macho.dysymtab_command),
2701 .ilocalsym = 0,
2702 .nlocalsym = 0,
2703 .iextdefsym = 0,
2704 .nextdefsym = 0,
2705 .iundefsym = 0,
2706 .nundefsym = 0,
2707 .tocoff = 0,
2708 .ntoc = 0,
2709 .modtaboff = 0,
2710 .nmodtab = 0,
2711 .extrefsymoff = 0,
2712 .nextrefsyms = 0,
2713 .indirectsymoff = 0,
2714 .nindirectsyms = 0,
2715 .extreloff = 0,
2716 .nextrel = 0,
2717 .locreloff = 0,
2718 .nlocrel = 0,
2719 },
2720 });
2721 }
2722
2723 if (self.dylinker_cmd_index == null) {
2724 self.dylinker_cmd_index = @intCast(u16, self.load_commands.items.len);
2725 const cmdsize = @intCast(u32, mem.alignForwardGeneric(
2726 u64,
2727 @sizeOf(macho.dylinker_command) + mem.lenZ(DEFAULT_DYLD_PATH),
2728 @sizeOf(u64),
2729 ));
2730 var dylinker_cmd = commands.emptyGenericCommandWithData(macho.dylinker_command{
2731 .cmd = macho.LC_LOAD_DYLINKER,
2732 .cmdsize = cmdsize,
2733 .name = @sizeOf(macho.dylinker_command),
2734 });
2735 dylinker_cmd.data = try self.base.allocator.alloc(u8, cmdsize - dylinker_cmd.inner.name);
2736 mem.set(u8, dylinker_cmd.data, 0);
2737 mem.copy(u8, dylinker_cmd.data, mem.spanZ(DEFAULT_DYLD_PATH));
2738 try self.load_commands.append(self.base.allocator, .{ .Dylinker = dylinker_cmd });
2739 }
2740
2741 if (self.main_cmd_index == null and self.base.options.output_mode == .Exe) {
2742 self.main_cmd_index = @intCast(u16, self.load_commands.items.len);
2743 try self.load_commands.append(self.base.allocator, .{
2744 .Main = .{
2745 .cmd = macho.LC_MAIN,
2746 .cmdsize = @sizeOf(macho.entry_point_command),
2747 .entryoff = 0x0,
2748 .stacksize = 0,
2749 },
2750 });
2751 }
2752
2753 if (self.dylib_id_cmd_index == null and self.base.options.output_mode == .Lib) {
2754 self.dylib_id_cmd_index = @intCast(u16, self.load_commands.items.len);
2755 const install_name = try std.fmt.allocPrint(self.base.allocator, "@rpath/{s}", .{
2756 self.base.options.emit.?.sub_path,
2757 });
2758 defer self.base.allocator.free(install_name);
2759 var dylib_cmd = try commands.createLoadDylibCommand(
2760 self.base.allocator,
2761 install_name,
2762 2,
2763 0x10000, // TODO forward user-provided versions
2764 0x10000,
2765 );
2766 errdefer dylib_cmd.deinit(self.base.allocator);
2767 dylib_cmd.inner.cmd = macho.LC_ID_DYLIB;
2768 try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd });
2769 }
2770
2771 if (self.source_version_cmd_index == null) {
2772 self.source_version_cmd_index = @intCast(u16, self.load_commands.items.len);
2773 try self.load_commands.append(self.base.allocator, .{
2774 .SourceVersion = .{
2775 .cmd = macho.LC_SOURCE_VERSION,
2776 .cmdsize = @sizeOf(macho.source_version_command),
2777 .version = 0x0,
2778 },
2779 });
2780 }
2781
2782 if (self.build_version_cmd_index == null) {
2783 self.build_version_cmd_index = @intCast(u16, self.load_commands.items.len);
2784 const cmdsize = @intCast(u32, mem.alignForwardGeneric(
2785 u64,
2786 @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version),
2787 @sizeOf(u64),
2788 ));
2789 const ver = self.base.options.target.os.version_range.semver.min;
2790 const version = ver.major << 16 | ver.minor << 8 | ver.patch;
2791 const is_simulator_abi = self.base.options.target.abi == .simulator;
2792 var cmd = commands.emptyGenericCommandWithData(macho.build_version_command{
2793 .cmd = macho.LC_BUILD_VERSION,
2794 .cmdsize = cmdsize,
2795 .platform = switch (self.base.options.target.os.tag) {
2796 .macos => macho.PLATFORM_MACOS,
2797 .ios => if (is_simulator_abi) macho.PLATFORM_IOSSIMULATOR else macho.PLATFORM_IOS,
2798 .watchos => if (is_simulator_abi) macho.PLATFORM_WATCHOSSIMULATOR else macho.PLATFORM_WATCHOS,
2799 .tvos => if (is_simulator_abi) macho.PLATFORM_TVOSSIMULATOR else macho.PLATFORM_TVOS,
2800 else => unreachable,
2801 },
2802 .minos = version,
2803 .sdk = version,
2804 .ntools = 1,
2805 });
2806 const ld_ver = macho.build_tool_version{
2807 .tool = macho.TOOL_LD,
2808 .version = 0x0,
2809 };
2810 cmd.data = try self.base.allocator.alloc(u8, cmdsize - @sizeOf(macho.build_version_command));
2811 mem.set(u8, cmd.data, 0);
2812 mem.copy(u8, cmd.data, mem.asBytes(&ld_ver));
2813 try self.load_commands.append(self.base.allocator, .{ .BuildVersion = cmd });
2814 }
2815
2816 if (self.uuid_cmd_index == null) {
2817 self.uuid_cmd_index = @intCast(u16, self.load_commands.items.len);
2818 var uuid_cmd: macho.uuid_command = .{
2819 .cmd = macho.LC_UUID,
2820 .cmdsize = @sizeOf(macho.uuid_command),
2821 .uuid = undefined,
2822 };
2823 std.crypto.random.bytes(&uuid_cmd.uuid);
2824 try self.load_commands.append(self.base.allocator, .{ .Uuid = uuid_cmd });
2825 }
2826}
2827
28282547fn addDataInCodeLC(self: *MachO) !void {
28292548 if (self.data_in_code_cmd_index == null) {
28302549 self.data_in_code_cmd_index = @intCast(u16, self.load_commands.items.len);
......@@ -4004,12 +3723,6 @@ pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl) u64 {
40043723}
40053724
40063725pub fn populateMissingMetadata(self: *MachO) !void {
4007 switch (self.base.options.output_mode) {
4008 .Exe => {},
4009 .Obj => return error.TODOImplementWritingObjFiles,
4010 .Lib => return error.TODOImplementWritingLibFiles,
4011 }
4012
40133726 if (self.pagezero_segment_cmd_index == null) {
40143727 self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
40153728 try self.load_commands.append(self.base.allocator, .{
......@@ -4019,11 +3732,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {
40193732 });
40203733 self.load_commands_dirty = true;
40213734 }
3735
40223736 if (self.text_segment_cmd_index == null) {
40233737 self.text_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
4024 const maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE | macho.VM_PROT_EXECUTE;
4025 const initprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE;
4026
40273738 const program_code_size_hint = self.base.options.program_code_size_hint;
40283739 const got_size_hint = @sizeOf(u64) * self.base.options.symbol_count_hint;
40293740 const ideal_size = self.header_pad + program_code_size_hint + 3 * got_size_hint;
......@@ -4036,12 +3747,13 @@ pub fn populateMissingMetadata(self: *MachO) !void {
40363747 .vmaddr = 0x100000000, // always starts at 4GB
40373748 .vmsize = needed_size,
40383749 .filesize = needed_size,
4039 .maxprot = maxprot,
4040 .initprot = initprot,
3750 .maxprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE,
3751 .initprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE,
40413752 }),
40423753 });
40433754 self.load_commands_dirty = true;
40443755 }
3756
40453757 if (self.text_section_index == null) {
40463758 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
40473759 self.text_section_index = @intCast(u16, text_segment.sections.items.len);
......@@ -4051,7 +3763,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
40513763 .aarch64 => 2,
40523764 else => unreachable, // unhandled architecture type
40533765 };
4054 const flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS;
40553766 const needed_size = self.base.options.program_code_size_hint;
40563767 const off = text_segment.findFreeSpace(needed_size, @as(u16, 1) << alignment, self.header_pad);
40573768
......@@ -4062,10 +3773,15 @@ pub fn populateMissingMetadata(self: *MachO) !void {
40623773 .size = @intCast(u32, needed_size),
40633774 .offset = @intCast(u32, off),
40643775 .@"align" = alignment,
4065 .flags = flags,
3776 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
3777 });
3778 _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
3779 .seg = self.text_segment_cmd_index.?,
3780 .sect = self.text_section_index.?,
40663781 });
40673782 self.load_commands_dirty = true;
40683783 }
3784
40693785 if (self.stubs_section_index == null) {
40703786 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
40713787 self.stubs_section_index = @intCast(u16, text_segment.sections.items.len);
......@@ -4080,7 +3796,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
40803796 .aarch64 => 3 * @sizeOf(u32),
40813797 else => unreachable, // unhandled architecture type
40823798 };
4083 const flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS;
40843799 const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
40853800 const off = text_segment.findFreeSpace(needed_size, @alignOf(u64), self.header_pad);
40863801 assert(off + needed_size <= text_segment.inner.fileoff + text_segment.inner.filesize); // TODO Must expand __TEXT segment.
......@@ -4092,11 +3807,16 @@ pub fn populateMissingMetadata(self: *MachO) !void {
40923807 .size = needed_size,
40933808 .offset = @intCast(u32, off),
40943809 .@"align" = alignment,
4095 .flags = flags,
3810 .flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
40963811 .reserved2 = stub_size,
40973812 });
3813 _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
3814 .seg = self.text_segment_cmd_index.?,
3815 .sect = self.stubs_section_index.?,
3816 });
40983817 self.load_commands_dirty = true;
40993818 }
3819
41003820 if (self.stub_helper_section_index == null) {
41013821 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
41023822 self.stub_helper_section_index = @intCast(u16, text_segment.sections.items.len);
......@@ -4106,7 +3826,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
41063826 .aarch64 => 2,
41073827 else => unreachable, // unhandled architecture type
41083828 };
4109 const flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS;
41103829 const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
41113830 const off = text_segment.findFreeSpace(needed_size, @alignOf(u64), self.header_pad);
41123831 assert(off + needed_size <= text_segment.inner.fileoff + text_segment.inner.filesize); // TODO Must expand __TEXT segment.
......@@ -4118,16 +3837,18 @@ pub fn populateMissingMetadata(self: *MachO) !void {
41183837 .size = needed_size,
41193838 .offset = @intCast(u32, off),
41203839 .@"align" = alignment,
4121 .flags = flags,
3840 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
3841 });
3842 _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
3843 .seg = self.text_segment_cmd_index.?,
3844 .sect = self.stub_helper_section_index.?,
41223845 });
41233846 self.load_commands_dirty = true;
41243847 }
3848
41253849 if (self.data_const_segment_cmd_index == null) {
41263850 self.data_const_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
4127 const maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE | macho.VM_PROT_EXECUTE;
4128 const initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE;
41293851 const address_and_offset = self.nextSegmentAddressAndOffset();
4130
41313852 const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
41323853 const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);
41333854
......@@ -4139,17 +3860,17 @@ pub fn populateMissingMetadata(self: *MachO) !void {
41393860 .vmsize = needed_size,
41403861 .fileoff = address_and_offset.offset,
41413862 .filesize = needed_size,
4142 .maxprot = maxprot,
4143 .initprot = initprot,
3863 .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
3864 .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
41443865 }),
41453866 });
41463867 self.load_commands_dirty = true;
41473868 }
3869
41483870 if (self.got_section_index == null) {
41493871 const dc_segment = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
41503872 self.got_section_index = @intCast(u16, dc_segment.sections.items.len);
41513873
4152 const flags = macho.S_NON_LAZY_SYMBOL_POINTERS;
41533874 const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
41543875 const off = dc_segment.findFreeSpace(needed_size, @alignOf(u64), null);
41553876 assert(off + needed_size <= dc_segment.inner.fileoff + dc_segment.inner.filesize); // TODO Must expand __DATA_CONST segment.
......@@ -4161,16 +3882,18 @@ pub fn populateMissingMetadata(self: *MachO) !void {
41613882 .size = needed_size,
41623883 .offset = @intCast(u32, off),
41633884 .@"align" = 3, // 2^3 = @sizeOf(u64)
4164 .flags = flags,
3885 .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
3886 });
3887 _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
3888 .seg = self.data_const_segment_cmd_index.?,
3889 .sect = self.got_section_index.?,
41653890 });
41663891 self.load_commands_dirty = true;
41673892 }
3893
41683894 if (self.data_segment_cmd_index == null) {
41693895 self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
4170 const maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE | macho.VM_PROT_EXECUTE;
4171 const initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE;
41723896 const address_and_offset = self.nextSegmentAddressAndOffset();
4173
41743897 const ideal_size = 2 * @sizeOf(u64) * self.base.options.symbol_count_hint;
41753898 const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);
41763899
......@@ -4182,17 +3905,17 @@ pub fn populateMissingMetadata(self: *MachO) !void {
41823905 .vmsize = needed_size,
41833906 .fileoff = address_and_offset.offset,
41843907 .filesize = needed_size,
4185 .maxprot = maxprot,
4186 .initprot = initprot,
3908 .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
3909 .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
41873910 }),
41883911 });
41893912 self.load_commands_dirty = true;
41903913 }
3914
41913915 if (self.la_symbol_ptr_section_index == null) {
41923916 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
41933917 self.la_symbol_ptr_section_index = @intCast(u16, data_segment.sections.items.len);
41943918
4195 const flags = macho.S_LAZY_SYMBOL_POINTERS;
41963919 const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
41973920 const off = data_segment.findFreeSpace(needed_size, @alignOf(u64), null);
41983921 assert(off + needed_size <= data_segment.inner.fileoff + data_segment.inner.filesize); // TODO Must expand __DATA segment.
......@@ -4204,10 +3927,15 @@ pub fn populateMissingMetadata(self: *MachO) !void {
42043927 .size = needed_size,
42053928 .offset = @intCast(u32, off),
42063929 .@"align" = 3, // 2^3 = @sizeOf(u64)
4207 .flags = flags,
3930 .flags = macho.S_LAZY_SYMBOL_POINTERS,
3931 });
3932 _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
3933 .seg = self.data_segment_cmd_index.?,
3934 .sect = self.la_symbol_ptr_section_index.?,
42083935 });
42093936 self.load_commands_dirty = true;
42103937 }
3938
42113939 if (self.data_section_index == null) {
42123940 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
42133941 self.data_section_index = @intCast(u16, data_segment.sections.items.len);
......@@ -4224,13 +3952,15 @@ pub fn populateMissingMetadata(self: *MachO) !void {
42243952 .offset = @intCast(u32, off),
42253953 .@"align" = 3, // 2^3 = @sizeOf(u64)
42263954 });
3955 _ = try self.section_ordinals.getOrPut(self.base.allocator, .{
3956 .seg = self.data_segment_cmd_index.?,
3957 .sect = self.data_section_index.?,
3958 });
42273959 self.load_commands_dirty = true;
42283960 }
3961
42293962 if (self.linkedit_segment_cmd_index == null) {
42303963 self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
4231
4232 const maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE | macho.VM_PROT_EXECUTE;
4233 const initprot = macho.VM_PROT_READ;
42343964 const address_and_offset = self.nextSegmentAddressAndOffset();
42353965
42363966 log.debug("found __LINKEDIT segment free space at 0x{x}", .{address_and_offset.offset});
......@@ -4239,12 +3969,13 @@ pub fn populateMissingMetadata(self: *MachO) !void {
42393969 .Segment = SegmentCommand.empty("__LINKEDIT", .{
42403970 .vmaddr = address_and_offset.address,
42413971 .fileoff = address_and_offset.offset,
4242 .maxprot = maxprot,
4243 .initprot = initprot,
3972 .maxprot = macho.VM_PROT_READ,
3973 .initprot = macho.VM_PROT_READ,
42443974 }),
42453975 });
42463976 self.load_commands_dirty = true;
42473977 }
3978
42483979 if (self.dyld_info_cmd_index == null) {
42493980 self.dyld_info_cmd_index = @intCast(u16, self.load_commands.items.len);
42503981
......@@ -4291,6 +4022,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
42914022
42924023 self.load_commands_dirty = true;
42934024 }
4025
42944026 if (self.symtab_cmd_index == null) {
42954027 self.symtab_cmd_index = @intCast(u16, self.load_commands.items.len);
42964028
......@@ -4323,6 +4055,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
43234055 self.load_commands_dirty = true;
43244056 self.strtab_dirty = true;
43254057 }
4058
43264059 if (self.dysymtab_cmd_index == null) {
43274060 self.dysymtab_cmd_index = @intCast(u16, self.load_commands.items.len);
43284061
......@@ -4358,6 +4091,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
43584091 });
43594092 self.load_commands_dirty = true;
43604093 }
4094
43614095 if (self.dylinker_cmd_index == null) {
43624096 self.dylinker_cmd_index = @intCast(u16, self.load_commands.items.len);
43634097 const cmdsize = @intCast(u32, mem.alignForwardGeneric(
......@@ -4376,17 +4110,8 @@ pub fn populateMissingMetadata(self: *MachO) !void {
43764110 try self.load_commands.append(self.base.allocator, .{ .Dylinker = dylinker_cmd });
43774111 self.load_commands_dirty = true;
43784112 }
4379 if (self.libsystem_cmd_index == null) {
4380 self.libsystem_cmd_index = @intCast(u16, self.load_commands.items.len);
4381
4382 var dylib_cmd = try commands.createLoadDylibCommand(self.base.allocator, mem.spanZ(LIB_SYSTEM_PATH), 2, 0, 0);
4383 errdefer dylib_cmd.deinit(self.base.allocator);
4384
4385 try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd });
43864113
4387 self.load_commands_dirty = true;
4388 }
4389 if (self.main_cmd_index == null) {
4114 if (self.main_cmd_index == null and self.base.options.output_mode == .Exe) {
43904115 self.main_cmd_index = @intCast(u16, self.load_commands.items.len);
43914116 try self.load_commands.append(self.base.allocator, .{
43924117 .Main = .{
......@@ -4398,6 +4123,38 @@ pub fn populateMissingMetadata(self: *MachO) !void {
43984123 });
43994124 self.load_commands_dirty = true;
44004125 }
4126
4127 if (self.dylib_id_cmd_index == null and self.base.options.output_mode == .Lib) {
4128 self.dylib_id_cmd_index = @intCast(u16, self.load_commands.items.len);
4129 const install_name = try std.fmt.allocPrint(self.base.allocator, "@rpath/{s}", .{
4130 self.base.options.emit.?.sub_path,
4131 });
4132 defer self.base.allocator.free(install_name);
4133 var dylib_cmd = try commands.createLoadDylibCommand(
4134 self.base.allocator,
4135 install_name,
4136 2,
4137 0x10000, // TODO forward user-provided versions
4138 0x10000,
4139 );
4140 errdefer dylib_cmd.deinit(self.base.allocator);
4141 dylib_cmd.inner.cmd = macho.LC_ID_DYLIB;
4142 try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd });
4143 self.load_commands_dirty = true;
4144 }
4145
4146 if (self.source_version_cmd_index == null) {
4147 self.source_version_cmd_index = @intCast(u16, self.load_commands.items.len);
4148 try self.load_commands.append(self.base.allocator, .{
4149 .SourceVersion = .{
4150 .cmd = macho.LC_SOURCE_VERSION,
4151 .cmdsize = @sizeOf(macho.source_version_command),
4152 .version = 0x0,
4153 },
4154 });
4155 self.load_commands_dirty = true;
4156 }
4157
44014158 if (self.build_version_cmd_index == null) {
44024159 self.build_version_cmd_index = @intCast(u16, self.load_commands.items.len);
44034160 const cmdsize = @intCast(u32, mem.alignForwardGeneric(
......@@ -4430,18 +4187,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {
44304187 mem.set(u8, cmd.data, 0);
44314188 mem.copy(u8, cmd.data, mem.asBytes(&ld_ver));
44324189 try self.load_commands.append(self.base.allocator, .{ .BuildVersion = cmd });
4433 }
4434 if (self.source_version_cmd_index == null) {
4435 self.source_version_cmd_index = @intCast(u16, self.load_commands.items.len);
4436 try self.load_commands.append(self.base.allocator, .{
4437 .SourceVersion = .{
4438 .cmd = macho.LC_SOURCE_VERSION,
4439 .cmdsize = @sizeOf(macho.source_version_command),
4440 .version = 0x0,
4441 },
4442 });
44434190 self.load_commands_dirty = true;
44444191 }
4192
44454193 if (self.uuid_cmd_index == null) {
44464194 self.uuid_cmd_index = @intCast(u16, self.load_commands.items.len);
44474195 var uuid_cmd: macho.uuid_command = .{
......@@ -4453,47 +4201,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
44534201 try self.load_commands.append(self.base.allocator, .{ .Uuid = uuid_cmd });
44544202 self.load_commands_dirty = true;
44554203 }
4456 if (self.code_signature_cmd_index == null and self.requires_adhoc_codesig) {
4457 self.code_signature_cmd_index = @intCast(u16, self.load_commands.items.len);
4458 try self.load_commands.append(self.base.allocator, .{
4459 .LinkeditData = .{
4460 .cmd = macho.LC_CODE_SIGNATURE,
4461 .cmdsize = @sizeOf(macho.linkedit_data_command),
4462 .dataoff = 0,
4463 .datasize = 0,
4464 },
4465 });
4466 self.load_commands_dirty = true;
4467 }
4468 if (!self.strtab_dir.containsAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{
4469 .strtab = &self.strtab,
4470 })) {
4471 const import_sym_index = @intCast(u32, self.undefs.items.len);
4472 const n_strx = try self.makeString("dyld_stub_binder");
4473 try self.undefs.append(self.base.allocator, .{
4474 .n_strx = n_strx,
4475 .n_type = macho.N_UNDF | macho.N_EXT,
4476 .n_sect = 0,
4477 .n_desc = @intCast(u8, 1) * macho.N_SYMBOL_RESOLVER,
4478 .n_value = 0,
4479 });
4480 try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{
4481 .where = .undef,
4482 .where_index = import_sym_index,
4483 });
4484 const got_key = GotIndirectionKey{
4485 .where = .undef,
4486 .where_index = import_sym_index,
4487 };
4488 const got_index = @intCast(u32, self.got_entries.items.len);
4489 try self.got_entries.append(self.base.allocator, got_key);
4490 try self.got_entries_map.putNoClobber(self.base.allocator, got_key, got_index);
4491 try self.writeGotEntry(got_index);
4492 self.binding_info_dirty = true;
4493 }
4494 if (self.stub_helper_stubs_start_off == null) {
4495 try self.writeStubHelperPreamble();
4496 }
44974204}
44984205
44994206fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {