| ... | ... | @@ -52,6 +52,8 @@ load_commands: std.ArrayListUnmanaged(LoadCommand) = .{}, |
| 52 | 52 | pagezero_segment_cmd_index: ?u16 = null, |
| 53 | 53 | /// __TEXT segment |
| 54 | 54 | text_segment_cmd_index: ?u16 = null, |
| 55 | /// __DATA_CONST segment |
| 56 | data_const_segment_cmd_index: ?u16 = null, |
| 55 | 57 | /// __DATA segment |
| 56 | 58 | data_segment_cmd_index: ?u16 = null, |
| 57 | 59 | /// __LINKEDIT segment |
| ... | ... | @@ -1519,6 +1521,64 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1519 | 1521 | self.header_dirty = true; |
| 1520 | 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 | 1582 | if (self.linkedit_segment_cmd_index == null) { |
| 1523 | 1583 | self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 1524 | 1584 | |
| ... | ... | @@ -1907,16 +1967,13 @@ const NextSegmentAddressAndOffset = struct { |
| 1907 | 1967 | }; |
| 1908 | 1968 | |
| 1909 | 1969 | fn nextSegmentAddressAndOffset(self: *MachO) NextSegmentAddressAndOffset { |
| 1910 | | const prev_segment_idx = blk: { |
| 1911 | | if (self.data_segment_cmd_index) |idx| { |
| 1912 | | break :blk idx; |
| 1913 | | } else if (self.text_segment_cmd_index) |idx| { |
| 1914 | | break :blk idx; |
| 1915 | | } else { |
| 1916 | | unreachable; // unhandled LC_SEGMENT_64 load command before __TEXT |
| 1970 | var prev_segment_idx: ?usize = null; // We use optional here for safety. |
| 1971 | for (self.load_commands.items) |cmd, i| { |
| 1972 | if (cmd == .Segment) { |
| 1973 | prev_segment_idx = i; |
| 1917 | 1974 | } |
| 1918 | | }; |
| 1919 | | const prev_segment = self.load_commands.items[prev_segment_idx].Segment; |
| 1975 | } |
| 1976 | const prev_segment = self.load_commands.items[prev_segment_idx.?].Segment; |
| 1920 | 1977 | const address = prev_segment.inner.vmaddr + prev_segment.inner.vmsize; |
| 1921 | 1978 | const offset = prev_segment.inner.fileoff + prev_segment.inner.filesize; |
| 1922 | 1979 | return .{ |
| ... | ... | @@ -2464,6 +2521,8 @@ fn parseFromFile(self: *MachO, file: fs.File) !void { |
| 2464 | 2521 | } |
| 2465 | 2522 | } else if (parseAndCmpName(&x.inner.segname, "__DATA")) { |
| 2466 | 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 | 2528 | macho.LC_DYLD_INFO_ONLY => { |