authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-01-05 21:58:33+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-01-13 23:53:25+01:00
log3d07f057b1ccbc20258114fde762969bcfddf1d3
tree2fe6b681762e8f5c6a4ec88ef229459460b0a618
parent5487dd13ea23ad7e547995b9a088ba37bfe17737

macho: prealloc DATA_CONST and DATA segments


1 files changed, 68 insertions(+), 9 deletions(-)

src/link/MachO.zig+68-9
......@@ -52,6 +52,8 @@ load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},
5252pagezero_segment_cmd_index: ?u16 = null,
5353/// __TEXT segment
5454text_segment_cmd_index: ?u16 = null,
55/// __DATA_CONST segment
56data_const_segment_cmd_index: ?u16 = null,
5557/// __DATA segment
5658data_segment_cmd_index: ?u16 = null,
5759/// __LINKEDIT segment
......@@ -1519,6 +1521,64 @@ pub fn populateMissingMetadata(self: *MachO) !void {
15191521 self.header_dirty = true;
15201522 self.load_commands_dirty = true;
15211523 }
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 }
15221582 if (self.linkedit_segment_cmd_index == null) {
15231583 self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
15241584
......@@ -1907,16 +1967,13 @@ const NextSegmentAddressAndOffset = struct {
19071967};
19081968
19091969fn 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;
19171974 }
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;
19201977 const address = prev_segment.inner.vmaddr + prev_segment.inner.vmsize;
19211978 const offset = prev_segment.inner.fileoff + prev_segment.inner.filesize;
19221979 return .{
......@@ -2464,6 +2521,8 @@ fn parseFromFile(self: *MachO, file: fs.File) !void {
24642521 }
24652522 } else if (parseAndCmpName(&x.inner.segname, "__DATA")) {
24662523 self.data_segment_cmd_index = i;
2524 } else if (parseAndCmpName(&x.inner.segname, "__DATA_CONST")) {
2525 self.data_const_segment_cmd_index = i;
24672526 }
24682527 },
24692528 macho.LC_DYLD_INFO_ONLY => {