authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-18 11:18:59+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-19 12:18:49+01:00
log6a021d845a78241415c1f8537cb8ae63a8367b89
tree7813cc80d2651adf41586b7d5318adb4ad985579
parentf33b644c4ff776f9e0947d592ac7a5df452710b6

macho: find free space even for __text section


2 files changed, 20 insertions(+), 29 deletions(-)

src/link/MachO.zig+18-20
...@@ -104,9 +104,7 @@ dyld_stub_binder_index: ?u16 = null,...@@ -104,9 +104,7 @@ dyld_stub_binder_index: ?u16 = null,
104/// Table of symbol names aka the string table.104/// Table of symbol names aka the string table.
105string_table: std.ArrayListUnmanaged(u8) = .{},105string_table: std.ArrayListUnmanaged(u8) = .{},
106106
107/// Table of symbol vaddr values. The values is the absolute vaddr value.107/// Table of trampolines to the actual symbols in __text section.
108/// If the vaddr of the executable __TEXT segment vaddr changes, the entire offset
109/// table needs to be rewritten.
110offset_table: std.ArrayListUnmanaged(u64) = .{},108offset_table: std.ArrayListUnmanaged(u64) = .{},
111109
112/// Table of binding info entries.110/// Table of binding info entries.
...@@ -1307,35 +1305,35 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1307,35 +1305,35 @@ pub fn populateMissingMetadata(self: *MachO) !void {
13071305
1308 log.debug("found __TEXT segment free space 0x{x} to 0x{x}\n", .{ 0, needed_size });1306 log.debug("found __TEXT segment free space 0x{x} to 0x{x}\n", .{ 0, needed_size });
13091307
1310 try self.load_commands.append(self.base.allocator, .{1308 var segment = SegmentCommand.empty(.{
1311 .Segment = SegmentCommand.empty(.{1309 .cmd = macho.LC_SEGMENT_64,
1312 .cmd = macho.LC_SEGMENT_64,1310 .cmdsize = @sizeOf(macho.segment_command_64),
1313 .cmdsize = @sizeOf(macho.segment_command_64),1311 .segname = makeStaticString("__TEXT"),
1314 .segname = makeStaticString("__TEXT"),1312 .vmaddr = 0x100000000, // always starts at 4GB
1315 .vmaddr = 0x100000000, // always starts at 4GB1313 .vmsize = needed_size,
1316 .vmsize = needed_size,1314 .fileoff = 0,
1317 .fileoff = 0,1315 .filesize = needed_size,
1318 .filesize = needed_size,1316 .maxprot = maxprot,
1319 .maxprot = maxprot,1317 .initprot = initprot,
1320 .initprot = initprot,1318 .nsects = 0,
1321 .nsects = 0,1319 .flags = 0,
1322 .flags = 0,
1323 }),
1324 });1320 });
1321 segment.header_pad = self.header_pad;
1322 try self.load_commands.append(self.base.allocator, .{ .Segment = segment });
1325 self.cmd_table_dirty = true;1323 self.cmd_table_dirty = true;
1326 }1324 }
1327 if (self.text_section_index == null) {1325 if (self.text_section_index == null) {
1328 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;1326 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1329 self.text_section_index = @intCast(u16, text_segment.sections.items.len);1327 self.text_section_index = @intCast(u16, text_segment.sections.items.len);
13301328
1331 const alignment: u32 = switch (self.base.options.target.cpu.arch) {1329 const alignment: u2 = switch (self.base.options.target.cpu.arch) {
1332 .x86_64 => 0,1330 .x86_64 => 0,
1333 .aarch64 => 2,1331 .aarch64 => 2,
1334 else => unreachable, // unhandled architecture type1332 else => unreachable, // unhandled architecture type
1335 };1333 };
1336 const flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS;1334 const flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS;
1337 const needed_size = self.base.options.program_code_size_hint;1335 const needed_size = self.base.options.program_code_size_hint;
1338 const off = self.header_pad;1336 const off = text_segment.findFreeSpace(needed_size, @as(u16, 1) << alignment);
13391337
1340 log.debug("found __text section free space 0x{x} to 0x{x}\n", .{ off, off + needed_size });1338 log.debug("found __text section free space 0x{x} to 0x{x}\n", .{ off, off + needed_size });
13411339
...@@ -2086,7 +2084,7 @@ fn parseFromFile(self: *MachO, file: fs.File) !void {...@@ -2086,7 +2084,7 @@ fn parseFromFile(self: *MachO, file: fs.File) !void {
2086 self.header = header;2084 self.header = header;
2087}2085}
20882086
2089pub fn parseAndCmpName(name: []const u8, needle: []const u8) bool {2087fn parseAndCmpName(name: []const u8, needle: []const u8) bool {
2090 const len = mem.indexOfScalar(u8, name[0..], @as(u8, 0)) orelse name.len;2088 const len = mem.indexOfScalar(u8, name[0..], @as(u8, 0)) orelse name.len;
2091 return mem.eql(u8, name[0..len], needle);2089 return mem.eql(u8, name[0..len], needle);
2092}2090}
src/link/MachO/commands.zig+2-9
...@@ -11,7 +11,6 @@ const MachO = @import("../MachO.zig");...@@ -11,7 +11,6 @@ const MachO = @import("../MachO.zig");
11const makeName = MachO.makeStaticString;11const makeName = MachO.makeStaticString;
12const alloc_num = MachO.alloc_num;12const alloc_num = MachO.alloc_num;
13const alloc_den = MachO.alloc_den;13const alloc_den = MachO.alloc_den;
14const parseAndCmpName = MachO.parseAndCmpName;
15const satMul = MachO.satMul;14const satMul = MachO.satMul;
1615
17pub const LoadCommand = union(enum) {16pub const LoadCommand = union(enum) {
...@@ -154,6 +153,7 @@ pub const LoadCommand = union(enum) {...@@ -154,6 +153,7 @@ pub const LoadCommand = union(enum) {
154153
155pub const SegmentCommand = struct {154pub const SegmentCommand = struct {
156 inner: macho.segment_command_64,155 inner: macho.segment_command_64,
156 header_pad: ?u64 = null,
157 sections: std.ArrayListUnmanaged(macho.section_64) = .{},157 sections: std.ArrayListUnmanaged(macho.section_64) = .{},
158158
159 pub fn empty(inner: macho.segment_command_64) SegmentCommand {159 pub fn empty(inner: macho.segment_command_64) SegmentCommand {
...@@ -179,14 +179,7 @@ pub const SegmentCommand = struct {...@@ -179,14 +179,7 @@ pub const SegmentCommand = struct {
179 }179 }
180180
181 pub fn findFreeSpace(self: SegmentCommand, object_size: u64, min_alignment: u16) u32 {181 pub fn findFreeSpace(self: SegmentCommand, object_size: u64, min_alignment: u16) u32 {
182 var start: u64 = blk: {182 var start: u64 = if (self.header_pad) |pad| pad else 0;
183 if (parseAndCmpName(self.inner.segname[0..], "__TEXT")) {
184 if (self.sections.items.len > 0) {
185 break :blk self.sections.items[0].offset;
186 }
187 }
188 break :blk 0;
189 };
190 while (self.detectAllocCollision(start, object_size)) |item_end| {183 while (self.detectAllocCollision(start, object_size)) |item_end| {
191 start = mem.alignForwardGeneric(u64, item_end, min_alignment);184 start = mem.alignForwardGeneric(u64, item_end, min_alignment);
192 }185 }