| ... | @@ -760,27 +760,6 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { | ... | @@ -760,27 +760,6 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 760 | try self.addCodeSignatureLC(); | 760 | try self.addCodeSignatureLC(); |
| 761 | | 761 | |
| 762 | if (use_stage1) { | 762 | if (use_stage1) { |
| 763 | { | | |
| 764 | const atom = try self.createDyldPrivateAtom(); | | |
| 765 | try self.allocateAtomStage1(atom, .{ | | |
| 766 | .seg = self.data_segment_cmd_index.?, | | |
| 767 | .sect = self.data_section_index.?, | | |
| 768 | }); | | |
| 769 | } | | |
| 770 | { | | |
| 771 | const atom = try self.createStubHelperPreambleAtom(); | | |
| 772 | try self.allocateAtomStage1(atom, .{ | | |
| 773 | .seg = self.text_segment_cmd_index.?, | | |
| 774 | .sect = self.stub_helper_section_index.?, | | |
| 775 | }); | | |
| 776 | // TODO this is just a temp | | |
| 777 | // We already prealloc stub helper size in populateMissingMetadata(), but | | |
| 778 | // perhaps it's not needed after all? | | |
| 779 | const seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; | | |
| 780 | const sect = &seg.sections.items[self.stub_helper_section_index.?]; | | |
| 781 | sect.size -= atom.size; | | |
| 782 | } | | |
| 783 | | | |
| 784 | try self.parseTextBlocks(); | 763 | try self.parseTextBlocks(); |
| 785 | try self.allocateTextSegment(); | 764 | try self.allocateTextSegment(); |
| 786 | try self.allocateDataConstSegment(); | 765 | try self.allocateDataConstSegment(); |
| ... | @@ -1919,55 +1898,70 @@ pub fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment: | ... | @@ -1919,55 +1898,70 @@ pub fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment: |
| 1919 | pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 { | 1898 | pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 { |
| 1920 | const seg = &self.load_commands.items[match.seg].Segment; | 1899 | const seg = &self.load_commands.items[match.seg].Segment; |
| 1921 | const sect = &seg.sections.items[match.sect]; | 1900 | const sect = &seg.sections.items[match.sect]; |
| 1922 | const sym = &self.locals.items[atom.local_sym_index]; | 1901 | const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1; |
| 1923 | | | |
| 1924 | var atom_placement: ?*TextBlock = null; | | |
| 1925 | | | |
| 1926 | // TODO converge with `allocateTextBlock` and handle free list | | |
| 1927 | const vaddr = if (self.blocks.get(match)) |last| blk: { | | |
| 1928 | const last_atom_sym = self.locals.items[last.local_sym_index]; | | |
| 1929 | const ideal_capacity = padToIdeal(last.size); | | |
| 1930 | const ideal_capacity_end_vaddr = last_atom_sym.n_value + ideal_capacity; | | |
| 1931 | const last_atom_alignment = try math.powi(u32, 2, atom.alignment); | | |
| 1932 | const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, last_atom_alignment); | | |
| 1933 | atom_placement = last; | | |
| 1934 | break :blk new_start_vaddr; | | |
| 1935 | } else sect.addr; | | |
| 1936 | | | |
| 1937 | log.debug("allocating atom for symbol {s} at address 0x{x}", .{ self.getString(sym.n_strx), vaddr }); | | |
| 1938 | | | |
| 1939 | const expand_section = atom_placement == null or atom_placement.?.next == null; | | |
| 1940 | if (expand_section) { | | |
| 1941 | const needed_size = (vaddr + atom.size) - sect.addr; | | |
| 1942 | const end_addr = blk: { | | |
| 1943 | const next_ordinal = self.section_ordinals.getIndex(match).?; // Ordinals are +1 to begin with. | | |
| 1944 | const end_addr = if (self.section_ordinals.keys().len > next_ordinal) inner: { | | |
| 1945 | const next_match = self.section_ordinals.keys()[next_ordinal]; | | |
| 1946 | const next_seg = self.load_commands.items[next_match.seg].Segment; | | |
| 1947 | const next_sect = next_seg.sections.items[next_match.sect]; | | |
| 1948 | break :inner next_sect.addr; | | |
| 1949 | } else seg.inner.filesize; | | |
| 1950 | break :blk end_addr; | | |
| 1951 | }; | | |
| 1952 | assert(needed_size <= end_addr); // TODO must expand the section | | |
| 1953 | } | | |
| 1954 | const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); | | |
| 1955 | sym.n_value = vaddr; | | |
| 1956 | sym.n_sect = n_sect; | | |
| 1957 | | 1902 | |
| 1958 | // Update each alias (if any) | 1903 | const vaddr = outer: { |
| 1959 | for (atom.aliases.items) |index| { | 1904 | if (!use_stage1) { |
| 1960 | const alias_sym = &self.locals.items[index]; | 1905 | const sym = &self.locals.items[atom.local_sym_index]; |
| 1961 | alias_sym.n_value = vaddr; | 1906 | |
| 1962 | alias_sym.n_sect = n_sect; | 1907 | var atom_placement: ?*TextBlock = null; |
| 1963 | } | 1908 | |
| | 1909 | // TODO converge with `allocateTextBlock` and handle free list |
| | 1910 | const vaddr = if (self.blocks.get(match)) |last| blk: { |
| | 1911 | const last_atom_sym = self.locals.items[last.local_sym_index]; |
| | 1912 | const ideal_capacity = padToIdeal(last.size); |
| | 1913 | const ideal_capacity_end_vaddr = last_atom_sym.n_value + ideal_capacity; |
| | 1914 | const last_atom_alignment = try math.powi(u32, 2, atom.alignment); |
| | 1915 | const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, last_atom_alignment); |
| | 1916 | atom_placement = last; |
| | 1917 | break :blk new_start_vaddr; |
| | 1918 | } else sect.addr; |
| | 1919 | |
| | 1920 | log.debug("allocating atom for symbol {s} at address 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| | 1921 | |
| | 1922 | const expand_section = atom_placement == null or atom_placement.?.next == null; |
| | 1923 | if (expand_section) { |
| | 1924 | const needed_size = (vaddr + atom.size) - sect.addr; |
| | 1925 | const end_addr = blk: { |
| | 1926 | const next_ordinal = self.section_ordinals.getIndex(match).?; // Ordinals are +1 to begin with. |
| | 1927 | const end_addr = if (self.section_ordinals.keys().len > next_ordinal) inner: { |
| | 1928 | const next_match = self.section_ordinals.keys()[next_ordinal]; |
| | 1929 | const next_seg = self.load_commands.items[next_match.seg].Segment; |
| | 1930 | const next_sect = next_seg.sections.items[next_match.sect]; |
| | 1931 | break :inner next_sect.addr; |
| | 1932 | } else seg.inner.filesize; |
| | 1933 | break :blk end_addr; |
| | 1934 | }; |
| | 1935 | assert(needed_size <= end_addr); // TODO must expand the section |
| | 1936 | } |
| | 1937 | const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| | 1938 | sym.n_value = vaddr; |
| | 1939 | sym.n_sect = n_sect; |
| 1964 | | 1940 | |
| 1965 | // Update each symbol contained within the TextBlock | 1941 | // Update each alias (if any) |
| 1966 | for (atom.contained.items) |sym_at_off| { | 1942 | for (atom.aliases.items) |index| { |
| 1967 | const contained_sym = &self.locals.items[sym_at_off.local_sym_index]; | 1943 | const alias_sym = &self.locals.items[index]; |
| 1968 | contained_sym.n_value = vaddr + sym_at_off.offset; | 1944 | alias_sym.n_value = vaddr; |
| 1969 | contained_sym.n_sect = n_sect; | 1945 | alias_sym.n_sect = n_sect; |
| 1970 | } | 1946 | } |
| | 1947 | |
| | 1948 | // Update each symbol contained within the TextBlock |
| | 1949 | for (atom.contained.items) |sym_at_off| { |
| | 1950 | const contained_sym = &self.locals.items[sym_at_off.local_sym_index]; |
| | 1951 | contained_sym.n_value = vaddr + sym_at_off.offset; |
| | 1952 | contained_sym.n_sect = n_sect; |
| | 1953 | } |
| | 1954 | |
| | 1955 | break :outer vaddr; |
| | 1956 | } else { |
| | 1957 | const new_alignment = math.max(sect.@"align", atom.alignment); |
| | 1958 | const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment); |
| | 1959 | const new_size = mem.alignForwardGeneric(u64, sect.size, new_alignment_pow_2) + atom.size; |
| | 1960 | sect.size = new_size; |
| | 1961 | sect.@"align" = new_alignment; |
| | 1962 | break :outer 0; |
| | 1963 | } |
| | 1964 | }; |
| 1971 | | 1965 | |
| 1972 | if (self.blocks.getPtr(match)) |last| { | 1966 | if (self.blocks.getPtr(match)) |last| { |
| 1973 | last.*.next = atom; | 1967 | last.*.next = atom; |
| ... | @@ -2017,27 +2011,6 @@ fn allocateGlobalSymbols(self: *MachO) !void { | ... | @@ -2017,27 +2011,6 @@ fn allocateGlobalSymbols(self: *MachO) !void { |
| 2017 | } | 2011 | } |
| 2018 | } | 2012 | } |
| 2019 | | 2013 | |
| 2020 | pub fn allocateAtomStage1(self: *MachO, atom: *TextBlock, match: MatchingSection) !void { | | |
| 2021 | // Update target section's metadata | | |
| 2022 | // TODO should we update segment's size here too? | | |
| 2023 | // How does it tie with incremental space allocs? | | |
| 2024 | const tseg = &self.load_commands.items[match.seg].Segment; | | |
| 2025 | const tsect = &tseg.sections.items[match.sect]; | | |
| 2026 | const new_alignment = math.max(tsect.@"align", atom.alignment); | | |
| 2027 | const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment); | | |
| 2028 | const new_size = mem.alignForwardGeneric(u64, tsect.size, new_alignment_pow_2) + atom.size; | | |
| 2029 | tsect.size = new_size; | | |
| 2030 | tsect.@"align" = new_alignment; | | |
| 2031 | | | |
| 2032 | if (self.blocks.getPtr(match)) |last| { | | |
| 2033 | last.*.next = atom; | | |
| 2034 | atom.prev = last.*; | | |
| 2035 | last.* = atom; | | |
| 2036 | } else { | | |
| 2037 | try self.blocks.putNoClobber(self.base.allocator, match, atom); | | |
| 2038 | } | | |
| 2039 | } | | |
| 2040 | | | |
| 2041 | fn writeAtoms(self: *MachO) !void { | 2014 | fn writeAtoms(self: *MachO) !void { |
| 2042 | var it = self.blocks.iterator(); | 2015 | var it = self.blocks.iterator(); |
| 2043 | while (it.next()) |entry| { | 2016 | while (it.next()) |entry| { |
| ... | @@ -2607,8 +2580,6 @@ fn resolveSymbolsInObject( | ... | @@ -2607,8 +2580,6 @@ fn resolveSymbolsInObject( |
| 2607 | } | 2580 | } |
| 2608 | | 2581 | |
| 2609 | fn resolveSymbols(self: *MachO) !void { | 2582 | fn resolveSymbols(self: *MachO) !void { |
| 2610 | const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1; | | |
| 2611 | | | |
| 2612 | var tentatives = std.AutoArrayHashMap(u32, void).init(self.base.allocator); | 2583 | var tentatives = std.AutoArrayHashMap(u32, void).init(self.base.allocator); |
| 2613 | defer tentatives.deinit(); | 2584 | defer tentatives.deinit(); |
| 2614 | | 2585 | |
| ... | @@ -2668,27 +2639,23 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2668,27 +2639,23 @@ fn resolveSymbols(self: *MachO) !void { |
| 2668 | resolv.local_sym_index = local_sym_index; | 2639 | resolv.local_sym_index = local_sym_index; |
| 2669 | | 2640 | |
| 2670 | const atom = try self.createEmptyAtom(local_sym_index, size, alignment); | 2641 | const atom = try self.createEmptyAtom(local_sym_index, size, alignment); |
| 2671 | if (use_stage1) { | 2642 | _ = try self.allocateAtom(atom, match); |
| 2672 | try self.allocateAtomStage1(atom, match); | | |
| 2673 | } | | |
| 2674 | } | 2643 | } |
| 2675 | | 2644 | |
| 2676 | try self.resolveDyldStubBinder(); | 2645 | try self.resolveDyldStubBinder(); |
| 2677 | if (!use_stage1) { | 2646 | { |
| 2678 | { | 2647 | const atom = try self.createDyldPrivateAtom(); |
| 2679 | const atom = try self.createDyldPrivateAtom(); | 2648 | _ = try self.allocateAtom(atom, .{ |
| 2680 | _ = try self.allocateAtom(atom, .{ | 2649 | .seg = self.data_segment_cmd_index.?, |
| 2681 | .seg = self.data_segment_cmd_index.?, | 2650 | .sect = self.data_section_index.?, |
| 2682 | .sect = self.data_section_index.?, | 2651 | }); |
| 2683 | }); | 2652 | } |
| 2684 | } | 2653 | { |
| 2685 | { | 2654 | const atom = try self.createStubHelperPreambleAtom(); |
| 2686 | const atom = try self.createStubHelperPreambleAtom(); | 2655 | _ = try self.allocateAtom(atom, .{ |
| 2687 | _ = try self.allocateAtom(atom, .{ | 2656 | .seg = self.text_segment_cmd_index.?, |
| 2688 | .seg = self.text_segment_cmd_index.?, | 2657 | .sect = self.stub_helper_section_index.?, |
| 2689 | .sect = self.stub_helper_section_index.?, | 2658 | }); |
| 2690 | }); | | |
| 2691 | } | | |
| 2692 | } | 2659 | } |
| 2693 | | 2660 | |
| 2694 | // Third pass, resolve symbols in dynamic libraries. | 2661 | // Third pass, resolve symbols in dynamic libraries. |
| ... | @@ -2800,9 +2767,7 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2800,9 +2767,7 @@ fn resolveSymbols(self: *MachO) !void { |
| 2800 | // TODO perhaps we should special-case special symbols? Create a separate | 2767 | // TODO perhaps we should special-case special symbols? Create a separate |
| 2801 | // linked list of atoms? | 2768 | // linked list of atoms? |
| 2802 | const atom = try self.createEmptyAtom(local_sym_index, 0, 0); | 2769 | const atom = try self.createEmptyAtom(local_sym_index, 0, 0); |
| 2803 | if (use_stage1) { | 2770 | _ = try self.allocateAtom(atom, match); |
| 2804 | try self.allocateAtomStage1(atom, match); | | |
| 2805 | } | | |
| 2806 | } | 2771 | } |
| 2807 | | 2772 | |
| 2808 | for (self.unresolved.keys()) |index| { | 2773 | for (self.unresolved.keys()) |index| { |
| ... | @@ -2869,12 +2834,7 @@ fn resolveDyldStubBinder(self: *MachO) !void { | ... | @@ -2869,12 +2834,7 @@ fn resolveDyldStubBinder(self: *MachO) !void { |
| 2869 | .seg = self.data_const_segment_cmd_index.?, | 2834 | .seg = self.data_const_segment_cmd_index.?, |
| 2870 | .sect = self.got_section_index.?, | 2835 | .sect = self.got_section_index.?, |
| 2871 | }; | 2836 | }; |
| 2872 | // TODO remove once we can incrementally update in stage1 too. | 2837 | _ = try self.allocateAtom(atom, match); |
| 2873 | if (!(build_options.is_stage1 and self.base.options.use_stage1)) { | | |
| 2874 | _ = try self.allocateAtom(atom, match); | | |
| 2875 | } else { | | |
| 2876 | try self.allocateAtomStage1(atom, match); | | |
| 2877 | } | | |
| 2878 | self.binding_info_dirty = true; | 2838 | self.binding_info_dirty = true; |
| 2879 | } | 2839 | } |
| 2880 | | 2840 | |