| ... | ... | @@ -281,6 +281,10 @@ const DEFAULT_DYLD_PATH: [*:0]const u8 = "/usr/lib/dyld"; |
| 281 | 281 | const minimum_text_block_size = 64; |
| 282 | 282 | pub const min_text_capacity = padToIdeal(minimum_text_block_size); |
| 283 | 283 | |
| 284 | /// Virtual memory offset corresponds to the size of __PAGEZERO segment and start of |
| 285 | /// __TEXT segment. |
| 286 | const pagezero_vmsize: u64 = 0x100000000; |
| 287 | |
| 284 | 288 | pub const Export = struct { |
| 285 | 289 | sym_index: ?u32 = null, |
| 286 | 290 | }; |
| ... | ... | @@ -1903,13 +1907,19 @@ pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 |
| 1903 | 1907 | const vaddr = outer: { |
| 1904 | 1908 | if (!use_stage1) { |
| 1905 | 1909 | const sym = &self.locals.items[atom.local_sym_index]; |
| 1910 | const needs_padding = blk: { |
| 1911 | // TODO is __text the only section that benefits from padding? |
| 1912 | if (match.seg == self.text_segment_cmd_index.? and |
| 1913 | match.sect == self.text_section_index.?) break :blk true; |
| 1914 | break :blk false; |
| 1915 | }; |
| 1906 | 1916 | |
| 1907 | 1917 | var atom_placement: ?*TextBlock = null; |
| 1908 | 1918 | |
| 1909 | 1919 | // TODO converge with `allocateTextBlock` and handle free list |
| 1910 | 1920 | const vaddr = if (self.blocks.get(match)) |last| blk: { |
| 1911 | 1921 | const last_atom_sym = self.locals.items[last.local_sym_index]; |
| 1912 | | const ideal_capacity = padToIdeal(last.size); |
| 1922 | const ideal_capacity = if (needs_padding) padToIdeal(last.size) else last.size; |
| 1913 | 1923 | const ideal_capacity_end_vaddr = last_atom_sym.n_value + ideal_capacity; |
| 1914 | 1924 | const last_atom_alignment = try math.powi(u32, 2, atom.alignment); |
| 1915 | 1925 | const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, last_atom_alignment); |
| ... | ... | @@ -1921,18 +1931,9 @@ pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 |
| 1921 | 1931 | |
| 1922 | 1932 | const expand_section = atom_placement == null or atom_placement.?.next == null; |
| 1923 | 1933 | 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 |
| 1934 | const max_size = seg.allocatedSize(vaddr - pagezero_vmsize); |
| 1935 | log.debug(" (atom size 0x{x}, max available size 0x{x})", .{ atom.size, max_size }); |
| 1936 | assert(atom.size <= max_size); // TODO must expand the section |
| 1936 | 1937 | } |
| 1937 | 1938 | const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| 1938 | 1939 | sym.n_value = vaddr; |
| ... | ... | @@ -3912,7 +3913,7 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3912 | 3913 | .Segment = .{ |
| 3913 | 3914 | .inner = .{ |
| 3914 | 3915 | .segname = makeStaticString("__PAGEZERO"), |
| 3915 | | .vmsize = 0x100000000, // size always set to 4GB |
| 3916 | .vmsize = pagezero_vmsize, |
| 3916 | 3917 | }, |
| 3917 | 3918 | }, |
| 3918 | 3919 | }); |
| ... | ... | @@ -3932,7 +3933,7 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3932 | 3933 | .Segment = .{ |
| 3933 | 3934 | .inner = .{ |
| 3934 | 3935 | .segname = makeStaticString("__TEXT"), |
| 3935 | | .vmaddr = 0x100000000, // always starts at 4GB |
| 3936 | .vmaddr = pagezero_vmsize, |
| 3936 | 3937 | .vmsize = needed_size, |
| 3937 | 3938 | .filesize = needed_size, |
| 3938 | 3939 | .maxprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE, |
| ... | ... | @@ -4452,8 +4453,6 @@ fn allocateSection( |
| 4452 | 4453 | const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) self.header_pad else null; |
| 4453 | 4454 | const off = seg.findFreeSpace(size, alignment_pow_2, padding); |
| 4454 | 4455 | |
| 4455 | | assert(off + size <= seg.inner.fileoff + seg.inner.filesize); // TODO expand |
| 4456 | | |
| 4457 | 4456 | log.debug("found {s},{s} section free space 0x{x} to 0x{x}", .{ |
| 4458 | 4457 | commands.segmentName(sect), |
| 4459 | 4458 | commands.sectionName(sect), |
| ... | ... | @@ -4556,7 +4555,9 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, |
| 4556 | 4555 | const expand_text_section = block_placement == null or block_placement.?.next == null; |
| 4557 | 4556 | if (expand_text_section) { |
| 4558 | 4557 | const needed_size = (vaddr + new_block_size) - text_section.addr; |
| 4559 | | assert(needed_size <= text_segment.inner.filesize); // TODO must move the entire text section. |
| 4558 | const max_size = text_segment.allocatedSize(vaddr - pagezero_vmsize); |
| 4559 | log.debug(" (atom needed size 0x{x}, max available size 0x{x})", .{ needed_size, max_size }); |
| 4560 | assert(needed_size <= max_size); // TODO must expand the section |
| 4560 | 4561 | _ = try self.blocks.put(self.base.allocator, match, text_block); |
| 4561 | 4562 | } |
| 4562 | 4563 | text_block.size = new_block_size; |