| ... | ... | @@ -760,27 +760,6 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 760 | 760 | try self.addCodeSignatureLC(); |
| 761 | 761 | |
| 762 | 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 | 763 | try self.parseTextBlocks(); |
| 785 | 764 | try self.allocateTextSegment(); |
| 786 | 765 | try self.allocateDataConstSegment(); |
| ... | ... | @@ -1919,55 +1898,70 @@ pub fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment: |
| 1919 | 1898 | pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 { |
| 1920 | 1899 | const seg = &self.load_commands.items[match.seg].Segment; |
| 1921 | 1900 | const sect = &seg.sections.items[match.sect]; |
| 1922 | | const sym = &self.locals.items[atom.local_sym_index]; |
| 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; |
| 1901 | const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1; |
| 1957 | 1902 | |
| 1958 | | // Update each alias (if any) |
| 1959 | | for (atom.aliases.items) |index| { |
| 1960 | | const alias_sym = &self.locals.items[index]; |
| 1961 | | alias_sym.n_value = vaddr; |
| 1962 | | alias_sym.n_sect = n_sect; |
| 1963 | | } |
| 1903 | const vaddr = outer: { |
| 1904 | if (!use_stage1) { |
| 1905 | const sym = &self.locals.items[atom.local_sym_index]; |
| 1906 | |
| 1907 | var atom_placement: ?*TextBlock = null; |
| 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 |
| 1966 | | for (atom.contained.items) |sym_at_off| { |
| 1967 | | const contained_sym = &self.locals.items[sym_at_off.local_sym_index]; |
| 1968 | | contained_sym.n_value = vaddr + sym_at_off.offset; |
| 1969 | | contained_sym.n_sect = n_sect; |
| 1970 | | } |
| 1941 | // Update each alias (if any) |
| 1942 | for (atom.aliases.items) |index| { |
| 1943 | const alias_sym = &self.locals.items[index]; |
| 1944 | alias_sym.n_value = vaddr; |
| 1945 | alias_sym.n_sect = n_sect; |
| 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 | 1966 | if (self.blocks.getPtr(match)) |last| { |
| 1973 | 1967 | last.*.next = atom; |
| ... | ... | @@ -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 | 2014 | fn writeAtoms(self: *MachO) !void { |
| 2042 | 2015 | var it = self.blocks.iterator(); |
| 2043 | 2016 | while (it.next()) |entry| { |
| ... | ... | @@ -2607,8 +2580,6 @@ fn resolveSymbolsInObject( |
| 2607 | 2580 | } |
| 2608 | 2581 | |
| 2609 | 2582 | fn resolveSymbols(self: *MachO) !void { |
| 2610 | | const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1; |
| 2611 | | |
| 2612 | 2583 | var tentatives = std.AutoArrayHashMap(u32, void).init(self.base.allocator); |
| 2613 | 2584 | defer tentatives.deinit(); |
| 2614 | 2585 | |
| ... | ... | @@ -2668,27 +2639,23 @@ fn resolveSymbols(self: *MachO) !void { |
| 2668 | 2639 | resolv.local_sym_index = local_sym_index; |
| 2669 | 2640 | |
| 2670 | 2641 | const atom = try self.createEmptyAtom(local_sym_index, size, alignment); |
| 2671 | | if (use_stage1) { |
| 2672 | | try self.allocateAtomStage1(atom, match); |
| 2673 | | } |
| 2642 | _ = try self.allocateAtom(atom, match); |
| 2674 | 2643 | } |
| 2675 | 2644 | |
| 2676 | 2645 | try self.resolveDyldStubBinder(); |
| 2677 | | if (!use_stage1) { |
| 2678 | | { |
| 2679 | | const atom = try self.createDyldPrivateAtom(); |
| 2680 | | _ = try self.allocateAtom(atom, .{ |
| 2681 | | .seg = self.data_segment_cmd_index.?, |
| 2682 | | .sect = self.data_section_index.?, |
| 2683 | | }); |
| 2684 | | } |
| 2685 | | { |
| 2686 | | const atom = try self.createStubHelperPreambleAtom(); |
| 2687 | | _ = try self.allocateAtom(atom, .{ |
| 2688 | | .seg = self.text_segment_cmd_index.?, |
| 2689 | | .sect = self.stub_helper_section_index.?, |
| 2690 | | }); |
| 2691 | | } |
| 2646 | { |
| 2647 | const atom = try self.createDyldPrivateAtom(); |
| 2648 | _ = try self.allocateAtom(atom, .{ |
| 2649 | .seg = self.data_segment_cmd_index.?, |
| 2650 | .sect = self.data_section_index.?, |
| 2651 | }); |
| 2652 | } |
| 2653 | { |
| 2654 | const atom = try self.createStubHelperPreambleAtom(); |
| 2655 | _ = try self.allocateAtom(atom, .{ |
| 2656 | .seg = self.text_segment_cmd_index.?, |
| 2657 | .sect = self.stub_helper_section_index.?, |
| 2658 | }); |
| 2692 | 2659 | } |
| 2693 | 2660 | |
| 2694 | 2661 | // Third pass, resolve symbols in dynamic libraries. |
| ... | ... | @@ -2800,9 +2767,7 @@ fn resolveSymbols(self: *MachO) !void { |
| 2800 | 2767 | // TODO perhaps we should special-case special symbols? Create a separate |
| 2801 | 2768 | // linked list of atoms? |
| 2802 | 2769 | const atom = try self.createEmptyAtom(local_sym_index, 0, 0); |
| 2803 | | if (use_stage1) { |
| 2804 | | try self.allocateAtomStage1(atom, match); |
| 2805 | | } |
| 2770 | _ = try self.allocateAtom(atom, match); |
| 2806 | 2771 | } |
| 2807 | 2772 | |
| 2808 | 2773 | for (self.unresolved.keys()) |index| { |
| ... | ... | @@ -2869,12 +2834,7 @@ fn resolveDyldStubBinder(self: *MachO) !void { |
| 2869 | 2834 | .seg = self.data_const_segment_cmd_index.?, |
| 2870 | 2835 | .sect = self.got_section_index.?, |
| 2871 | 2836 | }; |
| 2872 | | // TODO remove once we can incrementally update in stage1 too. |
| 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 | | } |
| 2837 | _ = try self.allocateAtom(atom, match); |
| 2878 | 2838 | self.binding_info_dirty = true; |
| 2879 | 2839 | } |
| 2880 | 2840 | |