| ... | @@ -788,6 +788,7 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { | ... | @@ -788,6 +788,7 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 788 | try self.allocateTextBlocks(); | 788 | try self.allocateTextBlocks(); |
| 789 | try self.flushZld(); | 789 | try self.flushZld(); |
| 790 | } else { | 790 | } else { |
| | 791 | try self.writeAtoms(); |
| 791 | try self.flushModule(comp); | 792 | try self.flushModule(comp); |
| 792 | } | 793 | } |
| 793 | } | 794 | } |
| ... | @@ -1901,8 +1902,7 @@ pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 | ... | @@ -1901,8 +1902,7 @@ pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 |
| 1901 | const last_atom_sym = self.locals.items[last.local_sym_index]; | 1902 | const last_atom_sym = self.locals.items[last.local_sym_index]; |
| 1902 | break :blk last_atom_sym.n_value + last.size; | 1903 | break :blk last_atom_sym.n_value + last.size; |
| 1903 | } else sect.addr; | 1904 | } else sect.addr; |
| 1904 | // const atom_alignment = try math.powi(u32, 2, atom.alignment); TODO | 1905 | const atom_alignment = try math.powi(u32, 2, atom.alignment); |
| 1905 | const atom_alignment = math.powi(u32, 2, atom.alignment) catch unreachable; | | |
| 1906 | const vaddr = mem.alignForwardGeneric(u64, base_addr, atom_alignment); | 1906 | const vaddr = mem.alignForwardGeneric(u64, base_addr, atom_alignment); |
| 1907 | log.debug("allocating atom for symbol {s} at address 0x{x}", .{ self.getString(sym.n_strx), vaddr }); | 1907 | log.debug("allocating atom for symbol {s} at address 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| 1908 | | 1908 | |
| ... | @@ -1954,6 +1954,20 @@ pub fn allocateAtomStage1(self: *MachO, atom: *TextBlock, match: MatchingSection | ... | @@ -1954,6 +1954,20 @@ pub fn allocateAtomStage1(self: *MachO, atom: *TextBlock, match: MatchingSection |
| 1954 | } | 1954 | } |
| 1955 | } | 1955 | } |
| 1956 | | 1956 | |
| | 1957 | fn writeAtoms(self: *MachO) !void { |
| | 1958 | var it = self.blocks.iterator(); |
| | 1959 | while (it.next()) |entry| { |
| | 1960 | const match = entry.key_ptr.*; |
| | 1961 | var atom: *TextBlock = entry.value_ptr.*; |
| | 1962 | |
| | 1963 | while (atom.prev) |prev| { |
| | 1964 | try self.writeAtom(atom, match); |
| | 1965 | atom = prev; |
| | 1966 | } |
| | 1967 | try self.writeAtom(atom, match); |
| | 1968 | } |
| | 1969 | } |
| | 1970 | |
| 1957 | pub fn createGotAtom(self: *MachO, key: GotIndirectionKey) !*TextBlock { | 1971 | pub fn createGotAtom(self: *MachO, key: GotIndirectionKey) !*TextBlock { |
| 1958 | const local_sym_index = @intCast(u32, self.locals.items.len); | 1972 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| 1959 | try self.locals.append(self.base.allocator, .{ | 1973 | try self.locals.append(self.base.allocator, .{ |
| ... | @@ -2588,21 +2602,17 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2588,21 +2602,17 @@ fn resolveSymbols(self: *MachO) !void { |
| 2588 | if (!use_stage1) { | 2602 | if (!use_stage1) { |
| 2589 | { | 2603 | { |
| 2590 | const atom = try self.createDyldPrivateAtom(); | 2604 | const atom = try self.createDyldPrivateAtom(); |
| 2591 | const match = MatchingSection{ | 2605 | _ = try self.allocateAtom(atom, .{ |
| 2592 | .seg = self.data_segment_cmd_index.?, | 2606 | .seg = self.data_segment_cmd_index.?, |
| 2593 | .sect = self.data_section_index.?, | 2607 | .sect = self.data_section_index.?, |
| 2594 | }; | 2608 | }); |
| 2595 | _ = try self.allocateAtom(atom, match); | | |
| 2596 | try self.writeAtom(atom, match); | | |
| 2597 | } | 2609 | } |
| 2598 | { | 2610 | { |
| 2599 | const atom = try self.createStubHelperPreambleAtom(); | 2611 | const atom = try self.createStubHelperPreambleAtom(); |
| 2600 | const match = MatchingSection{ | 2612 | _ = try self.allocateAtom(atom, .{ |
| 2601 | .seg = self.text_segment_cmd_index.?, | 2613 | .seg = self.text_segment_cmd_index.?, |
| 2602 | .sect = self.stub_helper_section_index.?, | 2614 | .sect = self.stub_helper_section_index.?, |
| 2603 | }; | 2615 | }); |
| 2604 | _ = try self.allocateAtom(atom, match); | | |
| 2605 | try self.writeAtom(atom, match); | | |
| 2606 | } | 2616 | } |
| 2607 | } | 2617 | } |
| 2608 | | 2618 | |
| ... | @@ -2634,12 +2644,10 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2634,12 +2644,10 @@ fn resolveSymbols(self: *MachO) !void { |
| 2634 | if (self.stubs_map.contains(resolv.where_index)) break :outer_blk; | 2644 | if (self.stubs_map.contains(resolv.where_index)) break :outer_blk; |
| 2635 | const stub_helper_atom = blk: { | 2645 | const stub_helper_atom = blk: { |
| 2636 | const atom = try self.createStubHelperAtom(); | 2646 | const atom = try self.createStubHelperAtom(); |
| 2637 | const match = MatchingSection{ | 2647 | _ = try self.allocateAtom(atom, .{ |
| 2638 | .seg = self.text_segment_cmd_index.?, | 2648 | .seg = self.text_segment_cmd_index.?, |
| 2639 | .sect = self.stub_helper_section_index.?, | 2649 | .sect = self.stub_helper_section_index.?, |
| 2640 | }; | 2650 | }); |
| 2641 | _ = try self.allocateAtom(atom, match); | | |
| 2642 | try self.writeAtom(atom, match); | | |
| 2643 | break :blk atom; | 2651 | break :blk atom; |
| 2644 | }; | 2652 | }; |
| 2645 | const laptr_atom = blk: { | 2653 | const laptr_atom = blk: { |
| ... | @@ -2647,22 +2655,18 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2647,22 +2655,18 @@ fn resolveSymbols(self: *MachO) !void { |
| 2647 | stub_helper_atom.local_sym_index, | 2655 | stub_helper_atom.local_sym_index, |
| 2648 | resolv.where_index, | 2656 | resolv.where_index, |
| 2649 | ); | 2657 | ); |
| 2650 | const match = MatchingSection{ | 2658 | _ = try self.allocateAtom(atom, .{ |
| 2651 | .seg = self.data_segment_cmd_index.?, | 2659 | .seg = self.data_segment_cmd_index.?, |
| 2652 | .sect = self.la_symbol_ptr_section_index.?, | 2660 | .sect = self.la_symbol_ptr_section_index.?, |
| 2653 | }; | 2661 | }); |
| 2654 | _ = try self.allocateAtom(atom, match); | | |
| 2655 | try self.writeAtom(atom, match); | | |
| 2656 | break :blk atom; | 2662 | break :blk atom; |
| 2657 | }; | 2663 | }; |
| 2658 | const stub_atom = blk: { | 2664 | const stub_atom = blk: { |
| 2659 | const atom = try self.createStubAtom(laptr_atom.local_sym_index); | 2665 | const atom = try self.createStubAtom(laptr_atom.local_sym_index); |
| 2660 | const match = MatchingSection{ | 2666 | _ = try self.allocateAtom(atom, .{ |
| 2661 | .seg = self.text_segment_cmd_index.?, | 2667 | .seg = self.text_segment_cmd_index.?, |
| 2662 | .sect = self.stubs_section_index.?, | 2668 | .sect = self.stubs_section_index.?, |
| 2663 | }; | 2669 | }); |
| 2664 | _ = try self.allocateAtom(atom, match); | | |
| 2665 | try self.writeAtom(atom, match); | | |
| 2666 | break :blk atom; | 2670 | break :blk atom; |
| 2667 | }; | 2671 | }; |
| 2668 | try self.stubs_map.putNoClobber(self.base.allocator, resolv.where_index, stub_atom); | 2672 | try self.stubs_map.putNoClobber(self.base.allocator, resolv.where_index, stub_atom); |
| ... | @@ -2793,7 +2797,6 @@ fn resolveDyldStubBinder(self: *MachO) !void { | ... | @@ -2793,7 +2797,6 @@ fn resolveDyldStubBinder(self: *MachO) !void { |
| 2793 | // TODO remove once we can incrementally update in stage1 too. | 2797 | // TODO remove once we can incrementally update in stage1 too. |
| 2794 | if (!(build_options.is_stage1 and self.base.options.use_stage1)) { | 2798 | if (!(build_options.is_stage1 and self.base.options.use_stage1)) { |
| 2795 | _ = try self.allocateAtom(atom, match); | 2799 | _ = try self.allocateAtom(atom, match); |
| 2796 | try self.writeAtom(atom, match); | | |
| 2797 | } else { | 2800 | } else { |
| 2798 | try self.allocateAtomStage1(atom, match); | 2801 | try self.allocateAtomStage1(atom, match); |
| 2799 | } | 2802 | } |
| ... | @@ -3480,10 +3483,6 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void { | ... | @@ -3480,10 +3483,6 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void { |
| 3480 | .where_index = decl.link.macho.local_sym_index, | 3483 | .where_index = decl.link.macho.local_sym_index, |
| 3481 | }; | 3484 | }; |
| 3482 | const got_atom = try self.createGotAtom(key); | 3485 | const got_atom = try self.createGotAtom(key); |
| 3483 | _ = try self.allocateAtom(got_atom, .{ | | |
| 3484 | .seg = self.data_const_segment_cmd_index.?, | | |
| 3485 | .sect = self.got_section_index.?, | | |
| 3486 | }); | | |
| 3487 | try self.got_entries_map.put(self.base.allocator, key, got_atom); | 3486 | try self.got_entries_map.put(self.base.allocator, key, got_atom); |
| 3488 | self.rebase_info_dirty = true; | 3487 | self.rebase_info_dirty = true; |
| 3489 | } | 3488 | } |
| ... | @@ -3549,9 +3548,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv | ... | @@ -3549,9 +3548,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv |
| 3549 | }, | 3548 | }, |
| 3550 | } | 3549 | } |
| 3551 | | 3550 | |
| 3552 | const symbol = try self.placeDecl(decl, decl.link.macho.code.items.len); | 3551 | _ = try self.placeDecl(decl, decl.link.macho.code.items.len); |
| 3553 | | | |
| 3554 | try self.writeCode(symbol, decl.link.macho.code.items); | | |
| 3555 | | 3552 | |
| 3556 | if (debug_buffers) |db| { | 3553 | if (debug_buffers) |db| { |
| 3557 | try self.d_sym.?.commitDeclDebugInfo( | 3554 | try self.d_sym.?.commitDeclDebugInfo( |
| ... | @@ -3642,9 +3639,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { | ... | @@ -3642,9 +3639,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 3642 | }, | 3639 | }, |
| 3643 | } | 3640 | } |
| 3644 | }; | 3641 | }; |
| 3645 | const symbol = try self.placeDecl(decl, code.len); | 3642 | _ = try self.placeDecl(decl, code.len); |
| 3646 | | | |
| 3647 | try self.writeCode(symbol, code); | | |
| 3648 | | 3643 | |
| 3649 | // Since we updated the vaddr and the size, each corresponding export symbol also | 3644 | // Since we updated the vaddr and the size, each corresponding export symbol also |
| 3650 | // needs to be updated. | 3645 | // needs to be updated. |
| ... | @@ -3667,16 +3662,14 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 | ... | @@ -3667,16 +3662,14 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 3667 | | 3662 | |
| 3668 | if (vaddr != symbol.n_value) { | 3663 | if (vaddr != symbol.n_value) { |
| 3669 | log.debug(" (writing new GOT entry)", .{}); | 3664 | log.debug(" (writing new GOT entry)", .{}); |
| 3670 | const match = MatchingSection{ | | |
| 3671 | .seg = self.data_const_segment_cmd_index.?, | | |
| 3672 | .sect = self.got_section_index.?, | | |
| 3673 | }; | | |
| 3674 | const got_atom = self.got_entries_map.get(.{ | 3665 | const got_atom = self.got_entries_map.get(.{ |
| 3675 | .where = .local, | 3666 | .where = .local, |
| 3676 | .where_index = decl.link.macho.local_sym_index, | 3667 | .where_index = decl.link.macho.local_sym_index, |
| 3677 | }) orelse unreachable; | 3668 | }) orelse unreachable; |
| 3678 | // _ = try self.allocateAtom(got_atom, match); | 3669 | _ = try self.allocateAtom(got_atom, .{ |
| 3679 | try self.writeAtom(got_atom, match); | 3670 | .seg = self.data_const_segment_cmd_index.?, |
| | 3671 | .sect = self.got_section_index.?, |
| | 3672 | }); |
| 3680 | } | 3673 | } |
| 3681 | | 3674 | |
| 3682 | symbol.n_value = vaddr; | 3675 | symbol.n_value = vaddr; |
| ... | @@ -3714,40 +3707,29 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 | ... | @@ -3714,40 +3707,29 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 3714 | .n_desc = 0, | 3707 | .n_desc = 0, |
| 3715 | .n_value = addr, | 3708 | .n_value = addr, |
| 3716 | }; | 3709 | }; |
| 3717 | const match = MatchingSection{ | | |
| 3718 | .seg = self.data_const_segment_cmd_index.?, | | |
| 3719 | .sect = self.got_section_index.?, | | |
| 3720 | }; | | |
| 3721 | const got_atom = self.got_entries_map.get(.{ | 3710 | const got_atom = self.got_entries_map.get(.{ |
| 3722 | .where = .local, | 3711 | .where = .local, |
| 3723 | .where_index = decl.link.macho.local_sym_index, | 3712 | .where_index = decl.link.macho.local_sym_index, |
| 3724 | }) orelse unreachable; | 3713 | }) orelse unreachable; |
| 3725 | // _ = try self.allocateAtom(got_atom, match); | 3714 | _ = try self.allocateAtom(got_atom, .{ |
| 3726 | try self.writeAtom(got_atom, match); | 3715 | .seg = self.data_const_segment_cmd_index.?, |
| | 3716 | .sect = self.got_section_index.?, |
| | 3717 | }); |
| 3727 | | 3718 | |
| 3728 | try self.writeLocalSymbol(decl.link.macho.local_sym_index); | 3719 | try self.writeLocalSymbol(decl.link.macho.local_sym_index); |
| 3729 | if (self.d_sym) |*ds| | 3720 | if (self.d_sym) |*ds| |
| 3730 | try ds.writeLocalSymbol(decl.link.macho.local_sym_index); | 3721 | try ds.writeLocalSymbol(decl.link.macho.local_sym_index); |
| 3731 | } | 3722 | } |
| 3732 | | 3723 | |
| 3733 | // Resolve relocations | 3724 | // // Resolve relocations |
| 3734 | try decl.link.macho.resolveRelocs(self); | 3725 | // try decl.link.macho.resolveRelocs(self); |
| 3735 | // TODO this requires further investigation: should we dispose of resolved relocs, or keep them | 3726 | // // TODO this requires further investigation: should we dispose of resolved relocs, or keep them |
| 3736 | // so that we can reapply them when moving/growing sections? | 3727 | // // so that we can reapply them when moving/growing sections? |
| 3737 | decl.link.macho.relocs.clearAndFree(self.base.allocator); | 3728 | // decl.link.macho.relocs.clearAndFree(self.base.allocator); |
| 3738 | | 3729 | |
| 3739 | return symbol; | 3730 | return symbol; |
| 3740 | } | 3731 | } |
| 3741 | | 3732 | |
| 3742 | fn writeCode(self: *MachO, symbol: *macho.nlist_64, code: []const u8) !void { | | |
| 3743 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; | | |
| 3744 | const text_section = text_segment.sections.items[self.text_section_index.?]; | | |
| 3745 | const section_offset = symbol.n_value - text_section.addr; | | |
| 3746 | const file_offset = text_section.offset + section_offset; | | |
| 3747 | log.debug("writing code for symbol {s} at file offset 0x{x}", .{ self.getString(symbol.n_strx), file_offset }); | | |
| 3748 | try self.base.file.?.pwriteAll(code, file_offset); | | |
| 3749 | } | | |
| 3750 | | | |
| 3751 | pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void { | 3733 | pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void { |
| 3752 | if (self.d_sym) |*ds| { | 3734 | if (self.d_sym) |*ds| { |
| 3753 | try ds.updateDeclLineNumber(module, decl); | 3735 | try ds.updateDeclLineNumber(module, decl); |
| ... | @@ -3983,7 +3965,7 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -3983,7 +3965,7 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3983 | .aarch64 => 3 * @sizeOf(u32), | 3965 | .aarch64 => 3 * @sizeOf(u32), |
| 3984 | else => unreachable, // unhandled architecture type | 3966 | else => unreachable, // unhandled architecture type |
| 3985 | }; | 3967 | }; |
| 3986 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; | 3968 | const needed_size = stub_size * self.base.options.symbol_count_hint; |
| 3987 | const off = text_segment.findFreeSpace(needed_size, @alignOf(u64), self.header_pad); | 3969 | const off = text_segment.findFreeSpace(needed_size, @alignOf(u64), self.header_pad); |
| 3988 | assert(off + needed_size <= text_segment.inner.fileoff + text_segment.inner.filesize); // TODO Must expand __TEXT segment. | 3970 | assert(off + needed_size <= text_segment.inner.fileoff + text_segment.inner.filesize); // TODO Must expand __TEXT segment. |
| 3989 | | 3971 | |
| ... | @@ -4739,8 +4721,9 @@ fn writeLocalSymbol(self: *MachO, index: usize) !void { | ... | @@ -4739,8 +4721,9 @@ fn writeLocalSymbol(self: *MachO, index: usize) !void { |
| 4739 | try self.relocateSymbolTable(); | 4721 | try self.relocateSymbolTable(); |
| 4740 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; | 4722 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; |
| 4741 | const off = symtab.symoff + @sizeOf(macho.nlist_64) * index; | 4723 | const off = symtab.symoff + @sizeOf(macho.nlist_64) * index; |
| 4742 | log.debug("writing local symbol {} at 0x{x}", .{ index, off }); | 4724 | const sym = self.locals.items[index]; |
| 4743 | try self.base.file.?.pwriteAll(mem.asBytes(&self.locals.items[index]), off); | 4725 | log.debug("writing local symbol {s}: {} at 0x{x}", .{ self.getString(sym.n_strx), sym, off }); |
| | 4726 | try self.base.file.?.pwriteAll(mem.asBytes(&sym), off); |
| 4744 | } | 4727 | } |
| 4745 | | 4728 | |
| 4746 | fn writeAllGlobalAndUndefSymbols(self: *MachO) !void { | 4729 | fn writeAllGlobalAndUndefSymbols(self: *MachO) !void { |