From 6a021d845a78241415c1f8537cb8ae63a8367b89 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Fri, 18 Dec 2020 11:18:59 +0100 Subject: [PATCH] macho: find free space even for __text section --- src/link/MachO.zig | 38 ++++++++++++++++++------------------- src/link/MachO/commands.zig | 11 ++--------- 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 597b957f98..91a1e422fd 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -104,9 +104,7 @@ dyld_stub_binder_index: ?u16 = null, /// Table of symbol names aka the string table. string_table: std.ArrayListUnmanaged(u8) = .{}, -/// Table of symbol vaddr values. The values is the absolute vaddr value. -/// If the vaddr of the executable __TEXT segment vaddr changes, the entire offset -/// table needs to be rewritten. +/// Table of trampolines to the actual symbols in __text section. offset_table: std.ArrayListUnmanaged(u64) = .{}, /// Table of binding info entries. @@ -1307,35 +1305,35 @@ pub fn populateMissingMetadata(self: *MachO) !void { log.debug("found __TEXT segment free space 0x{x} to 0x{x}\n", .{ 0, needed_size }); - try self.load_commands.append(self.base.allocator, .{ - .Segment = SegmentCommand.empty(.{ - .cmd = macho.LC_SEGMENT_64, - .cmdsize = @sizeOf(macho.segment_command_64), - .segname = makeStaticString("__TEXT"), - .vmaddr = 0x100000000, // always starts at 4GB - .vmsize = needed_size, - .fileoff = 0, - .filesize = needed_size, - .maxprot = maxprot, - .initprot = initprot, - .nsects = 0, - .flags = 0, - }), + var segment = SegmentCommand.empty(.{ + .cmd = macho.LC_SEGMENT_64, + .cmdsize = @sizeOf(macho.segment_command_64), + .segname = makeStaticString("__TEXT"), + .vmaddr = 0x100000000, // always starts at 4GB + .vmsize = needed_size, + .fileoff = 0, + .filesize = needed_size, + .maxprot = maxprot, + .initprot = initprot, + .nsects = 0, + .flags = 0, }); + segment.header_pad = self.header_pad; + try self.load_commands.append(self.base.allocator, .{ .Segment = segment }); self.cmd_table_dirty = true; } if (self.text_section_index == null) { const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; self.text_section_index = @intCast(u16, text_segment.sections.items.len); - const alignment: u32 = switch (self.base.options.target.cpu.arch) { + const alignment: u2 = switch (self.base.options.target.cpu.arch) { .x86_64 => 0, .aarch64 => 2, else => unreachable, // unhandled architecture type }; const flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS; const needed_size = self.base.options.program_code_size_hint; - const off = self.header_pad; + const off = text_segment.findFreeSpace(needed_size, @as(u16, 1) << alignment); log.debug("found __text section free space 0x{x} to 0x{x}\n", .{ off, off + needed_size }); @@ -2086,7 +2084,7 @@ fn parseFromFile(self: *MachO, file: fs.File) !void { self.header = header; } -pub fn parseAndCmpName(name: []const u8, needle: []const u8) bool { +fn parseAndCmpName(name: []const u8, needle: []const u8) bool { const len = mem.indexOfScalar(u8, name[0..], @as(u8, 0)) orelse name.len; return mem.eql(u8, name[0..len], needle); } diff --git a/src/link/MachO/commands.zig b/src/link/MachO/commands.zig index 8ae767d3e0..cb7487f3d0 100644 --- a/src/link/MachO/commands.zig +++ b/src/link/MachO/commands.zig @@ -11,7 +11,6 @@ const MachO = @import("../MachO.zig"); const makeName = MachO.makeStaticString; const alloc_num = MachO.alloc_num; const alloc_den = MachO.alloc_den; -const parseAndCmpName = MachO.parseAndCmpName; const satMul = MachO.satMul; pub const LoadCommand = union(enum) { @@ -154,6 +153,7 @@ pub const LoadCommand = union(enum) { pub const SegmentCommand = struct { inner: macho.segment_command_64, + header_pad: ?u64 = null, sections: std.ArrayListUnmanaged(macho.section_64) = .{}, pub fn empty(inner: macho.segment_command_64) SegmentCommand { @@ -179,14 +179,7 @@ pub const SegmentCommand = struct { } pub fn findFreeSpace(self: SegmentCommand, object_size: u64, min_alignment: u16) u32 { - var start: u64 = blk: { - if (parseAndCmpName(self.inner.segname[0..], "__TEXT")) { - if (self.sections.items.len > 0) { - break :blk self.sections.items[0].offset; - } - } - break :blk 0; - }; + var start: u64 = if (self.header_pad) |pad| pad else 0; while (self.detectAllocCollision(start, object_size)) |item_end| { start = mem.alignForwardGeneric(u64, item_end, min_alignment); }