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