| ... | @@ -52,6 +52,8 @@ load_commands: std.ArrayListUnmanaged(LoadCommand) = .{}, | ... | @@ -52,6 +52,8 @@ load_commands: std.ArrayListUnmanaged(LoadCommand) = .{}, |
| 52 | pagezero_segment_cmd_index: ?u16 = null, | 52 | pagezero_segment_cmd_index: ?u16 = null, |
| 53 | /// __TEXT segment | 53 | /// __TEXT segment |
| 54 | text_segment_cmd_index: ?u16 = null, | 54 | text_segment_cmd_index: ?u16 = null, |
| | 55 | /// __DATA_CONST segment |
| | 56 | data_const_segment_cmd_index: ?u16 = null, |
| 55 | /// __DATA segment | 57 | /// __DATA segment |
| 56 | data_segment_cmd_index: ?u16 = null, | 58 | data_segment_cmd_index: ?u16 = null, |
| 57 | /// __LINKEDIT segment | 59 | /// __LINKEDIT segment |
| ... | @@ -1519,6 +1521,64 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -1519,6 +1521,64 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1519 | self.header_dirty = true; | 1521 | self.header_dirty = true; |
| 1520 | self.load_commands_dirty = true; | 1522 | self.load_commands_dirty = true; |
| 1521 | } | 1523 | } |
| | 1524 | if (self.data_const_segment_cmd_index == null) { |
| | 1525 | self.data_const_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| | 1526 | const maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE | macho.VM_PROT_EXECUTE; |
| | 1527 | const initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE; |
| | 1528 | const address_and_offset = self.nextSegmentAddressAndOffset(); |
| | 1529 | |
| | 1530 | const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| | 1531 | const needed_size = mem.alignForwardGeneric(u64, satMul(ideal_size, alloc_num) / alloc_den, self.page_size); |
| | 1532 | |
| | 1533 | log.debug("found __DATA_CONST segment free space 0x{x} to 0x{x}", .{ address_and_offset.offset, address_and_offset.offset + needed_size }); |
| | 1534 | |
| | 1535 | try self.load_commands.append(self.base.allocator, .{ |
| | 1536 | .Segment = SegmentCommand.empty(.{ |
| | 1537 | .cmd = macho.LC_SEGMENT_64, |
| | 1538 | .cmdsize = @sizeOf(macho.segment_command_64), |
| | 1539 | .segname = makeStaticString("__DATA_CONST"), |
| | 1540 | .vmaddr = address_and_offset.address, |
| | 1541 | .vmsize = needed_size, |
| | 1542 | .fileoff = address_and_offset.offset, |
| | 1543 | .filesize = needed_size, |
| | 1544 | .maxprot = maxprot, |
| | 1545 | .initprot = initprot, |
| | 1546 | .nsects = 0, |
| | 1547 | .flags = 0, |
| | 1548 | }), |
| | 1549 | }); |
| | 1550 | self.header_dirty = true; |
| | 1551 | self.load_commands_dirty = true; |
| | 1552 | } |
| | 1553 | if (self.data_segment_cmd_index == null) { |
| | 1554 | self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| | 1555 | const maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE | macho.VM_PROT_EXECUTE; |
| | 1556 | const initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE; |
| | 1557 | const address_and_offset = self.nextSegmentAddressAndOffset(); |
| | 1558 | |
| | 1559 | const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| | 1560 | const needed_size = mem.alignForwardGeneric(u64, satMul(ideal_size, alloc_num) / alloc_den, self.page_size); |
| | 1561 | |
| | 1562 | log.debug("found __DATA segment free space 0x{x} to 0x{x}", .{ address_and_offset.offset, address_and_offset.offset + needed_size }); |
| | 1563 | |
| | 1564 | try self.load_commands.append(self.base.allocator, .{ |
| | 1565 | .Segment = SegmentCommand.empty(.{ |
| | 1566 | .cmd = macho.LC_SEGMENT_64, |
| | 1567 | .cmdsize = @sizeOf(macho.segment_command_64), |
| | 1568 | .segname = makeStaticString("__DATA"), |
| | 1569 | .vmaddr = address_and_offset.address, |
| | 1570 | .vmsize = needed_size, |
| | 1571 | .fileoff = address_and_offset.offset, |
| | 1572 | .filesize = needed_size, |
| | 1573 | .maxprot = maxprot, |
| | 1574 | .initprot = initprot, |
| | 1575 | .nsects = 0, |
| | 1576 | .flags = 0, |
| | 1577 | }), |
| | 1578 | }); |
| | 1579 | self.header_dirty = true; |
| | 1580 | self.load_commands_dirty = true; |
| | 1581 | } |
| 1522 | if (self.linkedit_segment_cmd_index == null) { | 1582 | if (self.linkedit_segment_cmd_index == null) { |
| 1523 | self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len); | 1583 | self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 1524 | | 1584 | |
| ... | @@ -1907,16 +1967,13 @@ const NextSegmentAddressAndOffset = struct { | ... | @@ -1907,16 +1967,13 @@ const NextSegmentAddressAndOffset = struct { |
| 1907 | }; | 1967 | }; |
| 1908 | | 1968 | |
| 1909 | fn nextSegmentAddressAndOffset(self: *MachO) NextSegmentAddressAndOffset { | 1969 | fn nextSegmentAddressAndOffset(self: *MachO) NextSegmentAddressAndOffset { |
| 1910 | const prev_segment_idx = blk: { | 1970 | var prev_segment_idx: ?usize = null; // We use optional here for safety. |
| 1911 | if (self.data_segment_cmd_index) |idx| { | 1971 | for (self.load_commands.items) |cmd, i| { |
| 1912 | break :blk idx; | 1972 | if (cmd == .Segment) { |
| 1913 | } else if (self.text_segment_cmd_index) |idx| { | 1973 | prev_segment_idx = i; |
| 1914 | break :blk idx; | | |
| 1915 | } else { | | |
| 1916 | unreachable; // unhandled LC_SEGMENT_64 load command before __TEXT | | |
| 1917 | } | 1974 | } |
| 1918 | }; | 1975 | } |
| 1919 | const prev_segment = self.load_commands.items[prev_segment_idx].Segment; | 1976 | const prev_segment = self.load_commands.items[prev_segment_idx.?].Segment; |
| 1920 | const address = prev_segment.inner.vmaddr + prev_segment.inner.vmsize; | 1977 | const address = prev_segment.inner.vmaddr + prev_segment.inner.vmsize; |
| 1921 | const offset = prev_segment.inner.fileoff + prev_segment.inner.filesize; | 1978 | const offset = prev_segment.inner.fileoff + prev_segment.inner.filesize; |
| 1922 | return .{ | 1979 | return .{ |
| ... | @@ -2464,6 +2521,8 @@ fn parseFromFile(self: *MachO, file: fs.File) !void { | ... | @@ -2464,6 +2521,8 @@ fn parseFromFile(self: *MachO, file: fs.File) !void { |
| 2464 | } | 2521 | } |
| 2465 | } else if (parseAndCmpName(&x.inner.segname, "__DATA")) { | 2522 | } else if (parseAndCmpName(&x.inner.segname, "__DATA")) { |
| 2466 | self.data_segment_cmd_index = i; | 2523 | self.data_segment_cmd_index = i; |
| | 2524 | } else if (parseAndCmpName(&x.inner.segname, "__DATA_CONST")) { |
| | 2525 | self.data_const_segment_cmd_index = i; |
| 2467 | } | 2526 | } |
| 2468 | }, | 2527 | }, |
| 2469 | macho.LC_DYLD_INFO_ONLY => { | 2528 | macho.LC_DYLD_INFO_ONLY => { |